@@ -327,10 +327,15 @@ fn adjust_for_rust_scalar<'tcx>(
327
327
}
328
328
329
329
/// Ensure that the ABI makes basic sense.
330
- fn fn_abi_sanity_check < ' tcx > ( cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > , fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ) {
330
+ fn fn_abi_sanity_check < ' tcx > (
331
+ cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
332
+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
333
+ spec_abi : SpecAbi ,
334
+ ) {
331
335
fn fn_arg_sanity_check < ' tcx > (
332
336
cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
333
337
fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
338
+ spec_abi : SpecAbi ,
334
339
arg : & ArgAbi < ' tcx , Ty < ' tcx > > ,
335
340
) {
336
341
match & arg. mode {
@@ -360,8 +365,8 @@ fn fn_abi_sanity_check<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, fn_abi: &FnAbi<'
360
365
// (See issue: https://github.com/rust-lang/rust/issues/117271)
361
366
assert ! (
362
367
matches!( & * cx. tcx. sess. target. arch, "wasm32" | "wasm64" )
363
- || fn_abi . conv == Conv :: PtxKernel ,
364
- "`PassMode::Direct` for aggregates only allowed on wasm and `extern \ " ptx-kernel\" ` fns \n Problematic type: {:#?}" ,
368
+ || matches! ( spec_abi , SpecAbi :: PtxKernel | SpecAbi :: Unadjusted ) ,
369
+ r# "`PassMode::Direct` for aggregates only allowed for "unadjusted" and "ptx-kernel" functions and on wasm \nProblematic type: {:#?}"# ,
365
370
arg. layout,
366
371
) ;
367
372
}
@@ -391,9 +396,9 @@ fn fn_abi_sanity_check<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, fn_abi: &FnAbi<'
391
396
}
392
397
393
398
for arg in fn_abi. args . iter ( ) {
394
- fn_arg_sanity_check ( cx, fn_abi, arg) ;
399
+ fn_arg_sanity_check ( cx, fn_abi, spec_abi , arg) ;
395
400
}
396
- fn_arg_sanity_check ( cx, fn_abi, & fn_abi. ret ) ;
401
+ fn_arg_sanity_check ( cx, fn_abi, spec_abi , & fn_abi. ret ) ;
397
402
}
398
403
399
404
// FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
@@ -522,7 +527,7 @@ fn fn_abi_new_uncached<'tcx>(
522
527
} ;
523
528
fn_abi_adjust_for_abi ( cx, & mut fn_abi, sig. abi , fn_def_id) ?;
524
529
debug ! ( "fn_abi_new_uncached = {:?}" , fn_abi) ;
525
- fn_abi_sanity_check ( cx, & fn_abi) ;
530
+ fn_abi_sanity_check ( cx, & fn_abi, sig . abi ) ;
526
531
Ok ( cx. tcx . arena . alloc ( fn_abi) )
527
532
}
528
533
@@ -534,6 +539,24 @@ fn fn_abi_adjust_for_abi<'tcx>(
534
539
fn_def_id : Option < DefId > ,
535
540
) -> Result < ( ) , & ' tcx FnAbiError < ' tcx > > {
536
541
if abi == SpecAbi :: Unadjusted {
542
+ // The "unadjusted" ABI passes aggregates in "direct" mode. That's fragile but needed for
543
+ // some LLVM intrinsics.
544
+ fn unadjust < ' tcx > ( arg : & mut ArgAbi < ' tcx , Ty < ' tcx > > ) {
545
+ // This still uses `PassMode::Pair` for ScalarPair types. That's unlikely to be intended,
546
+ // but who knows what breaks if we change this now.
547
+ if matches ! ( arg. layout. abi, Abi :: Aggregate { .. } ) {
548
+ assert ! (
549
+ arg. layout. abi. is_sized( ) ,
550
+ "'unadjusted' ABI does not support unsized arguments"
551
+ ) ;
552
+ }
553
+ arg. make_direct_deprecated ( ) ;
554
+ }
555
+
556
+ unadjust ( & mut fn_abi. ret ) ;
557
+ for arg in fn_abi. args . iter_mut ( ) {
558
+ unadjust ( arg) ;
559
+ }
537
560
return Ok ( ( ) ) ;
538
561
}
539
562
0 commit comments