@@ -6,23 +6,32 @@ use rustc_hir::{
66 def:: DefKind ,
77 def_id:: { CrateNum , LOCAL_CRATE } ,
88} ;
9- use rustc_middle:: middle:: {
10- codegen_fn_attrs:: CodegenFnAttrFlags , dependency_format:: Linkage ,
11- exported_symbols:: ExportedSymbol ,
12- } ;
139use rustc_middle:: mir;
1410use 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+ } ;
1518use rustc_session:: config:: CrateType ;
1619use rustc_span:: Symbol ;
1720use rustc_target:: {
18- abi:: { Align , Size } ,
21+ abi:: { call :: FnAbi , Align , Size } ,
1922 spec:: abi:: Abi ,
2023} ;
2124
2225use super :: backtrace:: EvalContextExt as _;
2326use crate :: * ;
2427use helpers:: { ToHost , ToSoft } ;
2528
29+ #[ derive( Debug , Copy , Clone ) ]
30+ pub enum ExtraFnVal {
31+ ForeignFn { link_name : Symbol } ,
32+ DynSym ( DynSym ) ,
33+ }
34+
2635/// Type of dynamic symbols (for `dlsym` et al)
2736#[ derive( Debug , Copy , Clone ) ]
2837pub struct DynSym ( Symbol ) ;
@@ -55,12 +64,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
5564 fn emulate_foreign_item (
5665 & mut self ,
5766 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 > ] ,
6069 dest : & PlaceTy < ' tcx , Provenance > ,
6170 ret : Option < mir:: BasicBlock > ,
6271 unwind : mir:: UnwindAction ,
63- ) -> InterpResult < ' tcx , Option < ( & ' mir mir :: Body < ' tcx > , ty :: Instance < ' tcx > ) > > {
72+ ) -> InterpResult < ' tcx , Option < ( ) > > {
6473 let this = self . eval_context_mut ( ) ;
6574 let tcx = this. tcx . tcx ;
6675
@@ -69,67 +78,102 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
6978 None =>
7079 match link_name. as_str ( ) {
7180 "miri_start_panic" => {
81+ let args = this. copy_fn_args ( args) ?; // FIXME: Should `InPlace` arguments be reset to uninit?
82+
7283 // `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) ?;
7485 return Ok ( None ) ;
7586 }
7687 // This matches calls to the foreign item `panic_impl`.
7788 // The implementation is provided by the function with the `#[panic_handler]` attribute.
7889 "panic_impl" => {
7990 // 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`.
8292 this. check_abi_and_shim_symbol_clash ( abi, Abi :: Rust , link_name) ?;
8393 let panic_impl_id = tcx. lang_items ( ) . panic_impl ( ) . unwrap ( ) ;
8494 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 ( ( ) ) ) ;
89107 }
90108 #[ rustfmt:: skip]
91- | "exit"
109+ "exit"
92110 | "ExitProcess"
93111 => {
94112 let exp_abi = if link_name. as_str ( ) == "exit" {
95113 Abi :: C { unwind : false }
96114 } else {
97115 Abi :: System { unwind : false }
98116 } ;
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) ?;
100119 // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway
101120 let code = this. read_scalar ( code) ?. to_i32 ( ) ?;
102121 throw_machine_stop ! ( TerminationInfo :: Exit { code: code. into( ) , leak_check: false } ) ;
103122 }
104123 "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) ?;
106127 throw_machine_stop ! ( TerminationInfo :: Abort (
107128 "the program aborted execution" . to_owned( )
108129 ) )
109130 }
110131 _ => {
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 ( ( ) ) ) ;
113144 }
145+
114146 this. handle_unsupported ( format ! (
115147 "can't call (diverging) foreign function: {link_name}"
116148 ) ) ?;
149+
117150 return Ok ( None ) ;
118151 }
119152 } ,
120153 Some ( p) => p,
121154 } ;
122155
123156 // 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) ? {
125159 EmulateForeignItemResult :: NeedsJumping => {
126160 trace ! ( "{:?}" , this. dump_place( dest) ) ;
127161 this. go_to_block ( ret) ;
128162 }
129163 EmulateForeignItemResult :: AlreadyJumped => ( ) ,
130164 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 ( ( ) ) ) ;
133177 }
134178
135179 this. handle_unsupported ( format ! (
@@ -147,13 +191,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
147191 fn emulate_dyn_sym (
148192 & mut self ,
149193 sym : DynSym ,
150- abi : Abi ,
151- args : & [ OpTy < ' tcx , Provenance > ] ,
194+ abis : ( Abi , & FnAbi < ' tcx , Ty < ' tcx > > ) ,
195+ args : & [ FnArg < ' tcx , Provenance > ] ,
152196 dest : & PlaceTy < ' tcx , Provenance > ,
153197 ret : Option < mir:: BasicBlock > ,
154198 unwind : mir:: UnwindAction ,
155199 ) -> 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) ?;
157201 assert ! ( res. is_none( ) , "DynSyms that delegate are not supported" ) ;
158202 Ok ( ( ) )
159203 }
@@ -162,7 +206,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
162206 fn lookup_exported_symbol (
163207 & mut self ,
164208 link_name : Symbol ,
165- ) -> InterpResult < ' tcx , Option < ( & ' mir mir :: Body < ' tcx > , ty:: Instance < ' tcx > ) > > {
209+ ) -> InterpResult < ' tcx , Option < ty:: Instance < ' tcx > > > {
166210 let this = self . eval_context_mut ( ) ;
167211 let tcx = this. tcx . tcx ;
168212
@@ -246,10 +290,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
246290 e. insert ( instance_and_crate. map ( |ic| ic. 0 ) )
247291 }
248292 } ;
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)
253295 }
254296
255297 fn malloc (
0 commit comments