@@ -8,23 +8,32 @@ use rustc_hir::{
8
8
def:: DefKind ,
9
9
def_id:: { CrateNum , LOCAL_CRATE } ,
10
10
} ;
11
- use rustc_middle:: middle:: {
12
- codegen_fn_attrs:: CodegenFnAttrFlags , dependency_format:: Linkage ,
13
- exported_symbols:: ExportedSymbol ,
14
- } ;
15
11
use rustc_middle:: mir;
16
12
use rustc_middle:: ty;
13
+ use rustc_middle:: {
14
+ middle:: {
15
+ codegen_fn_attrs:: CodegenFnAttrFlags , dependency_format:: Linkage ,
16
+ exported_symbols:: ExportedSymbol ,
17
+ } ,
18
+ ty:: Ty ,
19
+ } ;
17
20
use rustc_session:: config:: CrateType ;
18
21
use rustc_span:: Symbol ;
19
22
use rustc_target:: {
20
- abi:: { Align , Size } ,
23
+ abi:: { call :: FnAbi , Align , Size } ,
21
24
spec:: abi:: Abi ,
22
25
} ;
23
26
24
27
use super :: backtrace:: EvalContextExt as _;
25
28
use crate :: * ;
26
29
use helpers:: { ToHost , ToSoft } ;
27
30
31
+ #[ derive( Debug , Copy , Clone ) ]
32
+ pub enum ExtraFnVal {
33
+ ForeignFn { link_name : Symbol } ,
34
+ DynSym ( DynSym ) ,
35
+ }
36
+
28
37
/// Type of dynamic symbols (for `dlsym` et al)
29
38
#[ derive( Debug , Copy , Clone ) ]
30
39
pub struct DynSym ( Symbol ) ;
@@ -57,12 +66,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
57
66
fn emulate_foreign_item (
58
67
& mut self ,
59
68
link_name : Symbol ,
60
- abi : Abi ,
61
- args : & [ OpTy < ' tcx , Provenance > ] ,
69
+ ( abi, fn_abi ) : ( Abi , & FnAbi < ' tcx , Ty < ' tcx > > ) ,
70
+ args : & [ FnArg < ' tcx , Provenance > ] ,
62
71
dest : & PlaceTy < ' tcx , Provenance > ,
63
72
ret : Option < mir:: BasicBlock > ,
64
73
unwind : mir:: UnwindAction ,
65
- ) -> InterpResult < ' tcx , Option < ( & ' mir mir :: Body < ' tcx > , ty :: Instance < ' tcx > ) > > {
74
+ ) -> InterpResult < ' tcx , Option < ( ) > > {
66
75
let this = self . eval_context_mut ( ) ;
67
76
let tcx = this. tcx . tcx ;
68
77
@@ -71,67 +80,102 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
71
80
None =>
72
81
match link_name. as_str ( ) {
73
82
"miri_start_panic" => {
83
+ let args = this. copy_fn_args ( args) ?; // FIXME: Should `InPlace` arguments be reset to uninit?
84
+
74
85
// `check_shim` happens inside `handle_miri_start_panic`.
75
- this. handle_miri_start_panic ( abi, link_name, args, unwind) ?;
86
+ this. handle_miri_start_panic ( abi, link_name, & args, unwind) ?;
76
87
return Ok ( None ) ;
77
88
}
78
89
// This matches calls to the foreign item `panic_impl`.
79
90
// The implementation is provided by the function with the `#[panic_handler]` attribute.
80
91
"panic_impl" => {
81
92
// We don't use `check_shim` here because we are just forwarding to the lang
82
- // item. Argument count checking will be performed when the returned `Body` is
83
- // called.
93
+ // item. Argument count checking will be performed in `eval_fn_call`.
84
94
this. check_abi_and_shim_symbol_clash ( abi, Abi :: Rust , link_name) ?;
85
95
let panic_impl_id = tcx. lang_items ( ) . panic_impl ( ) . unwrap ( ) ;
86
96
let panic_impl_instance = ty:: Instance :: mono ( tcx, panic_impl_id) ;
87
- return Ok ( Some ( (
88
- this. load_mir ( panic_impl_instance. def , None ) ?,
89
- panic_impl_instance,
90
- ) ) ) ;
97
+
98
+ this. eval_fn_call (
99
+ FnVal :: Instance ( panic_impl_instance) ,
100
+ ( abi, fn_abi) ,
101
+ args,
102
+ false ,
103
+ dest,
104
+ ret,
105
+ unwind,
106
+ ) ?;
107
+
108
+ return Ok ( Some ( ( ) ) ) ;
91
109
}
92
110
#[ rustfmt:: skip]
93
- | "exit"
111
+ "exit"
94
112
| "ExitProcess"
95
113
=> {
96
114
let exp_abi = if link_name. as_str ( ) == "exit" {
97
115
Abi :: C { unwind : false }
98
116
} else {
99
117
Abi :: System { unwind : false }
100
118
} ;
101
- let [ code] = this. check_shim ( abi, exp_abi, link_name, args) ?;
119
+ let args = this. copy_fn_args ( args) ?; // FIXME: Should `InPlace` arguments be reset to uninit?
120
+ let [ code] = this. check_shim ( abi, exp_abi, link_name, & args) ?;
102
121
// it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway
103
122
let code = this. read_scalar ( code) ?. to_i32 ( ) ?;
104
123
throw_machine_stop ! ( TerminationInfo :: Exit { code: code. into( ) , leak_check: false } ) ;
105
124
}
106
125
"abort" => {
107
- let [ ] = this. check_shim ( abi, Abi :: C { unwind : false } , link_name, args) ?;
126
+ let args = this. copy_fn_args ( args) ?; // FIXME: Should `InPlace` arguments be reset to uninit?
127
+ let [ ] =
128
+ this. check_shim ( abi, Abi :: C { unwind : false } , link_name, & args) ?;
108
129
throw_machine_stop ! ( TerminationInfo :: Abort (
109
130
"the program aborted execution" . to_owned( )
110
131
) )
111
132
}
112
133
_ => {
113
- if let Some ( body) = this. lookup_exported_symbol ( link_name) ? {
114
- return Ok ( Some ( body) ) ;
134
+ if let Some ( instance) = this. lookup_exported_symbol ( link_name) ? {
135
+ this. eval_fn_call (
136
+ FnVal :: Instance ( instance) ,
137
+ ( abi, fn_abi) ,
138
+ args,
139
+ false ,
140
+ dest,
141
+ ret,
142
+ unwind,
143
+ ) ?;
144
+
145
+ return Ok ( Some ( ( ) ) ) ;
115
146
}
147
+
116
148
this. handle_unsupported ( format ! (
117
149
"can't call (diverging) foreign function: {link_name}"
118
150
) ) ?;
151
+
119
152
return Ok ( None ) ;
120
153
}
121
154
} ,
122
155
Some ( p) => p,
123
156
} ;
124
157
125
158
// Second: functions that return immediately.
126
- match this. emulate_foreign_item_inner ( link_name, abi, args, dest) ? {
159
+ let args2 = this. copy_fn_args ( args) ?; // FIXME: Should `InPlace` arguments be reset to uninit?
160
+ match this. emulate_foreign_item_inner ( link_name, abi, & args2, dest) ? {
127
161
EmulateForeignItemResult :: NeedsJumping => {
128
162
trace ! ( "{:?}" , this. dump_place( dest) ) ;
129
163
this. go_to_block ( ret) ;
130
164
}
131
165
EmulateForeignItemResult :: AlreadyJumped => ( ) ,
132
166
EmulateForeignItemResult :: NotSupported => {
133
- if let Some ( body) = this. lookup_exported_symbol ( link_name) ? {
134
- return Ok ( Some ( body) ) ;
167
+ if let Some ( instance) = this. lookup_exported_symbol ( link_name) ? {
168
+ this. eval_fn_call (
169
+ FnVal :: Instance ( instance) ,
170
+ ( abi, fn_abi) ,
171
+ args,
172
+ false ,
173
+ dest,
174
+ Some ( ret) ,
175
+ unwind,
176
+ ) ?;
177
+
178
+ return Ok ( Some ( ( ) ) ) ;
135
179
}
136
180
137
181
this. handle_unsupported ( format ! (
@@ -149,13 +193,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
149
193
fn emulate_dyn_sym (
150
194
& mut self ,
151
195
sym : DynSym ,
152
- abi : Abi ,
153
- args : & [ OpTy < ' tcx , Provenance > ] ,
196
+ abis : ( Abi , & FnAbi < ' tcx , Ty < ' tcx > > ) ,
197
+ args : & [ FnArg < ' tcx , Provenance > ] ,
154
198
dest : & PlaceTy < ' tcx , Provenance > ,
155
199
ret : Option < mir:: BasicBlock > ,
156
200
unwind : mir:: UnwindAction ,
157
201
) -> InterpResult < ' tcx > {
158
- let res = self . emulate_foreign_item ( sym. 0 , abi , args, dest, ret, unwind) ?;
202
+ let res = self . emulate_foreign_item ( sym. 0 , abis , args, dest, ret, unwind) ?;
159
203
assert ! ( res. is_none( ) , "DynSyms that delegate are not supported" ) ;
160
204
Ok ( ( ) )
161
205
}
@@ -164,7 +208,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
164
208
fn lookup_exported_symbol (
165
209
& mut self ,
166
210
link_name : Symbol ,
167
- ) -> InterpResult < ' tcx , Option < ( & ' mir mir :: Body < ' tcx > , ty:: Instance < ' tcx > ) > > {
211
+ ) -> InterpResult < ' tcx , Option < ty:: Instance < ' tcx > > > {
168
212
let this = self . eval_context_mut ( ) ;
169
213
let tcx = this. tcx . tcx ;
170
214
@@ -248,10 +292,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
248
292
e. insert ( instance_and_crate. map ( |ic| ic. 0 ) )
249
293
}
250
294
} ;
251
- match instance {
252
- None => Ok ( None ) , // no symbol with this name
253
- Some ( instance) => Ok ( Some ( ( this. load_mir ( instance. def , None ) ?, instance) ) ) ,
254
- }
295
+
296
+ Ok ( instance)
255
297
}
256
298
257
299
fn malloc (
0 commit comments