Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a731c2d
update toolchain to 2025-11-13, fails
Firestar99 Feb 26, 2026
8aed8db
adjust target declaration, conflicts with target declaration refactor
Firestar99 Feb 26, 2026
b4c3e49
make build.rs handle macOS non-utf8 metadata files
dvdplm Nov 14, 2025
74877ee
Port backend to newer rustc ABI/target behavior
LegNeato Mar 6, 2026
5819774
Update compiletest baselines for new nightly diagnostics
LegNeato Mar 6, 2026
3bbb1fd
Ignore is-like-gpu in target-spec JSON comparison
LegNeato Mar 6, 2026
6e009cc
Fix clippy single_match_else in call callee type handling
LegNeato Mar 6, 2026
10389c9
Update pinned toolchain to nightly-2026-03-06
LegNeato Mar 6, 2026
7db643c
Port backend trait surface to rustc 1.96 APIs
LegNeato Mar 6, 2026
24201f6
Port backend internals and ABI plumbing to latest nightly
LegNeato Mar 6, 2026
131d5ac
Handle newer panic format_args lowering patterns
LegNeato Mar 6, 2026
1693d02
Handle nightly panic format_args lowering and unsized const reification
LegNeato Mar 6, 2026
b591923
Fix new nightly clippy suggestions in type trie and linker
LegNeato Mar 6, 2026
c14bd5b
Port linker test harness to current rustc session APIs
LegNeato Mar 6, 2026
d14c956
Resolve new collapsible-match clippy lints in example runners
LegNeato Mar 6, 2026
14ba846
Guard runtime-array const reification against truncation and ZST tails
LegNeato Mar 6, 2026
bf414e8
Replace fmt::Arguments sentinel metadata with typed constructor tags
LegNeato Mar 6, 2026
cb223c7
Gate bounds/precondition panic-entry detection to non-local core symbols
LegNeato Mar 6, 2026
e1591d0
Fix panic-entry matching and disable-pqp unused-features lint
LegNeato Mar 7, 2026
6434ab8
Bless compiletest stderr for updated nightly diagnostics
LegNeato Mar 7, 2026
cab2c49
Rustfmt codegen_cx panic-entry matcher formatting
LegNeato Mar 7, 2026
929fe0c
spirv-builder: pass -Zjson-target-spec for JSON targets
LegNeato Mar 7, 2026
7303965
compiletests: bless sampled image query_size_lod stderr
LegNeato Mar 7, 2026
3341df6
codegen: adapt panic format_args decompiler for new nightly shapes
LegNeato Mar 7, 2026
cfb698b
codegen: stop treating core precondition_check as panic entry point
LegNeato Mar 7, 2026
8423fd4
codegen: harden panic format_args fallback for split/pass-through shapes
LegNeato Mar 7, 2026
8ffe0f5
codegen: preserve raw fn ABI query invariants
LegNeato Mar 7, 2026
7fc220e
codegen: harden panic message decoding for nightly call shapes
LegNeato Mar 7, 2026
c0beae1
codegen: preserve panic_const messages in panic fast path
LegNeato Mar 7, 2026
b54de5f
codegen: decode panic_bounds_check debug-printf args
LegNeato Mar 7, 2026
c3c424a
compiletests: normalize relative spirv-std paths in stderr
LegNeato Mar 7, 2026
7e26485
fix lint and spv1.3 stderr for panic/message updates
LegNeato Mar 7, 2026
90926fd
codegen: use size-based alloca for panic arg spill
LegNeato Mar 7, 2026
2fe48e0
codegen: emit typed local panic spills without typed_alloca
LegNeato Mar 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/rustc_codegen_spirv-types/src/compile_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl<'a> Trie<'a> {

fn emit(&self, builder: &mut String, full_name: String, indent: usize) {
let mut children = self.children.iter().collect::<Vec<_>>();
children.sort_unstable_by(|(k1, _), (k2, _)| k1.cmp(k2));
children.sort_unstable_by_key(|(k1, _)| *k1);
for (child_name, child) in children {
let full_child_name = if full_name.is_empty() {
(*child_name).to_string()
Expand Down
11 changes: 4 additions & 7 deletions crates/rustc_codegen_spirv-types/src/target_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,10 @@ impl TargetSpecVersion {
/// format the target spec json
pub fn format_spec(&self, target: &SpirvTarget) -> String {
let target_env = target.env();
let extra = match self {
TargetSpecVersion::Rustc_1_76_0 => r#""os": "unknown","#,
_ => r#""crt-static-respected": true,"#,
};
let target_pointer_width = match self {
TargetSpecVersion::Rustc_1_76_0 | TargetSpecVersion::Rustc_1_85_0 => "\"32\"",
TargetSpecVersion::Rustc_1_93_0 => "32",
let (extra, target_pointer_width) = match self {
TargetSpecVersion::Rustc_1_76_0 => (r#""os": "unknown","#, "\"32\""),
TargetSpecVersion::Rustc_1_85_0 => (r#""crt-static-respected": true,"#, "\"32\""),
TargetSpecVersion::Rustc_1_93_0 => (r#""crt-static-respected": true,"#, "32"),
};
format!(
r#"{{
Expand Down
12 changes: 7 additions & 5 deletions crates/rustc_codegen_spirv/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ use std::{env, fs, mem};
/// `cargo publish`. We need to figure out a way to do this properly, but let's hardcode it for now :/
//const REQUIRED_RUST_TOOLCHAIN: &str = include_str!("../../rust-toolchain.toml");
const REQUIRED_RUST_TOOLCHAIN: &str = r#"[toolchain]
channel = "nightly-2025-11-02"
channel = "nightly-2026-03-06"
components = ["rust-src", "rustc-dev", "llvm-tools"]
# commit_hash = bd3ac0330018c23b111bbee176f32c377be7b319"#;
# commit_hash = 69370dc4a8862b8401615a2a7b950704ba66c495"#;

fn rustc_output(arg: &str) -> Result<String, Box<dyn Error>> {
let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".into());
Expand Down Expand Up @@ -135,6 +135,10 @@ fn generate_pqp_cg_ssa() -> Result<(), Box<dyn Error>> {
}

let in_path = entry.path();

if in_path.ends_with(".DS_Store") {
continue;
}
let out_path = out_dir.join(entry.file_name());

let mut src = fs::read_to_string(in_path)?;
Expand Down Expand Up @@ -318,16 +322,14 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {",
let pqp_cg_ssa_top_level = all_extern_crates
+ r#"

// HACK(eddyb) reexporting macro output for further macro use (can't patch macro).
use maybe_pqp_cg_ssa::fluent_generated;

#[allow(unused, clippy::all, clippy::pedantic, clippy::restriction)]
#[path = "pqp_cg_ssa/src/lib.rs"]
mod maybe_pqp_cg_ssa;
"#;
fs::write(out_dir.join("pqp_cg_ssa.rs"), pqp_cg_ssa_top_level)?;

println!("cargo::rustc-check-cfg=cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)");
println!("cargo::rustc-check-cfg=cfg(bootstrap)");

// HACK(eddyb) `if cfg!(llvm_enzyme)` added upstream for autodiff support.
println!("cargo::rustc-check-cfg=cfg(llvm_enzyme)");
Expand Down
105 changes: 72 additions & 33 deletions crates/rustc_codegen_spirv/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ use rustc_abi::{
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::ErrorGuaranteed;
use rustc_index::Idx;
use rustc_middle::query::Providers;
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
use rustc_middle::ty::{
self, Const, CoroutineArgs, CoroutineArgsExt as _, FloatTy, IntTy, PolyFnSig, Ty, TyCtxt,
TyKind, UintTy,
TyKind, UintTy, ValTreeKindExt,
};
use rustc_middle::ty::{GenericArgsRef, ScalarInt};
use rustc_middle::util::Providers;
use rustc_middle::{bug, span_bug};
use rustc_session::config::OptLevel;
use rustc_span::DUMMY_SP;
use rustc_span::def_id::DefId;
use rustc_span::{Span, Symbol};
Expand All @@ -29,6 +30,19 @@ use std::cell::RefCell;
use std::collections::hash_map::Entry;
use std::fmt;

fn rewrite_c_abi_to_rust<'tcx>(
fn_sig: ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>>,
) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> {
fn_sig.map_bound(|outer| {
outer.map_bound(|mut inner| {
if let Abi::C { .. } = inner.abi {
inner.abi = Abi::Rust;
}
inner
})
})
}

pub(crate) fn provide(providers: &mut Providers) {
// This is a lil weird: so, we obviously don't support C ABIs at all. However, libcore does declare some extern
// C functions:
Expand All @@ -38,19 +52,25 @@ pub(crate) fn provide(providers: &mut Providers) {
// This theoretically then should be fine to leave as C, but, there's no backend hook for
// `FnAbi::adjust_for_cabi`, causing it to panic:
// https://github.com/rust-lang/rust/blob/5fae56971d8487088c0099c82c0a5ce1638b5f62/compiler/rustc_target/src/abi/call/mod.rs#L603
// So, treat any `extern "C"` functions as `extern "unadjusted"`, to be able to compile libcore with arch=spirv.
providers.fn_sig = |tcx, def_id| {
// So, treat any `extern "C"` functions as `extern "Rust"`, to be able to
// compile libcore with arch=spirv.
//
// NOTE: this used to rewrite to `extern "unadjusted"`, but rustc now
// validates `#[rustc_pass_indirectly_in_non_rustic_abis]` for non-Rust ABIs,
// and `Unadjusted` does not satisfy that requirement.
providers.queries.fn_sig = |tcx, def_id| {
// 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
// capture variables. Fortunately, the defaults are exposed (thanks rustdoc), so use that instead.
let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS.fn_sig)(tcx, def_id);
result.map_bound(|outer| {
outer.map_bound(|mut inner| {
if let Abi::C { .. } = inner.abi {
inner.abi = Abi::Unadjusted;
}
inner
})
})
let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS.queries.fn_sig)(tcx, def_id);
rewrite_c_abi_to_rust(result)
};
providers.extern_queries.fn_sig = |tcx, def_id| {
// 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
// capture variables. Fortunately, the defaults are exposed (thanks rustdoc), so use that instead.
let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS
.extern_queries
.fn_sig)(tcx, def_id);
rewrite_c_abi_to_rust(result)
};

// For the Rust ABI, `FnAbi` adjustments are backend-agnostic, but they will
Expand All @@ -62,7 +82,7 @@ pub(crate) fn provide(providers: &mut Providers) {
fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
) -> &'tcx FnAbi<'tcx, Ty<'tcx>> {
let readjust_arg_abi = |arg: &ArgAbi<'tcx, Ty<'tcx>>| {
let mut arg = ArgAbi::new(&tcx, arg.layout, |_, _, _| ArgAttributes::new());
let mut arg = ArgAbi::new(&tcx, arg.layout, |_, _| ArgAttributes::new());
// FIXME: this is bad! https://github.com/rust-lang/rust/issues/115666
// <https://github.com/rust-lang/rust/commit/eaaa03faf77b157907894a4207d8378ecaec7b45>
arg.make_direct_deprecated();
Expand All @@ -81,6 +101,12 @@ pub(crate) fn provide(providers: &mut Providers) {
arg.mode = PassMode::Ignore;
}

// SPIR-V backend lowers arguments by-value and cannot handle
// backend-specific indirection/casts at this layer.
if matches!(arg.mode, PassMode::Cast { .. } | PassMode::Indirect { .. }) {
arg.mode = PassMode::Direct(ArgAttributes::new());
}

arg
};
tcx.arena.alloc(FnAbi {
Expand All @@ -96,12 +122,30 @@ pub(crate) fn provide(providers: &mut Providers) {
can_unwind: fn_abi.can_unwind,
})
}
providers.fn_abi_of_fn_ptr = |tcx, key| {
let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS.fn_abi_of_fn_ptr)(tcx, key);
providers.queries.fn_abi_of_fn_ptr = |tcx, key| {
let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS
.queries
.fn_abi_of_fn_ptr)(tcx, key);
Ok(readjust_fn_abi(tcx, result?))
};
providers.fn_abi_of_instance = |tcx, key| {
let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS.fn_abi_of_instance)(tcx, key);
providers.queries.fn_abi_of_instance_no_deduced_attrs = |tcx, key| {
let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS
.queries
.fn_abi_of_instance_no_deduced_attrs)(tcx, key);
// Keep this query in its original shape while `fn_abi_of_instance_raw`
// is being computed: rustc validates strict invariants there.
// Otherwise, if `fn_abi_of_instance` would route through this query
// directly (e.g. incremental or opt-level=0), apply SPIR-V readjustment.
if tcx.sess.opts.optimize != OptLevel::No && tcx.sess.opts.incremental.is_none() {
result
} else {
Ok(readjust_fn_abi(tcx, result?))
}
};
providers.queries.fn_abi_of_instance_raw = |tcx, key| {
let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS
.queries
.fn_abi_of_instance_raw)(tcx, key);
Ok(readjust_fn_abi(tcx, result?))
};

Expand All @@ -111,7 +155,7 @@ pub(crate) fn provide(providers: &mut Providers) {
//
// FIXME(eddyb) same as the FIXME comment on `check_well_formed`:
// need to migrate away from `#[repr(simd)]` ASAP.
providers.check_mono_item = |_, _| {};
providers.queries.check_mono_item = |_, _| {};
}

/// If a struct contains a pointer to itself, even indirectly, then doing a naiive recursive walk
Expand Down Expand Up @@ -286,6 +330,7 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> {
span = cx.tcx.def_span(adt.did());
}

#[allow(deprecated)]
let attrs = AggregatedSpirvAttributes::parse(cx, cx.tcx.get_all_attrs(adt.did()));

if let Some(intrinsic_type_attr) = attrs.intrinsic_type.map(|attr| attr.value)
Expand Down Expand Up @@ -390,6 +435,10 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> {
}
.def(span, cx)
}
BackendRepr::ScalableVector { .. } => cx
.tcx
.dcx()
.fatal("scalable vectors are not supported in SPIR-V backend"),
BackendRepr::Memory { sized: _ } => trans_aggregate(cx, span, *self),
}
}
Expand Down Expand Up @@ -609,22 +658,11 @@ fn trans_aggregate<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx>
.def(span, cx)
}
}
FieldsShape::Arbitrary {
offsets: _,
memory_index: _,
} => trans_struct_or_union(cx, span, ty, None),
FieldsShape::Arbitrary { .. } => trans_struct_or_union(cx, span, ty, None),
}
}

#[cfg_attr(
not(rustc_codegen_spirv_disable_pqp_cg_ssa),
expect(
unused,
reason = "actually used from \
`<rustc_codegen_ssa::traits::ConstCodegenMethods for CodegenCx<'_>>::const_struct`, \
but `rustc_codegen_ssa` being `pqp_cg_ssa` makes that trait unexported"
)
)]
#[cfg_attr(not(rustc_codegen_spirv_disable_pqp_cg_ssa), allow(unused))]
// returns (field_offsets, size, align)
pub fn auto_struct_layout(
cx: &CodegenCx<'_>,
Expand Down Expand Up @@ -861,7 +899,8 @@ fn trans_intrinsic_type<'tcx>(
} = const_.to_value();
assert!(const_ty.is_integral());
const_val
.try_to_scalar_int()
.try_to_scalar()
.and_then(|scalar| scalar.try_to_scalar_int().ok())
.and_then(P::from_scalar_int)
.ok_or_else(|| {
cx.tcx
Expand Down
12 changes: 7 additions & 5 deletions crates/rustc_codegen_spirv/src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,9 @@ pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers {
check_mod_attrs: |tcx, module_def_id| {
// Run both the default checks, and our `#[spirv(...)]` ones.
(rustc_interface::DEFAULT_QUERY_PROVIDERS.check_mod_attrs)(tcx, module_def_id);
(rustc_interface::DEFAULT_QUERY_PROVIDERS
.queries
.check_mod_attrs)(tcx, module_def_id);
check_mod_attrs(tcx, module_def_id);
},
..*providers
Expand All @@ -537,10 +539,10 @@ fn parse_attrs_for_checking<'a>(
Attribute::Unparsed(item) => {
// #[...]
let s = &item.path.segments;
if let Some(rust_gpu) = s.get(0) && rust_gpu.name == sym.rust_gpu {
if let Some(rust_gpu) = s.get(0) && *rust_gpu == sym.rust_gpu {
// #[rust_gpu ...]
match s.get(1) {
Some(command) if command.name == sym.spirv_attr_with_version => {
Some(command) if *command == sym.spirv_attr_with_version => {
// #[rust_gpu::spirv ...]
if let Some(args) = attr.meta_item_list() {
// #[rust_gpu::spirv(...)]
Expand All @@ -554,11 +556,11 @@ fn parse_attrs_for_checking<'a>(
))
}
}
Some(command) if command.name == sym.vector => {
Some(command) if *command == sym.vector => {
// #[rust_gpu::vector ...]
match s.get(2) {
// #[rust_gpu::vector::v1]
Some(version) if version.name == sym.v1 => {
Some(version) if *version == sym.v1 => {
Ok(SmallVec::from_iter([
Ok((attr.span(), SpirvAttribute::IntrinsicType(IntrinsicType::Vector)))
]))
Expand Down
Loading
Loading