1
1
use std:: borrow:: Cow ;
2
2
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 } ;
6
6
use syntax:: source_map:: Span ;
7
+ use rustc_target:: abi:: call:: FnAbi ;
7
8
use rustc_target:: spec:: abi:: Abi ;
8
9
9
10
use super :: {
@@ -60,16 +61,22 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
60
61
..
61
62
} => {
62
63
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 {
64
65
ty:: FnPtr ( sig) => {
65
66
let caller_abi = sig. abi ( ) ;
66
67
let fn_ptr = self . read_scalar ( func) ?. not_undef ( ) ?;
67
68
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, & [ ] ) )
69
72
}
70
73
ty:: FnDef ( def_id, substs) => {
71
74
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)
73
80
} ,
74
81
_ => {
75
82
bug ! ( "invalid callee of type {:?}" , func. layout. ty)
@@ -84,6 +91,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
84
91
fn_val,
85
92
terminator. source_info . span ,
86
93
abi,
94
+ & fn_abi,
87
95
& args[ ..] ,
88
96
ret,
89
97
* cleanup
@@ -234,7 +242,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
234
242
& mut self ,
235
243
fn_val : FnVal < ' tcx , M :: ExtraFnVal > ,
236
244
span : Span ,
245
+ // FIXME(eddyb) this shouldn't be needed, its main purpose
246
+ // right now is special-casing `RustCall` and intrinsics.
237
247
caller_abi : Abi ,
248
+ caller_fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
238
249
args : & [ OpTy < ' tcx , M :: PointerTag > ] ,
239
250
ret : Option < ( PlaceTy < ' tcx , M :: PointerTag > , mir:: BasicBlock ) > ,
240
251
unwind : Option < mir:: BasicBlock >
@@ -249,26 +260,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
249
260
} ;
250
261
251
262
// ABI check
263
+ // FIXME(eddyb) check every aspect of `FnAbi` and use it below
264
+ // for adjusting various details (such as ignoring ZSTs).
252
265
{
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) )
272
271
}
273
272
}
274
273
@@ -444,7 +443,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
444
443
} ) ;
445
444
trace ! ( "Patched self operand to {:#?}" , args[ 0 ] ) ;
446
445
// 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)
448
447
}
449
448
}
450
449
}
@@ -479,10 +478,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
479
478
let ty = self . tcx . mk_unit ( ) ; // return type is ()
480
479
let dest = MPlaceTy :: dangling ( self . layout_of ( ty) ?, self ) ;
481
480
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
+
482
485
self . eval_fn_call (
483
486
FnVal :: Instance ( instance) ,
484
487
span,
485
488
Abi :: Rust ,
489
+ & fn_abi,
486
490
& [ arg. into ( ) ] ,
487
491
Some ( ( dest. into ( ) , target) ) ,
488
492
unwind
0 commit comments