@@ -327,6 +327,76 @@ fn adjust_for_rust_scalar<'tcx>(
327
327
}
328
328
}
329
329
330
+ /// Ensure that the ABI makes basic sense.
331
+ fn fn_abi_sanity_check < ' tcx > ( cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > , fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ) {
332
+ fn fn_arg_sanity_check < ' tcx > (
333
+ cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
334
+ fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
335
+ arg : & ArgAbi < ' tcx , Ty < ' tcx > > ,
336
+ ) {
337
+ match & arg. mode {
338
+ PassMode :: Ignore => { }
339
+ PassMode :: Direct ( _) => {
340
+ // Here the Rust type is used to determine the actual ABI, so we have to be very
341
+ // careful. Scalar/ScalarPair is fine, since backends will generally use
342
+ // `layout.abi` and ignore everything else. We should just reject `Aggregate`
343
+ // entirely here, but some targets need to be fixed first.
344
+ if matches ! ( arg. layout. abi, Abi :: Aggregate { .. } ) {
345
+ // For an unsized type we'd only pass the sized prefix, so there is no universe
346
+ // in which we ever want to allow this.
347
+ assert ! (
348
+ arg. layout. is_sized( ) ,
349
+ "`PassMode::Direct` for unsized type in ABI: {:#?}" ,
350
+ fn_abi
351
+ ) ;
352
+ // This really shouldn't happen even for sized aggregates, since
353
+ // `immediate_llvm_type` will use `layout.fields` to turn this Rust type into an
354
+ // LLVM type. This means all sorts of Rust type details leak into the ABI.
355
+ // However wasm sadly *does* currently use this mode so we have to allow it --
356
+ // but we absolutely shouldn't let any more targets do that.
357
+ // (Also see <https://github.com/rust-lang/rust/issues/115666>.)
358
+ //
359
+ // The unstable abi `PtxKernel` also uses Direct for now.
360
+ // It needs to switch to something else before stabilization can happen.
361
+ // (See issue: https://github.com/rust-lang/rust/issues/117271)
362
+ assert ! (
363
+ matches!( & * cx. tcx. sess. target. arch, "wasm32" | "wasm64" )
364
+ || fn_abi. conv == Conv :: PtxKernel ,
365
+ "`PassMode::Direct` for aggregates only allowed on wasm and `extern \" ptx-kernel\" ` fns\n Problematic type: {:#?}" ,
366
+ arg. layout,
367
+ ) ;
368
+ }
369
+ }
370
+ PassMode :: Pair ( _, _) => {
371
+ // Similar to `Direct`, we need to make sure that backends use `layout.abi` and
372
+ // ignore the rest of the layout.
373
+ assert ! (
374
+ matches!( arg. layout. abi, Abi :: ScalarPair ( ..) ) ,
375
+ "PassMode::Pair for type {}" ,
376
+ arg. layout. ty
377
+ ) ;
378
+ }
379
+ PassMode :: Cast { .. } => {
380
+ // `Cast` means "transmute to `CastType`"; that only makes sense for sized types.
381
+ assert ! ( arg. layout. is_sized( ) ) ;
382
+ }
383
+ PassMode :: Indirect { meta_attrs : None , .. } => {
384
+ // No metadata, must be sized.
385
+ assert ! ( arg. layout. is_sized( ) ) ;
386
+ }
387
+ PassMode :: Indirect { meta_attrs : Some ( _) , on_stack, .. } => {
388
+ // With metadata. Must be unsized and not on the stack.
389
+ assert ! ( arg. layout. is_unsized( ) && !on_stack) ;
390
+ }
391
+ }
392
+ }
393
+
394
+ for arg in fn_abi. args . iter ( ) {
395
+ fn_arg_sanity_check ( cx, fn_abi, arg) ;
396
+ }
397
+ fn_arg_sanity_check ( cx, fn_abi, & fn_abi. ret ) ;
398
+ }
399
+
330
400
// FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
331
401
// arguments of this method, into a separate `struct`.
332
402
#[ tracing:: instrument( level = "debug" , skip( cx, caller_location, fn_def_id, force_thin_self_ptr) ) ]
@@ -453,6 +523,7 @@ fn fn_abi_new_uncached<'tcx>(
453
523
} ;
454
524
fn_abi_adjust_for_abi ( cx, & mut fn_abi, sig. abi , fn_def_id) ?;
455
525
debug ! ( "fn_abi_new_uncached = {:?}" , fn_abi) ;
526
+ fn_abi_sanity_check ( cx, & fn_abi) ;
456
527
Ok ( cx. tcx . arena . alloc ( fn_abi) )
457
528
}
458
529
0 commit comments