Skip to content

Commit

Permalink
Merge pull request #323 from Nadrieril/update-charon
Browse files Browse the repository at this point in the history
  • Loading branch information
Nadrieril authored Aug 28, 2024
2 parents 9723ad3 + 5ecf716 commit 80dbc55
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 176 deletions.
2 changes: 1 addition & 1 deletion charon-pin
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# This is the commit from https://github.com/AeneasVerif/charon that should be used with this version of aeneas.
597fe150c3952fd197e37bc7b5ae2cb2f0d07c81
79355ca1a90eccd7e3c3ded0fe3d1473a91f20ac
6 changes: 0 additions & 6 deletions compiler/Assumed.ml
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,6 @@ let raw_assumed_fun_infos : raw_assumed_fun_info list =
false,
"alloc::boxed::Box::new",
Some [ true; false ] );
(* BoxFree shouldn't be used *)
( BoxFree,
Sig.box_free_sig,
false,
"alloc::boxed::Box::free",
Some [ true; false ] );
(* Array Index *)
( ArrayIndexShared,
Sig.array_index_sig false,
Expand Down
237 changes: 77 additions & 160 deletions compiler/InterpreterStatements.ml
Original file line number Diff line number Diff line change
Expand Up @@ -281,28 +281,20 @@ let push_frame (ctx : eval_ctx) : eval_ctx = ctx_push_frame ctx
let get_assumed_function_return_type (span : Meta.span) (ctx : eval_ctx)
(fid : assumed_fun_id) (generics : generic_args) : ety =
sanity_check __FILE__ __LINE__ (generics.trait_refs = []) span;
(* [Box::free] has a special treatment *)
match fid with
| BoxFree ->
sanity_check __FILE__ __LINE__ (generics.regions = []) span;
sanity_check __FILE__ __LINE__ (List.length generics.types = 1) span;
sanity_check __FILE__ __LINE__ (generics.const_generics = []) span;
mk_unit_ty
| _ ->
(* Retrieve the function's signature *)
let sg = Assumed.get_assumed_fun_sig fid in
(* Instantiate the return type *)
(* There shouldn't be any reference to Self *)
let tr_self : trait_instance_id = UnknownTrait __FUNCTION__ in
let generics = Subst.generic_args_erase_regions generics in
let { Subst.r_subst = _; ty_subst; cg_subst; tr_subst; tr_self } =
Subst.make_subst_from_generics sg.generics generics tr_self
in
let ty =
Subst.erase_regions_substitute_types ty_subst cg_subst tr_subst tr_self
sg.output
in
AssociatedTypes.ctx_normalize_erase_ty span ctx ty
(* Retrieve the function's signature *)
let sg = Assumed.get_assumed_fun_sig fid in
(* Instantiate the return type *)
(* There shouldn't be any reference to Self *)
let tr_self : trait_instance_id = UnknownTrait __FUNCTION__ in
let generics = Subst.generic_args_erase_regions generics in
let { Subst.r_subst = _; ty_subst; cg_subst; tr_subst; tr_self } =
Subst.make_subst_from_generics sg.generics generics tr_self
in
let ty =
Subst.erase_regions_substitute_types ty_subst cg_subst tr_subst tr_self
sg.output
in
AssociatedTypes.ctx_normalize_erase_ty span ctx ty

let move_return_value (config : config) (span : Meta.span)
(pop_return_value : bool) (ctx : eval_ctx) :
Expand Down Expand Up @@ -434,45 +426,6 @@ let eval_box_new_concrete (config : config) (span : Meta.span)
comp cc (assign_to_place config span box_v dest ctx)
| _ -> craise __FILE__ __LINE__ span "Inconsistent state"

(** Auxiliary function - see {!eval_assumed_function_call}.
[Box::free] is not handled the same way as the other assumed functions:
- in the regular case, whenever we need to evaluate an assumed function,
we evaluate the operands, push a frame, call a dedicated function
to correctly update the variables in the frame (and mimic the execution
of a body) and finally pop the frame
- in the case of [Box::free]: the value given to this function is often
of the form [Box(⊥)] because we can move the value out of the
box before freeing the box. It makes it invalid to see box_free as a
"regular" function: it is not valid to call a function with arguments
which contain [⊥]. For this reason, we execute [Box::free] as drop_value,
but this is a bit annoying with regards to the semantics...
Followingly this function doesn't behave like the others: it does not expect
a stack frame to have been pushed, but rather simply behaves like {!drop_value}.
It thus updates the box value (by calling {!drop_value}) and updates
the destination (by setting it to [()]).
*)
let eval_box_free (config : config) (span : Meta.span) (generics : generic_args)
(args : operand list) (dest : place) : cm_fun =
fun ctx ->
match (generics.regions, generics.types, generics.const_generics, args) with
| [], [ boxed_ty ], [], [ Move input_box_place ] ->
(* Required type checking *)
let input_box =
InterpreterPaths.read_place span Write input_box_place ctx
in
(let input_ty = ty_get_box input_box.ty in
sanity_check __FILE__ __LINE__ (input_ty = boxed_ty))
span;

(* Drop the value *)
let ctx, cc = drop_value config span input_box_place ctx in

(* Update the destination by setting it to [()] *)
comp cc (assign_to_place config span mk_unit_value dest ctx)
| _ -> craise __FILE__ __LINE__ span "Inconsistent state"

(** Evaluate a non-local function call in concrete mode *)
let eval_assumed_function_call_concrete (config : config) (span : Meta.span)
(fid : assumed_fun_id) (call : call) : cm_fun =
Expand All @@ -483,72 +436,59 @@ let eval_assumed_function_call_concrete (config : config) (span : Meta.span)
| FnOpMove _ ->
(* Closure case: TODO *)
craise __FILE__ __LINE__ span "Closures are not supported yet"
| FnOpRegular func -> (
| FnOpRegular func ->
let generics = func.generics in
(* Sanity check: we don't fully handle the const generic vars environment
in concrete mode yet *)
sanity_check __FILE__ __LINE__ (generics.const_generics = []) span;
(* There are two cases (and this is extremely annoying):
- the function is not box_free
- the function is box_free
See {!eval_box_free}
*)
match fid with
| BoxFree ->
(* Degenerate case: box_free *)
eval_box_free config span generics args dest ctx
| _ ->
(* "Normal" case: not box_free *)
(* Evaluate the operands *)
(* let ctx, args_vl = eval_operands config ctx args in *)
let args_vl, ctx, cc = eval_operands config span args ctx in

(* Evaluate the call
*
* Style note: at some point we used {!comp_transmit} to
* transmit the result of {!eval_operands} above down to {!push_vars}
* below, without having to introduce an intermediary function call,
* but it made it less clear where the computed values came from,
* so we reversed the modifications. *)
(* Push the stack frame: we initialize the frame with the return variable,
and one variable per input argument *)
let ctx = push_frame ctx in

(* Create and push the return variable *)
let ret_vid = VarId.zero in
let ret_ty = get_assumed_function_return_type span ctx fid generics in
let ret_var = mk_var ret_vid (Some "@return") ret_ty in
let ctx = push_uninitialized_var span ret_var ctx in

(* Create and push the input variables *)
let input_vars =
VarId.mapi_from1
(fun id (v : typed_value) -> (mk_var id None v.ty, v))
args_vl
in
let ctx = push_vars span input_vars ctx in

(* "Execute" the function body. As the functions are assumed, here we call
* custom functions to perform the proper manipulations: we don't have
* access to a body. *)
let ctx, cf_eval_body =
match fid with
| BoxNew -> eval_box_new_concrete config span generics ctx
| BoxFree ->
(* Should have been treated above *)
craise __FILE__ __LINE__ span "Unreachable"
| ArrayIndexShared
| ArrayIndexMut
| ArrayToSliceShared
| ArrayToSliceMut
| ArrayRepeat
| SliceIndexShared
| SliceIndexMut -> craise __FILE__ __LINE__ span "Unimplemented"
in
let cc = cc_comp cc cf_eval_body in

(* Pop the frame *)
comp cc (pop_frame_assign config span dest ctx))
(* Evaluate the operands *)
(* let ctx, args_vl = eval_operands config ctx args in *)
let args_vl, ctx, cc = eval_operands config span args ctx in

(* Evaluate the call
*
* Style note: at some point we used {!comp_transmit} to
* transmit the result of {!eval_operands} above down to {!push_vars}
* below, without having to introduce an intermediary function call,
* but it made it less clear where the computed values came from,
* so we reversed the modifications. *)
(* Push the stack frame: we initialize the frame with the return variable,
and one variable per input argument *)
let ctx = push_frame ctx in

(* Create and push the return variable *)
let ret_vid = VarId.zero in
let ret_ty = get_assumed_function_return_type span ctx fid generics in
let ret_var = mk_var ret_vid (Some "@return") ret_ty in
let ctx = push_uninitialized_var span ret_var ctx in

(* Create and push the input variables *)
let input_vars =
VarId.mapi_from1
(fun id (v : typed_value) -> (mk_var id None v.ty, v))
args_vl
in
let ctx = push_vars span input_vars ctx in

(* "Execute" the function body. As the functions are assumed, here we call
* custom functions to perform the proper manipulations: we don't have
* access to a body. *)
let ctx, cf_eval_body =
match fid with
| BoxNew -> eval_box_new_concrete config span generics ctx
| ArrayIndexShared
| ArrayIndexMut
| ArrayToSliceShared
| ArrayToSliceMut
| ArrayRepeat
| SliceIndexShared
| SliceIndexMut -> craise __FILE__ __LINE__ span "Unimplemented"
in
let cc = cc_comp cc cf_eval_body in

(* Pop the frame *)
comp cc (pop_frame_assign config span dest ctx)

(** Helper
Expand Down Expand Up @@ -1552,45 +1492,22 @@ and eval_assumed_function_call_symbolic (config : config) (span : Meta.span)
generics.types)
span;

(* There are two cases (and this is extremely annoying):
- the function is not box_free
- the function is box_free
See {!eval_box_free}
*)
match fid with
| BoxFree ->
(* Degenerate case: box_free - note that this is not really a function
* call: no need to call a "synthesize_..." function *)
let ctx, cc = eval_box_free config span generics args dest ctx in
([ (ctx, Unit) ], cc_singleton __FILE__ __LINE__ span cc)
| _ ->
(* "Normal" case: not box_free *)
(* In symbolic mode, the behaviour of a function call is completely defined
* by the signature of the function: we thus simply generate correctly
* instantiated signatures, and delegate the work to an auxiliary function *)
let sg, regions_hierarchy, inst_sig =
match fid with
| BoxFree ->
(* Should have been treated above *)
craise __FILE__ __LINE__ span "Unreachable"
| _ ->
let regions_hierarchy =
LlbcAstUtils.FunIdMap.find (FAssumed fid)
ctx.fun_ctx.regions_hierarchies
in
(* There shouldn't be any reference to Self *)
let tr_self = UnknownTrait __FUNCTION__ in
let sg = Assumed.get_assumed_fun_sig fid in
let inst_sg =
instantiate_fun_sig span ctx generics tr_self sg regions_hierarchy
in
(sg, regions_hierarchy, inst_sg)
in
(* In symbolic mode, the behaviour of a function call is completely defined
* by the signature of the function: we thus simply generate correctly
* instantiated signatures, and delegate the work to an auxiliary function *)
let regions_hierarchy =
LlbcAstUtils.FunIdMap.find (FAssumed fid) ctx.fun_ctx.regions_hierarchies
in
(* There shouldn't be any reference to Self *)
let tr_self = UnknownTrait __FUNCTION__ in
let sg = Assumed.get_assumed_fun_sig fid in
let inst_sig =
instantiate_fun_sig span ctx generics tr_self sg regions_hierarchy
in

(* Evaluate the function call *)
eval_function_call_symbolic_from_inst_sig config span
(FunId (FAssumed fid)) sg regions_hierarchy inst_sig generics None args
dest ctx
(* Evaluate the function call *)
eval_function_call_symbolic_from_inst_sig config span (FunId (FAssumed fid))
sg regions_hierarchy inst_sig generics None args dest ctx

(** Evaluate a statement seen as a function body *)
and eval_function_body (config : config) (body : statement) : stl_cm_fun =
Expand Down
1 change: 0 additions & 1 deletion compiler/PrintPure.ml
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,6 @@ let fun_suffix (lp_id : LoopId.id option) : string =
let llbc_assumed_fun_id_to_string (fid : A.assumed_fun_id) : string =
match fid with
| BoxNew -> "alloc::boxed::Box::new"
| BoxFree -> "alloc::alloc::box_free"
| ArrayIndexShared -> "@ArrayIndexShared"
| ArrayIndexMut -> "@ArrayIndexMut"
| ArrayToSliceShared -> "@ArrayToSliceShared"
Expand Down
4 changes: 0 additions & 4 deletions compiler/PureMicroPasses.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1587,10 +1587,6 @@ let eliminate_box_functions (_ctx : trans_ctx) (def : fun_decl) : fun_decl =
| BoxNew ->
let arg, args = Collections.List.pop args in
mk_apps def.item_meta.span arg args
| BoxFree ->
sanity_check __FILE__ __LINE__ (args = [])
def.item_meta.span;
mk_unit_rvalue
| SliceIndexShared
| SliceIndexMut
| ArrayIndexShared
Expand Down
1 change: 0 additions & 1 deletion compiler/SymbolicToPure.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2195,7 +2195,6 @@ and translate_function_call (call : S.call) (e : S.expression) (ctx : bs_ctx) :
| FunId (FAssumed fid) -> (
match fid with
| BoxNew -> "box_new"
| BoxFree -> "box_free"
| ArrayRepeat -> "array_repeat"
| ArrayIndexShared -> "index_shared"
| ArrayIndexMut -> "index_mut"
Expand Down
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 80dbc55

Please sign in to comment.