@@ -365,10 +365,15 @@ fn adjust_for_rust_scalar<'tcx>(
365
365
}
366
366
367
367
/// Ensure that the ABI makes basic sense.
368
- fn fn_abi_sanity_check < ' tcx > ( cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > , fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ) {
368
+ fn fn_abi_sanity_check < ' tcx > (
369
+ cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
370
+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
371
+ spec_abi : SpecAbi ,
372
+ ) {
369
373
fn fn_arg_sanity_check < ' tcx > (
370
374
cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
371
375
fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
376
+ spec_abi : SpecAbi ,
372
377
arg : & ArgAbi < ' tcx , Ty < ' tcx > > ,
373
378
) {
374
379
match & arg. mode {
@@ -398,8 +403,8 @@ fn fn_abi_sanity_check<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, fn_abi: &FnAbi<'
398
403
// (See issue: https://github.com/rust-lang/rust/issues/117271)
399
404
assert ! (
400
405
matches!( & * cx. tcx. sess. target. arch, "wasm32" | "wasm64" )
401
- || fn_abi . conv == Conv :: PtxKernel ,
402
- "`PassMode::Direct` for aggregates only allowed on wasm and `extern \ " ptx-kernel\" ` fns \n Problematic type: {:#?}" ,
406
+ || matches! ( spec_abi , SpecAbi :: PtxKernel | SpecAbi :: Unadjusted ) ,
407
+ r# "`PassMode::Direct` for aggregates only allowed for "unadjusted" and "ptx-kernel" functions and on wasm \nProblematic type: {:#?}"# ,
403
408
arg. layout,
404
409
) ;
405
410
}
@@ -429,9 +434,9 @@ fn fn_abi_sanity_check<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, fn_abi: &FnAbi<'
429
434
}
430
435
431
436
for arg in fn_abi. args . iter ( ) {
432
- fn_arg_sanity_check ( cx, fn_abi, arg) ;
437
+ fn_arg_sanity_check ( cx, fn_abi, spec_abi , arg) ;
433
438
}
434
- fn_arg_sanity_check ( cx, fn_abi, & fn_abi. ret ) ;
439
+ fn_arg_sanity_check ( cx, fn_abi, spec_abi , & fn_abi. ret ) ;
435
440
}
436
441
437
442
// FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
@@ -560,7 +565,7 @@ fn fn_abi_new_uncached<'tcx>(
560
565
} ;
561
566
fn_abi_adjust_for_abi ( cx, & mut fn_abi, sig. abi , fn_def_id) ?;
562
567
debug ! ( "fn_abi_new_uncached = {:?}" , fn_abi) ;
563
- fn_abi_sanity_check ( cx, & fn_abi) ;
568
+ fn_abi_sanity_check ( cx, & fn_abi, sig . abi ) ;
564
569
Ok ( cx. tcx . arena . alloc ( fn_abi) )
565
570
}
566
571
@@ -572,6 +577,24 @@ fn fn_abi_adjust_for_abi<'tcx>(
572
577
fn_def_id : Option < DefId > ,
573
578
) -> Result < ( ) , & ' tcx FnAbiError < ' tcx > > {
574
579
if abi == SpecAbi :: Unadjusted {
580
+ // The "unadjusted" ABI passes aggregates in "direct" mode. That's fragile but needed for
581
+ // some LLVM intrinsics.
582
+ fn unadjust < ' tcx > ( arg : & mut ArgAbi < ' tcx , Ty < ' tcx > > ) {
583
+ // This still uses `PassMode::Pair` for ScalarPair types. That's unlikely to be intended,
584
+ // but who knows what breaks if we change this now.
585
+ if matches ! ( arg. layout. abi, Abi :: Aggregate { .. } ) {
586
+ assert ! (
587
+ arg. layout. abi. is_sized( ) ,
588
+ "'unadjusted' ABI does not support unsized arguments"
589
+ ) ;
590
+ }
591
+ arg. make_direct_deprecated ( ) ;
592
+ }
593
+
594
+ unadjust ( & mut fn_abi. ret ) ;
595
+ for arg in fn_abi. args . iter_mut ( ) {
596
+ unadjust ( arg) ;
597
+ }
575
598
return Ok ( ( ) ) ;
576
599
}
577
600
0 commit comments