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