Skip to content

Commit 74877ee

Browse files
committed
Port backend to newer rustc ABI/target behavior
- Rewrite extern C fn sigs to Rust ABI to satisfy new rustc fn_abi sanity checks. - Handle direct calls represented as ptr<void> by recovering function signature from callee type/fn_abi. - Keep generated SPIR-V target JSON aligned with backend target options and rustc 1.93 schema expectations.
1 parent b4c3e49 commit 74877ee

3 files changed

Lines changed: 58 additions & 30 deletions

File tree

crates/rustc_codegen_spirv-types/src/target_spec.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,10 @@ impl TargetSpecVersion {
5555
/// format the target spec json
5656
pub fn format_spec(&self, target: &SpirvTarget) -> String {
5757
let target_env = target.env();
58-
let extra = match self {
59-
TargetSpecVersion::Rustc_1_76_0 => r#""os": "unknown","#,
60-
_ => r#""crt-static-respected": true,"#,
61-
};
62-
let target_pointer_width = match self {
63-
TargetSpecVersion::Rustc_1_76_0 | TargetSpecVersion::Rustc_1_85_0 => "\"32\"",
64-
TargetSpecVersion::Rustc_1_93_0 => "32",
58+
let (extra, target_pointer_width) = match self {
59+
TargetSpecVersion::Rustc_1_76_0 => (r#""os": "unknown","#, "\"32\""),
60+
TargetSpecVersion::Rustc_1_85_0 => (r#""crt-static-respected": true,"#, "\"32\""),
61+
TargetSpecVersion::Rustc_1_93_0 => (r#""crt-static-respected": true,"#, "32"),
6562
};
6663
format!(
6764
r#"{{

crates/rustc_codegen_spirv/src/abi.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,20 @@ pub(crate) fn provide(providers: &mut Providers) {
3838
// This theoretically then should be fine to leave as C, but, there's no backend hook for
3939
// `FnAbi::adjust_for_cabi`, causing it to panic:
4040
// https://github.com/rust-lang/rust/blob/5fae56971d8487088c0099c82c0a5ce1638b5f62/compiler/rustc_target/src/abi/call/mod.rs#L603
41-
// So, treat any `extern "C"` functions as `extern "unadjusted"`, to be able to compile libcore with arch=spirv.
41+
// So, treat any `extern "C"` functions as `extern "Rust"`, to be able to
42+
// compile libcore with arch=spirv.
43+
//
44+
// NOTE: this used to rewrite to `extern "unadjusted"`, but rustc now
45+
// validates `#[rustc_pass_indirectly_in_non_rustic_abis]` for non-Rust ABIs,
46+
// and `Unadjusted` does not satisfy that requirement.
4247
providers.fn_sig = |tcx, def_id| {
4348
// We can't capture the old fn_sig and just call that, because fn_sig is a `fn`, not a `Fn`, i.e. it can't
4449
// capture variables. Fortunately, the defaults are exposed (thanks rustdoc), so use that instead.
4550
let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS.fn_sig)(tcx, def_id);
4651
result.map_bound(|outer| {
4752
outer.map_bound(|mut inner| {
4853
if let Abi::C { .. } = inner.abi {
49-
inner.abi = Abi::Unadjusted;
54+
inner.abi = Abi::Rust;
5055
}
5156
inner
5257
})

crates/rustc_codegen_spirv/src/builder/builder_methods.rs

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3274,29 +3274,55 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
32743274
// be fixed upstream, so we never see any "function pointer" values being
32753275
// created just to perform direct calls.
32763276
let (callee_val, result_type, argument_types) = match self.lookup_type(callee.ty) {
3277-
SpirvType::Pointer { pointee } => match self.lookup_type(pointee) {
3278-
SpirvType::Function {
3279-
return_type,
3280-
arguments,
3281-
} => (
3282-
if let SpirvValueKind::FnAddr { function } = callee.kind {
3277+
SpirvType::Pointer { pointee } => {
3278+
let (pointee_is_function, result_type, argument_types) = match self
3279+
.lookup_type(pointee)
3280+
{
3281+
SpirvType::Function {
3282+
return_type,
3283+
arguments,
3284+
} => (true, return_type, arguments),
3285+
// Newer rustc can represent direct call targets as `ptr<void>`,
3286+
// with the callee signature carried separately.
3287+
_ => match self.lookup_type(callee_ty) {
3288+
SpirvType::Function {
3289+
return_type,
3290+
arguments,
3291+
} => (false, return_type, arguments),
3292+
_ => {
3293+
let Some(fn_abi) = fn_abi else {
3294+
bug!(
3295+
"call expected `fn` pointer to point to function type, got `{}`",
3296+
self.debug_type(pointee)
3297+
);
3298+
};
3299+
let fn_ty = fn_abi.spirv_type(self.span(), self);
3300+
match self.lookup_type(fn_ty) {
3301+
SpirvType::Function {
3302+
return_type,
3303+
arguments,
3304+
} => (false, return_type, arguments),
3305+
_ => bug!("call expected function ABI to lower to function type"),
3306+
}
3307+
}
3308+
},
3309+
};
3310+
3311+
let callee_val = if let SpirvValueKind::FnAddr { function } = callee.kind {
3312+
if pointee_is_function {
32833313
assert_ty_eq!(self, callee_ty, pointee);
3284-
function
32853314
}
3286-
// Truly indirect call.
3287-
else {
3288-
let fn_ptr_val = callee.def(self);
3289-
self.zombie(fn_ptr_val, "indirect calls are not supported in SPIR-V");
3290-
fn_ptr_val
3291-
},
3292-
return_type,
3293-
arguments,
3294-
),
3295-
_ => bug!(
3296-
"call expected `fn` pointer to point to function type, got `{}`",
3297-
self.debug_type(pointee)
3298-
),
3299-
},
3315+
function
3316+
}
3317+
// Truly indirect call.
3318+
else {
3319+
let fn_ptr_val = callee.def(self);
3320+
self.zombie(fn_ptr_val, "indirect calls are not supported in SPIR-V");
3321+
fn_ptr_val
3322+
};
3323+
3324+
(callee_val, result_type, argument_types)
3325+
}
33003326

33013327
_ => bug!(
33023328
"call expected `fn` pointer type, got `{}`",

0 commit comments

Comments
 (0)