@@ -7,96 +7,85 @@ use crate::codegen_cprover_gotoc::GotocCtx;
7
7
use cbmc:: goto_program:: { Expr , Stmt , Symbol } ;
8
8
use cbmc:: InternString ;
9
9
use 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 ;
12
14
use std:: collections:: BTreeMap ;
13
15
use std:: iter:: FromIterator ;
14
16
use tracing:: { debug, debug_span} ;
15
17
16
18
/// Codegen MIR functions into gotoc
17
19
impl < ' 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
-
26
20
/// Declare variables according to their index.
27
21
/// - Index 0 represents the return value.
28
22
/// - Indices [1, N] represent the function parameters where N is the number of parameters.
29
23
/// - 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 ( ) {
36
29
// We have already added this local in the function prelude, so
37
30
// skip adding it again here.
38
- return ;
31
+ continue ;
39
32
}
40
33
let base_name = self . codegen_var_base_name ( & lc) ;
41
34
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 ) ;
46
37
// Indices [1, N] represent the function parameters where N is the number of parameters.
47
38
// 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 ) ) ;
56
43
let sym_e = sym. to_expr ( ) ;
57
44
self . symbol_table . insert ( sym) ;
58
45
59
46
// Index 0 represents the return value, which does not need to be
60
47
// declared in the first block
61
- if lc. index ( ) < 1 || lc. index ( ) > mir . arg_count {
48
+ if lc < 1 || lc > body . arg_locals ( ) . len ( ) {
62
49
let init = self . codegen_default_initializer ( & sym_e) ;
63
50
self . current_fn_mut ( ) . push_onto_block ( Stmt :: decl ( sym_e, init, loc) ) ;
64
51
}
65
- } ) ;
52
+ }
66
53
}
67
54
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) ;
71
57
let old_sym = self . symbol_table . lookup ( & name) . unwrap ( ) ;
72
58
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 ( ) ;
75
60
if old_sym. is_function_definition ( ) {
76
61
debug ! ( "Double codegen of {:?}" , old_sym) ;
77
62
} else {
78
63
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 ( ) ) ;
87
76
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 ( ) ;
90
80
}
91
- self . reset_current_fn ( ) ;
92
81
}
93
82
94
83
/// Codegen changes required due to the function ABI.
95
84
/// 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) ;
100
89
}
101
90
}
102
91
@@ -117,34 +106,27 @@ impl<'tcx> GotocCtx<'tcx> {
117
106
///
118
107
/// See:
119
108
/// <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) {
125
114
// No need to spread a ZST since it will be ignored.
126
115
return ;
127
116
}
128
117
129
- let loc = self . codegen_span ( & spread_data. source_info . span ) ;
118
+ let loc = self . codegen_span_stable ( spread_data. span ) ;
130
119
131
120
// 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
+ ) ;
148
130
149
131
// When we codegen the function signature elsewhere, we will codegen the untupled version.
150
132
// We then marshall the arguments into a local variable holding the expected tuple.
@@ -166,7 +148,7 @@ impl<'tcx> GotocCtx<'tcx> {
166
148
// };
167
149
// ```
168
150
// 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) ;
170
152
171
153
// We need to marshall the arguments into the tuple
172
154
// The arguments themselves have been tacked onto the explicit function paramaters by
@@ -185,21 +167,19 @@ impl<'tcx> GotocCtx<'tcx> {
185
167
// }
186
168
// ```
187
169
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" )
192
172
} ;
193
- let starting_idx = sig . inputs ( ) . len ( ) ;
173
+ let starting_idx = spread_arg ;
194
174
let marshalled_tuple_fields =
195
175
BTreeMap :: from_iter ( args. iter ( ) . enumerate ( ) . map ( |( arg_i, arg_t) | {
196
176
// The components come at the end, so offset by the untupled length.
197
177
// 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;
199
179
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)
201
181
. with_is_hidden ( false )
202
- . with_is_parameter ( !self . is_zst ( arg_t) ) ;
182
+ . with_is_parameter ( !self . is_zst_stable ( * arg_t) ) ;
203
183
// The spread arguments are additional function paramaters that are patched in
204
184
// They are to the function signature added in the `fn_typ` function.
205
185
// But they were never added to the symbol table, which we currently do here.
@@ -222,19 +202,18 @@ impl<'tcx> GotocCtx<'tcx> {
222
202
) ;
223
203
}
224
204
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| {
232
211
Symbol :: function (
233
212
fname,
234
- ctx. fn_typ ( ) ,
213
+ ctx. fn_typ ( & body ) ,
235
214
None ,
236
- ctx . current_fn ( ) . readable_name ( ) ,
237
- ctx. codegen_span ( & mir . span ) ,
215
+ instance . name ( ) ,
216
+ ctx. codegen_span_stable ( instance . def . span ( ) ) ,
238
217
)
239
218
} ) ;
240
219
self . reset_current_fn ( ) ;
0 commit comments