From d9e7ed6743760600fb3ebd8dabe2146abd1be35b Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 2 Jul 2025 05:12:44 +0300 Subject: [PATCH 1/4] rustup: update to `nightly-2025-06-23` (~1.89). --- crates/rustc_codegen_spirv/build.rs | 14 +- crates/rustc_codegen_spirv/src/abi.rs | 46 +- .../src/builder/builder_methods.rs | 32 +- .../src/builder/intrinsics.rs | 24 +- crates/rustc_codegen_spirv/src/builder/mod.rs | 9 - .../src/codegen_cx/declare.rs | 66 ++- .../rustc_codegen_spirv/src/codegen_cx/mod.rs | 4 - crates/rustc_codegen_spirv/src/lib.rs | 43 +- crates/rustc_codegen_spirv/src/link.rs | 23 +- crates/rustc_codegen_spirv/src/linker/test.rs | 22 +- crates/spirv-builder/src/lib.rs | 7 + rust-toolchain.toml | 4 +- tests/compiletests/src/main.rs | 7 + .../subgroup_cluster_size_0_fail.stderr | 4 +- ..._cluster_size_non_power_of_two_fail.stderr | 4 +- tests/compiletests/ui/dis/issue-1062.stderr | 2 +- .../ui/dis/panic_builtin_bounds_check.stderr | 58 +-- .../ui/dis/panic_sequential_many.stderr | 419 +++++++++--------- .../ui/dis/ptr_copy.normal.stderr | 108 ++--- 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 +- .../ui/lang/core/unwrap_or.stderr | 4 +- 24 files changed, 497 insertions(+), 411 deletions(-) diff --git a/crates/rustc_codegen_spirv/build.rs b/crates/rustc_codegen_spirv/build.rs index 7bb8ca3eed..d68757267a 100644 --- a/crates/rustc_codegen_spirv/build.rs +++ b/crates/rustc_codegen_spirv/build.rs @@ -18,9 +18,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-05-09" +channel = "nightly-2025-06-23" components = ["rust-src", "rustc-dev", "llvm-tools"] -# commit_hash = 50aa04180709189a03dde5fd1c05751b2625ed37"#; +# commit_hash = be19eda0dc4c22c5cf5f1b48fd163acf9bd4b0a6"#; fn rustc_output(arg: &str) -> Result> { let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".into()); @@ -209,6 +209,13 @@ pub(crate) fn create_object_file(_: &Session) -> Option> #[cfg(any())] pub(crate) fn create_object_file(sess: &Session) -> Option> {", ); + src = src.replace( + " +pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {", + " +#[cfg(any())] +pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {", + ); } // HACK(eddyb) "typed alloca" patches. @@ -320,9 +327,6 @@ mod maybe_pqp_cg_ssa; // HACK(eddyb) `if cfg!(llvm_enzyme)` added upstream for autodiff support. println!("cargo::rustc-check-cfg=cfg(llvm_enzyme)"); - // HACK(eddyb) `cfg_attr(bootstrap, ...` used upstream temporarily. - println!("cargo::rustc-check-cfg=cfg(bootstrap)"); - Ok(()) } diff --git a/crates/rustc_codegen_spirv/src/abi.rs b/crates/rustc_codegen_spirv/src/abi.rs index 0502b6a851..22d1737736 100644 --- a/crates/rustc_codegen_spirv/src/abi.rs +++ b/crates/rustc_codegen_spirv/src/abi.rs @@ -290,7 +290,7 @@ pub(crate) fn provide(providers: &mut Providers) { let trivial_struct = match tcx.hir_node_by_def_id(def_id) { rustc_hir::Node::Item(item) => match item.kind { rustc_hir::ItemKind::Struct( - .., + _, &rustc_hir::Generics { params: &[] @@ -309,6 +309,7 @@ pub(crate) fn provide(providers: &mut Providers) { where_clause_span: _, span: _, }, + _, ) => Some(tcx.adt_def(def_id)), _ => None, }, @@ -792,10 +793,11 @@ fn dig_scalar_pointee<'tcx>( // the type is really more "Layout with Ty" (`.ty` field + `Deref`s to `Layout`). fn trans_aggregate<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx>) -> Word { fn create_zst<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx>) -> Word { + assert_eq!(ty.size, Size::ZERO); SpirvType::Adt { def_id: def_id_for_spirv_type_adt(ty), size: Some(Size::ZERO), - align: Align::from_bytes(0).unwrap(), + align: ty.align.abi, field_types: &[], field_offsets: &[], field_names: None, @@ -817,14 +819,18 @@ fn trans_aggregate<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx> // NOTE(eddyb) even if long-term this may become a byte array, that // only works for "data types" and not "opaque handles" (images etc.). let largest_case = (0..ty.fields.count()) - .map(|i| ty.field(cx, i)) - .max_by_key(|case| case.size); + .map(|i| (FieldIdx::from_usize(i), ty.field(cx, i))) + .max_by_key(|(_, case)| case.size); - if let Some(case) = largest_case { - assert_eq!(ty.size, case.size); - case.spirv_type(span, cx) + if let Some((case_idx, case)) = largest_case { + if ty.align != case.align { + // HACK(eddyb) mismatched alignment requires a wrapper `struct`. + trans_struct_or_union(cx, span, ty, Some(case_idx)) + } else { + assert_eq!(ty.size, case.size); + case.spirv_type(span, cx) + } } else { - assert_eq!(ty.size, Size::ZERO); create_zst(cx, span, ty) } } @@ -859,10 +865,19 @@ fn trans_aggregate<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx> FieldsShape::Arbitrary { offsets: _, memory_index: _, - } => trans_struct(cx, span, ty), + } => 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" + ) +)] // returns (field_offsets, size, align) pub fn auto_struct_layout( cx: &CodegenCx<'_>, @@ -890,7 +905,12 @@ pub fn auto_struct_layout( } // see struct_llfields in librustc_codegen_llvm for implementation hints -fn trans_struct<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx>) -> Word { +fn trans_struct_or_union<'tcx>( + cx: &CodegenCx<'tcx>, + span: Span, + ty: TyAndLayout<'tcx>, + union_case: Option, +) -> Word { let size = if ty.is_unsized() { None } else { Some(ty.size) }; let align = ty.align.abi; // FIXME(eddyb) use `AccumulateVec`s just like `rustc` itself does. @@ -898,6 +918,12 @@ fn trans_struct<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx>) - let mut field_offsets = Vec::new(); let mut field_names = Vec::new(); for i in ty.fields.index_by_increasing_offset() { + if let Some(expected_field_idx) = union_case { + if i != expected_field_idx.as_usize() { + continue; + } + } + let field_ty = ty.field(cx, i); field_types.push(field_ty.spirv_type(span, cx)); let offset = ty.fields.offset(i); diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index 27660b86e0..aa6b769b9b 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -14,7 +14,7 @@ use rustc_abi::{Align, BackendRepr, Scalar, Size, WrappingRange}; use rustc_apfloat::{Float, Round, Status, ieee}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::common::{ - AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind, + AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind, }; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; @@ -26,7 +26,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, AtomicOrdering, Ty}; use rustc_span::Span; use rustc_target::callconv::FnAbi; use smallvec::SmallVec; @@ -157,17 +157,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn ordering_to_semantics_def(&self, ordering: AtomicOrdering) -> SpirvValue { let mut invalid_seq_cst = false; let semantics = match ordering { - AtomicOrdering::Unordered | AtomicOrdering::Relaxed => MemorySemantics::NONE, - // Note: rustc currently has AtomicOrdering::Consume commented out, if it ever becomes - // uncommented, it should be MakeVisible | Acquire. + AtomicOrdering::Relaxed => MemorySemantics::NONE, AtomicOrdering::Acquire => MemorySemantics::MAKE_VISIBLE | MemorySemantics::ACQUIRE, AtomicOrdering::Release => MemorySemantics::MAKE_AVAILABLE | MemorySemantics::RELEASE, - AtomicOrdering::AcquireRelease => { + AtomicOrdering::AcqRel => { MemorySemantics::MAKE_AVAILABLE | MemorySemantics::MAKE_VISIBLE | MemorySemantics::ACQUIRE_RELEASE } - AtomicOrdering::SequentiallyConsistent => { + AtomicOrdering::SeqCst => { let emit = self.emit(); let memory_model = emit.module_ref().memory_model.as_ref().unwrap(); if memory_model.operands[1].unwrap_memory_model() == MemoryModel::Vulkan { @@ -182,8 +180,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if invalid_seq_cst { self.zombie( semantics.def(self), - "cannot use AtomicOrdering=SequentiallyConsistent on Vulkan memory model \ - (check if AcquireRelease fits your needs)", + "cannot use `AtomicOrdering::SeqCst` on Vulkan memory model \ + (check if `AcqRel` fits your needs)", ); } semantics @@ -3127,6 +3125,14 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { String::from_utf8(piece_str_bytes).ok() }; + // 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()); + return Ok(decoded_format_args); + } + // HACK(eddyb) some entry-points only take a `&str`, not `fmt::Arguments`. if let [ SpirvValue { @@ -3359,7 +3365,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { } }; - let prepare_args_insts = try_rev_take(3).ok_or_else(|| { + let prepare_args_insts = try_rev_take(2).ok_or_else(|| { FormatArgsNotRecognized( "fmt::Arguments::new_v1_formatted call: ran out of instructions".into(), ) @@ -3367,9 +3373,6 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { let (rt_args_slice_ptr_id, _fmt_placeholders_slice_ptr_id) = match prepare_args_insts[..] { [ - // HACK(eddyb) `rt::UnsafeArg::new()` call - // (`unsafe` ZST "constructor"). - Inst::Call(_, _, ref rt_unsafe_arg_call_args), Inst::Bitcast( rt_args_cast_out_id, rt_args_cast_in_id, @@ -3378,8 +3381,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { placeholders_cast_out_id, placeholders_cast_in_id, ), - ] if rt_unsafe_arg_call_args.is_empty() - && rt_args_cast_out_id == rt_args_slice_ptr_id + ] if rt_args_cast_out_id == rt_args_slice_ptr_id && placeholders_cast_out_id == fmt_placeholders_slice_ptr_id => { diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index 1f9b13962f..084f14b649 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -17,8 +17,6 @@ use rustc_middle::ty::{FnDef, Instance, Ty, TyKind, TypingEnv}; use rustc_middle::{bug, ty}; use rustc_span::Span; use rustc_span::sym; -use rustc_target::callconv::{FnAbi, PassMode}; -use std::assert_matches::assert_matches; fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_>) -> Option<(u64, bool)> { match ty.kind() { @@ -64,9 +62,8 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { fn codegen_intrinsic_call( &mut self, instance: Instance<'tcx>, - fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, Self::Value>], - llresult: Self::Value, + result: PlaceRef<'tcx, Self::Value>, _span: Span, ) -> Result<(), ty::Instance<'tcx>> { let callee_ty = instance.ty(self.tcx, TypingEnv::fully_monomorphized()); @@ -84,7 +81,6 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { let name = self.tcx.item_name(def_id); let ret_ty = self.layout_of(sig.output()).spirv_type(self.span(), self); - let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout); let value = match name { sym::likely | sym::unlikely => { @@ -94,7 +90,7 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { sym::breakpoint => { self.abort(); - assert!(fn_abi.ret.is_ignore()); + assert!(result.layout.ty.is_unit()); return Ok(()); } @@ -113,7 +109,7 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { | sym::prefetch_read_instruction | sym::prefetch_write_instruction => { // ignore - assert!(fn_abi.ret.is_ignore()); + assert!(result.layout.ty.is_unit()); return Ok(()); } @@ -338,8 +334,14 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { } }; - if !fn_abi.ret.is_ignore() { - assert_matches!(fn_abi.ret.mode, PassMode::Direct(_) | PassMode::Pair(..)); + if result.layout.ty.is_bool() { + let val = self.from_immediate(value); + self.store_to_place(val, result.val); + } else if !result.layout.ty.is_unit() { + // FIXME(eddyb) upstream uses `self.store_to_place(value, result.val);`, + // which AFAICT does not handle packed pairs explicitly, meaning it + // can/will store e.g. LLVM `{A, B}` values, which is legal (in LLVM), + // but seems suboptimal (or even risky with e.g. layout randomization). OperandRef::from_immediate_or_packed_pair(self, value, result.layout) .val .store(self, result); @@ -360,10 +362,6 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { cond } - fn type_test(&mut self, _pointer: Self::Value, _typeid: Self::Metadata) -> Self::Value { - todo!() - } - fn type_checked_load( &mut self, _llvtable: Self::Value, diff --git a/crates/rustc_codegen_spirv/src/builder/mod.rs b/crates/rustc_codegen_spirv/src/builder/mod.rs index 37d7d53fe3..e1dcd1577c 100644 --- a/crates/rustc_codegen_spirv/src/builder/mod.rs +++ b/crates/rustc_codegen_spirv/src/builder/mod.rs @@ -12,7 +12,6 @@ pub use spirv_asm::InstructionTable; // 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 crate::abi::ConvSpirvType; use crate::builder_spirv::{BuilderCursor, SpirvValue, SpirvValueExt}; use crate::codegen_cx::CodegenCx; use crate::spirv_type::SpirvType; @@ -193,10 +192,6 @@ impl<'a, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'tcx> { todo!() } - fn get_dbg_loc(&self) -> Option { - None - } - fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) { todo!() } @@ -254,10 +249,6 @@ impl<'a, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'a, 'tcx> { ), } } - - fn arg_memory_ty(&self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>) -> Self::Type { - arg_abi.layout.spirv_type(self.span(), self) - } } impl AbiBuilderMethods for Builder<'_, '_> { diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs index c13e01d567..909c3bb0ee 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs @@ -10,7 +10,7 @@ use crate::spirv_type::SpirvType; use itertools::Itertools; use rspirv::spirv::{FunctionControl, LinkageType, StorageClass, Word}; use rustc_abi::Align; -use rustc_attr_parsing::InlineAttr; +use rustc_attr_data_structures::InlineAttr; use rustc_codegen_ssa::traits::{PreDefineCodegenMethods, StaticCodegenMethods}; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; @@ -203,7 +203,9 @@ 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 demangled_symbol_name == "core::panicking::panic_nounwind_fmt" { + if let Some("panic_nounwind_fmt" | "panic_explicit") = + demangled_symbol_name.strip_prefix("core::panicking::") + { self.panic_entry_points.borrow_mut().insert(def_id); } if let Some(pieces_len) = demangled_symbol_name @@ -301,7 +303,7 @@ impl<'tcx> CodegenCx<'tcx> { impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'tcx> { fn predefine_static( - &self, + &mut self, def_id: DefId, linkage: Linkage, _visibility: Visibility, @@ -331,7 +333,7 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'tcx> { } fn predefine_fn( - &self, + &mut self, instance: Instance<'tcx>, linkage: Linkage, _visibility: Visibility, @@ -366,7 +368,7 @@ impl<'tcx> StaticCodegenMethods for CodegenCx<'tcx> { ) } - fn codegen_static(&self, def_id: DefId) { + fn codegen_static(&mut self, def_id: DefId) { let g = self.get_static(def_id); let alloc = match self.tcx.eval_static_initializer(def_id) { @@ -385,19 +387,69 @@ impl<'tcx> StaticCodegenMethods for CodegenCx<'tcx> { assert_ty_eq!(self, value_ty, v.ty); self.builder .set_global_initializer(g.def_cx(self), v.def_cx(self)); + + let attrs = self.tcx.codegen_fn_attrs(def_id); + + let alloc = alloc.inner(); + let align_override = + Some(alloc.align).filter(|&align| align != self.lookup_type(value_ty).alignof(self)); + if let Some(_align) = align_override { + // FIXME(eddyb) implement, or at least error. + } + + if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) { + // FIXME(eddyb) implement, or at least error. + } + + if let Some(_section) = attrs.link_section { + // FIXME(eddyb) implement, or at least error. + } + + if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) { + // `USED` and `USED_LINKER` can't be used together. + assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)); + + // The semantics of #[used] in Rust only require the symbol to make it into the + // object file. It is explicitly allowed for the linker to strip the symbol if it + // is dead, which means we are allowed to use `llvm.compiler.used` instead of + // `llvm.used` here. + // + // Additionally, https://reviews.llvm.org/D97448 in LLVM 13 started emitting unique + // sections with SHF_GNU_RETAIN flag for llvm.used symbols, which may trigger bugs + // in the handling of `.init_array` (the static constructor list) in versions of + // the gold linker (prior to the one released with binutils 2.36). + // + // That said, we only ever emit these when `#[used(compiler)]` is explicitly + // requested. This is to avoid similar breakage on other targets, in particular + // MachO targets have *their* static constructor lists broken if `llvm.compiler.used` + // is emitted rather than `llvm.used`. However, that check happens when assigning + // the `CodegenFnAttrFlags` in the `codegen_fn_attrs` query, so we don't need to + // take care of it here. + self.add_compiler_used_global(g); + } + if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) { + // `USED` and `USED_LINKER` can't be used together. + assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)); + + self.add_used_global(g); + } } +} +impl CodegenCx<'_> { /// Mark the given global value as "used", to prevent the compiler and linker from potentially /// removing a static variable that may otherwise appear unused. - fn add_used_global(&self, _global: Self::Value) { + fn add_used_global(&self, global: SpirvValue) { // TODO: Ignore for now. + let _unused = (self, global); } /// Same as `add_used_global`, but only prevent the compiler from potentially removing an /// otherwise unused symbol. The linker is still permitted to drop it. /// /// This corresponds to the semantics of the `#[used]` attribute. - fn add_compiler_used_global(&self, _global: Self::Value) { + fn add_compiler_used_global(&self, global: SpirvValue) { // TODO: Ignore for now. + let _unused = (self, global); } } diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs index 19d365fdcb..744c7695d7 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs @@ -894,10 +894,6 @@ impl<'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'tcx> { self.tcx.sess } - fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx> { - self.codegen_unit - } - fn set_frame_pointer_type(&self, _llfn: Self::Function) { todo!() } diff --git a/crates/rustc_codegen_spirv/src/lib.rs b/crates/rustc_codegen_spirv/src/lib.rs index c3b29b786a..a9238cfeae 100644 --- a/crates/rustc_codegen_spirv/src/lib.rs +++ b/crates/rustc_codegen_spirv/src/lib.rs @@ -2,7 +2,6 @@ #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] -#![cfg_attr(bootstrap, feature(let_chains))] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(file_buffered)] @@ -33,7 +32,6 @@ //! [`spirv-tools`]: https://rust-gpu.github.io/rust-gpu/api/spirv_tools //! [`spirv-tools-sys`]: https://rust-gpu.github.io/rust-gpu/api/spirv_tools_sys #![feature(rustc_private)] -#![feature(result_flattening)] // crate-specific exceptions: #![allow( unsafe_code, // rustc_codegen_ssa requires unsafe functions in traits to be impl'd @@ -41,7 +39,7 @@ clippy::todo, // still lots to implement :) // FIXME(eddyb) new warnings from 1.83 rustup, apply their suggested changes. - elided_named_lifetimes, + mismatched_lifetime_syntaxes, clippy::needless_lifetimes, )] @@ -87,6 +85,8 @@ extern crate rustc_arena; #[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_ast; #[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] +extern crate rustc_attr_data_structures; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_attr_parsing; #[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_codegen_ssa; @@ -262,12 +262,7 @@ impl CodegenBackend for SpirvCodegenBackend { crate::attr::provide(providers); } - fn codegen_crate( - &self, - tcx: TyCtxt<'_>, - metadata: EncodedMetadata, - need_metadata_module: bool, - ) -> Box { + fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box { Box::new(maybe_pqp_cg_ssa::base::codegen_crate( Self, tcx, @@ -277,8 +272,6 @@ impl CodegenBackend for SpirvCodegenBackend { .target_cpu .clone() .unwrap_or_else(|| tcx.sess.target.cpu.to_string()), - metadata, - need_metadata_module, )) } @@ -294,11 +287,18 @@ impl CodegenBackend for SpirvCodegenBackend { .join(sess) } - fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) { + fn link( + &self, + sess: &Session, + codegen_results: CodegenResults, + metadata: EncodedMetadata, + outputs: &OutputFilenames, + ) { let timer = sess.timer("link_crate"); link::link( sess, &codegen_results, + &metadata, outputs, codegen_results.crate_info.local_crate_name.as_str(), ); @@ -346,7 +346,7 @@ impl WriteBackendMethods for SpirvCodegenBackend { warn!("TODO: Implement print_statistics"); } - unsafe fn optimize( + fn optimize( _: &CodegenContext, _: DiagCtxtHandle<'_>, _: &mut ModuleCodegen, @@ -356,7 +356,7 @@ impl WriteBackendMethods for SpirvCodegenBackend { Ok(()) } - unsafe fn optimize_thin( + fn optimize_thin( _cgcx: &CodegenContext, thin_module: ThinModule, ) -> Result, FatalError> { @@ -378,7 +378,7 @@ impl WriteBackendMethods for SpirvCodegenBackend { todo!() } - unsafe fn codegen( + fn codegen( cgcx: &CodegenContext, _diag_handler: DiagCtxtHandle<'_>, module: ModuleCodegen, @@ -439,9 +439,9 @@ impl ExtraBackendMethods for SpirvCodegenBackend { todo!() } - fn compile_codegen_unit( + fn compile_codegen_unit<'tcx>( &self, - tcx: TyCtxt<'_>, + tcx: TyCtxt<'tcx>, cgu_name: Symbol, ) -> (ModuleCodegen, u64) { let _timer = tcx @@ -452,8 +452,8 @@ impl ExtraBackendMethods for SpirvCodegenBackend { let cgu = tcx.codegen_unit(cgu_name); let mut cx = CodegenCx::new(tcx, cgu); - let do_codegen = |cx: &mut CodegenCx<'_>| { - let mono_items = cx.codegen_unit.items_in_deterministic_order(cx.tcx); + let do_codegen = |cx: &mut CodegenCx<'tcx>| { + let mono_items = cgu.items_in_deterministic_order(cx.tcx); if let Some(dir) = &cx.codegen_args.dump_mir { dump_mir(tcx, mono_items.as_slice(), &dir.join(cgu_name.to_string())); @@ -462,6 +462,7 @@ impl ExtraBackendMethods for SpirvCodegenBackend { for &(mono_item, mono_item_data) in mono_items.iter() { mono_item.predefine::>( cx, + cgu_name.as_str(), mono_item_data.linkage, mono_item_data.visibility, ); @@ -469,10 +470,10 @@ impl ExtraBackendMethods for SpirvCodegenBackend { // ... and now that we have everything pre-defined, fill out those definitions. for &(mono_item, mono_item_data) in &mono_items { - mono_item.define::>(cx, mono_item_data); + mono_item.define::>(cx, cgu_name.as_str(), mono_item_data); } - if let Some(_entry) = maybe_create_entry_wrapper::>(cx) { + if let Some(_entry) = maybe_create_entry_wrapper::>(cx, cgu) { // attributes::sanitize(&cx, SanitizerSet::empty(), entry); } }; diff --git a/crates/rustc_codegen_spirv/src/link.rs b/crates/rustc_codegen_spirv/src/link.rs index 22165e2a03..540d8a2841 100644 --- a/crates/rustc_codegen_spirv/src/link.rs +++ b/crates/rustc_codegen_spirv/src/link.rs @@ -13,7 +13,7 @@ use rustc_codegen_ssa::back::write::CodegenContext; use rustc_codegen_ssa::{CodegenResults, NativeLib}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Diag, FatalError}; -use rustc_metadata::fs::METADATA_FILENAME; +use rustc_metadata::{EncodedMetadata, fs::METADATA_FILENAME}; use rustc_middle::bug; use rustc_middle::dep_graph::WorkProduct; use rustc_middle::middle::dependency_format::Linkage; @@ -35,6 +35,7 @@ use std::sync::Arc; pub fn link( sess: &Session, codegen_results: &CodegenResults, + metadata: &EncodedMetadata, outputs: &OutputFilenames, crate_name: &str, ) { @@ -73,7 +74,12 @@ pub fn link( ); match crate_type { CrateType::Rlib => { - link_rlib(sess, codegen_results, &out_filename_file_for_writing); + link_rlib( + sess, + codegen_results, + metadata, + &out_filename_file_for_writing, + ); } CrateType::Executable | CrateType::Cdylib | CrateType::Dylib => { // HACK(eddyb) there's no way way to access `outputs.filestem`, @@ -117,7 +123,12 @@ pub fn link( } } -fn link_rlib(sess: &Session, codegen_results: &CodegenResults, out_filename: &Path) { +fn link_rlib( + sess: &Session, + codegen_results: &CodegenResults, + metadata: &EncodedMetadata, + out_filename: &Path, +) { let mut file_list = Vec::<&Path>::new(); for obj in codegen_results .modules @@ -139,11 +150,7 @@ fn link_rlib(sess: &Session, codegen_results: &CodegenResults, out_filename: &Pa } } - create_archive( - &file_list, - codegen_results.metadata.stub_or_full(), - out_filename, - ); + create_archive(&file_list, metadata.stub_or_full(), out_filename); } fn link_exe( diff --git a/crates/rustc_codegen_spirv/src/linker/test.rs b/crates/rustc_codegen_spirv/src/linker/test.rs index 1a1e1061ec..adb55d94af 100644 --- a/crates/rustc_codegen_spirv/src/linker/test.rs +++ b/crates/rustc_codegen_spirv/src/linker/test.rs @@ -144,6 +144,8 @@ fn link_with_linker_opts( checksum_hash_kind: None, }; rustc_span::create_session_globals_then(sopts.edition, &[], Some(sm_inputs), || { + extern crate rustc_driver_impl; + let mut sess = rustc_session::build_session( sopts, CompilerIO { @@ -163,10 +165,7 @@ fn link_with_linker_opts( Default::default(), rustc_interface::util::rustc_version_str().unwrap_or("unknown"), Default::default(), - { - extern crate rustc_driver_impl; - &rustc_driver_impl::USING_INTERNAL_FEATURES - }, + &rustc_driver_impl::USING_INTERNAL_FEATURES, Default::default(), ); @@ -175,16 +174,11 @@ fn link_with_linker_opts( sess.psess = { let source_map = sess.psess.clone_source_map(); - let fallback_bundle = { - extern crate rustc_error_messages; - rustc_error_messages::fallback_fluent_bundle( - Vec::new(), - sess.opts.unstable_opts.translate_directionality_markers, - ) - }; - let emitter = - rustc_errors::emitter::HumanEmitter::new(Box::new(buf), fallback_bundle) - .sm(Some(source_map.clone())); + let emitter = rustc_errors::emitter::HumanEmitter::new( + Box::new(buf), + rustc_driver_impl::default_translator(), + ) + .sm(Some(source_map.clone())); rustc_session::parse::ParseSess::with_dcx( rustc_errors::DiagCtxt::new(Box::new(emitter)) diff --git a/crates/spirv-builder/src/lib.rs b/crates/spirv-builder/src/lib.rs index 9fd658e648..6161916fac 100644 --- a/crates/spirv-builder/src/lib.rs +++ b/crates/spirv-builder/src/lib.rs @@ -848,6 +848,13 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result { // GVN currently can lead to the memcpy-out-of-const-alloc-global-var // pattern, even for `ScalarPair` (e.g. `return None::;`). "-Zmir-enable-passes=-GVN".to_string(), + // HACK(eddyb) avoid ever reusing instantiations from `compiler_builtins` + // which is special-cased to turn calls to functions that never return, + // into aborts, and this applies to the panics of UB-checking helpers + // (https://github.com/rust-lang/rust/pull/122580#issuecomment-3033026194) + // but while upstream that only loses the panic message, for us it's even + // worse, as we lose the chance to remove otherwise-dead `fmt::Arguments`. + "-Zshare-generics=off".to_string(), ]; // Wrapper for `env::var` that appropriately informs Cargo of the dependency. diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 174ba5c1f0..695cb49f92 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,7 +1,7 @@ [toolchain] -channel = "nightly-2025-05-09" +channel = "nightly-2025-06-23" components = ["rust-src", "rustc-dev", "llvm-tools"] -# commit_hash = 50aa04180709189a03dde5fd1c05751b2625ed37 +# commit_hash = be19eda0dc4c22c5cf5f1b48fd163acf9bd4b0a6 # Whenever changing the nightly channel, update the commit hash above, and make # sure to change `REQUIRED_TOOLCHAIN` in `crates/rustc_codegen_spirv/build.rs` also. diff --git a/tests/compiletests/src/main.rs b/tests/compiletests/src/main.rs index e41dbc94ec..56e85b5a83 100644 --- a/tests/compiletests/src/main.rs +++ b/tests/compiletests/src/main.rs @@ -371,6 +371,13 @@ fn rust_flags(codegen_backend_path: &Path) -> String { // GVN currently can lead to the memcpy-out-of-const-alloc-global-var // pattern, even for `ScalarPair` (e.g. `return None::;`). "-Zmir-enable-passes=-GVN", + // HACK(eddyb) avoid ever reusing instantiations from `compiler_builtins` + // which is special-cased to turn calls to functions that never return, + // into aborts, and this applies to the panics of UB-checking helpers + // (https://github.com/rust-lang/rust/pull/122580#issuecomment-3033026194) + // but while upstream that only loses the panic message, for us it's even + // worse, as we lose the chance to remove otherwise-dead `fmt::Arguments`. + "-Zshare-generics=off", // NOTE(eddyb) flags copied from `spirv-builder` are all above this line. "-Cdebuginfo=2", "-Cembed-bitcode=no", 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 b192673f2c..632c45702f 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,4 +1,4 @@ -error[E0080]: evaluation of `spirv_std::arch::subgroup_clustered_i_add::<0, u32, u32>::{constant#0}` failed +error[E0080]: evaluation panicked: `ClusterSize` must be at least 1 --> $SPIRV_STD_SRC/arch/subgroup.rs:840:1 | 840 | / macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r" @@ -8,7 +8,7 @@ error[E0080]: evaluation of `spirv_std::arch::subgroup_clustered_i_add::<0, u32, ... | 856 | | * `ClusterSize` must not be greater than the size of the group 857 | | "); - | |__^ evaluation panicked: `ClusterSize` must be at least 1 + | |__^ evaluation of `spirv_std::arch::subgroup_clustered_i_add::<0, u32, u32>::{constant#0}` failed here | = 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) 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 3fb35d0b83..b6b1b35fb9 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,4 +1,4 @@ -error[E0080]: evaluation of `spirv_std::arch::subgroup_clustered_i_add::<5, u32, u32>::{constant#0}` failed +error[E0080]: evaluation panicked: `ClusterSize` must be a power of 2 --> $SPIRV_STD_SRC/arch/subgroup.rs:840:1 | 840 | / macro_subgroup_op_clustered!(impl Integer, "OpGroupNonUniformIAdd", subgroup_clustered_i_add; r" @@ -8,7 +8,7 @@ error[E0080]: evaluation of `spirv_std::arch::subgroup_clustered_i_add::<5, u32, ... | 856 | | * `ClusterSize` must not be greater than the size of the group 857 | | "); - | |__^ evaluation panicked: `ClusterSize` must be a power of 2 + | |__^ evaluation of `spirv_std::arch::subgroup_clustered_i_add::<5, u32, u32>::{constant#0}` failed here | = 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) diff --git a/tests/compiletests/ui/dis/issue-1062.stderr b/tests/compiletests/ui/dis/issue-1062.stderr index 50182936c7..5019327bfb 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 1108 4 +OpLine %11 1128 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 5a0a23a6fb..f340038ed1 100644 --- a/tests/compiletests/ui/dis/panic_builtin_bounds_check.stderr +++ b/tests/compiletests/ui/dis/panic_builtin_bounds_check.stderr @@ -4,47 +4,47 @@ 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:25: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 -%7 = OpTypeFunction %6 -%8 = OpTypeInt 32 0 -%9 = OpConstant %8 4 -%5 = OpTypeArray %8 %9 -%10 = OpTypePointer Function %5 -%11 = OpConstant %8 0 -%12 = OpConstant %8 1 -%13 = OpConstant %8 2 -%14 = OpConstant %8 3 -%15 = OpTypeBool -%16 = OpConstant %8 5 -%17 = OpUndef %8 -%18 = OpTypePointer Function %8 -%2 = OpFunction %6 None %7 +%3 = OpString "/n[Rust panicked at $SYSROOT/lib/rustlib/src/rust/library/core/src/panicking.rs:280: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 +%6 = OpTypeArray %9 %10 +%11 = OpTypePointer Function %6 +%12 = OpConstant %9 0 +%13 = OpConstant %9 1 +%14 = OpConstant %9 2 +%15 = OpConstant %9 3 +%16 = OpTypeBool +%17 = OpConstant %9 5 +%18 = OpTypePointer Function %9 +%2 = OpFunction %7 None %8 %19 = OpLabel -OpLine %4 30 4 -%20 = OpVariable %10 Function -OpLine %4 30 23 -%21 = OpCompositeConstruct %5 %11 %12 %13 %14 -OpLine %4 25 4 +OpLine %5 30 4 +%20 = OpVariable %11 Function +OpLine %5 30 23 +%21 = OpCompositeConstruct %6 %12 %13 %14 %15 +OpLine %5 25 4 OpStore %20 %21 -%22 = OpULessThan %15 %16 %9 +%22 = OpULessThan %16 %17 %10 OpNoLine OpSelectionMerge %23 None OpBranchConditional %22 %24 %25 %24 = OpLabel OpBranch %23 %25 = OpLabel -OpLine %4 25 4 -%26 = OpExtInst %6 %1 1 %3 %17 %16 +OpLine %4 280 4 +%26 = OpExtInst %7 %1 1 %3 %10 %17 OpNoLine OpReturn %23 = OpLabel -OpLine %4 25 4 -%27 = OpIAdd %8 %11 %16 +OpLine %5 25 4 +%27 = OpIAdd %9 %12 %17 %28 = OpInBoundsAccessChain %18 %20 %27 -%29 = OpLoad %8 %28 +%29 = OpLoad %9 %28 OpNoLine OpReturn OpFunctionEnd diff --git a/tests/compiletests/ui/dis/panic_sequential_many.stderr b/tests/compiletests/ui/dis/panic_sequential_many.stderr index 5c86eaab48..61ff80b9bd 100644 --- a/tests/compiletests/ui/dis/panic_sequential_many.stderr +++ b/tests/compiletests/ui/dis/panic_sequential_many.stderr @@ -4,8 +4,9 @@ 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:29:10]/n attempt to divide by zero/n in main()/n" -%7 = OpString "$DIR/panic_sequential_many.rs" +%6 = OpString "/n[Rust panicked at $SYSROOT/lib/rustlib/src/rust/library/core/src/panicking.rs:187: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" OpName %3 "x" OpName %4 "y" OpName %5 "o" @@ -14,262 +15,262 @@ OpDecorate %3 Location 0 OpDecorate %4 Flat OpDecorate %4 Location 1 OpDecorate %5 Location 0 -%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 26 12 -%16 = OpLoad %8 %3 -OpLine %7 26 35 -%17 = OpLoad %8 %4 -OpLine %7 29 9 -%18 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %19 None -OpBranchConditional %18 %20 %21 -%20 = OpLabel -OpLine %7 29 9 -%22 = OpExtInst %11 %1 1 %6 -OpNoLine -OpReturn +%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 26 12 +%17 = OpLoad %9 %3 +OpLine %8 26 35 +%18 = OpLoad %9 %4 +OpLine %8 29 9 +%19 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %20 None +OpBranchConditional %19 %21 %22 %21 = OpLabel -OpBranch %19 -%19 = OpLabel -OpLine %7 29 9 -%23 = OpUDiv %8 %16 %17 -%24 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %25 None -OpBranchConditional %24 %26 %27 -%26 = OpLabel -OpLine %7 29 9 -%28 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%23 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%22 = OpLabel +OpBranch %20 +%20 = OpLabel +OpLine %8 29 9 +%24 = OpUDiv %9 %17 %18 +%25 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %26 None +OpBranchConditional %25 %27 %28 %27 = OpLabel -OpBranch %25 -%25 = OpLabel -OpLine %7 29 9 -%29 = OpUDiv %8 %23 %17 -%30 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %31 None -OpBranchConditional %30 %32 %33 -%32 = OpLabel -OpLine %7 29 9 -%34 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%29 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%28 = OpLabel +OpBranch %26 +%26 = OpLabel +OpLine %8 29 9 +%30 = OpUDiv %9 %24 %18 +%31 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %32 None +OpBranchConditional %31 %33 %34 %33 = OpLabel -OpBranch %31 -%31 = OpLabel -OpLine %7 29 9 -%35 = OpUDiv %8 %29 %17 -%36 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %37 None -OpBranchConditional %36 %38 %39 -%38 = OpLabel -OpLine %7 29 9 -%40 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%35 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%34 = OpLabel +OpBranch %32 +%32 = OpLabel +OpLine %8 29 9 +%36 = OpUDiv %9 %30 %18 +%37 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %38 None +OpBranchConditional %37 %39 %40 %39 = OpLabel -OpBranch %37 -%37 = OpLabel -OpLine %7 29 9 -%41 = OpUDiv %8 %35 %17 -%42 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %43 None -OpBranchConditional %42 %44 %45 -%44 = OpLabel -OpLine %7 29 9 -%46 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%41 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%40 = OpLabel +OpBranch %38 +%38 = OpLabel +OpLine %8 29 9 +%42 = OpUDiv %9 %36 %18 +%43 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %44 None +OpBranchConditional %43 %45 %46 %45 = OpLabel -OpBranch %43 -%43 = OpLabel -OpLine %7 29 9 -%47 = OpUDiv %8 %41 %17 -%48 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %49 None -OpBranchConditional %48 %50 %51 -%50 = OpLabel -OpLine %7 29 9 -%52 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%47 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%46 = OpLabel +OpBranch %44 +%44 = OpLabel +OpLine %8 29 9 +%48 = OpUDiv %9 %42 %18 +%49 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %50 None +OpBranchConditional %49 %51 %52 %51 = OpLabel -OpBranch %49 -%49 = OpLabel -OpLine %7 29 9 -%53 = OpUDiv %8 %47 %17 -%54 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %55 None -OpBranchConditional %54 %56 %57 -%56 = OpLabel -OpLine %7 29 9 -%58 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%53 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%52 = OpLabel +OpBranch %50 +%50 = OpLabel +OpLine %8 29 9 +%54 = OpUDiv %9 %48 %18 +%55 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %56 None +OpBranchConditional %55 %57 %58 %57 = OpLabel -OpBranch %55 -%55 = OpLabel -OpLine %7 29 9 -%59 = OpUDiv %8 %53 %17 -%60 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %61 None -OpBranchConditional %60 %62 %63 -%62 = OpLabel -OpLine %7 29 9 -%64 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%59 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%58 = OpLabel +OpBranch %56 +%56 = OpLabel +OpLine %8 29 9 +%60 = OpUDiv %9 %54 %18 +%61 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %62 None +OpBranchConditional %61 %63 %64 %63 = OpLabel -OpBranch %61 -%61 = OpLabel -OpLine %7 29 9 -%65 = OpUDiv %8 %59 %17 -%66 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %67 None -OpBranchConditional %66 %68 %69 -%68 = OpLabel -OpLine %7 29 9 -%70 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%65 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%64 = OpLabel +OpBranch %62 +%62 = OpLabel +OpLine %8 29 9 +%66 = OpUDiv %9 %60 %18 +%67 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %68 None +OpBranchConditional %67 %69 %70 %69 = OpLabel -OpBranch %67 -%67 = OpLabel -OpLine %7 29 9 -%71 = OpUDiv %8 %65 %17 -%72 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %73 None -OpBranchConditional %72 %74 %75 -%74 = OpLabel -OpLine %7 29 9 -%76 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%71 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%70 = OpLabel +OpBranch %68 +%68 = OpLabel +OpLine %8 29 9 +%72 = OpUDiv %9 %66 %18 +%73 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %74 None +OpBranchConditional %73 %75 %76 %75 = OpLabel -OpBranch %73 -%73 = OpLabel -OpLine %7 29 9 -%77 = OpUDiv %8 %71 %17 -%78 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %79 None -OpBranchConditional %78 %80 %81 -%80 = OpLabel -OpLine %7 29 9 -%82 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%77 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%76 = OpLabel +OpBranch %74 +%74 = OpLabel +OpLine %8 29 9 +%78 = OpUDiv %9 %72 %18 +%79 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %80 None +OpBranchConditional %79 %81 %82 %81 = OpLabel -OpBranch %79 -%79 = OpLabel -OpLine %7 29 9 -%83 = OpUDiv %8 %77 %17 -%84 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %85 None -OpBranchConditional %84 %86 %87 -%86 = OpLabel -OpLine %7 29 9 -%88 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%83 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%82 = OpLabel +OpBranch %80 +%80 = OpLabel +OpLine %8 29 9 +%84 = OpUDiv %9 %78 %18 +%85 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %86 None +OpBranchConditional %85 %87 %88 %87 = OpLabel -OpBranch %85 -%85 = OpLabel -OpLine %7 29 9 -%89 = OpUDiv %8 %83 %17 -%90 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %91 None -OpBranchConditional %90 %92 %93 -%92 = OpLabel -OpLine %7 29 9 -%94 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%89 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%88 = OpLabel +OpBranch %86 +%86 = OpLabel +OpLine %8 29 9 +%90 = OpUDiv %9 %84 %18 +%91 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %92 None +OpBranchConditional %91 %93 %94 %93 = OpLabel -OpBranch %91 -%91 = OpLabel -OpLine %7 29 9 -%95 = OpUDiv %8 %89 %17 -%96 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %97 None -OpBranchConditional %96 %98 %99 -%98 = OpLabel -OpLine %7 29 9 -%100 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%95 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%94 = OpLabel +OpBranch %92 +%92 = OpLabel +OpLine %8 29 9 +%96 = OpUDiv %9 %90 %18 +%97 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %98 None +OpBranchConditional %97 %99 %100 %99 = OpLabel -OpBranch %97 -%97 = OpLabel -OpLine %7 29 9 -%101 = OpUDiv %8 %95 %17 -%102 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %103 None -OpBranchConditional %102 %104 %105 -%104 = OpLabel -OpLine %7 29 9 -%106 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%101 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%100 = OpLabel +OpBranch %98 +%98 = OpLabel +OpLine %8 29 9 +%102 = OpUDiv %9 %96 %18 +%103 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %104 None +OpBranchConditional %103 %105 %106 %105 = OpLabel -OpBranch %103 -%103 = OpLabel -OpLine %7 29 9 -%107 = OpUDiv %8 %101 %17 -%108 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %109 None -OpBranchConditional %108 %110 %111 -%110 = OpLabel -OpLine %7 29 9 -%112 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%107 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%106 = OpLabel +OpBranch %104 +%104 = OpLabel +OpLine %8 29 9 +%108 = OpUDiv %9 %102 %18 +%109 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %110 None +OpBranchConditional %109 %111 %112 %111 = OpLabel -OpBranch %109 -%109 = OpLabel -OpLine %7 29 9 -%113 = OpUDiv %8 %107 %17 -%114 = OpIEqual %13 %17 %14 -OpNoLine -OpSelectionMerge %115 None -OpBranchConditional %114 %116 %117 -%116 = OpLabel -OpLine %7 29 9 -%118 = OpExtInst %11 %1 1 %6 +OpLine %7 187 4 +%113 = OpExtInst %12 %1 1 %6 OpNoLine OpReturn +%112 = OpLabel +OpBranch %110 +%110 = OpLabel +OpLine %8 29 9 +%114 = OpUDiv %9 %108 %18 +%115 = OpIEqual %14 %18 %15 +OpNoLine +OpSelectionMerge %116 None +OpBranchConditional %115 %117 %118 %117 = OpLabel -OpBranch %115 -%115 = OpLabel -OpLine %7 29 4 -%119 = OpUDiv %8 %113 %17 -OpStore %5 %119 +OpLine %7 187 4 +%119 = OpExtInst %12 %1 1 %6 +OpNoLine +OpReturn +%118 = OpLabel +OpBranch %116 +%116 = OpLabel +OpLine %8 29 4 +%120 = OpUDiv %9 %114 %18 +OpStore %5 %120 OpNoLine OpReturn OpFunctionEnd diff --git a/tests/compiletests/ui/dis/ptr_copy.normal.stderr b/tests/compiletests/ui/dis/ptr_copy.normal.stderr index 994c1a6e8c..c7db2ddf11 100644 --- a/tests/compiletests/ui/dis/ptr_copy.normal.stderr +++ b/tests/compiletests/ui/dis/ptr_copy.normal.stderr @@ -1,68 +1,68 @@ error: cannot memcpy dynamically sized data - --> $CORE_SRC/intrinsics/mod.rs:3850:9 - | -3850 | copy(src, dst, count) - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: used from within `core::intrinsics::copy::` - --> $CORE_SRC/intrinsics/mod.rs:3830:21 - | -3830 | pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { - | ^^^^ + --> $CORE_SRC/ptr/mod.rs:633:9 + | +633 | crate::intrinsics::copy(src, dst, count) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: used from within `core::ptr::copy::` + --> $CORE_SRC/ptr/mod.rs:618:21 + | +618 | 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 - | -28 | unsafe { core::ptr::copy(src, dst, 1) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/ptr_copy.rs:28:18 + | +28 | unsafe { core::ptr::copy(src, dst, 1) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: called by `ptr_copy::main` - --> $DIR/ptr_copy.rs:33:5 - | -33 | copy_via_raw_ptr(&i, o); - | ^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/ptr_copy.rs:33:5 + | +33 | copy_via_raw_ptr(&i, o); + | ^^^^^^^^^^^^^^^^^^^^^^^ note: called by `main` - --> $DIR/ptr_copy.rs:32:8 - | -32 | pub fn main(i: f32, o: &mut f32) { - | ^^^^ + --> $DIR/ptr_copy.rs:32:8 + | +32 | pub fn main(i: f32, o: &mut f32) { + | ^^^^ error: cannot cast between pointer types from `*f32` to `*struct () { }` - --> $CORE_SRC/intrinsics/mod.rs:3838:9 - | -3838 | / ub_checks::assert_unsafe_precondition!( -3839 | | check_language_ub, -3840 | | "ptr::copy requires that both pointer arguments are aligned and non-null", -... | -3848 | | && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) -3849 | | ); - | |_________^ - | -note: used from within `core::intrinsics::copy::` - --> $CORE_SRC/intrinsics/mod.rs:3838:9 - | -3838 | / ub_checks::assert_unsafe_precondition!( -3839 | | check_language_ub, -3840 | | "ptr::copy requires that both pointer arguments are aligned and non-null", -... | -3848 | | && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) -3849 | | ); - | |_________^ + --> $CORE_SRC/ptr/mod.rs:621:9 + | +621 | / ub_checks::assert_unsafe_precondition!( +622 | | check_language_ub, +623 | | "ptr::copy requires that both pointer arguments are aligned and non-null", +... | +631 | | && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) +632 | | ); + | |_________^ + | +note: used from within `core::ptr::copy::` + --> $CORE_SRC/ptr/mod.rs:621:9 + | +621 | / ub_checks::assert_unsafe_precondition!( +622 | | check_language_ub, +623 | | "ptr::copy requires that both pointer arguments are aligned and non-null", +... | +631 | | && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) +632 | | ); + | |_________^ note: called by `ptr_copy::copy_via_raw_ptr` - --> $DIR/ptr_copy.rs:28:18 - | -28 | unsafe { core::ptr::copy(src, dst, 1) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/ptr_copy.rs:28:18 + | +28 | unsafe { core::ptr::copy(src, dst, 1) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: called by `ptr_copy::main` - --> $DIR/ptr_copy.rs:33:5 - | -33 | copy_via_raw_ptr(&i, o); - | ^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/ptr_copy.rs:33:5 + | +33 | copy_via_raw_ptr(&i, o); + | ^^^^^^^^^^^^^^^^^^^^^^^ note: called by `main` - --> $DIR/ptr_copy.rs:32:8 - | -32 | pub fn main(i: f32, o: &mut f32) { - | ^^^^ + --> $DIR/ptr_copy.rs:32:8 + | +32 | pub fn main(i: f32, o: &mut f32) { + | ^^^^ error: aborting due to 2 previous errors diff --git a/tests/compiletests/ui/dis/ptr_read.stderr b/tests/compiletests/ui/dis/ptr_read.stderr index 4d4ea6333d..87764b0941 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 1455 8 +OpLine %8 1732 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 4d4ea6333d..87764b0941 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 1455 8 +OpLine %8 1732 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 3b757241cc..26d592becb 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 1655 8 +OpLine %11 1932 8 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 701ac3e759..7b94da100b 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 1655 8 +OpLine %11 1932 8 OpStore %6 %9 OpNoLine OpReturn diff --git a/tests/compiletests/ui/lang/core/unwrap_or.stderr b/tests/compiletests/ui/lang/core/unwrap_or.stderr index acb13945ed..e950047a28 100644 --- a/tests/compiletests/ui/lang/core/unwrap_or.stderr +++ b/tests/compiletests/ui/lang/core/unwrap_or.stderr @@ -3,9 +3,9 @@ OpLine %5 13 11 %6 = OpCompositeInsert %7 %8 %9 0 %10 = OpCompositeExtract %11 %6 1 -OpLine %12 1024 14 +OpLine %12 1026 14 %13 = OpBitcast %14 %8 -OpLine %12 1024 8 +OpLine %12 1026 8 %15 = OpINotEqual %16 %13 %17 OpNoLine OpSelectionMerge %18 None From 8c7f678cd15601cbfdb50bace2c02d6fe63c7b81 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 2 Jul 2025 20:18:40 +0300 Subject: [PATCH 2/4] builder: support suboptimal `format_args!` codegen (extra copies etc.). --- .../src/builder/builder_methods.rs | 165 +++++++++++++++--- 1 file changed, 142 insertions(+), 23 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index aa6b769b9b..0ea0c8647e 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -3246,10 +3246,25 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { // Take `count` instructions, advancing backwards, but returning // instructions in their original order (and decoded to `Inst`s). - let mut try_rev_take = |count| { + let mut try_rev_take = |count: isize| { + // HACK(eddyb) this is extremely silly but it's easier to do + // this than to rely on `Iterator::peekable` or anything else, + // lower down this file, without messing up the state here. + let is_peek = count < 0; + let count = count.unsigned_abs(); + + let mut non_debug_insts_for_peek = is_peek.then(|| non_debug_insts.clone()); + let non_debug_insts = non_debug_insts_for_peek + .as_mut() + .unwrap_or(&mut non_debug_insts); + + // FIXME(eddyb) there might be an easier way to do this, + // e.g. maybe `map_while` + post-`collect` length check? let maybe_rev_insts = (0..count).map(|_| { let (i, inst) = non_debug_insts.next_back()?; - taken_inst_idx_range.start.set(i); + if !is_peek { + taken_inst_idx_range.start.set(i); + } // HACK(eddyb) avoid the logic below that assumes only ID operands if inst.class.opcode == Op::CompositeExtract { @@ -3509,15 +3524,21 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { } }).collect::>()?; - let rev_ref_arg_ids_with_ty_and_spec = (rev_copies_to_rt_args_array_src_ptrs - .into_iter()) - .map(|copy_to_rt_args_array_src_ptr| { + // HACK(eddyb) sometimes there is an extra tuple of refs, + // nowadays, but MIR opts mean it's not always guaranteed, + // hopefully it's always uniform across all the arguments. + let mut maybe_ref_args_tmp_slot_ptr = None; + + let rev_maybe_ref_arg_ids_with_ty_and_spec = ((0..rt_args_count) + .rev() + .zip_eq(rev_copies_to_rt_args_array_src_ptrs)) + .map(|(rt_arg_idx, copy_to_rt_args_array_src_ptr)| { let rt_arg_new_call_insts = try_rev_take(4).ok_or_else(|| { FormatArgsNotRecognized( "fmt::rt::Argument::new call: ran out of instructions".into(), ) })?; - match rt_arg_new_call_insts[..] { + let (ref_arg_id, ty, spec) = match rt_arg_new_call_insts[..] { [ Inst::Call(call_ret_id, callee_id, ref call_args), Inst::InBoundsAccessChain(tmp_slot_field_ptr, tmp_slot_ptr, 0), @@ -3541,36 +3562,134 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { FormatArgsNotRecognized(format!( "fmt::rt::Argument::new call sequence ({rt_arg_new_call_insts:?})" )) - }) + })?; + + // HACK(eddyb) `0` (an invalid ID) is later used as a + // placeholder (see also `maybe_ref_args_tmp_slot_ptr`). + assert_ne!(ref_arg_id, 0); + + // HACK(eddyb) `try_rev_take(-2)` is "peeking", not taking. + let maybe_ref_args_tuple_load_insts = try_rev_take(-2); + let maybe_ref_arg_id = match maybe_ref_args_tuple_load_insts.as_deref() { + Some( + &[ + Inst::InBoundsAccessChain(field_ptr, base_ptr, field_idx), + Inst::Load(ld_val, ld_src_ptr), + ], + ) if maybe_ref_args_tmp_slot_ptr + .is_none_or(|expected| base_ptr == expected) + && field_idx as usize == rt_arg_idx + && (ld_val, ld_src_ptr) == (ref_arg_id, field_ptr) => + { + // HACK(eddyb) consume the peeked instructions. + try_rev_take(2).unwrap(); + + maybe_ref_args_tmp_slot_ptr = Some(base_ptr); + + // HACK(eddyb) using `0` (an invalid ID) as a + // placeholder to require further processing. + 0 + } + _ => ref_arg_id, + }; + + Ok((maybe_ref_arg_id, ty, spec)) }) .collect::>()?; decoded_format_args.ref_arg_ids_with_ty_and_spec = - rev_ref_arg_ids_with_ty_and_spec; + rev_maybe_ref_arg_ids_with_ty_and_spec; decoded_format_args.ref_arg_ids_with_ty_and_spec.reverse(); + + // HACK(eddyb) see above for context regarding the use of + // `0` as placeholders and `maybe_ref_args_tmp_slot_ptr`. + if let Some(ref_args_tmp_slot_ptr) = maybe_ref_args_tmp_slot_ptr { + for (rt_arg_idx, (maybe_ref_arg_id, ..)) in decoded_format_args + .ref_arg_ids_with_ty_and_spec + .iter_mut() + .enumerate() + .rev() + { + if *maybe_ref_arg_id == 0 { + let ref_arg_store_insts = try_rev_take(2).ok_or_else(|| { + FormatArgsNotRecognized( + "fmt::rt::Argument::new argument store: ran out of instructions".into(), + ) + })?; + + *maybe_ref_arg_id = match ref_arg_store_insts[..] { + [ + Inst::InBoundsAccessChain(field_ptr, base_ptr, field_idx), + Inst::Store(st_dst_ptr, st_val), + ] if base_ptr == ref_args_tmp_slot_ptr + && field_idx as usize == rt_arg_idx + && st_dst_ptr == field_ptr => + { + Some(st_val) + } + _ => None, + } + .ok_or_else(|| { + FormatArgsNotRecognized(format!( + "fmt::rt::Argument::new argument store sequence ({ref_arg_store_insts:?})" + )) + })?; + } + } + } } // If the `pieces: &[&str]` slice needs a bitcast, it'll be here. - 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 => in_id, + // 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 + } _ => pieces_slice_ptr_id, }; decoded_format_args.const_pieces = - const_slice_as_elem_ids(pieces_slice_ptr_id, pieces_len).and_then( - |piece_ids| { - piece_ids - .iter() - .map(|&piece_id| { - match self.builder.lookup_const_by_id(piece_id)? { - SpirvConst::Composite(piece) => { - const_str_as_utf8(piece.try_into().ok()?) - } - _ => None, + match const_slice_as_elem_ids(pieces_slice_ptr_id, pieces_len) { + Some(piece_ids) => piece_ids + .iter() + .map( + |&piece_id| match self.builder.lookup_const_by_id(piece_id)? { + SpirvConst::Composite(piece) => { + const_str_as_utf8(piece.try_into().ok()?) } - }) - .collect::>() + _ => 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!`. From 982333eb741e16a7c50e4a20935b196f20585d1c Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 9 Jul 2025 16:31:38 +0300 Subject: [PATCH 3/4] Fix new `clippy::collapsible_if` warnings. --- crates/rustc_codegen_spirv/build.rs | 22 +-- crates/rustc_codegen_spirv/src/abi.rs | 38 ++--- .../src/builder/builder_methods.rs | 115 ++++++------- .../src/builder/spirv_asm.rs | 14 +- .../src/codegen_cx/constant.rs | 21 ++- .../src/codegen_cx/declare.rs | 50 +++--- .../rustc_codegen_spirv/src/codegen_cx/mod.rs | 20 +-- crates/rustc_codegen_spirv/src/lib.rs | 12 +- crates/rustc_codegen_spirv/src/linker/dce.rs | 16 +- .../src/linker/duplicates.rs | 18 +-- .../src/linker/import_export_link.rs | 36 ++--- .../rustc_codegen_spirv/src/linker/inline.rs | 30 ++-- .../rustc_codegen_spirv/src/linker/mem2reg.rs | 48 +++--- .../src/linker/param_weakening.rs | 35 ++-- .../src/linker/peephole_opts.rs | 24 +-- .../src/linker/simple_passes.rs | 35 ++-- .../src/linker/specializer.rs | 114 +++++++------ .../src/linker/spirt_passes/controlflow.rs | 25 ++- .../src/linker/spirt_passes/debuginfo.rs | 102 ++++++------ .../src/linker/spirt_passes/diagnostics.rs | 153 +++++++++--------- .../src/linker/spirt_passes/mod.rs | 10 +- .../src/linker/spirt_passes/reduce.rs | 63 ++++---- crates/spirv-std/macros/src/image.rs | 5 +- crates/spirv-std/macros/src/lib.rs | 12 +- examples/runners/wgpu/src/compute.rs | 77 ++++----- 25 files changed, 528 insertions(+), 567 deletions(-) diff --git a/crates/rustc_codegen_spirv/build.rs b/crates/rustc_codegen_spirv/build.rs index d68757267a..3b46d9d97c 100644 --- a/crates/rustc_codegen_spirv/build.rs +++ b/crates/rustc_codegen_spirv/build.rs @@ -262,17 +262,17 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {", } if line.starts_with('[') { toml_directive = Some(line); - } else if toml_directive == Some("[dependencies]") { - if let Some((name, _)) = line.split_once(" = ") { - // HACK(eddyb) ignore a weird edge case. - if name == "thorin-dwp" { - continue; - } - let extern_crate = format!("extern crate {};", name.replace('-', "_")); - if !all_extern_crates.contains(&extern_crate) { - writeln(&mut all_extern_crates, "#[allow(unused_extern_crates)]"); - writeln(&mut all_extern_crates, &extern_crate); - } + } else if toml_directive == Some("[dependencies]") + && let Some((name, _)) = line.split_once(" = ") + { + // HACK(eddyb) ignore a weird edge case. + if name == "thorin-dwp" { + continue; + } + let extern_crate = format!("extern crate {};", name.replace('-', "_")); + if !all_extern_crates.contains(&extern_crate) { + writeln(&mut all_extern_crates, "#[allow(unused_extern_crates)]"); + writeln(&mut all_extern_crates, &extern_crate); } } } diff --git a/crates/rustc_codegen_spirv/src/abi.rs b/crates/rustc_codegen_spirv/src/abi.rs index 22d1737736..3c0c025845 100644 --- a/crates/rustc_codegen_spirv/src/abi.rs +++ b/crates/rustc_codegen_spirv/src/abi.rs @@ -542,12 +542,11 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { let attrs = AggregatedSpirvAttributes::parse(cx, cx.tcx.get_attrs_unchecked(adt.did())); - if let Some(intrinsic_type_attr) = attrs.intrinsic_type.map(|attr| attr.value) { - if let Ok(spirv_type) = + if let Some(intrinsic_type_attr) = attrs.intrinsic_type.map(|attr| attr.value) + && let Ok(spirv_type) = trans_intrinsic_type(cx, span, *self, args, intrinsic_type_attr) - { - return spirv_type; - } + { + return spirv_type; } } @@ -613,12 +612,12 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { }; // FIXME(eddyb) use `ArrayVec` here. let mut field_names = Vec::new(); - if let TyKind::Adt(adt, _) = self.ty.kind() { - if let Variants::Single { index } = self.variants { - for i in self.fields.index_by_increasing_offset() { - let field = &adt.variants()[index].fields[FieldIdx::new(i)]; - field_names.push(field.name); - } + if let TyKind::Adt(adt, _) = self.ty.kind() + && let Variants::Single { index } = self.variants + { + for i in self.fields.index_by_increasing_offset() { + let field = &adt.variants()[index].fields[FieldIdx::new(i)]; + field_names.push(field.name); } } SpirvType::Adt { @@ -918,10 +917,10 @@ fn trans_struct_or_union<'tcx>( let mut field_offsets = Vec::new(); let mut field_names = Vec::new(); for i in ty.fields.index_by_increasing_offset() { - if let Some(expected_field_idx) = union_case { - if i != expected_field_idx.as_usize() { - continue; - } + if let Some(expected_field_idx) = union_case + && i != expected_field_idx.as_usize() + { + continue; } let field_ty = ty.field(cx, i); @@ -995,10 +994,11 @@ impl<'tcx> From> for TyLayoutNameKey<'tcx> { impl fmt::Display for TyLayoutNameKey<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.ty)?; - if let (TyKind::Adt(def, _), Some(index)) = (self.ty.kind(), self.variant) { - if def.is_enum() && !def.variants().is_empty() { - write!(f, "::{}", def.variants()[index].name)?; - } + if let (TyKind::Adt(def, _), Some(index)) = (self.ty.kind(), self.variant) + && def.is_enum() + && !def.variants().is_empty() + { + write!(f, "::{}", def.variants()[index].name)?; } if let (TyKind::Coroutine(_, _), Some(index)) = (self.ty.kind(), self.variant) { write!(f, "::{}", CoroutineArgs::variant_name(index))?; diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index 0ea0c8647e..1fb35929c5 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -1791,14 +1791,12 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { // nightlies - and that PR happens to remove the last GEP that can be // emitted with any "structured" (struct/array) indices, beyond the // "first index" (which acts as `<*T>::offset` aka "pointer arithmetic"). - if let &[ptr_base_index, structured_index] = indices { - if self.builder.lookup_const_scalar(ptr_base_index) == Some(0) { - if let SpirvType::Array { element, .. } | SpirvType::RuntimeArray { element, .. } = - self.lookup_type(ty) - { - return self.maybe_inbounds_gep(element, ptr, &[structured_index], true); - } - } + if let &[ptr_base_index, structured_index] = indices + && self.builder.lookup_const_scalar(ptr_base_index) == Some(0) + && let SpirvType::Array { element, .. } | SpirvType::RuntimeArray { element, .. } = + self.lookup_type(ty) + { + return self.maybe_inbounds_gep(element, ptr, &[structured_index], true); } self.maybe_inbounds_gep(ty, ptr, indices, true) @@ -1883,22 +1881,20 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { // capabilities. For example, casting a f16 constant to f32 will directly // create a f32 constant, avoiding the need for Float16 capability if it is // not used elsewhere. - if let Some(const_val) = self.builder.lookup_const_scalar(val) { - if let (SpirvType::Float(src_width), SpirvType::Float(dst_width)) = + if let Some(const_val) = self.builder.lookup_const_scalar(val) + && let (SpirvType::Float(src_width), SpirvType::Float(dst_width)) = (self.lookup_type(val.ty), self.lookup_type(dest_ty)) - { - if src_width < dst_width { - // Convert the bit representation to the actual float value - let float_val = match src_width { - 32 => Some(f32::from_bits(const_val as u32) as f64), - 64 => Some(f64::from_bits(const_val as u64)), - _ => None, - }; + && src_width < dst_width + { + // Convert the bit representation to the actual float value + let float_val = match src_width { + 32 => Some(f32::from_bits(const_val as u32) as f64), + 64 => Some(f64::from_bits(const_val as u64)), + _ => None, + }; - if let Some(val) = float_val { - return self.constant_float(dest_ty, val); - } - } + if let Some(val) = float_val { + return self.constant_float(dest_ty, val); } } @@ -3105,14 +3101,11 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { let const_slice_as_elem_ids = |ptr_id: Word, len: usize| { if let SpirvConst::PtrTo { pointee } = self.builder.lookup_const_by_id(ptr_id)? - { - if let SpirvConst::Composite(elems) = + && let SpirvConst::Composite(elems) = self.builder.lookup_const_by_id(pointee)? - { - if elems.len() == len { - return Some(elems); - } - } + && elems.len() == len + { + return Some(elems); } None }; @@ -3147,12 +3140,11 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { ] = args[..] { // Optional `&'static panic::Location<'static>`. - if other_args.len() <= 1 { - if let Some(const_msg) = const_str_as_utf8(&[a_id, b_id]) { - decoded_format_args.const_pieces = - Some([const_msg].into_iter().collect()); - return Ok(decoded_format_args); - } + if other_args.len() <= 1 + && let Some(const_msg) = const_str_as_utf8(&[a_id, b_id]) + { + decoded_format_args.const_pieces = Some([const_msg].into_iter().collect()); + return Ok(decoded_format_args); } } @@ -3267,12 +3259,11 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { } // HACK(eddyb) avoid the logic below that assumes only ID operands - if inst.class.opcode == Op::CompositeExtract { - if let (Some(r), &[Operand::IdRef(x), Operand::LiteralBit32(i)]) = + if inst.class.opcode == Op::CompositeExtract + && let (Some(r), &[Operand::IdRef(x), Operand::LiteralBit32(i)]) = (inst.result_id, &inst.operands[..]) - { - return Some(Inst::CompositeExtract(r, x, i)); - } + { + return Some(Inst::CompositeExtract(r, x, i)); } // HACK(eddyb) all instructions accepted below @@ -3483,8 +3474,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { // access chain cases that `inbounds_gep` can now cause. if let Inst::InBoundsAccessChain(dst_field_ptr, dst_base_ptr, 0) = copy_to_rt_args_array_insts[0] - { - if let Some(mut prev_insts) = try_rev_take(1) { + && let Some(mut prev_insts) = try_rev_take(1) { assert_eq!(prev_insts.len(), 1); let prev_inst = prev_insts.pop().unwrap(); @@ -3503,7 +3493,6 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { } } } - } match copy_to_rt_args_array_insts[..] { [ @@ -3855,27 +3844,27 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { // Since From is only implemented for safe conversions (widening conversions that preserve // the numeric value), we can directly create a constant of the target type for primitive // numeric types. - if let [arg] = args { - if let Some(const_val) = self.builder.lookup_const_scalar(*arg) { - use rustc_middle::ty::FloatTy; - let optimized_result = match (source_ty.kind(), target_ty.kind()) { - // Integer widening conversions - (ty::Uint(_), ty::Uint(_)) | (ty::Int(_), ty::Int(_)) => { - Some(self.constant_int(result_type, const_val)) - } - // Float widening conversions - // TODO(@LegNeato): Handle more float types - (ty::Float(FloatTy::F32), ty::Float(FloatTy::F64)) => { - let float_val = f32::from_bits(const_val as u32) as f64; - Some(self.constant_float(result_type, float_val)) - } - // No optimization for narrowing conversions or unsupported types - _ => None, - }; - - if let Some(result) = optimized_result { - return result; + if let [arg] = args + && let Some(const_val) = self.builder.lookup_const_scalar(*arg) + { + use rustc_middle::ty::FloatTy; + let optimized_result = match (source_ty.kind(), target_ty.kind()) { + // Integer widening conversions + (ty::Uint(_), ty::Uint(_)) | (ty::Int(_), ty::Int(_)) => { + Some(self.constant_int(result_type, const_val)) } + // Float widening conversions + // TODO(@LegNeato): Handle more float types + (ty::Float(FloatTy::F32), ty::Float(FloatTy::F64)) => { + let float_val = f32::from_bits(const_val as u32) as f64; + Some(self.constant_float(result_type, float_val)) + } + // No optimization for narrowing conversions or unsupported types + _ => None, + }; + + if let Some(result) = optimized_result { + return result; } } } diff --git a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs index 320716f1f8..663ebbeaf4 100644 --- a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs +++ b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs @@ -126,15 +126,13 @@ impl<'a, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'tcx> { | InlineAsmOperandRef::Label { .. } => (None, None), }; - if let Some(in_value) = in_value { - if let (BackendRepr::Scalar(scalar), OperandValue::Immediate(in_value_spv)) = + if let Some(in_value) = in_value + && let (BackendRepr::Scalar(scalar), OperandValue::Immediate(in_value_spv)) = (in_value.layout.backend_repr, &mut in_value.val) - { - if let Primitive::Pointer(_) = scalar.primitive() { - let in_value_precise_type = in_value.layout.spirv_type(self.span(), self); - *in_value_spv = self.pointercast(*in_value_spv, in_value_precise_type); - } - } + && let Primitive::Pointer(_) = scalar.primitive() + { + let in_value_precise_type = in_value.layout.spirv_type(self.span(), self); + *in_value_spv = self.pointercast(*in_value_spv, in_value_precise_type); } if let Some(out_place) = out_place { let out_place_precise_type = out_place.layout.spirv_type(self.span(), self); diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs index 87e7338de5..de18275db1 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs @@ -343,18 +343,15 @@ impl<'tcx> CodegenCx<'tcx> { 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`). - if let SpirvValueKind::IllegalConst(_) = val.kind { - if let Some(SpirvConst::PtrTo { pointee }) = self.builder.lookup_const(val) { - if let Some(SpirvConst::ConstDataFromAlloc(alloc)) = - self.builder.lookup_const_by_id(pointee) - { - if let SpirvType::Pointer { pointee } = self.lookup_type(ty) { - let mut offset = Size::ZERO; - let init = self.read_from_const_alloc(alloc, &mut offset, pointee); - return self.static_addr_of(init, alloc.inner().align, None); - } - } - } + if let SpirvValueKind::IllegalConst(_) = val.kind + && let Some(SpirvConst::PtrTo { pointee }) = self.builder.lookup_const(val) + && let Some(SpirvConst::ConstDataFromAlloc(alloc)) = + self.builder.lookup_const_by_id(pointee) + && let SpirvType::Pointer { pointee } = self.lookup_type(ty) + { + let mut offset = Size::ZERO; + let init = self.read_from_const_alloc(alloc, &mut offset, pointee); + return self.static_addr_of(init, alloc.inner().align, 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 909c3bb0ee..73b434a8bf 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs @@ -168,25 +168,25 @@ impl<'tcx> CodegenCx<'tcx> { } // Check if this is a From trait implementation - if let Some(impl_def_id) = self.tcx.impl_of_method(def_id) { - if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) { - let trait_def_id = trait_ref.skip_binder().def_id; - - // Check if this is the From trait. - let trait_path = self.tcx.def_path_str(trait_def_id); - if matches!( - trait_path.as_str(), - "core::convert::From" | "std::convert::From" - ) { - // Extract the source and target types from the trait substitutions - let trait_args = trait_ref.skip_binder().args; - if let (Some(target_ty), Some(source_ty)) = - (trait_args.types().nth(0), trait_args.types().nth(1)) - { - self.from_trait_impls - .borrow_mut() - .insert(def_id, (source_ty, target_ty)); - } + if let Some(impl_def_id) = self.tcx.impl_of_method(def_id) + && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) + { + let trait_def_id = trait_ref.skip_binder().def_id; + + // Check if this is the From trait. + let trait_path = self.tcx.def_path_str(trait_def_id); + if matches!( + trait_path.as_str(), + "core::convert::From" | "std::convert::From" + ) { + // Extract the source and target types from the trait substitutions + let trait_args = trait_ref.skip_binder().args; + if let (Some(target_ty), Some(source_ty)) = + (trait_args.types().nth(0), trait_args.types().nth(1)) + { + self.from_trait_impls + .borrow_mut() + .insert(def_id, (source_ty, target_ty)); } } } @@ -251,12 +251,12 @@ impl<'tcx> CodegenCx<'tcx> { _ => return None, }) }); - if let Some(spec) = spec { - if let Some((ty,)) = instance.args.types().collect_tuple() { - self.fmt_rt_arg_new_fn_ids_to_ty_and_spec - .borrow_mut() - .insert(fn_id, (ty, spec)); - } + if let Some(spec) = spec + && let Some((ty,)) = instance.args.types().collect_tuple() + { + self.fmt_rt_arg_new_fn_ids_to_ty_and_spec + .borrow_mut() + .insert(fn_id, (ty, spec)); } } diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs index 744c7695d7..24d8373447 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs @@ -774,16 +774,16 @@ impl CodegenArgs { // with just the filename component of the path. if inst.class.opcode == Op::String { let path = Path::new(inst.operands[0].unwrap_literal_string()); - if path.is_absolute() { - if let Some(file_name) = path.file_name() { - let mut inst = inst.clone(); - inst.operands[0] = Operand::LiteralString(format!( - "$OPSTRING_FILENAME/{}", - file_name.to_string_lossy(), - )); - eprintln!("{}", inst.disassemble()); - continue; - } + if path.is_absolute() + && let Some(file_name) = path.file_name() + { + let mut inst = inst.clone(); + inst.operands[0] = Operand::LiteralString(format!( + "$OPSTRING_FILENAME/{}", + file_name.to_string_lossy(), + )); + eprintln!("{}", inst.disassemble()); + continue; } } eprintln!("{}", inst.disassemble()); diff --git a/crates/rustc_codegen_spirv/src/lib.rs b/crates/rustc_codegen_spirv/src/lib.rs index a9238cfeae..2954fd31d4 100644 --- a/crates/rustc_codegen_spirv/src/lib.rs +++ b/crates/rustc_codegen_spirv/src/lib.rs @@ -178,12 +178,12 @@ fn dump_mir(tcx: TyCtxt<'_>, mono_items: &[(MonoItem<'_>, MonoItemData)], path: create_dir_all(path.parent().unwrap()).unwrap(); let mut file = File::create(path).unwrap(); for &(mono_item, _) in mono_items { - if let MonoItem::Fn(instance) = mono_item { - if matches!(instance.def, InstanceKind::Item(_)) { - let mut mir = Cursor::new(Vec::new()); - if write_mir_pretty(tcx, Some(instance.def_id()), &mut mir).is_ok() { - writeln!(file, "{}", String::from_utf8(mir.into_inner()).unwrap()).unwrap(); - } + if let MonoItem::Fn(instance) = mono_item + && matches!(instance.def, InstanceKind::Item(_)) + { + let mut mir = Cursor::new(Vec::new()); + if write_mir_pretty(tcx, Some(instance.def_id()), &mut mir).is_ok() { + writeln!(file, "{}", String::from_utf8(mir.into_inner()).unwrap()).unwrap(); } } } diff --git a/crates/rustc_codegen_spirv/src/linker/dce.rs b/crates/rustc_codegen_spirv/src/linker/dce.rs index 6c702d8862..20bcbd3310 100644 --- a/crates/rustc_codegen_spirv/src/linker/dce.rs +++ b/crates/rustc_codegen_spirv/src/linker/dce.rs @@ -57,10 +57,10 @@ fn all_inst_iter(func: &Function) -> impl DoubleEndedIterator) -> bool { let mut any = false; for inst in module.global_inst_iter() { - if let Some(id) = inst.result_id { - if rooted.contains(&id) { - any |= root(inst, rooted); - } + if let Some(id) = inst.result_id + && rooted.contains(&id) + { + any |= root(inst, rooted); } } for func in &module.functions { @@ -72,10 +72,10 @@ fn spread_roots(module: &Module, rooted: &mut FxIndexSet) -> bool { for inst in all_inst_iter(func).rev() { if !instruction_is_pure(inst) { any |= root(inst, rooted); - } else if let Some(id) = inst.result_id { - if rooted.contains(&id) { - any |= root(inst, rooted); - } + } else if let Some(id) = inst.result_id + && rooted.contains(&id) + { + any |= root(inst, rooted); } } } diff --git a/crates/rustc_codegen_spirv/src/linker/duplicates.rs b/crates/rustc_codegen_spirv/src/linker/duplicates.rs index 0f8a36d8a0..76f85a7713 100644 --- a/crates/rustc_codegen_spirv/src/linker/duplicates.rs +++ b/crates/rustc_codegen_spirv/src/linker/duplicates.rs @@ -56,10 +56,10 @@ pub fn remove_duplicate_ext_inst_imports(module: &mut Module) { // Then rewrite all OpExtInst referencing the rewritten IDs for inst in module.all_inst_iter_mut() { - if inst.class.opcode == Op::ExtInst { - if let Operand::IdRef(ref mut id) = inst.operands[0] { - *id = rewrite_rules.get(id).copied().unwrap_or(*id); - } + if inst.class.opcode == Op::ExtInst + && let Operand::IdRef(ref mut id) = inst.operands[0] + { + *id = rewrite_rules.get(id).copied().unwrap_or(*id); } } } @@ -201,11 +201,11 @@ pub fn remove_duplicate_types(module: &mut Module) { let names = gather_names(&module.debug_names); for inst in &mut module.types_global_values { - if inst.class.opcode == Op::TypeForwardPointer { - if let Operand::IdRef(id) = inst.operands[0] { - unresolved_forward_pointers.insert(id); - continue; - } + if inst.class.opcode == Op::TypeForwardPointer + && let Operand::IdRef(id) = inst.operands[0] + { + unresolved_forward_pointers.insert(id); + continue; } if inst.class.opcode == Op::TypePointer && unresolved_forward_pointers.contains(&inst.result_id.unwrap()) diff --git a/crates/rustc_codegen_spirv/src/linker/import_export_link.rs b/crates/rustc_codegen_spirv/src/linker/import_export_link.rs index e5290af40d..c93cb3a78d 100644 --- a/crates/rustc_codegen_spirv/src/linker/import_export_link.rs +++ b/crates/rustc_codegen_spirv/src/linker/import_export_link.rs @@ -34,16 +34,16 @@ fn find_import_export_pairs_and_killed_params( .map(|(z, _)| z) .collect(); for inst in module.global_inst_iter() { - if let Some(result_id) = inst.result_id { - if !zombie_infected.contains(&result_id) { - let mut id_operands = inst.operands.iter().filter_map(|o| o.id_ref_any()); - // NOTE(eddyb) this takes advantage of the fact that the module - // is ordered def-before-use (with the minor exception of forward - // references for recursive data, which are not fully supported), - // to be able to propagate "zombie infection" in one pass. - if id_operands.any(|id| zombie_infected.contains(&id)) { - zombie_infected.insert(result_id); - } + if let Some(result_id) = inst.result_id + && !zombie_infected.contains(&result_id) + { + let mut id_operands = inst.operands.iter().filter_map(|o| o.id_ref_any()); + // NOTE(eddyb) this takes advantage of the fact that the module + // is ordered def-before-use (with the minor exception of forward + // references for recursive data, which are not fully supported), + // to be able to propagate "zombie infection" in one pass. + if id_operands.any(|id| zombie_infected.contains(&id)) { + zombie_infected.insert(result_id); } } } @@ -202,17 +202,17 @@ fn check_tys_equal( fn replace_all_uses_with(module: &mut Module, rules: &FxHashMap) { module.all_inst_iter_mut().for_each(|inst| { - if let Some(result_type) = &mut inst.result_type { - if let Some(&rewrite) = rules.get(result_type) { - *result_type = rewrite; - } + if let Some(result_type) = &mut inst.result_type + && let Some(&rewrite) = rules.get(result_type) + { + *result_type = rewrite; } inst.operands.iter_mut().for_each(|op| { - if let Some(w) = op.id_ref_any_mut() { - if let Some(&rewrite) = rules.get(w) { - *w = rewrite; - } + if let Some(w) = op.id_ref_any_mut() + && let Some(&rewrite) = rules.get(w) + { + *w = rewrite; } }); }); diff --git a/crates/rustc_codegen_spirv/src/linker/inline.rs b/crates/rustc_codegen_spirv/src/linker/inline.rs index 34a4886ca0..0ab19bd40f 100644 --- a/crates/rustc_codegen_spirv/src/linker/inline.rs +++ b/crates/rustc_codegen_spirv/src/linker/inline.rs @@ -510,13 +510,13 @@ impl Inliner<'_, '_> { // AFAIK there is no case where keeping decorations on inline wouldn't be valid. for annotation_idx in 0..self.annotations.len() { let inst = &self.annotations[annotation_idx]; - if let [Operand::IdRef(target), ..] = inst.operands[..] { - if let Some(&rewritten_target) = rewrite_rules.get(&target) { - // Copy decoration instruction and push it. - let mut cloned_inst = inst.clone(); - cloned_inst.operands[0] = Operand::IdRef(rewritten_target); - self.annotations.push(cloned_inst); - } + if let [Operand::IdRef(target), ..] = inst.operands[..] + && let Some(&rewritten_target) = rewrite_rules.get(&target) + { + // Copy decoration instruction and push it. + let mut cloned_inst = inst.clone(); + cloned_inst.operands[0] = Operand::IdRef(rewritten_target); + self.annotations.push(cloned_inst); } } } @@ -664,10 +664,10 @@ impl Inliner<'_, '_> { // HACK(eddyb) new IDs should be generated earlier, to avoid pushing // callee IDs to `call_result_phi.operands` only to rewrite them here. for op in &mut call_result_phi.operands { - if let Some(id) = op.id_ref_any_mut() { - if let Some(&rewrite) = rewrite_rules.get(id) { - *id = rewrite; - } + if let Some(id) = op.id_ref_any_mut() + && let Some(&rewrite) = rewrite_rules.get(id) + { + *id = rewrite; } } @@ -699,10 +699,10 @@ impl Inliner<'_, '_> { }; for reaching_inst in reaching_insts { for op in &mut reaching_inst.operands { - if let Some(id) = op.id_ref_any_mut() { - if *id == call_result_id { - *id = returned_value_id; - } + if let Some(id) = op.id_ref_any_mut() + && *id == call_result_id + { + *id = returned_value_id; } } } diff --git a/crates/rustc_codegen_spirv/src/linker/mem2reg.rs b/crates/rustc_codegen_spirv/src/linker/mem2reg.rs index 6a2cb926d5..df2434d63d 100644 --- a/crates/rustc_codegen_spirv/src/linker/mem2reg.rs +++ b/crates/rustc_codegen_spirv/src/linker/mem2reg.rs @@ -265,31 +265,27 @@ fn collect_access_chains( let mut changed = false; for inst in blocks.values().flat_map(|b| &b.instructions) { for (index, op) in inst.operands.iter().enumerate() { - if let Operand::IdRef(id) = op { - if variables.contains_key(id) { - match inst.class.opcode { - // Only allow store if pointer is the lhs, not rhs - Op::Store if index == 0 => {} - Op::Load - | Op::AccessChain - | Op::InBoundsAccessChain - | Op::CopyMemory => {} - _ => return None, - } + if let Operand::IdRef(id) = op + && variables.contains_key(id) + { + match inst.class.opcode { + // Only allow store if pointer is the lhs, not rhs + Op::Store if index == 0 => {} + Op::Load | Op::AccessChain | Op::InBoundsAccessChain | Op::CopyMemory => {} + _ => return None, } } } - if let Op::AccessChain | Op::InBoundsAccessChain = inst.class.opcode { - if let Some(base) = variables.get(&inst.operands[0].id_ref_any().unwrap()) { - let info = - construct_access_chain_info(pointer_to_pointee, constants, inst, base)?; - match variables.entry(inst.result_id.unwrap()) { - hash_map::Entry::Vacant(entry) => { - entry.insert(info); - changed = true; - } - hash_map::Entry::Occupied(_) => {} + if let Op::AccessChain | Op::InBoundsAccessChain = inst.class.opcode + && let Some(base) = variables.get(&inst.operands[0].id_ref_any().unwrap()) + { + let info = construct_access_chain_info(pointer_to_pointee, constants, inst, base)?; + match variables.entry(inst.result_id.unwrap()) { + hash_map::Entry::Vacant(entry) => { + entry.insert(info); + changed = true; } + hash_map::Entry::Occupied(_) => {} } } } @@ -492,11 +488,11 @@ impl Renamer<'_, '_> { fn rename(&mut self, block: usize, from_block: Option) { let original_stack = self.stack.len(); - if let Some(from_block) = from_block { - if self.blocks_with_phi.contains(&block) { - let new_top = self.insert_phi_value(block, from_block); - self.stack.push(new_top); - } + if let Some(from_block) = from_block + && self.blocks_with_phi.contains(&block) + { + let new_top = self.insert_phi_value(block, from_block); + self.stack.push(new_top); } if !self.visited.insert(block) { diff --git a/crates/rustc_codegen_spirv/src/linker/param_weakening.rs b/crates/rustc_codegen_spirv/src/linker/param_weakening.rs index ee9df070c5..ebc0cdb7e6 100644 --- a/crates/rustc_codegen_spirv/src/linker/param_weakening.rs +++ b/crates/rustc_codegen_spirv/src/linker/param_weakening.rs @@ -48,16 +48,16 @@ pub fn remove_unused_params(module: Module) -> Module { }; for (i, operand) in operands.iter().enumerate() { - if let Some(ignore_operands) = ignore_operands { - if ignore_operands.contains(i) { - continue; - } + if let Some(ignore_operands) = ignore_operands + && ignore_operands.contains(i) + { + continue; } - if let Operand::IdRef(id) = operand { - if let Some(¶m_idx) = params_id_to_idx.get(id) { - unused_params.remove(param_idx); - } + if let Operand::IdRef(id) = operand + && let Some(¶m_idx) = params_id_to_idx.get(id) + { + unused_params.remove(param_idx); } } } @@ -82,17 +82,16 @@ pub fn remove_unused_params(module: Module) -> Module { } for inst in func.all_inst_iter_mut() { - if inst.class.opcode == Op::FunctionCall { - if let Some(unused_callee_params) = + if inst.class.opcode == Op::FunctionCall + && let Some(unused_callee_params) = unused_params_per_func_id.get(&inst.operands[0].unwrap_id_ref()) - { - inst.operands = mem::take(&mut inst.operands) - .into_iter() - .enumerate() - .filter(|&(i, _)| i == 0 || !unused_callee_params.contains(i - 1)) - .map(|(_, o)| o) - .collect(); - } + { + inst.operands = mem::take(&mut inst.operands) + .into_iter() + .enumerate() + .filter(|&(i, _)| i == 0 || !unused_callee_params.contains(i - 1)) + .map(|(_, o)| o) + .collect(); } } diff --git a/crates/rustc_codegen_spirv/src/linker/peephole_opts.rs b/crates/rustc_codegen_spirv/src/linker/peephole_opts.rs index 6a0df87bfd..abd30051f0 100644 --- a/crates/rustc_codegen_spirv/src/linker/peephole_opts.rs +++ b/crates/rustc_codegen_spirv/src/linker/peephole_opts.rs @@ -344,20 +344,20 @@ fn process_instruction( // Fun little optimization: SPIR-V has a fancy OpVectorTimesScalar instruction. If we have a // vector times a collection of scalars, and the scalars are all the same, reduce it! - if operation_opcode == Op::FMul && composite_arguments.len() == 2 { - if let (&IdentifiedOperand::Vector(composite), IdentifiedOperand::Scalars(scalars)) + if operation_opcode == Op::FMul + && composite_arguments.len() == 2 + && let (&IdentifiedOperand::Vector(composite), IdentifiedOperand::Scalars(scalars)) | (IdentifiedOperand::Scalars(scalars), &IdentifiedOperand::Vector(composite)) = (&composite_arguments[0], &composite_arguments[1]) - { - let scalar = scalars[0]; - if scalars.iter().skip(1).all(|&s| s == scalar) { - return Some(Instruction::new( - Op::VectorTimesScalar, - inst.result_type, - inst.result_id, - vec![Operand::IdRef(composite), Operand::IdRef(scalar)], - )); - } + { + let scalar = scalars[0]; + if scalars.iter().skip(1).all(|&s| s == scalar) { + return Some(Instruction::new( + Op::VectorTimesScalar, + inst.result_type, + inst.result_id, + vec![Operand::IdRef(composite), Operand::IdRef(scalar)], + )); } } diff --git a/crates/rustc_codegen_spirv/src/linker/simple_passes.rs b/crates/rustc_codegen_spirv/src/linker/simple_passes.rs index 77932b99c7..32a47d12a3 100644 --- a/crates/rustc_codegen_spirv/src/linker/simple_passes.rs +++ b/crates/rustc_codegen_spirv/src/linker/simple_passes.rs @@ -69,12 +69,11 @@ pub fn block_ordering_pass(func: &mut Function) { let mut edges = outgoing_edges(current_block).collect::>(); // HACK(eddyb) treat `OpSelectionMerge` as an edge, in case it points // to an otherwise-unreachable block. - if let Some(before_last_idx) = current_block.instructions.len().checked_sub(2) { - if let Some(before_last) = current_block.instructions.get(before_last_idx) { - if before_last.class.opcode == Op::SelectionMerge { - edges.push(before_last.operands[0].unwrap_id_ref()); - } - } + if let Some(before_last_idx) = current_block.instructions.len().checked_sub(2) + && let Some(before_last) = current_block.instructions.get(before_last_idx) + && before_last.class.opcode == Op::SelectionMerge + { + edges.push(before_last.operands[0].unwrap_id_ref()); } // Reverse the order, so reverse-postorder keeps things tidy for &outgoing in edges.iter().rev() { @@ -308,23 +307,23 @@ pub fn check_type_capabilities(sess: &Session, module: &Module) -> Result<()> { let signedness = inst.operands[1].unwrap_literal_bit32() != 0; let type_name = if signedness { "i" } else { "u" }; - if let Some(required_cap) = capability_for_int_width(width) { - if !declared_capabilities.contains(&required_cap) { - errors.push(format!( - "`{type_name}{width}` type used without `OpCapability {required_cap:?}`" - )); - } + if let Some(required_cap) = capability_for_int_width(width) + && !declared_capabilities.contains(&required_cap) + { + errors.push(format!( + "`{type_name}{width}` type used without `OpCapability {required_cap:?}`" + )); } } Op::TypeFloat => { let width = inst.operands[0].unwrap_literal_bit32(); - if let Some(required_cap) = capability_for_float_width(width) { - if !declared_capabilities.contains(&required_cap) { - errors.push(format!( - "`f{width}` type used without `OpCapability {required_cap:?}`" - )); - } + if let Some(required_cap) = capability_for_float_width(width) + && !declared_capabilities.contains(&required_cap) + { + errors.push(format!( + "`f{width}` type used without `OpCapability {required_cap:?}`" + )); } } _ => {} diff --git a/crates/rustc_codegen_spirv/src/linker/specializer.rs b/crates/rustc_codegen_spirv/src/linker/specializer.rs index 88b8095062..f8184fe550 100644 --- a/crates/rustc_codegen_spirv/src/linker/specializer.rs +++ b/crates/rustc_codegen_spirv/src/linker/specializer.rs @@ -145,22 +145,21 @@ pub fn specialize( for inst in &module.entry_points { for interface_operand in &inst.operands[3..] { let interface_id = interface_operand.unwrap_id_ref(); - if let Some(generic) = specializer.generics.get(&interface_id) { - if let Some(param_values) = &generic.param_values { - if param_values.iter().all(|v| matches!(v, Value::Known(_))) { - interface_concrete_instances.insert(Instance { - generic_id: interface_id, - generic_args: param_values - .iter() - .copied() - .map(|v| match v { - Value::Known(v) => v, - _ => unreachable!(), - }) - .collect(), - }); - } - } + if let Some(generic) = specializer.generics.get(&interface_id) + && let Some(param_values) = &generic.param_values + && param_values.iter().all(|v| matches!(v, Value::Known(_))) + { + interface_concrete_instances.insert(Instance { + generic_id: interface_id, + generic_args: param_values + .iter() + .copied() + .map(|v| match v { + Value::Known(v) => v, + _ => unreachable!(), + }) + .collect(), + }); } } } @@ -588,10 +587,10 @@ impl Specializer { }; // Record all integer `OpConstant`s (used for `IndexComposite`). - if inst.class.opcode == Op::Constant { - if let Operand::LiteralBit32(x) = inst.operands[0] { - self.int_consts.insert(result_id, x); - } + if inst.class.opcode == Op::Constant + && let Operand::LiteralBit32(x) = inst.operands[0] + { + self.int_consts.insert(result_id, x); } // Instantiate `inst` in a fresh inference context, to determine @@ -2095,10 +2094,9 @@ impl<'a, S: Specialization> InferCx<'a, S> { if let (Some(expected), Some(found)) = ( ret_ty.clone(), self.type_of_result.get(&ret_val_id).cloned(), - ) { - if let Err(e) = self.equate_infer_operands(expected, found) { - e.report(inst); - } + ) && let Err(e) = self.equate_infer_operands(expected, found) + { + e.report(inst); } } @@ -2336,17 +2334,17 @@ impl<'a, S: Specialization> Expander<'a, S> { let expand_debug_or_annotation = |insts: Vec| { let mut expanded_insts = Vec::with_capacity(insts.len().next_power_of_two()); for inst in insts { - if let [Operand::IdRef(target), ..] = inst.operands[..] { - if self.specializer.generics.contains_key(&target) { - expanded_insts.extend(self.all_instances_of(target).map( - |(_, &instance_id)| { - let mut expanded_inst = inst.clone(); - expanded_inst.operands[0] = Operand::IdRef(instance_id); - expanded_inst - }, - )); - continue; - } + if let [Operand::IdRef(target), ..] = inst.operands[..] + && self.specializer.generics.contains_key(&target) + { + expanded_insts.extend(self.all_instances_of(target).map( + |(_, &instance_id)| { + let mut expanded_inst = inst.clone(); + expanded_inst.operands[0] = Operand::IdRef(instance_id); + expanded_inst + }, + )); + continue; } expanded_insts.push(inst); } @@ -2363,23 +2361,23 @@ impl<'a, S: Specialization> Expander<'a, S> { let mut expanded_types_global_values = Vec::with_capacity(types_global_values.len().next_power_of_two()); for inst in types_global_values { - if let Some(result_id) = inst.result_id { - if let Some(generic) = self.specializer.generics.get(&result_id) { - expanded_types_global_values.extend(self.all_instances_of(result_id).map( - |(instance, &instance_id)| { - let mut expanded_inst = inst.clone(); - expanded_inst.result_id = Some(instance_id); - for (loc, operand) in generic - .replacements - .to_concrete(&instance.generic_args, |i| self.instances[&i]) - { - expanded_inst.index_set(loc, operand.into()); - } - expanded_inst - }, - )); - continue; - } + if let Some(result_id) = inst.result_id + && let Some(generic) = self.specializer.generics.get(&result_id) + { + expanded_types_global_values.extend(self.all_instances_of(result_id).map( + |(instance, &instance_id)| { + let mut expanded_inst = inst.clone(); + expanded_inst.result_id = Some(instance_id); + for (loc, operand) in generic + .replacements + .to_concrete(&instance.generic_args, |i| self.instances[&i]) + { + expanded_inst.index_set(loc, operand.into()); + } + expanded_inst + }, + )); + continue; } expanded_types_global_values.push(inst); } @@ -2444,12 +2442,12 @@ impl<'a, S: Specialization> Expander<'a, S> { // HACK(eddyb) this duplicates similar logic from `inline`. for annotation_idx in 0..expanded_annotations.len() { let inst = &expanded_annotations[annotation_idx]; - if let [Operand::IdRef(target), ..] = inst.operands[..] { - if let Some(&rewritten_target) = rewrite_rules.get(&target) { - let mut expanded_inst = inst.clone(); - expanded_inst.operands[0] = Operand::IdRef(rewritten_target); - expanded_annotations.push(expanded_inst); - } + if let [Operand::IdRef(target), ..] = inst.operands[..] + && let Some(&rewritten_target) = rewrite_rules.get(&target) + { + let mut expanded_inst = inst.clone(); + expanded_inst.operands[0] = Operand::IdRef(rewritten_target); + expanded_annotations.push(expanded_inst); } } } diff --git a/crates/rustc_codegen_spirv/src/linker/spirt_passes/controlflow.rs b/crates/rustc_codegen_spirv/src/linker/spirt_passes/controlflow.rs index 76ae455e02..9be7cb4dc5 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/controlflow.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/controlflow.rs @@ -113,20 +113,17 @@ pub fn convert_custom_aborts_to_unstructured_returns_in_entry_points( .filter_map(|func_at_inst| { let data_inst_def = func_at_inst.def(); let data_inst_form_def = &cx[data_inst_def.form]; - if let DataInstKind::SpvInst(spv_inst) = &data_inst_form_def.kind { - if spv_inst.opcode == wk.OpLoad { - if let Value::Const(ct) = data_inst_def.inputs[0] { - if let ConstKind::PtrToGlobalVar(gv) = cx[ct].kind { - if interface_global_vars.contains(&gv) { - return Some(( - gv, - data_inst_form_def.output_type.unwrap(), - Value::DataInstOutput(func_at_inst.position), - )); - } - } - } - } + if let DataInstKind::SpvInst(spv_inst) = &data_inst_form_def.kind + && spv_inst.opcode == wk.OpLoad + && let Value::Const(ct) = data_inst_def.inputs[0] + && let ConstKind::PtrToGlobalVar(gv) = cx[ct].kind + && interface_global_vars.contains(&gv) + { + return Some(( + gv, + data_inst_form_def.output_type.unwrap(), + Value::DataInstOutput(func_at_inst.position), + )); } None }); diff --git a/crates/rustc_codegen_spirv/src/linker/spirt_passes/debuginfo.rs b/crates/rustc_codegen_spirv/src/linker/spirt_passes/debuginfo.rs index e89e079c9d..6ac52bb2b1 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/debuginfo.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/debuginfo.rs @@ -84,60 +84,58 @@ impl Transformer for CustomDebuginfoToSpv<'_> { ext_set, inst: ext_inst, } = self.cx[data_inst_def.form].kind + && ext_set == self.custom_ext_inst_set { - if ext_set == self.custom_ext_inst_set { - let custom_op = CustomOp::decode(ext_inst); - match custom_op.with_operands(&data_inst_def.inputs) { - CustomInst::SetDebugSrcLoc { - file, - line_start: line, - line_end: _, - col_start: col, - col_end: _, - } => { - let const_kind = |v: Value| match v { - Value::Const(ct) => &self.cx[ct].kind, - _ => unreachable!(), - }; - let const_str = |v: Value| match const_kind(v) { - &ConstKind::SpvStringLiteralForExtInst(s) => s, - _ => unreachable!(), - }; - let const_u32 = |v: Value| match const_kind(v) { - ConstKind::SpvInst { - spv_inst_and_const_inputs, - } => { - let (spv_inst, _const_inputs) = - &**spv_inst_and_const_inputs; - assert!(spv_inst.opcode == self.wk.OpConstant); - match spv_inst.imms[..] { - [spv::Imm::Short(_, x)] => x, - _ => unreachable!(), - } + let custom_op = CustomOp::decode(ext_inst); + match custom_op.with_operands(&data_inst_def.inputs) { + CustomInst::SetDebugSrcLoc { + file, + line_start: line, + line_end: _, + col_start: col, + col_end: _, + } => { + let const_kind = |v: Value| match v { + Value::Const(ct) => &self.cx[ct].kind, + _ => unreachable!(), + }; + let const_str = |v: Value| match const_kind(v) { + &ConstKind::SpvStringLiteralForExtInst(s) => s, + _ => unreachable!(), + }; + let const_u32 = |v: Value| match const_kind(v) { + ConstKind::SpvInst { + spv_inst_and_const_inputs, + } => { + let (spv_inst, _const_inputs) = &**spv_inst_and_const_inputs; + assert!(spv_inst.opcode == self.wk.OpConstant); + match spv_inst.imms[..] { + [spv::Imm::Short(_, x)] => x, + _ => unreachable!(), } - _ => unreachable!(), - }; - current_file_line_col = - Some((const_str(file), const_u32(line), const_u32(col))); - insts_to_remove.push(inst); - continue; - } - CustomInst::ClearDebugSrcLoc => { - current_file_line_col = None; - insts_to_remove.push(inst); - continue; - } - CustomInst::PushInlinedCallFrame { .. } - | CustomInst::PopInlinedCallFrame => { - insts_to_remove.push(inst); - continue; - } - CustomInst::Abort { .. } => { - assert!( - !custom_op.is_debuginfo(), - "`CustomOp::{custom_op:?}` debuginfo not lowered" - ); - } + } + _ => unreachable!(), + }; + current_file_line_col = + Some((const_str(file), const_u32(line), const_u32(col))); + insts_to_remove.push(inst); + continue; + } + CustomInst::ClearDebugSrcLoc => { + current_file_line_col = None; + insts_to_remove.push(inst); + continue; + } + CustomInst::PushInlinedCallFrame { .. } + | CustomInst::PopInlinedCallFrame => { + insts_to_remove.push(inst); + continue; + } + CustomInst::Abort { .. } => { + assert!( + !custom_op.is_debuginfo(), + "`CustomOp::{custom_op:?}` debuginfo not lowered" + ); } } } 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 29fefe430d..3951a7f8c0 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs @@ -404,28 +404,28 @@ impl DiagnosticReporter<'_> { }); let attrs_def = &self.cx[attrs]; - if !self.linker_options.early_report_zombies { - if let Some(zombie) = try_decode_custom_decoration::>(attrs_def) { - let ZombieDecoration { reason } = zombie.decode(); - let def_span = current_def - .and_then(|def| def.to_rustc_span(self.cx, &mut self.span_regen)) - .or_else(|| { - // If there's no clear source for the span, try to get - // it from the same attrs as the zombie, which could - // be missing from `use_stack` in some edge cases - // (such as zombied function parameters). - self.span_regen.spirt_attrs_to_rustc_span(self.cx, attrs) - }) - .unwrap_or(DUMMY_SP); - let mut err = self - .sess - .dcx() - .struct_span_err(def_span, reason.to_string()); - for use_origin in use_stack_for_def.iter().rev() { - use_origin.note(self.cx, &mut self.span_regen, &mut err); - } - self.overall_result = Err(err.emit()); + if !self.linker_options.early_report_zombies + && let Some(zombie) = try_decode_custom_decoration::>(attrs_def) + { + let ZombieDecoration { reason } = zombie.decode(); + let def_span = current_def + .and_then(|def| def.to_rustc_span(self.cx, &mut self.span_regen)) + .or_else(|| { + // If there's no clear source for the span, try to get + // it from the same attrs as the zombie, which could + // be missing from `use_stack` in some edge cases + // (such as zombied function parameters). + self.span_regen.spirt_attrs_to_rustc_span(self.cx, attrs) + }) + .unwrap_or(DUMMY_SP); + let mut err = self + .sess + .dcx() + .struct_span_err(def_span, reason.to_string()); + for use_origin in use_stack_for_def.iter().rev() { + use_origin.note(self.cx, &mut self.span_regen, &mut err); } + self.overall_result = Err(err.emit()); } let diags = attrs_def.attrs.iter().flat_map(|attr| match attr { @@ -623,69 +623,68 @@ impl<'a> Visitor<'a> for DiagnosticReporter<'a> { ext_set, inst: ext_inst, } = self.cx[data_inst_def.form].kind + && ext_set == self.custom_ext_inst_set { - if ext_set == self.custom_ext_inst_set { - match CustomOp::decode(ext_inst) { - CustomOp::SetDebugSrcLoc => { - *last_debug_src_loc_inst = Some(data_inst_def); + match CustomOp::decode(ext_inst) { + CustomOp::SetDebugSrcLoc => { + *last_debug_src_loc_inst = Some(data_inst_def); + } + CustomOp::ClearDebugSrcLoc => { + *last_debug_src_loc_inst = None; + } + op => match op.with_operands(&data_inst_def.inputs) { + CustomInst::SetDebugSrcLoc { .. } | CustomInst::ClearDebugSrcLoc => { + unreachable!() } - CustomOp::ClearDebugSrcLoc => { - *last_debug_src_loc_inst = None; + CustomInst::PushInlinedCallFrame { callee_name } => { + // Treat this like a call, in the caller. + replace_origin(self, IntraFuncUseOrigin::CallCallee); + + let const_kind = |v: Value| match v { + Value::Const(ct) => &self.cx[ct].kind, + _ => unreachable!(), + }; + let const_str = |v: Value| match const_kind(v) { + &ConstKind::SpvStringLiteralForExtInst(s) => s, + _ => unreachable!(), + }; + self.use_stack.push(UseOrigin::IntraFunc { + func_attrs: AttrSet::default(), + special_func: Some(SpecialFunc::Inlined { + callee_name: const_str(callee_name), + }), + last_debug_src_loc_inst: None, + inst_attrs: AttrSet::default(), + origin: IntraFuncUseOrigin::Other, + }); } - op => match op.with_operands(&data_inst_def.inputs) { - CustomInst::SetDebugSrcLoc { .. } - | CustomInst::ClearDebugSrcLoc => unreachable!(), - CustomInst::PushInlinedCallFrame { callee_name } => { - // Treat this like a call, in the caller. - replace_origin(self, IntraFuncUseOrigin::CallCallee); - - let const_kind = |v: Value| match v { - Value::Const(ct) => &self.cx[ct].kind, - _ => unreachable!(), - }; - let const_str = |v: Value| match const_kind(v) { - &ConstKind::SpvStringLiteralForExtInst(s) => s, - _ => unreachable!(), - }; - self.use_stack.push(UseOrigin::IntraFunc { - func_attrs: AttrSet::default(), - special_func: Some(SpecialFunc::Inlined { - callee_name: const_str(callee_name), - }), - last_debug_src_loc_inst: None, - inst_attrs: AttrSet::default(), - origin: IntraFuncUseOrigin::Other, - }); - } - CustomInst::PopInlinedCallFrame => { - match self.use_stack.last() { - Some(UseOrigin::IntraFunc { special_func, .. }) => { - if let Some(SpecialFunc::Inlined { .. }) = special_func - { - self.use_stack.pop().unwrap(); - // Undo what `PushInlinedCallFrame` did to the - // original `UseOrigin::IntraFunc`. - replace_origin(self, IntraFuncUseOrigin::Other); - } else { - // HACK(eddyb) synthesize a diagnostic to report right away. - self.report_from_attrs( - AttrSet::default().append_diag( - self.cx, - Diag::bug([ - "`PopInlinedCallFrame` without an \ + CustomInst::PopInlinedCallFrame => { + match self.use_stack.last() { + Some(UseOrigin::IntraFunc { special_func, .. }) => { + if let Some(SpecialFunc::Inlined { .. }) = special_func { + self.use_stack.pop().unwrap(); + // Undo what `PushInlinedCallFrame` did to the + // original `UseOrigin::IntraFunc`. + replace_origin(self, IntraFuncUseOrigin::Other); + } else { + // HACK(eddyb) synthesize a diagnostic to report right away. + self.report_from_attrs( + AttrSet::default().append_diag( + self.cx, + Diag::bug([ + "`PopInlinedCallFrame` without an \ inlined call frame in `use_stack`" - .into(), - ]), - ), - ); - } + .into(), + ]), + ), + ); } - _ => unreachable!(), } + _ => unreachable!(), } - CustomInst::Abort { .. } => {} - }, - } + } + CustomInst::Abort { .. } => {} + }, } } } diff --git a/crates/rustc_codegen_spirv/src/linker/spirt_passes/mod.rs b/crates/rustc_codegen_spirv/src/linker/spirt_passes/mod.rs index a8962db011..96f878518b 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/mod.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/mod.rs @@ -313,10 +313,9 @@ fn remove_unused_values_in_func(cx: &Context, func_def_body: &mut FuncDefBody) { region, input_idx: _, } = v + && region == self.func_body_region { - if region == self.func_body_region { - return; - } + return; } if self.used.insert(v) { self.queue.push_back(v); @@ -461,10 +460,9 @@ fn remove_unused_values_in_func(cx: &Context, func_def_body: &mut FuncDefBody) { while let Some(mut func_at_inst) = func_at_inst_iter.next() { if let DataInstKind::SpvInst(spv_inst) = &cx[func_at_inst.reborrow().def().form].kind + && spv_inst.opcode == wk.OpNop { - if spv_inst.opcode == wk.OpNop { - continue; - } + continue; } if !used_values.contains(&Value::DataInstOutput(func_at_inst.position)) { // Replace the removed `DataInstDef` itself with `OpNop`, diff --git a/crates/rustc_codegen_spirv/src/linker/spirt_passes/reduce.rs b/crates/rustc_codegen_spirv/src/linker/spirt_passes/reduce.rs index fa0728afa3..5954109de6 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/reduce.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/reduce.rs @@ -110,37 +110,38 @@ pub(crate) fn reduce_in_func(cx: &Context, func_def_body: &mut FuncDefBody) { // allowing us to bypass SPIR-T current (and temporary) lossiness // wrt `default: OpUnreachable` (i.e. we prove the `default:` can't // be entered based on `x` not having values other than `0` or `1`) - if let SelectionKind::SpvInst(spv_inst) = kind { - if spv_inst.opcode == wk.OpSwitch && cases.len() == 3 { - // FIXME(eddyb) this kind of `OpSwitch` decoding logic should - // be done by SPIR-T ahead of time, not here. - let num_logical_imms = cases.len() - 1; - assert_eq!(spv_inst.imms.len() % num_logical_imms, 0); - let logical_imm_size = spv_inst.imms.len() / num_logical_imms; - // FIXME(eddyb) collect to array instead. - let logical_imms_as_u32s: SmallVec<[_; 2]> = spv_inst - .imms - .chunks(logical_imm_size) - .map(spv_imm_checked_trunc32) - .collect(); - - // FIMXE(eddyb) support more values than just `0..=1`. - if logical_imms_as_u32s[..] == [Some(0), Some(1)] { - let redu = Reducible { - op: PureOp::IntToBool, - output_type: cx.intern(TypeDef { - attrs: Default::default(), - kind: TypeKind::SpvInst { - spv_inst: wk.OpTypeBool.into(), - type_and_const_inputs: iter::empty().collect(), - }, - }), - input: *scrutinee, - }; - let redu_target = - ReductionTarget::SwitchToIfElse(func_at_control_node.position); - reduction_queue.push((redu_target, redu)); - } + if let SelectionKind::SpvInst(spv_inst) = kind + && spv_inst.opcode == wk.OpSwitch + && cases.len() == 3 + { + // FIXME(eddyb) this kind of `OpSwitch` decoding logic should + // be done by SPIR-T ahead of time, not here. + let num_logical_imms = cases.len() - 1; + assert_eq!(spv_inst.imms.len() % num_logical_imms, 0); + let logical_imm_size = spv_inst.imms.len() / num_logical_imms; + // FIXME(eddyb) collect to array instead. + let logical_imms_as_u32s: SmallVec<[_; 2]> = spv_inst + .imms + .chunks(logical_imm_size) + .map(spv_imm_checked_trunc32) + .collect(); + + // FIMXE(eddyb) support more values than just `0..=1`. + if logical_imms_as_u32s[..] == [Some(0), Some(1)] { + let redu = Reducible { + op: PureOp::IntToBool, + output_type: cx.intern(TypeDef { + attrs: Default::default(), + kind: TypeKind::SpvInst { + spv_inst: wk.OpTypeBool.into(), + type_and_const_inputs: iter::empty().collect(), + }, + }), + input: *scrutinee, + }; + let redu_target = + ReductionTarget::SwitchToIfElse(func_at_control_node.position); + reduction_queue.push((redu_target, redu)); } } } diff --git a/crates/spirv-std/macros/src/image.rs b/crates/spirv-std/macros/src/image.rs index 0af4a7c67c..536ef3ae7b 100644 --- a/crates/spirv-std/macros/src/image.rs +++ b/crates/spirv-std/macros/src/image.rs @@ -238,7 +238,9 @@ impl Parse for ImageType { ) })?; - if format.is_some() && format != Some(ImageFormat::Unknown) { + if let Some(format) = &format + && *format != ImageFormat::Unknown + { if sampled_type.is_some() { return Err(syn::Error::new( starting_span, @@ -254,7 +256,6 @@ impl Parse for ImageType { )); } - let format = format.as_ref().unwrap(); sampled_type = Some(match format { ImageFormat::Rgba32f | ImageFormat::Rgba16f diff --git a/crates/spirv-std/macros/src/lib.rs b/crates/spirv-std/macros/src/lib.rs index 940604bc16..c1f0d57ab9 100644 --- a/crates/spirv-std/macros/src/lib.rs +++ b/crates/spirv-std/macros/src/lib.rs @@ -529,14 +529,12 @@ impl SampleImplRewriter { // use the type to insert it into the generic argument of the trait we're implementing // e.g., `ImageWithMethods` becomes `ImageWithMethods, NoneTy, NoneTy>>` - if let Some(t) = &mut new_impl.trait_ { - if let syn::PathArguments::AngleBracketed(a) = + if let Some(t) = &mut new_impl.trait_ + && let syn::PathArguments::AngleBracketed(a) = &mut t.1.segments.last_mut().unwrap().arguments - { - if let Some(syn::GenericArgument::Type(t)) = a.args.last_mut() { - *t = ty.clone(); - } - } + && let Some(syn::GenericArgument::Type(t)) = a.args.last_mut() + { + *t = ty.clone(); } // rewrite the implemented functions diff --git a/examples/runners/wgpu/src/compute.rs b/examples/runners/wgpu/src/compute.rs index 6d97aaf7d0..3bf624865c 100644 --- a/examples/runners/wgpu/src/compute.rs +++ b/examples/runners/wgpu/src/compute.rs @@ -177,16 +177,12 @@ async fn start_internal(options: &Options, compiled_shader_modules: CompiledShad let mut cpass = encoder.begin_compute_pass(&Default::default()); cpass.set_bind_group(0, &bind_group, &[]); cpass.set_pipeline(&compute_pipeline); - if timestamping { - if let Some(queries) = queries.as_ref() { - cpass.write_timestamp(queries, 0); - } + if timestamping && let Some(queries) = queries.as_ref() { + cpass.write_timestamp(queries, 0); } cpass.dispatch_workgroups(src_range.len() as u32 / 64, 1, 1); - if timestamping { - if let Some(queries) = queries.as_ref() { - cpass.write_timestamp(queries, 1); - } + if timestamping && let Some(queries) = queries.as_ref() { + cpass.write_timestamp(queries, 1); } } @@ -198,56 +194,53 @@ async fn start_internal(options: &Options, compiled_shader_modules: CompiledShad src.len() as wgpu::BufferAddress, ); - if timestamping { - if let (Some(queries), Some(timestamp_buffer), Some(timestamp_readback_buffer)) = ( + if timestamping + && let (Some(queries), Some(timestamp_buffer), Some(timestamp_readback_buffer)) = ( queries.as_ref(), timestamp_buffer.as_ref(), timestamp_readback_buffer.as_ref(), - ) { - encoder.resolve_query_set(queries, 0..2, timestamp_buffer, 0); - encoder.copy_buffer_to_buffer( - timestamp_buffer, - 0, - timestamp_readback_buffer, - 0, - timestamp_buffer.size(), - ); - } + ) + { + encoder.resolve_query_set(queries, 0..2, timestamp_buffer, 0); + encoder.copy_buffer_to_buffer( + timestamp_buffer, + 0, + timestamp_readback_buffer, + 0, + timestamp_buffer.size(), + ); } queue.submit(Some(encoder.finish())); let buffer_slice = readback_buffer.slice(..); - if timestamping { - if let Some(timestamp_readback_buffer) = timestamp_readback_buffer.as_ref() { - let timestamp_slice = timestamp_readback_buffer.slice(..); - timestamp_slice.map_async(wgpu::MapMode::Read, |r| r.unwrap()); - } + if timestamping && let Some(timestamp_readback_buffer) = timestamp_readback_buffer.as_ref() { + let timestamp_slice = timestamp_readback_buffer.slice(..); + timestamp_slice.map_async(wgpu::MapMode::Read, |r| r.unwrap()); } buffer_slice.map_async(wgpu::MapMode::Read, |r| r.unwrap()); // NOTE(eddyb) `poll` should return only after the above callbacks fire // (see also https://github.com/gfx-rs/wgpu/pull/2698 for more details). device.poll(wgpu::PollType::Wait).unwrap(); - if timestamping { - if let (Some(timestamp_readback_buffer), Some(timestamp_period)) = + if timestamping + && let (Some(timestamp_readback_buffer), Some(timestamp_period)) = (timestamp_readback_buffer.as_ref(), timestamp_period) + { { - { - let timing_data = timestamp_readback_buffer.slice(..).get_mapped_range(); - let timings = timing_data - .chunks_exact(8) - .map(|b| u64::from_ne_bytes(b.try_into().unwrap())) - .collect::>(); + let timing_data = timestamp_readback_buffer.slice(..).get_mapped_range(); + let timings = timing_data + .chunks_exact(8) + .map(|b| u64::from_ne_bytes(b.try_into().unwrap())) + .collect::>(); - println!( - "Took: {:?}", - Duration::from_nanos( - ((timings[1] - timings[0]) as f64 * f64::from(timestamp_period)) as u64 - ) - ); - drop(timing_data); - timestamp_readback_buffer.unmap(); - } + println!( + "Took: {:?}", + Duration::from_nanos( + ((timings[1] - timings[0]) as f64 * f64::from(timestamp_period)) as u64 + ) + ); + drop(timing_data); + timestamp_readback_buffer.unmap(); } } From 183e828531d780e852bc5ff50028ddb09d9a5e17 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 9 Jul 2025 19:56:08 +0300 Subject: [PATCH 4/4] Fix new `clippy::doc_markdown` warnings. --- .../arch/demote_to_helper_invocation_ext.rs | 2 +- crates/spirv-std/src/arch/mesh_shading.rs | 22 ++++++------ crates/spirv-std/src/arch/ray_tracing.rs | 2 +- crates/spirv-std/src/arch/subgroup.rs | 36 +++++++++---------- crates/spirv-std/src/image.rs | 2 +- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/crates/spirv-std/src/arch/demote_to_helper_invocation_ext.rs b/crates/spirv-std/src/arch/demote_to_helper_invocation_ext.rs index 2388fbcee9..8be3d572a1 100644 --- a/crates/spirv-std/src/arch/demote_to_helper_invocation_ext.rs +++ b/crates/spirv-std/src/arch/demote_to_helper_invocation_ext.rs @@ -5,7 +5,7 @@ use core::arch::asm; /// `discard()` in HLSL. Any stores to memory after this instruction are /// suppressed and the fragment does not write outputs to the framebuffer. /// -/// Unlike [super::kill], this does not necessarily terminate the invocation. It +/// Unlike [`super::kill`], this does not necessarily terminate the invocation. It /// is not considered a flow control instruction (flow control does not become /// non-uniform) and does not terminate the block. /// diff --git a/crates/spirv-std/src/arch/mesh_shading.rs b/crates/spirv-std/src/arch/mesh_shading.rs index cc906a17cf..5a06197f07 100644 --- a/crates/spirv-std/src/arch/mesh_shading.rs +++ b/crates/spirv-std/src/arch/mesh_shading.rs @@ -16,7 +16,7 @@ use core::arch::asm; /// There must not be any control flow path to an output write that is not preceded /// by this instruction. /// -/// This instruction is only valid in the *MeshEXT* Execution Model. +/// This instruction is only valid in the *`MeshEXT`* Execution Model. #[spirv_std_macros::gpu_only] #[doc(alias = "OpSetMeshOutputsEXT")] #[inline] @@ -38,7 +38,7 @@ pub unsafe fn set_mesh_outputs_ext(vertex_count: u32, primitive_count: u32) { /// for the launch of child mesh tasks. See Vulkan API specification for more detail. /// /// 'Payload' is an optional pointer to the payload structure to pass to the generated mesh shader invocations. -/// 'Payload' must be the result of an *OpVariable* with a storage class of *TaskPayloadWorkgroupEXT*. +/// 'Payload' must be the result of an *`OpVariable`* with a storage class of *`TaskPayloadWorkgroupEXT`*. /// /// The arguments are taken from the first invocation in each workgroup. /// Any invocation must execute this instruction exactly once and under uniform @@ -46,14 +46,14 @@ pub unsafe fn set_mesh_outputs_ext(vertex_count: u32, primitive_count: u32) { /// This instruction also serves as an *OpControlBarrier* instruction, and also /// performs and adheres to the description and semantics of an *OpControlBarrier* /// instruction with the 'Execution' and 'Memory' operands set to *Workgroup* and -/// the 'Semantics' operand set to a combination of *WorkgroupMemory* and -/// *AcquireRelease*. +/// the 'Semantics' operand set to a combination of *`WorkgroupMemory`* and +/// *`AcquireRelease`*. /// Ceases all further processing: Only instructions executed before -/// *OpEmitMeshTasksEXT* have observable side effects. +/// *`OpEmitMeshTasksEXT`* have observable side effects. /// /// This instruction must be the last instruction in a block. /// -/// This instruction is only valid in the *TaskEXT* Execution Model. +/// This instruction is only valid in the *`TaskEXT`* Execution Model. #[spirv_std_macros::gpu_only] #[doc(alias = "OpEmitMeshTasksEXT")] #[inline] @@ -77,7 +77,7 @@ pub unsafe fn emit_mesh_tasks_ext(group_count_x: u32, group_count_y: u32, group_ /// for the launch of child mesh tasks. See Vulkan API specification for more detail. /// /// 'Payload' is an optional pointer to the payload structure to pass to the generated mesh shader invocations. -/// 'Payload' must be the result of an *OpVariable* with a storage class of *TaskPayloadWorkgroupEXT*. +/// 'Payload' must be the result of an *`OpVariable`* with a storage class of *`TaskPayloadWorkgroupEXT`*. /// /// The arguments are taken from the first invocation in each workgroup. /// Any invocation must execute this instruction exactly once and under uniform @@ -85,14 +85,14 @@ pub unsafe fn emit_mesh_tasks_ext(group_count_x: u32, group_count_y: u32, group_ /// This instruction also serves as an *OpControlBarrier* instruction, and also /// performs and adheres to the description and semantics of an *OpControlBarrier* /// instruction with the 'Execution' and 'Memory' operands set to *Workgroup* and -/// the 'Semantics' operand set to a combination of *WorkgroupMemory* and -/// *AcquireRelease*. +/// the 'Semantics' operand set to a combination of *`WorkgroupMemory`* and +/// *`AcquireRelease`*. /// Ceases all further processing: Only instructions executed before -/// *OpEmitMeshTasksEXT* have observable side effects. +/// *`OpEmitMeshTasksEXT`* have observable side effects. /// /// This instruction must be the last instruction in a block. /// -/// This instruction is only valid in the *TaskEXT* Execution Model. +/// This instruction is only valid in the *`TaskEXT`* Execution Model. #[spirv_std_macros::gpu_only] #[doc(alias = "OpEmitMeshTasksEXT")] #[inline] diff --git a/crates/spirv-std/src/arch/ray_tracing.rs b/crates/spirv-std/src/arch/ray_tracing.rs index 7612ffb3d3..ccfd540222 100644 --- a/crates/spirv-std/src/arch/ray_tracing.rs +++ b/crates/spirv-std/src/arch/ray_tracing.rs @@ -14,7 +14,7 @@ use core::arch::asm; /// - `hit_kind` is the integer hit kind reported back to other shaders and /// accessible by the `hit kind` builtin. /// -/// This instruction is allowed only in IntersectionKHR execution model. +/// This instruction is allowed only in `IntersectionKHR` execution model. /// /// This instruction is a shader call instruction which may invoke shaders with /// the `any_hit` execution model. diff --git a/crates/spirv-std/src/arch/subgroup.rs b/crates/spirv-std/src/arch/subgroup.rs index 660c9ee5f3..f6acf93765 100644 --- a/crates/spirv-std/src/arch/subgroup.rs +++ b/crates/spirv-std/src/arch/subgroup.rs @@ -844,7 +844,7 @@ Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 0. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is 0. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. @@ -875,7 +875,7 @@ Result Type must be a scalar or vector of floating-point type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 0. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is 0. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. The method used to perform the group operation on the contributed Value(s) from active invocations is implementation defined. @@ -908,7 +908,7 @@ Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 1. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is 1. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. @@ -939,7 +939,7 @@ Result Type must be a scalar or vector of floating-point type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 1. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is 1. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. The method used to perform the group operation on the contributed Value(s) from active invocations is implementation defined. @@ -959,7 +959,7 @@ Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is INT_MAX. +The identity I for Operation is `INT_MAX`. The type of `value` must be the same as Result Type. @@ -972,7 +972,7 @@ Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is INT_MAX. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is `INT_MAX`. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. @@ -990,7 +990,7 @@ Result Type must be a scalar or vector of integer type, whose Signedness operand Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is UINT_MAX. +The identity I for Operation is `UINT_MAX`. The type of `value` must be the same as Result Type. @@ -1003,7 +1003,7 @@ Result Type must be a scalar or vector of integer type, whose Signedness operand Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is UINT_MAX. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is `UINT_MAX`. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. @@ -1034,7 +1034,7 @@ Result Type must be a scalar or vector of floating-point type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is +INF. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is +INF. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. The method used to perform the group operation on the contributed Value(s) from active invocations is implementation defined. From the set of Value(s) provided by active invocations within a subgroup, if for any two Values one of them is a NaN, the other is chosen. If all Value(s) that are used by the current invocation are NaN, then the result is an undefined value. @@ -1054,7 +1054,7 @@ Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is INT_MIN. +The identity I for Operation is `INT_MIN`. The type of `value` must be the same as Result Type. @@ -1067,7 +1067,7 @@ Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is INT_MIN. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is `INT_MIN`. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. @@ -1098,7 +1098,7 @@ Result Type must be a scalar or vector of integer type, whose Signedness operand Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 0. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is 0. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. @@ -1160,7 +1160,7 @@ Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is ~0. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is ~0. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. @@ -1193,7 +1193,7 @@ Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 0. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is 0. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. @@ -1226,7 +1226,7 @@ Result Type must be a scalar or vector of integer type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 0. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is 0. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. @@ -1259,7 +1259,7 @@ Result Type must be a scalar or vector of Boolean type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is ~0. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is ~0. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. @@ -1292,7 +1292,7 @@ Result Type must be a scalar or vector of Boolean type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 0. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is 0. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. @@ -1325,7 +1325,7 @@ Result Type must be a scalar or vector of Boolean type. Execution is a Scope that identifies the group of invocations affected by this command. It must be Subgroup. -The identity I for Operation is 0. If Operation is ClusteredReduce, `ClusterSize` must be present. +The identity I for Operation is 0. If Operation is `ClusteredReduce`, `ClusterSize` must be present. The type of `value` must be the same as Result Type. diff --git a/crates/spirv-std/src/image.rs b/crates/spirv-std/src/image.rs index 77af83b5c6..361cd1cf29 100644 --- a/crates/spirv-std/src/image.rs +++ b/crates/spirv-std/src/image.rs @@ -95,7 +95,7 @@ pub type Cubemap = crate::Image!(cube, type=f32, sampled, __crate_root=crate); /// You likely want to write this type using the [`crate::Image!`] macro helper, as the generic /// arguments here can get extremely verbose. /// -/// See SPIR-V OpTypeImage specification for the meaning of integer parameters. +/// See SPIR-V `OpTypeImage` specification for the meaning of integer parameters. #[spirv(generic_image_type)] #[derive(Copy, Clone)] // HACK(eddyb) avoids "transparent newtype of `_anti_zst_padding`" misinterpretation.