Skip to content

Commit 111bebd

Browse files
committed
abi: readjust FnAbis to remove unsupported PassModes, via query hooks.
1 parent 13678f8 commit 111bebd

File tree

3 files changed

+49
-8
lines changed

3 files changed

+49
-8
lines changed

crates/rustc_codegen_spirv/src/abi.rs

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
1313
use rustc_middle::ty::query::Providers;
1414
use rustc_middle::ty::subst::SubstsRef;
1515
use rustc_middle::ty::{
16-
self, Const, FloatTy, GeneratorSubsts, IntTy, ParamEnv, PolyFnSig, Ty, TyKind, TypeAndMut,
17-
UintTy,
16+
self, Const, FloatTy, GeneratorSubsts, IntTy, ParamEnv, PolyFnSig, Ty, TyCtxt, TyKind,
17+
TypeAndMut, UintTy,
1818
};
1919
use rustc_span::def_id::DefId;
2020
use rustc_span::Span;
2121
use rustc_span::DUMMY_SP;
22-
use rustc_target::abi::call::{CastTarget, FnAbi, PassMode, Reg, RegKind};
22+
use rustc_target::abi::call::{ArgAbi, ArgAttributes, CastTarget, FnAbi, PassMode, Reg, RegKind};
2323
use rustc_target::abi::{Abi, Align, FieldsShape, Primitive, Scalar, Size, VariantIdx, Variants};
2424
use rustc_target::spec::abi::Abi as SpecAbi;
2525
use std::cell::RefCell;
@@ -35,7 +35,7 @@ pub(crate) fn provide(providers: &mut Providers) {
3535
// However, those functions will be implemented by compiler-builtins:
3636
// https://github.com/rust-lang/rust/blob/5fae56971d8487088c0099c82c0a5ce1638b5f62/library/core/src/lib.rs#L23-L27
3737
// This theoretically then should be fine to leave as C, but, there's no backend hook for
38-
// FnAbi::adjust_for_cabi, causing it to panic:
38+
// `FnAbi::adjust_for_cabi`, causing it to panic:
3939
// https://github.com/rust-lang/rust/blob/5fae56971d8487088c0099c82c0a5ce1638b5f62/compiler/rustc_target/src/abi/call/mod.rs#L603
4040
// So, treat any `extern "C"` functions as `extern "unadjusted"`, to be able to compile libcore with arch=spirv.
4141
providers.fn_sig = |tcx, def_id| {
@@ -49,6 +49,46 @@ pub(crate) fn provide(providers: &mut Providers) {
4949
inner
5050
})
5151
};
52+
53+
// For the Rust ABI, `FnAbi` adjustments are backend-agnostic, but they will
54+
// use features like `PassMode::Cast`, that are incompatible with SPIR-V.
55+
// By hooking the queries computing `FnAbi`s, we can recompute the `FnAbi`
56+
// from the return/args layouts, to e.g. prefer using `PassMode::Direct`.
57+
fn readjust_fn_abi<'tcx>(
58+
tcx: TyCtxt<'tcx>,
59+
fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
60+
) -> &'tcx FnAbi<'tcx, Ty<'tcx>> {
61+
let readjust_arg_abi = |arg: &ArgAbi<'tcx, Ty<'tcx>>| {
62+
let mut arg = ArgAbi::new(&tcx, arg.layout, |_, _, _| ArgAttributes::new());
63+
64+
// Avoid pointlessly passing ZSTs, just like the official Rust ABI.
65+
if arg.layout.is_zst() {
66+
arg.mode = PassMode::Ignore;
67+
}
68+
69+
arg
70+
};
71+
tcx.arena.alloc(FnAbi {
72+
args: fn_abi.args.iter().map(readjust_arg_abi).collect(),
73+
ret: readjust_arg_abi(&fn_abi.ret),
74+
75+
// FIXME(eddyb) validate some of these, and report errors - however,
76+
// we can't just emit errors from here, since we have no `Span`, so
77+
// we should have instead a check on MIR for e.g. C variadic calls.
78+
c_variadic: fn_abi.c_variadic,
79+
fixed_count: fn_abi.fixed_count,
80+
conv: fn_abi.conv,
81+
can_unwind: fn_abi.can_unwind,
82+
})
83+
}
84+
providers.fn_abi_of_fn_ptr = |tcx, key| {
85+
let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS.fn_abi_of_fn_ptr)(tcx, key);
86+
Ok(readjust_fn_abi(tcx, result?))
87+
};
88+
providers.fn_abi_of_instance = |tcx, key| {
89+
let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS.fn_abi_of_instance)(tcx, key);
90+
Ok(readjust_fn_abi(tcx, result?))
91+
};
5292
}
5393

5494
pub(crate) fn provide_extern(providers: &mut Providers) {

tests/ui/dis/issue-723-indirect-input.stderr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ OpDecorate %2 Location 0
1717
%8 = OpTypeInt 32 0
1818
%9 = OpConstant %8 3
1919
%5 = OpTypeArray %7 %9
20-
%10 = OpTypePointer Input %5
20+
%10 = OpTypeFunction %6 %5
2121
%11 = OpTypeFunction %6
22-
%2 = OpVariable %10 Input
22+
%12 = OpTypePointer Input %5
23+
%2 = OpVariable %12 Input

tests/ui/lang/consts/nested-ref-in-composite.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ error: constant arrays/structs cannot contain pointers to other constants
66
|
77
= note: Stack:
88
nested_ref_in_composite::main_pair
9-
Unnamed function ID %26
9+
Unnamed function ID %24
1010

1111
error: constant arrays/structs cannot contain pointers to other constants
1212
--> $DIR/nested-ref-in-composite.rs:27:19
@@ -16,7 +16,7 @@ error: constant arrays/structs cannot contain pointers to other constants
1616
|
1717
= note: Stack:
1818
nested_ref_in_composite::main_array3
19-
Unnamed function ID %34
19+
Unnamed function ID %33
2020

2121
error: error:0:0 - No OpEntryPoint instruction was found. This is only allowed if the Linkage capability is being used.
2222
|

0 commit comments

Comments
 (0)