@@ -8,23 +8,32 @@ use rustc_hir::{
88 def:: DefKind ,
99 def_id:: { CrateNum , LOCAL_CRATE } ,
1010} ;
11- use rustc_middle:: middle:: {
12- codegen_fn_attrs:: CodegenFnAttrFlags , dependency_format:: Linkage ,
13- exported_symbols:: ExportedSymbol ,
14- } ;
1511use rustc_middle:: mir;
1612use 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+ } ;
1720use rustc_session:: config:: CrateType ;
1821use rustc_span:: Symbol ;
1922use rustc_target:: {
20- abi:: { Align , Size } ,
23+ abi:: { call :: FnAbi , Align , Size } ,
2124 spec:: abi:: Abi ,
2225} ;
2326
2427use super :: backtrace:: EvalContextExt as _;
2528use crate :: * ;
2629use helpers:: { ToHost , ToSoft } ;
2730
31+ #[ derive( Debug , Copy , Clone ) ]
32+ pub enum ExtraFnVal {
33+ ForeignFn { link_name : Symbol } ,
34+ DynSym ( DynSym ) ,
35+ }
36+
2837/// Type of dynamic symbols (for `dlsym` et al)
2938#[ derive( Debug , Copy , Clone ) ]
3039pub struct DynSym ( Symbol ) ;
@@ -57,12 +66,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
5766 fn emulate_foreign_item (
5867 & mut self ,
5968 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 > ] ,
6271 dest : & PlaceTy < ' tcx , Provenance > ,
6372 ret : Option < mir:: BasicBlock > ,
6473 unwind : mir:: UnwindAction ,
65- ) -> InterpResult < ' tcx , Option < ( & ' mir mir :: Body < ' tcx > , ty :: Instance < ' tcx > ) > > {
74+ ) -> InterpResult < ' tcx , Option < ( ) > > {
6675 let this = self . eval_context_mut ( ) ;
6776 let tcx = this. tcx . tcx ;
6877
@@ -71,67 +80,102 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
7180 None =>
7281 match link_name. as_str ( ) {
7382 "miri_start_panic" => {
83+ let args = this. copy_fn_args ( args) ?; // FIXME: Should `InPlace` arguments be reset to uninit?
84+
7485 // `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) ?;
7687 return Ok ( None ) ;
7788 }
7889 // This matches calls to the foreign item `panic_impl`.
7990 // The implementation is provided by the function with the `#[panic_handler]` attribute.
8091 "panic_impl" => {
8192 // 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`.
8494 this. check_abi_and_shim_symbol_clash ( abi, Abi :: Rust , link_name) ?;
8595 let panic_impl_id = tcx. lang_items ( ) . panic_impl ( ) . unwrap ( ) ;
8696 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 ( ( ) ) ) ;
91109 }
92110 #[ rustfmt:: skip]
93- | "exit"
111+ "exit"
94112 | "ExitProcess"
95113 => {
96114 let exp_abi = if link_name. as_str ( ) == "exit" {
97115 Abi :: C { unwind : false }
98116 } else {
99117 Abi :: System { unwind : false }
100118 } ;
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) ?;
102121 // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway
103122 let code = this. read_scalar ( code) ?. to_i32 ( ) ?;
104123 throw_machine_stop ! ( TerminationInfo :: Exit { code: code. into( ) , leak_check: false } ) ;
105124 }
106125 "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) ?;
108129 throw_machine_stop ! ( TerminationInfo :: Abort (
109130 "the program aborted execution" . to_owned( )
110131 ) )
111132 }
112133 _ => {
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 ( ( ) ) ) ;
115146 }
147+
116148 this. handle_unsupported ( format ! (
117149 "can't call (diverging) foreign function: {link_name}"
118150 ) ) ?;
151+
119152 return Ok ( None ) ;
120153 }
121154 } ,
122155 Some ( p) => p,
123156 } ;
124157
125158 // 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) ? {
127161 EmulateForeignItemResult :: NeedsJumping => {
128162 trace ! ( "{:?}" , this. dump_place( dest) ) ;
129163 this. go_to_block ( ret) ;
130164 }
131165 EmulateForeignItemResult :: AlreadyJumped => ( ) ,
132166 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 ( ( ) ) ) ;
135179 }
136180
137181 this. handle_unsupported ( format ! (
@@ -149,13 +193,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
149193 fn emulate_dyn_sym (
150194 & mut self ,
151195 sym : DynSym ,
152- abi : Abi ,
153- args : & [ OpTy < ' tcx , Provenance > ] ,
196+ abis : ( Abi , & FnAbi < ' tcx , Ty < ' tcx > > ) ,
197+ args : & [ FnArg < ' tcx , Provenance > ] ,
154198 dest : & PlaceTy < ' tcx , Provenance > ,
155199 ret : Option < mir:: BasicBlock > ,
156200 unwind : mir:: UnwindAction ,
157201 ) -> 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) ?;
159203 assert ! ( res. is_none( ) , "DynSyms that delegate are not supported" ) ;
160204 Ok ( ( ) )
161205 }
@@ -164,7 +208,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
164208 fn lookup_exported_symbol (
165209 & mut self ,
166210 link_name : Symbol ,
167- ) -> InterpResult < ' tcx , Option < ( & ' mir mir :: Body < ' tcx > , ty:: Instance < ' tcx > ) > > {
211+ ) -> InterpResult < ' tcx , Option < ty:: Instance < ' tcx > > > {
168212 let this = self . eval_context_mut ( ) ;
169213 let tcx = this. tcx . tcx ;
170214
@@ -248,10 +292,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
248292 e. insert ( instance_and_crate. map ( |ic| ic. 0 ) )
249293 }
250294 } ;
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)
255297 }
256298
257299 fn malloc (
0 commit comments