@@ -108,9 +108,28 @@ let mk_typename_from_type_decl crate (type_decl : Charon.Generated_Types.type_de
108108 Textual.TypeName. of_string name
109109
110110
111+ (* Model for box drops when using --desugar-drops *)
112+ let is_box_primitive_drop_in_place crate fun_decl_id =
113+ let decl = fun_map_find_id crate fun_decl_id in
114+ match (decl.item_meta.name, decl.signature.inputs) with
115+ | ( PeIdent (" alloc" , _)
116+ :: PeIdent (" boxed" , _)
117+ :: PeIdent (" Box" , _)
118+ :: _
119+ :: PeIdent (" drop_in_place" , _)
120+ :: _
121+ , TRawPtr (TAdt {id= TBuiltin TBox ; generics= {types= TLiteral _ :: _ }}, _) :: _ ) ->
122+ true
123+ | _ , _ ->
124+ false
125+
126+
111127let fun_name_from_fun_operand (crate : Charon.UllbcAst.crate )
112128 (operand : Charon.Generated_GAst.fn_operand ) : Textual.QualifiedProcName.t =
113129 match operand with
130+ | FnOpRegular {kind= FunId (FRegular fun_decl_id)}
131+ when is_box_primitive_drop_in_place crate fun_decl_id ->
132+ Textual.ProcDecl. boxdrop_name
114133 | FnOpRegular {kind = FunId (FRegular fun_decl_id )} ->
115134 let decl = fun_map_find_id crate fun_decl_id in
116135 mk_qualified_proc_name crate decl.item_meta
@@ -225,6 +244,33 @@ let proc_name_from_binop (op : Charon.Generated_Expressions.binop) (typ : Textua
225244 (Textual.ProcDecl. of_binop bin_op, typ)
226245
227246
247+ (* Model Unqiue<T> and NonNull<T> as *T *)
248+ let is_pointer_type crate (name : Charon.Generated_Types.name ) =
249+ let name = name |> List. map ~f: (name_of_path_element crate) in
250+ match name with
251+ | "core" :: "ptr" :: "non_null" :: "NonNull" :: _ ->
252+ true
253+ | "core" :: "ptr" :: "unique" :: "Unique" :: _ ->
254+ true
255+ | _ ->
256+ false
257+
258+
259+ let is_ty_decl_pointer_type crate type_decl_id =
260+ let type_decl = type_decl_map_find_id crate type_decl_id in
261+ is_pointer_type crate type_decl.item_meta.name
262+
263+
264+ let is_ty_pointer_type crate (ty : Charon.Generated_Types.ty ) =
265+ match ty with
266+ | TAdt {id = TAdtId type_decl_id } ->
267+ is_ty_decl_pointer_type crate type_decl_id
268+ | TAdt {id = TBuiltin TBox } ->
269+ true
270+ | _ ->
271+ false
272+
273+
228274let rec mk_struct_args crate (types : Charon.Generated_Types.ty list ) =
229275 List. map types ~f: (fun typ ->
230276 Textual.TypeName. of_string (Format. asprintf " %a" Textual.Typ. pp (ty_to_textual_typ crate typ)) )
@@ -239,13 +285,25 @@ and mk_tuple_struct_typ crate type_decl_ref =
239285 Textual.Typ. Struct (mk_tuple_type_name crate type_decl_ref)
240286
241287
288+ and mk_ptr_from_generics_types crate (types : Charon.Generated_Types.ty list ) =
289+ match types with
290+ | typ :: _ ->
291+ Textual.Typ. mk_ptr (ty_to_textual_typ crate typ)
292+ | _ ->
293+ Textual.Typ. mk_ptr Textual.Typ. Void
294+
295+
242296and adt_ty_to_textual_typ crate (type_decl_ref : Charon.Generated_Types.type_decl_ref ) :
243297 Textual.Typ. t =
244298 (* TODO: Implement other adt types *)
245299 match type_decl_ref.id with
246300 | TTuple ->
247301 if List. is_empty type_decl_ref.generics.types then Textual.Typ. Void
248302 else mk_tuple_struct_typ crate type_decl_ref.generics.types
303+ | TAdtId type_decl_id
304+ when let type_decl = type_decl_map_find_id crate type_decl_id in
305+ is_pointer_type crate type_decl.item_meta.name ->
306+ mk_ptr_from_generics_types crate type_decl_ref.generics.types
249307 | TAdtId type_decl_id -> (
250308 let type_decl = type_decl_map_find_id crate type_decl_id in
251309 match type_decl.kind with
@@ -257,12 +315,8 @@ and adt_ty_to_textual_typ crate (type_decl_ref : Charon.Generated_Types.type_dec
257315 Textual.Typ. Struct type_name
258316 | _ ->
259317 Textual.Typ. Void )
260- | TBuiltin TBox -> (
261- match type_decl_ref.generics.types with
262- | typ :: _ ->
263- Textual.Typ. mk_ptr (ty_to_textual_typ crate typ)
264- | _ ->
265- Textual.Typ. mk_ptr Textual.Typ. Void )
318+ | TBuiltin TBox ->
319+ mk_ptr_from_generics_types crate type_decl_ref.generics.types
266320 | TBuiltin TStr ->
267321 Textual.Typ. Struct Textual.TypeName. sil_string
268322
@@ -377,10 +431,31 @@ let rec mk_exp_from_place ~loc (crate : Charon.UllbcAst.crate) (place_map : plac
377431 | PlaceLocal var_id ->
378432 let exp = Textual.Exp. Lvar (place_map_find_id place_map var_id) in
379433 exp
434+ (* This models the --precise-drop versions of Box, Unqiue and NonNull as pointers since the
435+ compiler has some special handling for how it treats Box and NonNull and their ABI are equivalent.
436+ For example:
437+ let b = Box::new(10);
438+ let value = *b;
439+ Is lowered in mir to
440+ b_1 = @BoxNew<i32>
441+ _3 := transmute<NonNull<i32>, *const i32>(copy (( *(b_1)).0));
442+ value_2 := copy ( *(_3));
443+ There are two abstractions here:
444+ (1) *b_1 is the derefence of the box struct, box that access the underlying unique.
445+ The .0 is then a regular field acces of the unqiue that gets The NonNull.
446+ (2) The transmute treats the NonNull struct the same is it's field.
447+ This skips the ( *(b_1)) step.
448+ *)
449+ | PlaceProjection (({ty= TAdt {id= TBuiltin TBox }} as projection_place), Deref )
450+ when is_ty_pointer_type crate place.ty ->
451+ mk_exp_from_place ~loc crate place_map projection_place
380452 | PlaceProjection (projection_place , Deref) ->
381453 let proj_typ = ty_to_textual_typ crate projection_place.ty in
382454 let exp = mk_exp_from_place ~loc crate place_map projection_place in
383455 Textual.Exp. Load {exp; typ= Some proj_typ}
456+ (* This skips the NonNull<T>.0 and Unqiue<T>.0 step *)
457+ | PlaceProjection (projection_place , Field _ ) when is_ty_pointer_type crate projection_place.ty ->
458+ mk_exp_from_place ~loc crate place_map projection_place
384459 | PlaceProjection (projection_place , Field (ProjAdt (type_decl_id , variant ), field_id )) ->
385460 let exp = mk_exp_from_place ~loc crate place_map projection_place in
386461 let type_decl = type_decl_map_find_id crate type_decl_id in
@@ -630,21 +705,26 @@ let mk_terminator (crate : Charon.UllbcAst.crate) (idx : int) (place_map : place
630705 (* A drop frees the memory of a value once it goes out of scope.
631706 The following implementation is a simplified model for drops
632707 of boxes created by Box::new() of types using the global allocator.
708+
633709 https://doc.rust-lang.org/1.93.1/alloc/alloc/struct.Global.html
634710 https://rustc-dev-guide.rust-lang.org/mir/drop-elaboration.html
635711 https://doc.rust-lang.org/1.93.1/alloc/alloc/trait.GlobalAlloc.html#tymethod.dealloc
636712 *)
637- | Drop (Precise, ({ty = TAdt {id = TBuiltin TBox } } as place ), _trait_ref , target , on_unwind ) ->
638- let exp, _ = mk_exp_from_place_load ~loc crate place_map place in
639- let qualified_free_name = Textual.ProcDecl. free_name in
640- let free_call = Textual.Exp. call_non_virtual qualified_free_name [exp] in
641- let free_instr = Textual.Instr. Let {id= None ; exp= free_call; loc} in
642- let on_unwind = mk_label (Charon.Generated_UllbcAst.BlockId. to_int on_unwind) in
643- let target = mk_jump target in
644- ([] , [free_instr], target, [on_unwind])
713+ | Drop (Precise, place , _trait_ref , target , on_unwind ) -> (
714+ match place.ty with
715+ | TAdt {id = TBuiltin TBox ; generics = {types = TLiteral _ :: _ } } ->
716+ let exp, _ = mk_exp_from_place_load ~loc crate place_map place in
717+ let qualified_free_name = Textual.ProcDecl. free_name in
718+ let free_call = Textual.Exp. call_non_virtual qualified_free_name [exp] in
719+ let free_instr = Textual.Instr. Let {id= None ; exp= free_call; loc} in
720+ let on_unwind = mk_label (Charon.Generated_UllbcAst.BlockId. to_int on_unwind) in
721+ let target = mk_jump target in
722+ ([] , [free_instr], target, [on_unwind])
723+ | ty ->
724+ L. die UserError " [ERROR] Unsupported drop for type: @. > %a @." Charon.Types. pp_ty ty )
645725 | _ ->
646- L. die UserError " [ERROR] Unsupported terminator: %a " Charon.Generated_UllbcAst. pp_terminator
647- terminator
726+ L. die UserError " [ERROR] Unsupported terminator: @. > %a @. "
727+ Charon.Generated_UllbcAst. pp_terminator terminator
648728
649729
650730let mk_field_store_instr_from_rvalue ~loc crate lexp enclosing_class place_map field_id
@@ -680,16 +760,7 @@ let mk_instr crate (place_map : place_map_ty) (statement : Charon.Generated_Ullb
680760 | Assign (lhs , Aggregate (AggregatedAdt ({id = TAdtId type_decl_id } , None, None), ops )) ->
681761 let lexp = mk_exp_from_place ~loc crate place_map lhs in
682762 let type_decl = type_decl_map_find_id crate type_decl_id in
683- let fields =
684- match type_decl.kind with
685- | Struct fields ->
686- fields
687- | _ ->
688- L. die UserError
689- " [ERROR] Should not be reachable: Encountered none struct kind even tough variant \
690- and field_id are None. @. > %a @."
691- Charon.Generated_Types. pp_type_decl_kind type_decl.kind
692- in
763+ let fields = Charon.TypesUtils. type_decl_get_fields type_decl None in
693764 let enclosing_class = mk_typename_from_type_decl crate type_decl None in
694765 mk_field_store_instrs_from_rvalues ~loc crate lexp enclosing_class place_map ops fields
695766 (* Enum Variant *)
@@ -749,6 +820,10 @@ let mk_instr crate (place_map : place_map_ty) (statement : Charon.Generated_Ullb
749820 []
750821 | StorageLive _ ->
751822 []
823+ | PlaceMention place ->
824+ let exp, _ = mk_exp_from_place_load ~loc crate place_map place in
825+ let instr = Textual.Instr. Let {id= None ; exp; loc} in
826+ [instr]
752827 | s ->
753828 L. die UserError " [ERROR] Unsupported statement: @. > %a @."
754829 Charon.Generated_UllbcAst. pp_statement_kind s
0 commit comments