From a731c2d9610b7de98c8c99a78df41f077ee40957 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Thu, 26 Feb 2026 13:31:36 +0100 Subject: [PATCH 01/34] update toolchain to 2025-11-13, fails --- crates/rustc_codegen_spirv/build.rs | 4 ++-- crates/rustc_codegen_spirv/src/builder/builder_methods.rs | 1 + crates/rustc_codegen_spirv/src/builder/mod.rs | 2 +- crates/rustc_codegen_spirv/src/lib.rs | 2 -- rust-toolchain.toml | 4 ++-- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/crates/rustc_codegen_spirv/build.rs b/crates/rustc_codegen_spirv/build.rs index bb6ff18619..ceaa02e462 100644 --- a/crates/rustc_codegen_spirv/build.rs +++ b/crates/rustc_codegen_spirv/build.rs @@ -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-2025-11-13" components = ["rust-src", "rustc-dev", "llvm-tools"] -# commit_hash = bd3ac0330018c23b111bbee176f32c377be7b319"#; +# commit_hash = 01867557cd7dbe256a031a7b8e28d05daecd75ab"#; fn rustc_output(arg: &str) -> Result> { let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".into()); diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index 05157d7f93..b05000bd76 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -1917,6 +1917,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { OperandRef { val, layout: place.layout, + move_annotation: None, } } diff --git a/crates/rustc_codegen_spirv/src/builder/mod.rs b/crates/rustc_codegen_spirv/src/builder/mod.rs index 7135e144c8..19eb997d60 100644 --- a/crates/rustc_codegen_spirv/src/builder/mod.rs +++ b/crates/rustc_codegen_spirv/src/builder/mod.rs @@ -174,7 +174,7 @@ impl<'a, 'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'tcx> { fn add_coverage(&mut self, _instance: Instance<'tcx>, _kind: &CoverageKind) {} } -impl<'a, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'tcx> { +impl<'a, 'tcx> DebugInfoBuilderMethods<'_> for Builder<'a, 'tcx> { fn dbg_var_addr( &mut self, _dbg_var: Self::DIVariable, diff --git a/crates/rustc_codegen_spirv/src/lib.rs b/crates/rustc_codegen_spirv/src/lib.rs index 76f5f5bc71..3523d3a4ac 100644 --- a/crates/rustc_codegen_spirv/src/lib.rs +++ b/crates/rustc_codegen_spirv/src/lib.rs @@ -1,5 +1,4 @@ // HACK(eddyb) start of `rustc_codegen_ssa` crate-level attributes (see `build.rs`). -#![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] @@ -7,7 +6,6 @@ #![feature(file_buffered)] #![feature(if_let_guard)] #![feature(negative_impls)] -#![feature(rustdoc_internals)] #![feature(string_from_utf8_lossy_owned)] #![feature(trait_alias)] #![feature(try_blocks)] diff --git a/rust-toolchain.toml b/rust-toolchain.toml index b27e9b9dec..4270279926 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,7 +1,7 @@ [toolchain] -channel = "nightly-2025-11-02" +channel = "nightly-2025-11-13" components = ["rust-src", "rustc-dev", "llvm-tools"] -# commit_hash = bd3ac0330018c23b111bbee176f32c377be7b319 +# commit_hash = 01867557cd7dbe256a031a7b8e28d05daecd75ab # Whenever changing the nightly channel, update the commit hash above, and # change `REQUIRED_RUST_TOOLCHAIN` in `crates/rustc_codegen_spirv/build.rs` too. From 8aed8dbd685a5e2c50e6f643113bbce57e7b7a99 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Thu, 26 Feb 2026 13:32:30 +0100 Subject: [PATCH 02/34] adjust target declaration, conflicts with target declaration refactor see https://github.com/Rust-GPU/rust-gpu/pull/491 --- crates/rustc_codegen_spirv/src/link.rs | 10 +++++++--- crates/rustc_codegen_spirv/src/target.rs | 9 +++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/link.rs b/crates/rustc_codegen_spirv/src/link.rs index 430cbac59b..205cba0ca6 100644 --- a/crates/rustc_codegen_spirv/src/link.rs +++ b/crates/rustc_codegen_spirv/src/link.rs @@ -25,12 +25,14 @@ use rustc_session::config::{ }; use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; use rustc_span::Symbol; +use spirv_tools::TargetEnv; use std::collections::BTreeMap; use std::ffi::{CString, OsStr}; use std::fs::File; use std::io::{BufWriter, Read}; use std::iter; use std::path::{Path, PathBuf}; +use std::str::FromStr; use std::sync::Arc; pub fn link( @@ -337,7 +339,8 @@ fn do_spirv_opt( opt::{self, Optimizer}, }; - let mut optimizer = opt::create(sess.target.options.env.parse().ok()); + let target_env = TargetEnv::from_str(sess.target.options.env.desc()).ok(); + let mut optimizer = opt::create(target_env); match sess.opts.optimize { OptLevel::No => {} @@ -399,7 +402,8 @@ fn do_spirv_val( ) { use spirv_tools::val::{self, Validator}; - let validator = val::create(sess.target.options.env.parse().ok()); + let target_env = TargetEnv::from_str(sess.target.options.env.desc()).ok(); + let validator = val::create(target_env); if let Err(e) = validator.validate(spv_binary, Some(options)) { let mut err = sess.dcx().struct_err(e.to_string()); @@ -498,7 +502,7 @@ fn add_upstream_native_libraries( fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool { match lib.cfg { Some(ref cfg) => { - eval_config_entry(sess, cfg, CRATE_NODE_ID, None, ShouldEmit::ErrorsAndLints).as_bool() + eval_config_entry(sess, cfg, CRATE_NODE_ID, ShouldEmit::ErrorsAndLints).as_bool() } None => true, } diff --git a/crates/rustc_codegen_spirv/src/target.rs b/crates/rustc_codegen_spirv/src/target.rs index 71390f9b8d..08be3c27e0 100644 --- a/crates/rustc_codegen_spirv/src/target.rs +++ b/crates/rustc_codegen_spirv/src/target.rs @@ -1,5 +1,5 @@ use rspirv::spirv::MemoryModel; -use rustc_target::spec::{Cc, LinkerFlavor, PanicStrategy, Target, TargetOptions}; +use rustc_target::spec::{Arch, Cc, Env, LinkerFlavor, PanicStrategy, Target, TargetOptions}; use spirv_tools::TargetEnv; const ARCH: &str = "spirv"; @@ -61,8 +61,9 @@ impl SpirvTarget { o.emit_debug_gdb_scripts = false; o.linker_flavor = LinkerFlavor::Unix(Cc::No); o.panic_strategy = PanicStrategy::Abort; - o.env = self.env.to_string().into(); - o.vendor = self.vendor.clone().into(); + o.env = Env::Other(self.env.to_string().into()); + // Note(@firestar99): not sure if this does anything + o.is_like_gpu = true; // TODO: Investigate if main_needs_argc_argv is useful (for building exes) o.main_needs_argc_argv = false; o @@ -74,7 +75,7 @@ impl SpirvTarget { metadata: Default::default(), pointer_width: 32, data_layout: "e-m:e-p:32:32:32-i64:64-n8:16:32:64".into(), - arch: ARCH.into(), + arch: Arch::Other(ARCH.into()), options: self.init_target_opts(), } } From b4c3e49431f209c465fd86c5ac6ba10f223b47e9 Mon Sep 17 00:00:00 2001 From: David Palm Date: Fri, 14 Nov 2025 09:13:00 +0100 Subject: [PATCH 03/34] make build.rs handle macOS non-utf8 metadata files --- crates/rustc_codegen_spirv/build.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/rustc_codegen_spirv/build.rs b/crates/rustc_codegen_spirv/build.rs index ceaa02e462..e21c94726d 100644 --- a/crates/rustc_codegen_spirv/build.rs +++ b/crates/rustc_codegen_spirv/build.rs @@ -135,6 +135,10 @@ fn generate_pqp_cg_ssa() -> Result<(), Box> { } 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)?; From 74877eecbdcdd1325a66de37b85ba45016b41f2e Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 13:36:16 -0800 Subject: [PATCH 04/34] 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 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. --- .../src/target_spec.rs | 11 ++- crates/rustc_codegen_spirv/src/abi.rs | 9 ++- .../src/builder/builder_methods.rs | 68 +++++++++++++------ 3 files changed, 58 insertions(+), 30 deletions(-) diff --git a/crates/rustc_codegen_spirv-types/src/target_spec.rs b/crates/rustc_codegen_spirv-types/src/target_spec.rs index 3af35c8a8c..d7faf951e6 100644 --- a/crates/rustc_codegen_spirv-types/src/target_spec.rs +++ b/crates/rustc_codegen_spirv-types/src/target_spec.rs @@ -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#"{{ diff --git a/crates/rustc_codegen_spirv/src/abi.rs b/crates/rustc_codegen_spirv/src/abi.rs index bcfa0d86af..e7870173f1 100644 --- a/crates/rustc_codegen_spirv/src/abi.rs +++ b/crates/rustc_codegen_spirv/src/abi.rs @@ -38,7 +38,12 @@ 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. + // 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.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. @@ -46,7 +51,7 @@ pub(crate) fn provide(providers: &mut Providers) { result.map_bound(|outer| { outer.map_bound(|mut inner| { if let Abi::C { .. } = inner.abi { - inner.abi = Abi::Unadjusted; + inner.abi = Abi::Rust; } inner }) diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index b05000bd76..ccfb290336 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -3274,29 +3274,55 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { // be fixed upstream, so we never see any "function pointer" values being // created just to perform direct calls. let (callee_val, result_type, argument_types) = match self.lookup_type(callee.ty) { - SpirvType::Pointer { pointee } => match self.lookup_type(pointee) { - SpirvType::Function { - return_type, - arguments, - } => ( - if let SpirvValueKind::FnAddr { function } = callee.kind { + SpirvType::Pointer { pointee } => { + let (pointee_is_function, result_type, argument_types) = match self + .lookup_type(pointee) + { + SpirvType::Function { + return_type, + arguments, + } => (true, return_type, arguments), + // Newer rustc can represent direct call targets as `ptr`, + // with the callee signature carried separately. + _ => match self.lookup_type(callee_ty) { + SpirvType::Function { + return_type, + arguments, + } => (false, return_type, arguments), + _ => { + let Some(fn_abi) = fn_abi else { + bug!( + "call expected `fn` pointer to point to function type, got `{}`", + self.debug_type(pointee) + ); + }; + let fn_ty = fn_abi.spirv_type(self.span(), self); + match self.lookup_type(fn_ty) { + SpirvType::Function { + return_type, + arguments, + } => (false, return_type, arguments), + _ => bug!("call expected function ABI to lower to function type"), + } + } + }, + }; + + let callee_val = if let SpirvValueKind::FnAddr { function } = callee.kind { + if pointee_is_function { assert_ty_eq!(self, callee_ty, pointee); - function } - // Truly indirect call. - else { - let fn_ptr_val = callee.def(self); - self.zombie(fn_ptr_val, "indirect calls are not supported in SPIR-V"); - fn_ptr_val - }, - return_type, - arguments, - ), - _ => bug!( - "call expected `fn` pointer to point to function type, got `{}`", - self.debug_type(pointee) - ), - }, + function + } + // Truly indirect call. + else { + let fn_ptr_val = callee.def(self); + self.zombie(fn_ptr_val, "indirect calls are not supported in SPIR-V"); + fn_ptr_val + }; + + (callee_val, result_type, argument_types) + } _ => bug!( "call expected `fn` pointer type, got `{}`", From 5819774e68268cf9ff0eae479d6241fae158ac5a Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 13:36:20 -0800 Subject: [PATCH 05/34] Update compiletest baselines for new nightly diagnostics Refresh expected stderr for debug_printf trait-path wording and unwrap_or line mapping changes. --- .../ui/arch/debug_printf_type_checking.stderr | 24 +++++++++---------- .../ui/lang/core/unwrap_or.stderr | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/compiletests/ui/arch/debug_printf_type_checking.stderr b/tests/compiletests/ui/arch/debug_printf_type_checking.stderr index d28980af39..3e753ed396 100644 --- a/tests/compiletests/ui/arch/debug_printf_type_checking.stderr +++ b/tests/compiletests/ui/arch/debug_printf_type_checking.stderr @@ -114,21 +114,21 @@ LL - debug_printf!("%u", 11.0_f32); LL + debug_printf!("%u", 11u32); | -error[E0277]: the trait bound `{float}: Vector` is not satisfied +error[E0277]: the trait bound `{float}: spirv_std::Vector` is not satisfied --> $DIR/debug_printf_type_checking.rs:23:9 | LL | debug_printf!("%v2f", 11.0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Vector` is not implemented for `{float}` - | - = help: the following other types implement trait `Vector`: - `BVec2` implements `Vector` - `BVec3` implements `Vector` - `BVec4` implements `Vector` - `DVec2` implements `Vector` - `DVec3` implements `Vector` - `DVec4` implements `Vector` - `IVec2` implements `Vector` - `IVec3` implements `Vector` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `spirv_std::Vector` is not implemented for `{float}` + | + = help: the following other types implement trait `spirv_std::Vector`: + `BVec2` implements `spirv_std::Vector` + `BVec3` implements `spirv_std::Vector` + `BVec4` implements `spirv_std::Vector` + `DVec2` implements `spirv_std::Vector` + `DVec3` implements `spirv_std::Vector` + `DVec4` implements `spirv_std::Vector` + `IVec2` implements `spirv_std::Vector` + `IVec3` implements `spirv_std::Vector` and 8 others note: required by a bound in `assert_is_vector` --> $SPIRV_STD_SRC/debug_printf.rs:11:40 diff --git a/tests/compiletests/ui/lang/core/unwrap_or.stderr b/tests/compiletests/ui/lang/core/unwrap_or.stderr index a5bcc86afb..ef3722823c 100644 --- a/tests/compiletests/ui/lang/core/unwrap_or.stderr +++ b/tests/compiletests/ui/lang/core/unwrap_or.stderr @@ -1,8 +1,8 @@ %1 = OpFunction %2 None %3 %4 = OpLabel -OpLine %5 1041 14 +OpLine %5 1042 14 %6 = OpBitcast %7 %8 -OpLine %5 1041 8 +OpLine %5 1042 8 %9 = OpINotEqual %10 %6 %11 OpNoLine OpSelectionMerge %12 None From 3bbb1fd4a07ffa88855806adf94b6824dd640bbe Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 13:50:54 -0800 Subject: [PATCH 06/34] Ignore is-like-gpu in target-spec JSON comparison Normalize target-spec JSON before comparing backend-expected vs provided JSON by dropping the is-like-gpu key, which rustc rejects in external target JSON for non-nvptx/amdgcn targets. --- .../rustc_codegen_spirv/src/codegen_cx/mod.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs index 9d1382b06f..64fc9d4994 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs @@ -116,6 +116,15 @@ impl<'tcx> CodegenCx<'tcx> { // HACK(eddyb) this loads the same `serde_json` used by `rustc_target`. extern crate serde_json; + fn normalize_target_spec_json(mut json: serde_json::Value) -> serde_json::Value { + // rustc currently rejects this key in external target JSON unless + // the target is `nvptx64` or `amdgcn`, even though the in-memory + // target options for SPIR-V can set it. + if let Some(obj) = json.as_object_mut() { + obj.remove("is-like-gpu"); + } + json + } let expected = &target.rustc_target(); let found = &tcx.sess.target; @@ -128,11 +137,13 @@ impl<'tcx> CodegenCx<'tcx> { TargetTuple::TargetTuple(_) => { // FIXME(eddyb) this case should be impossible as upstream // `rustc` doesn't support `spirv-*` targets! - (expected != found).then(|| [expected, found].map(|spec| spec.to_json())) + let expected = normalize_target_spec_json(expected.to_json()); + let found = normalize_target_spec_json(found.to_json()); + (expected != found).then_some([expected, found]) } TargetTuple::TargetJson { contents, .. } => { - let expected = expected.to_json(); - let found = serde_json::from_str(contents).unwrap(); + let expected = normalize_target_spec_json(expected.to_json()); + let found = normalize_target_spec_json(serde_json::from_str(contents).unwrap()); (expected != found).then_some([expected, found]) } } From 6e009cce07d0b77c205b7c512319eb50d5a5fd57 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 14:11:39 -0800 Subject: [PATCH 07/34] Fix clippy single_match_else in call callee type handling --- .../src/builder/builder_methods.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index ccfb290336..c6f0fa576b 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -3284,12 +3284,14 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { } => (true, return_type, arguments), // Newer rustc can represent direct call targets as `ptr`, // with the callee signature carried separately. - _ => match self.lookup_type(callee_ty) { - SpirvType::Function { + _ => { + if let SpirvType::Function { return_type, arguments, - } => (false, return_type, arguments), - _ => { + } = self.lookup_type(callee_ty) + { + (false, return_type, arguments) + } else { let Some(fn_abi) = fn_abi else { bug!( "call expected `fn` pointer to point to function type, got `{}`", @@ -3305,7 +3307,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { _ => bug!("call expected function ABI to lower to function type"), } } - }, + } }; let callee_val = if let SpirvValueKind::FnAddr { function } = callee.kind { From 10389c9831ca1f138f1d7dcb6f48bda956c3e501 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 14:08:55 -0800 Subject: [PATCH 08/34] Update pinned toolchain to nightly-2026-03-06 --- crates/rustc_codegen_spirv/build.rs | 4 ++-- rust-toolchain.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/rustc_codegen_spirv/build.rs b/crates/rustc_codegen_spirv/build.rs index e21c94726d..8d5527258f 100644 --- a/crates/rustc_codegen_spirv/build.rs +++ b/crates/rustc_codegen_spirv/build.rs @@ -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-13" +channel = "nightly-2026-03-06" components = ["rust-src", "rustc-dev", "llvm-tools"] -# commit_hash = 01867557cd7dbe256a031a7b8e28d05daecd75ab"#; +# commit_hash = 69370dc4a8862b8401615a2a7b950704ba66c495"#; fn rustc_output(arg: &str) -> Result> { let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".into()); diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 4270279926..396b585eae 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,7 +1,7 @@ [toolchain] -channel = "nightly-2025-11-13" +channel = "nightly-2026-03-06" components = ["rust-src", "rustc-dev", "llvm-tools"] -# commit_hash = 01867557cd7dbe256a031a7b8e28d05daecd75ab +# commit_hash = 69370dc4a8862b8401615a2a7b950704ba66c495 # Whenever changing the nightly channel, update the commit hash above, and # change `REQUIRED_RUST_TOOLCHAIN` in `crates/rustc_codegen_spirv/build.rs` too. From 7db643c33efbdf46260ea0d17fe598ea059cb832 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 14:18:35 -0800 Subject: [PATCH 09/34] Port backend trait surface to rustc 1.96 APIs --- crates/rustc_codegen_spirv/build.rs | 3 - .../src/builder/builder_methods.rs | 9 ++ .../src/builder/intrinsics.rs | 13 +- crates/rustc_codegen_spirv/src/builder/mod.rs | 2 +- .../rustc_codegen_spirv/src/builder_spirv.rs | 11 +- .../src/codegen_cx/constant.rs | 50 +++---- .../src/codegen_cx/declare.rs | 5 +- .../src/codegen_cx/entry.rs | 2 +- .../rustc_codegen_spirv/src/codegen_cx/mod.rs | 4 +- .../src/codegen_cx/type_.rs | 4 +- crates/rustc_codegen_spirv/src/lib.rs | 139 ++++++++---------- crates/rustc_codegen_spirv/src/link.rs | 69 ++++----- 12 files changed, 147 insertions(+), 164 deletions(-) diff --git a/crates/rustc_codegen_spirv/build.rs b/crates/rustc_codegen_spirv/build.rs index 8d5527258f..e7edd32e9c 100644 --- a/crates/rustc_codegen_spirv/build.rs +++ b/crates/rustc_codegen_spirv/build.rs @@ -322,9 +322,6 @@ 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; diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index c6f0fa576b..5959a6bdbf 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -1825,6 +1825,11 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { self.declare_func_local_var(self.type_array(self.type_i8(), size.bytes()), align) } + fn scalable_alloca(&mut self, elt: u64, align: Align, element_ty: Ty<'_>) -> Self::Value { + let element = self.layout_of(element_ty).spirv_type(self.span(), self); + self.declare_func_local_var(self.type_array(element, elt), align) + } + fn load(&mut self, ty: Self::Type, ptr: Self::Value, _align: Align) -> Self::Value { let (ptr, access_ty) = self.adjust_pointer_for_typed_access(ptr, ty); let loaded_val = ptr.const_fold_load(self).unwrap_or_else(|| { @@ -3077,6 +3082,10 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { todo!() } + fn get_funclet_cleanuppad(&self, _funclet: &Self::Funclet) -> Self::Value { + bug!("Funclets are not supported") + } + fn atomic_cmpxchg( &mut self, dst: Self::Value, diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index 85239e0e80..247257da94 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -83,7 +83,7 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { let ret_ty = self.layout_of(sig.output()).spirv_type(self.span(), self); let value = match name { - sym::likely | sym::unlikely => { + _ if name == sym::unlikely || name.as_str() == "likely" => { // Ignore these for now. args[0].immediate() } @@ -369,6 +369,15 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { Ok(()) } + fn codegen_llvm_intrinsic_call( + &mut self, + instance: ty::Instance<'tcx>, + _args: &[OperandRef<'tcx, Self::Value>], + _is_cleanup: bool, + ) -> Self::Value { + bug!("LLVM intrinsic call not supported in SPIR-V backend: {instance:?}") + } + fn abort(&mut self) { self.abort_with_kind_and_message_debug_printf("abort", "intrinsics::abort() called", []); } @@ -386,7 +395,7 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { &mut self, _llvtable: Self::Value, _vtable_byte_offset: u64, - _typeid: Self::Metadata, + _typeid: &[u8], ) -> Self::Value { todo!() } diff --git a/crates/rustc_codegen_spirv/src/builder/mod.rs b/crates/rustc_codegen_spirv/src/builder/mod.rs index 19eb997d60..ba4af829a9 100644 --- a/crates/rustc_codegen_spirv/src/builder/mod.rs +++ b/crates/rustc_codegen_spirv/src/builder/mod.rs @@ -291,11 +291,11 @@ impl<'a, 'tcx> StaticBuilderMethods for Builder<'a, 'tcx> { impl<'a, 'tcx> BackendTypes for Builder<'a, 'tcx> { type Value = as BackendTypes>::Value; - type Metadata = as BackendTypes>::Metadata; type Function = as BackendTypes>::Function; type BasicBlock = as BackendTypes>::BasicBlock; type Type = as BackendTypes>::Type; + type FunctionSignature = as BackendTypes>::FunctionSignature; type Funclet = as BackendTypes>::Funclet; type DIScope = as BackendTypes>::DIScope; diff --git a/crates/rustc_codegen_spirv/src/builder_spirv.rs b/crates/rustc_codegen_spirv/src/builder_spirv.rs index ba8e01fd44..7d93b65f8d 100644 --- a/crates/rustc_codegen_spirv/src/builder_spirv.rs +++ b/crates/rustc_codegen_spirv/src/builder_spirv.rs @@ -15,14 +15,14 @@ use rspirv::{binary::Assemble, binary::Disassemble}; use rustc_abi::Size; use rustc_arena::DroplessArena; use rustc_codegen_ssa::traits::ConstCodegenMethods as _; +use rustc_data_structures::assert_matches; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::bug; use rustc_middle::mir::interpret::ConstAllocation; use rustc_middle::ty::TyCtxt; use rustc_span::source_map::SourceMap; use rustc_span::symbol::Symbol; -use rustc_span::{DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Span}; -use std::assert_matches::assert_matches; +use rustc_span::{DUMMY_SP, SourceFile, Span}; use std::cell::{RefCell, RefMut}; use std::hash::{Hash, Hasher}; use std::iter; @@ -883,12 +883,7 @@ impl<'tcx> BuilderSpirv<'tcx> { // `RealFileName::to_string_lossy` returning `Cow<'_, str>`, // but sadly that `'_` is the lifetime of the temporary `Arc`, // not `'tcx`, so we have to arena-allocate to get `&'tcx str`. - let file_name = match &sf.name { - FileName::Real(name) => { - name.to_string_lossy(FileNameDisplayPreference::Remapped) - } - _ => sf.name.prefer_remapped_unconditionally().to_string().into(), - }; + let file_name = sf.name.prefer_remapped_unconditionally().to_string_lossy(); let file_name = { // FIXME(eddyb) it should be possible to arena-allocate a // `&str` directly, but it would require upstream changes, diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs index f4e73354d6..4a1c19556e 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs @@ -250,19 +250,14 @@ impl ConstCodegenMethods for CodegenCx<'_> { let alloc_id = prov.alloc_id(); let (base_addr, _base_addr_space) = match self.tcx.global_alloc(alloc_id) { GlobalAlloc::Memory(alloc) => { - let pointee = match self.lookup_type(ty) { + let _pointee = match self.lookup_type(ty) { SpirvType::Pointer { pointee } => pointee, other => self.tcx.dcx().fatal(format!( "GlobalAlloc::Memory type not implemented: {}", other.debug(ty, self) )), }; - // FIXME(eddyb) always use `const_data_from_alloc`, and - // defer the actual `try_read_from_const_alloc` step. - let init = self - .try_read_from_const_alloc(alloc, pointee) - .unwrap_or_else(|| self.const_data_from_alloc(alloc)); - let value = self.static_addr_of(init, alloc.inner().align, None); + let value = self.static_addr_of(alloc, None); (value, AddressSpace::ZERO) } GlobalAlloc::Function { instance } => ( @@ -279,19 +274,14 @@ impl ConstCodegenMethods for CodegenCx<'_> { }), ))) .unwrap_memory(); - let pointee = match self.lookup_type(ty) { + let _pointee = match self.lookup_type(ty) { SpirvType::Pointer { pointee } => pointee, other => self.tcx.dcx().fatal(format!( "GlobalAlloc::VTable type not implemented: {}", other.debug(ty, self) )), }; - // FIXME(eddyb) always use `const_data_from_alloc`, and - // defer the actual `try_read_from_const_alloc` step. - let init = self - .try_read_from_const_alloc(alloc, pointee) - .unwrap_or_else(|| self.const_data_from_alloc(alloc)); - let value = self.static_addr_of(init, alloc.inner().align, None); + let value = self.static_addr_of(alloc, None); (value, AddressSpace::ZERO) } GlobalAlloc::Static(def_id) => { @@ -317,20 +307,6 @@ impl ConstCodegenMethods for CodegenCx<'_> { } } - // HACK(eddyb) this uses a symbolic `ConstDataFromAlloc`, to allow deferring - // the actual value generation until after a pointer to this value is cast - // to its final type (e.g. that will be loaded as). - // FIXME(eddyb) replace this with `qptr` handling of constant data. - fn const_data_from_alloc(&self, alloc: ConstAllocation<'_>) -> Self::Value { - // HACK(eddyb) the `ConstCodegenMethods` trait no longer guarantees the - // lifetime that `alloc` is interned for, but since it *is* interned, - // we can cheaply recover it (see also the `ty::Lift` infrastructure). - let alloc = self.tcx.lift(alloc).unwrap(); - - let void_type = SpirvType::Void.def(DUMMY_SP, self); - self.def_constant(void_type, SpirvConst::ConstDataFromAlloc(alloc)) - } - fn const_ptr_byte_offset(&self, val: Self::Value, offset: Size) -> Self::Value { if offset == Size::ZERO { val @@ -345,6 +321,20 @@ impl ConstCodegenMethods for CodegenCx<'_> { } impl<'tcx> CodegenCx<'tcx> { + // HACK(eddyb) this uses a symbolic `ConstDataFromAlloc`, to allow deferring + // the actual value generation until after a pointer to this value is cast + // to its final type (e.g. that will be loaded as). + // FIXME(eddyb) replace this with `qptr` handling of constant data. + pub(crate) fn const_data_from_alloc(&self, alloc: ConstAllocation<'_>) -> SpirvValue { + // HACK(eddyb) the `ConstCodegenMethods` trait no longer guarantees the + // lifetime that `alloc` is interned for, but since it *is* interned, + // we can cheaply recover it (see also the `ty::Lift` infrastructure). + let alloc = self.tcx.lift(alloc).unwrap(); + + let void_type = SpirvType::Void.def(DUMMY_SP, self); + self.def_constant(void_type, SpirvConst::ConstDataFromAlloc(alloc)) + } + pub fn const_bitcast(&self, val: SpirvValue, ty: Word) -> SpirvValue { // HACK(eddyb) special-case `const_data_from_alloc` + `static_addr_of` // as the old `from_const_alloc` (now `OperandRef::from_const_alloc`). @@ -353,9 +343,9 @@ impl<'tcx> CodegenCx<'tcx> { && let Some(SpirvConst::ConstDataFromAlloc(alloc)) = self.builder.lookup_const_by_id(pointee) && let SpirvType::Pointer { pointee } = self.lookup_type(ty) - && let Some(init) = self.try_read_from_const_alloc(alloc, pointee) + && self.try_read_from_const_alloc(alloc, pointee).is_some() { - return self.static_addr_of(init, alloc.inner().align, None); + return self.static_addr_of(alloc, None); } if val.ty == ty { diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs index 71eeb5085a..ea4eb006cc 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs @@ -9,11 +9,11 @@ use crate::custom_decorations::{CustomDecoration, SrcLocDecoration}; use crate::spirv_type::SpirvType; use itertools::Itertools; use rspirv::spirv::{FunctionControl, LinkageType, StorageClass, Word}; -use rustc_abi::Align; use rustc_codegen_ssa::traits::{PreDefineCodegenMethods, StaticCodegenMethods}; use rustc_hir::attrs::{InlineAttr, Linkage}; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; +use rustc_middle::mir::interpret::ConstAllocation; use rustc_middle::mir::mono::{MonoItem, Visibility}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt, TypingEnv}; @@ -368,7 +368,8 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'tcx> { } impl<'tcx> StaticCodegenMethods for CodegenCx<'tcx> { - fn static_addr_of(&self, cv: Self::Value, _align: Align, _kind: Option<&str>) -> Self::Value { + fn static_addr_of(&self, alloc: ConstAllocation<'_>, _kind: Option<&str>) -> Self::Value { + let cv = self.const_data_from_alloc(alloc); self.def_constant( self.type_ptr_to(cv.ty), SpirvConst::PtrTo { diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs index 0b78839bc5..e6f764bb4c 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs @@ -13,6 +13,7 @@ use rspirv::spirv::{ }; use rustc_abi::FieldsShape; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, MiscCodegenMethods as _}; +use rustc_data_structures::assert_matches; use rustc_data_structures::fx::FxHashMap; use rustc_errors::MultiSpan; use rustc_hir as hir; @@ -21,7 +22,6 @@ use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{DUMMY_SP, Span}; use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; -use std::assert_matches::assert_matches; /// Various information about an entry-point parameter, which can only be deduced /// (and/or checked) in all cases by using the original reference/value Rust type diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs index 64fc9d4994..f2f976c6fc 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs @@ -788,11 +788,11 @@ impl FromStr for ModuleOutputType { impl<'tcx> BackendTypes for CodegenCx<'tcx> { type Value = SpirvValue; - type Metadata = (); type Function = SpirvFunctionCursor; type BasicBlock = SpirvBlockCursor; type Type = Word; + type FunctionSignature = Word; // Funclet: A structure representing an active landing pad for the duration of a basic block. (??) // https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/common/struct.Funclet.html // @@ -880,7 +880,7 @@ impl<'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'tcx> { todo!() } - fn declare_c_main(&self, _fn_type: Self::Type) -> Option { + fn declare_c_main(&self, _fn_type: Self::FunctionSignature) -> Option { todo!() } } diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs b/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs index be570c7015..8525596494 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs @@ -76,7 +76,7 @@ impl<'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'tcx> { ) } - fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Type { + fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::FunctionSignature { fn_abi.spirv_type(DUMMY_SP, self) } @@ -171,7 +171,7 @@ impl BaseTypeCodegenMethods for CodegenCx<'_> { .def(DUMMY_SP, self) } - fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type { + fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::FunctionSignature { SpirvType::Function { return_type: ret, arguments: args, diff --git a/crates/rustc_codegen_spirv/src/lib.rs b/crates/rustc_codegen_spirv/src/lib.rs index 3523d3a4ac..cd508bfc74 100644 --- a/crates/rustc_codegen_spirv/src/lib.rs +++ b/crates/rustc_codegen_spirv/src/lib.rs @@ -1,10 +1,10 @@ // HACK(eddyb) start of `rustc_codegen_ssa` crate-level attributes (see `build.rs`). #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![feature(assert_matches)] +#![cfg_attr(bootstrap, feature(assert_matches))] #![feature(box_patterns)] #![feature(file_buffered)] -#![feature(if_let_guard)] +#![cfg_attr(bootstrap, feature(if_let_guard))] #![feature(negative_impls)] #![feature(string_from_utf8_lossy_owned)] #![feature(trait_alias)] @@ -139,19 +139,21 @@ use builder::Builder; use codegen_cx::CodegenCx; use maybe_pqp_cg_ssa::back::lto::{SerializedModule, ThinModule}; use maybe_pqp_cg_ssa::back::write::{ - CodegenContext, FatLtoInput, ModuleConfig, OngoingCodegen, TargetMachineFactoryConfig, + CodegenContext, FatLtoInput, ModuleConfig, OngoingCodegen, SharedEmitter, + TargetMachineFactoryFn, }; use maybe_pqp_cg_ssa::base::maybe_create_entry_wrapper; use maybe_pqp_cg_ssa::mono_item::MonoItemExt; use maybe_pqp_cg_ssa::traits::{ - CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, - WriteBackendMethods, + CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, WriteBackendMethods, +}; +use maybe_pqp_cg_ssa::{ + CompiledModule, CompiledModules, CrateInfo, ModuleCodegen, ModuleKind, TargetConfig, }; -use maybe_pqp_cg_ssa::{CodegenResults, CompiledModule, ModuleCodegen, ModuleKind, TargetConfig}; use rspirv::binary::Assemble; use rustc_ast::expand::allocator::AllocatorMethod; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::DiagCtxtHandle; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::mir::mono::{MonoItem, MonoItemData}; @@ -167,7 +169,7 @@ use std::io::Cursor; use std::io::Write; use std::path::{Path, PathBuf}; use std::sync::Arc; -use tracing::{error, warn}; +use tracing::error; fn dump_mir(tcx: TyCtxt<'_>, mono_items: &[(MonoItem<'_>, MonoItemData)], path: &Path) { fs::create_dir_all(path.parent().unwrap()).unwrap(); @@ -193,10 +195,6 @@ impl CodegenBackend for SpirvCodegenBackend { init_logging(sess); } - fn locale_resource(&self) -> &'static str { - rustc_errors::DEFAULT_LOCALE_RESOURCE - } - fn target_config(&self, sess: &Session) -> TargetConfig { let cmdline = sess.opts.cg.target_feature.split(','); let cfg = sess.target.options.features.split(','); @@ -236,17 +234,16 @@ impl CodegenBackend for SpirvCodegenBackend { crate::attr::provide(providers); } - fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box { - Box::new(maybe_pqp_cg_ssa::base::codegen_crate( - Self, - tcx, - tcx.sess - .opts - .cg - .target_cpu - .clone() - .unwrap_or_else(|| tcx.sess.target.cpu.to_string()), - )) + fn target_cpu(&self, sess: &Session) -> String { + sess.opts + .cg + .target_cpu + .clone() + .unwrap_or_else(|| sess.target.cpu.to_string()) + } + + fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>, crate_info: &CrateInfo) -> Box { + Box::new(maybe_pqp_cg_ssa::base::codegen_crate(Self, tcx, crate_info)) } fn join_codegen( @@ -254,7 +251,7 @@ impl CodegenBackend for SpirvCodegenBackend { ongoing_codegen: Box, sess: &Session, _outputs: &OutputFilenames, - ) -> (CodegenResults, FxIndexMap) { + ) -> (CompiledModules, FxIndexMap) { ongoing_codegen .downcast::>() .expect("Expected OngoingCodegen, found Box") @@ -264,17 +261,19 @@ impl CodegenBackend for SpirvCodegenBackend { fn link( &self, sess: &Session, - codegen_results: CodegenResults, + compiled_modules: CompiledModules, + crate_info: CrateInfo, metadata: EncodedMetadata, outputs: &OutputFilenames, ) { let timer = sess.timer("link_crate"); link::link( sess, - &codegen_results, + &compiled_modules, + &crate_info, &metadata, outputs, - codegen_results.crate_info.local_crate_name.as_str(), + crate_info.local_crate_name.as_str(), ); drop(timer); } @@ -296,15 +295,10 @@ impl ModuleBufferMethods for SpirvModuleBuffer { self.as_bytes() } } -impl ThinBufferMethods for SpirvModuleBuffer { - fn data(&self) -> &[u8] { - self.as_bytes() - } -} impl SpirvCodegenBackend { fn optimize_common( - _cgcx: &CodegenContext, + _cgcx: &CodegenContext, module: &mut ModuleCodegen<::Module>, ) { // Apply DCE ("dead code elimination") to modules before ever serializing @@ -321,61 +315,69 @@ impl SpirvCodegenBackend { impl WriteBackendMethods for SpirvCodegenBackend { type Module = rspirv::dr::Module; type TargetMachine = (); - type TargetMachineError = String; type ModuleBuffer = SpirvModuleBuffer; type ThinData = (); - type ThinBuffer = SpirvModuleBuffer; + + fn target_machine_factory( + &self, + _sess: &Session, + _opt_level: config::OptLevel, + _target_features: &[String], + ) -> TargetMachineFactoryFn { + Arc::new(|_| Ok(())) + } // FIXME(eddyb) reuse the "merge" stage of `crate::linker` for this, or even // consider setting `requires_lto = true` in the target specs and moving the // entirety of `crate::linker` into this stage (lacking diagnostics may be // an issue - it's surprising `CodegenBackend::link` has `Session` at all). - fn run_and_optimize_fat_lto( - cgcx: &CodegenContext, + fn optimize_and_codegen_fat_lto( + cgcx: &CodegenContext, + _prof: &SelfProfilerRef, + _shared_emitter: &SharedEmitter, + _tm_factory: TargetMachineFactoryFn, _exported_symbols_for_lto: &[String], _each_linked_rlib_for_lto: &[PathBuf], _modules: Vec>, - ) -> ModuleCodegen { + ) -> CompiledModule { assert!( cgcx.lto == rustc_session::config::Lto::Fat, - "`run_and_optimize_fat_lto` (for `WorkItemResult::NeedsFatLto`) should \ + "`optimize_and_codegen_fat_lto` should \ only be invoked due to `-Clto` (or equivalent)" ); unreachable!("Rust-GPU does not support fat LTO") } fn run_thin_lto( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + _prof: &SelfProfilerRef, + _dcx: rustc_errors::DiagCtxtHandle<'_>, // FIXME(bjorn3): Limit LTO exports to these symbols _exported_symbols_for_lto: &[String], _each_linked_rlib_for_lto: &[PathBuf], // njn: ? - modules: Vec<(String, Self::ThinBuffer)>, + modules: Vec<(String, Self::ModuleBuffer)>, cached_modules: Vec<(SerializedModule, WorkProduct)>, ) -> (Vec>, Vec) { link::run_thin(cgcx, modules, cached_modules) } - fn print_pass_timings(&self) { - warn!("TODO: Implement print_pass_timings"); - } - - fn print_statistics(&self) { - warn!("TODO: Implement print_statistics"); - } - fn optimize( - cgcx: &CodegenContext, - _dcx: DiagCtxtHandle<'_>, + cgcx: &CodegenContext, + _prof: &SelfProfilerRef, + _shared_emitter: &SharedEmitter, module: &mut ModuleCodegen, _config: &ModuleConfig, ) { Self::optimize_common(cgcx, module); } - fn optimize_thin( - cgcx: &CodegenContext, + fn optimize_and_codegen_thin( + cgcx: &CodegenContext, + prof: &SelfProfilerRef, + shared_emitter: &SharedEmitter, + _tm_factory: TargetMachineFactoryFn, thin_module: ThinModule, - ) -> ModuleCodegen { + ) -> CompiledModule { // FIXME(eddyb) the inefficiency of Module -> [u8] -> Module roundtrips // comes from upstream and it applies to `rustc_codegen_llvm` as well, // eventually it should be properly addressed (for `ThinLocal` at least). @@ -389,16 +391,19 @@ impl WriteBackendMethods for SpirvCodegenBackend { thin_lto_buffer: None, }; Self::optimize_common(cgcx, &mut module); - module + Self::codegen(cgcx, prof, shared_emitter, module, &cgcx.module_config) } fn codegen( - cgcx: &CodegenContext, + cgcx: &CodegenContext, + _prof: &SelfProfilerRef, + _shared_emitter: &SharedEmitter, module: ModuleCodegen, _config: &ModuleConfig, ) -> CompiledModule { let kind = module.kind; - let (name, module_buffer) = Self::serialize_module(module); + let name = module.name; + let module_buffer = Self::serialize_module(module.module_llvm, false); let path = cgcx.output_filenames.temp_path_for_cgu( OutputType::Object, @@ -419,15 +424,8 @@ impl WriteBackendMethods for SpirvCodegenBackend { } } - fn prepare_thin(module: ModuleCodegen) -> (String, Self::ThinBuffer) { - Self::serialize_module(module) - } - - fn serialize_module(module: ModuleCodegen) -> (String, Self::ModuleBuffer) { - ( - module.name, - SpirvModuleBuffer(module.module_llvm.assemble()), - ) + fn serialize_module(module: Self::Module, _is_thin: bool) -> Self::ModuleBuffer { + SpirvModuleBuffer(module.assemble()) } } @@ -499,15 +497,6 @@ impl ExtraBackendMethods for SpirvCodegenBackend { 0, ) } - - fn target_machine_factory( - &self, - _sess: &Session, - _opt_level: config::OptLevel, - _target_features: &[String], - ) -> Arc Result<(), String> + Send + Sync + 'static> { - Arc::new(|_| Ok(())) - } } struct DumpModuleOnPanic<'a, 'cx, 'tcx> { diff --git a/crates/rustc_codegen_spirv/src/link.rs b/crates/rustc_codegen_spirv/src/link.rs index 205cba0ca6..6f3f081ca9 100644 --- a/crates/rustc_codegen_spirv/src/link.rs +++ b/crates/rustc_codegen_spirv/src/link.rs @@ -11,7 +11,7 @@ use rustc_attr_parsing::{ShouldEmit, eval_config_entry}; use rustc_codegen_spirv_types::{CompileResult, ModuleResult}; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared}; use rustc_codegen_ssa::back::write::CodegenContext; -use rustc_codegen_ssa::{CodegenResults, NativeLib}; +use rustc_codegen_ssa::{CompiledModules, CrateInfo, NativeLib}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Diag; use rustc_hir::attrs::NativeLibKind; @@ -37,7 +37,8 @@ use std::sync::Arc; pub fn link( sess: &Session, - codegen_results: &CodegenResults, + compiled_modules: &CompiledModules, + crate_info: &CrateInfo, metadata: &EncodedMetadata, outputs: &OutputFilenames, crate_name: &str, @@ -59,7 +60,7 @@ pub fn link( ); } - for obj in codegen_results + for obj in compiled_modules .modules .iter() .filter_map(|m| m.object.as_ref()) @@ -79,7 +80,8 @@ pub fn link( CrateType::Rlib => { link_rlib( sess, - codegen_results, + compiled_modules, + crate_info, metadata, &out_filename_file_for_writing, ); @@ -97,7 +99,8 @@ pub fn link( sess, crate_type, &out_filename_file_for_writing, - codegen_results, + compiled_modules, + crate_info, outputs, &disambiguated_crate_name_for_dumps, ); @@ -128,19 +131,20 @@ pub fn link( fn link_rlib( sess: &Session, - codegen_results: &CodegenResults, + compiled_modules: &CompiledModules, + crate_info: &CrateInfo, metadata: &EncodedMetadata, out_filename: &Path, ) { let mut file_list = Vec::<&Path>::new(); - for obj in codegen_results + for obj in compiled_modules .modules .iter() .filter_map(|m| m.object.as_ref()) { file_list.push(obj); } - for lib in codegen_results.crate_info.used_libraries.iter() { + for lib in crate_info.used_libraries.iter() { if let NativeLibKind::Static { bundle: None | Some(true), .. @@ -160,13 +164,14 @@ fn link_exe( sess: &Session, crate_type: CrateType, out_filename: &Path, - codegen_results: &CodegenResults, + compiled_modules: &CompiledModules, + crate_info: &CrateInfo, outputs: &OutputFilenames, disambiguated_crate_name_for_dumps: &OsStr, ) { let mut objects = Vec::new(); let mut rlibs = Vec::new(); - for obj in codegen_results + for obj in compiled_modules .modules .iter() .filter_map(|m| m.object.as_ref()) @@ -174,12 +179,7 @@ fn link_exe( objects.push(obj.clone()); } - link_local_crate_native_libs_and_dependent_crate_libs( - &mut rlibs, - sess, - crate_type, - codegen_results, - ); + link_local_crate_native_libs_and_dependent_crate_libs(&mut rlibs, sess, crate_type, crate_info); let cg_args = CodegenArgs::from_session(sess); @@ -417,20 +417,19 @@ fn link_local_crate_native_libs_and_dependent_crate_libs( rlibs: &mut Vec, sess: &Session, crate_type: CrateType, - codegen_results: &CodegenResults, + crate_info: &CrateInfo, ) { if sess.opts.unstable_opts.link_native_libraries { - add_local_native_libraries(sess, codegen_results); + add_local_native_libraries(sess, crate_info); } - add_upstream_rust_crates(sess, rlibs, codegen_results, crate_type); + add_upstream_rust_crates(sess, rlibs, crate_info, crate_type); if sess.opts.unstable_opts.link_native_libraries { - add_upstream_native_libraries(sess, codegen_results, crate_type); + add_upstream_native_libraries(sess, crate_info, crate_type); } } -fn add_local_native_libraries(sess: &Session, codegen_results: &CodegenResults) { - let relevant_libs = codegen_results - .crate_info +fn add_local_native_libraries(sess: &Session, crate_info: &CrateInfo) { + let relevant_libs = crate_info .used_libraries .iter() .filter(|l| relevant_lib(sess, l)); @@ -440,16 +439,15 @@ fn add_local_native_libraries(sess: &Session, codegen_results: &CodegenResults) fn add_upstream_rust_crates( sess: &Session, rlibs: &mut Vec, - codegen_results: &CodegenResults, + crate_info: &CrateInfo, crate_type: CrateType, ) { - let data = codegen_results - .crate_info + let data = crate_info .dependency_formats .get(&crate_type) .expect("failed to find crate type in dependency format list"); - for &cnum in &codegen_results.crate_info.used_crates { - let src = &codegen_results.crate_info.used_crate_source[&cnum]; + for &cnum in &crate_info.used_crates { + let src = &crate_info.used_crate_source[&cnum]; match data[cnum] { Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => rlibs.push(src.rlib.as_ref().unwrap().0.clone()), @@ -461,19 +459,14 @@ fn add_upstream_rust_crates( } } -fn add_upstream_native_libraries( - sess: &Session, - codegen_results: &CodegenResults, - crate_type: CrateType, -) { - let data = codegen_results - .crate_info +fn add_upstream_native_libraries(sess: &Session, crate_info: &CrateInfo, crate_type: CrateType) { + let data = crate_info .dependency_formats .get(&crate_type) .expect("failed to find crate type in dependency format list"); - for &cnum in &codegen_results.crate_info.used_crates { - for lib in codegen_results.crate_info.native_libraries[&cnum].iter() { + for &cnum in &crate_info.used_crates { + for lib in crate_info.native_libraries[&cnum].iter() { if !relevant_lib(sess, lib) { continue; } @@ -638,7 +631,7 @@ fn do_link( /// As of right now, this is essentially a no-op, just plumbing through all the files. // TODO: WorkProduct impl pub(crate) fn run_thin( - cgcx: &CodegenContext, + cgcx: &CodegenContext, modules: Vec<(String, SpirvModuleBuffer)>, cached_modules: Vec<(SerializedModule, WorkProduct)>, ) -> (Vec>, Vec) { From 24201f6e091bce08d65f9b40e8c539799ef4eca3 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 14:57:21 -0800 Subject: [PATCH 10/34] Port backend internals and ABI plumbing to latest nightly --- crates/rustc_codegen_spirv/build.rs | 1 + crates/rustc_codegen_spirv/src/abi.rs | 89 ++++++++++++------- crates/rustc_codegen_spirv/src/attr.rs | 12 +-- .../src/builder/builder_methods.rs | 4 +- .../src/builder/intrinsics.rs | 11 ++- .../src/codegen_cx/constant.rs | 4 +- .../src/codegen_cx/declare.rs | 25 ++++-- .../src/codegen_cx/type_.rs | 5 +- .../src/custom_decorations.rs | 3 +- crates/rustc_codegen_spirv/src/lib.rs | 6 +- crates/rustc_codegen_spirv/src/link.rs | 11 +-- tests/compiletests/src/main.rs | 1 + 12 files changed, 105 insertions(+), 67 deletions(-) diff --git a/crates/rustc_codegen_spirv/build.rs b/crates/rustc_codegen_spirv/build.rs index e7edd32e9c..d67b24907b 100644 --- a/crates/rustc_codegen_spirv/build.rs +++ b/crates/rustc_codegen_spirv/build.rs @@ -329,6 +329,7 @@ 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)"); diff --git a/crates/rustc_codegen_spirv/src/abi.rs b/crates/rustc_codegen_spirv/src/abi.rs index e7870173f1..c3790ba78d 100644 --- a/crates/rustc_codegen_spirv/src/abi.rs +++ b/crates/rustc_codegen_spirv/src/abi.rs @@ -13,13 +13,13 @@ 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_span::DUMMY_SP; use rustc_span::def_id::DefId; @@ -29,6 +29,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: @@ -44,18 +57,19 @@ pub(crate) fn provide(providers: &mut Providers) { // 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.fn_sig = |tcx, def_id| { + 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::Rust; - } - 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 @@ -67,7 +81,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 // arg.make_direct_deprecated(); @@ -86,6 +100,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 { @@ -101,12 +121,22 @@ 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.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); 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_raw = |tcx, key| { + let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS + .queries + .fn_abi_of_instance_raw)(tcx, key); Ok(readjust_fn_abi(tcx, result?)) }; @@ -116,7 +146,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 @@ -291,6 +321,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) @@ -395,6 +426,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), } } @@ -614,22 +649,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 \ - `>::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<'_>, @@ -866,7 +890,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 diff --git a/crates/rustc_codegen_spirv/src/attr.rs b/crates/rustc_codegen_spirv/src/attr.rs index 3a877241d2..3d3c22d812 100644 --- a/crates/rustc_codegen_spirv/src/attr.rs +++ b/crates/rustc_codegen_spirv/src/attr.rs @@ -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 @@ -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(...)] @@ -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))) ])) diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index 5959a6bdbf..6cd4cfdc30 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -1826,8 +1826,8 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { } fn scalable_alloca(&mut self, elt: u64, align: Align, element_ty: Ty<'_>) -> Self::Value { - let element = self.layout_of(element_ty).spirv_type(self.span(), self); - self.declare_func_local_var(self.type_array(element, elt), align) + let _ = (elt, align, element_ty); + self.fatal("scalable alloca is not supported in SPIR-V backend") } fn load(&mut self, ty: Self::Type, ptr: Self::Value, _align: Align) -> Self::Value { diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index 247257da94..c7460e0699 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -400,12 +400,15 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { todo!() } - fn va_start(&mut self, _val: Self::Value) -> Self::Value { - todo!() + fn va_start(&mut self, val: Self::Value) -> Self::Value { + // SPIR-V backend has no variadic ABI support; keep the placeholder + // operand unchanged so MIR lowering can proceed without crashing. + val } - fn va_end(&mut self, _val: Self::Value) -> Self::Value { - todo!() + fn va_end(&mut self, val: Self::Value) -> Self::Value { + // See `va_start` above. + val } } diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs index 4a1c19556e..49c0d2de11 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs @@ -343,9 +343,9 @@ impl<'tcx> CodegenCx<'tcx> { && let Some(SpirvConst::ConstDataFromAlloc(alloc)) = self.builder.lookup_const_by_id(pointee) && let SpirvType::Pointer { pointee } = self.lookup_type(ty) - && self.try_read_from_const_alloc(alloc, pointee).is_some() + && let Some(init) = self.try_read_from_const_alloc(alloc, pointee) { - return self.static_addr_of(alloc, None); + return self.static_addr_of_constant(init); } if val.ty == ty { diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs index ea4eb006cc..a06d4d3328 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs @@ -39,6 +39,15 @@ fn attrs_to_spirv(attrs: &CodegenFnAttrs) -> FunctionControl { } impl<'tcx> CodegenCx<'tcx> { + pub(crate) fn static_addr_of_constant(&self, cv: SpirvValue) -> SpirvValue { + self.def_constant( + self.type_ptr_to(cv.ty), + SpirvConst::PtrTo { + pointee: cv.def_cx(self), + }, + ) + } + /// Returns a function if it already exists, or declares a header if it doesn't. pub fn get_fn_ext(&self, instance: Instance<'tcx>) -> SpirvFunctionCursor { assert!(!instance.args.has_infer()); @@ -133,6 +142,7 @@ impl<'tcx> CodegenCx<'tcx> { self.set_linkage(fn_id, symbol_name.to_owned(), linkage); } + #[allow(deprecated)] let attrs = AggregatedSpirvAttributes::parse(self, self.tcx.get_all_attrs(def_id)); if let Some(entry) = attrs.entry.map(|attr| attr.value) { // HACK(eddyb) early insert to let `shader_entry_stub` call this @@ -212,11 +222,14 @@ impl<'tcx> CodegenCx<'tcx> { // HACK(eddyb) there is no good way to identify these definitions // (e.g. no `#[lang = "..."]` attribute), but this works well enough. - if let Some("panic_nounwind_fmt" | "panic_explicit") = - demangled_symbol_name.strip_prefix("core::panicking::") + if let Some(name) = demangled_symbol_name.strip_prefix("core::panicking::") + && (name == "panic_explicit" || name.starts_with("panic_")) { self.panic_entry_points.borrow_mut().insert(def_id); } + if demangled_symbol_name.ends_with("::precondition_check") { + self.panic_entry_points.borrow_mut().insert(def_id); + } if let Some(pieces_len) = demangled_symbol_name .strip_prefix("::new_const::<") .and_then(|s| s.strip_suffix(">")) @@ -369,13 +382,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'tcx> { impl<'tcx> StaticCodegenMethods for CodegenCx<'tcx> { fn static_addr_of(&self, alloc: ConstAllocation<'_>, _kind: Option<&str>) -> Self::Value { - let cv = self.const_data_from_alloc(alloc); - self.def_constant( - self.type_ptr_to(cv.ty), - SpirvConst::PtrTo { - pointee: cv.def_cx(self), - }, - ) + self.static_addr_of_constant(self.const_data_from_alloc(alloc)) } fn codegen_static(&mut self, def_id: DefId) { diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs b/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs index 8525596494..66502467c9 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs @@ -97,7 +97,9 @@ impl<'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'tcx> { fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool { match layout.backend_repr { - BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. } => true, + BackendRepr::Scalar(_) + | BackendRepr::ScalableVector { .. } + | BackendRepr::SimdVector { .. } => true, BackendRepr::ScalarPair(..) => false, BackendRepr::Memory { .. } => layout.is_zst(), } @@ -107,6 +109,7 @@ impl<'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'tcx> { match layout.backend_repr { BackendRepr::ScalarPair(..) => true, BackendRepr::Scalar(_) + | BackendRepr::ScalableVector { .. } | BackendRepr::SimdVector { .. } | BackendRepr::Memory { .. } => false, } diff --git a/crates/rustc_codegen_spirv/src/custom_decorations.rs b/crates/rustc_codegen_spirv/src/custom_decorations.rs index 1027df9aed..34afe14bc5 100644 --- a/crates/rustc_codegen_spirv/src/custom_decorations.rs +++ b/crates/rustc_codegen_spirv/src/custom_decorations.rs @@ -12,7 +12,6 @@ use rustc_span::{Span, source_map::SourceMap}; use smallvec::SmallVec; use std::borrow::Cow; use std::marker::PhantomData; -use std::path::PathBuf; use std::sync::Arc; use std::{fmt, iter, slice, str}; @@ -447,7 +446,7 @@ impl<'a> SpanRegenerator<'a> { // HACK(eddyb) in case the file has changed, and because `SourceMap` // is strictly monotonic, we need to come up with some other name. - let mut sm_file_name_candidates = [PathBuf::from(file_name).into()] + let mut sm_file_name_candidates = [FileName::Custom(file_name.to_string())] .into_iter() .chain((0..).map(|i| FileName::Custom(format!("outdated({i}) {file_name}")))); diff --git a/crates/rustc_codegen_spirv/src/lib.rs b/crates/rustc_codegen_spirv/src/lib.rs index cd508bfc74..a647fb54ff 100644 --- a/crates/rustc_codegen_spirv/src/lib.rs +++ b/crates/rustc_codegen_spirv/src/lib.rs @@ -228,10 +228,10 @@ impl CodegenBackend for SpirvCodegenBackend { // FIXME(eddyb) this is currently only passed back to us, specifically // into `target_machine_factory` (which is a noop), but it might make // sense to move some of the target feature parsing into here. - providers.global_backend_features = |_tcx, ()| vec![]; + providers.queries.global_backend_features = |_tcx, ()| vec![]; crate::abi::provide(providers); - crate::attr::provide(providers); + crate::attr::provide(&mut providers.queries); } fn target_cpu(&self, sess: &Session) -> String { @@ -324,7 +324,7 @@ impl WriteBackendMethods for SpirvCodegenBackend { _opt_level: config::OptLevel, _target_features: &[String], ) -> TargetMachineFactoryFn { - Arc::new(|_| Ok(())) + Arc::new(|_, _| ()) } // FIXME(eddyb) reuse the "merge" stage of `crate::linker` for this, or even diff --git a/crates/rustc_codegen_spirv/src/link.rs b/crates/rustc_codegen_spirv/src/link.rs index 6f3f081ca9..4fead0d21e 100644 --- a/crates/rustc_codegen_spirv/src/link.rs +++ b/crates/rustc_codegen_spirv/src/link.rs @@ -6,8 +6,7 @@ use crate::{SpirvCodegenBackend, SpirvModuleBuffer, linker}; use ar::{Archive, GnuBuilder, Header}; use rspirv::binary::Assemble; use rspirv::dr::Module; -use rustc_ast::CRATE_NODE_ID; -use rustc_attr_parsing::{ShouldEmit, eval_config_entry}; +use rustc_attr_parsing::eval_config_entry; use rustc_codegen_spirv_types::{CompileResult, ModuleResult}; use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared}; use rustc_codegen_ssa::back::write::CodegenContext; @@ -450,7 +449,7 @@ fn add_upstream_rust_crates( let src = &crate_info.used_crate_source[&cnum]; match data[cnum] { Linkage::NotLinked | Linkage::IncludedFromDylib => {} - Linkage::Static => rlibs.push(src.rlib.as_ref().unwrap().0.clone()), + Linkage::Static => rlibs.push(src.rlib.as_ref().unwrap().clone()), //Linkage::Dynamic => rlibs.push(src.dylib.as_ref().unwrap().0.clone()), Linkage::Dynamic => { sess.dcx().err("TODO: Linkage::Dynamic not supported yet"); @@ -494,9 +493,7 @@ fn add_upstream_native_libraries(sess: &Session, crate_info: &CrateInfo, crate_t // (see `compiler/rustc_codegen_ssa/src/back/link.rs`) fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool { match lib.cfg { - Some(ref cfg) => { - eval_config_entry(sess, cfg, CRATE_NODE_ID, ShouldEmit::ErrorsAndLints).as_bool() - } + Some(ref cfg) => eval_config_entry(sess, cfg).as_bool(), None => true, } } @@ -635,7 +632,7 @@ pub(crate) fn run_thin( modules: Vec<(String, SpirvModuleBuffer)>, cached_modules: Vec<(SerializedModule, WorkProduct)>, ) -> (Vec>, Vec) { - if cgcx.opts.cg.linker_plugin_lto.enabled() { + if cgcx.use_linker_plugin_lto { unreachable!("We should never reach this case if the LTO step is deferred to the linker"); } assert!( diff --git a/tests/compiletests/src/main.rs b/tests/compiletests/src/main.rs index abe325d8b6..7df7ea070b 100644 --- a/tests/compiletests/src/main.rs +++ b/tests/compiletests/src/main.rs @@ -198,6 +198,7 @@ impl Runner { "build", "-p", "compiletests-deps-helper", + "-Zjson-target-spec", "-Zbuild-std=core", "-Zbuild-std-features=compiler-builtins-mem", "--target", From 131d5aca396bbdc061397a9476f0c59278a707f1 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 14:57:24 -0800 Subject: [PATCH 11/34] Handle newer panic format_args lowering patterns --- .../src/builder/format_args_decompiler.rs | 274 ++++++++++-------- 1 file changed, 157 insertions(+), 117 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs index c9442030c7..bd084f4605 100644 --- a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs +++ b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs @@ -276,130 +276,168 @@ impl<'tcx> DecodedFormatArgs<'tcx> { insts.reverse(); Some(insts) }; - let fmt_args_new_call_insts = try_rev_take(3).ok_or_else(|| { - FormatArgsNotRecognized("fmt::Arguments::new call: ran out of instructions".into()) - })?; + // Newer rustc can pass the `fmt::Arguments::new_*` result directly to + // panic entry points (single trailing call), while older versions go + // through a local temporary (`Call -> Store -> Load`). + let fmt_args_new_call_inst_count = if matches!( + try_rev_take(-3).as_deref(), + Some(&[Inst::Call(_, _, _), Inst::Store(_, _), Inst::Load(_, _)]) + ) { + 3 + } else if matches!( + try_rev_take(-1).as_deref(), + Some(&[Inst::Call(call_ret_id, _, _)]) if call_ret_id == format_args_id + ) { + 1 + } else { + // HACK(eddyb) gather context for new call patterns before bailing. + let mut insts = SmallVec::<[Inst; 32]>::new(); + while let Some(extra_inst) = try_rev_take(1) { + insts.extend(extra_inst); + if insts.len() >= 32 { + break; + } + } + insts.reverse(); + + return Err(if insts.is_empty() { + FormatArgsNotRecognized("fmt::Arguments::new call: ran out of instructions".into()) + } else { + FormatArgsNotRecognized(format!("fmt::Arguments::new call sequence ({insts:?})",)) + }); + }; + let fmt_args_new_call_insts = try_rev_take(fmt_args_new_call_inst_count).unwrap(); + let (call_args, pieces_len, rt_args_count) = match fmt_args_new_call_insts[..] { + [ + Inst::Call(call_ret_id, callee_id, ref call_args), + Inst::Store(st_dst_id, st_val_id), + Inst::Load(ld_val_id, ld_src_id), + ] if call_ret_id == st_val_id + && st_dst_id == ld_src_id + && ld_val_id == format_args_id => + { + require_local_var(st_dst_id, "fmt::Arguments::new destination")?; + + let Some(&(pieces_len, rt_args_count)) = + cx.fmt_args_new_fn_ids.borrow().get(&callee_id) + else { + return Err(FormatArgsNotRecognized( + "fmt::Arguments::new callee not registered".into(), + )); + }; + + (call_args, pieces_len, rt_args_count) + } + [Inst::Call(call_ret_id, callee_id, ref call_args)] + if call_ret_id == format_args_id => + { + let Some(&(pieces_len, rt_args_count)) = + cx.fmt_args_new_fn_ids.borrow().get(&callee_id) + else { + return Err(FormatArgsNotRecognized( + "fmt::Arguments::new callee not registered".into(), + )); + }; + + (call_args, pieces_len, rt_args_count) + } + _ => { + // HACK(eddyb) this gathers more context before reporting. + let mut insts = fmt_args_new_call_insts; + insts.reverse(); + while let Some(extra_inst) = try_rev_take(1) { + insts.extend(extra_inst); + if insts.len() >= 32 { + break; + } + } + insts.reverse(); + + return Err(FormatArgsNotRecognized(format!( + "fmt::Arguments::new call sequence ({insts:?})", + ))); + } + }; let ((pieces_slice_ptr_id, pieces_len), (rt_args_slice_ptr_id, rt_args_count)) = - match fmt_args_new_call_insts[..] { + match call_args[..] { + // `::new_v1_formatted` + // + // HACK(eddyb) this isn't fully supported, + // as that would require digging into unstable + // internals of `core::fmt::rt::Placeholder`s, + // but the whole call still needs to be removed, + // and both const str pieces and runtime args + // can still be printed (even if in jankier way). [ - Inst::Call(call_ret_id, callee_id, ref call_args), - Inst::Store(st_dst_id, st_val_id), - Inst::Load(ld_val_id, ld_src_id), - ] if call_ret_id == st_val_id - && st_dst_id == ld_src_id - && ld_val_id == format_args_id => - { - require_local_var(st_dst_id, "fmt::Arguments::new destination")?; - - let Some(&(pieces_len, rt_args_count)) = - cx.fmt_args_new_fn_ids.borrow().get(&callee_id) - else { - return Err(FormatArgsNotRecognized( - "fmt::Arguments::new callee not registered".into(), - )); - }; + pieces_slice_ptr_id, + pieces_len_id, + rt_args_slice_ptr_id, + rt_args_len_id, + fmt_placeholders_slice_ptr_id, + fmt_placeholders_len_id, + ] if (pieces_len, rt_args_count) == (!0, !0) => { + let [pieces_len, rt_args_len, fmt_placeholders_len] = + match [pieces_len_id, rt_args_len_id, fmt_placeholders_len_id] + .map(const_u32_as_usize) + { + [Some(a), Some(b), Some(c)] => [a, b, c], + _ => { + return Err(FormatArgsNotRecognized( + "fmt::Arguments::new_v1_formatted \ + with dynamic lengths" + .into(), + )); + } + }; - match call_args[..] { - // `::new_v1_formatted` - // - // HACK(eddyb) this isn't fully supported, - // as that would require digging into unstable - // internals of `core::fmt::rt::Placeholder`s, - // but the whole call still needs to be removed, - // and both const str pieces and runtime args - // can still be printed (even if in jankier way). - [ - pieces_slice_ptr_id, - pieces_len_id, - rt_args_slice_ptr_id, - rt_args_len_id, - fmt_placeholders_slice_ptr_id, - fmt_placeholders_len_id, - ] if (pieces_len, rt_args_count) == (!0, !0) => { - let [pieces_len, rt_args_len, fmt_placeholders_len] = - match [pieces_len_id, rt_args_len_id, fmt_placeholders_len_id] - .map(const_u32_as_usize) - { - [Some(a), Some(b), Some(c)] => [a, b, c], - _ => { - return Err(FormatArgsNotRecognized( - "fmt::Arguments::new_v1_formatted \ - with dynamic lengths" - .into(), - )); - } - }; - - let prepare_args_insts = try_rev_take(2).ok_or_else(|| { - FormatArgsNotRecognized( - "fmt::Arguments::new_v1_formatted call: ran out of instructions".into(), - ) - })?; - let (rt_args_slice_ptr_id, _fmt_placeholders_slice_ptr_id) = - match prepare_args_insts[..] { - [ - Inst::Bitcast(rt_args_cast_out_id, rt_args_cast_in_id), - Inst::Bitcast( - placeholders_cast_out_id, - placeholders_cast_in_id, - ), - ] if rt_args_cast_out_id == rt_args_slice_ptr_id - && placeholders_cast_out_id - == fmt_placeholders_slice_ptr_id => - { - (rt_args_cast_in_id, placeholders_cast_in_id) - } - _ => { - let mut insts = prepare_args_insts; - insts.extend(fmt_args_new_call_insts); - return Err(FormatArgsNotRecognized(format!( - "fmt::Arguments::new_v1_formatted call sequence ({insts:?})", - ))); - } - }; - - decoded_format_args.has_unknown_fmt_placeholder_to_args_mapping = - Some(fmt_placeholders_len); - - ( - (pieces_slice_ptr_id, pieces_len), - (Some(rt_args_slice_ptr_id), rt_args_len), - ) - } + let prepare_args_insts = try_rev_take(2).ok_or_else(|| { + FormatArgsNotRecognized( + "fmt::Arguments::new_v1_formatted call: ran out of instructions".into(), + ) + })?; + let (rt_args_slice_ptr_id, _fmt_placeholders_slice_ptr_id) = + match prepare_args_insts[..] { + [ + Inst::Bitcast(rt_args_cast_out_id, rt_args_cast_in_id), + Inst::Bitcast(placeholders_cast_out_id, placeholders_cast_in_id), + ] if rt_args_cast_out_id == rt_args_slice_ptr_id + && placeholders_cast_out_id == fmt_placeholders_slice_ptr_id => + { + (rt_args_cast_in_id, placeholders_cast_in_id) + } + _ => { + let mut insts = prepare_args_insts; + insts.extend(fmt_args_new_call_insts); + return Err(FormatArgsNotRecognized(format!( + "fmt::Arguments::new_v1_formatted call sequence ({insts:?})", + ))); + } + }; - // `::new_v1` - [pieces_slice_ptr_id, rt_args_slice_ptr_id] => ( - (pieces_slice_ptr_id, pieces_len), - (Some(rt_args_slice_ptr_id), rt_args_count), - ), + decoded_format_args.has_unknown_fmt_placeholder_to_args_mapping = + Some(fmt_placeholders_len); - // `::new_const` - [pieces_slice_ptr_id] if rt_args_count == 0 => { - ((pieces_slice_ptr_id, pieces_len), (None, rt_args_count)) - } + ( + (pieces_slice_ptr_id, pieces_len), + (Some(rt_args_slice_ptr_id), rt_args_len), + ) + } - _ => { - return Err(FormatArgsNotRecognized( - "fmt::Arguments::new call args".into(), - )); - } - } + // `::new_v1` + [pieces_slice_ptr_id, rt_args_slice_ptr_id] => ( + (pieces_slice_ptr_id, pieces_len), + (Some(rt_args_slice_ptr_id), rt_args_count), + ), + + // `::new_const` + [pieces_slice_ptr_id] if rt_args_count == 0 => { + ((pieces_slice_ptr_id, pieces_len), (None, rt_args_count)) } - _ => { - // HACK(eddyb) this gathers more context before reporting. - let mut insts = fmt_args_new_call_insts; - insts.reverse(); - while let Some(extra_inst) = try_rev_take(1) { - insts.extend(extra_inst); - if insts.len() >= 32 { - break; - } - } - insts.reverse(); - return Err(FormatArgsNotRecognized(format!( - "fmt::Arguments::new call sequence ({insts:?})", - ))); + _ => { + return Err(FormatArgsNotRecognized( + "fmt::Arguments::new call args".into(), + )); } }; @@ -772,7 +810,9 @@ impl<'a, 'tcx> CodegenPanic<'a, 'tcx> for FormatArgsResult<'tcx> { match self { Ok(e) => e.codegen_panic(builder, result_type), Err(FormatArgsNotRecognized(step)) => { - if let Some(current_span) = builder.current_span { + if let Some(current_span) = builder.current_span + && !builder.tcx.sess.opts.unstable_opts.ui_testing + { // HACK(eddyb) Cargo silences warnings in dependencies. let force_warn = |span, msg| -> rustc_errors::Diag<'_, ()> { rustc_errors::Diag::new( From 1693d0290d6310f1cf2bbc46bda0fbae3476b111 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 15:14:15 -0800 Subject: [PATCH 12/34] Handle nightly panic format_args lowering and unsized const reification --- .../src/builder/format_args_decompiler.rs | 319 +++++++++++------- .../src/codegen_cx/constant.rs | 74 ++-- .../src/codegen_cx/declare.rs | 7 + 3 files changed, 263 insertions(+), 137 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs index bd084f4605..b479715b11 100644 --- a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs +++ b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs @@ -183,6 +183,7 @@ impl<'tcx> DecodedFormatArgs<'tcx> { enum Inst { Bitcast(ID, ID), CompositeExtract(ID, ID, u32), + CompositeInsert(ID, ID, ID, u32), InBoundsAccessChain(ID, ID, u32), InBoundsAccessChain2(ID, ID, u32, u32), Store(ID, ID), @@ -229,6 +230,18 @@ impl<'tcx> DecodedFormatArgs<'tcx> { { return Some(Inst::CompositeExtract(r, x, i)); } + if inst.class.opcode == Op::CompositeInsert + && let ( + Some(r), + &[ + Operand::IdRef(inserted), + Operand::IdRef(base), + Operand::LiteralBit32(i), + ], + ) = (inst.result_id, &inst.operands[..]) + { + return Some(Inst::CompositeInsert(r, inserted, base, i)); + } // HACK(eddyb) all instructions accepted below // are expected to take no more than 4 operands, @@ -289,6 +302,20 @@ impl<'tcx> DecodedFormatArgs<'tcx> { Some(&[Inst::Call(call_ret_id, _, _)]) if call_ret_id == format_args_id ) { 1 + } else if matches!( + try_rev_take(-5).as_deref(), + Some(&[ + Inst::Call(call_ret_id, _, _), + Inst::CompositeExtract(extracted0, from0, 0), + Inst::CompositeExtract(extracted1, from1, 1), + Inst::CompositeInsert(inserted0, value0, _, 0), + Inst::CompositeInsert(inserted1, value1, inserted0_prev, 1), + ]) if [from0, from1] == [call_ret_id; 2] + && [value0, value1] == [extracted0, extracted1] + && inserted0 == inserted0_prev + && inserted1 == format_args_id + ) { + 5 } else { // HACK(eddyb) gather context for new call patterns before bailing. let mut insts = SmallVec::<[Inst; 32]>::new(); @@ -341,6 +368,27 @@ impl<'tcx> DecodedFormatArgs<'tcx> { (call_args, pieces_len, rt_args_count) } + [ + Inst::Call(call_ret_id, callee_id, ref call_args), + Inst::CompositeExtract(extracted0, from0, 0), + Inst::CompositeExtract(extracted1, from1, 1), + Inst::CompositeInsert(inserted0, value0, _, 0), + Inst::CompositeInsert(inserted1, value1, inserted0_prev, 1), + ] if [from0, from1] == [call_ret_id; 2] + && [value0, value1] == [extracted0, extracted1] + && inserted0 == inserted0_prev + && inserted1 == format_args_id => + { + let Some(&(pieces_len, rt_args_count)) = + cx.fmt_args_new_fn_ids.borrow().get(&callee_id) + else { + return Err(FormatArgsNotRecognized( + "fmt::Arguments::new callee not registered".into(), + )); + }; + + (call_args, pieces_len, rt_args_count) + } _ => { // HACK(eddyb) this gathers more context before reporting. let mut insts = fmt_args_new_call_insts; @@ -358,88 +406,112 @@ impl<'tcx> DecodedFormatArgs<'tcx> { ))); } }; - let ((pieces_slice_ptr_id, pieces_len), (rt_args_slice_ptr_id, rt_args_count)) = - match call_args[..] { - // `::new_v1_formatted` - // - // HACK(eddyb) this isn't fully supported, - // as that would require digging into unstable - // internals of `core::fmt::rt::Placeholder`s, - // but the whole call still needs to be removed, - // and both const str pieces and runtime args - // can still be printed (even if in jankier way). - [ - pieces_slice_ptr_id, - pieces_len_id, - rt_args_slice_ptr_id, - rt_args_len_id, - fmt_placeholders_slice_ptr_id, - fmt_placeholders_len_id, - ] if (pieces_len, rt_args_count) == (!0, !0) => { - let [pieces_len, rt_args_len, fmt_placeholders_len] = - match [pieces_len_id, rt_args_len_id, fmt_placeholders_len_id] - .map(const_u32_as_usize) - { - [Some(a), Some(b), Some(c)] => [a, b, c], - _ => { - return Err(FormatArgsNotRecognized( - "fmt::Arguments::new_v1_formatted \ + const FMT_ARGS_FROM_STR_PIECES_LEN: usize = !1; + enum PiecesSource { + Slice { ptr_id: Word, len: usize }, + DirectConstStr([Word; 2]), + } + let (pieces_source, (rt_args_slice_ptr_id, rt_args_count)) = match call_args[..] { + // `::new_v1_formatted` + // + // HACK(eddyb) this isn't fully supported, + // as that would require digging into unstable + // internals of `core::fmt::rt::Placeholder`s, + // but the whole call still needs to be removed, + // and both const str pieces and runtime args + // can still be printed (even if in jankier way). + [ + pieces_slice_ptr_id, + pieces_len_id, + rt_args_slice_ptr_id, + rt_args_len_id, + fmt_placeholders_slice_ptr_id, + fmt_placeholders_len_id, + ] if (pieces_len, rt_args_count) == (!0, !0) => { + let [pieces_len, rt_args_len, fmt_placeholders_len] = + match [pieces_len_id, rt_args_len_id, fmt_placeholders_len_id] + .map(const_u32_as_usize) + { + [Some(a), Some(b), Some(c)] => [a, b, c], + _ => { + return Err(FormatArgsNotRecognized( + "fmt::Arguments::new_v1_formatted \ with dynamic lengths" - .into(), - )); - } - }; + .into(), + )); + } + }; - let prepare_args_insts = try_rev_take(2).ok_or_else(|| { - FormatArgsNotRecognized( - "fmt::Arguments::new_v1_formatted call: ran out of instructions".into(), - ) - })?; - let (rt_args_slice_ptr_id, _fmt_placeholders_slice_ptr_id) = - match prepare_args_insts[..] { - [ - Inst::Bitcast(rt_args_cast_out_id, rt_args_cast_in_id), - Inst::Bitcast(placeholders_cast_out_id, placeholders_cast_in_id), - ] if rt_args_cast_out_id == rt_args_slice_ptr_id - && placeholders_cast_out_id == fmt_placeholders_slice_ptr_id => - { - (rt_args_cast_in_id, placeholders_cast_in_id) - } - _ => { - let mut insts = prepare_args_insts; - insts.extend(fmt_args_new_call_insts); - return Err(FormatArgsNotRecognized(format!( - "fmt::Arguments::new_v1_formatted call sequence ({insts:?})", - ))); - } - }; + let prepare_args_insts = try_rev_take(2).ok_or_else(|| { + FormatArgsNotRecognized( + "fmt::Arguments::new_v1_formatted call: ran out of instructions".into(), + ) + })?; + let (rt_args_slice_ptr_id, _fmt_placeholders_slice_ptr_id) = + match prepare_args_insts[..] { + [ + Inst::Bitcast(rt_args_cast_out_id, rt_args_cast_in_id), + Inst::Bitcast(placeholders_cast_out_id, placeholders_cast_in_id), + ] if rt_args_cast_out_id == rt_args_slice_ptr_id + && placeholders_cast_out_id == fmt_placeholders_slice_ptr_id => + { + (rt_args_cast_in_id, placeholders_cast_in_id) + } + _ => { + let mut insts = prepare_args_insts; + insts.extend(fmt_args_new_call_insts); + return Err(FormatArgsNotRecognized(format!( + "fmt::Arguments::new_v1_formatted call sequence ({insts:?})", + ))); + } + }; - decoded_format_args.has_unknown_fmt_placeholder_to_args_mapping = - Some(fmt_placeholders_len); + decoded_format_args.has_unknown_fmt_placeholder_to_args_mapping = + Some(fmt_placeholders_len); - ( - (pieces_slice_ptr_id, pieces_len), - (Some(rt_args_slice_ptr_id), rt_args_len), - ) - } + ( + PiecesSource::Slice { + ptr_id: pieces_slice_ptr_id, + len: pieces_len, + }, + (Some(rt_args_slice_ptr_id), rt_args_len), + ) + } - // `::new_v1` - [pieces_slice_ptr_id, rt_args_slice_ptr_id] => ( - (pieces_slice_ptr_id, pieces_len), - (Some(rt_args_slice_ptr_id), rt_args_count), - ), + // `::from_str` + [str_ptr_id, str_len_id] + if (pieces_len, rt_args_count) == (FMT_ARGS_FROM_STR_PIECES_LEN, 0) => + { + ( + PiecesSource::DirectConstStr([str_ptr_id, str_len_id]), + (None, 0), + ) + } - // `::new_const` - [pieces_slice_ptr_id] if rt_args_count == 0 => { - ((pieces_slice_ptr_id, pieces_len), (None, rt_args_count)) - } + // `::new_v1` + [pieces_slice_ptr_id, rt_args_slice_ptr_id] => ( + PiecesSource::Slice { + ptr_id: pieces_slice_ptr_id, + len: pieces_len, + }, + (Some(rt_args_slice_ptr_id), rt_args_count), + ), - _ => { - return Err(FormatArgsNotRecognized( - "fmt::Arguments::new call args".into(), - )); - } - }; + // `::new_const` + [pieces_slice_ptr_id] if rt_args_count == 0 => ( + PiecesSource::Slice { + ptr_id: pieces_slice_ptr_id, + len: pieces_len, + }, + (None, rt_args_count), + ), + + _ => { + return Err(FormatArgsNotRecognized( + "fmt::Arguments::new call args".into(), + )); + } + }; // HACK(eddyb) this is the worst part: if we do have runtime // arguments (from e.g. new `assert!`s being added to `core`), @@ -626,52 +698,65 @@ impl<'tcx> DecodedFormatArgs<'tcx> { } } - // If the `pieces: &[&str]` slice needs a bitcast, it'll be here. - // HACK(eddyb) `try_rev_take(-1)` is "peeking", not taking. - let pieces_slice_ptr_id = match try_rev_take(-1).as_deref() { - Some(&[Inst::Bitcast(out_id, in_id)]) if out_id == pieces_slice_ptr_id => { - // HACK(eddyb) consume the peeked instructions. - try_rev_take(1).unwrap(); - - in_id + decoded_format_args.const_pieces = match pieces_source { + PiecesSource::DirectConstStr(str_ref) => { + const_str_as_utf8(&str_ref).map(|s| [s].into_iter().collect()) } - _ => pieces_slice_ptr_id, - }; - decoded_format_args.const_pieces = - match const_slice_as_elem_ids(pieces_slice_ptr_id, pieces_len) { - Some(piece_ids) => piece_ids - .iter() - .map(|&piece_id| match cx.builder.lookup_const_by_id(piece_id)? { - SpirvConst::Composite(piece) => const_str_as_utf8(piece.try_into().ok()?), - _ => None, - }) - .collect::>(), - // HACK(eddyb) minor upstream blunder results in at - // least one instance of a runtime `[&str; 1]` array, - // see also this comment left on the responsible PR: - // https://github.com/rust-lang/rust/pull/129658#discussion_r2181834781 - // HACK(eddyb) `try_rev_take(-4)` is "peeking", not taking. - None if pieces_len == 1 => match try_rev_take(-4).as_deref() { - Some( - &[ - Inst::InBoundsAccessChain2(field0_ptr, array_ptr_0, 0, 0), - Inst::Store(st0_dst_ptr, st0_val), - Inst::InBoundsAccessChain2(field1_ptr, array_ptr_1, 0, 1), - Inst::Store(st1_dst_ptr, st1_val), - ], - ) if [array_ptr_0, array_ptr_1] == [pieces_slice_ptr_id; 2] - && st0_dst_ptr == field0_ptr - && st1_dst_ptr == field1_ptr => - { + PiecesSource::Slice { + ptr_id: pieces_slice_ptr_id, + len: pieces_len, + } => { + // If the `pieces: &[&str]` slice needs a bitcast, it'll be here. + // HACK(eddyb) `try_rev_take(-1)` is "peeking", not taking. + let pieces_slice_ptr_id = match try_rev_take(-1).as_deref() { + Some(&[Inst::Bitcast(out_id, in_id)]) if out_id == pieces_slice_ptr_id => { // HACK(eddyb) consume the peeked instructions. - try_rev_take(4).unwrap(); + try_rev_take(1).unwrap(); - const_str_as_utf8(&[st0_val, st1_val]).map(|s| [s].into_iter().collect()) + in_id } - _ => None, - }, - None => None, - }; + _ => pieces_slice_ptr_id, + }; + + match const_slice_as_elem_ids(pieces_slice_ptr_id, pieces_len) { + Some(piece_ids) => piece_ids + .iter() + .map(|&piece_id| match cx.builder.lookup_const_by_id(piece_id)? { + SpirvConst::Composite(piece) => { + const_str_as_utf8(piece.try_into().ok()?) + } + _ => None, + }) + .collect::>(), + // HACK(eddyb) minor upstream blunder results in at + // least one instance of a runtime `[&str; 1]` array, + // see also this comment left on the responsible PR: + // https://github.com/rust-lang/rust/pull/129658#discussion_r2181834781 + // HACK(eddyb) `try_rev_take(-4)` is "peeking", not taking. + None if pieces_len == 1 => match try_rev_take(-4).as_deref() { + Some( + &[ + Inst::InBoundsAccessChain2(field0_ptr, array_ptr_0, 0, 0), + Inst::Store(st0_dst_ptr, st0_val), + Inst::InBoundsAccessChain2(field1_ptr, array_ptr_1, 0, 1), + Inst::Store(st1_dst_ptr, st1_val), + ], + ) if [array_ptr_0, array_ptr_1] == [pieces_slice_ptr_id; 2] + && st0_dst_ptr == field0_ptr + && st1_dst_ptr == field1_ptr => + { + // HACK(eddyb) consume the peeked instructions. + try_rev_take(4).unwrap(); + + const_str_as_utf8(&[st0_val, st1_val]) + .map(|s| [s].into_iter().collect()) + } + _ => None, + }, + None => None, + } + } + }; // Keep all instructions up to (but not including) the last one // confirmed above to be the first instruction of `format_args!`. diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs index 49c0d2de11..9022283b74 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs @@ -8,7 +8,9 @@ use crate::spirv_type::SpirvType; use itertools::Itertools as _; use rspirv::spirv::Word; use rustc_abi::{self as abi, AddressSpace, Float, HasDataLayout, Integer, Primitive, Size}; -use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods}; +use rustc_codegen_ssa::traits::{ + BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods, +}; use rustc_middle::mir::interpret::{AllocError, ConstAllocation, GlobalAlloc, Scalar, alloc_range}; use rustc_middle::ty::layout::LayoutOf; use rustc_span::{DUMMY_SP, Span}; @@ -168,13 +170,14 @@ impl ConstCodegenMethods for CodegenCx<'_> { let str_ty = self .layout_of(self.tcx.types.str_) .spirv_type(DUMMY_SP, self); + let bytes_ty = self.type_array(self.type_i8(), len as u64); ( self.def_constant( self.type_ptr_to(str_ty), SpirvConst::PtrTo { pointee: self .constant_composite( - str_ty, + bytes_ty, s.bytes().map(|b| self.const_u8(b).def_cx(self)), ) .def_cx(self), @@ -343,9 +346,38 @@ impl<'tcx> CodegenCx<'tcx> { && let Some(SpirvConst::ConstDataFromAlloc(alloc)) = self.builder.lookup_const_by_id(pointee) && let SpirvType::Pointer { pointee } = self.lookup_type(ty) - && let Some(init) = self.try_read_from_const_alloc(alloc, pointee) { - return self.static_addr_of_constant(init); + let init = self.try_read_from_const_alloc(alloc, pointee).or_else(|| { + match self.lookup_type(pointee) { + // Reify unsized constants through a sized backing array, + // then keep the requested pointer type in `SpirvConst::PtrTo`. + SpirvType::RuntimeArray { element } => { + let elem_size = self.lookup_type(element).sizeof(self)?; + if elem_size.bytes() == 0 { + return None; + } + + let alloc_size = alloc.inner().size(); + if alloc_size.bytes() % elem_size.bytes() != 0 { + return None; + } + + let count = alloc_size.bytes() / elem_size.bytes(); + let sized_ty = self.type_array(element, count); + self.try_read_from_const_alloc(alloc, sized_ty) + } + _ => None, + } + }); + + if let Some(init) = init { + return self.def_constant( + ty, + SpirvConst::PtrTo { + pointee: init.def_cx(self), + }, + ); + } } if val.ty == ty { @@ -554,8 +586,7 @@ impl<'tcx> CodegenCx<'tcx> { } SpirvType::Vector { element, .. } | SpirvType::Matrix { element, .. } - | SpirvType::Array { element, .. } - | SpirvType::RuntimeArray { element } => { + | SpirvType::Array { element, .. } => { let stride = self.lookup_type(element).sizeof(self).unwrap(); let count = match ty_def { @@ -565,9 +596,6 @@ impl<'tcx> CodegenCx<'tcx> { SpirvType::Array { count, .. } => { u64::try_from(self.builder.lookup_const_scalar(count).unwrap()).unwrap() } - SpirvType::RuntimeArray { .. } => { - (alloc.inner().size() - offset).bytes() / stride.bytes() - } _ => unreachable!(), }; @@ -590,19 +618,25 @@ impl<'tcx> CodegenCx<'tcx> { assert_eq!(read_size, ty_size); } - if let SpirvType::RuntimeArray { .. } = ty_def { - // FIXME(eddyb) values of this type should never be created, - // the only reasonable encoding of e.g. `&str` consts should - // be `&[u8; N]` consts, with the `static_addr_of` pointer - // (*not* the value it points to) cast to `&str`, afterwards. - self.zombie_no_span( - result.def_cx(self), - &format!("unsupported unsized `{}` constant", self.debug_type(ty)), - ); - } - (result, read_size) } + SpirvType::RuntimeArray { element } => { + let stride = self.lookup_type(element).sizeof(self).unwrap(); + let count = (alloc.inner().size() - offset).bytes() / stride.bytes(); + let sized_ty = self.type_array(element, count); + + let result = self.constant_composite( + sized_ty, + (0..count).map(|i| { + let (e, e_size) = + self.read_from_const_alloc_at(alloc, element, offset + i * stride); + assert_eq!(e_size, stride); + e.def_cx(self) + }), + ); + + (result, count * stride) + } SpirvType::Void | SpirvType::Function { .. } diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs index a06d4d3328..4e50e33575 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs @@ -230,6 +230,9 @@ impl<'tcx> CodegenCx<'tcx> { if demangled_symbol_name.ends_with("::precondition_check") { self.panic_entry_points.borrow_mut().insert(def_id); } + if demangled_symbol_name.contains("::bounds_check") { + self.panic_entry_points.borrow_mut().insert(def_id); + } if let Some(pieces_len) = demangled_symbol_name .strip_prefix("::new_const::<") .and_then(|s| s.strip_suffix(">")) @@ -254,6 +257,10 @@ impl<'tcx> CodegenCx<'tcx> { .borrow_mut() .insert(fn_id, (!0, !0)); } + if demangled_symbol_name == "::from_str" { + // HACK(eddyb) `!1` distinguishes `from_str` from normal `new_*`. + self.fmt_args_new_fn_ids.borrow_mut().insert(fn_id, (!1, 0)); + } // HACK(eddyb) there is no good way to identify these definitions // (e.g. no `#[lang = "..."]` attribute), but this works well enough. From b591923b27adf1362942b44a33096ce7f2b9ca26 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 15:14:20 -0800 Subject: [PATCH 13/34] Fix new nightly clippy suggestions in type trie and linker --- .../rustc_codegen_spirv-types/src/compile_result.rs | 2 +- crates/rustc_codegen_spirv/src/linker/specializer.rs | 11 +++++------ .../src/linker/spirt_passes/diagnostics.rs | 9 +++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/rustc_codegen_spirv-types/src/compile_result.rs b/crates/rustc_codegen_spirv-types/src/compile_result.rs index 7a19591532..77e7e5b660 100644 --- a/crates/rustc_codegen_spirv-types/src/compile_result.rs +++ b/crates/rustc_codegen_spirv-types/src/compile_result.rs @@ -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::>(); - 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() diff --git a/crates/rustc_codegen_spirv/src/linker/specializer.rs b/crates/rustc_codegen_spirv/src/linker/specializer.rs index f8184fe550..6de9db06ae 100644 --- a/crates/rustc_codegen_spirv/src/linker/specializer.rs +++ b/crates/rustc_codegen_spirv/src/linker/specializer.rs @@ -879,14 +879,13 @@ impl<'a> InferOperandList<'a> { // Maybe filter this operand, but only *after* consuming the "generic" args for it. match self.transform { - None => {} - // Skip a non-ID operand. - Some(InferOperandListTransform::TypeOfId) => { - if first_operand.id_ref_any().is_none() { - continue; - } + Some(InferOperandListTransform::TypeOfId) + if first_operand.id_ref_any().is_none() => + { + continue; } + None | Some(InferOperandListTransform::TypeOfId) => {} } // Maybe replace this operand with a different one. diff --git a/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs b/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs index 3951a7f8c0..74ef56086b 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs @@ -336,8 +336,9 @@ impl UseOrigin<'_> { inst_attrs: _, origin, } => { - let func_desc = special_func - .map(|special_func| match special_func { + let func_desc = special_func.map_or_else( + || name_from_attrs(*func_attrs, "function"), + |special_func| match special_func { SpecialFunc::Exported(&ExportKey::LinkName(name)) => { format!("function export `{}`", &cx[name]) } @@ -361,8 +362,8 @@ impl UseOrigin<'_> { "" => "unnamed function".into(), callee_name => format!("`{callee_name}`"), }, - }) - .unwrap_or_else(|| name_from_attrs(*func_attrs, "function")); + }, + ); match origin { IntraFuncUseOrigin::CallCallee => format!("called by {func_desc}"), IntraFuncUseOrigin::Other => format!("used from within {func_desc}"), From c14bd5b87aeeb4f09004511efeca63735c52dad5 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 15:19:49 -0800 Subject: [PATCH 14/34] Port linker test harness to current rustc session APIs --- crates/rustc_codegen_spirv/src/linker/test.rs | 42 +++++++------------ 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/linker/test.rs b/crates/rustc_codegen_spirv/src/linker/test.rs index e71e31b493..c94647102a 100644 --- a/crates/rustc_codegen_spirv/src/linker/test.rs +++ b/crates/rustc_codegen_spirv/src/linker/test.rs @@ -1,12 +1,10 @@ use super::{LinkResult, link}; use rspirv::dr::Module; -use rustc_errors::registry::Registry; use rustc_session::CompilerIO; use rustc_session::config::{Input, OutputFilenames, OutputTypes}; use rustc_span::FileName; use std::io::Write; use std::sync::{Arc, Mutex}; -use termcolor::{ColorSpec, WriteColor}; // https://github.com/colin-kiegel/rust-pretty-assertions/issues/24 #[derive(PartialEq, Eq)] @@ -91,19 +89,6 @@ fn link_with_linker_opts( self.0.lock().unwrap().flush() } } - impl WriteColor for BufWriter { - fn supports_color(&self) -> bool { - false - } - - fn set_color(&mut self, _spec: &ColorSpec) -> std::io::Result<()> { - Ok(()) - } - - fn reset(&mut self) -> std::io::Result<()> { - Ok(()) - } - } let buf = BufWriter::default(); let output = buf.clone(); @@ -119,8 +104,13 @@ fn link_with_linker_opts( let mut early_dcx = rustc_session::EarlyDiagCtxt::new(rustc_session::config::ErrorOutputType::default()); let matches = - rustc_driver::handle_options(&early_dcx, &["".to_string(), "x.rs".to_string()]) - .unwrap(); + match rustc_driver::handle_options(&early_dcx, &["".to_string(), "x.rs".to_string()]) { + rustc_driver::HandledOptions::Normal(matches) + | rustc_driver::HandledOptions::HelpOnly(matches) => matches, + rustc_driver::HandledOptions::None => { + unreachable!("failed to parse test rustc args") + } + }; let sopts = rustc_session::config::build_session_options(&mut early_dcx, &matches); let target = "spirv-unknown-spv1.0" @@ -148,12 +138,9 @@ fn link_with_linker_opts( temps_dir: None, }, Default::default(), - Registry::new(&[]), - Default::default(), - Default::default(), target, rustc_interface::util::rustc_version_str().unwrap_or("unknown"), - Default::default(), + None, &rustc_driver_impl::USING_INTERNAL_FEATURES, ); @@ -162,11 +149,14 @@ fn link_with_linker_opts( sess.psess = { let source_map = sess.psess.clone_source_map(); - let emitter = rustc_errors::emitter::HumanEmitter::new( - rustc_errors::AutoStream::new(Box::new(buf), rustc_errors::ColorChoice::Never), - rustc_driver_impl::default_translator(), - ) - .sm(Some(source_map.clone())); + let emitter = + rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter::new( + rustc_errors::AutoStream::new( + Box::new(buf) as Box, + rustc_errors::ColorChoice::Never, + ), + ) + .sm(Some(source_map.clone())); rustc_session::parse::ParseSess::with_dcx( rustc_errors::DiagCtxt::new(Box::new(emitter)) From d14c9563529f937e72e339671efec0a52d07bbf9 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 15:19:51 -0800 Subject: [PATCH 15/34] Resolve new collapsible-match clippy lints in example runners --- examples/runners/ash/src/main.rs | 20 +++++++++----------- examples/runners/wgpu/src/graphics.rs | 14 ++++++-------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/examples/runners/ash/src/main.rs b/examples/runners/ash/src/main.rs index 61c1aaee92..c83858330f 100644 --- a/examples/runners/ash/src/main.rs +++ b/examples/runners/ash/src/main.rs @@ -202,17 +202,15 @@ pub fn main() -> anyhow::Result<()> { .. } => match key { winit::keyboard::NamedKey::Escape => event_loop_window_target.exit(), - winit::keyboard::NamedKey::F5 => { - if !recompiling_shaders { - recompiling_shaders = true; - let compiler_sender = compiler_sender.clone(); - thread::spawn(move || { - let shader_code = compile_shaders(&options.shader) - .context("Compiling shaders failed") - .unwrap(); - compiler_sender.try_send(shader_code).unwrap(); - }); - } + winit::keyboard::NamedKey::F5 if !recompiling_shaders => { + recompiling_shaders = true; + let compiler_sender = compiler_sender.clone(); + thread::spawn(move || { + let shader_code = compile_shaders(&options.shader) + .context("Compiling shaders failed") + .unwrap(); + compiler_sender.try_send(shader_code).unwrap(); + }); } winit::keyboard::NamedKey::ArrowUp | winit::keyboard::NamedKey::ArrowDown => { diff --git a/examples/runners/wgpu/src/graphics.rs b/examples/runners/wgpu/src/graphics.rs index d241d212ff..73354101f6 100644 --- a/examples/runners/wgpu/src/graphics.rs +++ b/examples/runners/wgpu/src/graphics.rs @@ -262,14 +262,12 @@ async fn run( Event::WindowEvent { event: WindowEvent::Resized(size), .. - } => { - if size.width != 0 && size.height != 0 { - // Recreate the swap chain with the new size - if let Ok((surface, surface_config)) = &mut surface_with_config { - surface_config.width = size.width; - surface_config.height = size.height; - surface.configure(&device, surface_config); - } + } if size.width != 0 && size.height != 0 => { + // Recreate the swap chain with the new size + if let Ok((surface, surface_config)) = &mut surface_with_config { + surface_config.width = size.width; + surface_config.height = size.height; + surface.configure(&device, surface_config); } } Event::WindowEvent { From 14ba846405005736eba34964ee968b7c3958bfa6 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 15:25:39 -0800 Subject: [PATCH 16/34] Guard runtime-array const reification against truncation and ZST tails --- .../src/codegen_cx/constant.rs | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs index 9022283b74..c13c3b25dd 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs @@ -622,7 +622,33 @@ impl<'tcx> CodegenCx<'tcx> { } SpirvType::RuntimeArray { element } => { let stride = self.lookup_type(element).sizeof(self).unwrap(); - let count = (alloc.inner().size() - offset).bytes() / stride.bytes(); + if stride.bytes() == 0 { + let result = self.undef(ty); + self.zombie_no_span( + result.def_cx(self), + &format!( + "unsupported unsized `{}` constant with zero-sized elements", + self.debug_type(ty) + ), + ); + return (result, Size::ZERO); + } + + let read_size = alloc.inner().size() - offset; + let rem = read_size.bytes() % stride.bytes(); + if rem != 0 { + let result = self.undef(ty); + self.zombie_no_span( + result.def_cx(self), + &format!( + "unsupported unsized `{}` constant with {rem} trailing bytes", + self.debug_type(ty) + ), + ); + return (result, read_size); + } + + let count = read_size.bytes() / stride.bytes(); let sized_ty = self.type_array(element, count); let result = self.constant_composite( From bf414e8ba18532bf44f31a46be9a88cffa1d147a Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 15:50:22 -0800 Subject: [PATCH 17/34] Replace fmt::Arguments sentinel metadata with typed constructor tags --- .../src/builder/format_args_decompiler.rs | 90 +++++++++---------- .../src/codegen_cx/declare.rs | 24 +++-- .../rustc_codegen_spirv/src/codegen_cx/mod.rs | 25 +++++- 3 files changed, 78 insertions(+), 61 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs index b479715b11..2d1f0ca3ab 100644 --- a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs +++ b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs @@ -1,6 +1,7 @@ use crate::abi::ConvSpirvType; use crate::builder::Builder; use crate::builder_spirv::{SpirvConst, SpirvValue, SpirvValueExt, SpirvValueKind}; +use crate::codegen_cx::FmtArgsCtor; use crate::custom_insts::CustomOp; use either::Either; use itertools::Itertools; @@ -334,7 +335,16 @@ impl<'tcx> DecodedFormatArgs<'tcx> { }); }; let fmt_args_new_call_insts = try_rev_take(fmt_args_new_call_inst_count).unwrap(); - let (call_args, pieces_len, rt_args_count) = match fmt_args_new_call_insts[..] { + let lookup_fmt_args_ctor = |callee_id| { + cx.fmt_args_new_fn_ids + .borrow() + .get(&callee_id) + .copied() + .ok_or_else(|| { + FormatArgsNotRecognized("fmt::Arguments::new callee not registered".into()) + }) + }; + let (call_args, ctor) = match fmt_args_new_call_insts[..] { [ Inst::Call(call_ret_id, callee_id, ref call_args), Inst::Store(st_dst_id, st_val_id), @@ -345,28 +355,12 @@ impl<'tcx> DecodedFormatArgs<'tcx> { { require_local_var(st_dst_id, "fmt::Arguments::new destination")?; - let Some(&(pieces_len, rt_args_count)) = - cx.fmt_args_new_fn_ids.borrow().get(&callee_id) - else { - return Err(FormatArgsNotRecognized( - "fmt::Arguments::new callee not registered".into(), - )); - }; - - (call_args, pieces_len, rt_args_count) + (call_args.as_slice(), lookup_fmt_args_ctor(callee_id)?) } [Inst::Call(call_ret_id, callee_id, ref call_args)] if call_ret_id == format_args_id => { - let Some(&(pieces_len, rt_args_count)) = - cx.fmt_args_new_fn_ids.borrow().get(&callee_id) - else { - return Err(FormatArgsNotRecognized( - "fmt::Arguments::new callee not registered".into(), - )); - }; - - (call_args, pieces_len, rt_args_count) + (call_args.as_slice(), lookup_fmt_args_ctor(callee_id)?) } [ Inst::Call(call_ret_id, callee_id, ref call_args), @@ -379,15 +373,7 @@ impl<'tcx> DecodedFormatArgs<'tcx> { && inserted0 == inserted0_prev && inserted1 == format_args_id => { - let Some(&(pieces_len, rt_args_count)) = - cx.fmt_args_new_fn_ids.borrow().get(&callee_id) - else { - return Err(FormatArgsNotRecognized( - "fmt::Arguments::new callee not registered".into(), - )); - }; - - (call_args, pieces_len, rt_args_count) + (call_args.as_slice(), lookup_fmt_args_ctor(callee_id)?) } _ => { // HACK(eddyb) this gathers more context before reporting. @@ -406,12 +392,11 @@ impl<'tcx> DecodedFormatArgs<'tcx> { ))); } }; - const FMT_ARGS_FROM_STR_PIECES_LEN: usize = !1; enum PiecesSource { Slice { ptr_id: Word, len: usize }, DirectConstStr([Word; 2]), } - let (pieces_source, (rt_args_slice_ptr_id, rt_args_count)) = match call_args[..] { + let (pieces_source, (rt_args_slice_ptr_id, rt_args_count)) = match (ctor, call_args) { // `::new_v1_formatted` // // HACK(eddyb) this isn't fully supported, @@ -420,14 +405,17 @@ impl<'tcx> DecodedFormatArgs<'tcx> { // but the whole call still needs to be removed, // and both const str pieces and runtime args // can still be printed (even if in jankier way). - [ - pieces_slice_ptr_id, - pieces_len_id, - rt_args_slice_ptr_id, - rt_args_len_id, - fmt_placeholders_slice_ptr_id, - fmt_placeholders_len_id, - ] if (pieces_len, rt_args_count) == (!0, !0) => { + ( + FmtArgsCtor::NewV1FormattedDynamic, + &[ + pieces_slice_ptr_id, + pieces_len_id, + rt_args_slice_ptr_id, + rt_args_len_id, + fmt_placeholders_slice_ptr_id, + fmt_placeholders_len_id, + ], + ) => { let [pieces_len, rt_args_len, fmt_placeholders_len] = match [pieces_len_id, rt_args_len_id, fmt_placeholders_len_id] .map(const_u32_as_usize) @@ -479,17 +467,19 @@ impl<'tcx> DecodedFormatArgs<'tcx> { } // `::from_str` - [str_ptr_id, str_len_id] - if (pieces_len, rt_args_count) == (FMT_ARGS_FROM_STR_PIECES_LEN, 0) => - { - ( - PiecesSource::DirectConstStr([str_ptr_id, str_len_id]), - (None, 0), - ) - } + (FmtArgsCtor::FromStr, &[str_ptr_id, str_len_id]) => ( + PiecesSource::DirectConstStr([str_ptr_id, str_len_id]), + (None, 0), + ), // `::new_v1` - [pieces_slice_ptr_id, rt_args_slice_ptr_id] => ( + ( + FmtArgsCtor::NewV1 { + pieces_len, + rt_args_count, + }, + &[pieces_slice_ptr_id, rt_args_slice_ptr_id], + ) => ( PiecesSource::Slice { ptr_id: pieces_slice_ptr_id, len: pieces_len, @@ -498,17 +488,17 @@ impl<'tcx> DecodedFormatArgs<'tcx> { ), // `::new_const` - [pieces_slice_ptr_id] if rt_args_count == 0 => ( + (FmtArgsCtor::NewConst { pieces_len }, &[pieces_slice_ptr_id]) => ( PiecesSource::Slice { ptr_id: pieces_slice_ptr_id, len: pieces_len, }, - (None, rt_args_count), + (None, 0), ), _ => { return Err(FormatArgsNotRecognized( - "fmt::Arguments::new call args".into(), + "fmt::Arguments::new ctor/call-args mismatch".into(), )); } }; diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs index 4e50e33575..f2aea002e8 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs @@ -1,7 +1,7 @@ // HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; -use super::CodegenCx; +use super::{CodegenCx, FmtArgsCtor}; use crate::abi::ConvSpirvType; use crate::attr::AggregatedSpirvAttributes; use crate::builder_spirv::{SpirvConst, SpirvFunctionCursor, SpirvValue, SpirvValueExt}; @@ -237,9 +237,12 @@ impl<'tcx> CodegenCx<'tcx> { .strip_prefix("::new_const::<") .and_then(|s| s.strip_suffix(">")) { - self.fmt_args_new_fn_ids - .borrow_mut() - .insert(fn_id, (pieces_len.parse().unwrap(), 0)); + self.fmt_args_new_fn_ids.borrow_mut().insert( + fn_id, + FmtArgsCtor::NewConst { + pieces_len: pieces_len.parse().unwrap(), + }, + ); } if let Some(generics) = demangled_symbol_name .strip_prefix("::new_v1::<") @@ -248,18 +251,21 @@ impl<'tcx> CodegenCx<'tcx> { let (pieces_len, rt_args_len) = generics.split_once(", ").unwrap(); self.fmt_args_new_fn_ids.borrow_mut().insert( fn_id, - (pieces_len.parse().unwrap(), rt_args_len.parse().unwrap()), + FmtArgsCtor::NewV1 { + pieces_len: pieces_len.parse().unwrap(), + rt_args_count: rt_args_len.parse().unwrap(), + }, ); } if demangled_symbol_name == "::new_v1_formatted" { - // HACK(eddyb) `!0` used as a placeholder value to indicate "dynamic". self.fmt_args_new_fn_ids .borrow_mut() - .insert(fn_id, (!0, !0)); + .insert(fn_id, FmtArgsCtor::NewV1FormattedDynamic); } if demangled_symbol_name == "::from_str" { - // HACK(eddyb) `!1` distinguishes `from_str` from normal `new_*`. - self.fmt_args_new_fn_ids.borrow_mut().insert(fn_id, (!1, 0)); + self.fmt_args_new_fn_ids + .borrow_mut() + .insert(fn_id, FmtArgsCtor::FromStr); } // HACK(eddyb) there is no good way to identify these definitions diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs index f2f976c6fc..a16d3aa191 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs @@ -43,6 +43,26 @@ use std::path::PathBuf; use std::rc::Rc; use std::str::FromStr; +/// Tags the `core::fmt::Arguments` constructor behind a lowered call. +/// +/// During panic-format decompilation we pattern-match constructor calls to +/// recover `pieces` and runtime argument slices. This enum keeps that matching +/// explicit and type-safe, replacing the old sentinel tuple encoding. +#[derive(Clone, Copy, Debug)] +pub enum FmtArgsCtor { + /// `Arguments::new_const(pieces)`. + NewConst { pieces_len: usize }, + /// `Arguments::new_v1(pieces, args)`. + NewV1 { + pieces_len: usize, + rt_args_count: usize, + }, + /// `Arguments::new_v1_formatted(..)` where lengths come from call operands. + NewV1FormattedDynamic, + /// `Arguments::from_str(s)`. + FromStr, +} + pub struct CodegenCx<'tcx> { pub tcx: TyCtxt<'tcx>, pub codegen_unit: &'tcx CodegenUnit<'tcx>, @@ -73,8 +93,9 @@ pub struct CodegenCx<'tcx> { /// of these lang items, which we always replace with an "abort". pub panic_entry_points: RefCell>, - /// `core::fmt::Arguments::new_{v1,const}` instances (for Rust 2021 panics). - pub fmt_args_new_fn_ids: RefCell>, + /// `core::fmt::Arguments::{new_const,new_v1,new_v1_formatted,from_str}` + /// instances (for Rust 2021 panics). + pub fmt_args_new_fn_ids: RefCell>, /// `core::fmt::rt::Argument::new_*::` instances (for panics' `format_args!`), /// with their `T` type (i.e. of the value being formatted), and formatting From cb223c770dcf51c295986e6bb9596f7001ba6684 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 15:50:33 -0800 Subject: [PATCH 18/34] Gate bounds/precondition panic-entry detection to non-local core symbols --- crates/rustc_codegen_spirv/src/codegen_cx/declare.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs index f2aea002e8..943660d1a6 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs @@ -19,6 +19,7 @@ use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt, TypingEnv}; use rustc_span::Span; use rustc_span::def_id::DefId; +use rustc_span::symbol::sym; fn attrs_to_spirv(attrs: &CodegenFnAttrs) -> FunctionControl { let mut control = FunctionControl::NONE; @@ -227,10 +228,11 @@ impl<'tcx> CodegenCx<'tcx> { { self.panic_entry_points.borrow_mut().insert(def_id); } - if demangled_symbol_name.ends_with("::precondition_check") { + let is_nonlocal_core = !def_id.is_local() && self.tcx.crate_name(def_id.krate) == sym::core; + if is_nonlocal_core && demangled_symbol_name.ends_with("::precondition_check") { self.panic_entry_points.borrow_mut().insert(def_id); } - if demangled_symbol_name.contains("::bounds_check") { + if is_nonlocal_core && demangled_symbol_name.ends_with("::bounds_check") { self.panic_entry_points.borrow_mut().insert(def_id); } if let Some(pieces_len) = demangled_symbol_name From e1591d049401ba3094d156b2d3b9223c34ed1227 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 16:15:22 -0800 Subject: [PATCH 19/34] Fix panic-entry matching and disable-pqp unused-features lint --- crates/rustc_codegen_spirv/src/codegen_cx/declare.rs | 9 +++++++-- crates/rustc_codegen_spirv/src/lib.rs | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs index 943660d1a6..b3a303c5da 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs @@ -228,11 +228,16 @@ impl<'tcx> CodegenCx<'tcx> { { self.panic_entry_points.borrow_mut().insert(def_id); } - let is_nonlocal_core = !def_id.is_local() && self.tcx.crate_name(def_id.krate) == sym::core; + let is_nonlocal = !def_id.is_local(); + let is_nonlocal_core = is_nonlocal && self.tcx.crate_name(def_id.krate) == sym::core; if is_nonlocal_core && demangled_symbol_name.ends_with("::precondition_check") { self.panic_entry_points.borrow_mut().insert(def_id); } - if is_nonlocal_core && demangled_symbol_name.ends_with("::bounds_check") { + let is_spirv_std_byte_addressable_bounds_check = + is_nonlocal && self.tcx.def_path_str(def_id) == "spirv_std::byte_addressable_buffer::bounds_check"; + if (is_nonlocal_core && demangled_symbol_name.ends_with("::bounds_check")) + || is_spirv_std_byte_addressable_bounds_check + { self.panic_entry_points.borrow_mut().insert(def_id); } if let Some(pieces_len) = demangled_symbol_name diff --git a/crates/rustc_codegen_spirv/src/lib.rs b/crates/rustc_codegen_spirv/src/lib.rs index a647fb54ff..306ecf9c84 100644 --- a/crates/rustc_codegen_spirv/src/lib.rs +++ b/crates/rustc_codegen_spirv/src/lib.rs @@ -9,6 +9,7 @@ #![feature(string_from_utf8_lossy_owned)] #![feature(trait_alias)] #![feature(try_blocks)] +#![cfg_attr(rustc_codegen_spirv_disable_pqp_cg_ssa, allow(unused_features))] #![recursion_limit = "256"] // HACK(eddyb) end of `rustc_codegen_ssa` crate-level attributes (see `build.rs`). From 6434ab8f1473662b8dba9d432c990fb1f11f70e4 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 16:15:29 -0800 Subject: [PATCH 20/34] Bless compiletest stderr for updated nightly diagnostics --- .../ui/arch/debug_printf_type_checking.stderr | 22 +- .../subgroup/subgroup_cluster_size_0_fail.rs | 1 + .../subgroup_cluster_size_0_fail.stderr | 31 +- ...roup_cluster_size_non_power_of_two_fail.rs | 1 + ..._cluster_size_non_power_of_two_fail.stderr | 31 +- .../subgroup_composite_enum_err.stderr | 33 +- tests/compiletests/ui/dis/issue-1062.stderr | 2 +- .../ui/dis/panic_builtin_bounds_check.stderr | 86 ++-- .../ui/dis/panic_sequential_many.stderr | 419 +++++++++--------- .../ui/dis/ptr_copy.normal.stderr | 51 +-- tests/compiletests/ui/dis/ptr_read.stderr | 2 +- .../ui/dis/ptr_read_method.stderr | 2 +- tests/compiletests/ui/dis/ptr_write.stderr | 2 +- .../ui/dis/ptr_write_method.stderr | 2 +- .../compiletests/ui/dis/scalars.nocaps.stderr | 18 +- tests/compiletests/ui/image/gather_err.stderr | 90 +--- .../ui/image/query/query_levels_err.stderr | 57 +-- .../ui/image/query/query_lod_err.stderr | 57 +-- .../ui/image/query/query_size_err.stderr | 9 +- .../ui/image/query/query_size_lod_err.stderr | 57 +-- .../consts/nested-ref-in-composite.stderr | 12 +- .../ui/lang/consts/nested-ref.stderr | 4 +- .../ui/lang/consts/u32-from-u64-fail.stderr | 2 +- .../ui/lang/core/intrinsics/black_box.stderr | 2 +- .../core/ref/member_ref_arg-broken.stderr | 8 +- .../ui/lang/core/ref/member_ref_arg.stderr | 4 +- .../core/ref/zst_member_ref_arg-broken.stderr | 54 +-- tests/compiletests/ui/lang/issue-452.stderr | 6 +- 28 files changed, 417 insertions(+), 648 deletions(-) diff --git a/tests/compiletests/ui/arch/debug_printf_type_checking.stderr b/tests/compiletests/ui/arch/debug_printf_type_checking.stderr index 3e753ed396..35e91acb44 100644 --- a/tests/compiletests/ui/arch/debug_printf_type_checking.stderr +++ b/tests/compiletests/ui/arch/debug_printf_type_checking.stderr @@ -75,10 +75,7 @@ LL | debug_printf!("%f", 11_u32); | | | this argument influences the return type of `assert_is_type` note: function defined here - --> $SPIRV_STD_SRC/debug_printf.rs:6:8 - | -LL | pub fn assert_is_type(ty: T) -> T { - | ^^^^^^^^^^^^^^ + --> crates/spirv-std/src/debug_printf.rs:6:7 = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) help: change the type of the numeric literal from `u32` to `f32` | @@ -103,10 +100,7 @@ LL | debug_printf!("%u", 11.0_f32); | | | this argument influences the return type of `assert_is_type` note: function defined here - --> $SPIRV_STD_SRC/debug_printf.rs:6:8 - | -LL | pub fn assert_is_type(ty: T) -> T { - | ^^^^^^^^^^^^^^ + --> crates/spirv-std/src/debug_printf.rs:6:7 = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) help: change the type of the numeric literal from `f32` to `u32` | @@ -130,11 +124,8 @@ LL | debug_printf!("%v2f", 11.0); `IVec2` implements `spirv_std::Vector` `IVec3` implements `spirv_std::Vector` and 8 others -note: required by a bound in `assert_is_vector` - --> $SPIRV_STD_SRC/debug_printf.rs:11:40 - | -LL | pub fn assert_is_vector, const SIZE: usize>(vec: V) -> V { - | ^^^^^^^^^^^^^^^^ required by this bound in `assert_is_vector` +note: required by a bound in `spirv_std::debug_printf::assert_is_vector` + --> crates/spirv-std/src/debug_printf.rs:11:0 = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types @@ -154,10 +145,7 @@ LL | debug_printf!("%f", Vec2::splat(33.3)); | | | this argument influences the return type of `assert_is_type` note: function defined here - --> $SPIRV_STD_SRC/debug_printf.rs:6:8 - | -LL | pub fn assert_is_type(ty: T) -> T { - | ^^^^^^^^^^^^^^ + --> crates/spirv-std/src/debug_printf.rs:6:7 = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 14 previous errors diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.rs b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.rs index 4fec2a3db5..be91429d86 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.rs +++ b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.rs @@ -1,6 +1,7 @@ // build-pass // compile-flags: -C target-feature=+GroupNonUniform,+GroupNonUniformArithmetic,+GroupNonUniformClustered,+ext:SPV_KHR_vulkan_memory_model // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" +// normalize-stderr-test "\S*/lib/rustlib/" -> "$$SYSROOT/lib/rustlib/" use glam::UVec3; use spirv_std::arch::{GroupOperation, SubgroupMask}; diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.stderr index f6e00334ed..b2036d1478 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.stderr +++ b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.stderr @@ -1,33 +1,26 @@ error[E0080]: evaluation panicked: `ClusterSize` must be at least 1 - --> $SPIRV_STD_SRC/arch/subgroup.rs:937:1 + --> $SYSROOT/lib/rustlib/src/rust/library/core/src/panic.rs:62:9 | -LL | / macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r" -LL | | An integer add group operation of all `value` operands contributed by active invocations in the group. -LL | | -LL | | Result Type must be a scalar or vector of integer type. -... | -LL | | * `ClusterSize` must not be greater than the size of the group -LL | | "); - | |__^ evaluation of `spirv_std::arch::subgroup_clustered_i_add::<0, u32, u32>::{constant#0}` failed here +LL | $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `spirv_std::arch::subgroup_clustered_i_add::<0, u32, u32>::{constant#0}` failed here + | + --> crates/spirv-std/src/arch/subgroup.rs:937:0 + ::: crates/spirv-std/src/arch/subgroup.rs:954:2 + | + = note: in this macro invocation | = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `macro_subgroup_op_clustered` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered - --> $SPIRV_STD_SRC/arch/subgroup.rs:937:1 + --> crates/spirv-std/src/arch/subgroup.rs:890:12 + ::: crates/spirv-std/src/arch/subgroup.rs:954:2 | -LL | / macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r" -LL | | An integer add group operation of all `value` operands contributed by active invocations in the group. -LL | | -LL | | Result Type must be a scalar or vector of integer type. -... | -LL | | * `ClusterSize` must not be greater than the size of the group -LL | | "); - | |__^ + = note: in this macro invocation | = note: this note originates in the macro `macro_subgroup_op_clustered` (in Nightly builds, run with -Z macro-backtrace for more info) note: the above error was encountered while instantiating `fn subgroup_clustered_i_add::<0, u32, u32>` - --> $DIR/subgroup_cluster_size_0_fail.rs:10:5 + --> $DIR/subgroup_cluster_size_0_fail.rs:11:5 | LL | spirv_std::arch::subgroup_clustered_i_add::<0, _>(value) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.rs b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.rs index 9184cc25b1..685771fc89 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.rs +++ b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.rs @@ -1,6 +1,7 @@ // build-pass // compile-flags: -C target-feature=+GroupNonUniform,+GroupNonUniformArithmetic,+GroupNonUniformClustered,+ext:SPV_KHR_vulkan_memory_model // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" +// normalize-stderr-test "\S*/lib/rustlib/" -> "$$SYSROOT/lib/rustlib/" use glam::UVec3; use spirv_std::arch::{GroupOperation, SubgroupMask}; diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.stderr index 2ce2568495..9d387e13fd 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.stderr +++ b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.stderr @@ -1,33 +1,26 @@ error[E0080]: evaluation panicked: `ClusterSize` must be a power of 2 - --> $SPIRV_STD_SRC/arch/subgroup.rs:937:1 + --> $SYSROOT/lib/rustlib/src/rust/library/core/src/panic.rs:62:9 | -LL | / macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r" -LL | | An integer add group operation of all `value` operands contributed by active invocations in the group. -LL | | -LL | | Result Type must be a scalar or vector of integer type. -... | -LL | | * `ClusterSize` must not be greater than the size of the group -LL | | "); - | |__^ evaluation of `spirv_std::arch::subgroup_clustered_i_add::<5, u32, u32>::{constant#0}` failed here +LL | $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `spirv_std::arch::subgroup_clustered_i_add::<5, u32, u32>::{constant#0}` failed here + | + --> crates/spirv-std/src/arch/subgroup.rs:937:0 + ::: crates/spirv-std/src/arch/subgroup.rs:954:2 + | + = note: in this macro invocation | = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `macro_subgroup_op_clustered` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered - --> $SPIRV_STD_SRC/arch/subgroup.rs:937:1 + --> crates/spirv-std/src/arch/subgroup.rs:890:12 + ::: crates/spirv-std/src/arch/subgroup.rs:954:2 | -LL | / macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r" -LL | | An integer add group operation of all `value` operands contributed by active invocations in the group. -LL | | -LL | | Result Type must be a scalar or vector of integer type. -... | -LL | | * `ClusterSize` must not be greater than the size of the group -LL | | "); - | |__^ + = note: in this macro invocation | = note: this note originates in the macro `macro_subgroup_op_clustered` (in Nightly builds, run with -Z macro-backtrace for more info) note: the above error was encountered while instantiating `fn subgroup_clustered_i_add::<5, u32, u32>` - --> $DIR/subgroup_cluster_size_non_power_of_two_fail.rs:10:5 + --> $DIR/subgroup_cluster_size_non_power_of_two_fail.rs:11:5 | LL | spirv_std::arch::subgroup_clustered_i_add::<5, _>(value) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_composite_enum_err.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_composite_enum_err.stderr index 174b5d911a..7c4cd4db21 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_composite_enum_err.stderr +++ b/tests/compiletests/ui/arch/subgroup/subgroup_composite_enum_err.stderr @@ -21,35 +21,6 @@ LL | | C, LL | | } | |_^ -error[E0412]: cannot find type `C` in this scope - --> $DIR/subgroup_composite_enum_err.rs: - | -LL | #[repr(C)] - | ^ -LL | #[derive(Copy, Clone, Default, ScalarComposite)] - | --------------- similarly named type parameter `F` defined here - | -help: there is an enum variant `crate::CRepr::C` and 6 others; try using the variant's enum - | -LL - #[repr(C)] -LL + #[repr(crate::CRepr)] - | -LL - #[repr(C)] -LL + #[repr(crate::NoDefault)] - | -LL - #[repr(C)] -LL + #[repr(crate::NoFrom)] - | -LL - #[repr(C)] -LL + #[repr(crate::NoRepr)] - | - = and 2 other candidates -help: a type parameter with a similar name exists - | -LL - #[repr(C)] -LL + #[repr(F)] - | - error[E0566]: conflicting representation hints --> $DIR/subgroup_composite_enum_err.rs: | @@ -142,7 +113,7 @@ LL | enum_repr_from!(NoDefault, i32); candidate #1: `Default` = note: this error originates in the macro `enum_repr_from` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors -Some errors have detailed explanations: E0277, E0412, E0566, E0599. +Some errors have detailed explanations: E0277, E0566, E0599. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/compiletests/ui/dis/issue-1062.stderr b/tests/compiletests/ui/dis/issue-1062.stderr index 9a72a047cb..d2c69d4d0e 100644 --- a/tests/compiletests/ui/dis/issue-1062.stderr +++ b/tests/compiletests/ui/dis/issue-1062.stderr @@ -4,7 +4,7 @@ OpLine %5 11 12 %6 = OpLoad %7 %8 OpLine %5 11 35 %9 = OpLoad %7 %10 -OpLine %11 1134 4 +OpLine %11 1243 4 %12 = OpBitwiseAnd %7 %9 %13 %14 = OpISub %7 %15 %12 %16 = OpShiftLeftLogical %7 %6 %12 diff --git a/tests/compiletests/ui/dis/panic_builtin_bounds_check.stderr b/tests/compiletests/ui/dis/panic_builtin_bounds_check.stderr index 6486f832eb..5b014aff8f 100644 --- a/tests/compiletests/ui/dis/panic_builtin_bounds_check.stderr +++ b/tests/compiletests/ui/dis/panic_builtin_bounds_check.stderr @@ -4,53 +4,53 @@ OpExtension "SPV_KHR_non_semantic_info" OpMemoryModel Logical Simple OpEntryPoint Fragment %2 "main" OpExecutionMode %2 OriginUpperLeft -%3 = OpString "/n[Rust panicked at $SYSROOT/lib/rustlib/src/rust/library/core/src/panicking.rs:276:5]/n index out of bounds: the len is %u but the index is %u/n in main()/n" -%4 = OpString $SYSROOT/lib/rustlib/src/rust/library/core/src/panicking.rs" -%5 = OpString "$DIR/panic_builtin_bounds_check.rs" -OpDecorate %6 ArrayStride 4 -%7 = OpTypeVoid -%8 = OpTypeFunction %7 -%9 = OpTypeInt 32 0 -%10 = OpConstant %9 4 -%11 = OpTypeArray %9 %10 -%12 = OpTypePointer Function %11 -%6 = OpTypeArray %9 %10 -%13 = OpConstant %9 0 -%14 = OpConstant %9 1 -%15 = OpConstant %9 2 -%16 = OpConstant %9 3 -%17 = OpTypeBool -%18 = OpConstant %9 5 -%19 = OpTypePointer Function %9 -%2 = OpFunction %7 None %8 -%20 = OpLabel -OpLine %5 32 4 -%21 = OpVariable %12 Function -OpLine %5 32 23 -%22 = OpCompositeConstruct %6 %13 %14 %15 %16 -OpLine %5 27 4 -%23 = OpCompositeExtract %9 %22 0 -%24 = OpCompositeExtract %9 %22 1 -%25 = OpCompositeExtract %9 %22 2 -%26 = OpCompositeExtract %9 %22 3 -%27 = OpCompositeConstruct %11 %23 %24 %25 %26 -OpStore %21 %27 -%28 = OpULessThan %17 %18 %10 +%3 = OpString "/n[Rust panicked at $DIR/panic_builtin_bounds_check.rs:27:5]/n (failed to find/decode `format_args!` expansion)/n in main()/n" +%4 = OpString "$DIR/panic_builtin_bounds_check.rs" +OpDecorate %5 ArrayStride 4 +%6 = OpTypeVoid +%7 = OpTypeFunction %6 +%8 = OpTypeInt 32 0 +%9 = OpConstant %8 4 +%10 = OpTypeArray %8 %9 +%11 = OpTypePointer Function %10 +%5 = OpTypeArray %8 %9 +%12 = OpConstant %8 0 +%13 = OpConstant %8 1 +%14 = OpConstant %8 2 +%15 = OpConstant %8 3 +%16 = OpTypeBool +%17 = OpConstant %8 5 +%18 = OpTypePointer Function %8 +%2 = OpFunction %6 None %7 +%19 = OpLabel +OpLine %4 32 4 +%20 = OpVariable %11 Function +OpLine %4 32 23 +%21 = OpCompositeConstruct %5 %12 %13 %14 %15 +OpLine %4 32 4 +%22 = OpCompositeExtract %8 %21 0 +%23 = OpCompositeExtract %8 %21 1 +%24 = OpCompositeExtract %8 %21 2 +%25 = OpCompositeExtract %8 %21 3 +%26 = OpCompositeConstruct %10 %22 %23 %24 %25 +OpStore %20 %26 +OpLine %4 27 4 +%27 = OpULessThan %16 %17 %9 OpNoLine -OpSelectionMerge %29 None -OpBranchConditional %28 %30 %31 +OpSelectionMerge %28 None +OpBranchConditional %27 %29 %30 +%29 = OpLabel +OpBranch %28 %30 = OpLabel -OpBranch %29 -%31 = OpLabel -OpLine %4 276 4 -%32 = OpExtInst %7 %1 1 %3 %10 %18 +OpLine %4 27 4 +%31 = OpExtInst %6 %1 1 %3 OpNoLine OpReturn -%29 = OpLabel -OpLine %5 27 4 -%33 = OpIAdd %9 %13 %18 -%34 = OpInBoundsAccessChain %19 %21 %33 -%35 = OpLoad %9 %34 +%28 = OpLabel +OpLine %4 27 4 +%32 = OpIAdd %8 %12 %17 +%33 = OpInBoundsAccessChain %18 %20 %32 +%34 = OpLoad %8 %33 OpNoLine OpReturn OpFunctionEnd diff --git a/tests/compiletests/ui/dis/panic_sequential_many.stderr b/tests/compiletests/ui/dis/panic_sequential_many.stderr index ffe854c6fe..4c37429d15 100644 --- a/tests/compiletests/ui/dis/panic_sequential_many.stderr +++ b/tests/compiletests/ui/dis/panic_sequential_many.stderr @@ -4,9 +4,8 @@ OpExtension "SPV_KHR_non_semantic_info" OpMemoryModel Logical Simple OpEntryPoint Fragment %2 "main" %3 %4 %5 OpExecutionMode %2 OriginUpperLeft -%6 = OpString "/n[Rust panicked at $SYSROOT/lib/rustlib/src/rust/library/core/src/panicking.rs:192:5]/n attempt to divide by zero/n in main()/n" -%7 = OpString $SYSROOT/lib/rustlib/src/rust/library/core/src/panicking.rs" -%8 = OpString "$DIR/panic_sequential_many.rs" +%6 = OpString "/n[Rust panicked at $DIR/panic_sequential_many.rs:31:10]/n explicit panic/n in main()/n" +%7 = OpString "$DIR/panic_sequential_many.rs" OpName %3 "x" OpName %4 "y" OpName %5 "o" @@ -15,262 +14,262 @@ OpDecorate %3 Location 0 OpDecorate %4 Flat OpDecorate %4 Location 1 OpDecorate %5 Location 0 -%9 = OpTypeInt 32 0 -%10 = OpTypePointer Input %9 -%11 = OpTypePointer Output %9 -%12 = OpTypeVoid -%13 = OpTypeFunction %12 -%3 = OpVariable %10 Input -%4 = OpVariable %10 Input -%14 = OpTypeBool -%15 = OpConstant %9 0 -%5 = OpVariable %11 Output -%2 = OpFunction %12 None %13 -%16 = OpLabel -OpLine %8 28 12 -%17 = OpLoad %9 %3 -OpLine %8 28 35 -%18 = OpLoad %9 %4 -OpLine %8 31 9 -%19 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %20 None -OpBranchConditional %19 %21 %22 -%21 = OpLabel -OpLine %7 192 4 -%23 = OpExtInst %12 %1 1 %6 -OpNoLine -OpReturn -%22 = OpLabel -OpBranch %20 +%8 = OpTypeInt 32 0 +%9 = OpTypePointer Input %8 +%10 = OpTypePointer Output %8 +%11 = OpTypeVoid +%12 = OpTypeFunction %11 +%3 = OpVariable %9 Input +%4 = OpVariable %9 Input +%13 = OpTypeBool +%14 = OpConstant %8 0 +%5 = OpVariable %10 Output +%2 = OpFunction %11 None %12 +%15 = OpLabel +OpLine %7 28 12 +%16 = OpLoad %8 %3 +OpLine %7 28 35 +%17 = OpLoad %8 %4 +OpLine %7 31 9 +%18 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %19 None +OpBranchConditional %18 %20 %21 %20 = OpLabel -OpLine %8 31 9 -%24 = OpUDiv %9 %17 %18 -%25 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %26 None -OpBranchConditional %25 %27 %28 -%27 = OpLabel -OpLine %7 192 4 -%29 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%22 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%28 = OpLabel -OpBranch %26 +%21 = OpLabel +OpBranch %19 +%19 = OpLabel +OpLine %7 31 9 +%23 = OpUDiv %8 %16 %17 +%24 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %25 None +OpBranchConditional %24 %26 %27 %26 = OpLabel -OpLine %8 31 9 -%30 = OpUDiv %9 %24 %18 -%31 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %32 None -OpBranchConditional %31 %33 %34 -%33 = OpLabel -OpLine %7 192 4 -%35 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%28 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%34 = OpLabel -OpBranch %32 +%27 = OpLabel +OpBranch %25 +%25 = OpLabel +OpLine %7 31 9 +%29 = OpUDiv %8 %23 %17 +%30 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %31 None +OpBranchConditional %30 %32 %33 %32 = OpLabel -OpLine %8 31 9 -%36 = OpUDiv %9 %30 %18 -%37 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %38 None -OpBranchConditional %37 %39 %40 -%39 = OpLabel -OpLine %7 192 4 -%41 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%34 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%40 = OpLabel -OpBranch %38 +%33 = OpLabel +OpBranch %31 +%31 = OpLabel +OpLine %7 31 9 +%35 = OpUDiv %8 %29 %17 +%36 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %37 None +OpBranchConditional %36 %38 %39 %38 = OpLabel -OpLine %8 31 9 -%42 = OpUDiv %9 %36 %18 -%43 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %44 None -OpBranchConditional %43 %45 %46 -%45 = OpLabel -OpLine %7 192 4 -%47 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%40 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%46 = OpLabel -OpBranch %44 +%39 = OpLabel +OpBranch %37 +%37 = OpLabel +OpLine %7 31 9 +%41 = OpUDiv %8 %35 %17 +%42 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %43 None +OpBranchConditional %42 %44 %45 %44 = OpLabel -OpLine %8 31 9 -%48 = OpUDiv %9 %42 %18 -%49 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %50 None -OpBranchConditional %49 %51 %52 -%51 = OpLabel -OpLine %7 192 4 -%53 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%46 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%52 = OpLabel -OpBranch %50 +%45 = OpLabel +OpBranch %43 +%43 = OpLabel +OpLine %7 31 9 +%47 = OpUDiv %8 %41 %17 +%48 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %49 None +OpBranchConditional %48 %50 %51 %50 = OpLabel -OpLine %8 31 9 -%54 = OpUDiv %9 %48 %18 -%55 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %56 None -OpBranchConditional %55 %57 %58 -%57 = OpLabel -OpLine %7 192 4 -%59 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%52 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%58 = OpLabel -OpBranch %56 +%51 = OpLabel +OpBranch %49 +%49 = OpLabel +OpLine %7 31 9 +%53 = OpUDiv %8 %47 %17 +%54 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %55 None +OpBranchConditional %54 %56 %57 %56 = OpLabel -OpLine %8 31 9 -%60 = OpUDiv %9 %54 %18 -%61 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %62 None -OpBranchConditional %61 %63 %64 -%63 = OpLabel -OpLine %7 192 4 -%65 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%58 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%64 = OpLabel -OpBranch %62 +%57 = OpLabel +OpBranch %55 +%55 = OpLabel +OpLine %7 31 9 +%59 = OpUDiv %8 %53 %17 +%60 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %61 None +OpBranchConditional %60 %62 %63 %62 = OpLabel -OpLine %8 31 9 -%66 = OpUDiv %9 %60 %18 -%67 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %68 None -OpBranchConditional %67 %69 %70 -%69 = OpLabel -OpLine %7 192 4 -%71 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%64 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%70 = OpLabel -OpBranch %68 +%63 = OpLabel +OpBranch %61 +%61 = OpLabel +OpLine %7 31 9 +%65 = OpUDiv %8 %59 %17 +%66 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %67 None +OpBranchConditional %66 %68 %69 %68 = OpLabel -OpLine %8 31 9 -%72 = OpUDiv %9 %66 %18 -%73 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %74 None -OpBranchConditional %73 %75 %76 -%75 = OpLabel -OpLine %7 192 4 -%77 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%70 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%76 = OpLabel -OpBranch %74 +%69 = OpLabel +OpBranch %67 +%67 = OpLabel +OpLine %7 31 9 +%71 = OpUDiv %8 %65 %17 +%72 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %73 None +OpBranchConditional %72 %74 %75 %74 = OpLabel -OpLine %8 31 9 -%78 = OpUDiv %9 %72 %18 -%79 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %80 None -OpBranchConditional %79 %81 %82 -%81 = OpLabel -OpLine %7 192 4 -%83 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%76 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%82 = OpLabel -OpBranch %80 +%75 = OpLabel +OpBranch %73 +%73 = OpLabel +OpLine %7 31 9 +%77 = OpUDiv %8 %71 %17 +%78 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %79 None +OpBranchConditional %78 %80 %81 %80 = OpLabel -OpLine %8 31 9 -%84 = OpUDiv %9 %78 %18 -%85 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %86 None -OpBranchConditional %85 %87 %88 -%87 = OpLabel -OpLine %7 192 4 -%89 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%82 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%88 = OpLabel -OpBranch %86 +%81 = OpLabel +OpBranch %79 +%79 = OpLabel +OpLine %7 31 9 +%83 = OpUDiv %8 %77 %17 +%84 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %85 None +OpBranchConditional %84 %86 %87 %86 = OpLabel -OpLine %8 31 9 -%90 = OpUDiv %9 %84 %18 -%91 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %92 None -OpBranchConditional %91 %93 %94 -%93 = OpLabel -OpLine %7 192 4 -%95 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%88 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%94 = OpLabel -OpBranch %92 +%87 = OpLabel +OpBranch %85 +%85 = OpLabel +OpLine %7 31 9 +%89 = OpUDiv %8 %83 %17 +%90 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %91 None +OpBranchConditional %90 %92 %93 %92 = OpLabel -OpLine %8 31 9 -%96 = OpUDiv %9 %90 %18 -%97 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %98 None -OpBranchConditional %97 %99 %100 -%99 = OpLabel -OpLine %7 192 4 -%101 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%94 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%100 = OpLabel -OpBranch %98 +%93 = OpLabel +OpBranch %91 +%91 = OpLabel +OpLine %7 31 9 +%95 = OpUDiv %8 %89 %17 +%96 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %97 None +OpBranchConditional %96 %98 %99 %98 = OpLabel -OpLine %8 31 9 -%102 = OpUDiv %9 %96 %18 -%103 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %104 None -OpBranchConditional %103 %105 %106 -%105 = OpLabel -OpLine %7 192 4 -%107 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%100 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%106 = OpLabel -OpBranch %104 +%99 = OpLabel +OpBranch %97 +%97 = OpLabel +OpLine %7 31 9 +%101 = OpUDiv %8 %95 %17 +%102 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %103 None +OpBranchConditional %102 %104 %105 %104 = OpLabel -OpLine %8 31 9 -%108 = OpUDiv %9 %102 %18 -%109 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %110 None -OpBranchConditional %109 %111 %112 -%111 = OpLabel -OpLine %7 192 4 -%113 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%106 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%112 = OpLabel -OpBranch %110 +%105 = OpLabel +OpBranch %103 +%103 = OpLabel +OpLine %7 31 9 +%107 = OpUDiv %8 %101 %17 +%108 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %109 None +OpBranchConditional %108 %110 %111 %110 = OpLabel -OpLine %8 31 9 -%114 = OpUDiv %9 %108 %18 -%115 = OpIEqual %14 %18 %15 -OpNoLine -OpSelectionMerge %116 None -OpBranchConditional %115 %117 %118 -%117 = OpLabel -OpLine %7 192 4 -%119 = OpExtInst %12 %1 1 %6 +OpLine %7 31 9 +%112 = OpExtInst %11 %1 1 %6 OpNoLine OpReturn -%118 = OpLabel -OpBranch %116 +%111 = OpLabel +OpBranch %109 +%109 = OpLabel +OpLine %7 31 9 +%113 = OpUDiv %8 %107 %17 +%114 = OpIEqual %13 %17 %14 +OpNoLine +OpSelectionMerge %115 None +OpBranchConditional %114 %116 %117 %116 = OpLabel -OpLine %8 31 4 -%120 = OpUDiv %9 %114 %18 -OpStore %5 %120 +OpLine %7 31 9 +%118 = OpExtInst %11 %1 1 %6 +OpNoLine +OpReturn +%117 = OpLabel +OpBranch %115 +%115 = OpLabel +OpLine %7 31 4 +%119 = OpUDiv %8 %113 %17 +OpStore %5 %119 OpNoLine OpReturn OpFunctionEnd diff --git a/tests/compiletests/ui/dis/ptr_copy.normal.stderr b/tests/compiletests/ui/dis/ptr_copy.normal.stderr index fd9b231031..4061062671 100644 --- a/tests/compiletests/ui/dis/ptr_copy.normal.stderr +++ b/tests/compiletests/ui/dis/ptr_copy.normal.stderr @@ -1,68 +1,29 @@ error: cannot memcpy dynamically sized data - --> $CORE_SRC/ptr/mod.rs:638:9 + --> $CORE_SRC/ptr/mod.rs>:642:9 | LL | crate::intrinsics::copy(src, dst, count) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: used from within `core::ptr::copy::` - --> $CORE_SRC/ptr/mod.rs:623:21 + --> $CORE_SRC/ptr/mod.rs>:627:21 | LL | pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { | ^^^^ note: called by `ptr_copy::copy_via_raw_ptr` - --> $DIR/ptr_copy.rs:28:18 + --> <$DIR/ptr_copy.rs>:28:18 | LL | unsafe { core::ptr::copy(src, dst, 1) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: called by `ptr_copy::main` - --> $DIR/ptr_copy.rs:33:5 + --> <$DIR/ptr_copy.rs>:33:5 | LL | copy_via_raw_ptr(&i, o); | ^^^^^^^^^^^^^^^^^^^^^^^ note: called by `main` - --> $DIR/ptr_copy.rs:32:8 + --> <$DIR/ptr_copy.rs>:32:8 | LL | pub fn main(i: f32, o: &mut f32) { | ^^^^ -error: cannot cast between pointer types - from `*f32` - to `*struct () { }` - --> $CORE_SRC/ptr/mod.rs:626:9 - | -LL | / ub_checks::assert_unsafe_precondition!( -LL | | check_language_ub, -LL | | "ptr::copy requires that both pointer arguments are aligned and non-null", -... | -LL | | && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) -LL | | ); - | |_________^ - | -note: used from within `core::ptr::copy::` - --> $CORE_SRC/ptr/mod.rs:626:9 - | -LL | / ub_checks::assert_unsafe_precondition!( -LL | | check_language_ub, -LL | | "ptr::copy requires that both pointer arguments are aligned and non-null", -... | -LL | | && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) -LL | | ); - | |_________^ -note: called by `ptr_copy::copy_via_raw_ptr` - --> $DIR/ptr_copy.rs:28:18 - | -LL | unsafe { core::ptr::copy(src, dst, 1) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: called by `ptr_copy::main` - --> $DIR/ptr_copy.rs:33:5 - | -LL | copy_via_raw_ptr(&i, o); - | ^^^^^^^^^^^^^^^^^^^^^^^ -note: called by `main` - --> $DIR/ptr_copy.rs:32:8 - | -LL | pub fn main(i: f32, o: &mut f32) { - | ^^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/compiletests/ui/dis/ptr_read.stderr b/tests/compiletests/ui/dis/ptr_read.stderr index 9ddcc0dd96..cc38b41e3d 100644 --- a/tests/compiletests/ui/dis/ptr_read.stderr +++ b/tests/compiletests/ui/dis/ptr_read.stderr @@ -2,7 +2,7 @@ %4 = OpFunctionParameter %5 %6 = OpFunctionParameter %5 %7 = OpLabel -OpLine %8 1744 8 +OpLine %8 1720 8 %9 = OpLoad %10 %4 OpLine %11 7 13 OpStore %6 %9 diff --git a/tests/compiletests/ui/dis/ptr_read_method.stderr b/tests/compiletests/ui/dis/ptr_read_method.stderr index 9ddcc0dd96..cc38b41e3d 100644 --- a/tests/compiletests/ui/dis/ptr_read_method.stderr +++ b/tests/compiletests/ui/dis/ptr_read_method.stderr @@ -2,7 +2,7 @@ %4 = OpFunctionParameter %5 %6 = OpFunctionParameter %5 %7 = OpLabel -OpLine %8 1744 8 +OpLine %8 1720 8 %9 = OpLoad %10 %4 OpLine %11 7 13 OpStore %6 %9 diff --git a/tests/compiletests/ui/dis/ptr_write.stderr b/tests/compiletests/ui/dis/ptr_write.stderr index 3b8503a01c..2efd1f59fa 100644 --- a/tests/compiletests/ui/dis/ptr_write.stderr +++ b/tests/compiletests/ui/dis/ptr_write.stderr @@ -4,7 +4,7 @@ %7 = OpLabel OpLine %8 7 35 %9 = OpLoad %10 %4 -OpLine %11 1944 8 +OpLine %11 1920 40 OpStore %6 %9 OpNoLine OpReturn diff --git a/tests/compiletests/ui/dis/ptr_write_method.stderr b/tests/compiletests/ui/dis/ptr_write_method.stderr index c9dcea78f4..296a00f49f 100644 --- a/tests/compiletests/ui/dis/ptr_write_method.stderr +++ b/tests/compiletests/ui/dis/ptr_write_method.stderr @@ -4,7 +4,7 @@ %7 = OpLabel OpLine %8 7 37 %9 = OpLoad %10 %4 -OpLine %11 1944 8 +OpLine %11 1920 40 OpStore %6 %9 OpNoLine OpReturn diff --git a/tests/compiletests/ui/dis/scalars.nocaps.stderr b/tests/compiletests/ui/dis/scalars.nocaps.stderr index f537b2c338..6d368d723a 100644 --- a/tests/compiletests/ui/dis/scalars.nocaps.stderr +++ b/tests/compiletests/ui/dis/scalars.nocaps.stderr @@ -1,7 +1,7 @@ error: `u8` type used without `OpCapability Int8` | note: used from within Fragment entry-point `main` - --> $DIR/scalars.rs:25:5 + --> <$DIR/scalars.rs>:25:5 | LL | #[spirv(flat)] in_u8: u8, | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | #[spirv(flat)] in_u8: u8, error: `u16` type used without `OpCapability Int16` | note: used from within Fragment entry-point `main` - --> $DIR/scalars.rs:26:5 + --> <$DIR/scalars.rs>:26:5 | LL | #[spirv(flat)] in_u16: u16, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | #[spirv(flat)] in_u16: u16, error: `u64` type used without `OpCapability Int64` | note: used from within Fragment entry-point `main` - --> $DIR/scalars.rs:28:5 + --> <$DIR/scalars.rs>:28:5 | LL | #[spirv(flat)] in_u64: u64, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | #[spirv(flat)] in_u64: u64, error: `u128` type unsupported in SPIR-V | note: used from within Fragment entry-point `main` - --> $DIR/scalars.rs:30:5 + --> <$DIR/scalars.rs>:30:5 | LL | / #[cfg(not(supported))] LL | | #[spirv(flat)] @@ -35,7 +35,7 @@ LL | | in_u128: u128, error: `i8` type used without `OpCapability Int8` | note: used from within Fragment entry-point `main` - --> $DIR/scalars.rs:34:5 + --> <$DIR/scalars.rs>:34:5 | LL | #[spirv(flat)] in_i8: i8, | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | #[spirv(flat)] in_i8: i8, error: `i16` type used without `OpCapability Int16` | note: used from within Fragment entry-point `main` - --> $DIR/scalars.rs:35:5 + --> <$DIR/scalars.rs>:35:5 | LL | #[spirv(flat)] in_i16: i16, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | #[spirv(flat)] in_i16: i16, error: `i64` type used without `OpCapability Int64` | note: used from within Fragment entry-point `main` - --> $DIR/scalars.rs:37:5 + --> <$DIR/scalars.rs>:37:5 | LL | #[spirv(flat)] in_i64: i64, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -59,7 +59,7 @@ LL | #[spirv(flat)] in_i64: i64, error: `i128` type unsupported in SPIR-V | note: used from within Fragment entry-point `main` - --> $DIR/scalars.rs:39:5 + --> <$DIR/scalars.rs>:39:5 | LL | / #[cfg(not(supported))] LL | | #[spirv(flat)] @@ -69,7 +69,7 @@ LL | | in_i128: i128, error: `f64` type used without `OpCapability Float64` | note: used from within Fragment entry-point `main` - --> $DIR/scalars.rs:44:5 + --> <$DIR/scalars.rs>:44:5 | LL | #[spirv(flat)] in_f64: f64, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/compiletests/ui/image/gather_err.stderr b/tests/compiletests/ui/image/gather_err.stderr index 966acd413f..d1ca9781c6 100644 --- a/tests/compiletests/ui/image/gather_err.stderr +++ b/tests/compiletests/ui/image/gather_err.stderr @@ -5,42 +5,19 @@ LL | let r1: glam::Vec4 = image1d.gather(*sampler, 0.0f32, 0); | ^^^^^^ the trait `HasGather` is not implemented for `Image` | help: the following other types implement trait `HasGather` - --> $SPIRV_STD_SRC/image.rs:1652:1 + --> crates/spirv-std/src/image.rs:1652:0 + ::: crates/spirv-std/src/image.rs:1669:5 | -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -note: required by a bound in `Image::::gather` - --> $SPIRV_STD_SRC/image.rs:200:15 + = note: `Image` + ::: crates/spirv-std/src/image.rs:1689:5 + | + = note: `Image` + ::: crates/spirv-std/src/image.rs:1709:5 | -LL | pub fn gather( - | ------ required by a bound in this associated function -... -LL | Self: HasGather, - | ^^^^^^^^^ required by this bound in `Image::::gather` + = note: `Image` +note: required by a bound in `Image::::gather` + --> crates/spirv-std/src/image.rs:190:4 + = note: this error originates in the attribute macro `crate::macros::gpu_only` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Image: HasGather` is not satisfied --> $DIR/gather_err.rs:16:34 @@ -49,42 +26,19 @@ LL | let r2: glam::Vec4 = image3d.gather(*sampler, v3, 0); | ^^^^^^ the trait `HasGather` is not implemented for `Image` | help: the following other types implement trait `HasGather` - --> $SPIRV_STD_SRC/image.rs:1652:1 + --> crates/spirv-std/src/image.rs:1652:0 + ::: crates/spirv-std/src/image.rs:1669:5 | -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -note: required by a bound in `Image::::gather` - --> $SPIRV_STD_SRC/image.rs:200:15 + = note: `Image` + ::: crates/spirv-std/src/image.rs:1689:5 + | + = note: `Image` + ::: crates/spirv-std/src/image.rs:1709:5 | -LL | pub fn gather( - | ------ required by a bound in this associated function -... -LL | Self: HasGather, - | ^^^^^^^^^ required by this bound in `Image::::gather` + = note: `Image` +note: required by a bound in `Image::::gather` + --> crates/spirv-std/src/image.rs:190:4 + = note: this error originates in the attribute macro `crate::macros::gpu_only` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/compiletests/ui/image/query/query_levels_err.stderr b/tests/compiletests/ui/image/query/query_levels_err.stderr index 366003fbf3..7f86ab980e 100644 --- a/tests/compiletests/ui/image/query/query_levels_err.stderr +++ b/tests/compiletests/ui/image/query/query_levels_err.stderr @@ -5,51 +5,22 @@ LL | *output = image.query_levels(); | ^^^^^^^^^^^^ the trait `HasQueryLevels` is not implemented for `Image` | help: the following other types implement trait `HasQueryLevels` - --> $SPIRV_STD_SRC/image.rs:1718:1 + --> crates/spirv-std/src/image.rs:1718:0 + ::: crates/spirv-std/src/image.rs:1736:5 | -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -note: required by a bound in `Image::::query_levels` - --> $SPIRV_STD_SRC/image.rs:971:15 + = note: `Image` + ::: crates/spirv-std/src/image.rs:1757:5 + | + = note: `Image` + ::: crates/spirv-std/src/image.rs:1778:5 | -LL | pub fn query_levels(&self) -> u32 - | ------------ required by a bound in this associated function -LL | where -LL | Self: HasQueryLevels, - | ^^^^^^^^^^^^^^ required by this bound in `Image::::query_levels` + = note: `Image` + ::: crates/spirv-std/src/image.rs:1799:5 + | + = note: `Image` +note: required by a bound in `Image::::query_levels` + --> crates/spirv-std/src/image.rs:966:4 + = note: this error originates in the attribute macro `crate::macros::gpu_only` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/compiletests/ui/image/query/query_lod_err.stderr b/tests/compiletests/ui/image/query/query_lod_err.stderr index c82125f949..eec51e82e8 100644 --- a/tests/compiletests/ui/image/query/query_lod_err.stderr +++ b/tests/compiletests/ui/image/query/query_lod_err.stderr @@ -5,51 +5,22 @@ LL | *output = image.query_lod(*sampler, glam::Vec2::new(0.0, 1.0)); | ^^^^^^^^^ the trait `HasQueryLevels` is not implemented for `Image` | help: the following other types implement trait `HasQueryLevels` - --> $SPIRV_STD_SRC/image.rs:1718:1 + --> crates/spirv-std/src/image.rs:1718:0 + ::: crates/spirv-std/src/image.rs:1736:5 | -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -note: required by a bound in `Image::::query_lod` - --> $SPIRV_STD_SRC/image.rs:1001:15 + = note: `Image` + ::: crates/spirv-std/src/image.rs:1757:5 + | + = note: `Image` + ::: crates/spirv-std/src/image.rs:1778:5 | -LL | pub fn query_lod( - | --------- required by a bound in this associated function -... -LL | Self: HasQueryLevels, - | ^^^^^^^^^^^^^^ required by this bound in `Image::::query_lod` + = note: `Image` + ::: crates/spirv-std/src/image.rs:1799:5 + | + = note: `Image` +note: required by a bound in `Image::::query_lod` + --> crates/spirv-std/src/image.rs:992:4 + = note: this error originates in the attribute macro `crate::macros::gpu_only` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/compiletests/ui/image/query/query_size_err.stderr b/tests/compiletests/ui/image/query/query_size_err.stderr index 65344f467a..2fc76db3d5 100644 --- a/tests/compiletests/ui/image/query/query_size_err.stderr +++ b/tests/compiletests/ui/image/query/query_size_err.stderr @@ -15,13 +15,8 @@ LL | *output = image.query_size(); Image and 6 others note: required by a bound in `Image::::query_size` - --> $SPIRV_STD_SRC/image.rs:1037:15 - | -LL | pub fn query_size + Default>(&self) -> Size - | ---------- required by a bound in this associated function -LL | where -LL | Self: HasQuerySize, - | ^^^^^^^^^^^^ required by this bound in `Image::::query_size` + --> crates/spirv-std/src/image.rs:1032:4 + = note: this error originates in the attribute macro `crate::macros::gpu_only` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/compiletests/ui/image/query/query_size_lod_err.stderr b/tests/compiletests/ui/image/query/query_size_lod_err.stderr index 2edffece1d..734631bae3 100644 --- a/tests/compiletests/ui/image/query/query_size_lod_err.stderr +++ b/tests/compiletests/ui/image/query/query_size_lod_err.stderr @@ -5,51 +5,22 @@ LL | *output = image.query_size_lod(0); | ^^^^^^^^^^^^^^ the trait `HasQuerySizeLod` is not implemented for `Image` | help: the following other types implement trait `HasQuerySizeLod` - --> $SPIRV_STD_SRC/image.rs:2089:1 + --> crates/spirv-std/src/image.rs:2089:0 + ::: crates/spirv-std/src/image.rs:2106:5 | -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -note: required by a bound in `Image::::query_size_lod` - --> $SPIRV_STD_SRC/image.rs:1084:15 + = note: `Image` + ::: crates/spirv-std/src/image.rs:2126:5 + | + = note: `Image` + ::: crates/spirv-std/src/image.rs:2146:5 | -LL | pub fn query_size_lod + Default>( - | -------------- required by a bound in this associated function -... -LL | Self: HasQuerySizeLod, - | ^^^^^^^^^^^^^^^ required by this bound in `Image::::query_size_lod` + = note: `Image` + ::: crates/spirv-std/src/image.rs:2166:5 + | + = note: `Image` +note: required by a bound in `Image::::query_size_lod` + --> crates/spirv-std/src/image.rs:1076:4 + = note: this error originates in the attribute macro `crate::macros::gpu_only` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/compiletests/ui/lang/consts/nested-ref-in-composite.stderr b/tests/compiletests/ui/lang/consts/nested-ref-in-composite.stderr index b2da8063b8..3786719887 100644 --- a/tests/compiletests/ui/lang/consts/nested-ref-in-composite.stderr +++ b/tests/compiletests/ui/lang/consts/nested-ref-in-composite.stderr @@ -1,33 +1,33 @@ error: constant arrays/structs cannot contain pointers to other constants - --> $DIR/nested-ref-in-composite.rs:25:19 + --> <$DIR/nested-ref-in-composite.rs>:25:19 | LL | *array3_out = array3_deep_load(&[&0, &1, &2]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: used from within `nested_ref_in_composite::main_array3` - --> $DIR/nested-ref-in-composite.rs:25:19 + --> <$DIR/nested-ref-in-composite.rs>:25:19 | LL | *array3_out = array3_deep_load(&[&0, &1, &2]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: called by `main_array3` - --> $DIR/nested-ref-in-composite.rs:24:8 + --> <$DIR/nested-ref-in-composite.rs>:24:8 | LL | pub fn main_array3(array3_out: &mut [u32; 3]) { | ^^^^^^^^^^^ error: constant arrays/structs cannot contain pointers to other constants - --> $DIR/nested-ref-in-composite.rs:20:17 + --> <$DIR/nested-ref-in-composite.rs>:20:17 | LL | *pair_out = pair_deep_load(&(&123, &3.14)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: used from within `nested_ref_in_composite::main_pair` - --> $DIR/nested-ref-in-composite.rs:20:17 + --> <$DIR/nested-ref-in-composite.rs>:20:17 | LL | *pair_out = pair_deep_load(&(&123, &3.14)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: called by `main_pair` - --> $DIR/nested-ref-in-composite.rs:19:8 + --> <$DIR/nested-ref-in-composite.rs>:19:8 | LL | pub fn main_pair(pair_out: &mut (u32, f32)) { | ^^^^^^^^^ diff --git a/tests/compiletests/ui/lang/consts/nested-ref.stderr b/tests/compiletests/ui/lang/consts/nested-ref.stderr index 805ec9b607..ef34288a66 100644 --- a/tests/compiletests/ui/lang/consts/nested-ref.stderr +++ b/tests/compiletests/ui/lang/consts/nested-ref.stderr @@ -1,5 +1,5 @@ warning: `#[inline(never)]` function `nested_ref::deep_load` has been inlined - --> $DIR/nested-ref.rs:12:4 + --> <$DIR/nested-ref.rs>:12:4 | LL | fn deep_load(r: &'static &'static u32) -> u32 { | ^^^^^^^^^ @@ -8,7 +8,7 @@ LL | fn deep_load(r: &'static &'static u32) -> u32 { = note: called from `nested_ref::main` warning: `#[inline(never)]` function `nested_ref::deep_transpose` has been inlined - --> $DIR/nested-ref.rs:19:4 + --> <$DIR/nested-ref.rs>:19:4 | LL | fn deep_transpose(r: &'static &'static Mat2) -> Mat2 { | ^^^^^^^^^^^^^^ diff --git a/tests/compiletests/ui/lang/consts/u32-from-u64-fail.stderr b/tests/compiletests/ui/lang/consts/u32-from-u64-fail.stderr index 9ada3d8e3b..9d70528c26 100644 --- a/tests/compiletests/ui/lang/consts/u32-from-u64-fail.stderr +++ b/tests/compiletests/ui/lang/consts/u32-from-u64-fail.stderr @@ -5,10 +5,10 @@ LL | let value = u32::from(K); | ^^^ the trait `From` is not implemented for `u32` | = help: the following other types implement trait `From`: - `u32` implements `From` `u32` implements `From` `u32` implements `From` `u32` implements `From` + `u32` implements `From` `u32` implements `From` `u32` implements `From` diff --git a/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr b/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr index c5dfb04dea..188b18391f 100644 --- a/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr +++ b/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr @@ -8,7 +8,7 @@ OpLine %5 41 19 %10 = OpIAdd %7 %11 %12 OpLine %5 47 8 %13 = OpBitcast %7 %14 -OpLine %15 1103 17 +OpLine %15 1184 17 %16 = OpBitcast %7 %17 OpLine %5 46 4 %18 = OpCompositeConstruct %2 %13 %16 %19 %20 %21 %22 %6 %23 %10 %24 %24 %24 diff --git a/tests/compiletests/ui/lang/core/ref/member_ref_arg-broken.stderr b/tests/compiletests/ui/lang/core/ref/member_ref_arg-broken.stderr index c46b2e0276..17c52a8fab 100644 --- a/tests/compiletests/ui/lang/core/ref/member_ref_arg-broken.stderr +++ b/tests/compiletests/ui/lang/core/ref/member_ref_arg-broken.stderr @@ -1,5 +1,5 @@ warning: `#[inline(never)]` function `member_ref_arg_broken::f` has been inlined - --> $DIR/member_ref_arg-broken.rs:20:4 + --> <$DIR/member_ref_arg-broken.rs>:20:4 | LL | fn f(x: &u32) -> u32 { | ^ @@ -8,7 +8,7 @@ LL | fn f(x: &u32) -> u32 { = note: called from `member_ref_arg_broken::main` warning: `#[inline(never)]` function `member_ref_arg_broken::g` has been inlined - --> $DIR/member_ref_arg-broken.rs:25:4 + --> <$DIR/member_ref_arg-broken.rs>:25:4 | LL | fn g(xy: (&u32, &u32)) -> (u32, u32) { | ^ @@ -17,7 +17,7 @@ LL | fn g(xy: (&u32, &u32)) -> (u32, u32) { = note: called from `member_ref_arg_broken::main` warning: `#[inline(never)]` function `member_ref_arg_broken::h` has been inlined - --> $DIR/member_ref_arg-broken.rs:30:4 + --> <$DIR/member_ref_arg-broken.rs>:30:4 | LL | fn h(xyz: (&u32, &u32, &u32)) -> (u32, u32, u32) { | ^ @@ -26,7 +26,7 @@ LL | fn h(xyz: (&u32, &u32, &u32)) -> (u32, u32, u32) { = note: called from `member_ref_arg_broken::main` warning: `#[inline(never)]` function `member_ref_arg_broken::h_newtyped` has been inlined - --> $DIR/member_ref_arg-broken.rs:41:4 + --> <$DIR/member_ref_arg-broken.rs>:41:4 | LL | fn h_newtyped(xyz: ((&u32, &u32, &u32),)) -> (u32, u32, u32) { | ^^^^^^^^^^ diff --git a/tests/compiletests/ui/lang/core/ref/member_ref_arg.stderr b/tests/compiletests/ui/lang/core/ref/member_ref_arg.stderr index 5ec9e260b4..7596b6f46a 100644 --- a/tests/compiletests/ui/lang/core/ref/member_ref_arg.stderr +++ b/tests/compiletests/ui/lang/core/ref/member_ref_arg.stderr @@ -1,5 +1,5 @@ warning: `#[inline(never)]` function `member_ref_arg::f` has been inlined - --> $DIR/member_ref_arg.rs:14:4 + --> <$DIR/member_ref_arg.rs>:14:4 | LL | fn f(x: &u32) {} | ^ @@ -8,7 +8,7 @@ LL | fn f(x: &u32) {} = note: called from `member_ref_arg::main` warning: `#[inline(never)]` function `member_ref_arg::g` has been inlined - --> $DIR/member_ref_arg.rs:17:4 + --> <$DIR/member_ref_arg.rs>:17:4 | LL | fn g(xy: (&u32, &u32)) {} | ^ diff --git a/tests/compiletests/ui/lang/core/ref/zst_member_ref_arg-broken.stderr b/tests/compiletests/ui/lang/core/ref/zst_member_ref_arg-broken.stderr index 748fe9a222..2283fa5057 100644 --- a/tests/compiletests/ui/lang/core/ref/zst_member_ref_arg-broken.stderr +++ b/tests/compiletests/ui/lang/core/ref/zst_member_ref_arg-broken.stderr @@ -1,16 +1,16 @@ error: cannot offset a pointer to an arbitrary element - --> $DIR/zst_member_ref_arg-broken.rs:23:7 + --> <$DIR/zst_member_ref_arg-broken.rs>:23:7 | LL | f(&s.y); | ^^^^ | note: used from within `zst_member_ref_arg_broken::main_scalar` - --> $DIR/zst_member_ref_arg-broken.rs:23:7 + --> <$DIR/zst_member_ref_arg-broken.rs>:23:7 | LL | f(&s.y); | ^^^^ note: called by `main_scalar` - --> $DIR/zst_member_ref_arg-broken.rs:22:8 + --> <$DIR/zst_member_ref_arg-broken.rs>:22:8 | LL | pub fn main_scalar(#[spirv(push_constant)] s: &S) { | ^^^^^^^^^^^ @@ -18,18 +18,18 @@ LL | pub fn main_scalar(#[spirv(push_constant)] s: &S) { error: cannot cast between pointer types from `*u32` to `*u8` - --> $DIR/zst_member_ref_arg-broken.rs:23:7 + --> <$DIR/zst_member_ref_arg-broken.rs>:23:7 | LL | f(&s.y); | ^^^^ | note: used from within `zst_member_ref_arg_broken::main_scalar` - --> $DIR/zst_member_ref_arg-broken.rs:23:7 + --> <$DIR/zst_member_ref_arg-broken.rs>:23:7 | LL | f(&s.y); | ^^^^ note: called by `main_scalar` - --> $DIR/zst_member_ref_arg-broken.rs:22:8 + --> <$DIR/zst_member_ref_arg-broken.rs>:22:8 | LL | pub fn main_scalar(#[spirv(push_constant)] s: &S) { | ^^^^^^^^^^^ @@ -37,35 +37,35 @@ LL | pub fn main_scalar(#[spirv(push_constant)] s: &S) { error: cannot cast between pointer types from `*u8` to `*struct B { }` - --> $DIR/zst_member_ref_arg-broken.rs:23:5 + --> <$DIR/zst_member_ref_arg-broken.rs>:23:5 | LL | f(&s.y); | ^^^^^^^ | note: used from within `zst_member_ref_arg_broken::main_scalar` - --> $DIR/zst_member_ref_arg-broken.rs:23:5 + --> <$DIR/zst_member_ref_arg-broken.rs>:23:5 | LL | f(&s.y); | ^^^^^^^ note: called by `main_scalar` - --> $DIR/zst_member_ref_arg-broken.rs:22:8 + --> <$DIR/zst_member_ref_arg-broken.rs>:22:8 | LL | pub fn main_scalar(#[spirv(push_constant)] s: &S) { | ^^^^^^^^^^^ error: cannot offset a pointer to an arbitrary element - --> $DIR/zst_member_ref_arg-broken.rs:28:7 + --> <$DIR/zst_member_ref_arg-broken.rs>:28:7 | LL | f(&s.y); | ^^^^ | note: used from within `zst_member_ref_arg_broken::main_scalar_pair` - --> $DIR/zst_member_ref_arg-broken.rs:28:7 + --> <$DIR/zst_member_ref_arg-broken.rs>:28:7 | LL | f(&s.y); | ^^^^ note: called by `main_scalar_pair` - --> $DIR/zst_member_ref_arg-broken.rs:27:8 + --> <$DIR/zst_member_ref_arg-broken.rs>:27:8 | LL | pub fn main_scalar_pair(#[spirv(push_constant)] s: &S) { | ^^^^^^^^^^^^^^^^ @@ -73,18 +73,18 @@ LL | pub fn main_scalar_pair(#[spirv(push_constant)] s: &S) { error: cannot cast between pointer types from `*struct S { u32, u32 }` to `*u8` - --> $DIR/zst_member_ref_arg-broken.rs:28:7 + --> <$DIR/zst_member_ref_arg-broken.rs>:28:7 | LL | f(&s.y); | ^^^^ | note: used from within `zst_member_ref_arg_broken::main_scalar_pair` - --> $DIR/zst_member_ref_arg-broken.rs:28:7 + --> <$DIR/zst_member_ref_arg-broken.rs>:28:7 | LL | f(&s.y); | ^^^^ note: called by `main_scalar_pair` - --> $DIR/zst_member_ref_arg-broken.rs:27:8 + --> <$DIR/zst_member_ref_arg-broken.rs>:27:8 | LL | pub fn main_scalar_pair(#[spirv(push_constant)] s: &S) { | ^^^^^^^^^^^^^^^^ @@ -92,35 +92,35 @@ LL | pub fn main_scalar_pair(#[spirv(push_constant)] s: &S) { error: cannot cast between pointer types from `*u8` to `*struct B { }` - --> $DIR/zst_member_ref_arg-broken.rs:28:5 + --> <$DIR/zst_member_ref_arg-broken.rs>:28:5 | LL | f(&s.y); | ^^^^^^^ | note: used from within `zst_member_ref_arg_broken::main_scalar_pair` - --> $DIR/zst_member_ref_arg-broken.rs:28:5 + --> <$DIR/zst_member_ref_arg-broken.rs>:28:5 | LL | f(&s.y); | ^^^^^^^ note: called by `main_scalar_pair` - --> $DIR/zst_member_ref_arg-broken.rs:27:8 + --> <$DIR/zst_member_ref_arg-broken.rs>:27:8 | LL | pub fn main_scalar_pair(#[spirv(push_constant)] s: &S) { | ^^^^^^^^^^^^^^^^ error: cannot offset a pointer to an arbitrary element - --> $DIR/zst_member_ref_arg-broken.rs:33:7 + --> <$DIR/zst_member_ref_arg-broken.rs>:33:7 | LL | f(&s.y); | ^^^^ | note: used from within `zst_member_ref_arg_broken::main_scalar_scalar_pair_nested` - --> $DIR/zst_member_ref_arg-broken.rs:33:7 + --> <$DIR/zst_member_ref_arg-broken.rs>:33:7 | LL | f(&s.y); | ^^^^ note: called by `main_scalar_scalar_pair_nested` - --> $DIR/zst_member_ref_arg-broken.rs:32:8 + --> <$DIR/zst_member_ref_arg-broken.rs>:32:8 | LL | pub fn main_scalar_scalar_pair_nested(#[spirv(push_constant)] s: &S<(usize, usize)>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -128,18 +128,18 @@ LL | pub fn main_scalar_scalar_pair_nested(#[spirv(push_constant)] s: &S<(usize, error: cannot cast between pointer types from `*struct (usize, usize) { u32, u32 }` to `*u8` - --> $DIR/zst_member_ref_arg-broken.rs:33:7 + --> <$DIR/zst_member_ref_arg-broken.rs>:33:7 | LL | f(&s.y); | ^^^^ | note: used from within `zst_member_ref_arg_broken::main_scalar_scalar_pair_nested` - --> $DIR/zst_member_ref_arg-broken.rs:33:7 + --> <$DIR/zst_member_ref_arg-broken.rs>:33:7 | LL | f(&s.y); | ^^^^ note: called by `main_scalar_scalar_pair_nested` - --> $DIR/zst_member_ref_arg-broken.rs:32:8 + --> <$DIR/zst_member_ref_arg-broken.rs>:32:8 | LL | pub fn main_scalar_scalar_pair_nested(#[spirv(push_constant)] s: &S<(usize, usize)>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -147,18 +147,18 @@ LL | pub fn main_scalar_scalar_pair_nested(#[spirv(push_constant)] s: &S<(usize, error: cannot cast between pointer types from `*u8` to `*struct B { }` - --> $DIR/zst_member_ref_arg-broken.rs:33:5 + --> <$DIR/zst_member_ref_arg-broken.rs>:33:5 | LL | f(&s.y); | ^^^^^^^ | note: used from within `zst_member_ref_arg_broken::main_scalar_scalar_pair_nested` - --> $DIR/zst_member_ref_arg-broken.rs:33:5 + --> <$DIR/zst_member_ref_arg-broken.rs>:33:5 | LL | f(&s.y); | ^^^^^^^ note: called by `main_scalar_scalar_pair_nested` - --> $DIR/zst_member_ref_arg-broken.rs:32:8 + --> <$DIR/zst_member_ref_arg-broken.rs>:32:8 | LL | pub fn main_scalar_scalar_pair_nested(#[spirv(push_constant)] s: &S<(usize, usize)>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/compiletests/ui/lang/issue-452.stderr b/tests/compiletests/ui/lang/issue-452.stderr index 2f6b71f042..d74e29aa91 100644 --- a/tests/compiletests/ui/lang/issue-452.stderr +++ b/tests/compiletests/ui/lang/issue-452.stderr @@ -1,17 +1,17 @@ error: function pointer types are not allowed - --> $DIR/issue-452.rs:8:1 + --> <$DIR/issue-452.rs>:8:1 | LL | fn use_cmp(cmp: fn(&Position) -> u32) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: used by unnamed global (%44) note: used from within `issue_452::main` - --> $DIR/issue-452.rs:17:5 + --> <$DIR/issue-452.rs>:17:5 | LL | use_cmp(|p| p.0); | ^^^^^^^^^^^^^^^^ note: called by `main` - --> $DIR/issue-452.rs:16:8 + --> <$DIR/issue-452.rs>:16:8 | LL | pub fn main() { | ^^^^ From cab2c490f4d59f0495c263e987bb46a25c296dad Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 16:25:54 -0800 Subject: [PATCH 21/34] Rustfmt codegen_cx panic-entry matcher formatting --- crates/rustc_codegen_spirv/src/codegen_cx/declare.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs index b3a303c5da..aaa9932201 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs @@ -233,8 +233,8 @@ impl<'tcx> CodegenCx<'tcx> { if is_nonlocal_core && demangled_symbol_name.ends_with("::precondition_check") { self.panic_entry_points.borrow_mut().insert(def_id); } - let is_spirv_std_byte_addressable_bounds_check = - is_nonlocal && self.tcx.def_path_str(def_id) == "spirv_std::byte_addressable_buffer::bounds_check"; + let is_spirv_std_byte_addressable_bounds_check = is_nonlocal + && self.tcx.def_path_str(def_id) == "spirv_std::byte_addressable_buffer::bounds_check"; if (is_nonlocal_core && demangled_symbol_name.ends_with("::bounds_check")) || is_spirv_std_byte_addressable_bounds_check { From 929fe0cc5c9b9a34afaa9572060690f460bd6721 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 16:54:57 -0800 Subject: [PATCH 22/34] spirv-builder: pass -Zjson-target-spec for JSON targets --- crates/spirv-builder/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/spirv-builder/src/lib.rs b/crates/spirv-builder/src/lib.rs index 96d1d10bee..a498833bd8 100644 --- a/crates/spirv-builder/src/lib.rs +++ b/crates/spirv-builder/src/lib.rs @@ -1047,6 +1047,12 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result { let target_spec_dir = target_dir.join("target-specs"); let target = TargetSpecVersion::target_arg(toolchain_rustc_version, &target, &target_spec_dir)?; + if Path::new(&target) + .extension() + .is_some_and(|ext| ext == "json") + { + cargo.arg("-Zjson-target-spec"); + } cargo.arg("--target").arg(target); if !builder.shader_crate_features.default_features { From 73039655b23afbe61d67eeba900e78e73d49717e Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 16:55:00 -0800 Subject: [PATCH 23/34] compiletests: bless sampled image query_size_lod stderr --- ...mpled_image_rect_query_size_lod_err.stderr | 57 +++++-------------- 1 file changed, 14 insertions(+), 43 deletions(-) diff --git a/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr b/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr index 2f7faa1296..ebbe4c2b9a 100644 --- a/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr +++ b/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr @@ -5,51 +5,22 @@ LL | *output = rect_sampled.query_size_lod(0); | ^^^^^^^^^^^^^^ the trait `HasQuerySizeLod` is not implemented for `Image` | help: the following other types implement trait `HasQuerySizeLod` - --> /image.rs:2089:1 + --> crates/spirv-std/src/image.rs:2089:0 + ::: crates/spirv-std/src/image.rs:2106:5 | -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -... -LL | / impl< -LL | | SampledType: SampleType, -LL | | const DEPTH: u32, -LL | | const FORMAT: u32, -... | -LL | | COMPONENTS, -LL | | > - | |_____^ `Image` -note: required by a bound in `SampledImage::>::query_size_lod` - --> /image.rs:1253:12 + = note: `Image` + ::: crates/spirv-std/src/image.rs:2126:5 + | + = note: `Image` + ::: crates/spirv-std/src/image.rs:2146:5 | -LL | pub fn query_size_lod + Default>( - | -------------- required by a bound in this associated function -... -LL | >: HasQuerySizeLod, - | ^^^^^^^^^^^^^^^ required by this bound in `SampledImage::>::query_size_lod` + = note: `Image` + ::: crates/spirv-std/src/image.rs:2166:5 + | + = note: `Image` +note: required by a bound in `SampledImage::>::query_size_lod` + --> crates/spirv-std/src/image.rs:1236:4 + = note: this error originates in the attribute macro `crate::macros::gpu_only` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error From 3341df62ccc0d63370c7298371c651655f33e64b Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 16:55:03 -0800 Subject: [PATCH 24/34] codegen: adapt panic format_args decompiler for new nightly shapes --- .../src/builder/format_args_decompiler.rs | 456 ++++++++++++++---- .../src/codegen_cx/declare.rs | 26 +- .../rustc_codegen_spirv/src/codegen_cx/mod.rs | 9 +- 3 files changed, 388 insertions(+), 103 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs index 2d1f0ca3ab..887aaaa2a7 100644 --- a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs +++ b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs @@ -3,6 +3,7 @@ use crate::builder::Builder; use crate::builder_spirv::{SpirvConst, SpirvValue, SpirvValueExt, SpirvValueKind}; use crate::codegen_cx::FmtArgsCtor; use crate::custom_insts::CustomOp; +use crate::spirv_type::SpirvType; use either::Either; use itertools::Itertools; use rspirv::dr::Operand; @@ -74,13 +75,116 @@ impl<'tcx> DecodedFormatArgs<'tcx> { } None }; - let const_str_as_utf8 = |&[str_ptr_id, str_len_id]: &[Word; 2]| { - let str_len = const_u32_as_usize(str_len_id)?; - let piece_str_bytes = const_slice_as_elem_ids(str_ptr_id, str_len)? + let const_ptr_to_composite_len = |ptr_id: Word| { + if let SpirvConst::PtrTo { pointee } = cx.builder.lookup_const_by_id(ptr_id)? + && let SpirvConst::Composite(elems) = cx.builder.lookup_const_by_id(pointee)? + { + return Some(elems.len()); + } + None + }; + let array_len_from_ptr_type = |ptr_ty_id: Word| { + let pointee_ty_id = match cx.lookup_type(ptr_ty_id) { + SpirvType::Pointer { pointee } => pointee, + _ => return None, + }; + let count = match cx.lookup_type(pointee_ty_id) { + SpirvType::Array { count, .. } => count, + _ => return None, + }; + match count.kind { + SpirvValueKind::Def(count_id) => const_u32_as_usize(count_id), + _ => None, + } + }; + let const_slice_as_u8s = |ptr_id: Word, len: usize| { + const_slice_as_elem_ids(ptr_id, len)? .iter() .map(|&id| u8::try_from(const_u32_as_usize(id)?).ok()) - .collect::>>()?; - String::from_utf8(piece_str_bytes).ok() + .collect::>>() + }; + let const_str_as_utf8 = |&[str_ptr_id, str_len_id]: &[Word; 2]| { + let len_bits = const_u32_as_usize(str_len_id)?; + [Some(len_bits), (len_bits & 1 == 1).then_some(len_bits >> 1)] + .into_iter() + .flatten() + .find_map(|str_len| { + let piece_str_bytes = const_slice_as_u8s(str_ptr_id, str_len)?; + String::from_utf8(piece_str_bytes).ok() + }) + }; + let parse_encoded_template = |template_ptr_id: Word, template_len: usize| { + let bytes = const_slice_as_u8s(template_ptr_id, template_len)?; + + let mut i = 0; + let mut pieces = SmallVec::<[String; 2]>::new(); + let mut current_piece = String::new(); + let mut placeholder_count = 0usize; + let mut next_implicit_arg_index = 0u16; + let mut placeholders_map_1_to_1 = true; + + while let Some(&first) = bytes.get(i) { + i += 1; + match first { + 0 => break, + 1..=127 => { + let lit_len = first as usize; + let lit = bytes.get(i..i + lit_len)?; + i += lit_len; + current_piece.push_str(std::str::from_utf8(lit).ok()?); + } + 128 => { + let len_bytes = bytes.get(i..i + 2)?; + i += 2; + let lit_len = u16::from_le_bytes([len_bytes[0], len_bytes[1]]) as usize; + let lit = bytes.get(i..i + lit_len)?; + i += lit_len; + current_piece.push_str(std::str::from_utf8(lit).ok()?); + } + 0xC0..=0xFF => { + let flags_len = if first & 1 != 0 { 4 } else { 0 }; + let width_len = if first & 2 != 0 { 2 } else { 0 }; + let precision_len = if first & 4 != 0 { 2 } else { 0 }; + let arg_index_len = if first & 8 != 0 { 2 } else { 0 }; + let placeholder_len = flags_len + width_len + precision_len + arg_index_len; + let placeholder = bytes.get(i..i + placeholder_len)?; + i += placeholder_len; + + let mut off = flags_len + width_len + precision_len; + let arg_index = if arg_index_len != 0 { + let lo = *placeholder.get(off)?; + let hi = *placeholder.get(off + 1)?; + off += 2; + let arg_index = u16::from_le_bytes([lo, hi]); + next_implicit_arg_index = arg_index.saturating_add(1); + arg_index + } else { + let arg_index = next_implicit_arg_index; + next_implicit_arg_index = next_implicit_arg_index.saturating_add(1); + arg_index + }; + debug_assert_eq!(off, placeholder_len); + + // Width/precision can indirectly reference count arguments. + if first & (1 << 4) != 0 || first & (1 << 5) != 0 { + placeholders_map_1_to_1 = false; + } + if arg_index as usize != placeholder_count { + placeholders_map_1_to_1 = false; + } + + pieces.push(std::mem::take(&mut current_piece)); + placeholder_count += 1; + } + _ => return None, + } + } + if i != bytes.len() { + return None; + } + + pieces.push(current_piece); + Some((pieces, placeholder_count, placeholders_map_1_to_1)) }; // HACK(eddyb) `panic_explicit` doesn't take any regular arguments, @@ -104,8 +208,8 @@ impl<'tcx> DecodedFormatArgs<'tcx> { ref other_args @ .., ] = args[..] { - // Optional `&'static panic::Location<'static>`. - if other_args.len() <= 1 + // Optional `force_no_backtrace` and/or `&'static panic::Location<'static>`. + if other_args.len() <= 2 && let Some(const_msg) = const_str_as_utf8(&[a_id, b_id]) { decoded_format_args.const_pieces = Some([const_msg].into_iter().collect()); @@ -113,29 +217,75 @@ impl<'tcx> DecodedFormatArgs<'tcx> { } } - let format_args_id = match *args { - // HACK(eddyb) `panic_nounwind_fmt` takes an extra argument. + // Newer `core::fmt::Arguments` can be scalarized at the panic call-site + // (`template: *const u8`, `args: *const fmt::rt::Argument`), instead of + // being passed as one aggregate value. + let split_fmt_args = match *args { [ SpirvValue { - kind: SpirvValueKind::Def(format_args_id), + kind: SpirvValueKind::Def(template_id), + ty: template_ty_id, .. }, - _, // `&'static panic::Location<'static>` - ] - | [ SpirvValue { - kind: SpirvValueKind::Def(format_args_id), + kind: SpirvValueKind::Def(rt_args_or_tagged_len_id), + ty: rt_args_or_tagged_len_ty_id, .. }, - _, // `force_no_backtrace: bool` - _, // `&'static panic::Location<'static>` - ] => format_args_id, + ref trailing @ .., + ] if trailing.len() <= 2 + && matches!(cx.lookup_type(template_ty_id), SpirvType::Pointer { .. }) + && matches!( + cx.lookup_type(rt_args_or_tagged_len_ty_id), + SpirvType::Pointer { .. } | SpirvType::Integer(..) + ) + && const_str_as_utf8(&[template_id, rt_args_or_tagged_len_id]).is_none() => + { + let looks_like_bool = matches!( + cx.builder.lookup_const_by_id(rt_args_or_tagged_len_id), + Some(SpirvConst::Scalar(0 | 1)) + ); + if trailing.len() == 1 && looks_like_bool { + None + } else { + Some(( + template_id, + template_ty_id, + rt_args_or_tagged_len_id, + rt_args_or_tagged_len_ty_id, + )) + } + } + _ => None, + }; - _ => { - return Err(FormatArgsNotRecognized( - "panic entry-point call args".into(), - )); + let format_args_id = if split_fmt_args.is_none() { + match *args { + // HACK(eddyb) `panic_nounwind_fmt` takes an extra argument. + [ + SpirvValue { + kind: SpirvValueKind::Def(format_args_id), + .. + }, + _, // `&'static panic::Location<'static>` + ] + | [ + SpirvValue { + kind: SpirvValueKind::Def(format_args_id), + .. + }, + _, // `force_no_backtrace: bool` + _, // `&'static panic::Location<'static>` + ] => format_args_id, + + _ => { + return Err(FormatArgsNotRecognized( + "panic entry-point call args".into(), + )); + } } + } else { + 0 }; let custom_ext_inst_set_import = builder.ext_inst.borrow_mut().import_custom(builder); @@ -290,51 +440,6 @@ impl<'tcx> DecodedFormatArgs<'tcx> { insts.reverse(); Some(insts) }; - // Newer rustc can pass the `fmt::Arguments::new_*` result directly to - // panic entry points (single trailing call), while older versions go - // through a local temporary (`Call -> Store -> Load`). - let fmt_args_new_call_inst_count = if matches!( - try_rev_take(-3).as_deref(), - Some(&[Inst::Call(_, _, _), Inst::Store(_, _), Inst::Load(_, _)]) - ) { - 3 - } else if matches!( - try_rev_take(-1).as_deref(), - Some(&[Inst::Call(call_ret_id, _, _)]) if call_ret_id == format_args_id - ) { - 1 - } else if matches!( - try_rev_take(-5).as_deref(), - Some(&[ - Inst::Call(call_ret_id, _, _), - Inst::CompositeExtract(extracted0, from0, 0), - Inst::CompositeExtract(extracted1, from1, 1), - Inst::CompositeInsert(inserted0, value0, _, 0), - Inst::CompositeInsert(inserted1, value1, inserted0_prev, 1), - ]) if [from0, from1] == [call_ret_id; 2] - && [value0, value1] == [extracted0, extracted1] - && inserted0 == inserted0_prev - && inserted1 == format_args_id - ) { - 5 - } else { - // HACK(eddyb) gather context for new call patterns before bailing. - let mut insts = SmallVec::<[Inst; 32]>::new(); - while let Some(extra_inst) = try_rev_take(1) { - insts.extend(extra_inst); - if insts.len() >= 32 { - break; - } - } - insts.reverse(); - - return Err(if insts.is_empty() { - FormatArgsNotRecognized("fmt::Arguments::new call: ran out of instructions".into()) - } else { - FormatArgsNotRecognized(format!("fmt::Arguments::new call sequence ({insts:?})",)) - }); - }; - let fmt_args_new_call_insts = try_rev_take(fmt_args_new_call_inst_count).unwrap(); let lookup_fmt_args_ctor = |callee_id| { cx.fmt_args_new_fn_ids .borrow() @@ -344,41 +449,97 @@ impl<'tcx> DecodedFormatArgs<'tcx> { FormatArgsNotRecognized("fmt::Arguments::new callee not registered".into()) }) }; - let (call_args, ctor) = match fmt_args_new_call_insts[..] { - [ - Inst::Call(call_ret_id, callee_id, ref call_args), - Inst::Store(st_dst_id, st_val_id), - Inst::Load(ld_val_id, ld_src_id), - ] if call_ret_id == st_val_id - && st_dst_id == ld_src_id - && ld_val_id == format_args_id => + let (ctor, call_args_storage) = 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)) = ( + 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, + } + } 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] { - require_local_var(st_dst_id, "fmt::Arguments::new destination")?; + // Consume the matched call instruction. + try_rev_take(1).unwrap(); + lookup_fmt_args_ctor(callee_id)? + } else { + return Err(FormatArgsNotRecognized( + "fmt::Arguments::new call: split fmt::Arguments args without recoverable ctor metadata".into(), + )); + }; - (call_args.as_slice(), lookup_fmt_args_ctor(callee_id)?) - } - [Inst::Call(call_ret_id, callee_id, ref call_args)] - if call_ret_id == format_args_id => - { - (call_args.as_slice(), lookup_fmt_args_ctor(callee_id)?) - } - [ - Inst::Call(call_ret_id, callee_id, ref call_args), - Inst::CompositeExtract(extracted0, from0, 0), - Inst::CompositeExtract(extracted1, from1, 1), - Inst::CompositeInsert(inserted0, value0, _, 0), - Inst::CompositeInsert(inserted1, value1, inserted0_prev, 1), - ] if [from0, from1] == [call_ret_id; 2] - && [value0, value1] == [extracted0, extracted1] - && inserted0 == inserted0_prev - && inserted1 == format_args_id => + ( + 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 + // through a local temporary (`Call -> Store -> Load`). + let fmt_args_new_call_inst_count = if matches!( + try_rev_take(-3).as_deref(), + Some(&[Inst::Call(_, _, _), Inst::Store(_, _), Inst::Load(_, _)]) + ) { + 3 + } else if let Some(&[Inst::Call(call_ret_id, callee_id, _)]) = + try_rev_take(-1).as_deref() { - (call_args.as_slice(), lookup_fmt_args_ctor(callee_id)?) - } - _ => { - // HACK(eddyb) this gathers more context before reporting. - let mut insts = fmt_args_new_call_insts; + if call_ret_id == format_args_id + || cx.fmt_args_new_fn_ids.borrow().contains_key(&callee_id) + { + 1 + } else { + 0 + } + } else if matches!( + try_rev_take(-5).as_deref(), + Some(&[ + Inst::Call(call_ret_id, _, _), + Inst::CompositeExtract(extracted0, from0, 0), + Inst::CompositeExtract(extracted1, from1, 1), + Inst::CompositeInsert(inserted0, value0, _, 0), + Inst::CompositeInsert(inserted1, value1, inserted0_prev, 1), + ]) if [from0, from1] == [call_ret_id; 2] + && [value0, value1] == [extracted0, extracted1] + && inserted0 == inserted0_prev + && inserted1 == format_args_id + ) { + 5 + } else if try_rev_take(-1).is_some() { + 0 + } else { + // HACK(eddyb) gather context for new call patterns before bailing. + let mut insts = SmallVec::<[Inst; 32]>::new(); + while let Some(extra_inst) = try_rev_take(1) { + insts.extend(extra_inst); + if insts.len() >= 32 { + break; + } + } insts.reverse(); + + if insts.is_empty() { + return Ok(decoded_format_args); + } + return Err(FormatArgsNotRecognized(format!( + "fmt::Arguments::new call sequence ({insts:?})", + ))); + }; + if fmt_args_new_call_inst_count == 0 { + // HACK(eddyb) gather context for new call patterns before bailing. + let mut insts = SmallVec::<[Inst; 32]>::new(); while let Some(extra_inst) = try_rev_take(1) { insts.extend(extra_inst); if insts.len() >= 32 { @@ -387,16 +548,96 @@ impl<'tcx> DecodedFormatArgs<'tcx> { } insts.reverse(); + if insts.is_empty() { + return Ok(decoded_format_args); + } return Err(FormatArgsNotRecognized(format!( "fmt::Arguments::new call sequence ({insts:?})", ))); } + let fmt_args_new_call_insts = try_rev_take(fmt_args_new_call_inst_count).unwrap(); + match fmt_args_new_call_insts[..] { + [ + Inst::Call(call_ret_id, callee_id, ref call_args), + Inst::Store(st_dst_id, st_val_id), + Inst::Load(ld_val_id, ld_src_id), + ] if call_ret_id == st_val_id + && st_dst_id == ld_src_id + && ld_val_id == format_args_id => + { + require_local_var(st_dst_id, "fmt::Arguments::new destination")?; + + ( + lookup_fmt_args_ctor(callee_id)?, + call_args.iter().copied().collect(), + ) + } + [Inst::Call(call_ret_id, callee_id, ref call_args)] + if call_ret_id == format_args_id + || cx.fmt_args_new_fn_ids.borrow().contains_key(&callee_id) => + { + ( + lookup_fmt_args_ctor(callee_id)?, + call_args.iter().copied().collect(), + ) + } + [ + Inst::Call(call_ret_id, callee_id, ref call_args), + Inst::CompositeExtract(extracted0, from0, 0), + Inst::CompositeExtract(extracted1, from1, 1), + Inst::CompositeInsert(inserted0, value0, _, 0), + Inst::CompositeInsert(inserted1, value1, inserted0_prev, 1), + ] if [from0, from1] == [call_ret_id; 2] + && [value0, value1] == [extracted0, extracted1] + && inserted0 == inserted0_prev + && inserted1 == format_args_id => + { + ( + lookup_fmt_args_ctor(callee_id)?, + call_args.iter().copied().collect(), + ) + } + _ => { + // HACK(eddyb) this gathers more context before reporting. + let mut insts = fmt_args_new_call_insts; + insts.reverse(); + while let Some(extra_inst) = try_rev_take(1) { + insts.extend(extra_inst); + if insts.len() >= 32 { + break; + } + } + insts.reverse(); + + return Err(FormatArgsNotRecognized(format!( + "fmt::Arguments::new call sequence ({insts:?})", + ))); + } + } }; + let call_args = call_args_storage.as_slice(); enum PiecesSource { Slice { ptr_id: Word, len: usize }, + EncodedTemplate { ptr_id: Word, len: usize }, DirectConstStr([Word; 2]), } + let mut template_placeholder_info = None; let (pieces_source, (rt_args_slice_ptr_id, rt_args_count)) = match (ctor, call_args) { + // `::new` + ( + FmtArgsCtor::NewTemplate { + template_len, + rt_args_count, + }, + &[template_ptr_id, rt_args_slice_ptr_id], + ) => ( + PiecesSource::EncodedTemplate { + ptr_id: template_ptr_id, + len: template_len, + }, + (Some(rt_args_slice_ptr_id), rt_args_count), + ), + // `::new_v1_formatted` // // HACK(eddyb) this isn't fully supported, @@ -446,10 +687,8 @@ impl<'tcx> DecodedFormatArgs<'tcx> { (rt_args_cast_in_id, placeholders_cast_in_id) } _ => { - let mut insts = prepare_args_insts; - insts.extend(fmt_args_new_call_insts); return Err(FormatArgsNotRecognized(format!( - "fmt::Arguments::new_v1_formatted call sequence ({insts:?})", + "fmt::Arguments::new_v1_formatted call sequence ({prepare_args_insts:?})", ))); } }; @@ -692,6 +931,15 @@ impl<'tcx> DecodedFormatArgs<'tcx> { PiecesSource::DirectConstStr(str_ref) => { const_str_as_utf8(&str_ref).map(|s| [s].into_iter().collect()) } + PiecesSource::EncodedTemplate { + ptr_id: template_ptr_id, + len: template_len, + } => parse_encoded_template(template_ptr_id, template_len).map( + |(pieces, placeholder_count, placeholders_map_1_to_1)| { + template_placeholder_info = Some((placeholder_count, placeholders_map_1_to_1)); + pieces + }, + ), PiecesSource::Slice { ptr_id: pieces_slice_ptr_id, len: pieces_len, @@ -748,6 +996,14 @@ impl<'tcx> DecodedFormatArgs<'tcx> { } }; + if let Some((placeholder_count, placeholders_map_1_to_1)) = template_placeholder_info { + let decoded_arg_count = decoded_format_args.ref_arg_ids_with_ty_and_spec.len(); + if !placeholders_map_1_to_1 || placeholder_count != decoded_arg_count { + decoded_format_args.has_unknown_fmt_placeholder_to_args_mapping = + Some(placeholder_count); + } + } + // Keep all instructions up to (but not including) the last one // confirmed above to be the first instruction of `format_args!`. func.blocks[block_idx] diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs index aaa9932201..a2cef668e9 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs @@ -240,6 +240,23 @@ impl<'tcx> CodegenCx<'tcx> { { self.panic_entry_points.borrow_mut().insert(def_id); } + if let Some(generics) = demangled_symbol_name + .strip_prefix("::new::<") + .and_then(|s| s.strip_suffix(">")) + { + let mut generics = generics.split(',').map(str::trim); + if let (Some(template_len), Some(rt_args_count), None) = + (generics.next(), generics.next(), generics.next()) + { + self.fmt_args_new_fn_ids.borrow_mut().insert( + fn_id, + FmtArgsCtor::NewTemplate { + template_len: template_len.parse().unwrap(), + rt_args_count: rt_args_count.parse().unwrap(), + }, + ); + } + } if let Some(pieces_len) = demangled_symbol_name .strip_prefix("::new_const::<") .and_then(|s| s.strip_suffix(">")) @@ -269,7 +286,9 @@ impl<'tcx> CodegenCx<'tcx> { .borrow_mut() .insert(fn_id, FmtArgsCtor::NewV1FormattedDynamic); } - if demangled_symbol_name == "::from_str" { + if demangled_symbol_name == "::from_str" + || demangled_symbol_name == "::from_str_nonconst" + { self.fmt_args_new_fn_ids .borrow_mut() .insert(fn_id, FmtArgsCtor::FromStr); @@ -301,6 +320,11 @@ impl<'tcx> CodegenCx<'tcx> { .insert(fn_id, (ty, spec)); } } + if demangled_symbol_name == "::from_usize" { + self.fmt_rt_arg_new_fn_ids_to_ty_and_spec + .borrow_mut() + .insert(fn_id, (self.tcx.types.usize, '?')); + } declared } diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs index a16d3aa191..8b505a4648 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs @@ -50,6 +50,11 @@ use std::str::FromStr; /// explicit and type-safe, replacing the old sentinel tuple encoding. #[derive(Clone, Copy, Debug)] pub enum FmtArgsCtor { + /// `Arguments::new(template, args)` (new format template encoding). + NewTemplate { + template_len: usize, + rt_args_count: usize, + }, /// `Arguments::new_const(pieces)`. NewConst { pieces_len: usize }, /// `Arguments::new_v1(pieces, args)`. @@ -59,7 +64,7 @@ pub enum FmtArgsCtor { }, /// `Arguments::new_v1_formatted(..)` where lengths come from call operands. NewV1FormattedDynamic, - /// `Arguments::from_str(s)`. + /// `Arguments::from_str(s)` / `Arguments::from_str_nonconst(s)`. FromStr, } @@ -93,7 +98,7 @@ pub struct CodegenCx<'tcx> { /// of these lang items, which we always replace with an "abort". pub panic_entry_points: RefCell>, - /// `core::fmt::Arguments::{new_const,new_v1,new_v1_formatted,from_str}` + /// `core::fmt::Arguments::{new,new_const,new_v1,new_v1_formatted,from_str,from_str_nonconst}` /// instances (for Rust 2021 panics). pub fmt_args_new_fn_ids: RefCell>, From cfb698b0aeccd31ceb6ad04824ff03276992762b Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 17:01:55 -0800 Subject: [PATCH 25/34] codegen: stop treating core precondition_check as panic entry point --- crates/rustc_codegen_spirv/src/codegen_cx/declare.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs index a2cef668e9..86b9e511c5 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs @@ -230,9 +230,6 @@ impl<'tcx> CodegenCx<'tcx> { } let is_nonlocal = !def_id.is_local(); let is_nonlocal_core = is_nonlocal && self.tcx.crate_name(def_id.krate) == sym::core; - if is_nonlocal_core && demangled_symbol_name.ends_with("::precondition_check") { - self.panic_entry_points.borrow_mut().insert(def_id); - } let is_spirv_std_byte_addressable_bounds_check = is_nonlocal && self.tcx.def_path_str(def_id) == "spirv_std::byte_addressable_buffer::bounds_check"; if (is_nonlocal_core && demangled_symbol_name.ends_with("::bounds_check")) From 8423fd45b0d373e701d9bb1c317b9ac991de0239 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 17:01:58 -0800 Subject: [PATCH 26/34] codegen: harden panic format_args fallback for split/pass-through shapes --- .../src/builder/format_args_decompiler.rs | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs index 887aaaa2a7..cb106e19bf 100644 --- a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs +++ b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs @@ -199,10 +199,12 @@ impl<'tcx> DecodedFormatArgs<'tcx> { if let [ SpirvValue { kind: SpirvValueKind::Def(a_id), + ty: a_ty, .. }, SpirvValue { kind: SpirvValueKind::Def(b_id), + ty: b_ty, .. }, ref other_args @ .., @@ -215,6 +217,17 @@ impl<'tcx> DecodedFormatArgs<'tcx> { decoded_format_args.const_pieces = Some([const_msg].into_iter().collect()); return Ok(decoded_format_args); } + + // Dynamic `&str` panic messages (e.g. `panic_display(&msg)` where + // `msg` isn't a directly recoverable constant). + if other_args.len() <= 2 + && matches!(cx.lookup_type(a_ty), SpirvType::Pointer { .. }) + && matches!(cx.lookup_type(b_ty), SpirvType::Integer(..)) + { + decoded_format_args.const_pieces = + Some(["".into()].into_iter().collect()); + return Ok(decoded_format_args); + } } // Newer `core::fmt::Arguments` can be scalarized at the panic call-site @@ -475,9 +488,10 @@ impl<'tcx> DecodedFormatArgs<'tcx> { try_rev_take(1).unwrap(); lookup_fmt_args_ctor(callee_id)? } else { - return Err(FormatArgsNotRecognized( - "fmt::Arguments::new call: split fmt::Arguments args without recoverable ctor metadata".into(), - )); + // 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); }; ( @@ -533,6 +547,9 @@ impl<'tcx> DecodedFormatArgs<'tcx> { if insts.is_empty() { return Ok(decoded_format_args); } + if !insts.iter().any(|inst| matches!(inst, Inst::Call(_, _, _))) { + return Ok(decoded_format_args); + } return Err(FormatArgsNotRecognized(format!( "fmt::Arguments::new call sequence ({insts:?})", ))); @@ -551,6 +568,9 @@ impl<'tcx> DecodedFormatArgs<'tcx> { if insts.is_empty() { return Ok(decoded_format_args); } + if !insts.iter().any(|inst| matches!(inst, Inst::Call(_, _, _))) { + return Ok(decoded_format_args); + } return Err(FormatArgsNotRecognized(format!( "fmt::Arguments::new call sequence ({insts:?})", ))); From 8ffe0f51f484e89627e84a310ca2ac4a80a342d7 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 17:58:04 -0800 Subject: [PATCH 27/34] codegen: preserve raw fn ABI query invariants --- crates/rustc_codegen_spirv/src/abi.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/rustc_codegen_spirv/src/abi.rs b/crates/rustc_codegen_spirv/src/abi.rs index c3790ba78d..2aea31b8db 100644 --- a/crates/rustc_codegen_spirv/src/abi.rs +++ b/crates/rustc_codegen_spirv/src/abi.rs @@ -21,6 +21,7 @@ use rustc_middle::ty::{ 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}; @@ -131,7 +132,15 @@ pub(crate) fn provide(providers: &mut Providers) { let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS .queries .fn_abi_of_instance_no_deduced_attrs)(tcx, key); - Ok(readjust_fn_abi(tcx, result?)) + // 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 From 7fc220eb4f0837ea64081707f581dd8638d115a0 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 17:58:09 -0800 Subject: [PATCH 28/34] codegen: harden panic message decoding for nightly call shapes --- .../src/builder/format_args_decompiler.rs | 307 +++++++++--------- .../src/codegen_cx/declare.rs | 16 +- .../ui/dis/panic_builtin_bounds_check.stderr | 2 +- 3 files changed, 164 insertions(+), 161 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs index cb106e19bf..fbcbf86639 100644 --- a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs +++ b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs @@ -200,12 +200,10 @@ impl<'tcx> DecodedFormatArgs<'tcx> { SpirvValue { kind: SpirvValueKind::Def(a_id), ty: a_ty, - .. }, SpirvValue { kind: SpirvValueKind::Def(b_id), ty: b_ty, - .. }, ref other_args @ .., ] = args[..] @@ -238,12 +236,10 @@ impl<'tcx> DecodedFormatArgs<'tcx> { SpirvValue { kind: SpirvValueKind::Def(template_id), ty: template_ty_id, - .. }, SpirvValue { kind: SpirvValueKind::Def(rt_args_or_tagged_len_id), ty: rt_args_or_tagged_len_ty_id, - .. }, ref trailing @ .., ] if trailing.len() <= 2 @@ -462,165 +458,98 @@ impl<'tcx> DecodedFormatArgs<'tcx> { FormatArgsNotRecognized("fmt::Arguments::new callee not registered".into()) }) }; - let (ctor, call_args_storage) = 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)) = ( - 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, - } - } 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)? - } 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 - // through a local temporary (`Call -> Store -> Load`). - let fmt_args_new_call_inst_count = if matches!( - try_rev_take(-3).as_deref(), - Some(&[Inst::Call(_, _, _), Inst::Store(_, _), Inst::Load(_, _)]) - ) { - 3 - } else if let Some(&[Inst::Call(call_ret_id, callee_id, _)]) = - try_rev_take(-1).as_deref() + let (ctor, call_args_storage) = + if let Some((template_id, template_ty_id, rt_args_ptr_id, rt_args_ptr_ty_id)) = + split_fmt_args { - if call_ret_id == format_args_id - || cx.fmt_args_new_fn_ids.borrow().contains_key(&callee_id) + let ctor = 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, + } + } 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] { - 1 + // Consume the matched call instruction. + try_rev_take(1).unwrap(); + lookup_fmt_args_ctor(callee_id)? } else { - 0 - } - } else if matches!( - try_rev_take(-5).as_deref(), - Some(&[ - Inst::Call(call_ret_id, _, _), - Inst::CompositeExtract(extracted0, from0, 0), - Inst::CompositeExtract(extracted1, from1, 1), - Inst::CompositeInsert(inserted0, value0, _, 0), - Inst::CompositeInsert(inserted1, value1, inserted0_prev, 1), - ]) if [from0, from1] == [call_ret_id; 2] - && [value0, value1] == [extracted0, extracted1] - && inserted0 == inserted0_prev - && inserted1 == format_args_id - ) { - 5 - } else if try_rev_take(-1).is_some() { - 0 - } else { - // HACK(eddyb) gather context for new call patterns before bailing. - let mut insts = SmallVec::<[Inst; 32]>::new(); - while let Some(extra_inst) = try_rev_take(1) { - insts.extend(extra_inst); - if insts.len() >= 32 { - break; - } - } - insts.reverse(); - - if insts.is_empty() { - return Ok(decoded_format_args); - } - if !insts.iter().any(|inst| matches!(inst, Inst::Call(_, _, _))) { + // 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); - } - return Err(FormatArgsNotRecognized(format!( - "fmt::Arguments::new call sequence ({insts:?})", - ))); - }; - if fmt_args_new_call_inst_count == 0 { - // HACK(eddyb) gather context for new call patterns before bailing. - let mut insts = SmallVec::<[Inst; 32]>::new(); - while let Some(extra_inst) = try_rev_take(1) { - insts.extend(extra_inst); - if insts.len() >= 32 { - break; - } - } - insts.reverse(); + }; - if insts.is_empty() { - return Ok(decoded_format_args); - } - if !insts.iter().any(|inst| matches!(inst, Inst::Call(_, _, _))) { - return Ok(decoded_format_args); - } - return Err(FormatArgsNotRecognized(format!( - "fmt::Arguments::new call sequence ({insts:?})", - ))); - } - let fmt_args_new_call_insts = try_rev_take(fmt_args_new_call_inst_count).unwrap(); - match fmt_args_new_call_insts[..] { - [ - Inst::Call(call_ret_id, callee_id, ref call_args), - Inst::Store(st_dst_id, st_val_id), - Inst::Load(ld_val_id, ld_src_id), - ] if call_ret_id == st_val_id - && st_dst_id == ld_src_id - && ld_val_id == format_args_id => + ( + 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 + // through a local temporary (`Call -> Store -> Load`). + let fmt_args_new_call_inst_count = if matches!( + try_rev_take(-3).as_deref(), + Some(&[Inst::Call(_, _, _), Inst::Store(_, _), Inst::Load(_, _)]) + ) { + 3 + } else if let Some(&[Inst::Call(call_ret_id, callee_id, _)]) = + try_rev_take(-1).as_deref() { - require_local_var(st_dst_id, "fmt::Arguments::new destination")?; - - ( - lookup_fmt_args_ctor(callee_id)?, - call_args.iter().copied().collect(), - ) - } - [Inst::Call(call_ret_id, callee_id, ref call_args)] if call_ret_id == format_args_id - || cx.fmt_args_new_fn_ids.borrow().contains_key(&callee_id) => - { - ( - lookup_fmt_args_ctor(callee_id)?, - call_args.iter().copied().collect(), - ) - } - [ - Inst::Call(call_ret_id, callee_id, ref call_args), - Inst::CompositeExtract(extracted0, from0, 0), - Inst::CompositeExtract(extracted1, from1, 1), - Inst::CompositeInsert(inserted0, value0, _, 0), - Inst::CompositeInsert(inserted1, value1, inserted0_prev, 1), - ] if [from0, from1] == [call_ret_id; 2] - && [value0, value1] == [extracted0, extracted1] - && inserted0 == inserted0_prev - && inserted1 == format_args_id => - { - ( - lookup_fmt_args_ctor(callee_id)?, - call_args.iter().copied().collect(), - ) - } - _ => { - // HACK(eddyb) this gathers more context before reporting. - let mut insts = fmt_args_new_call_insts; + || cx.fmt_args_new_fn_ids.borrow().contains_key(&callee_id) + { + 1 + } else { + 0 + } + } else if matches!( + try_rev_take(-5).as_deref(), + Some(&[ + Inst::Call(call_ret_id, _, _), + Inst::CompositeExtract(extracted0, from0, 0), + Inst::CompositeExtract(extracted1, from1, 1), + Inst::CompositeInsert(inserted0, value0, _, 0), + Inst::CompositeInsert(inserted1, value1, inserted0_prev, 1), + ]) if [from0, from1] == [call_ret_id; 2] + && [value0, value1] == [extracted0, extracted1] + && inserted0 == inserted0_prev + && inserted1 == format_args_id + ) { + 5 + } else if try_rev_take(-1).is_some() { + 0 + } else { + // HACK(eddyb) gather context for new call patterns before bailing. + let mut insts = SmallVec::<[Inst; 32]>::new(); + while let Some(extra_inst) = try_rev_take(1) { + insts.extend(extra_inst); + if insts.len() >= 32 { + break; + } + } insts.reverse(); + + if insts.is_empty() { + return Ok(decoded_format_args); + } + if !insts.iter().any(|inst| matches!(inst, Inst::Call(_, _, _))) { + return Ok(decoded_format_args); + } + return Err(FormatArgsNotRecognized(format!( + "fmt::Arguments::new call sequence ({insts:?})", + ))); + }; + if fmt_args_new_call_inst_count == 0 { + // HACK(eddyb) gather context for new call patterns before bailing. + let mut insts = SmallVec::<[Inst; 32]>::new(); while let Some(extra_inst) = try_rev_take(1) { insts.extend(extra_inst); if insts.len() >= 32 { @@ -629,12 +558,76 @@ impl<'tcx> DecodedFormatArgs<'tcx> { } insts.reverse(); + if insts.is_empty() { + return Ok(decoded_format_args); + } + if !insts.iter().any(|inst| matches!(inst, Inst::Call(_, _, _))) { + return Ok(decoded_format_args); + } return Err(FormatArgsNotRecognized(format!( "fmt::Arguments::new call sequence ({insts:?})", ))); } - } - }; + let fmt_args_new_call_insts = try_rev_take(fmt_args_new_call_inst_count).unwrap(); + match fmt_args_new_call_insts[..] { + [ + Inst::Call(call_ret_id, callee_id, ref call_args), + Inst::Store(st_dst_id, st_val_id), + Inst::Load(ld_val_id, ld_src_id), + ] if call_ret_id == st_val_id + && st_dst_id == ld_src_id + && ld_val_id == format_args_id => + { + require_local_var(st_dst_id, "fmt::Arguments::new destination")?; + + ( + lookup_fmt_args_ctor(callee_id)?, + call_args.iter().copied().collect(), + ) + } + [Inst::Call(call_ret_id, callee_id, ref call_args)] + if call_ret_id == format_args_id + || cx.fmt_args_new_fn_ids.borrow().contains_key(&callee_id) => + { + ( + lookup_fmt_args_ctor(callee_id)?, + call_args.iter().copied().collect(), + ) + } + [ + Inst::Call(call_ret_id, callee_id, ref call_args), + Inst::CompositeExtract(extracted0, from0, 0), + Inst::CompositeExtract(extracted1, from1, 1), + Inst::CompositeInsert(inserted0, value0, _, 0), + Inst::CompositeInsert(inserted1, value1, inserted0_prev, 1), + ] if [from0, from1] == [call_ret_id; 2] + && [value0, value1] == [extracted0, extracted1] + && inserted0 == inserted0_prev + && inserted1 == format_args_id => + { + ( + lookup_fmt_args_ctor(callee_id)?, + call_args.iter().copied().collect(), + ) + } + _ => { + // HACK(eddyb) this gathers more context before reporting. + let mut insts = fmt_args_new_call_insts; + insts.reverse(); + while let Some(extra_inst) = try_rev_take(1) { + insts.extend(extra_inst); + if insts.len() >= 32 { + break; + } + } + insts.reverse(); + + return Err(FormatArgsNotRecognized(format!( + "fmt::Arguments::new call sequence ({insts:?})", + ))); + } + } + }; let call_args = call_args_storage.as_slice(); enum PiecesSource { Slice { ptr_id: Word, len: usize }, diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs index 86b9e511c5..0b80191fb9 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs @@ -230,9 +230,19 @@ impl<'tcx> CodegenCx<'tcx> { } let is_nonlocal = !def_id.is_local(); let is_nonlocal_core = is_nonlocal && self.tcx.crate_name(def_id.krate) == sym::core; - let is_spirv_std_byte_addressable_bounds_check = is_nonlocal - && self.tcx.def_path_str(def_id) == "spirv_std::byte_addressable_buffer::bounds_check"; - if (is_nonlocal_core && demangled_symbol_name.ends_with("::bounds_check")) + let nonlocal_def_path = is_nonlocal.then(|| self.tcx.def_path_str(def_id)); + let is_nonlocal_core_bounds_check = is_nonlocal_core + && nonlocal_def_path + .as_deref() + .is_some_and(|path| path.ends_with("::bounds_check")); + let is_nonlocal_core_precondition_check = is_nonlocal_core + && nonlocal_def_path + .as_deref() + .is_some_and(|path| path.ends_with("::precondition_check")); + let is_spirv_std_byte_addressable_bounds_check = nonlocal_def_path.as_deref() + == Some("spirv_std::byte_addressable_buffer::bounds_check"); + if is_nonlocal_core_bounds_check + || is_nonlocal_core_precondition_check || is_spirv_std_byte_addressable_bounds_check { self.panic_entry_points.borrow_mut().insert(def_id); diff --git a/tests/compiletests/ui/dis/panic_builtin_bounds_check.stderr b/tests/compiletests/ui/dis/panic_builtin_bounds_check.stderr index 5b014aff8f..2a4d3999c9 100644 --- a/tests/compiletests/ui/dis/panic_builtin_bounds_check.stderr +++ b/tests/compiletests/ui/dis/panic_builtin_bounds_check.stderr @@ -4,7 +4,7 @@ OpExtension "SPV_KHR_non_semantic_info" OpMemoryModel Logical Simple OpEntryPoint Fragment %2 "main" OpExecutionMode %2 OriginUpperLeft -%3 = OpString "/n[Rust panicked at $DIR/panic_builtin_bounds_check.rs:27:5]/n (failed to find/decode `format_args!` expansion)/n in main()/n" +%3 = OpString "/n[Rust panicked at $DIR/panic_builtin_bounds_check.rs:27:5]/n /n in main()/n" %4 = OpString "$DIR/panic_builtin_bounds_check.rs" OpDecorate %5 ArrayStride 4 %6 = OpTypeVoid From c0beae16915d87561ddcc7fd85f73d7136e40432 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 18:40:02 -0800 Subject: [PATCH 29/34] codegen: preserve panic_const messages in panic fast path --- .../src/builder/builder_methods.rs | 8 ++- .../src/builder/format_args_decompiler.rs | 54 ++++++++++++++++++- .../ui/dis/panic_sequential_many.stderr | 2 +- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index 6cd4cfdc30..32583b1688 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -3381,8 +3381,12 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { } if is_panic_entry_point { - return DecodedFormatArgs::try_decode_and_remove_format_args(self, args) - .codegen_panic(self, result_type); + return DecodedFormatArgs::try_decode_and_remove_format_args( + self, + args, + instance_def_id, + ) + .codegen_panic(self, result_type); } if buffer_load_intrinsic { return self.codegen_buffer_load_intrinsic(fn_abi, result_type, args); diff --git a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs index fbcbf86639..6a7cfbe7f9 100644 --- a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs +++ b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs @@ -12,6 +12,7 @@ use rustc_abi::BackendRepr; use rustc_data_structures::fx::FxHashSet; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; +use rustc_span::def_id::DefId; use smallvec::SmallVec; use std::borrow::Cow; use std::cell::Cell; @@ -56,6 +57,7 @@ impl<'tcx> DecodedFormatArgs<'tcx> { pub fn try_decode_and_remove_format_args<'a>( builder: &mut Builder<'a, 'tcx>, args: &[SpirvValue], + panic_def_id: Option, ) -> FormatArgsResult<'tcx> { let mut decoded_format_args = DecodedFormatArgs::default(); @@ -187,11 +189,59 @@ impl<'tcx> DecodedFormatArgs<'tcx> { Some((pieces, placeholder_count, placeholders_map_1_to_1)) }; + let panic_const_message = || { + let def_id = panic_def_id?; + let def_path = cx.tcx.def_path_str(def_id); + let name = def_path.strip_prefix("core::panicking::panic_const::")?; + match name { + "panic_const_add_overflow" => Some("attempt to add with overflow"), + "panic_const_sub_overflow" => Some("attempt to subtract with overflow"), + "panic_const_mul_overflow" => Some("attempt to multiply with overflow"), + "panic_const_div_overflow" => Some("attempt to divide with overflow"), + "panic_const_rem_overflow" => { + Some("attempt to calculate the remainder with overflow") + } + "panic_const_neg_overflow" => Some("attempt to negate with overflow"), + "panic_const_shr_overflow" => Some("attempt to shift right with overflow"), + "panic_const_shl_overflow" => Some("attempt to shift left with overflow"), + "panic_const_div_by_zero" => Some("attempt to divide by zero"), + "panic_const_rem_by_zero" => { + Some("attempt to calculate the remainder with a divisor of zero") + } + "panic_const_coroutine_resumed" => Some("coroutine resumed after completion"), + "panic_const_async_fn_resumed" => Some("`async fn` resumed after completion"), + "panic_const_async_gen_fn_resumed" => { + Some("`async gen fn` resumed after completion") + } + "panic_const_gen_fn_none" => { + Some("`gen fn` should just keep returning `None` after completion") + } + "panic_const_coroutine_resumed_panic" => Some("coroutine resumed after panicking"), + "panic_const_async_fn_resumed_panic" => Some("`async fn` resumed after panicking"), + "panic_const_async_gen_fn_resumed_panic" => { + Some("`async gen fn` resumed after panicking") + } + "panic_const_gen_fn_none_panic" => { + Some("`gen fn` should just keep returning `None` after panicking") + } + "panic_const_coroutine_resumed_drop" => Some("coroutine resumed after async drop"), + "panic_const_async_fn_resumed_drop" => Some("`async fn` resumed after async drop"), + "panic_const_async_gen_fn_resumed_drop" => { + Some("`async gen fn` resumed after async drop") + } + "panic_const_gen_fn_none_drop" => Some("`gen fn` resumed after async drop"), + _ => None, + } + }; + // HACK(eddyb) `panic_explicit` doesn't take any regular arguments, // only an (implicit) `&'static panic::Location<'static>`. if args.len() == 1 { - decoded_format_args.const_pieces = - Some(["explicit panic".into()].into_iter().collect()); + decoded_format_args.const_pieces = Some( + [panic_const_message().unwrap_or("explicit panic").into()] + .into_iter() + .collect(), + ); return Ok(decoded_format_args); } diff --git a/tests/compiletests/ui/dis/panic_sequential_many.stderr b/tests/compiletests/ui/dis/panic_sequential_many.stderr index 4c37429d15..21cd242d7c 100644 --- a/tests/compiletests/ui/dis/panic_sequential_many.stderr +++ b/tests/compiletests/ui/dis/panic_sequential_many.stderr @@ -4,7 +4,7 @@ OpExtension "SPV_KHR_non_semantic_info" OpMemoryModel Logical Simple OpEntryPoint Fragment %2 "main" %3 %4 %5 OpExecutionMode %2 OriginUpperLeft -%6 = OpString "/n[Rust panicked at $DIR/panic_sequential_many.rs:31:10]/n explicit panic/n in main()/n" +%6 = OpString "/n[Rust panicked at $DIR/panic_sequential_many.rs:31:10]/n attempt to divide by zero/n in main()/n" %7 = OpString "$DIR/panic_sequential_many.rs" OpName %3 "x" OpName %4 "y" From b54de5f177aaa63f2b005170f7be562f73668fe8 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 19:52:07 -0800 Subject: [PATCH 30/34] codegen: decode panic_bounds_check debug-printf args --- .../src/builder/format_args_decompiler.rs | 40 ++++++++++++++++++- .../ui/dis/panic_builtin_bounds_check.stderr | 4 +- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs index 6a7cfbe7f9..4b771b5b32 100644 --- a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs +++ b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs @@ -8,7 +8,7 @@ use either::Either; use itertools::Itertools; use rspirv::dr::Operand; use rspirv::spirv::{Op, Word}; -use rustc_abi::BackendRepr; +use rustc_abi::{Align, BackendRepr}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; @@ -17,6 +17,8 @@ use smallvec::SmallVec; use std::borrow::Cow; use std::cell::Cell; +use crate::maybe_pqp_cg_ssa::traits::BuilderMethods; + // HACK(eddyb) Rust 2021 `panic!` always uses `format_args!`, even // in the simple case that used to pass a `&str` constant, which // would not remain reachable in the SPIR-V - but `format_args!` is @@ -233,6 +235,42 @@ impl<'tcx> DecodedFormatArgs<'tcx> { _ => None, } }; + let mut spill_value_to_local = |value: SpirvValue| { + let ptr = builder.typed_alloca(value.ty, Align::ONE); + builder.store(value, ptr, Align::ONE); + match ptr.kind { + SpirvValueKind::Def(id) => Some(id), + _ => None, + } + }; + + if panic_def_id.is_some_and(|def_id| { + cx.tcx.def_path_str(def_id) == "core::panicking::panic_bounds_check" + }) && args.len() >= 2 + { + let index = args[0].clone(); + let len = args[1].clone(); + if let (Some(len_ref_id), Some(index_ref_id)) = + (spill_value_to_local(len), spill_value_to_local(index)) + { + decoded_format_args.const_pieces = Some( + [ + "index out of bounds: the len is ".into(), + " but the index is ".into(), + String::new(), + ] + .into_iter() + .collect(), + ); + decoded_format_args.ref_arg_ids_with_ty_and_spec = [ + (len_ref_id, cx.tcx.types.usize, ' '), + (index_ref_id, cx.tcx.types.usize, ' '), + ] + .into_iter() + .collect(); + return Ok(decoded_format_args); + } + } // HACK(eddyb) `panic_explicit` doesn't take any regular arguments, // only an (implicit) `&'static panic::Location<'static>`. diff --git a/tests/compiletests/ui/dis/panic_builtin_bounds_check.stderr b/tests/compiletests/ui/dis/panic_builtin_bounds_check.stderr index 2a4d3999c9..2a6a8e7746 100644 --- a/tests/compiletests/ui/dis/panic_builtin_bounds_check.stderr +++ b/tests/compiletests/ui/dis/panic_builtin_bounds_check.stderr @@ -4,7 +4,7 @@ OpExtension "SPV_KHR_non_semantic_info" OpMemoryModel Logical Simple OpEntryPoint Fragment %2 "main" OpExecutionMode %2 OriginUpperLeft -%3 = OpString "/n[Rust panicked at $DIR/panic_builtin_bounds_check.rs:27:5]/n /n in main()/n" +%3 = OpString "/n[Rust panicked at $DIR/panic_builtin_bounds_check.rs:27:5]/n index out of bounds: the len is %u but the index is %u/n in main()/n" %4 = OpString "$DIR/panic_builtin_bounds_check.rs" OpDecorate %5 ArrayStride 4 %6 = OpTypeVoid @@ -43,7 +43,7 @@ OpBranchConditional %27 %29 %30 OpBranch %28 %30 = OpLabel OpLine %4 27 4 -%31 = OpExtInst %6 %1 1 %3 +%31 = OpExtInst %6 %1 1 %3 %9 %17 OpNoLine OpReturn %28 = OpLabel From c3c424a6f522b9f527aca6747a504cdc579dca15 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 19:52:15 -0800 Subject: [PATCH 31/34] compiletests: normalize relative spirv-std paths in stderr --- .../ui/arch/debug_printf_type_checking.rs | 1 + .../ui/arch/debug_printf_type_checking.stderr | 42 +++++++++---------- .../subgroup/subgroup_cluster_size_0_fail.rs | 2 + .../subgroup_cluster_size_0_fail.stderr | 12 +++--- ...roup_cluster_size_non_power_of_two_fail.rs | 2 + ..._cluster_size_non_power_of_two_fail.stderr | 12 +++--- .../subgroup/subgroup_composite_enum_err.rs | 1 + .../ui/dis/ptr_copy.normal.stderr | 10 ++--- tests/compiletests/ui/dis/ptr_copy.rs | 1 + .../ui/dis/ptr_copy.via_intrinsic.stderr | 2 +- tests/compiletests/ui/image/gather_err.rs | 1 + tests/compiletests/ui/image/gather_err.stderr | 24 +++++------ .../ui/image/query/query_levels_err.rs | 1 + .../ui/image/query/query_levels_err.stderr | 14 +++---- .../ui/image/query/query_lod_err.rs | 1 + .../ui/image/query/query_lod_err.stderr | 14 +++---- .../ui/image/query/query_size_err.rs | 1 + .../ui/image/query/query_size_err.stderr | 4 +- .../ui/image/query/query_size_lod_err.rs | 1 + .../ui/image/query/query_size_lod_err.stderr | 14 +++---- .../sampled_image_rect_query_size_lod_err.rs | 3 +- ...mpled_image_rect_query_size_lod_err.stderr | 12 +++--- 22 files changed, 94 insertions(+), 81 deletions(-) diff --git a/tests/compiletests/ui/arch/debug_printf_type_checking.rs b/tests/compiletests/ui/arch/debug_printf_type_checking.rs index 5efe7ecd3a..3f6be184d3 100644 --- a/tests/compiletests/ui/arch/debug_printf_type_checking.rs +++ b/tests/compiletests/ui/arch/debug_printf_type_checking.rs @@ -1,5 +1,6 @@ // build-fail // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" +// normalize-stderr-test "crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // compile-flags: -Ctarget-feature=+ext:SPV_KHR_non_semantic_info use spirv_std::spirv; diff --git a/tests/compiletests/ui/arch/debug_printf_type_checking.stderr b/tests/compiletests/ui/arch/debug_printf_type_checking.stderr index 35e91acb44..126cadfecb 100644 --- a/tests/compiletests/ui/arch/debug_printf_type_checking.stderr +++ b/tests/compiletests/ui/arch/debug_printf_type_checking.stderr @@ -1,65 +1,65 @@ error: Unterminated format specifier: missing type after precision - --> $DIR/debug_printf_type_checking.rs:11:23 + --> $DIR/debug_printf_type_checking.rs:12:23 | LL | debug_printf!("%1"); | ^^^^ error: Unterminated format specifier: missing type after decimal point - --> $DIR/debug_printf_type_checking.rs:12:23 + --> $DIR/debug_printf_type_checking.rs:13:23 | LL | debug_printf!("%1."); | ^^^^^ error: Unrecognised format specifier: '.' - --> $DIR/debug_printf_type_checking.rs:13:23 + --> $DIR/debug_printf_type_checking.rs:14:23 | LL | debug_printf!("%."); | ^^^^ error: Unrecognised format specifier: '.' - --> $DIR/debug_printf_type_checking.rs:14:23 + --> $DIR/debug_printf_type_checking.rs:15:23 | LL | debug_printf!("%.1"); | ^^^^^ error: Unterminated format specifier: missing type after fraction precision - --> $DIR/debug_printf_type_checking.rs:15:23 + --> $DIR/debug_printf_type_checking.rs:16:23 | LL | debug_printf!("%1.1"); | ^^^^^^ error: Missing vector dimensions specifier - --> $DIR/debug_printf_type_checking.rs:16:23 + --> $DIR/debug_printf_type_checking.rs:17:23 | LL | debug_printf!("%1.1v"); | ^^^^^^^ error: Invalid width for vector: 5 - --> $DIR/debug_printf_type_checking.rs:17:23 + --> $DIR/debug_printf_type_checking.rs:18:23 | LL | debug_printf!("%1.1v5"); | ^^^^^^^^ error: Missing vector type specifier - --> $DIR/debug_printf_type_checking.rs:18:23 + --> $DIR/debug_printf_type_checking.rs:19:23 | LL | debug_printf!("%1.1v2"); | ^^^^^^^^ error: Unrecognised vector type specifier: 'r' - --> $DIR/debug_printf_type_checking.rs:19:23 + --> $DIR/debug_printf_type_checking.rs:20:23 | LL | debug_printf!("%1.1v2r"); | ^^^^^^^^^ error: Unrecognised format specifier: 'r' - --> $DIR/debug_printf_type_checking.rs:20:23 + --> $DIR/debug_printf_type_checking.rs:21:23 | LL | debug_printf!("%r", 11_i32); | ^^^^ error[E0308]: mismatched types - --> $DIR/debug_printf_type_checking.rs:21:29 + --> $DIR/debug_printf_type_checking.rs:22:29 | LL | debug_printf!("%f", 11_u32); | --------------------^^^^^^- @@ -68,14 +68,14 @@ LL | debug_printf!("%f", 11_u32); | arguments to this function are incorrect | help: the return type of this call is `u32` due to the type of the argument passed - --> $DIR/debug_printf_type_checking.rs:21:9 + --> $DIR/debug_printf_type_checking.rs:22:9 | LL | debug_printf!("%f", 11_u32); | ^^^^^^^^^^^^^^^^^^^^------^ | | | this argument influences the return type of `assert_is_type` note: function defined here - --> crates/spirv-std/src/debug_printf.rs:6:7 + --> $SPIRV_STD_SRC/debug_printf.rs:6:7 = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) help: change the type of the numeric literal from `u32` to `f32` | @@ -84,7 +84,7 @@ LL + debug_printf!("%f", 11_f32); | error[E0308]: mismatched types - --> $DIR/debug_printf_type_checking.rs:22:29 + --> $DIR/debug_printf_type_checking.rs:23:29 | LL | debug_printf!("%u", 11.0_f32); | --------------------^^^^^^^^- @@ -93,14 +93,14 @@ LL | debug_printf!("%u", 11.0_f32); | arguments to this function are incorrect | help: the return type of this call is `f32` due to the type of the argument passed - --> $DIR/debug_printf_type_checking.rs:22:9 + --> $DIR/debug_printf_type_checking.rs:23:9 | LL | debug_printf!("%u", 11.0_f32); | ^^^^^^^^^^^^^^^^^^^^--------^ | | | this argument influences the return type of `assert_is_type` note: function defined here - --> crates/spirv-std/src/debug_printf.rs:6:7 + --> $SPIRV_STD_SRC/debug_printf.rs:6:7 = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) help: change the type of the numeric literal from `f32` to `u32` | @@ -109,7 +109,7 @@ LL + debug_printf!("%u", 11u32); | error[E0277]: the trait bound `{float}: spirv_std::Vector` is not satisfied - --> $DIR/debug_printf_type_checking.rs:23:9 + --> $DIR/debug_printf_type_checking.rs:24:9 | LL | debug_printf!("%v2f", 11.0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `spirv_std::Vector` is not implemented for `{float}` @@ -125,11 +125,11 @@ LL | debug_printf!("%v2f", 11.0); `IVec3` implements `spirv_std::Vector` and 8 others note: required by a bound in `spirv_std::debug_printf::assert_is_vector` - --> crates/spirv-std/src/debug_printf.rs:11:0 + --> $SPIRV_STD_SRC/debug_printf.rs:11:0 = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/debug_printf_type_checking.rs:24:29 + --> $DIR/debug_printf_type_checking.rs:25:29 | LL | debug_printf!("%f", Vec2::splat(33.3)); | --------------------^^^^^^^^^^^^^^^^^- @@ -138,14 +138,14 @@ LL | debug_printf!("%f", Vec2::splat(33.3)); | arguments to this function are incorrect | help: the return type of this call is `Vec2` due to the type of the argument passed - --> $DIR/debug_printf_type_checking.rs:24:9 + --> $DIR/debug_printf_type_checking.rs:25:9 | LL | debug_printf!("%f", Vec2::splat(33.3)); | ^^^^^^^^^^^^^^^^^^^^-----------------^ | | | this argument influences the return type of `assert_is_type` note: function defined here - --> crates/spirv-std/src/debug_printf.rs:6:7 + --> $SPIRV_STD_SRC/debug_printf.rs:6:7 = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 14 previous errors diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.rs b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.rs index be91429d86..4b06f08bc3 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.rs +++ b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.rs @@ -1,7 +1,9 @@ // build-pass // compile-flags: -C target-feature=+GroupNonUniform,+GroupNonUniformArithmetic,+GroupNonUniformClustered,+ext:SPV_KHR_vulkan_memory_model // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" +// normalize-stderr-test "crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // normalize-stderr-test "\S*/lib/rustlib/" -> "$$SYSROOT/lib/rustlib/" +// normalize-stderr-test "\$SYSROOT/lib/rustlib/src/rust/library/core/src/panic.rs:\d+:\d+" -> "$$SYSROOT/lib/rustlib/src/rust/library/core/src/panic.rs:LL:CC" use glam::UVec3; use spirv_std::arch::{GroupOperation, SubgroupMask}; diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.stderr index b2036d1478..8f3203c360 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.stderr +++ b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_0_fail.stderr @@ -1,26 +1,26 @@ error[E0080]: evaluation panicked: `ClusterSize` must be at least 1 - --> $SYSROOT/lib/rustlib/src/rust/library/core/src/panic.rs:62:9 + --> $SYSROOT/lib/rustlib/src/rust/library/core/src/panic.rs:LL:CC | LL | $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `spirv_std::arch::subgroup_clustered_i_add::<0, u32, u32>::{constant#0}` failed here | - --> crates/spirv-std/src/arch/subgroup.rs:937:0 - ::: crates/spirv-std/src/arch/subgroup.rs:954:2 + --> $SPIRV_STD_SRC/arch/subgroup.rs:937:0 + ::: $SPIRV_STD_SRC/arch/subgroup.rs:954:2 | = note: in this macro invocation | = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `macro_subgroup_op_clustered` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered - --> crates/spirv-std/src/arch/subgroup.rs:890:12 - ::: crates/spirv-std/src/arch/subgroup.rs:954:2 + --> $SPIRV_STD_SRC/arch/subgroup.rs:890:12 + ::: $SPIRV_STD_SRC/arch/subgroup.rs:954:2 | = note: in this macro invocation | = note: this note originates in the macro `macro_subgroup_op_clustered` (in Nightly builds, run with -Z macro-backtrace for more info) note: the above error was encountered while instantiating `fn subgroup_clustered_i_add::<0, u32, u32>` - --> $DIR/subgroup_cluster_size_0_fail.rs:11:5 + --> $DIR/subgroup_cluster_size_0_fail.rs:13:5 | LL | spirv_std::arch::subgroup_clustered_i_add::<0, _>(value) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.rs b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.rs index 685771fc89..295ebd83e6 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.rs +++ b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.rs @@ -1,7 +1,9 @@ // build-pass // compile-flags: -C target-feature=+GroupNonUniform,+GroupNonUniformArithmetic,+GroupNonUniformClustered,+ext:SPV_KHR_vulkan_memory_model // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" +// normalize-stderr-test "crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // normalize-stderr-test "\S*/lib/rustlib/" -> "$$SYSROOT/lib/rustlib/" +// normalize-stderr-test "\$SYSROOT/lib/rustlib/src/rust/library/core/src/panic.rs:\d+:\d+" -> "$$SYSROOT/lib/rustlib/src/rust/library/core/src/panic.rs:LL:CC" use glam::UVec3; use spirv_std::arch::{GroupOperation, SubgroupMask}; diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.stderr index 9d387e13fd..c5d4993cdb 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.stderr +++ b/tests/compiletests/ui/arch/subgroup/subgroup_cluster_size_non_power_of_two_fail.stderr @@ -1,26 +1,26 @@ error[E0080]: evaluation panicked: `ClusterSize` must be a power of 2 - --> $SYSROOT/lib/rustlib/src/rust/library/core/src/panic.rs:62:9 + --> $SYSROOT/lib/rustlib/src/rust/library/core/src/panic.rs:LL:CC | LL | $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `spirv_std::arch::subgroup_clustered_i_add::<5, u32, u32>::{constant#0}` failed here | - --> crates/spirv-std/src/arch/subgroup.rs:937:0 - ::: crates/spirv-std/src/arch/subgroup.rs:954:2 + --> $SPIRV_STD_SRC/arch/subgroup.rs:937:0 + ::: $SPIRV_STD_SRC/arch/subgroup.rs:954:2 | = note: in this macro invocation | = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `macro_subgroup_op_clustered` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered - --> crates/spirv-std/src/arch/subgroup.rs:890:12 - ::: crates/spirv-std/src/arch/subgroup.rs:954:2 + --> $SPIRV_STD_SRC/arch/subgroup.rs:890:12 + ::: $SPIRV_STD_SRC/arch/subgroup.rs:954:2 | = note: in this macro invocation | = note: this note originates in the macro `macro_subgroup_op_clustered` (in Nightly builds, run with -Z macro-backtrace for more info) note: the above error was encountered while instantiating `fn subgroup_clustered_i_add::<5, u32, u32>` - --> $DIR/subgroup_cluster_size_non_power_of_two_fail.rs:11:5 + --> $DIR/subgroup_cluster_size_non_power_of_two_fail.rs:13:5 | LL | spirv_std::arch::subgroup_clustered_i_add::<5, _>(value) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_composite_enum_err.rs b/tests/compiletests/ui/arch/subgroup/subgroup_composite_enum_err.rs index 0579efeeaf..f01b3c4a89 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_composite_enum_err.rs +++ b/tests/compiletests/ui/arch/subgroup/subgroup_composite_enum_err.rs @@ -1,5 +1,6 @@ // build-fail // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" +// normalize-stderr-test "crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // normalize-stderr-test "\.rs:\d+:\d+" -> ".rs:" // normalize-stderr-test "(\n)\d* *([ -])([\|\+\-\=])" -> "$1 $2$3" diff --git a/tests/compiletests/ui/dis/ptr_copy.normal.stderr b/tests/compiletests/ui/dis/ptr_copy.normal.stderr index 4061062671..34c4431e71 100644 --- a/tests/compiletests/ui/dis/ptr_copy.normal.stderr +++ b/tests/compiletests/ui/dis/ptr_copy.normal.stderr @@ -1,26 +1,26 @@ error: cannot memcpy dynamically sized data - --> $CORE_SRC/ptr/mod.rs>:642:9 + --> <$CORE_SRC/ptr/mod.rs>:642:9 | LL | crate::intrinsics::copy(src, dst, count) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: used from within `core::ptr::copy::` - --> $CORE_SRC/ptr/mod.rs>:627:21 + --> <$CORE_SRC/ptr/mod.rs>:627:21 | LL | pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { | ^^^^ note: called by `ptr_copy::copy_via_raw_ptr` - --> <$DIR/ptr_copy.rs>:28:18 + --> <$DIR/ptr_copy.rs>:29:18 | LL | unsafe { core::ptr::copy(src, dst, 1) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: called by `ptr_copy::main` - --> <$DIR/ptr_copy.rs>:33:5 + --> <$DIR/ptr_copy.rs>:34:5 | LL | copy_via_raw_ptr(&i, o); | ^^^^^^^^^^^^^^^^^^^^^^^ note: called by `main` - --> <$DIR/ptr_copy.rs>:32:8 + --> <$DIR/ptr_copy.rs>:33:8 | LL | pub fn main(i: f32, o: &mut f32) { | ^^^^ diff --git a/tests/compiletests/ui/dis/ptr_copy.rs b/tests/compiletests/ui/dis/ptr_copy.rs index 59a08ce76b..2ff840b91a 100644 --- a/tests/compiletests/ui/dis/ptr_copy.rs +++ b/tests/compiletests/ui/dis/ptr_copy.rs @@ -1,5 +1,6 @@ // revisions: normal via_intrinsic //[normal] build-fail +// normalize-stderr-test "<\S*/library/core/src/" -> "<$$CORE_SRC/" // normalize-stderr-test "\S*/library/core/src/" -> "$$CORE_SRC/" //[via_intrinsic] build-pass // compile-flags: -C llvm-args=--disassemble-fn=ptr_copy::copy_via_raw_ptr diff --git a/tests/compiletests/ui/dis/ptr_copy.via_intrinsic.stderr b/tests/compiletests/ui/dis/ptr_copy.via_intrinsic.stderr index cb2adb4cbb..6297ea7fea 100644 --- a/tests/compiletests/ui/dis/ptr_copy.via_intrinsic.stderr +++ b/tests/compiletests/ui/dis/ptr_copy.via_intrinsic.stderr @@ -2,7 +2,7 @@ %4 = OpFunctionParameter %5 %6 = OpFunctionParameter %5 %7 = OpLabel -OpLine %8 17 17 +OpLine %8 18 17 OpCopyMemory %6 %4 OpNoLine OpReturn diff --git a/tests/compiletests/ui/image/gather_err.rs b/tests/compiletests/ui/image/gather_err.rs index e44da14565..74bf4a6b4e 100644 --- a/tests/compiletests/ui/image/gather_err.rs +++ b/tests/compiletests/ui/image/gather_err.rs @@ -1,5 +1,6 @@ // build-fail // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" +// normalize-stderr-test "crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // compile-flags: -Ctarget-feature=+Sampled1D use spirv_std::{Image, Sampler, arch, spirv}; diff --git a/tests/compiletests/ui/image/gather_err.stderr b/tests/compiletests/ui/image/gather_err.stderr index d1ca9781c6..be5333a14c 100644 --- a/tests/compiletests/ui/image/gather_err.stderr +++ b/tests/compiletests/ui/image/gather_err.stderr @@ -1,43 +1,43 @@ error[E0277]: the trait bound `Image: HasGather` is not satisfied - --> $DIR/gather_err.rs:15:34 + --> $DIR/gather_err.rs:16:34 | LL | let r1: glam::Vec4 = image1d.gather(*sampler, 0.0f32, 0); | ^^^^^^ the trait `HasGather` is not implemented for `Image` | help: the following other types implement trait `HasGather` - --> crates/spirv-std/src/image.rs:1652:0 - ::: crates/spirv-std/src/image.rs:1669:5 + --> $SPIRV_STD_SRC/image.rs:1652:0 + ::: $SPIRV_STD_SRC/image.rs:1669:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:1689:5 + ::: $SPIRV_STD_SRC/image.rs:1689:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:1709:5 + ::: $SPIRV_STD_SRC/image.rs:1709:5 | = note: `Image` note: required by a bound in `Image::::gather` - --> crates/spirv-std/src/image.rs:190:4 + --> $SPIRV_STD_SRC/image.rs:190:4 = note: this error originates in the attribute macro `crate::macros::gpu_only` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Image: HasGather` is not satisfied - --> $DIR/gather_err.rs:16:34 + --> $DIR/gather_err.rs:17:34 | LL | let r2: glam::Vec4 = image3d.gather(*sampler, v3, 0); | ^^^^^^ the trait `HasGather` is not implemented for `Image` | help: the following other types implement trait `HasGather` - --> crates/spirv-std/src/image.rs:1652:0 - ::: crates/spirv-std/src/image.rs:1669:5 + --> $SPIRV_STD_SRC/image.rs:1652:0 + ::: $SPIRV_STD_SRC/image.rs:1669:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:1689:5 + ::: $SPIRV_STD_SRC/image.rs:1689:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:1709:5 + ::: $SPIRV_STD_SRC/image.rs:1709:5 | = note: `Image` note: required by a bound in `Image::::gather` - --> crates/spirv-std/src/image.rs:190:4 + --> $SPIRV_STD_SRC/image.rs:190:4 = note: this error originates in the attribute macro `crate::macros::gpu_only` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/compiletests/ui/image/query/query_levels_err.rs b/tests/compiletests/ui/image/query/query_levels_err.rs index 1fa5581a41..56ca4f6702 100644 --- a/tests/compiletests/ui/image/query/query_levels_err.rs +++ b/tests/compiletests/ui/image/query/query_levels_err.rs @@ -1,5 +1,6 @@ // build-fail // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" +// normalize-stderr-test "crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // compile-flags: -C target-feature=+ImageQuery use spirv_std::{Image, arch, spirv}; diff --git a/tests/compiletests/ui/image/query/query_levels_err.stderr b/tests/compiletests/ui/image/query/query_levels_err.stderr index 7f86ab980e..7c263b28b1 100644 --- a/tests/compiletests/ui/image/query/query_levels_err.stderr +++ b/tests/compiletests/ui/image/query/query_levels_err.stderr @@ -1,25 +1,25 @@ error[E0277]: the trait bound `Image: HasQueryLevels` is not satisfied - --> $DIR/query_levels_err.rs:12:21 + --> $DIR/query_levels_err.rs:13:21 | LL | *output = image.query_levels(); | ^^^^^^^^^^^^ the trait `HasQueryLevels` is not implemented for `Image` | help: the following other types implement trait `HasQueryLevels` - --> crates/spirv-std/src/image.rs:1718:0 - ::: crates/spirv-std/src/image.rs:1736:5 + --> $SPIRV_STD_SRC/image.rs:1718:0 + ::: $SPIRV_STD_SRC/image.rs:1736:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:1757:5 + ::: $SPIRV_STD_SRC/image.rs:1757:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:1778:5 + ::: $SPIRV_STD_SRC/image.rs:1778:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:1799:5 + ::: $SPIRV_STD_SRC/image.rs:1799:5 | = note: `Image` note: required by a bound in `Image::::query_levels` - --> crates/spirv-std/src/image.rs:966:4 + --> $SPIRV_STD_SRC/image.rs:966:4 = note: this error originates in the attribute macro `crate::macros::gpu_only` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/compiletests/ui/image/query/query_lod_err.rs b/tests/compiletests/ui/image/query/query_lod_err.rs index 74e86972f1..19e6b40f09 100644 --- a/tests/compiletests/ui/image/query/query_lod_err.rs +++ b/tests/compiletests/ui/image/query/query_lod_err.rs @@ -1,5 +1,6 @@ // build-fail // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" +// normalize-stderr-test "crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // compile-flags: -C target-feature=+ImageQuery use spirv_std::{Image, Sampler, arch, spirv}; diff --git a/tests/compiletests/ui/image/query/query_lod_err.stderr b/tests/compiletests/ui/image/query/query_lod_err.stderr index eec51e82e8..4f61b4d940 100644 --- a/tests/compiletests/ui/image/query/query_lod_err.stderr +++ b/tests/compiletests/ui/image/query/query_lod_err.stderr @@ -1,25 +1,25 @@ error[E0277]: the trait bound `Image: HasQueryLevels` is not satisfied - --> $DIR/query_lod_err.rs:13:21 + --> $DIR/query_lod_err.rs:14:21 | LL | *output = image.query_lod(*sampler, glam::Vec2::new(0.0, 1.0)); | ^^^^^^^^^ the trait `HasQueryLevels` is not implemented for `Image` | help: the following other types implement trait `HasQueryLevels` - --> crates/spirv-std/src/image.rs:1718:0 - ::: crates/spirv-std/src/image.rs:1736:5 + --> $SPIRV_STD_SRC/image.rs:1718:0 + ::: $SPIRV_STD_SRC/image.rs:1736:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:1757:5 + ::: $SPIRV_STD_SRC/image.rs:1757:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:1778:5 + ::: $SPIRV_STD_SRC/image.rs:1778:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:1799:5 + ::: $SPIRV_STD_SRC/image.rs:1799:5 | = note: `Image` note: required by a bound in `Image::::query_lod` - --> crates/spirv-std/src/image.rs:992:4 + --> $SPIRV_STD_SRC/image.rs:992:4 = note: this error originates in the attribute macro `crate::macros::gpu_only` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/compiletests/ui/image/query/query_size_err.rs b/tests/compiletests/ui/image/query/query_size_err.rs index c526f3bd6b..18b10007fd 100644 --- a/tests/compiletests/ui/image/query/query_size_err.rs +++ b/tests/compiletests/ui/image/query/query_size_err.rs @@ -1,5 +1,6 @@ // build-fail // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" +// normalize-stderr-test "crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // compile-flags: -C target-feature=+ImageQuery use spirv_std::{Image, arch, spirv}; diff --git a/tests/compiletests/ui/image/query/query_size_err.stderr b/tests/compiletests/ui/image/query/query_size_err.stderr index 2fc76db3d5..ae5e4531ad 100644 --- a/tests/compiletests/ui/image/query/query_size_err.stderr +++ b/tests/compiletests/ui/image/query/query_size_err.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Image: HasQuerySize` is not satisfied - --> $DIR/query_size_err.rs:12:21 + --> $DIR/query_size_err.rs:13:21 | LL | *output = image.query_size(); | ^^^^^^^^^^ the trait `HasQuerySize` is not implemented for `Image` @@ -15,7 +15,7 @@ LL | *output = image.query_size(); Image and 6 others note: required by a bound in `Image::::query_size` - --> crates/spirv-std/src/image.rs:1032:4 + --> $SPIRV_STD_SRC/image.rs:1032:4 = note: this error originates in the attribute macro `crate::macros::gpu_only` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/compiletests/ui/image/query/query_size_lod_err.rs b/tests/compiletests/ui/image/query/query_size_lod_err.rs index 8b2e9e8ff1..63ba128801 100644 --- a/tests/compiletests/ui/image/query/query_size_lod_err.rs +++ b/tests/compiletests/ui/image/query/query_size_lod_err.rs @@ -1,5 +1,6 @@ // build-fail // normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" +// normalize-stderr-test "crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // compile-flags: -C target-feature=+ImageQuery use spirv_std::{Image, arch, spirv}; diff --git a/tests/compiletests/ui/image/query/query_size_lod_err.stderr b/tests/compiletests/ui/image/query/query_size_lod_err.stderr index 734631bae3..26400e2327 100644 --- a/tests/compiletests/ui/image/query/query_size_lod_err.stderr +++ b/tests/compiletests/ui/image/query/query_size_lod_err.stderr @@ -1,25 +1,25 @@ error[E0277]: the trait bound `Image: HasQuerySizeLod` is not satisfied - --> $DIR/query_size_lod_err.rs:12:21 + --> $DIR/query_size_lod_err.rs:13:21 | LL | *output = image.query_size_lod(0); | ^^^^^^^^^^^^^^ the trait `HasQuerySizeLod` is not implemented for `Image` | help: the following other types implement trait `HasQuerySizeLod` - --> crates/spirv-std/src/image.rs:2089:0 - ::: crates/spirv-std/src/image.rs:2106:5 + --> $SPIRV_STD_SRC/image.rs:2089:0 + ::: $SPIRV_STD_SRC/image.rs:2106:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:2126:5 + ::: $SPIRV_STD_SRC/image.rs:2126:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:2146:5 + ::: $SPIRV_STD_SRC/image.rs:2146:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:2166:5 + ::: $SPIRV_STD_SRC/image.rs:2166:5 | = note: `Image` note: required by a bound in `Image::::query_size_lod` - --> crates/spirv-std/src/image.rs:1076:4 + --> $SPIRV_STD_SRC/image.rs:1076:4 = note: this error originates in the attribute macro `crate::macros::gpu_only` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.rs b/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.rs index acfe0a61a3..c12a9d8863 100644 --- a/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.rs +++ b/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.rs @@ -1,5 +1,6 @@ // build-fail -// normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$SPIRV_STD_SRC/" +// normalize-stderr-test "\S*/crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" +// normalize-stderr-test "crates/spirv-std/src/" -> "$$SPIRV_STD_SRC/" // compile-flags: -C target-feature=+ImageQuery,+SampledRect // ignore-vulkan1.0 // ignore-vulkan1.1 diff --git a/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr b/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr index ebbe4c2b9a..f95c0b1825 100644 --- a/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr +++ b/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr @@ -5,21 +5,21 @@ LL | *output = rect_sampled.query_size_lod(0); | ^^^^^^^^^^^^^^ the trait `HasQuerySizeLod` is not implemented for `Image` | help: the following other types implement trait `HasQuerySizeLod` - --> crates/spirv-std/src/image.rs:2089:0 - ::: crates/spirv-std/src/image.rs:2106:5 + --> $SPIRV_STD_SRC/image.rs:2089:0 + ::: $SPIRV_STD_SRC/image.rs:2106:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:2126:5 + ::: $SPIRV_STD_SRC/image.rs:2126:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:2146:5 + ::: $SPIRV_STD_SRC/image.rs:2146:5 | = note: `Image` - ::: crates/spirv-std/src/image.rs:2166:5 + ::: $SPIRV_STD_SRC/image.rs:2166:5 | = note: `Image` note: required by a bound in `SampledImage::>::query_size_lod` - --> crates/spirv-std/src/image.rs:1236:4 + --> $SPIRV_STD_SRC/image.rs:1236:4 = note: this error originates in the attribute macro `crate::macros::gpu_only` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error From 7e26485e3f1421e21c08847b5edcaebb1d91a1c1 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 21:10:42 -0800 Subject: [PATCH 32/34] fix lint and spv1.3 stderr for panic/message updates --- .../rustc_codegen_spirv/src/builder/format_args_decompiler.rs | 4 ++-- .../image/query/sampled_image_rect_query_size_lod_err.stderr | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs index 4b771b5b32..ec12725676 100644 --- a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs +++ b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs @@ -248,8 +248,8 @@ impl<'tcx> DecodedFormatArgs<'tcx> { cx.tcx.def_path_str(def_id) == "core::panicking::panic_bounds_check" }) && args.len() >= 2 { - let index = args[0].clone(); - let len = args[1].clone(); + let index = args[0]; + let len = args[1]; if let (Some(len_ref_id), Some(index_ref_id)) = (spill_value_to_local(len), spill_value_to_local(index)) { diff --git a/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr b/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr index f95c0b1825..74c76374c0 100644 --- a/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr +++ b/tests/compiletests/ui/image/query/sampled_image_rect_query_size_lod_err.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Image: HasQuerySizeLod` is not satisfied - --> $DIR/sampled_image_rect_query_size_lod_err.rs:21:28 + --> $DIR/sampled_image_rect_query_size_lod_err.rs:22:28 | LL | *output = rect_sampled.query_size_lod(0); | ^^^^^^^^^^^^^^ the trait `HasQuerySizeLod` is not implemented for `Image` From 90926fd3250b57987377f59a798c4a469eb212e1 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 21:18:16 -0800 Subject: [PATCH 33/34] codegen: use size-based alloca for panic arg spill --- .../src/builder/format_args_decompiler.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs index ec12725676..5346a7ea36 100644 --- a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs +++ b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs @@ -236,7 +236,11 @@ impl<'tcx> DecodedFormatArgs<'tcx> { } }; let mut spill_value_to_local = |value: SpirvValue| { - let ptr = builder.typed_alloca(value.ty, Align::ONE); + let size = builder + .lookup_type(value.ty) + .sizeof(builder) + .expect("panic argument should have a sized type"); + let ptr = builder.alloca(size, Align::ONE); builder.store(value, ptr, Align::ONE); match ptr.kind { SpirvValueKind::Def(id) => Some(id), From 2fe48e07cfa33a337830f904d66a34e1429390d8 Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Fri, 6 Mar 2026 21:25:45 -0800 Subject: [PATCH 34/34] codegen: emit typed local panic spills without typed_alloca --- .../src/builder/format_args_decompiler.rs | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs index 5346a7ea36..6b0e63b247 100644 --- a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs +++ b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs @@ -6,8 +6,8 @@ use crate::custom_insts::CustomOp; use crate::spirv_type::SpirvType; use either::Either; use itertools::Itertools; -use rspirv::dr::Operand; -use rspirv::spirv::{Op, Word}; +use rspirv::dr::{InsertPoint, Instruction, Operand}; +use rspirv::spirv::{Op, StorageClass, Word}; use rustc_abi::{Align, BackendRepr}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::ty::Ty; @@ -236,11 +236,37 @@ impl<'tcx> DecodedFormatArgs<'tcx> { } }; let mut spill_value_to_local = |value: SpirvValue| { - let size = builder - .lookup_type(value.ty) - .sizeof(builder) - .expect("panic argument should have a sized type"); - let ptr = builder.alloca(size, Align::ONE); + let ptr_ty = builder.type_ptr_to(value.ty); + + let ptr = { + // `OpVariable`s in functions must be inserted at the start of the + // first block, before any non-`OpVariable` instruction. + let mut emit = builder.emit(); + emit.select_block(Some(0)).unwrap(); + let index = { + let block = &emit.module_ref().functions[emit.selected_function().unwrap()] + .blocks[emit.selected_block().unwrap()]; + block + .instructions + .iter() + .enumerate() + .find_map(|(index, inst)| { + (inst.class.opcode != Op::Variable) + .then_some(InsertPoint::FromBegin(index)) + }) + .unwrap_or(InsertPoint::End) + }; + let result_id = emit.id(); + let inst = Instruction::new( + Op::Variable, + Some(ptr_ty), + Some(result_id), + vec![Operand::StorageClass(StorageClass::Function)], + ); + emit.insert_into_block(index, inst).unwrap(); + result_id.with_type(ptr_ty) + }; + builder.store(value, ptr, Align::ONE); match ptr.kind { SpirvValueKind::Def(id) => Some(id),