@@ -327,10 +327,15 @@ fn adjust_for_rust_scalar<'tcx>(
327327}
328328
329329/// 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+ ) {
331335 fn fn_arg_sanity_check < ' tcx > (
332336 cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
333337 fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
338+ spec_abi : SpecAbi ,
334339 arg : & ArgAbi < ' tcx , Ty < ' tcx > > ,
335340 ) {
336341 match & arg. mode {
@@ -360,8 +365,8 @@ fn fn_abi_sanity_check<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, fn_abi: &FnAbi<'
360365 // (See issue: https://github.com/rust-lang/rust/issues/117271)
361366 assert ! (
362367 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: {:#?}"# ,
365370 arg. layout,
366371 ) ;
367372 }
@@ -391,9 +396,9 @@ fn fn_abi_sanity_check<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, fn_abi: &FnAbi<'
391396 }
392397
393398 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) ;
395400 }
396- fn_arg_sanity_check ( cx, fn_abi, & fn_abi. ret ) ;
401+ fn_arg_sanity_check ( cx, fn_abi, spec_abi , & fn_abi. ret ) ;
397402}
398403
399404// FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
@@ -522,7 +527,7 @@ fn fn_abi_new_uncached<'tcx>(
522527 } ;
523528 fn_abi_adjust_for_abi ( cx, & mut fn_abi, sig. abi , fn_def_id) ?;
524529 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 ) ;
526531 Ok ( cx. tcx . arena . alloc ( fn_abi) )
527532}
528533
@@ -534,6 +539,24 @@ fn fn_abi_adjust_for_abi<'tcx>(
534539 fn_def_id : Option < DefId > ,
535540) -> Result < ( ) , & ' tcx FnAbiError < ' tcx > > {
536541 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+ }
537560 return Ok ( ( ) ) ;
538561 }
539562
0 commit comments