11use std:: borrow:: Cow ;
22
3- use rustc:: { mir, ty } ;
4- use rustc:: ty:: Instance ;
5- use rustc:: ty:: layout:: { self , TyLayout , LayoutOf } ;
3+ use rustc:: mir;
4+ use rustc:: ty:: { self , Instance , Ty } ;
5+ use rustc:: ty:: layout:: { self , FnAbiExt , TyLayout , LayoutOf } ;
66use syntax:: source_map:: Span ;
7+ use rustc_target:: abi:: call:: FnAbi ;
78use rustc_target:: spec:: abi:: Abi ;
89
910use super :: {
@@ -60,16 +61,22 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
6061 ..
6162 } => {
6263 let func = self . eval_operand ( func, None ) ?;
63- let ( fn_val, abi) = match func. layout . ty . kind {
64+ let ( fn_val, abi, fn_abi ) = match func. layout . ty . kind {
6465 ty:: FnPtr ( sig) => {
6566 let caller_abi = sig. abi ( ) ;
6667 let fn_ptr = self . read_scalar ( func) ?. not_undef ( ) ?;
6768 let fn_val = self . memory . get_fn ( fn_ptr) ?;
68- ( fn_val, caller_abi)
69+ // FIXME(eddyb) compute `extra_args` to pass to
70+ // `FnAbi::of_fn_ptr` to support C variadics.
71+ ( fn_val, caller_abi, FnAbi :: of_fn_ptr ( self , sig, & [ ] ) )
6972 }
7073 ty:: FnDef ( def_id, substs) => {
7174 let sig = func. layout . ty . fn_sig ( * self . tcx ) ;
72- ( FnVal :: Instance ( self . resolve ( def_id, substs) ?) , sig. abi ( ) )
75+ let instance = self . resolve ( def_id, substs) ?;
76+ // FIXME(eddyb) compute `extra_args` to pass to
77+ // `FnAbi::of_instance` to support C variadics.
78+ let fn_abi = FnAbi :: of_instance ( self , instance, & [ ] ) ;
79+ ( FnVal :: Instance ( instance) , sig. abi ( ) , fn_abi)
7380 } ,
7481 _ => {
7582 bug ! ( "invalid callee of type {:?}" , func. layout. ty)
@@ -84,6 +91,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
8491 fn_val,
8592 terminator. source_info . span ,
8693 abi,
94+ & fn_abi,
8795 & args[ ..] ,
8896 ret,
8997 * cleanup
@@ -234,7 +242,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
234242 & mut self ,
235243 fn_val : FnVal < ' tcx , M :: ExtraFnVal > ,
236244 span : Span ,
245+ // FIXME(eddyb) this shouldn't be needed, its main purpose
246+ // right now is special-casing `RustCall` and intrinsics.
237247 caller_abi : Abi ,
248+ caller_fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
238249 args : & [ OpTy < ' tcx , M :: PointerTag > ] ,
239250 ret : Option < ( PlaceTy < ' tcx , M :: PointerTag > , mir:: BasicBlock ) > ,
240251 unwind : Option < mir:: BasicBlock >
@@ -249,26 +260,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
249260 } ;
250261
251262 // ABI check
263+ // FIXME(eddyb) check every aspect of `FnAbi` and use it below
264+ // for adjusting various details (such as ignoring ZSTs).
252265 {
253- let callee_abi = {
254- let instance_ty = instance. ty ( * self . tcx ) ;
255- match instance_ty. kind {
256- ty:: FnDef ( ..) =>
257- instance_ty. fn_sig ( * self . tcx ) . abi ( ) ,
258- ty:: Closure ( ..) => Abi :: RustCall ,
259- ty:: Generator ( ..) => Abi :: Rust ,
260- _ => bug ! ( "unexpected callee ty: {:?}" , instance_ty) ,
261- }
262- } ;
263- let normalize_abi = |abi| match abi {
264- Abi :: Rust | Abi :: RustCall | Abi :: RustIntrinsic | Abi :: PlatformIntrinsic =>
265- // These are all the same ABI, really.
266- Abi :: Rust ,
267- abi =>
268- abi,
269- } ;
270- if normalize_abi ( caller_abi) != normalize_abi ( callee_abi) {
271- throw_unsup ! ( FunctionAbiMismatch ( caller_abi, callee_abi) )
266+ // FIXME(eddyb) compute `extra_args` to pass to
267+ // `FnAbi::of_instance` to support C variadics.
268+ let callee_fn_abi = FnAbi :: of_instance ( self , instance, & [ ] ) ;
269+ if caller_fn_abi. conv != callee_fn_abi. conv {
270+ throw_unsup ! ( FunctionAbiMismatch ( caller_fn_abi. conv, callee_fn_abi. conv) )
272271 }
273272 }
274273
@@ -444,7 +443,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
444443 } ) ;
445444 trace ! ( "Patched self operand to {:#?}" , args[ 0 ] ) ;
446445 // recurse with concrete function
447- self . eval_fn_call ( drop_fn, span, caller_abi, & args, ret, unwind)
446+ self . eval_fn_call ( drop_fn, span, caller_abi, caller_fn_abi , & args, ret, unwind)
448447 }
449448 }
450449 }
@@ -479,10 +478,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
479478 let ty = self . tcx . mk_unit ( ) ; // return type is ()
480479 let dest = MPlaceTy :: dangling ( self . layout_of ( ty) ?, self ) ;
481480
481+ // FIXME(eddyb) perhaps compute this more like the way it's done in
482+ // `rustc_codegen_ssa::mir::block`?
483+ let fn_abi = FnAbi :: of_instance ( self , instance, & [ ] ) ;
484+
482485 self . eval_fn_call (
483486 FnVal :: Instance ( instance) ,
484487 span,
485488 Abi :: Rust ,
489+ & fn_abi,
486490 & [ arg. into ( ) ] ,
487491 Some ( ( dest. into ( ) , target) ) ,
488492 unwind
0 commit comments