@@ -7,96 +7,85 @@ use crate::codegen_cprover_gotoc::GotocCtx;
77use cbmc:: goto_program:: { Expr , Stmt , Symbol } ;
88use cbmc:: InternString ;
99use rustc_middle:: mir:: traversal:: reverse_postorder;
10- use rustc_middle:: mir:: { Body , HasLocalDecls , Local } ;
11- use rustc_middle:: ty:: { self , Instance } ;
10+ use stable_mir:: mir:: mono:: Instance ;
11+ use stable_mir:: mir:: { Body , Local } ;
12+ use stable_mir:: ty:: { RigidTy , TyKind } ;
13+ use stable_mir:: CrateDef ;
1214use std:: collections:: BTreeMap ;
1315use std:: iter:: FromIterator ;
1416use tracing:: { debug, debug_span} ;
1517
1618/// Codegen MIR functions into gotoc
1719impl < ' tcx > GotocCtx < ' tcx > {
18- /// Get the number of parameters that the current function expects.
19- fn get_params_size ( & self ) -> usize {
20- let sig = self . current_fn ( ) . sig ( ) ;
21- let sig = self . tcx . normalize_erasing_late_bound_regions ( ty:: ParamEnv :: reveal_all ( ) , sig) ;
22- // we don't call [codegen_function_sig] because we want to get a bit more metainformation.
23- sig. inputs ( ) . len ( )
24- }
25-
2620 /// Declare variables according to their index.
2721 /// - Index 0 represents the return value.
2822 /// - Indices [1, N] represent the function parameters where N is the number of parameters.
2923 /// - Indices that are greater than N represent local variables.
30- fn codegen_declare_variables ( & mut self ) {
31- let mir = self . current_fn ( ) . body_internal ( ) ;
32- let ldecls = mir. local_decls ( ) ;
33- let num_args = self . get_params_size ( ) ;
34- ldecls. indices ( ) . enumerate ( ) . for_each ( |( idx, lc) | {
35- if Some ( lc) == mir. spread_arg {
24+ fn codegen_declare_variables ( & mut self , body : & Body ) {
25+ let ldecls = body. local_decls ( ) ;
26+ let num_args = body. arg_locals ( ) . len ( ) ;
27+ for ( lc, ldata) in ldecls {
28+ if Some ( lc) == body. spread_arg ( ) {
3629 // We have already added this local in the function prelude, so
3730 // skip adding it again here.
38- return ;
31+ continue ;
3932 }
4033 let base_name = self . codegen_var_base_name ( & lc) ;
4134 let name = self . codegen_var_name ( & lc) ;
42- let ldata = & ldecls[ lc] ;
43- let var_ty = self . monomorphize ( ldata. ty ) ;
44- let var_type = self . codegen_ty ( var_ty) ;
45- let loc = self . codegen_span ( & ldata. source_info . span ) ;
35+ let var_type = self . codegen_ty_stable ( ldata. ty ) ;
36+ let loc = self . codegen_span_stable ( ldata. span ) ;
4637 // Indices [1, N] represent the function parameters where N is the number of parameters.
4738 // Except that ZST fields are not included as parameters.
48- let sym = Symbol :: variable (
49- name,
50- base_name,
51- var_type,
52- self . codegen_span ( & ldata. source_info . span ) ,
53- )
54- . with_is_hidden ( !self . is_user_variable ( & lc) )
55- . with_is_parameter ( ( idx > 0 && idx <= num_args) && !self . is_zst ( var_ty) ) ;
39+ let sym =
40+ Symbol :: variable ( name, base_name, var_type, self . codegen_span_stable ( ldata. span ) )
41+ . with_is_hidden ( !self . is_user_variable ( & lc) )
42+ . with_is_parameter ( ( lc > 0 && lc <= num_args) && !self . is_zst_stable ( ldata. ty ) ) ;
5643 let sym_e = sym. to_expr ( ) ;
5744 self . symbol_table . insert ( sym) ;
5845
5946 // Index 0 represents the return value, which does not need to be
6047 // declared in the first block
61- if lc. index ( ) < 1 || lc. index ( ) > mir . arg_count {
48+ if lc < 1 || lc > body . arg_locals ( ) . len ( ) {
6249 let init = self . codegen_default_initializer ( & sym_e) ;
6350 self . current_fn_mut ( ) . push_onto_block ( Stmt :: decl ( sym_e, init, loc) ) ;
6451 }
65- } ) ;
52+ }
6653 }
6754
68- pub fn codegen_function ( & mut self , instance : Instance < ' tcx > ) {
69- self . set_current_fn ( instance) ;
70- let name = self . current_fn ( ) . name ( ) ;
55+ pub fn codegen_function ( & mut self , instance : Instance ) {
56+ let name = self . symbol_name_stable ( instance) ;
7157 let old_sym = self . symbol_table . lookup ( & name) . unwrap ( ) ;
7258
73- let _trace_span =
74- debug_span ! ( "CodegenFunction" , name = self . current_fn( ) . readable_name( ) ) . entered ( ) ;
59+ let _trace_span = debug_span ! ( "CodegenFunction" , name = instance. name( ) ) . entered ( ) ;
7560 if old_sym. is_function_definition ( ) {
7661 debug ! ( "Double codegen of {:?}" , old_sym) ;
7762 } else {
7863 assert ! ( old_sym. is_function( ) ) ;
79- let mir = self . current_fn ( ) . body_internal ( ) ;
80- self . print_instance ( instance, mir) ;
81- self . codegen_function_prelude ( ) ;
82- self . codegen_declare_variables ( ) ;
83-
84- reverse_postorder ( mir) . for_each ( |( bb, bbd) | self . codegen_block ( bb, bbd) ) ;
85-
86- let loc = self . codegen_span ( & mir. span ) ;
64+ let body = instance. body ( ) . unwrap ( ) ;
65+ self . set_current_fn ( instance, & body) ;
66+ self . print_instance ( instance, & body) ;
67+ self . codegen_function_prelude ( & body) ;
68+ self . codegen_declare_variables ( & body) ;
69+
70+ // Get the order from internal body for now.
71+ let internal_body = self . current_fn ( ) . body_internal ( ) ;
72+ reverse_postorder ( internal_body)
73+ . for_each ( |( bb, _) | self . codegen_block ( bb. index ( ) , & body. blocks [ bb. index ( ) ] ) ) ;
74+
75+ let loc = self . codegen_span_stable ( instance. def . span ( ) ) ;
8776 let stmts = self . current_fn_mut ( ) . extract_block ( ) ;
88- let body = Stmt :: block ( stmts, loc) ;
89- self . symbol_table . update_fn_declaration_with_definition ( & name, body) ;
77+ let goto_body = Stmt :: block ( stmts, loc) ;
78+ self . symbol_table . update_fn_declaration_with_definition ( & name, goto_body) ;
79+ self . reset_current_fn ( ) ;
9080 }
91- self . reset_current_fn ( ) ;
9281 }
9382
9483 /// Codegen changes required due to the function ABI.
9584 /// We currently untuple arguments for RustCall ABI where the `spread_arg` is set.
96- fn codegen_function_prelude ( & mut self ) {
97- let mir = self . current_fn ( ) . body_internal ( ) ;
98- if let Some ( spread_arg) = mir . spread_arg {
99- self . codegen_spread_arg ( mir , spread_arg) ;
85+ fn codegen_function_prelude ( & mut self , body : & Body ) {
86+ debug ! ( spread_arg=?body . spread_arg ( ) , "codegen_function_prelude" ) ;
87+ if let Some ( spread_arg) = body . spread_arg ( ) {
88+ self . codegen_spread_arg ( body , spread_arg) ;
10089 }
10190 }
10291
@@ -117,34 +106,27 @@ impl<'tcx> GotocCtx<'tcx> {
117106 ///
118107 /// See:
119108 /// <https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Determine.20untupled.20closure.20args.20from.20Instance.3F>
120- fn codegen_spread_arg ( & mut self , mir : & Body < ' tcx > , spread_arg : Local ) {
121- tracing :: debug!( current=?self . current_fn, "codegen_spread_arg" ) ;
122- let spread_data = & mir . local_decls ( ) [ spread_arg] ;
123- let tup_ty = self . monomorphize ( spread_data. ty ) ;
124- if self . is_zst ( tup_ty) {
109+ fn codegen_spread_arg ( & mut self , body : & Body , spread_arg : Local ) {
110+ debug ! ( current=?self . current_fn( ) . name ( ) , "codegen_spread_arg" ) ;
111+ let spread_data = & body . locals ( ) [ spread_arg] ;
112+ let tup_ty = spread_data. ty ;
113+ if self . is_zst_stable ( tup_ty) {
125114 // No need to spread a ZST since it will be ignored.
126115 return ;
127116 }
128117
129- let loc = self . codegen_span ( & spread_data. source_info . span ) ;
118+ let loc = self . codegen_span_stable ( spread_data. span ) ;
130119
131120 // Get the function signature from MIR, _before_ we untuple
132- let fntyp = self . current_fn ( ) . instance ( ) . ty ( self . tcx , ty:: ParamEnv :: reveal_all ( ) ) ;
133- let sig = match fntyp. kind ( ) {
134- ty:: FnPtr ( ..) | ty:: FnDef ( ..) => fntyp. fn_sig ( self . tcx ) . skip_binder ( ) ,
135- // Closures themselves will have their arguments already untupled,
136- // see Zulip link above.
137- ty:: Closure ( ..) => unreachable ! (
138- "Unexpected `spread arg` set for closure, got: {:?}, {:?}" ,
139- fntyp,
140- self . current_fn( ) . readable_name( )
141- ) ,
142- _ => unreachable ! (
143- "Expected function type for `spread arg` prelude, got: {:?}, {:?}" ,
144- fntyp,
145- self . current_fn( ) . readable_name( )
146- ) ,
147- } ;
121+ let instance = self . current_fn ( ) . instance_stable ( ) ;
122+ // Closures themselves will have their arguments already untupled,
123+ // see Zulip link above.
124+ assert ! (
125+ !instance. ty( ) . kind( ) . is_closure( ) ,
126+ "Unexpected spread arg `{}` set for closure `{}`" ,
127+ spread_arg,
128+ instance. name( )
129+ ) ;
148130
149131 // When we codegen the function signature elsewhere, we will codegen the untupled version.
150132 // We then marshall the arguments into a local variable holding the expected tuple.
@@ -166,7 +148,7 @@ impl<'tcx> GotocCtx<'tcx> {
166148 // };
167149 // ```
168150 // Note how the compiler has reordered the fields to improve packing.
169- let tup_type = self . codegen_ty ( tup_ty) ;
151+ let tup_type = self . codegen_ty_stable ( tup_ty) ;
170152
171153 // We need to marshall the arguments into the tuple
172154 // The arguments themselves have been tacked onto the explicit function paramaters by
@@ -185,21 +167,19 @@ impl<'tcx> GotocCtx<'tcx> {
185167 // }
186168 // ```
187169
188- let tupe = sig. inputs ( ) . last ( ) . unwrap ( ) ;
189- let args = match tupe. kind ( ) {
190- ty:: Tuple ( args) => * args,
191- _ => unreachable ! ( "a function's spread argument must be a tuple" ) ,
170+ let TyKind :: RigidTy ( RigidTy :: Tuple ( args) ) = tup_ty. kind ( ) else {
171+ unreachable ! ( "a function's spread argument must be a tuple" )
192172 } ;
193- let starting_idx = sig . inputs ( ) . len ( ) ;
173+ let starting_idx = spread_arg ;
194174 let marshalled_tuple_fields =
195175 BTreeMap :: from_iter ( args. iter ( ) . enumerate ( ) . map ( |( arg_i, arg_t) | {
196176 // The components come at the end, so offset by the untupled length.
197177 // This follows the naming convention defined in `typ.rs`.
198- let lc = Local :: from_usize ( arg_i + starting_idx) ;
178+ let lc = arg_i + starting_idx;
199179 let ( name, base_name) = self . codegen_spread_arg_name ( & lc) ;
200- let sym = Symbol :: variable ( name, base_name, self . codegen_ty ( arg_t) , loc)
180+ let sym = Symbol :: variable ( name, base_name, self . codegen_ty_stable ( * arg_t) , loc)
201181 . with_is_hidden ( false )
202- . with_is_parameter ( !self . is_zst ( arg_t) ) ;
182+ . with_is_parameter ( !self . is_zst_stable ( * arg_t) ) ;
203183 // The spread arguments are additional function paramaters that are patched in
204184 // They are to the function signature added in the `fn_typ` function.
205185 // But they were never added to the symbol table, which we currently do here.
@@ -222,19 +202,18 @@ impl<'tcx> GotocCtx<'tcx> {
222202 ) ;
223203 }
224204
225- pub fn declare_function ( & mut self , instance : Instance < ' tcx > ) {
226- debug ! ( "declaring {}; {:?}" , instance, instance) ;
227- self . set_current_fn ( instance) ;
228- debug ! ( krate = self . current_fn( ) . krate( ) . as_str( ) ) ;
229- debug ! ( is_std = self . current_fn( ) . is_std( ) ) ;
230- self . ensure ( & self . current_fn ( ) . name ( ) , |ctx, fname| {
231- let mir = ctx. current_fn ( ) . body_internal ( ) ;
205+ pub fn declare_function ( & mut self , instance : Instance ) {
206+ debug ! ( "declaring {}; {:?}" , instance. name( ) , instance) ;
207+ let body = instance. body ( ) . unwrap ( ) ;
208+ self . set_current_fn ( instance, & body) ;
209+ debug ! ( krate=?instance. def. krate( ) , is_std=self . current_fn( ) . is_std( ) , "declare_function" ) ;
210+ self . ensure ( & self . symbol_name_stable ( instance) , |ctx, fname| {
232211 Symbol :: function (
233212 fname,
234- ctx. fn_typ ( ) ,
213+ ctx. fn_typ ( & body ) ,
235214 None ,
236- ctx . current_fn ( ) . readable_name ( ) ,
237- ctx. codegen_span ( & mir . span ) ,
215+ instance . name ( ) ,
216+ ctx. codegen_span_stable ( instance . def . span ( ) ) ,
238217 )
239218 } ) ;
240219 self . reset_current_fn ( ) ;
0 commit comments