Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
081ccfa
scalar pair: remove abi patching scalar pairs to scalars, fixup fmt a…
LegNeato Sep 8, 2025
54f6cfa
scalar pair: cleanup entry scalar pair handling
Firestar99 Aug 11, 2026
74c893e
update to nightly-2026-06-09, needs scalar pair support or patching c…
Firestar99 Jun 9, 2026
795557f
update to nightly-2026-06-12
Firestar99 Jun 25, 2026
8f2fc79
update to nightly-2026-06-13, compiletests break
Firestar99 Jun 25, 2026
686f4da
patch out codegen_ssa debuginfo generation causing compile failures
Firestar99 Jun 26, 2026
6157213
update to nightly-2026-06-25
Firestar99 Jun 25, 2026
6d7a10f
update to nightly-2026-07-03, rustc 1.98.0
Firestar99 Jul 16, 2026
5cc5458
fix clippy
Firestar99 Jul 16, 2026
7590d13
update to nightly-2026-07-16, failing compiletests
Firestar99 Jul 16, 2026
ff8de5a
failing compiletests, rustc seems to change types?
Firestar99 Jul 16, 2026
7bb3c7c
ignore cg_ssa attributes only required for bootstrap feature
Firestar99 Jul 16, 2026
f0630fe
update to nightly-2026-07-18
Firestar99 Aug 6, 2026
5e4decb
update to nightly-2026-07-19, requires full scalar pair support
Firestar99 Aug 6, 2026
72befe9
update to nightly-2026-07-30
Firestar99 Aug 10, 2026
2e5213a
update to nightly-2026-08-06, requires build-dir-new-layout support
Firestar99 Aug 6, 2026
b76f137
fix example-runner-wgpu on android and wasm
Firestar99 Aug 11, 2026
5400044
fixup compiletests emitting invalid spv
Firestar99 Sep 13, 2026
9aa55c1
fixup memset_fill_u128
Firestar99 Sep 13, 2026
cdcf434
update to nightly-2026-08-15
Firestar99 Sep 13, 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
1 change: 0 additions & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ rustflags = [
"-Wclippy::flat_map_option",
"-Wclippy::float_cmp_const",
"-Wclippy::fn_params_excessive_bools",
"-Wclippy::from_iter_instead_of_collect",
"-Wclippy::if_let_mutex",
"-Wclippy::implicit_clone",
"-Wclippy::imprecise_flops",
Expand Down
13 changes: 10 additions & 3 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-2026-05-22"
channel = "nightly-2026-08-15"
components = ["rust-src", "rustc-dev", "llvm-tools"]
# commit_hash = e96c36b6f76833388c519561d145492d2c08db4e"#;
# commit_hash = d453bdd8f092d099bc336f0bda4163f809ad18e0"#;

fn rustc_output(arg: &str) -> Result<String, Box<dyn Error>> {
let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".into());
Expand Down Expand Up @@ -153,7 +153,10 @@ fn generate_pqp_cg_ssa() -> Result<(), Box<dyn Error>> {
for line in mem::take(&mut src).lines() {
if line.starts_with("#!") {
src += "// ";
if !line.starts_with("#![doc(") && line != "#![warn(unreachable_pub)]" {
if !line.starts_with("#![doc(")
&& line != "#![warn(unreachable_pub)]"
&& !line.starts_with("#![cfg_attr(bootstrap,")
{
writeln(&mut cg_ssa_lib_rc_attrs, line);
}
} else if line == "#[macro_use]" || line.starts_with("extern crate ") {
Expand Down Expand Up @@ -256,6 +259,10 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {",
);
}

if relative_path == Path::new("src/mir/mod.rs") {
src = src.replace("fx.fill_function_debug_context(&mut start_bx);", "");
}

fs::write(out_path, src)?;
}
}
Expand Down
40 changes: 23 additions & 17 deletions crates/rustc_codegen_spirv/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,19 @@ 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(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();

// FIXME(eddyb) detect `#[rust_gpu::vector::v1]` more specifically,
// to avoid affecting anything should actually be passed as a pair.
if let PassMode::Pair(..) = arg.mode {
// HACK(eddyb) this avoids breaking e.g. `&[T]` pairs.
if let TyKind::Adt(..) = arg.layout.ty.kind() {
arg.mode = PassMode::Direct(ArgAttributes::new());
}
}
// replaces removed `arg.make_direct_deprecated();`
arg.mode = if let PassMode::Indirect { .. } = arg.mode {
PassMode::Direct(ArgAttributes::new())
} else if arg.layout.is_zst() {
PassMode::Ignore
} else if let PassMode::Ignore | PassMode::Direct(..) | PassMode::Pair(..) = arg.mode {
arg.mode
} else {
panic!("Tried to make {:?} direct", arg.mode)
};

// Avoid pointlessly passing ZSTs, just like the official Rust ABI.
if arg.layout.is_zst() {
Expand Down Expand Up @@ -391,7 +391,7 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> {
}
.def_with_name(cx, span, TyLayoutNameKey::from(*self)),
BackendRepr::Scalar(scalar) => trans_scalar(cx, span, *self, scalar, Size::ZERO),
BackendRepr::ScalarPair(a, b) => {
BackendRepr::ScalarPair { a, b, .. } => {
// NOTE(eddyb) unlike `BackendRepr::Scalar`'s simpler newtype-unpacking
// behavior, `BackendRepr::ScalarPair` can be composed in two ways:
// * two `BackendRepr::Scalar` fields (and any number of ZST fields),
Expand All @@ -414,7 +414,10 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> {
// Note: We can't use auto_struct_layout here because the spirv types here might be undefined due to
// recursive pointer types.
let a_offset = Size::ZERO;
let b_offset = a.primitive().size(cx).align_to(b.primitive().align(cx).abi);
let b_offset = a
.primitive()
.size(cx)
.align_to(b.primitive().default_align(cx).abi);
let a = trans_scalar(cx, span, *self, a, a_offset);
let b = trans_scalar(cx, span, *self, b, b_offset);
let size = if self.is_unsized() {
Expand Down Expand Up @@ -450,7 +453,7 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> {
let elem_spirv = trans_scalar(cx, span, *self, element, Size::ZERO);
SpirvType::Vector {
element: elem_spirv,
count: count as u32,
count: count.as_u32(),
size: self.size,
align: self.align.abi,
}
Expand Down Expand Up @@ -490,8 +493,8 @@ pub fn scalar_pair_element_backend_type<'tcx>(
ty: TyAndLayout<'tcx>,
index: usize,
) -> Word {
let [a, b] = match ty.layout.backend_repr() {
BackendRepr::ScalarPair(a, b) => [a, b],
let [a, b] = match ty.backend_repr {
BackendRepr::ScalarPair { a, b, .. } => [a, b],
other => span_bug!(
span,
"scalar_pair_element_backend_type invalid abi: {:?}",
Expand All @@ -500,7 +503,10 @@ pub fn scalar_pair_element_backend_type<'tcx>(
};
let offset = match index {
0 => Size::ZERO,
1 => a.primitive().size(cx).align_to(b.primitive().align(cx).abi),
1 => a
.primitive()
.size(cx)
.align_to(b.primitive().default_align(cx).abi),
_ => unreachable!(),
};
trans_scalar(cx, span, ty, [a, b][index], offset)
Expand Down
12 changes: 6 additions & 6 deletions crates/rustc_codegen_spirv/src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::symbols::Symbols;
use rspirv::spirv::{BuiltIn, ExecutionMode, ExecutionModel, StorageClass};
use rustc_ast::{LitKind, MetaItemInner, MetaItemLit};
use rustc_hir as hir;
use rustc_hir::def_id::LocalModDefId;
use rustc_hir::def_id::LocalModId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{Attribute, CRATE_HIR_ID, HirId, MethodKind, Target};
use rustc_middle::hir::nested_filter;
Expand Down Expand Up @@ -433,19 +433,19 @@ impl<'tcx> Visitor<'tcx> for CheckSpirvAttrVisitor<'tcx> {
}

fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
let target = Target::from_item(item);
let target = Target::from(item);
self.check_spirv_attributes(item.hir_id(), target);
intravisit::walk_item(self, item);
}

fn visit_generic_param(&mut self, generic_param: &'tcx hir::GenericParam<'tcx>) {
let target = Target::from_generic_param(generic_param);
let target = Target::from(generic_param);
self.check_spirv_attributes(generic_param.hir_id, target);
intravisit::walk_generic_param(self, generic_param);
}

fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
let target = Target::from_trait_item(trait_item);
let target = Target::from(trait_item);
self.check_spirv_attributes(trait_item.hir_id(), target);
intravisit::walk_trait_item(self, trait_item);
}
Expand All @@ -461,7 +461,7 @@ impl<'tcx> Visitor<'tcx> for CheckSpirvAttrVisitor<'tcx> {
}

fn visit_foreign_item(&mut self, f_item: &'tcx hir::ForeignItem<'tcx>) {
let target = Target::from_foreign_item(f_item);
let target = Target::from(f_item);
self.check_spirv_attributes(f_item.hir_id(), target);
intravisit::walk_foreign_item(self, f_item);
}
Expand Down Expand Up @@ -503,7 +503,7 @@ impl<'tcx> Visitor<'tcx> for CheckSpirvAttrVisitor<'tcx> {
}

// FIXME(eddyb) DRY this somehow and make it reusable from somewhere in `rustc`.
fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalModId) {
let check_spirv_attr_visitor = &mut CheckSpirvAttrVisitor {
tcx,
sym: Symbols::get(),
Expand Down
18 changes: 12 additions & 6 deletions crates/rustc_codegen_spirv/src/builder/builder_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ fn memset_fill_u64(b: u8) -> u64 {

fn memset_fill_u128(b: u8) -> u128 {
let b64 = memset_fill_u64(b) as u128;
b64 | b64 >> 64
b64 | b64 << 64
}

fn memset_dynamic_scalar(
Expand Down Expand Up @@ -484,6 +484,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
16 => memset_dynamic_scalar(self, fill_var, 2, false),
32 => memset_dynamic_scalar(self, fill_var, 4, false),
64 => memset_dynamic_scalar(self, fill_var, 8, false),
128 => memset_dynamic_scalar(self, fill_var, 16, false),
_ => self.fatal(format!(
"memset on integer width {width} not implemented yet"
)),
Expand Down Expand Up @@ -1873,7 +1874,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
self.bitcast(loaded_val, ty)
}

fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value) -> Self::Value {
fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value, _align: Align) -> Self::Value {
// TODO: Implement this
let result = self.load(ty, ptr, Align::from_bytes(0).unwrap());
self.zombie(result.def(self), "volatile load is not supported yet");
Expand Down Expand Up @@ -1917,18 +1918,18 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {

let val = if place.val.llextra.is_some() {
OperandValue::Ref(place.val)
} else if self.cx.is_backend_immediate(place.layout) {
} else if place.layout.backend_repr.is_scalar_or_simd() {
let llval = self.load(
place.layout.spirv_type(self.span(), self),
place.val.llval,
place.val.align,
);
OperandValue::Immediate(llval)
} else if let BackendRepr::ScalarPair(a, b) = place.layout.backend_repr {
} else if let BackendRepr::ScalarPair { a, b, .. } = place.layout.backend_repr {
let b_offset = a
.primitive()
.size(self)
.align_to(b.primitive().align(self).abi);
.align_to(b.primitive().default_align(self).abi);

let mut load = |i, scalar: Scalar, align| {
let llptr = if i == 0 {
Expand Down Expand Up @@ -2012,7 +2013,8 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
align: Align,
flags: MemFlags,
) -> Self::Value {
if flags != MemFlags::empty() {
let allowed_flags = MemFlags::CAPTURES_READ_ONLY;
if !(flags & !allowed_flags).is_empty() {
self.err(format!("store_with_flags is not supported yet: {flags:?}"));
}
self.store(val, ptr, align)
Expand Down Expand Up @@ -3503,4 +3505,8 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
fn alloca_with_ty(&mut self, _layout: TyAndLayout<'tcx>) -> Self::Value {
bug!("scalable alloca is not supported in SPIR-V backend")
}

fn vscale(&mut self, _ty: Self::Type) -> Self::Value {
self.fatal("scalable vectors not supported");
}
}
49 changes: 37 additions & 12 deletions crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,35 +557,60 @@ impl<'tcx> DecodedFormatArgs<'tcx> {
if let Some((template_id, template_ty_id, rt_args_ptr_id, rt_args_ptr_ty_id)) =
split_fmt_args
{
let ctor = if let (Some(template_len), Some(rt_args_count)) = (
if let (Some(template_len), Some(rt_args_count)) = (
const_ptr_to_composite_len(template_id)
.or_else(|| array_len_from_ptr_type(template_ty_id)),
const_ptr_to_composite_len(rt_args_ptr_id)
.or_else(|| array_len_from_ptr_type(rt_args_ptr_ty_id)),
) {
FmtArgsCtor::NewTemplate {
template_len,
rt_args_count,
}
(
FmtArgsCtor::NewTemplate {
template_len,
rt_args_count,
},
SmallVec::<[Word; 8]>::from_slice(&[template_id, rt_args_ptr_id]),
)
} else if let Some(&[Inst::Call(_, callee_id, ref call_args)]) =
try_rev_take(-1).as_deref()
&& call_args.len() == 2
&& [call_args[0], call_args[1]] == [template_id, rt_args_ptr_id]
{
// Consume the matched call instruction.
try_rev_take(1).unwrap();
lookup_fmt_args_ctor(callee_id)?
(
lookup_fmt_args_ctor(callee_id)?,
SmallVec::<[Word; 8]>::from_slice(&[template_id, rt_args_ptr_id]),
)
} else if let Some(
&[
Inst::Call(call_ret_id, callee_id, ref call_args),
Inst::CompositeExtract(extracted0, from0, 0),
Inst::CompositeExtract(extracted1, from1, 1),
],
) = try_rev_take(-3).as_deref()
&& [from0, from1] == [call_ret_id; 2]
&& [extracted0, extracted1] == [template_id, rt_args_ptr_id]
{
// Newer rustc, since `BackendRepr::ScalarPair` args are no
// longer forced to `PassMode::Direct`, returns the whole
// `fmt::Arguments` from its `new_*` constructor as a scalar
// pair, and splits it (via `OpCompositeExtract`s) into the
// two scalar values passed to the panic entry-point.
//
// The constructor's own arguments (i.e. `pieces`/`template`
// and the `rt::Argument` slice pointers) still carry the
// recoverable const data, so use those, like the aggregate
// (non-split) `Call`+`extract`+`insert` case does below.
let call_args_storage = call_args.iter().copied().collect();
// Consume the matched call + both `OpCompositeExtract`s.
try_rev_take(3).unwrap();
(lookup_fmt_args_ctor(callee_id)?, call_args_storage)
} else {
// We failed to recover constructor metadata for an already-split
// `fmt::Arguments` value. Keep panic lowering sound by falling
// back to an unknown panic message, without requiring decompilation.
return Ok(decoded_format_args);
};

(
ctor,
SmallVec::<[Word; 8]>::from_slice(&[template_id, rt_args_ptr_id]),
)
}
} else {
// Newer rustc can pass the `fmt::Arguments::new_*` result directly to
// panic entry points (single trailing call), while older versions go
Expand Down
Loading
Loading