@@ -182,20 +182,28 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
182
182
}
183
183
184
184
fn check_argument_compat (
185
+ rust_abi : bool ,
185
186
caller : TyLayout < ' tcx > ,
186
187
callee : TyLayout < ' tcx > ,
187
188
) -> bool {
188
189
if caller. ty == callee. ty {
189
190
// No question
190
191
return true ;
191
192
}
193
+ if !rust_abi {
194
+ // Don't risk anything
195
+ return false ;
196
+ }
192
197
// Compare layout
193
198
match ( & caller. abi , & callee. abi ) {
199
+ // Different valid ranges are okay (once we enforce validity,
200
+ // that will take care to make it UB to leave the range, just
201
+ // like for transmute).
194
202
( layout:: Abi :: Scalar ( ref caller) , layout:: Abi :: Scalar ( ref callee) ) =>
195
- // Different valid ranges are okay (once we enforce validity,
196
- // that will take care to make it UB to leave the range, just
197
- // like for transmute).
198
203
caller. value == callee. value ,
204
+ ( layout:: Abi :: ScalarPair ( ref caller1, ref caller2) ,
205
+ layout:: Abi :: ScalarPair ( ref callee1, ref callee2) ) =>
206
+ caller1. value == callee1. value && caller2. value == callee2. value ,
199
207
// Be conservative
200
208
_ => false
201
209
}
@@ -204,22 +212,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
204
212
/// Pass a single argument, checking the types for compatibility.
205
213
fn pass_argument (
206
214
& mut self ,
207
- skip_zst : bool ,
215
+ rust_abi : bool ,
208
216
caller_arg : & mut impl Iterator < Item =OpTy < ' tcx , M :: PointerTag > > ,
209
217
callee_arg : PlaceTy < ' tcx , M :: PointerTag > ,
210
218
) -> EvalResult < ' tcx > {
211
- if skip_zst && callee_arg. layout . is_zst ( ) {
219
+ if rust_abi && callee_arg. layout . is_zst ( ) {
212
220
// Nothing to do.
213
221
trace ! ( "Skipping callee ZST" ) ;
214
222
return Ok ( ( ) ) ;
215
223
}
216
224
let caller_arg = caller_arg. next ( )
217
225
. ok_or_else ( || EvalErrorKind :: FunctionArgCountMismatch ) ?;
218
- if skip_zst {
226
+ if rust_abi {
219
227
debug_assert ! ( !caller_arg. layout. is_zst( ) , "ZSTs must have been already filtered out" ) ;
220
228
}
221
229
// Now, check
222
- if !Self :: check_argument_compat ( caller_arg. layout , callee_arg. layout ) {
230
+ if !Self :: check_argument_compat ( rust_abi , caller_arg. layout , callee_arg. layout ) {
223
231
return err ! ( FunctionArgMismatch ( caller_arg. layout. ty, callee_arg. layout. ty) ) ;
224
232
}
225
233
// We allow some transmutes here
@@ -319,7 +327,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
319
327
// Figure out how to pass which arguments.
320
328
// We have two iterators: Where the arguments come from,
321
329
// and where they go to.
322
- let skip_zst = match caller_abi {
330
+ let rust_abi = match caller_abi {
323
331
Abi :: Rust | Abi :: RustCall => true ,
324
332
_ => false
325
333
} ;
@@ -344,7 +352,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
344
352
} ;
345
353
// Skip ZSTs
346
354
let mut caller_iter = caller_args. iter ( )
347
- . filter ( |op| !skip_zst || !op. layout . is_zst ( ) )
355
+ . filter ( |op| !rust_abi || !op. layout . is_zst ( ) )
348
356
. map ( |op| * op) ;
349
357
350
358
// Now we have to spread them out across the callee's locals,
@@ -359,11 +367,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
359
367
// Must be a tuple
360
368
for i in 0 ..dest. layout . fields . count ( ) {
361
369
let dest = self . place_field ( dest, i as u64 ) ?;
362
- self . pass_argument ( skip_zst , & mut caller_iter, dest) ?;
370
+ self . pass_argument ( rust_abi , & mut caller_iter, dest) ?;
363
371
}
364
372
} else {
365
373
// Normal argument
366
- self . pass_argument ( skip_zst , & mut caller_iter, dest) ?;
374
+ self . pass_argument ( rust_abi , & mut caller_iter, dest) ?;
367
375
}
368
376
}
369
377
// Now we should have no more caller args
@@ -374,7 +382,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
374
382
// Don't forget to check the return type!
375
383
if let Some ( caller_ret) = dest {
376
384
let callee_ret = self . eval_place ( & mir:: Place :: Local ( mir:: RETURN_PLACE ) ) ?;
377
- if !Self :: check_argument_compat ( caller_ret. layout , callee_ret. layout ) {
385
+ if !Self :: check_argument_compat (
386
+ rust_abi,
387
+ caller_ret. layout ,
388
+ callee_ret. layout ,
389
+ ) {
378
390
return err ! ( FunctionRetMismatch (
379
391
caller_ret. layout. ty, callee_ret. layout. ty
380
392
) ) ;
0 commit comments