diff --git a/.cargo/config.toml b/.cargo/config.toml index 9c99fc9e3b..9596b2ef05 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -44,7 +44,6 @@ rustflags = [ "-Wclippy::map_err_ignore", "-Wclippy::map_flatten", "-Wclippy::map_unwrap_or", - "-Wclippy::match_on_vec_items", "-Wclippy::match_same_arms", "-Wclippy::match_wild_err_arm", "-Wclippy::match_wildcard_for_single_variants", diff --git a/Cargo.toml b/Cargo.toml index 13b1c0337f..2c32344e8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ members = [ [workspace.package] version = "0.9.0" authors = ["rust-gpu developers", "Embark "] -edition = "2021" +edition = "2024" license = "MIT OR Apache-2.0" repository = "https://github.com/rust-gpu/rust-gpu" diff --git a/crates/rustc_codegen_spirv/build.rs b/crates/rustc_codegen_spirv/build.rs index c7cafd699f..7bb8ca3eed 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-2024-11-22" +channel = "nightly-2025-05-09" components = ["rust-src", "rustc-dev", "llvm-tools"] -# commit_hash = b19329a37cedf2027517ae22c87cf201f93d776e"#; +# commit_hash = 50aa04180709189a03dde5fd1c05751b2625ed37"#; fn rustc_output(arg: &str) -> Result> { let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".into()); @@ -159,9 +159,9 @@ fn generate_pqp_cg_ssa() -> Result<(), Box> { } } - // HACK(eddyb) remove `windows` dependency (from MSVC linker output - // parsing, which `rustc_codegen_spirv` will never invoke anyway). if relative_path == Path::new("src/back/link.rs") { + // HACK(eddyb) remove `windows` dependency (from MSVC linker output + // parsing, which `rustc_codegen_spirv` will never invoke anyway). src = src.replace( "#[cfg(not(windows))] fn escape_linker_output(", @@ -179,6 +179,36 @@ mod win {", "#[cfg(any())] mod win {", ); + // HACK(eddyb) remove `object` dependency (for Windows `raw_dylib` + // handling, which `rustc_codegen_spirv` will never invoke anyway). + src = src.replace("mod raw_dylib;", "// mod raw_dylib;"); + src = src.replace( + " + for output_path in raw_dylib::", + " + #[cfg(any())] + for output_path in raw_dylib::", + ); + src = src.replace( + " + for link_path in raw_dylib::", + " + #[cfg(any())] + for link_path in raw_dylib::", + ); + } + if relative_path == Path::new("src/back/metadata.rs") { + // HACK(eddyb) remove `object` dependency. + src = src.replace( + " +pub(crate) fn create_object_file(sess: &Session) -> Option> {", + " +pub(crate) fn create_object_file(_: &Session) -> Option> { + None +} +#[cfg(any())] +pub(crate) fn create_object_file(sess: &Session) -> Option> {", + ); } // HACK(eddyb) "typed alloca" patches. @@ -198,8 +228,16 @@ mod win {", } else if relative_path == Path::new("src/mir/operand.rs") { src = src.replace("alloca(field.size,", "typed_alloca(llfield_ty,"); - // HACK(eddyb) non-array `#[repr(simd)]` workaround (see `src/abi.rs`). + // HACK(eddyb) non-array `#[repr(simd)]` workarounds (see `src/abi.rs`). src = src.replace("if constant_ty.is_simd() {", "if false {"); + src = src.replace( + "match (self.val, self.layout.backend_repr) {", + "match (self.val, self.layout.backend_repr) { + // `#[repr(simd)]` types are also immediate. + (OperandValue::Immediate(llval), BackendRepr::SimdVector { element, .. }) => { + (Some(element), bx.extract_element(llval, bx.cx().const_usize(i as u64))) + }", + ); } fs::write(out_path, src)?; @@ -259,6 +297,9 @@ mod win {", println!("cargo::warning={line}"); } println!("cargo::warning="); + + // HACK(eddyb) allow the warning to be cleared after `lib.rs` is fixed. + println!("cargo:rerun-if-changed=src/lib.rs"); } // HACK(eddyb) write a file that can be `include!`d from `lib.rs`. @@ -276,6 +317,12 @@ mod maybe_pqp_cg_ssa; println!("cargo::rustc-check-cfg=cfg(rustc_codegen_spirv_disable_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 04d1bf9860..294771714a 100644 --- a/crates/rustc_codegen_spirv/src/abi.rs +++ b/crates/rustc_codegen_spirv/src/abi.rs @@ -6,8 +6,14 @@ use crate::codegen_cx::CodegenCx; use crate::spirv_type::SpirvType; use itertools::Itertools; use rspirv::spirv::{Dim, ImageFormat, StorageClass, Word}; +use rustc_abi::ExternAbi as Abi; +use rustc_abi::{ + Align, BackendRepr, FieldIdx, FieldsShape, HasDataLayout as _, LayoutData, Primitive, + ReprFlags, ReprOptions, Scalar, Size, TagEncoding, VariantIdx, Variants, +}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorGuaranteed; +use rustc_hashes::Hash64; use rustc_index::Idx; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; @@ -20,12 +26,7 @@ use rustc_middle::{bug, span_bug}; use rustc_span::DUMMY_SP; use rustc_span::def_id::DefId; use rustc_span::{Span, Symbol}; -use rustc_target::abi::call::{ArgAbi, ArgAttributes, FnAbi, PassMode}; -use rustc_target::abi::{ - Align, BackendRepr, FieldsShape, LayoutData, Primitive, ReprFlags, ReprOptions, Scalar, Size, - TagEncoding, VariantIdx, Variants, -}; -use rustc_target::spec::abi::Abi; +use rustc_target::callconv::{ArgAbi, ArgAttributes, FnAbi, PassMode}; use std::cell::RefCell; use std::collections::hash_map::Entry; use std::fmt; @@ -106,10 +107,12 @@ pub(crate) fn provide(providers: &mut Providers) { ref variants, backend_repr, largest_niche, + uninhabited, align, size, max_repr_align, unadjusted_abi_align, + randomization_seed, } = *layout; LayoutData { fields: match *fields { @@ -125,6 +128,7 @@ pub(crate) fn provide(providers: &mut Providers) { }, }, variants: match *variants { + Variants::Empty => Variants::Empty, Variants::Single { index } => Variants::Single { index }, Variants::Multiple { tag, @@ -151,20 +155,108 @@ pub(crate) fn provide(providers: &mut Providers) { }, backend_repr, largest_niche, + uninhabited, align, size, max_repr_align, unadjusted_abi_align, + randomization_seed, } } providers.layout_of = |tcx, key| { + // HACK(eddyb) to special-case any types at all, they must be normalized, + // but when normalization would be needed, `layout_of`'s default provider + // recurses (supposedly for caching reasons), i.e. its calls `layout_of` + // w/ the normalized type in input, which once again reaches this hook, + // without ever needing any explicit normalization here. + let ty = key.value; + + // HACK(eddyb) bypassing upstream `#[repr(simd)]` changes (see also + // the later comment above `check_well_formed`, for more details). + let reimplement_old_style_repr_simd = match ty.kind() { + ty::Adt(def, args) if def.repr().simd() && !def.repr().packed() && def.is_struct() => { + Some(def.non_enum_variant()).and_then(|v| { + let (count, e_ty) = v + .fields + .iter() + .map(|f| f.ty(tcx, args)) + .dedup_with_count() + .exactly_one() + .ok()?; + let e_len = u64::try_from(count).ok().filter(|&e_len| e_len > 1)?; + Some((def, e_ty, e_len)) + }) + } + _ => None, + }; + + // HACK(eddyb) tweaked copy of the old upstream logic for `#[repr(simd)]`: + // https://github.com/rust-lang/rust/blob/1.86.0/compiler/rustc_ty_utils/src/layout.rs#L464-L590 + if let Some((adt_def, e_ty, e_len)) = reimplement_old_style_repr_simd { + let cx = rustc_middle::ty::layout::LayoutCx::new( + tcx, + key.typing_env.with_post_analysis_normalized(tcx), + ); + let dl = cx.data_layout(); + + // Compute the ABI of the element type: + let e_ly = cx.layout_of(e_ty)?; + let BackendRepr::Scalar(e_repr) = e_ly.backend_repr else { + // This error isn't caught in typeck, e.g., if + // the element type of the vector is generic. + tcx.dcx().span_fatal( + tcx.def_span(adt_def.did()), + format!( + "SIMD type `{ty}` with a non-primitive-scalar \ + (integer/float/pointer) element type `{}`", + e_ly.ty + ), + ); + }; + + // Compute the size and alignment of the vector: + let size = e_ly.size.checked_mul(e_len, dl).unwrap(); + let align = dl.llvmlike_vector_align(size); + let size = size.align_to(align.abi); + + let layout = tcx.mk_layout(LayoutData { + variants: Variants::Single { + index: rustc_abi::FIRST_VARIANT, + }, + fields: FieldsShape::Array { + stride: e_ly.size, + count: e_len, + }, + backend_repr: BackendRepr::SimdVector { + element: e_repr, + count: e_len, + }, + largest_niche: e_ly.largest_niche, + uninhabited: false, + size, + align, + max_repr_align: None, + unadjusted_abi_align: align.abi, + randomization_seed: e_ly.randomization_seed.wrapping_add(Hash64::new(e_len)), + }); + + return Ok(TyAndLayout { ty, layout }); + } + let TyAndLayout { ty, mut layout } = (rustc_interface::DEFAULT_QUERY_PROVIDERS.layout_of)(tcx, key)?; #[allow(clippy::match_like_matches_macro)] let hide_niche = match ty.kind() { - ty::Bool => true, + ty::Bool => { + // HACK(eddyb) we can't bypass e.g. `Option` being a byte, + // due to `core` PR https://github.com/rust-lang/rust/pull/138881 + // (which adds a new `transmute`, from `ControlFlow` to `u8`). + let libcore_needs_bool_niche = true; + + !libcore_needs_bool_niche + } _ => false, }; @@ -198,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: &[] @@ -462,7 +554,7 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { // `ScalarPair`. // There's a few layers that we go through here. First we inspect layout.backend_repr, then if relevant, layout.fields, etc. match self.backend_repr { - BackendRepr::Uninhabited => SpirvType::Adt { + _ if self.uninhabited => SpirvType::Adt { def_id: def_id_for_spirv_type_adt(*self), size: Some(Size::ZERO), align: Align::from_bytes(0).unwrap(), @@ -523,7 +615,7 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { 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[i.into()]; + let field = &adt.variants()[index].fields[FieldIdx::new(i)]; field_names.push(field.name); } } @@ -542,7 +634,7 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { } .def_with_name(cx, span, TyLayoutNameKey::from(*self)) } - BackendRepr::Vector { element, count } => { + BackendRepr::SimdVector { element, count } => { let elem_spirv = trans_scalar(cx, span, *self, element, Size::ZERO); SpirvType::Vector { element: elem_spirv, @@ -652,6 +744,7 @@ fn dig_scalar_pointee<'tcx>( } let all_fields = (match &layout.variants { + Variants::Empty => 0..0, Variants::Multiple { variants, .. } => 0..variants.len(), Variants::Single { index } => { let i = index.as_usize(); @@ -811,7 +904,7 @@ fn trans_struct<'tcx>(cx: &CodegenCx<'tcx>, span: Span, ty: TyAndLayout<'tcx>) - field_offsets.push(offset); if let Variants::Single { index } = ty.variants { if let TyKind::Adt(adt, _) = ty.ty.kind() { - let field = &adt.variants()[index].fields[i.into()]; + let field = &adt.variants()[index].fields[FieldIdx::new(i)]; field_names.push(field.name); } else { // FIXME(eddyb) this looks like something that should exist in rustc. @@ -867,7 +960,7 @@ impl<'tcx> From> for TyLayoutNameKey<'tcx> { ty: layout.ty, variant: match layout.variants { Variants::Single { index } => Some(index), - Variants::Multiple { .. } => None, + _ => None, }, } } @@ -984,9 +1077,10 @@ fn trans_intrinsic_type<'tcx>( cx: &CodegenCx<'tcx>, const_: Const<'tcx>, ) -> Result { - let (const_val, const_ty) = const_ - .try_to_valtree() - .expect("expected monomorphic const in codegen"); + let ty::Value { + ty: const_ty, + valtree: const_val, + } = const_.to_value(); assert!(const_ty.is_integral()); const_val .try_to_scalar_int() diff --git a/crates/rustc_codegen_spirv/src/attr.rs b/crates/rustc_codegen_spirv/src/attr.rs index a47b1ba1ad..b35dbb6c3c 100644 --- a/crates/rustc_codegen_spirv/src/attr.rs +++ b/crates/rustc_codegen_spirv/src/attr.rs @@ -5,11 +5,10 @@ use crate::codegen_cx::CodegenCx; use crate::symbols::Symbols; use rspirv::spirv::{BuiltIn, ExecutionMode, ExecutionModel, StorageClass}; -use rustc_ast::Attribute; use rustc_hir as hir; use rustc_hir::def_id::LocalModDefId; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{CRATE_HIR_ID, HirId, MethodKind, Target}; +use rustc_hir::{Attribute, CRATE_HIR_ID, HirId, MethodKind, Target}; use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; @@ -254,8 +253,8 @@ fn target_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) -> Targ match impl_item.kind { hir::ImplItemKind::Const(..) => Target::AssocConst, hir::ImplItemKind::Fn(..) => { - let parent_owner_id = tcx.hir().get_parent_item(impl_item.hir_id()); - let containing_item = tcx.hir().expect_item(parent_owner_id.def_id); + let parent_owner_id = tcx.hir_get_parent_item(impl_item.hir_id()); + let containing_item = tcx.hir_expect_item(parent_owner_id.def_id); let containing_impl_is_for_trait = match &containing_item.kind { hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => of_trait.is_some(), _ => unreachable!("parent of an ImplItem must be an Impl"), @@ -281,7 +280,7 @@ impl CheckSpirvAttrVisitor<'_> { let parse_attrs = |attrs| crate::symbols::parse_attrs_for_checking(&self.sym, attrs); - let attrs = self.tcx.hir().attrs(hir_id); + let attrs = self.tcx.hir_attrs(hir_id); for parse_attr_result in parse_attrs(attrs) { let (span, parsed_attr) = match parse_attr_result { Ok(span_and_parsed_attr) => span_and_parsed_attr, @@ -327,10 +326,9 @@ impl CheckSpirvAttrVisitor<'_> { | SpirvAttribute::SpecConstant(_) => match target { Target::Param => { let parent_hir_id = self.tcx.parent_hir_id(hir_id); - let parent_is_entry_point = - parse_attrs(self.tcx.hir().attrs(parent_hir_id)) - .filter_map(|r| r.ok()) - .any(|(_, attr)| matches!(attr, SpirvAttribute::Entry(_))); + let parent_is_entry_point = parse_attrs(self.tcx.hir_attrs(parent_hir_id)) + .filter_map(|r| r.ok()) + .any(|(_, attr)| matches!(attr, SpirvAttribute::Entry(_))); if !parent_is_entry_point { self.tcx.dcx().span_err( span, @@ -418,8 +416,8 @@ impl CheckSpirvAttrVisitor<'_> { impl<'tcx> Visitor<'tcx> for CheckSpirvAttrVisitor<'tcx> { type NestedFilter = nested_filter::OnlyBodies; - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.tcx } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { @@ -498,8 +496,7 @@ fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { tcx, sym: Symbols::get(), }; - tcx.hir() - .visit_item_likes_in_module(module_def_id, check_spirv_attr_visitor); + tcx.hir_visit_item_likes_in_module(module_def_id, check_spirv_attr_visitor); if module_def_id.is_top_level_module() { check_spirv_attr_visitor.check_spirv_attributes(CRATE_HIR_ID, Target::Mod); } diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index 3a8b4c1801..febd102d8a 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -10,6 +10,7 @@ use crate::spirv_type::SpirvType; use itertools::Itertools; use rspirv::dr::{InsertPoint, Instruction, Operand}; use rspirv::spirv::{Capability, MemoryModel, MemorySemantics, Op, Scope, StorageClass, Word}; +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::{ @@ -27,8 +28,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; -use rustc_target::abi::call::FnAbi; -use rustc_target::abi::{Align, BackendRepr, Scalar, Size, WrappingRange}; +use rustc_target::callconv::FnAbi; use smallvec::SmallVec; use std::borrow::Cow; use std::cell::Cell; @@ -139,11 +139,7 @@ fn memset_dynamic_scalar( .def(builder.span(), builder); let composite = builder .emit() - .composite_construct( - composite_type, - None, - iter::repeat(fill_var).take(byte_width), - ) + .composite_construct(composite_type, None, iter::repeat_n(fill_var, byte_width)) .unwrap(); let result_type = if is_float { SpirvType::Float(byte_width as u32 * 8) @@ -214,25 +210,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { )), }, SpirvType::Integer(width, true) => match width { - 8 => self - .constant_i8(self.span(), unsafe { - std::mem::transmute::(fill_byte) - }) - .def(self), + 8 => self.constant_i8(self.span(), fill_byte as i8).def(self), 16 => self - .constant_i16(self.span(), unsafe { - std::mem::transmute::(memset_fill_u16(fill_byte)) - }) + .constant_i16(self.span(), memset_fill_u16(fill_byte) as i16) .def(self), 32 => self - .constant_i32(self.span(), unsafe { - std::mem::transmute::(memset_fill_u32(fill_byte)) - }) + .constant_i32(self.span(), memset_fill_u32(fill_byte) as i32) .def(self), 64 => self - .constant_i64(self.span(), unsafe { - std::mem::transmute::(memset_fill_u64(fill_byte)) - }) + .constant_i64(self.span(), memset_fill_u64(fill_byte) as i64) .def(self), _ => self.fatal(format!( "memset on integer width {width} not implemented yet" @@ -252,18 +238,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let elem_pat = self.memset_const_pattern(&self.lookup_type(element), fill_byte); self.constant_composite( ty.def(self.span(), self), - iter::repeat(elem_pat).take(count as usize), + iter::repeat_n(elem_pat, count as usize), ) .def(self) } SpirvType::Array { element, count } => { let elem_pat = self.memset_const_pattern(&self.lookup_type(element), fill_byte); let count = self.builder.lookup_const_scalar(count).unwrap() as usize; - self.constant_composite( - ty.def(self.span(), self), - iter::repeat(elem_pat).take(count), - ) - .def(self) + self.constant_composite(ty.def(self.span(), self), iter::repeat_n(elem_pat, count)) + .def(self) } SpirvType::RuntimeArray { .. } => { self.fatal("memset on runtime arrays not implemented yet") @@ -308,7 +291,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .composite_construct( ty.def(self.span(), self), None, - iter::repeat(elem_pat).take(count), + iter::repeat_n(elem_pat, count), ) .unwrap() } @@ -318,7 +301,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .composite_construct( ty.def(self.span(), self), None, - iter::repeat(elem_pat).take(count as usize), + iter::repeat_n(elem_pat, count as usize), ) .unwrap() } @@ -618,7 +601,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if offset == Size::ZERO && leaf_size_range.contains(&ty_size) - && leaf_ty.map_or(true, |leaf_ty| leaf_ty == ty) + && leaf_ty.is_none_or(|leaf_ty| leaf_ty == ty) { trace!("returning type: {:?}", self.debug_type(ty)); trace!("returning indices with len: {:?}", indices.len()); @@ -854,46 +837,65 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // --- End Recovery Path --- + // FIXME(eddyb) the comments below might not make much sense, because this + // used to be in the "fallback path" before being moved to before merging. + // + // Before emitting the AccessChain, explicitly cast the base pointer `ptr` to + // ensure its pointee type matches the input `ty`. This is required because the + // SPIR-V `AccessChain` instruction implicitly uses the size of the base + // pointer's pointee type when applying the *first* index operand (our + // `ptr_base_index`). If `ty` and `original_pointee_ty` mismatched and we + // reached this fallback, this cast ensures SPIR-V validity. + trace!("maybe_inbounds_gep fallback path calling pointercast"); + // Cast ptr to point to `ty`. + // HACK(eddyb) temporary workaround for untyped pointers upstream. + // FIXME(eddyb) replace with untyped memory SPIR-V + `qptr` or similar. + let ptr = self.pointercast(ptr, self.type_ptr_to(ty)); + // Get the ID of the (potentially newly casted) pointer. + let ptr_id = ptr.def(self); + // HACK(eddyb) updated pointee type of `ptr` post-`pointercast`. + let original_pointee_ty = ty; + // --- Attempt GEP Merging Path --- // Check if the base pointer `ptr` itself was the result of a previous // AccessChain instruction. Merging is only attempted if the input type `ty` // matches the pointer's actual underlying pointee type `original_pointee_ty`. // If they differ, merging could be invalid. + // HACK(eddyb) always attempted now, because we `pointercast` first, which: + // - is noop when `ty == original_pointee_ty` pre-`pointercast` (old condition) + // - may generate (potentially mergeable) new `AccessChain`s in other cases let maybe_original_access_chain = if ty == original_pointee_ty { // Search the current function's instructions... // FIXME(eddyb) this could get ridiculously expensive, at the very least // it could use `.rev()`, hoping the base pointer was recently defined? - let search_result = { - let emit = self.emit(); - let module = emit.module_ref(); - emit.selected_function().and_then(|func_idx| { - module.functions.get(func_idx).and_then(|func| { - // Find the instruction that defined our base pointer `ptr_id`. - func.all_inst_iter() - .find(|inst| inst.result_id == Some(ptr_id)) - .and_then(|ptr_def_inst| { - // Check if that instruction was an `AccessChain` or `InBoundsAccessChain`. - if matches!( - ptr_def_inst.class.opcode, - Op::AccessChain | Op::InBoundsAccessChain - ) { - // If yes, extract its base pointer and its indices. - let base_ptr = ptr_def_inst.operands[0].unwrap_id_ref(); - let indices = ptr_def_inst.operands[1..] - .iter() - .map(|op| op.unwrap_id_ref()) - .collect::>(); - Some((base_ptr, indices)) - } else { - // The instruction defining ptr was not an `AccessChain`. - None - } - }) - }) + let emit = self.emit(); + let module = emit.module_ref(); + emit.selected_function().and_then(|func_idx| { + module.functions.get(func_idx).and_then(|func| { + // Find the instruction that defined our base pointer `ptr_id`. + func.all_inst_iter() + .find(|inst| inst.result_id == Some(ptr_id)) + .and_then(|ptr_def_inst| { + // Check if that instruction was an `AccessChain` or `InBoundsAccessChain`. + if matches!( + ptr_def_inst.class.opcode, + Op::AccessChain | Op::InBoundsAccessChain + ) { + // If yes, extract its base pointer and its indices. + let base_ptr = ptr_def_inst.operands[0].unwrap_id_ref(); + let indices = ptr_def_inst.operands[1..] + .iter() + .map(|op| op.unwrap_id_ref()) + .collect::>(); + Some((base_ptr, indices)) + } else { + // The instruction defining ptr was not an `AccessChain`. + None + } + }) }) - }; - search_result + }) } else { // Input type `ty` doesn't match the pointer's actual type, cannot safely merge. None @@ -908,12 +910,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // 2. The *last* index of the original AccessChain is a constant. // 3. The *first* index (`ptr_base_index`) of the *current* GEP is a constant. // Merging usually involves adding these two constant indices. + // + // FIXME(eddyb) the above comment seems inaccurate, there is no reason + // why runtime indices couldn't be added together just like constants + // (and in fact this is needed nowadays for all array indexing). let can_merge = if let Some(&last_original_idx_id) = original_indices.last() { - // Check if both the last original index and the current base index are constant scalars. - self.builder - .lookup_const_scalar(last_original_idx_id.with_type(ptr_base_index.ty)) - .is_some() - && self.builder.lookup_const_scalar(ptr_base_index).is_some() + // HACK(eddyb) see the above comment, this bypasses the const + // check below, without tripping a clippy warning etc. + let always_merge = true; + always_merge || { + // Check if both the last original index and the current base index are constant scalars. + self.builder + .lookup_const_scalar(last_original_idx_id.with_type(ptr_base_index.ty)) + .is_some() + && self.builder.lookup_const_scalar(ptr_base_index).is_some() + } } else { // Original access chain had no indices to merge with. false @@ -966,21 +977,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // This path is taken if neither the Recovery nor the Merging path succeeded or applied. // It performs a more direct translation of the GEP request. - // HACK(eddyb): Workaround for potential upstream issues where pointers might lack precise type info. - // FIXME(eddyb): Ideally, this should use untyped memory features if available/necessary. - - // Before emitting the AccessChain, explicitly cast the base pointer `ptr` to - // ensure its pointee type matches the input `ty`. This is required because the - // SPIR-V `AccessChain` instruction implicitly uses the size of the base - // pointer's pointee type when applying the *first* index operand (our - // `ptr_base_index`). If `ty` and `original_pointee_ty` mismatched and we - // reached this fallback, this cast ensures SPIR-V validity. - trace!("maybe_inbounds_gep fallback path calling pointercast"); - // Cast ptr to point to `ty`. - let ptr = self.pointercast(ptr, self.type_ptr_to(ty)); - // Get the ID of the (potentially newly casted) pointer. - let ptr_id = ptr.def(self); - trace!( "emitting access chain via fallback path with pointer type: {}", self.debug_type(final_spirv_ptr_type) @@ -1259,9 +1255,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }; // TODO: rspirv doesn't have insert_variable function let result_id = builder.id(); - let inst = Instruction::new(Op::Variable, Some(ptr_ty), Some(result_id), vec![ - Operand::StorageClass(StorageClass::Function), - ]); + let inst = Instruction::new( + Op::Variable, + Some(ptr_ty), + Some(result_id), + vec![Operand::StorageClass(StorageClass::Function)], + ); builder.insert_into_block(index, inst).unwrap(); result_id.with_type(ptr_ty) } @@ -1334,13 +1333,16 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { let ((line_start, col_start), (line_end, col_end)) = (line_col_range.start, line_col_range.end); - self.custom_inst(void_ty, CustomInst::SetDebugSrcLoc { - file: Operand::IdRef(file.file_name_op_string_id), - line_start: Operand::IdRef(self.const_u32(line_start).def(self)), - line_end: Operand::IdRef(self.const_u32(line_end).def(self)), - col_start: Operand::IdRef(self.const_u32(col_start).def(self)), - col_end: Operand::IdRef(self.const_u32(col_end).def(self)), - }); + self.custom_inst( + void_ty, + CustomInst::SetDebugSrcLoc { + file: Operand::IdRef(file.file_name_op_string_id), + line_start: Operand::IdRef(self.const_u32(line_start).def(self)), + line_end: Operand::IdRef(self.const_u32(line_end).def(self)), + col_start: Operand::IdRef(self.const_u32(col_start).def(self)), + col_end: Operand::IdRef(self.const_u32(col_end).def(self)), + }, + ); } // HACK(eddyb) remove the previous instruction if made irrelevant. @@ -1689,11 +1691,14 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { let signed = match ty.kind() { ty::Int(_) => true, ty::Uint(_) => false, - other => self.fatal(format!("Unexpected {} type: {other:#?}", match oop { - OverflowOp::Add => "checked add", - OverflowOp::Sub => "checked sub", - OverflowOp::Mul => "checked mul", - })), + other => self.fatal(format!( + "Unexpected {} type: {other:#?}", + match oop { + OverflowOp::Add => "checked add", + OverflowOp::Sub => "checked sub", + OverflowOp::Mul => "checked mul", + } + )), }; let result = if is_add { @@ -1833,7 +1838,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { place.val.llval, place.val.align, ); - OperandValue::Immediate(self.to_immediate(llval, place.layout)) + OperandValue::Immediate(llval) } else if let BackendRepr::ScalarPair(a, b) = place.layout.backend_repr { let b_offset = a .primitive() @@ -2330,9 +2335,19 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { } } - fn icmp(&mut self, op: IntPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + fn icmp(&mut self, op: IntPredicate, lhs: Self::Value, mut rhs: Self::Value) -> Self::Value { // Note: the signedness of the opcode doesn't have to match the signedness of the operands. use IntPredicate::*; + + if lhs.ty != rhs.ty + && [lhs, rhs].map(|v| matches!(self.lookup_type(v.ty), SpirvType::Pointer { .. })) + == [true, true] + { + // HACK(eddyb) temporary workaround for untyped pointers upstream. + // FIXME(eddyb) replace with untyped memory SPIR-V + `qptr` or similar. + rhs = self.pointercast(rhs, lhs.ty); + } + assert_ty_eq!(self, lhs.ty, rhs.ty); let b = SpirvType::Bool.def(self.span(), self); match self.lookup_type(lhs.ty) { @@ -2771,14 +2786,10 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { } .def(self.span(), self); if self.builder.lookup_const(elt).is_some() { - self.constant_composite(result_type, iter::repeat(elt.def(self)).take(num_elts)) + self.constant_composite(result_type, iter::repeat_n(elt.def(self), num_elts)) } else { self.emit() - .composite_construct( - result_type, - None, - iter::repeat(elt.def(self)).take(num_elts), - ) + .composite_construct(result_type, None, iter::repeat_n(elt.def(self), num_elts)) .unwrap() .with_type(result_type) } @@ -3541,9 +3552,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { .map(|s| Cow::Owned(s.replace('%', "%%"))) .interleave(ref_arg_ids_with_ty_and_spec.iter().map( |&(ref_id, ty, spec)| { - use rustc_target::abi::{ - Float::*, Integer::*, Primitive::*, - }; + use rustc_abi::{Float::*, Integer::*, Primitive::*}; let layout = self.layout_of(ty); diff --git a/crates/rustc_codegen_spirv/src/builder/byte_addressable_buffer.rs b/crates/rustc_codegen_spirv/src/builder/byte_addressable_buffer.rs index 76260a7765..41f42a3eff 100644 --- a/crates/rustc_codegen_spirv/src/builder/byte_addressable_buffer.rs +++ b/crates/rustc_codegen_spirv/src/builder/byte_addressable_buffer.rs @@ -5,11 +5,11 @@ use super::Builder; use crate::builder_spirv::{SpirvValue, SpirvValueExt, SpirvValueKind}; use crate::spirv_type::SpirvType; use rspirv::spirv::Word; +use rustc_abi::{Align, Size}; use rustc_codegen_ssa::traits::BuilderMethods; use rustc_errors::ErrorGuaranteed; use rustc_span::DUMMY_SP; -use rustc_target::abi::call::PassMode; -use rustc_target::abi::{Align, Size}; +use rustc_target::callconv::PassMode; impl<'a, 'tcx> Builder<'a, 'tcx> { fn load_err(&mut self, original_type: Word, invalid_type: Word) -> SpirvValue { diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index ef5857de52..241d4b0129 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -17,7 +17,7 @@ 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::abi::call::{FnAbi, PassMode}; +use rustc_target::callconv::{FnAbi, PassMode}; use std::assert_matches::assert_matches; fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_>) -> Option<(u64, bool)> { @@ -46,16 +46,10 @@ impl Builder<'_, '_> { ), }; let int_ty = SpirvType::Integer(width, false).def(self.span(), self); - let (mask_sign, mask_value) = match width { - 32 => ( - self.constant_u32(self.span(), 1 << 31), - self.constant_u32(self.span(), u32::MAX >> 1), - ), - 64 => ( - self.constant_u64(self.span(), 1 << 63), - self.constant_u64(self.span(), u64::MAX >> 1), - ), - _ => bug!("copysign must have width 32 or 64, not {}", width), + let [mask_sign, mask_value] = { + let sign_bit = 1u128.checked_shl(width - 1).unwrap(); + let value_mask = sign_bit - 1; + [sign_bit, value_mask].map(|v| self.constant_int(int_ty, v)) }; let val_bits = self.bitcast(val, int_ty); let sign_bits = self.bitcast(sign, int_ty); @@ -154,53 +148,83 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { result } - sym::sqrtf32 | sym::sqrtf64 => self.gl_op(GLOp::Sqrt, ret_ty, [args[0].immediate()]), - sym::powif32 | sym::powif64 => { + sym::sqrtf32 | sym::sqrtf64 | sym::sqrtf128 => { + self.gl_op(GLOp::Sqrt, ret_ty, [args[0].immediate()]) + } + sym::powif32 | sym::powif64 | sym::powif128 => { let float = self.sitofp(args[1].immediate(), args[0].immediate().ty); self.gl_op(GLOp::Pow, ret_ty, [args[0].immediate(), float]) } - sym::sinf32 | sym::sinf64 => self.gl_op(GLOp::Sin, ret_ty, [args[0].immediate()]), - sym::cosf32 | sym::cosf64 => self.gl_op(GLOp::Cos, ret_ty, [args[0].immediate()]), - sym::powf32 | sym::powf64 => self.gl_op(GLOp::Pow, ret_ty, [ - args[0].immediate(), - args[1].immediate(), - ]), - sym::expf32 | sym::expf64 => self.gl_op(GLOp::Exp, ret_ty, [args[0].immediate()]), - sym::exp2f32 | sym::exp2f64 => self.gl_op(GLOp::Exp2, ret_ty, [args[0].immediate()]), - sym::logf32 | sym::logf64 => self.gl_op(GLOp::Log, ret_ty, [args[0].immediate()]), - sym::log2f32 | sym::log2f64 => self.gl_op(GLOp::Log2, ret_ty, [args[0].immediate()]), - sym::log10f32 | sym::log10f64 => { + sym::sinf32 | sym::sinf64 | sym::sinf128 => { + self.gl_op(GLOp::Sin, ret_ty, [args[0].immediate()]) + } + sym::cosf32 | sym::cosf64 | sym::cosf128 => { + self.gl_op(GLOp::Cos, ret_ty, [args[0].immediate()]) + } + sym::powf32 | sym::powf64 | sym::powf128 => self.gl_op( + GLOp::Pow, + ret_ty, + [args[0].immediate(), args[1].immediate()], + ), + sym::expf32 | sym::expf64 | sym::expf128 => { + self.gl_op(GLOp::Exp, ret_ty, [args[0].immediate()]) + } + sym::exp2f32 | sym::exp2f64 | sym::exp2f128 => { + self.gl_op(GLOp::Exp2, ret_ty, [args[0].immediate()]) + } + sym::logf32 | sym::logf64 | sym::logf128 => { + self.gl_op(GLOp::Log, ret_ty, [args[0].immediate()]) + } + sym::log2f32 | sym::log2f64 | sym::log2f128 => { + self.gl_op(GLOp::Log2, ret_ty, [args[0].immediate()]) + } + sym::log10f32 | sym::log10f64 | sym::log10f128 => { // spir-v glsl doesn't have log10, so, // log10(x) == (1 / ln(10)) * ln(x) let mul = self.constant_float(args[0].immediate().ty, 1.0 / 10.0f64.ln()); let ln = self.gl_op(GLOp::Log, ret_ty, [args[0].immediate()]); self.fmul(mul, ln) } - sym::fmaf32 | sym::fmaf64 => self.gl_op(GLOp::Fma, ret_ty, [ - args[0].immediate(), - args[1].immediate(), - args[2].immediate(), - ]), - sym::fabsf32 | sym::fabsf64 => self.gl_op(GLOp::FAbs, ret_ty, [args[0].immediate()]), - sym::minnumf32 | sym::minnumf64 => self.gl_op(GLOp::FMin, ret_ty, [ - args[0].immediate(), - args[1].immediate(), - ]), - sym::maxnumf32 | sym::maxnumf64 => self.gl_op(GLOp::FMax, ret_ty, [ - args[0].immediate(), - args[1].immediate(), - ]), - sym::copysignf32 | sym::copysignf64 => { + sym::fmaf32 | sym::fmaf64 | sym::fmaf128 => self.gl_op( + GLOp::Fma, + ret_ty, + [ + args[0].immediate(), + args[1].immediate(), + args[2].immediate(), + ], + ), + sym::fabsf32 | sym::fabsf64 | sym::fabsf128 => { + self.gl_op(GLOp::FAbs, ret_ty, [args[0].immediate()]) + } + sym::minnumf32 | sym::minnumf64 | sym::minnumf128 => self.gl_op( + GLOp::FMin, + ret_ty, + [args[0].immediate(), args[1].immediate()], + ), + sym::maxnumf32 | sym::maxnumf64 | sym::maxnumf128 => self.gl_op( + GLOp::FMax, + ret_ty, + [args[0].immediate(), args[1].immediate()], + ), + sym::copysignf32 | sym::copysignf64 | sym::copysignf128 => { let val = args[0].immediate(); let sign = args[1].immediate(); self.copysign(val, sign) } - sym::floorf32 | sym::floorf64 => self.gl_op(GLOp::Floor, ret_ty, [args[0].immediate()]), - sym::ceilf32 | sym::ceilf64 => self.gl_op(GLOp::Ceil, ret_ty, [args[0].immediate()]), - sym::truncf32 | sym::truncf64 => self.gl_op(GLOp::Trunc, ret_ty, [args[0].immediate()]), - // TODO: Correctness of all these rounds - sym::rintf32 | sym::rintf64 => self.gl_op(GLOp::Round, ret_ty, [args[0].immediate()]), - sym::nearbyintf32 | sym::nearbyintf64 | sym::roundf32 | sym::roundf64 => { + sym::floorf32 | sym::floorf64 | sym::floorf128 => { + self.gl_op(GLOp::Floor, ret_ty, [args[0].immediate()]) + } + sym::ceilf32 | sym::ceilf64 | sym::ceilf128 => { + self.gl_op(GLOp::Ceil, ret_ty, [args[0].immediate()]) + } + sym::truncf32 | sym::truncf64 | sym::truncf128 => { + self.gl_op(GLOp::Trunc, ret_ty, [args[0].immediate()]) + } + sym::round_ties_even_f32 | sym::round_ties_even_f64 | sym::round_ties_even_f128 => { + self.gl_op(GLOp::RoundEven, ret_ty, [args[0].immediate()]) + } + sym::roundf32 | sym::roundf64 | sym::roundf128 => { self.gl_op(GLOp::Round, ret_ty, [args[0].immediate()]) } @@ -310,7 +334,7 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { _ => { // Call the fallback body instead of generating the intrinsic code - return Err(ty::Instance::new(instance.def_id(), instance.args)); + return Err(ty::Instance::new_raw(instance.def_id(), instance.args)); } }; @@ -483,9 +507,13 @@ impl Builder<'_, '_> { if trailing { let lsb = self .emit() - .ext_inst(u32, None, glsl, GLOp::FindILsb as u32, [Operand::IdRef( - arg, - )]) + .ext_inst( + u32, + None, + glsl, + GLOp::FindILsb as u32, + [Operand::IdRef(arg)], + ) .unwrap(); if offset == 0 { lsb @@ -497,9 +525,13 @@ impl Builder<'_, '_> { // rust is always unsigned, so FindUMsb let msb_bit = self .emit() - .ext_inst(u32, None, glsl, GLOp::FindUMsb as u32, [Operand::IdRef( - arg, - )]) + .ext_inst( + u32, + None, + glsl, + GLOp::FindUMsb as u32, + [Operand::IdRef(arg)], + ) .unwrap(); // the glsl op returns the Msb bit, not the amount of leading zeros of this u32 // leading zeros = 31 - Msb bit @@ -604,18 +636,21 @@ impl Builder<'_, '_> { // so the best thing we can do is use our own custom instruction. let kind_id = self.emit().string(kind); let message_debug_printf_fmt_str_id = self.emit().string(message_debug_printf_fmt_str); - self.custom_inst(void_ty, CustomInst::Abort { - kind: Operand::IdRef(kind_id), - message_debug_printf: [message_debug_printf_fmt_str_id] - .into_iter() - .chain( - message_debug_printf_args - .into_iter() - .map(|arg| arg.def(self)), - ) - .map(Operand::IdRef) - .collect(), - }); + self.custom_inst( + void_ty, + CustomInst::Abort { + kind: Operand::IdRef(kind_id), + message_debug_printf: [message_debug_printf_fmt_str_id] + .into_iter() + .chain( + message_debug_printf_args + .into_iter() + .map(|arg| arg.def(self)), + ) + .map(Operand::IdRef) + .collect(), + }, + ); self.unreachable(); // HACK(eddyb) we still need an active block in case the user of this diff --git a/crates/rustc_codegen_spirv/src/builder/libm_intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/libm_intrinsics.rs index 9ac081d161..4b57dc17c6 100644 --- a/crates/rustc_codegen_spirv/src/builder/libm_intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/libm_intrinsics.rs @@ -230,10 +230,11 @@ impl Builder<'_, '_> { } LibmIntrinsic::Custom(LibmCustomIntrinsic::Cbrt) => { assert_eq!(args.len(), 1); - self.gl_op(GLOp::Pow, result_type, [ - args[0], - self.constant_float(args[0].ty, 1.0 / 3.0), - ]) + self.gl_op( + GLOp::Pow, + result_type, + [args[0], self.constant_float(args[0].ty, 1.0 / 3.0)], + ) } LibmIntrinsic::Custom(LibmCustomIntrinsic::Log10) => { assert_eq!(args.len(), 1); diff --git a/crates/rustc_codegen_spirv/src/builder/mod.rs b/crates/rustc_codegen_spirv/src/builder/mod.rs index 044a9a13e6..37d7d53fe3 100644 --- a/crates/rustc_codegen_spirv/src/builder/mod.rs +++ b/crates/rustc_codegen_spirv/src/builder/mod.rs @@ -17,6 +17,7 @@ use crate::builder_spirv::{BuilderCursor, SpirvValue, SpirvValueExt}; use crate::codegen_cx::CodegenCx; use crate::spirv_type::SpirvType; use rspirv::spirv::Word; +use rustc_abi::{HasDataLayout, Size, TargetDataLayout}; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{ @@ -34,8 +35,7 @@ use rustc_middle::ty::layout::{ use rustc_middle::ty::{Instance, Ty, TyCtxt, TypingEnv}; use rustc_span::Span; use rustc_span::def_id::DefId; -use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; -use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout}; +use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; use rustc_target::spec::{HasTargetSpec, Target}; use std::ops::{Deref, Range}; @@ -260,7 +260,7 @@ impl<'a, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'a, 'tcx> { } } -impl<'a, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'tcx> { +impl AbiBuilderMethods for Builder<'_, '_> { fn get_param(&mut self, index: usize) -> Self::Value { self.function_parameter_values.borrow()[&self.current_fn.def(self)][index] } diff --git a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs index 91da22473d..02a3dbc9a9 100644 --- a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs +++ b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs @@ -211,7 +211,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { let start = line.as_str(); match line.next()? { // skip over leading whitespace - ch if ch.is_whitespace() => continue, + ch if ch.is_whitespace() => {} // lex a string '"' => { let mut cooked = String::new(); @@ -254,7 +254,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { let end = loop { let end = line.as_str(); match line.next() { - Some(ch) if !ch.is_whitespace() => continue, + Some(ch) if !ch.is_whitespace() => {} _ => break end, } }; @@ -788,6 +788,8 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { _ => return None, } + // HACK(eddyb) clippy false positive, `.ok()` loses information. + #[allow(clippy::manual_ok_err)] match subst_ty_pat( self, sig.output_type.unwrap(), diff --git a/crates/rustc_codegen_spirv/src/builder_spirv.rs b/crates/rustc_codegen_spirv/src/builder_spirv.rs index 4c87f0584d..936edf883a 100644 --- a/crates/rustc_codegen_spirv/src/builder_spirv.rs +++ b/crates/rustc_codegen_spirv/src/builder_spirv.rs @@ -12,23 +12,23 @@ use rspirv::spirv::{ AddressingModel, Capability, MemoryModel, Op, SourceLanguage, StorageClass, Word, }; use rspirv::{binary::Assemble, binary::Disassemble}; +use rustc_abi::Size; use rustc_arena::DroplessArena; use rustc_codegen_ssa::traits::ConstCodegenMethods as _; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::sync::Lrc; use rustc_middle::bug; use rustc_middle::mir::interpret::ConstAllocation; use rustc_middle::ty::TyCtxt; use rustc_span::source_map::SourceMap; use rustc_span::symbol::Symbol; use rustc_span::{DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Span}; -use rustc_target::abi::Size; use std::assert_matches::assert_matches; use std::cell::{RefCell, RefMut}; use std::hash::{Hash, Hasher}; use std::iter; use std::ops::Range; use std::str; +use std::sync::Arc; use std::{fs::File, io::Write, path::Path}; #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] @@ -346,16 +346,16 @@ struct WithConstLegality { /// equivalent to a whole `rustc` `SourceFile`, but has O(1) `Eq` and `Hash` /// implementations (i.e. not involving the path or the contents of the file). /// -/// This is possible because we can compare `Lrc`s by equality, as +/// This is possible because we can compare `Arc`s by equality, as /// `rustc`'s `SourceMap` already ensures that only one `SourceFile` will be /// allocated for some given file. For hashing, we could hash the address, or /// -struct DebugFileKey(Lrc); +struct DebugFileKey(Arc); impl PartialEq for DebugFileKey { fn eq(&self, other: &Self) -> bool { let (Self(self_sf), Self(other_sf)) = (self, other); - Lrc::ptr_eq(self_sf, other_sf) + Arc::ptr_eq(self_sf, other_sf) } } impl Eq for DebugFileKey {} @@ -829,7 +829,7 @@ impl<'tcx> BuilderSpirv<'tcx> { (self.def_debug_file(lo_loc.file), lo_line_col..hi_line_col) } - fn def_debug_file(&self, sf: Lrc) -> DebugFileSpirv<'tcx> { + fn def_debug_file(&self, sf: Arc) -> DebugFileSpirv<'tcx> { *self .debug_file_cache .borrow_mut() @@ -839,7 +839,7 @@ impl<'tcx> BuilderSpirv<'tcx> { // FIXME(eddyb) it would be nicer if we could just rely on // `RealFileName::to_string_lossy` returning `Cow<'_, str>`, - // but sadly that `'_` is the lifetime of the temporary `Lrc`, + // but sadly that `'_` is the lifetime of the temporary `Arc`, // not `'tcx`, so we have to arena-allocate to get `&'tcx str`. let file_name = match &sf.name { FileName::Real(name) => { diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs index 1461f23246..87e7338de5 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs @@ -6,12 +6,12 @@ use crate::abi::ConvSpirvType; use crate::builder_spirv::{SpirvConst, SpirvValue, SpirvValueExt, SpirvValueKind}; use crate::spirv_type::SpirvType; use rspirv::spirv::Word; +use rustc_abi::{self as abi, AddressSpace, Float, HasDataLayout, Integer, Primitive, Size}; use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods}; use rustc_middle::bug; use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar, alloc_range}; use rustc_middle::ty::layout::LayoutOf; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::{self, AddressSpace, Float, HasDataLayout, Integer, Primitive, Size}; impl<'tcx> CodegenCx<'tcx> { pub fn def_constant(&self, ty: Word, val: SpirvConst<'_, 'tcx>) -> SpirvValue { @@ -109,7 +109,7 @@ impl<'tcx> CodegenCx<'tcx> { } } -impl<'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'tcx> { +impl ConstCodegenMethods for CodegenCx<'_> { fn const_null(&self, t: Self::Type) -> Self::Value { self.constant_null(t) } @@ -169,11 +169,17 @@ impl<'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'tcx> { .layout_of(self.tcx.types.str_) .spirv_type(DUMMY_SP, self); ( - self.def_constant(self.type_ptr_to(str_ty), SpirvConst::PtrTo { - pointee: self - .constant_composite(str_ty, s.bytes().map(|b| self.const_u8(b).def_cx(self))) - .def_cx(self), - }), + self.def_constant( + self.type_ptr_to(str_ty), + SpirvConst::PtrTo { + pointee: self + .constant_composite( + str_ty, + s.bytes().map(|b| self.const_u8(b).def_cx(self)), + ) + .def_cx(self), + }, + ), self.const_usize(len as u64), ) } @@ -254,13 +260,18 @@ impl<'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'tcx> { (value, AddressSpace::DATA) } GlobalAlloc::Function { instance } => ( - self.get_fn_addr(instance.polymorphize(self.tcx)), + self.get_fn_addr(instance), self.data_layout().instruction_address_space, ), GlobalAlloc::VTable(vty, dyn_ty) => { let alloc = self .tcx - .global_alloc(self.tcx.vtable_allocation((vty, dyn_ty.principal()))) + .global_alloc(self.tcx.vtable_allocation(( + vty, + dyn_ty.principal().map(|principal| { + self.tcx.instantiate_bound_regions_with_erased(principal) + }), + ))) .unwrap_memory(); let pointee = match self.lookup_type(ty) { SpirvType::Pointer { pointee } => pointee, @@ -305,7 +316,12 @@ impl<'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'tcx> { // the actual value generation until after a pointer to this value is cast // to its final type (e.g. that will be loaded as). // FIXME(eddyb) replace this with `qptr` handling of constant data. - fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> Self::Value { + fn const_data_from_alloc(&self, alloc: ConstAllocation<'_>) -> Self::Value { + // HACK(eddyb) the `ConstCodegenMethods` trait no longer guarantees the + // lifetime that `alloc` is interned for, but since it *is* interned, + // we can cheaply recover it (see also the `ty::Lift` infrastructure). + let alloc = self.tcx.lift(alloc).unwrap(); + let void_type = SpirvType::Void.def(DUMMY_SP, self); self.def_constant(void_type, SpirvConst::ConstDataFromAlloc(alloc)) } diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs index eae83d8e93..12a888a6cb 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/declare.rs @@ -9,9 +9,9 @@ use crate::custom_decorations::{CustomDecoration, SrcLocDecoration}; use crate::spirv_type::SpirvType; use itertools::Itertools; use rspirv::spirv::{FunctionControl, LinkageType, StorageClass, Word}; -use rustc_attr::InlineAttr; +use rustc_abi::Align; +use rustc_attr_parsing::InlineAttr; use rustc_codegen_ssa::traits::{PreDefineCodegenMethods, StaticCodegenMethods}; -use rustc_hir::def::DefKind; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility}; @@ -19,13 +19,14 @@ use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt, TypingEnv}; use rustc_span::Span; use rustc_span::def_id::DefId; -use rustc_target::abi::Align; fn attrs_to_spirv(attrs: &CodegenFnAttrs) -> FunctionControl { let mut control = FunctionControl::NONE; match attrs.inline { InlineAttr::None => (), - InlineAttr::Hint | InlineAttr::Always => control.insert(FunctionControl::INLINE), + InlineAttr::Hint | InlineAttr::Always | InlineAttr::Force { .. } => { + control.insert(FunctionControl::INLINE); + } InlineAttr::Never => control.insert(FunctionControl::DONT_INLINE), } if attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) { @@ -131,13 +132,7 @@ impl<'tcx> CodegenCx<'tcx> { let declared = fn_id.with_type(function_type); - let attrs = AggregatedSpirvAttributes::parse(self, match self.tcx.def_kind(def_id) { - // This was made to ICE cross-crate at some point, but then got - // reverted in https://github.com/rust-lang/rust/pull/111381. - // FIXME(eddyb) remove this workaround once we rustup past that. - DefKind::Closure => &[], - _ => self.tcx.get_attrs_unchecked(def_id), - }); + let attrs = AggregatedSpirvAttributes::parse(self, self.tcx.get_attrs_unchecked(def_id)); if let Some(entry) = attrs.entry.map(|attr| attr.value) { let entry_name = entry .name @@ -339,9 +334,12 @@ impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'tcx> { impl<'tcx> StaticCodegenMethods for CodegenCx<'tcx> { fn static_addr_of(&self, cv: Self::Value, _align: Align, _kind: Option<&str>) -> Self::Value { - self.def_constant(self.type_ptr_to(cv.ty), SpirvConst::PtrTo { - pointee: cv.def_cx(self), - }) + self.def_constant( + self.type_ptr_to(cv.ty), + SpirvConst::PtrTo { + pointee: cv.def_cx(self), + }, + ) } fn codegen_static(&self, def_id: DefId) { diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs index a2ad70a010..7435781173 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs @@ -19,7 +19,7 @@ use rustc_middle::span_bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::Span; -use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode}; +use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; use std::assert_matches::assert_matches; /// Various information about an entry-point parameter, which can only be deduced @@ -82,7 +82,7 @@ impl<'tcx> CodegenCx<'tcx> { .span_err(span, format!("cannot declare {name} as an entry point")); return; }; - self.tcx.hir().body_owned_by(fn_local_def_id).params + self.tcx.hir_body_owned_by(fn_local_def_id).params }; for (arg_abi, hir_param) in fn_abi.args.iter().zip(hir_params) { match arg_abi.mode { @@ -354,10 +354,13 @@ impl<'tcx> CodegenCx<'tcx> { if !ref_is_read_only && storage_class_requires_read_only { let mut err = self.tcx.dcx().struct_span_err( hir_param.ty_span, - format!("entry-point requires {}...", match explicit_mutbl { - hir::Mutability::Not => "interior mutability", - hir::Mutability::Mut => "a mutable reference", - }), + format!( + "entry-point requires {}...", + match explicit_mutbl { + hir::Mutability::Not => "interior mutability", + hir::Mutability::Mut => "a mutable reference", + } + ), ); { let note_message = @@ -426,7 +429,7 @@ impl<'tcx> CodegenCx<'tcx> { call_args: &mut Vec, decoration_locations: &mut FxHashMap, ) { - let attrs = AggregatedSpirvAttributes::parse(self, self.tcx.hir().attrs(hir_param.hir_id)); + let attrs = AggregatedSpirvAttributes::parse(self, self.tcx.hir_attrs(hir_param.hir_id)); let EntryParamDeducedFromRustRefOrValue { value_layout, @@ -445,9 +448,11 @@ impl<'tcx> CodegenCx<'tcx> { let mut emit = self.emit_global(); let spec_const_id = emit.spec_constant_bit32(value_spirv_type, default.unwrap_or(0)); - emit.decorate(spec_const_id, Decoration::SpecId, [Operand::LiteralBit32( - id, - )]); + emit.decorate( + spec_const_id, + Decoration::SpecId, + [Operand::LiteralBit32(id)], + ); ( Err("`#[spirv(spec_constant)]` is not an entry-point interface variable"), Ok(spec_const_id), @@ -772,10 +777,13 @@ impl<'tcx> CodegenCx<'tcx> { } => true, SpirvType::RuntimeArray { element: elt, .. } | SpirvType::Array { element: elt, .. } => { - matches!(self.lookup_type(elt), SpirvType::Image { - dim: Dim::DimSubpassData, - .. - }) + matches!( + self.lookup_type(elt), + SpirvType::Image { + dim: Dim::DimSubpassData, + .. + } + ) } _ => false, }; diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs index f3a3828018..fb6b299132 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs @@ -16,6 +16,7 @@ use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; use itertools::Itertools as _; use rspirv::dr::{Module, Operand}; use rspirv::spirv::{Decoration, LinkageType, Op, Word}; +use rustc_abi::{AddressSpace, HasDataLayout, TargetDataLayout}; use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, VariableKind}; use rustc_codegen_ssa::traits::{ @@ -27,12 +28,11 @@ use rustc_hir::def_id::DefId; use rustc_middle::mir; use rustc_middle::mir::mono::CodegenUnit; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv}; -use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty, TyCtxt, TypingEnv}; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypingEnv}; use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_span::{DUMMY_SP, SourceFile, Span}; -use rustc_target::abi::call::{FnAbi, PassMode}; -use rustc_target::abi::{AddressSpace, HasDataLayout, TargetDataLayout}; +use rustc_target::callconv::{FnAbi, PassMode}; use rustc_target::spec::{HasTargetSpec, Target, TargetTuple}; use std::cell::RefCell; use std::collections::BTreeSet; @@ -52,7 +52,7 @@ pub struct CodegenCx<'tcx> { pub function_parameter_values: RefCell>>, pub type_cache: TypeCache<'tcx>, /// Cache generated vtables - pub vtables: RefCell, Option>), SpirvValue>>, + pub vtables: RefCell, Option>), SpirvValue>>, pub ext_inst: RefCell, /// Invalid SPIR-V IDs that should be stripped from the final binary, /// each with its own reason and span that should be used for reporting @@ -685,10 +685,10 @@ impl CodegenArgs { *current_id = *remap.entry(*current_id).or_insert_with(|| len as u32 + 1); }; module.all_inst_iter_mut().for_each(|inst| { - if let Some(ref mut result_id) = &mut inst.result_id { + if let Some(result_id) = &mut inst.result_id { insert(result_id); } - if let Some(ref mut result_type) = &mut inst.result_type { + if let Some(result_type) = &mut inst.result_type { insert(result_type); } inst.operands.iter_mut().for_each(|op| { @@ -849,7 +849,7 @@ impl<'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'tcx> { #[allow(clippy::type_complexity)] fn vtables( &self, - ) -> &RefCell, Option>), Self::Value>> { + ) -> &RefCell, Option>), Self::Value>> { &self.vtables } @@ -910,7 +910,7 @@ impl<'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'tcx> { fn create_vtable_debuginfo( &self, _ty: Ty<'tcx>, - _trait_ref: Option>, + _trait_ref: Option>, _vtable: Self::Value, ) { // Ignore. @@ -966,12 +966,24 @@ impl<'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'tcx> { impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'tcx> { fn codegen_global_asm( - &self, + &mut self, _template: &[InlineAsmTemplatePiece], _operands: &[GlobalAsmOperandRef<'tcx>], _options: InlineAsmOptions, - _line_spans: &[Span], + line_spans: &[Span], ) { - todo!() + self.tcx.dcx().span_fatal( + line_spans.first().copied().unwrap_or_default(), + "[Rust-GPU] `global_asm!` not yet supported", + ); + } + + // FIXME(eddyb) should this method be implemented as just symbol mangling, + // or renamed upstream into something much more specific? + fn mangled_name(&self, instance: Instance<'tcx>) -> String { + self.tcx.dcx().span_bug( + self.tcx.def_span(instance.def_id()), + "[Rust-GPU] `#[naked] fn` not yet supported", + ) } } diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs b/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs index f0005a9e42..6ed23ead89 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs @@ -5,6 +5,7 @@ use super::CodegenCx; use crate::abi::ConvSpirvType; use crate::spirv_type::SpirvType; use rspirv::spirv::Word; +use rustc_abi::{AddressSpace, BackendRepr, Reg}; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, LayoutTypeCodegenMethods}; use rustc_middle::ty::Ty; @@ -14,8 +15,7 @@ use rustc_middle::ty::layout::{ use rustc_middle::{bug, span_bug}; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Span}; -use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; -use rustc_target::abi::{AddressSpace, BackendRepr}; +use rustc_target::callconv::{CastTarget, FnAbi}; impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'tcx> { type LayoutOfResult = TyAndLayout<'tcx>; @@ -97,18 +97,17 @@ impl<'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'tcx> { fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool { match layout.backend_repr { - BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true, + BackendRepr::Scalar(_) | BackendRepr::SimdVector { .. } => true, BackendRepr::ScalarPair(..) => false, - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => layout.is_zst(), + BackendRepr::Memory { .. } => layout.is_zst(), } } fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool { match layout.backend_repr { BackendRepr::ScalarPair(..) => true, - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::Vector { .. } + BackendRepr::Scalar(_) + | BackendRepr::SimdVector { .. } | BackendRepr::Memory { .. } => false, } } @@ -130,7 +129,7 @@ impl<'tcx> CodegenCx<'tcx> { } } -impl<'tcx> BaseTypeCodegenMethods<'tcx> for CodegenCx<'tcx> { +impl BaseTypeCodegenMethods for CodegenCx<'_> { fn type_i8(&self) -> Self::Type { SpirvType::Integer(8, false).def(DUMMY_SP, self) } diff --git a/crates/rustc_codegen_spirv/src/custom_decorations.rs b/crates/rustc_codegen_spirv/src/custom_decorations.rs index e2cf68158c..1027df9aed 100644 --- a/crates/rustc_codegen_spirv/src/custom_decorations.rs +++ b/crates/rustc_codegen_spirv/src/custom_decorations.rs @@ -7,13 +7,13 @@ use either::Either; use rspirv::dr::{Instruction, Module, Operand}; use rspirv::spirv::{Decoration, Op, Word}; use rustc_data_structures::fx::FxIndexMap; -use rustc_data_structures::sync::Lrc; use rustc_span::{FileName, SourceFile}; use rustc_span::{Span, source_map::SourceMap}; use smallvec::SmallVec; use std::borrow::Cow; use std::marker::PhantomData; use std::path::PathBuf; +use std::sync::Arc; use std::{fmt, iter, slice, str}; /// Decorations not native to SPIR-V require some form of encoding into existing @@ -39,11 +39,16 @@ pub trait CustomDecoration<'a>: Sized { let mut encoded = Self::ENCODING_PREFIX.to_string(); self.encode(&mut encoded).unwrap(); - Instruction::new(Op::DecorateString, None, None, vec![ - Operand::IdRef(id), - Operand::Decoration(Decoration::UserTypeGOOGLE), - Operand::LiteralString(encoded), - ]) + Instruction::new( + Op::DecorateString, + None, + None, + vec![ + Operand::IdRef(id), + Operand::Decoration(Decoration::UserTypeGOOGLE), + Operand::LiteralString(encoded), + ], + ) } fn try_decode_from_inst(inst: &Instruction) -> Option<(Word, LazilyDecoded<'_, Self>)> { @@ -54,10 +59,13 @@ pub trait CustomDecoration<'a>: Sized { let prefixed_encoded = inst.operands[2].unwrap_literal_string(); let encoded = prefixed_encoded.strip_prefix(Self::ENCODING_PREFIX)?; - Some((id, LazilyDecoded { - encoded, - _marker: PhantomData, - })) + Some(( + id, + LazilyDecoded { + encoded, + _marker: PhantomData, + }, + )) } else { None } @@ -313,7 +321,7 @@ struct SpvDebugFile<'a> { /// Source strings from one `OpSource`, and any number of `OpSourceContinued`. op_source_parts: SmallVec<[&'a str; 1]>, - regenerated_rustc_source_file: Option>, + regenerated_rustc_source_file: Option>, } impl<'a> SpanRegenerator<'a> { diff --git a/crates/rustc_codegen_spirv/src/custom_insts.rs b/crates/rustc_codegen_spirv/src/custom_insts.rs index 54a1331c9f..645326028d 100644 --- a/crates/rustc_codegen_spirv/src/custom_insts.rs +++ b/crates/rustc_codegen_spirv/src/custom_insts.rs @@ -43,7 +43,8 @@ lazy_static! { /// achieved by hashing the `SCHEMA` constant from `def_custom_insts!` below pub static ref CUSTOM_EXT_INST_SET: String = { let schema_hash = { - use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; + use rustc_data_structures::stable_hasher::StableHasher; + use rustc_hashes::Hash128; use std::hash::Hash; let mut hasher = StableHasher::new(); @@ -57,31 +58,38 @@ lazy_static! { pub fn register_to_spirt_context(cx: &spirt::Context) { use spirt::spv::spec::{ExtInstSetDesc, ExtInstSetInstructionDesc}; - cx.register_custom_ext_inst_set(&CUSTOM_EXT_INST_SET, ExtInstSetDesc { - // HACK(eddyb) this is the most compact form I've found, that isn't - // outright lossy by omitting "Rust vs Rust-GPU" or the version. - short_alias: Some( - concat!("Rust-GPU ", join_cargo_pkg_version_major_minor_patch!(".")).into(), - ), - instructions: SCHEMA - .iter() - .map(|&(i, name, operand_names)| { - (i, ExtInstSetInstructionDesc { - name: name.into(), - operand_names: operand_names - .iter() - .map(|name| { - name.strip_prefix("..") - .unwrap_or(name) - .replace('_', " ") - .into() - }) - .collect(), - is_debuginfo: name.contains("Debug") || name.contains("InlinedCallFrame"), + cx.register_custom_ext_inst_set( + &CUSTOM_EXT_INST_SET, + ExtInstSetDesc { + // HACK(eddyb) this is the most compact form I've found, that isn't + // outright lossy by omitting "Rust vs Rust-GPU" or the version. + short_alias: Some( + concat!("Rust-GPU ", join_cargo_pkg_version_major_minor_patch!(".")).into(), + ), + instructions: SCHEMA + .iter() + .map(|&(i, name, operand_names)| { + ( + i, + ExtInstSetInstructionDesc { + name: name.into(), + operand_names: operand_names + .iter() + .map(|name| { + name.strip_prefix("..") + .unwrap_or(name) + .replace('_', " ") + .into() + }) + .collect(), + is_debuginfo: name.contains("Debug") + || name.contains("InlinedCallFrame"), + }, + ) }) - }) - .collect(), - }); + .collect(), + }, + ); } macro_rules! def_custom_insts { @@ -110,7 +118,7 @@ macro_rules! def_custom_insts { pub fn with_operands(self, operands: &[T]) -> CustomInst { match self { $(Self::$name => match operands { - [$($($field,)+ $(ref $variadic_field @ ..)?)?] => CustomInst::$name $({ + [$($($field,)+ $($variadic_field @ ..)?)?] => CustomInst::$name $({ $($field: $field.clone(),)+ $($variadic_field: $variadic_field.iter().cloned().collect())? })?, diff --git a/crates/rustc_codegen_spirv/src/lib.rs b/crates/rustc_codegen_spirv/src/lib.rs index b2bd123dd2..b607fd28c7 100644 --- a/crates/rustc_codegen_spirv/src/lib.rs +++ b/crates/rustc_codegen_spirv/src/lib.rs @@ -2,16 +2,17 @@ #![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(debug_closure_helpers)] #![feature(file_buffered)] #![feature(if_let_guard)] -#![feature(let_chains)] #![feature(negative_impls)] #![feature(rustdoc_internals)] +#![feature(string_from_utf8_lossy_owned)] #![feature(trait_alias)] #![feature(try_blocks)] +#![recursion_limit = "256"] // HACK(eddyb) end of `rustc_codegen_ssa` crate-level attributes (see `build.rs`). //! Welcome to the API documentation for the `rust-gpu` project, this API is @@ -36,7 +37,6 @@ // crate-specific exceptions: #![allow( unsafe_code, // rustc_codegen_ssa requires unsafe functions in traits to be impl'd - clippy::match_on_vec_items, // rustc_codegen_spirv has less strict panic requirements than other embark projects clippy::enum_glob_use, // pretty useful pattern with some codegen'd enums (e.g. rspirv::spirv::Op) clippy::todo, // still lots to implement :) @@ -79,13 +79,15 @@ use rustc_codegen_ssa as maybe_pqp_cg_ssa; // FIXME(eddyb) remove all `#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)]` // as soon as they're not needed anymore (i.e. using `rustc_codegen_ssa` again). +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] +extern crate rustc_abi; extern crate rustc_apfloat; #[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] 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; +extern crate rustc_attr_parsing; #[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_codegen_ssa; #[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] @@ -94,6 +96,8 @@ extern crate rustc_driver; #[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_errors; #[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] +extern crate rustc_hashes; +#[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_hir; #[cfg(rustc_codegen_spirv_disable_pqp_cg_ssa)] extern crate rustc_index; @@ -147,11 +151,12 @@ use maybe_pqp_cg_ssa::traits::{ CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods, }; -use maybe_pqp_cg_ssa::{CodegenResults, CompiledModule, ModuleCodegen, ModuleKind}; +use maybe_pqp_cg_ssa::{CodegenResults, CompiledModule, ModuleCodegen, ModuleKind, TargetConfig}; use rspirv::binary::Assemble; use rustc_ast::expand::allocator::AllocatorKind; +use rustc_ast::expand::autodiff_attrs::AutoDiffItem; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError}; +use rustc_errors::{DiagCtxtHandle, FatalError}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::mir::mono::{MonoItem, MonoItemData}; @@ -257,15 +262,33 @@ impl CodegenBackend for SpirvCodegenBackend { rustc_errors::DEFAULT_LOCALE_RESOURCE } - fn target_features(&self, sess: &Session, _allow_unstable: bool) -> Vec { + fn target_config(&self, sess: &Session) -> TargetConfig { let cmdline = sess.opts.cg.target_feature.split(','); let cfg = sess.target.options.features.split(','); - cfg.chain(cmdline) + + let target_features: Vec<_> = cfg + .chain(cmdline) .filter(|l| l.starts_with('+')) .map(|l| &l[1..]) .filter(|l| !l.is_empty()) .map(Symbol::intern) - .collect() + .collect(); + + // HACK(eddyb) this should be a superset of `target_features`, + // which *additionally* also includes unstable target features, + // but there is no reason to make a distinction for SPIR-V ones. + let unstable_target_features = target_features.clone(); + + TargetConfig { + target_features, + unstable_target_features, + + // FIXME(eddyb) support and/or emulate `f16` and `f128`. + has_reliable_f16: false, + has_reliable_f16_math: false, + has_reliable_f128: false, + has_reliable_f128_math: false, + } } fn provide(&self, providers: &mut rustc_middle::util::Providers) { @@ -310,12 +333,7 @@ impl CodegenBackend for SpirvCodegenBackend { .join(sess) } - fn link( - &self, - sess: &Session, - codegen_results: CodegenResults, - outputs: &OutputFilenames, - ) -> Result<(), ErrorGuaranteed> { + fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) { let timer = sess.timer("link_crate"); link::link( sess, @@ -324,8 +342,6 @@ impl CodegenBackend for SpirvCodegenBackend { codegen_results.crate_info.local_crate_name.as_str(), ); drop(timer); - - sess.dcx().has_errors().map_or(Ok(()), Err) } } @@ -372,7 +388,7 @@ impl WriteBackendMethods for SpirvCodegenBackend { unsafe fn optimize( _: &CodegenContext, _: DiagCtxtHandle<'_>, - _: &ModuleCodegen, + _: &mut ModuleCodegen, _: &ModuleConfig, ) -> Result<(), FatalError> { // TODO: Implement @@ -389,6 +405,7 @@ impl WriteBackendMethods for SpirvCodegenBackend { .to_vec(), name: thin_module.name().to_string(), kind: ModuleKind::Regular, + thin_lto_buffer: None, }; Ok(module) } @@ -406,9 +423,11 @@ impl WriteBackendMethods for SpirvCodegenBackend { module: ModuleCodegen, _config: &ModuleConfig, ) -> Result { - let path = cgcx - .output_filenames - .temp_path(OutputType::Object, Some(&module.name)); + let path = cgcx.output_filenames.temp_path_for_cgu( + OutputType::Object, + &module.name, + cgcx.invocation_temp.as_deref(), + ); // Note: endianness doesn't matter, readers deduce endianness from magic header. let spirv_module = spirv_tools::binary::from_binary(&module.module_llvm); File::create(&path) @@ -423,6 +442,7 @@ impl WriteBackendMethods for SpirvCodegenBackend { bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: vec![], }) } @@ -436,6 +456,15 @@ impl WriteBackendMethods for SpirvCodegenBackend { fn serialize_module(module: ModuleCodegen) -> (String, Self::ModuleBuffer) { (module.name, SpirvModuleBuffer(module.module_llvm)) } + + fn autodiff( + _cgcx: &CodegenContext, + _module: &ModuleCodegen, + _diff_fncs: Vec, + _config: &ModuleConfig, + ) -> Result<(), FatalError> { + todo!() + } } impl ExtraBackendMethods for SpirvCodegenBackend { @@ -461,8 +490,8 @@ impl ExtraBackendMethods for SpirvCodegenBackend { // TODO: Do dep_graph stuff let cgu = tcx.codegen_unit(cgu_name); - let cx = CodegenCx::new(tcx, cgu); - let do_codegen = || { + 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); if let Some(dir) = &cx.codegen_args.dump_mir { @@ -476,32 +505,38 @@ impl ExtraBackendMethods for SpirvCodegenBackend { } } mono_item.predefine::>( - &cx, + cx, mono_item_data.linkage, mono_item_data.visibility, ); } // ... and now that we have everything pre-defined, fill out those definitions. - for &(mono_item, _) in mono_items.iter() { + for &(mono_item, mono_item_data) in &mono_items { if let MonoItem::Fn(instance) = mono_item { if is_blocklisted_fn(cx.tcx, &cx.sym, instance) { continue; } } - mono_item.define::>(&cx); + mono_item.define::>(cx, mono_item_data); } - if let Some(_entry) = maybe_create_entry_wrapper::>(&cx) { + if let Some(_entry) = maybe_create_entry_wrapper::>(cx) { // attributes::sanitize(&cx, SanitizerSet::empty(), entry); } }; - if let Some(path) = &cx.codegen_args.dump_module_on_panic { - let module_dumper = DumpModuleOnPanic { cx: &cx, path }; - with_no_trimmed_paths!(do_codegen()); + // HACK(eddyb) mutable access needed for `mono_item.define::<...>(cx, ...)` + // but that alone leads to needless cloning and smuggling a mutable borrow + // through `DumpModuleOnPanic` (for both its `Drop` impl and `do_codegen`). + if let Some(path) = cx.codegen_args.dump_module_on_panic.clone() { + let module_dumper = DumpModuleOnPanic { + cx: &mut cx, + path: &path, + }; + with_no_trimmed_paths!(do_codegen(module_dumper.cx)); drop(module_dumper); } else { - with_no_trimmed_paths!(do_codegen()); + with_no_trimmed_paths!(do_codegen(&mut cx)); } let spirv_module = cx.finalize_module().assemble(); @@ -510,6 +545,7 @@ impl ExtraBackendMethods for SpirvCodegenBackend { name: cgu_name.to_string(), module_llvm: spirv_module, kind: ModuleKind::Regular, + thin_lto_buffer: None, }, 0, ) @@ -527,7 +563,7 @@ impl ExtraBackendMethods for SpirvCodegenBackend { } struct DumpModuleOnPanic<'a, 'cx, 'tcx> { - cx: &'cx CodegenCx<'tcx>, + cx: &'cx mut CodegenCx<'tcx>, path: &'a Path, } @@ -544,7 +580,7 @@ impl Drop for DumpModuleOnPanic<'_, '_, '_> { } /// This is the entrypoint for a hot plugged `rustc_codegen_spirv` -#[no_mangle] +#[unsafe(no_mangle)] pub fn __rustc_codegen_backend() -> Box { // Tweak rustc's default ICE panic hook, to direct people to `rust-gpu`. rustc_driver::install_ice_hook("https://github.com/rust-gpu/rust-gpu/issues/new", |dcx| { diff --git a/crates/rustc_codegen_spirv/src/link.rs b/crates/rustc_codegen_spirv/src/link.rs index 4c702b7c78..22165e2a03 100644 --- a/crates/rustc_codegen_spirv/src/link.rs +++ b/crates/rustc_codegen_spirv/src/link.rs @@ -65,8 +65,12 @@ pub fn link( if outputs.outputs.should_codegen() { let out_filename = out_filename(sess, crate_type, outputs, Symbol::intern(crate_name)); - let out_filename_file_for_writing = - out_filename.file_for_writing(outputs, OutputType::Exe, None); + let out_filename_file_for_writing = out_filename.file_for_writing( + outputs, + OutputType::Exe, + crate_name, + sess.invocation_temp.as_deref(), + ); match crate_type { CrateType::Rlib => { link_rlib(sess, codegen_results, &out_filename_file_for_writing); @@ -137,7 +141,7 @@ fn link_rlib(sess: &Session, codegen_results: &CodegenResults, out_filename: &Pa create_archive( &file_list, - codegen_results.metadata.raw_data(), + codegen_results.metadata.stub_or_full(), out_filename, ); } @@ -329,7 +333,7 @@ fn do_spirv_opt( match sess.opts.optimize { OptLevel::No => {} - OptLevel::Less | OptLevel::Default | OptLevel::Aggressive => { + OptLevel::Less | OptLevel::More | OptLevel::Aggressive => { optimizer.register_performance_passes(); } OptLevel::Size | OptLevel::SizeMin => { @@ -427,15 +431,14 @@ fn add_upstream_rust_crates( codegen_results: &CodegenResults, crate_type: CrateType, ) { - let (_, data) = codegen_results + let data = codegen_results .crate_info .dependency_formats - .iter() - .find(|(ty, _)| *ty == crate_type) + .get(&crate_type) .expect("failed to find crate type in dependency format list"); for &cnum in &codegen_results.crate_info.used_crates { let src = &codegen_results.crate_info.used_crate_source[&cnum]; - match data[cnum.as_usize() - 1] { + match data[cnum] { Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => rlibs.push(src.rlib.as_ref().unwrap().0.clone()), //Linkage::Dynamic => rlibs.push(src.dylib.as_ref().unwrap().0.clone()), @@ -451,11 +454,10 @@ fn add_upstream_native_libraries( codegen_results: &CodegenResults, crate_type: CrateType, ) { - let (_, data) = codegen_results + let data = codegen_results .crate_info .dependency_formats - .iter() - .find(|(ty, _)| *ty == crate_type) + .get(&crate_type) .expect("failed to find crate type in dependency format list"); for &cnum in &codegen_results.crate_info.used_crates { @@ -467,7 +469,7 @@ fn add_upstream_native_libraries( NativeLibKind::Static { bundle: Some(false), .. - } if data[cnum.as_usize() - 1] != Linkage::Static => {} + } if data[cnum] != Linkage::Static => {} NativeLibKind::Static { bundle: None | Some(true), @@ -487,7 +489,7 @@ fn add_upstream_native_libraries( // (see `compiler/rustc_codegen_ssa/src/back/link.rs`) fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool { match lib.cfg { - Some(ref cfg) => rustc_attr::cfg_matches(cfg, sess, CRATE_NODE_ID, None), + Some(ref cfg) => rustc_attr_parsing::cfg_matches(cfg, sess, CRATE_NODE_ID, None), None => true, } } diff --git a/crates/rustc_codegen_spirv/src/linker/destructure_composites.rs b/crates/rustc_codegen_spirv/src/linker/destructure_composites.rs index 9384eecf60..0185be16f9 100644 --- a/crates/rustc_codegen_spirv/src/linker/destructure_composites.rs +++ b/crates/rustc_codegen_spirv/src/linker/destructure_composites.rs @@ -51,7 +51,6 @@ pub fn destructure_composites(function: &mut Function) { rewrite_rules.get(&origin_id).map_or(origin_id, |id| *id), ); *inst = Instruction::new(Op::Nop, None, None, vec![]); - continue; } } } diff --git a/crates/rustc_codegen_spirv/src/linker/duplicates.rs b/crates/rustc_codegen_spirv/src/linker/duplicates.rs index 6b1b45d8cd..0f8a36d8a0 100644 --- a/crates/rustc_codegen_spirv/src/linker/duplicates.rs +++ b/crates/rustc_codegen_spirv/src/linker/duplicates.rs @@ -401,11 +401,12 @@ pub fn remove_duplicate_debuginfo(module: &mut Module) { // as it needs to reset callee-side `DbgLocInst`, // but we can replace it in-place and hope later // it get nop'd out by some real `DbgLocInst`. - insts[inst_idx] - .operands - .splice(1.., [Operand::LiteralExtInstInteger( + insts[inst_idx].operands.splice( + 1.., + [Operand::LiteralExtInstInteger( CustomOp::ClearDebugSrcLoc as u32, - )]); + )], + ); dbg = DbgState { loc: Some(DbgLocInst { inst_idx, 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 68a789104a..e5290af40d 100644 --- a/crates/rustc_codegen_spirv/src/linker/import_export_link.rs +++ b/crates/rustc_codegen_spirv/src/linker/import_export_link.rs @@ -202,7 +202,7 @@ 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(ref mut result_type) = &mut inst.result_type { + if let Some(result_type) = &mut inst.result_type { if let Some(&rewrite) = rules.get(result_type) { *result_type = rewrite; } @@ -229,10 +229,9 @@ fn kill_linkage_instructions( .retain(|f| !rewrite_rules.contains_key(&f.def_id().unwrap())); // drop imported variables - module.types_global_values.retain(|v| { - v.result_id - .map_or(true, |v| !rewrite_rules.contains_key(&v)) - }); + module + .types_global_values + .retain(|v| v.result_id.is_none_or(|v| !rewrite_rules.contains_key(&v))); // NOTE(eddyb) `Options`'s `keep_link_export`s field requests that `Export`s // are left in (primarily for unit testing - see also its doc comment). @@ -264,13 +263,13 @@ fn import_kill_annotations_and_debug( ) { module.annotations.retain(|inst| { inst.operands.is_empty() - || inst.operands[0].id_ref_any().map_or(true, |id| { + || inst.operands[0].id_ref_any().is_none_or(|id| { !rewrite_rules.contains_key(&id) && !killed_parameters.contains(&id) }) }); module.debug_names.retain(|inst| { inst.operands.is_empty() - || inst.operands[0].id_ref_any().map_or(true, |id| { + || inst.operands[0].id_ref_any().is_none_or(|id| { !rewrite_rules.contains_key(&id) && !killed_parameters.contains(&id) }) }); @@ -278,7 +277,7 @@ fn import_kill_annotations_and_debug( for inst in &mut module.annotations { if inst.class.opcode == Op::GroupDecorate { inst.operands.retain(|op| { - op.id_ref_any().map_or(true, |id| { + op.id_ref_any().is_none_or(|id| { !rewrite_rules.contains_key(&id) && !killed_parameters.contains(&id) }) }); diff --git a/crates/rustc_codegen_spirv/src/linker/inline.rs b/crates/rustc_codegen_spirv/src/linker/inline.rs index 70b2ec4b2b..34a4886ca0 100644 --- a/crates/rustc_codegen_spirv/src/linker/inline.rs +++ b/crates/rustc_codegen_spirv/src/linker/inline.rs @@ -63,9 +63,14 @@ pub fn inline(sess: &Session, module: &mut Module) -> super::Result<()> { custom_ext_inst_set_import: custom_ext_inst_set_import.unwrap_or_else(|| { let id = next_id(header); - let inst = Instruction::new(Op::ExtInstImport, None, Some(id), vec![ - Operand::LiteralString(custom_insts::CUSTOM_EXT_INST_SET.to_string()), - ]); + let inst = Instruction::new( + Op::ExtInstImport, + None, + Some(id), + vec![Operand::LiteralString( + custom_insts::CUSTOM_EXT_INST_SET.to_string(), + )], + ); module.ext_inst_imports.push(inst); id }), @@ -921,10 +926,12 @@ impl Inliner<'_, '_> { .entry(callee_name) .or_insert_with(|| { let id = next_id(self.header); - self.debug_string_source - .push(Instruction::new(Op::String, None, Some(id), vec![ - Operand::LiteralString(callee_name.to_string()), - ])); + self.debug_string_source.push(Instruction::new( + Op::String, + None, + Some(id), + vec![Operand::LiteralString(callee_name.to_string())], + )); id }); let mut mk_debuginfo_prefix_and_suffix = || { diff --git a/crates/rustc_codegen_spirv/src/linker/mem2reg.rs b/crates/rustc_codegen_spirv/src/linker/mem2reg.rs index ba82f95fee..6a2cb926d5 100644 --- a/crates/rustc_codegen_spirv/src/linker/mem2reg.rs +++ b/crates/rustc_codegen_spirv/src/linker/mem2reg.rs @@ -253,10 +253,13 @@ fn collect_access_chains( } let mut variables = FxHashMap::default(); - variables.insert(base_var, VarInfo { - ty: base_var_ty, - indices: vec![], - }); + variables.insert( + base_var, + VarInfo { + ty: base_var_ty, + indices: vec![], + }, + ); // Loop in case a previous block references a later AccessChain loop { let mut changed = false; @@ -345,17 +348,21 @@ fn split_copy_memory( } }; let temp_id = id(header); - block.instructions[inst_index] = - Instruction::new(Op::Load, Some(ty), Some(temp_id), vec![Operand::IdRef( - source, - )]); + block.instructions[inst_index] = Instruction::new( + Op::Load, + Some(ty), + Some(temp_id), + vec![Operand::IdRef(source)], + ); inst_index += 1; block.instructions.insert( inst_index, - Instruction::new(Op::Store, None, None, vec![ - Operand::IdRef(target), - Operand::IdRef(temp_id), - ]), + Instruction::new( + Op::Store, + None, + None, + vec![Operand::IdRef(target), Operand::IdRef(temp_id)], + ), ); } inst_index += 1; @@ -462,10 +469,12 @@ impl Renamer<'_, '_> { let new_id = id(self.header); self.blocks[block].instructions.insert( 0, - Instruction::new(Op::Phi, Some(self.base_var_type), Some(new_id), vec![ - Operand::IdRef(top_def), - Operand::IdRef(from_block_label), - ]), + Instruction::new( + Op::Phi, + Some(self.base_var_type), + Some(new_id), + vec![Operand::IdRef(top_def), Operand::IdRef(from_block_label)], + ), ); self.phi_defs.insert(new_id); new_id @@ -598,7 +607,7 @@ fn remove_old_variables( block.instructions.retain(|inst| { !matches!(inst.class.opcode, Op::AccessChain | Op::InBoundsAccessChain) || inst.operands.iter().all(|op| { - op.id_ref_any().map_or(true, |id| { + op.id_ref_any().is_none_or(|id| { var_maps_and_types .iter() .all(|(var_map, _)| !var_map.contains_key(&id)) diff --git a/crates/rustc_codegen_spirv/src/linker/mod.rs b/crates/rustc_codegen_spirv/src/linker/mod.rs index fa69dc8e7f..9422fb1347 100644 --- a/crates/rustc_codegen_spirv/src/linker/mod.rs +++ b/crates/rustc_codegen_spirv/src/linker/mod.rs @@ -336,23 +336,27 @@ pub fn link( for func in &mut output.functions { simple_passes::block_ordering_pass(func); } - output = specializer::specialize(opts, output, specializer::SimpleSpecialization { - specialize_operand: |operand| { - matches!(operand, Operand::StorageClass(StorageClass::Generic)) - }, + output = specializer::specialize( + opts, + output, + specializer::SimpleSpecialization { + specialize_operand: |operand| { + matches!(operand, Operand::StorageClass(StorageClass::Generic)) + }, - // NOTE(eddyb) this can be anything that is guaranteed to pass - // validation - there are no constraints so this is either some - // unused pointer, or perhaps one created using `OpConstantNull` - // and simply never mixed with pointers that have a storage class. - // It would be nice to use `Generic` itself here so that we leave - // some kind of indication of it being unconstrained, but `Generic` - // requires additional capabilities, so we use `Function` instead. - // TODO(eddyb) investigate whether this can end up in a pointer - // type that's the value of a module-scoped variable, and whether - // `Function` is actually invalid! (may need `Private`) - concrete_fallback: Operand::StorageClass(StorageClass::Function), - }); + // NOTE(eddyb) this can be anything that is guaranteed to pass + // validation - there are no constraints so this is either some + // unused pointer, or perhaps one created using `OpConstantNull` + // and simply never mixed with pointers that have a storage class. + // It would be nice to use `Generic` itself here so that we leave + // some kind of indication of it being unconstrained, but `Generic` + // requires additional capabilities, so we use `Function` instead. + // TODO(eddyb) investigate whether this can end up in a pointer + // type that's the value of a module-scoped variable, and whether + // `Function` is actually invalid! (may need `Private`) + concrete_fallback: Operand::StorageClass(StorageClass::Function), + }, + ); } // NOTE(eddyb) with SPIR-T, we can do `mem2reg` before inlining, too! @@ -477,7 +481,7 @@ pub fn link( let (spv_words, module_or_err, lower_from_spv_timer) = spv_module_to_spv_words_and_spirt_module(&output); let module = &mut module_or_err.map_err(|e| { - let spv_path = outputs.temp_path_ext("spirt-lower-from-spv-input.spv", None); + let spv_path = outputs.temp_path_for_diagnostic("spirt-lower-from-spv-input.spv"); let was_saved_msg = match std::fs::write(&spv_path, spirv_tools::binary::from_binary(&spv_words)) { @@ -638,10 +642,13 @@ pub fn link( module.entry_points.push(entry.clone()); let entry_name = entry.operands[2].unwrap_literal_string().to_string(); let mut file_stem = OsString::from( - sanitize_filename::sanitize_with_options(&entry_name, sanitize_filename::Options { - replacement: "-", - ..Default::default() - }) + sanitize_filename::sanitize_with_options( + &entry_name, + sanitize_filename::Options { + replacement: "-", + ..Default::default() + }, + ) .replace("--", "-"), ); // It's always possible to find an unambiguous `file_stem`, but it @@ -765,7 +772,7 @@ impl Drop for SpirtDumpGuard<'_> { self.per_pass_module_for_dumping .push(("", self.module.clone())); } - dump_spirt_file_path = Some(self.outputs.temp_path_ext("spirt", None)); + dump_spirt_file_path = Some(self.outputs.temp_path_for_diagnostic("spirt")); } if let Some(dump_spirt_file_path) = &dump_spirt_file_path { diff --git a/crates/rustc_codegen_spirv/src/linker/param_weakening.rs b/crates/rustc_codegen_spirv/src/linker/param_weakening.rs index 8dc6442ccc..ee9df070c5 100644 --- a/crates/rustc_codegen_spirv/src/linker/param_weakening.rs +++ b/crates/rustc_codegen_spirv/src/linker/param_weakening.rs @@ -8,7 +8,7 @@ use indexmap::IndexMap; use rspirv::dr::{Builder, Module, Operand}; use rspirv::spirv::{Op, Word}; use rustc_data_structures::fx::FxHashMap; -use rustc_index::bit_set::BitSet; +use rustc_index::bit_set::DenseBitSet as BitSet; use std::mem; pub fn remove_unused_params(module: Module) -> Module { diff --git a/crates/rustc_codegen_spirv/src/linker/simple_passes.rs b/crates/rustc_codegen_spirv/src/linker/simple_passes.rs index d0e7854895..b17a60a5ce 100644 --- a/crates/rustc_codegen_spirv/src/linker/simple_passes.rs +++ b/crates/rustc_codegen_spirv/src/linker/simple_passes.rs @@ -8,11 +8,11 @@ use std::mem::take; pub fn shift_ids(module: &mut Module, add: u32) { module.all_inst_iter_mut().for_each(|inst| { - if let Some(ref mut result_id) = &mut inst.result_id { + if let Some(result_id) = &mut inst.result_id { *result_id += add; } - if let Some(ref mut result_type) = &mut inst.result_type { + if let Some(result_type) = &mut inst.result_type { *result_type += add; } @@ -110,11 +110,11 @@ pub fn compact_ids(module: &mut Module) -> u32 { }; module.all_inst_iter_mut().for_each(|inst| { - if let Some(ref mut result_id) = &mut inst.result_id { + if let Some(result_id) = &mut inst.result_id { *result_id = insert(*result_id); } - if let Some(ref mut result_type) = &mut inst.result_type { + if let Some(result_type) = &mut inst.result_type { *result_type = insert(*result_type); } diff --git a/crates/rustc_codegen_spirv/src/linker/specializer.rs b/crates/rustc_codegen_spirv/src/linker/specializer.rs index 01c4c9f9b1..88b8095062 100644 --- a/crates/rustc_codegen_spirv/src/linker/specializer.rs +++ b/crates/rustc_codegen_spirv/src/linker/specializer.rs @@ -54,7 +54,6 @@ use crate::spirv_type_constraints::{self, InstSig, StorageClassPat, TyListPat, T use indexmap::{IndexMap, IndexSet}; use rspirv::dr::{Builder, Function, Instruction, Module, Operand}; use rspirv::spirv::{Op, StorageClass, Word}; -use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use smallvec::SmallVec; use std::collections::{BTreeMap, VecDeque}; @@ -624,12 +623,15 @@ impl Specializer { // Inference variables become "generic" parameters. if param_count > 0 { - self.generics.insert(result_id, Generic { - param_count, - def: inst.clone(), - param_values, - replacements, - }); + self.generics.insert( + result_id, + Generic { + param_count, + def: inst.clone(), + param_values, + replacements, + }, + ); } } } @@ -1109,10 +1111,10 @@ impl<'a> Match<'a> { self } - fn debug_with_infer_cx<'b>( + fn debug_with_infer_cx<'b, T: Specialization>( &'b self, - cx: &'b InferCx<'a, impl Specialization>, - ) -> impl fmt::Debug + Captures<'a> + '_ { + cx: &'b InferCx<'a, T>, + ) -> impl fmt::Debug + use<'a, 'b, T> { fn debug_var_found<'a, A: smallvec::Array + 'a, T: 'a, TD: fmt::Display>( var_found: &'a SmallIntMap>>, display: &'a impl Fn(&'a T) -> TD, @@ -2102,10 +2104,13 @@ impl<'a, S: Specialization> InferCx<'a, S> { Op::Return => {} - _ => self.instantiate_instruction(inst, InstructionLocation::FnBody { - block_idx, - inst_idx, - }), + _ => self.instantiate_instruction( + inst, + InstructionLocation::FnBody { + block_idx, + inst_idx, + }, + ), } } } 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 83b603c88b..76ae455e02 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/controlflow.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/controlflow.rs @@ -228,14 +228,17 @@ pub fn convert_custom_aborts_to_unstructured_returns_in_entry_points( }; let block_insts_maybe_custom = func_at_block_insts.into_iter().map(|func_at_inst| { let data_inst_def = func_at_inst.def(); - (func_at_inst, match cx[data_inst_def.form].kind { - DataInstKind::SpvExtInst { ext_set, inst } - if ext_set == custom_ext_inst_set => - { - Some(CustomOp::decode(inst).with_operands(&data_inst_def.inputs)) - } - _ => None, - }) + ( + func_at_inst, + match cx[data_inst_def.form].kind { + DataInstKind::SpvExtInst { ext_set, inst } + if ext_set == custom_ext_inst_set => + { + Some(CustomOp::decode(inst).with_operands(&data_inst_def.inputs)) + } + _ => None, + }, + ) }); let custom_terminator_inst = block_insts_maybe_custom .clone() 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 948f14fe8e..29fefe430d 100644 --- a/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs +++ b/crates/rustc_codegen_spirv/src/linker/spirt_passes/diagnostics.rs @@ -389,15 +389,15 @@ impl DiagnosticReporter<'_> { .split_last() .filter( |( - &UseOrigin::Global { + UseOrigin::Global { attrs: use_attrs, .. } - | &UseOrigin::IntraFunc { + | UseOrigin::IntraFunc { func_attrs: use_attrs, .. }, _, - )| { use_attrs == attrs }, + )| *use_attrs == attrs, ) .map_or((None, &self.use_stack[..]), |(current, stack)| { (Some(current), stack) diff --git a/crates/rustc_codegen_spirv/src/linker/test.rs b/crates/rustc_codegen_spirv/src/linker/test.rs index 529b4c697b..1a1e1061ec 100644 --- a/crates/rustc_codegen_spirv/src/linker/test.rs +++ b/crates/rustc_codegen_spirv/src/linker/test.rs @@ -66,12 +66,15 @@ fn load(bytes: &[u8]) -> Module { // FIXME(eddyb) shouldn't this be named just `link`? (`assemble_spirv` is separate) fn assemble_and_link(binaries: &[&[u8]]) -> Result { - link_with_linker_opts(binaries, &crate::linker::Options { - compact_ids: true, - dce: true, - keep_link_exports: true, - ..Default::default() - }) + link_with_linker_opts( + binaries, + &crate::linker::Options { + compact_ids: true, + dce: true, + keep_link_exports: true, + ..Default::default() + }, + ) } fn link_with_linker_opts( @@ -140,9 +143,8 @@ fn link_with_linker_opts( hash_kind: sopts.unstable_opts.src_hash_algorithm(&target), checksum_hash_kind: None, }; - rustc_span::create_session_globals_then(sopts.edition, Some(sm_inputs), || { + rustc_span::create_session_globals_then(sopts.edition, &[], Some(sm_inputs), || { let mut sess = rustc_session::build_session( - early_dcx, sopts, CompilerIO { input: Input::Str { @@ -161,7 +163,10 @@ fn link_with_linker_opts( Default::default(), rustc_interface::util::rustc_version_str().unwrap_or("unknown"), Default::default(), - Default::default(), + { + extern crate rustc_driver_impl; + &rustc_driver_impl::USING_INTERNAL_FEATURES + }, Default::default(), ); diff --git a/crates/rustc_codegen_spirv/src/spirv_type.rs b/crates/rustc_codegen_spirv/src/spirv_type.rs index d674f2542f..e774eff77d 100644 --- a/crates/rustc_codegen_spirv/src/spirv_type.rs +++ b/crates/rustc_codegen_spirv/src/spirv_type.rs @@ -4,11 +4,11 @@ use crate::codegen_cx::CodegenCx; use indexmap::IndexSet; use rspirv::dr::Operand; use rspirv::spirv::{Capability, Decoration, Dim, ImageFormat, StorageClass, Word}; +use rustc_abi::{Align, Size}; use rustc_data_structures::fx::FxHashMap; use rustc_middle::span_bug; use rustc_span::def_id::DefId; use rustc_span::{Span, Symbol}; -use rustc_target::abi::{Align, Size}; use std::cell::RefCell; use std::fmt; use std::iter; diff --git a/crates/rustc_codegen_spirv/src/symbols.rs b/crates/rustc_codegen_spirv/src/symbols.rs index e3d4dc2232..bb81d279b8 100644 --- a/crates/rustc_codegen_spirv/src/symbols.rs +++ b/crates/rustc_codegen_spirv/src/symbols.rs @@ -1,8 +1,9 @@ use crate::attr::{Entry, ExecutionModeExtra, IntrinsicType, SpecConstant, SpirvAttribute}; use crate::builder::libm_intrinsics; use rspirv::spirv::{BuiltIn, ExecutionMode, ExecutionModel, StorageClass}; -use rustc_ast::ast::{AttrKind, Attribute, LitIntType, LitKind, MetaItemInner, MetaItemLit}; +use rustc_ast::ast::{LitIntType, LitKind, MetaItemInner, MetaItemLit}; use rustc_data_structures::fx::FxHashMap; +use rustc_hir::Attribute; use rustc_span::Span; use rustc_span::symbol::{Ident, Symbol}; use std::rc::Rc; @@ -446,17 +447,17 @@ pub(crate) fn parse_attrs_for_checking<'a>( attrs: &'a [Attribute], ) -> impl Iterator> + 'a { attrs.iter().flat_map(move |attr| { - let (whole_attr_error, args) = match attr.kind { - AttrKind::Normal(ref normal) => { + let (whole_attr_error, args) = match attr { + Attribute::Unparsed(item) => { // #[...] - let s = &normal.item.path.segments; - if s.len() > 1 && s[0].ident.name == sym.rust_gpu { + let s = &item.path.segments; + if s.len() > 1 && s[0].name == sym.rust_gpu { // #[rust_gpu ...] - if s.len() != 2 || s[1].ident.name != sym.spirv { + if s.len() != 2 || s[1].name != sym.spirv { // #[rust_gpu::...] but not #[rust_gpu::spirv] ( Some(Err(( - attr.span, + attr.span(), "unknown `rust_gpu` attribute, expected `rust_gpu::spirv`" .to_string(), ))), @@ -469,7 +470,7 @@ pub(crate) fn parse_attrs_for_checking<'a>( // #[rust_gpu::spirv] ( Some(Err(( - attr.span, + attr.span(), "#[rust_gpu::spirv(..)] attribute must have at least one argument" .to_string(), ))), @@ -481,7 +482,7 @@ pub(crate) fn parse_attrs_for_checking<'a>( (None, Default::default()) } } - AttrKind::DocComment(..) => (None, Default::default()), // doccomment + Attribute::Parsed(_) => (None, Default::default()), }; whole_attr_error diff --git a/crates/rustc_codegen_spirv/src/target.rs b/crates/rustc_codegen_spirv/src/target.rs index 313c0a474b..9f0b26fae5 100644 --- a/crates/rustc_codegen_spirv/src/target.rs +++ b/crates/rustc_codegen_spirv/src/target.rs @@ -80,13 +80,13 @@ impl SpirvTarget { o.simd_types_indirect = false; o.allows_weak_linkage = false; o.crt_static_allows_dylibs = true; + o.crt_static_respected = true; o.dll_prefix = "".into(); o.dll_suffix = ".spv.json".into(); o.dynamic_linking = true; o.emit_debug_gdb_scripts = false; o.linker_flavor = LinkerFlavor::Unix(Cc::No); o.panic_strategy = PanicStrategy::Abort; - o.os = "unknown".into(); o.env = self.env.to_string().into(); o.vendor = self.vendor.clone().into(); // TODO: Investigate if main_needs_argc_argv is useful (for building exes) diff --git a/crates/spirv-builder/src/lib.rs b/crates/spirv-builder/src/lib.rs index ea017ed526..9e20671ea1 100644 --- a/crates/spirv-builder/src/lib.rs +++ b/crates/spirv-builder/src/lib.rs @@ -36,7 +36,6 @@ clippy::map_err_ignore, clippy::map_flatten, clippy::map_unwrap_or, - clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wildcard_for_single_variants, clippy::mem_forget, @@ -952,7 +951,7 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result { let mut cargo = Command::new("cargo"); if let Some(toolchain) = &builder.toolchain_overwrite { - cargo.arg(format!("+{}", toolchain)); + cargo.arg(format!("+{toolchain}")); } cargo.args([ "build", @@ -980,7 +979,7 @@ fn invoke_rustc(builder: &SpirvBuilder) -> Result { .arg(builder.path_to_target_spec.clone().unwrap_or_else(|| { PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("target-specs") - .join(format!("{}.json", target)) + .join(format!("{target}.json")) })); } else { cargo.arg("--target").arg(target); @@ -1074,22 +1073,21 @@ struct RustcOutput { const ARTIFACT_SUFFIX: &str = ".spv.json"; fn get_sole_artifact(out: &str) -> Option { - let last = out - .lines() - .filter_map(|line| { - if let Ok(line) = serde_json::from_str::(line) { - Some(line) - } else { - // Pass through invalid lines - println!("{line}"); - None - } - }) - .filter(|line| line.reason == "compiler-artifact") - .last() - .expect("Did not find output file in rustc output"); + let mut last_compiler_artifact = None; + for line in out.lines() { + let Ok(msg) = serde_json::from_str::(line) else { + // Pass through invalid lines + println!("{line}"); + continue; + }; + if msg.reason == "compiler-artifact" { + last_compiler_artifact = Some(msg); + } + } + let last_compiler_artifact = + last_compiler_artifact.expect("Did not find output file in rustc output"); - let mut filenames = last + let mut filenames = last_compiler_artifact .filenames .unwrap() .into_iter() @@ -1132,7 +1130,7 @@ fn leaf_deps(artifact: &Path, mut handle: impl FnMut(&RawStr)) -> std::io::Resul pub fn query_rustc_version(toolchain: Option<&str>) -> std::io::Result { let mut cmd = Command::new("rustc"); if let Some(toolchain) = toolchain { - cmd.arg(format!("+{}", toolchain)); + cmd.arg(format!("+{toolchain}")); } cmd.arg("--version"); let output = cmd.output()?; @@ -1144,5 +1142,5 @@ pub fn query_rustc_version(toolchain: Option<&str>) -> std::io::Result Version::parse(version).ok() }; Ok(parse(&stdout) - .unwrap_or_else(|| panic!("failed parsing `rustc --version` output `{}`", stdout))) + .unwrap_or_else(|| panic!("failed parsing `rustc --version` output `{stdout}`"))) } diff --git a/crates/spirv-builder/target-specs/spirv-unknown-opengl4.0.json b/crates/spirv-builder/target-specs/spirv-unknown-opengl4.0.json index 9fa58d8558..d76e303e2a 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-opengl4.0.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-opengl4.0.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-builder/target-specs/spirv-unknown-opengl4.1.json b/crates/spirv-builder/target-specs/spirv-unknown-opengl4.1.json index 13d687233c..10eaa2f6ed 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-opengl4.1.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-opengl4.1.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-builder/target-specs/spirv-unknown-opengl4.2.json b/crates/spirv-builder/target-specs/spirv-unknown-opengl4.2.json index d1312620a2..9a8e14bced 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-opengl4.2.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-opengl4.2.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-builder/target-specs/spirv-unknown-opengl4.3.json b/crates/spirv-builder/target-specs/spirv-unknown-opengl4.3.json index 7a52159432..a164073671 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-opengl4.3.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-opengl4.3.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-builder/target-specs/spirv-unknown-opengl4.5.json b/crates/spirv-builder/target-specs/spirv-unknown-opengl4.5.json index ba509ed6dd..00d23b035d 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-opengl4.5.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-opengl4.5.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-builder/target-specs/spirv-unknown-spv1.0.json b/crates/spirv-builder/target-specs/spirv-unknown-spv1.0.json index d9e2166f5c..b1f7f910c3 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-spv1.0.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-spv1.0.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-builder/target-specs/spirv-unknown-spv1.1.json b/crates/spirv-builder/target-specs/spirv-unknown-spv1.1.json index 8fc1bcaf38..4319c16514 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-spv1.1.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-spv1.1.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-builder/target-specs/spirv-unknown-spv1.2.json b/crates/spirv-builder/target-specs/spirv-unknown-spv1.2.json index 0037561bee..43a4ec9bd8 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-spv1.2.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-spv1.2.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-builder/target-specs/spirv-unknown-spv1.3.json b/crates/spirv-builder/target-specs/spirv-unknown-spv1.3.json index 645848caf5..3903cdba51 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-spv1.3.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-spv1.3.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-builder/target-specs/spirv-unknown-spv1.4.json b/crates/spirv-builder/target-specs/spirv-unknown-spv1.4.json index 43ab248a65..a645839c76 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-spv1.4.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-spv1.4.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-builder/target-specs/spirv-unknown-spv1.5.json b/crates/spirv-builder/target-specs/spirv-unknown-spv1.5.json index e339e11535..67a2fb375f 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-spv1.5.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-spv1.5.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.0.json b/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.0.json index a15b45b6c6..468d7e6049 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.0.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.0.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.1.json b/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.1.json index b71dd7b2fd..b75eaa7dd9 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.1.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.1.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.1spv1.4.json b/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.1spv1.4.json index 82634e6b85..66eaba431b 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.1spv1.4.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.1spv1.4.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.2.json b/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.2.json index 7952baed9d..34032c502a 100644 --- a/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.2.json +++ b/crates/spirv-builder/target-specs/spirv-unknown-vulkan1.2.json @@ -3,6 +3,7 @@ "arch": "spirv", "crt-objects-fallback": "false", "crt-static-allows-dylibs": true, + "crt-static-respected": true, "data-layout": "e-m:e-p:32:32:32-i64:64-n8:16:32:64", "dll-prefix": "", "dll-suffix": ".spv.json", @@ -19,7 +20,6 @@ "std": null, "tier": null }, - "os": "unknown", "panic-strategy": "abort", "simd-types-indirect": false, "target-pointer-width": "32" diff --git a/crates/spirv-std/macros/src/image.rs b/crates/spirv-std/macros/src/image.rs index 7cecb637a1..0af4a7c67c 100644 --- a/crates/spirv-std/macros/src/image.rs +++ b/crates/spirv-std/macros/src/image.rs @@ -218,7 +218,6 @@ impl Parse for ImageType { if input.peek(syn::Token![,]) { input.parse::()?; - continue; } else { break; } diff --git a/crates/spirv-std/macros/src/lib.rs b/crates/spirv-std/macros/src/lib.rs index f9f447004b..940604bc16 100644 --- a/crates/spirv-std/macros/src/lib.rs +++ b/crates/spirv-std/macros/src/lib.rs @@ -36,7 +36,6 @@ clippy::map_err_ignore, clippy::map_flatten, clippy::map_unwrap_or, - clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wildcard_for_single_variants, clippy::mem_forget, @@ -109,20 +108,20 @@ use std::fmt::Write; /// ## Arguments /// /// - `dimensionality` — Dimensionality of an image. -/// Accepted values: `1D`, `2D`, `3D`, `rect`, `cube`, `subpass`. +/// Accepted values: `1D`, `2D`, `3D`, `rect`, `cube`, `subpass`. /// - `type` — The sampled type of an image, mutually exclusive with `format`, -/// when set the image format is unknown. -/// Accepted values: `f32`, `f64`, `u8`, `u16`, `u32`, `u64`, `i8`, `i16`, `i32`, `i64`. +/// when set the image format is unknown. +/// Accepted values: `f32`, `f64`, `u8`, `u16`, `u32`, `u64`, `i8`, `i16`, `i32`, `i64`. /// - `format` — The image format of the image, mutually exclusive with `type`. -/// Accepted values: Snake case versions of [`ImageFormat`]. +/// Accepted values: Snake case versions of [`ImageFormat`]. /// - `sampled` — Whether it is known that the image will be used with a sampler. -/// Accepted values: `true` or `false`. Default: `unknown`. +/// Accepted values: `true` or `false`. Default: `unknown`. /// - `multisampled` — Whether the image contains multisampled content. -/// Accepted values: `true` or `false`. Default: `false`. +/// Accepted values: `true` or `false`. Default: `false`. /// - `arrayed` — Whether the image contains arrayed content. -/// Accepted values: `true` or `false`. Default: `false`. +/// Accepted values: `true` or `false`. Default: `false`. /// - `depth` — Whether it is known that the image is a depth image. -/// Accepted values: `true` or `false`. Default: `unknown`. +/// Accepted values: `true` or `false`. Default: `unknown`. /// /// [`ImageFormat`]: spirv_std_types::image_params::ImageFormat /// diff --git a/crates/spirv-std/src/arch.rs b/crates/spirv-std/src/arch.rs index 2d9ccdfded..2e2d664974 100644 --- a/crates/spirv-std/src/arch.rs +++ b/crates/spirv-std/src/arch.rs @@ -87,18 +87,20 @@ pub unsafe fn vector_extract_dynamic( vector: impl Vector, index: usize, ) -> T { - let mut result = T::default(); - - asm! { - "%vector = OpLoad _ {vector}", - "%element = OpVectorExtractDynamic _ %vector {index}", - "OpStore {element} %element", - vector = in(reg) &vector, - index = in(reg) index, - element = in(reg) &mut result - } + unsafe { + let mut result = T::default(); - result + asm! { + "%vector = OpLoad _ {vector}", + "%element = OpVectorExtractDynamic _ %vector {index}", + "OpStore {element} %element", + vector = in(reg) &vector, + index = in(reg) index, + element = in(reg) &mut result + } + + result + } } /// Make a copy of a vector, with a single, variably selected, @@ -115,20 +117,22 @@ pub unsafe fn vector_insert_dynamic, const N: usize>( index: usize, element: T, ) -> V { - let mut result = V::default(); - - asm! { - "%vector = OpLoad _ {vector}", - "%element = OpLoad _ {element}", - "%new_vector = OpVectorInsertDynamic _ %vector %element {index}", - "OpStore {result} %new_vector", - vector = in(reg) &vector, - index = in(reg) index, - element = in(reg) &element, - result = in(reg) &mut result, - } + unsafe { + let mut result = V::default(); - result + asm! { + "%vector = OpLoad _ {vector}", + "%element = OpLoad _ {element}", + "%new_vector = OpVectorInsertDynamic _ %vector %element {index}", + "OpStore {result} %new_vector", + vector = in(reg) &vector, + index = in(reg) index, + element = in(reg) &element, + result = in(reg) &mut result, + } + + result + } } /// Fragment-shader discard. Equivalvent to `discard()` from GLSL @@ -155,17 +159,19 @@ pub fn kill() -> ! { #[spirv_std_macros::gpu_only] #[doc(alias = "OpReadClockKHR")] pub unsafe fn read_clock_khr() -> u64 { - let mut result: u64; - - asm! { - "%uint = OpTypeInt 32 0", - "%scope = OpConstant %uint {scope}", - "{result} = OpReadClockKHR typeof*{result} %scope", - result = out(reg) result, - scope = const SCOPE, - }; + unsafe { + let mut result: u64; - result + asm! { + "%uint = OpTypeInt 32 0", + "%scope = OpConstant %uint {scope}", + "{result} = OpReadClockKHR typeof*{result} %scope", + result = out(reg) result, + scope = const SCOPE, + }; + + result + } } /// Like `read_clock_khr` but returns a vector to avoid requiring the `Int64` @@ -179,35 +185,39 @@ pub unsafe fn read_clock_khr() -> u64 { #[spirv_std_macros::gpu_only] #[doc(alias = "OpReadClockKHR")] pub unsafe fn read_clock_uvec2_khr, const SCOPE: u32>() -> V { - let mut result = V::default(); + unsafe { + let mut result = V::default(); - asm! { - "%uint = OpTypeInt 32 0", - "%scope = OpConstant %uint {scope}", - "%result = OpReadClockKHR typeof*{result} %scope", - "OpStore {result} %result", - result = in(reg) &mut result, - scope = const SCOPE, - }; + asm! { + "%uint = OpTypeInt 32 0", + "%scope = OpConstant %uint {scope}", + "%result = OpReadClockKHR typeof*{result} %scope", + "OpStore {result} %result", + result = in(reg) &mut result, + scope = const SCOPE, + }; - result + result + } } #[cfg(target_arch = "spirv")] unsafe fn call_glsl_op_with_ints(a: T, b: T) -> T { - let mut result = T::default(); - asm!( - "%glsl = OpExtInstImport \"GLSL.std.450\"", - "%a = OpLoad _ {a}", - "%b = OpLoad _ {b}", - "%result = OpExtInst typeof*{result} %glsl {op} %a %b", - "OpStore {result} %result", - a = in(reg) &a, - b = in(reg) &b, - result = in(reg) &mut result, - op = const OP - ); - result + unsafe { + let mut result = T::default(); + asm!( + "%glsl = OpExtInstImport \"GLSL.std.450\"", + "%a = OpLoad _ {a}", + "%b = OpLoad _ {b}", + "%result = OpExtInst typeof*{result} %glsl {op} %a %b", + "OpStore {result} %result", + a = in(reg) &a, + b = in(reg) &b, + result = in(reg) &mut result, + op = const OP + ); + result + } } /// Compute the minimum of two unsigned integers via a GLSL extended instruction. @@ -254,83 +264,91 @@ pub trait IndexUnchecked { impl IndexUnchecked for [T] { #[cfg(target_arch = "spirv")] unsafe fn index_unchecked(&self, index: usize) -> &T { - // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. - let mut result_slot = core::mem::MaybeUninit::uninit(); - asm! { - "%slice_ptr = OpLoad _ {slice_ptr_ptr}", - "%data_ptr = OpCompositeExtract _ %slice_ptr 0", - "%result = OpAccessChain _ %data_ptr {index}", - "OpStore {result_slot} %result", - slice_ptr_ptr = in(reg) &self, - index = in(reg) index, - result_slot = in(reg) result_slot.as_mut_ptr(), + unsafe { + // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. + let mut result_slot = core::mem::MaybeUninit::uninit(); + asm! { + "%slice_ptr = OpLoad _ {slice_ptr_ptr}", + "%data_ptr = OpCompositeExtract _ %slice_ptr 0", + "%result = OpAccessChain _ %data_ptr {index}", + "OpStore {result_slot} %result", + slice_ptr_ptr = in(reg) &self, + index = in(reg) index, + result_slot = in(reg) result_slot.as_mut_ptr(), + } + result_slot.assume_init() } - result_slot.assume_init() } #[cfg(not(target_arch = "spirv"))] unsafe fn index_unchecked(&self, index: usize) -> &T { - self.get_unchecked(index) + unsafe { self.get_unchecked(index) } } #[cfg(target_arch = "spirv")] unsafe fn index_unchecked_mut(&mut self, index: usize) -> &mut T { - // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. - let mut result_slot = core::mem::MaybeUninit::uninit(); - asm! { - "%slice_ptr = OpLoad _ {slice_ptr_ptr}", - "%data_ptr = OpCompositeExtract _ %slice_ptr 0", - "%result = OpAccessChain _ %data_ptr {index}", - "OpStore {result_slot} %result", - slice_ptr_ptr = in(reg) &self, - index = in(reg) index, - result_slot = in(reg) result_slot.as_mut_ptr(), + unsafe { + // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. + let mut result_slot = core::mem::MaybeUninit::uninit(); + asm! { + "%slice_ptr = OpLoad _ {slice_ptr_ptr}", + "%data_ptr = OpCompositeExtract _ %slice_ptr 0", + "%result = OpAccessChain _ %data_ptr {index}", + "OpStore {result_slot} %result", + slice_ptr_ptr = in(reg) &self, + index = in(reg) index, + result_slot = in(reg) result_slot.as_mut_ptr(), + } + result_slot.assume_init() } - result_slot.assume_init() } #[cfg(not(target_arch = "spirv"))] unsafe fn index_unchecked_mut(&mut self, index: usize) -> &mut T { - self.get_unchecked_mut(index) + unsafe { self.get_unchecked_mut(index) } } } impl IndexUnchecked for [T; N] { #[cfg(target_arch = "spirv")] unsafe fn index_unchecked(&self, index: usize) -> &T { - // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. - let mut result_slot = core::mem::MaybeUninit::uninit(); - asm! { - "%result = OpAccessChain _ {array_ptr} {index}", - "OpStore {result_slot} %result", - array_ptr = in(reg) self, - index = in(reg) index, - result_slot = in(reg) result_slot.as_mut_ptr(), + unsafe { + // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. + let mut result_slot = core::mem::MaybeUninit::uninit(); + asm! { + "%result = OpAccessChain _ {array_ptr} {index}", + "OpStore {result_slot} %result", + array_ptr = in(reg) self, + index = in(reg) index, + result_slot = in(reg) result_slot.as_mut_ptr(), + } + result_slot.assume_init() } - result_slot.assume_init() } #[cfg(not(target_arch = "spirv"))] unsafe fn index_unchecked(&self, index: usize) -> &T { - self.get_unchecked(index) + unsafe { self.get_unchecked(index) } } #[cfg(target_arch = "spirv")] unsafe fn index_unchecked_mut(&mut self, index: usize) -> &mut T { - // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. - let mut result_slot = core::mem::MaybeUninit::uninit(); - asm! { - "%result = OpAccessChain _ {array_ptr} {index}", - "OpStore {result_slot} %result", - array_ptr = in(reg) self, - index = in(reg) index, - result_slot = in(reg) result_slot.as_mut_ptr(), + unsafe { + // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. + let mut result_slot = core::mem::MaybeUninit::uninit(); + asm! { + "%result = OpAccessChain _ {array_ptr} {index}", + "OpStore {result_slot} %result", + array_ptr = in(reg) self, + index = in(reg) index, + result_slot = in(reg) result_slot.as_mut_ptr(), + } + result_slot.assume_init() } - result_slot.assume_init() } #[cfg(not(target_arch = "spirv"))] unsafe fn index_unchecked_mut(&mut self, index: usize) -> &mut T { - self.get_unchecked_mut(index) + unsafe { self.get_unchecked_mut(index) } } } diff --git a/crates/spirv-std/src/arch/atomics.rs b/crates/spirv-std/src/arch/atomics.rs index e03ebaa4c4..d818a0e0fd 100644 --- a/crates/spirv-std/src/arch/atomics.rs +++ b/crates/spirv-std/src/arch/atomics.rs @@ -14,21 +14,23 @@ use crate::{ #[doc(alias = "OpAtomicLoad")] #[inline] pub unsafe fn atomic_load(ptr: &N) -> N { - let mut result = N::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%result = OpAtomicLoad _ {ptr} %scope %semantics", - "OpStore {result} %result", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - result = in(reg) &mut result + unsafe { + let mut result = N::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%result = OpAtomicLoad _ {ptr} %scope %semantics", + "OpStore {result} %result", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + result = in(reg) &mut result + } + + result } - - result } /// Atomically store through `ptr` using the given `SEMANTICS`. All subparts of @@ -41,16 +43,18 @@ pub unsafe fn atomic_store( ptr: &mut N, value: N, ) { - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "OpAtomicStore {ptr} %scope %semantics %value", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - value = in(reg) &value + unsafe { + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "OpAtomicStore {ptr} %scope %semantics %value", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + value = in(reg) &value + } } } @@ -69,23 +73,25 @@ pub unsafe fn atomic_exchange ptr: &mut N, value: N, ) -> N { - let mut old = N::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicExchange _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value + unsafe { + let mut old = N::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicExchange _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -111,27 +117,29 @@ pub unsafe fn atomic_compare_exchange< value: I, comparator: I, ) -> I { - let mut old = I::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%equal = OpConstant %u32 {equal}", - "%unequal = OpConstant %u32 {unequal}", - "%value = OpLoad _ {value}", - "%comparator = OpLoad _ {comparator}", - "%old = OpAtomicCompareExchange _ {ptr} %scope %equal %unequal %value %comparator", - "OpStore {old} %old", - scope = const SCOPE, - equal = const EQUAL, - unequal = const UNEQUAL, - ptr = in(reg) ptr, - value = in(reg) &value, - comparator = in(reg) &comparator, - old = in(reg) &mut old, + unsafe { + let mut old = I::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%equal = OpConstant %u32 {equal}", + "%unequal = OpConstant %u32 {unequal}", + "%value = OpLoad _ {value}", + "%comparator = OpLoad _ {comparator}", + "%old = OpAtomicCompareExchange _ {ptr} %scope %equal %unequal %value %comparator", + "OpStore {old} %old", + scope = const SCOPE, + equal = const EQUAL, + unequal = const UNEQUAL, + ptr = in(reg) ptr, + value = in(reg) &value, + comparator = in(reg) &comparator, + old = in(reg) &mut old, + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -148,21 +156,23 @@ pub unsafe fn atomic_compare_exchange< pub unsafe fn atomic_i_increment( ptr: &mut I, ) -> I { - let mut old = I::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%old = OpAtomicIIncrement _ {ptr} %scope %semantics", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old + unsafe { + let mut old = I::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%old = OpAtomicIIncrement _ {ptr} %scope %semantics", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -179,21 +189,23 @@ pub unsafe fn atomic_i_increment( ptr: &mut I, ) -> I { - let mut old = I::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%old = OpAtomicIDecrement _ {ptr} %scope %semantics", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old + unsafe { + let mut old = I::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%old = OpAtomicIDecrement _ {ptr} %scope %semantics", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -211,23 +223,25 @@ pub unsafe fn atomic_i_add( ptr: &mut I, value: I, ) -> I { - let mut old = I::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicIAdd _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value + unsafe { + let mut old = I::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicIAdd _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -245,23 +259,25 @@ pub unsafe fn atomic_i_sub( ptr: &mut I, value: I, ) -> I { - let mut old = I::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicISub _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value + unsafe { + let mut old = I::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicISub _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -280,23 +296,25 @@ pub unsafe fn atomic_s_min S { - let mut old = S::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicSMin _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value + unsafe { + let mut old = S::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicSMin _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -315,23 +333,25 @@ pub unsafe fn atomic_u_min U { - let mut old = U::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicUMin _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value + unsafe { + let mut old = U::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicUMin _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -350,23 +370,25 @@ pub unsafe fn atomic_s_max S { - let mut old = S::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicSMax _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value + unsafe { + let mut old = S::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicSMax _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -385,23 +407,25 @@ pub unsafe fn atomic_u_max U { - let mut old = U::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicUMax _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value + unsafe { + let mut old = U::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicUMax _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -419,23 +443,25 @@ pub unsafe fn atomic_and( ptr: &mut I, value: I, ) -> I { - let mut old = I::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicAnd _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value + unsafe { + let mut old = I::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicAnd _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -453,23 +479,25 @@ pub unsafe fn atomic_or( ptr: &mut I, value: I, ) -> I { - let mut old = I::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicOr _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value + unsafe { + let mut old = I::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicOr _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -487,23 +515,25 @@ pub unsafe fn atomic_xor( ptr: &mut I, value: I, ) -> I { - let mut old = I::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicXor _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value + unsafe { + let mut old = I::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicXor _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -522,23 +552,25 @@ pub unsafe fn atomic_f_min( ptr: &mut F, value: F, ) -> F { - let mut old = F::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicFMinEXT _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value + unsafe { + let mut old = F::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicFMinEXT _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -557,23 +589,25 @@ pub unsafe fn atomic_f_max( ptr: &mut F, value: F, ) -> F { - let mut old = F::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicFMaxEXT _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value + unsafe { + let mut old = F::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicFMaxEXT _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old } - - old } /// Perform the following steps atomically with respect to any other atomic @@ -591,21 +625,23 @@ pub unsafe fn atomic_f_add( ptr: &mut F, value: F, ) -> F { - let mut old = F::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%scope = OpConstant %u32 {scope}", - "%semantics = OpConstant %u32 {semantics}", - "%value = OpLoad _ {value}", - "%old = OpAtomicFAddEXT _ {ptr} %scope %semantics %value", - "OpStore {old} %old", - scope = const SCOPE, - semantics = const SEMANTICS, - ptr = in(reg) ptr, - old = in(reg) &mut old, - value = in(reg) &value + unsafe { + let mut old = F::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%scope = OpConstant %u32 {scope}", + "%semantics = OpConstant %u32 {semantics}", + "%value = OpLoad _ {value}", + "%old = OpAtomicFAddEXT _ {ptr} %scope %semantics %value", + "OpStore {old} %old", + scope = const SCOPE, + semantics = const SEMANTICS, + ptr = in(reg) ptr, + old = in(reg) &mut old, + value = in(reg) &value + } + + old } - - old } diff --git a/crates/spirv-std/src/arch/barrier.rs b/crates/spirv-std/src/arch/barrier.rs index 8b70a536f6..aa7df1746c 100644 --- a/crates/spirv-std/src/arch/barrier.rs +++ b/crates/spirv-std/src/arch/barrier.rs @@ -38,15 +38,17 @@ pub unsafe fn control_barrier< const MEMORY: u32, // Scope const SEMANTICS: u32, // Semantics >() { - asm! { - "%u32 = OpTypeInt 32 0", - "%execution = OpConstant %u32 {execution}", - "%memory = OpConstant %u32 {memory}", - "%semantics = OpConstant %u32 {semantics}", - "OpControlBarrier %execution %memory %semantics", - execution = const EXECUTION, - memory = const MEMORY, - semantics = const SEMANTICS, + unsafe { + asm! { + "%u32 = OpTypeInt 32 0", + "%execution = OpConstant %u32 {execution}", + "%memory = OpConstant %u32 {memory}", + "%semantics = OpConstant %u32 {semantics}", + "OpControlBarrier %execution %memory %semantics", + execution = const EXECUTION, + memory = const MEMORY, + semantics = const SEMANTICS, + } } } @@ -72,13 +74,15 @@ pub unsafe fn memory_barrier< const MEMORY: u32, // Scope const SEMANTICS: u32, // Semantics >() { - asm! { - "%u32 = OpTypeInt 32 0", - "%memory = OpConstant %u32 {memory}", - "%semantics = OpConstant %u32 {semantics}", - "OpMemoryBarrier %memory %semantics", - memory = const MEMORY, - semantics = const SEMANTICS, + unsafe { + asm! { + "%u32 = OpTypeInt 32 0", + "%memory = OpConstant %u32 {memory}", + "%semantics = OpConstant %u32 {semantics}", + "OpMemoryBarrier %memory %semantics", + memory = const MEMORY, + semantics = const SEMANTICS, + } } } @@ -90,13 +94,15 @@ pub unsafe fn memory_barrier< #[spirv_std_macros::gpu_only] #[inline] pub unsafe fn workgroup_memory_barrier() { - memory_barrier::< - { crate::memory::Scope::Workgroup as u32 }, - { - crate::memory::Semantics::WORKGROUP_MEMORY.bits() - | crate::memory::Semantics::ACQUIRE_RELEASE.bits() - }, - >(); + unsafe { + memory_barrier::< + { crate::memory::Scope::Workgroup as u32 }, + { + crate::memory::Semantics::WORKGROUP_MEMORY.bits() + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() + }, + >(); + } } /// Blocks execution of all threads in a group until all group shared accesses have been completed and all threads in the group have reached this call. @@ -107,14 +113,16 @@ pub unsafe fn workgroup_memory_barrier() { #[spirv_std_macros::gpu_only] #[inline] pub unsafe fn workgroup_memory_barrier_with_group_sync() { - control_barrier::< - { crate::memory::Scope::Workgroup as u32 }, - { crate::memory::Scope::Workgroup as u32 }, - { - crate::memory::Semantics::WORKGROUP_MEMORY.bits() - | crate::memory::Semantics::ACQUIRE_RELEASE.bits() - }, - >(); + unsafe { + control_barrier::< + { crate::memory::Scope::Workgroup as u32 }, + { crate::memory::Scope::Workgroup as u32 }, + { + crate::memory::Semantics::WORKGROUP_MEMORY.bits() + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() + }, + >(); + } } /// Blocks execution of all threads in a group until all device memory accesses have been completed. @@ -125,14 +133,16 @@ pub unsafe fn workgroup_memory_barrier_with_group_sync() { #[spirv_std_macros::gpu_only] #[inline] pub unsafe fn device_memory_barrier() { - memory_barrier::< - { crate::memory::Scope::Device as u32 }, - { - crate::memory::Semantics::IMAGE_MEMORY.bits() - | crate::memory::Semantics::UNIFORM_MEMORY.bits() - | crate::memory::Semantics::ACQUIRE_RELEASE.bits() - }, - >(); + unsafe { + memory_barrier::< + { crate::memory::Scope::Device as u32 }, + { + crate::memory::Semantics::IMAGE_MEMORY.bits() + | crate::memory::Semantics::UNIFORM_MEMORY.bits() + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() + }, + >(); + } } /// Blocks execution of all threads in a group until all device memory accesses have been completed and all threads in the group have reached this call. @@ -143,15 +153,17 @@ pub unsafe fn device_memory_barrier() { #[spirv_std_macros::gpu_only] #[inline] pub unsafe fn device_memory_barrier_with_group_sync() { - control_barrier::< - { crate::memory::Scope::Workgroup as u32 }, - { crate::memory::Scope::Device as u32 }, - { - crate::memory::Semantics::IMAGE_MEMORY.bits() - | crate::memory::Semantics::UNIFORM_MEMORY.bits() - | crate::memory::Semantics::ACQUIRE_RELEASE.bits() - }, - >(); + unsafe { + control_barrier::< + { crate::memory::Scope::Workgroup as u32 }, + { crate::memory::Scope::Device as u32 }, + { + crate::memory::Semantics::IMAGE_MEMORY.bits() + | crate::memory::Semantics::UNIFORM_MEMORY.bits() + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() + }, + >(); + } } /// Blocks execution of all threads in a group until all memory accesses have been completed. @@ -162,15 +174,17 @@ pub unsafe fn device_memory_barrier_with_group_sync() { #[spirv_std_macros::gpu_only] #[inline] pub unsafe fn all_memory_barrier() { - memory_barrier::< - { crate::memory::Scope::Device as u32 }, - { - crate::memory::Semantics::WORKGROUP_MEMORY.bits() - | crate::memory::Semantics::IMAGE_MEMORY.bits() - | crate::memory::Semantics::UNIFORM_MEMORY.bits() - | crate::memory::Semantics::ACQUIRE_RELEASE.bits() - }, - >(); + unsafe { + memory_barrier::< + { crate::memory::Scope::Device as u32 }, + { + crate::memory::Semantics::WORKGROUP_MEMORY.bits() + | crate::memory::Semantics::IMAGE_MEMORY.bits() + | crate::memory::Semantics::UNIFORM_MEMORY.bits() + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() + }, + >(); + } } /// Blocks execution of all threads in a group until all memory accesses have been completed and all threads in the group have reached this call. @@ -181,14 +195,16 @@ pub unsafe fn all_memory_barrier() { #[spirv_std_macros::gpu_only] #[inline] pub unsafe fn all_memory_barrier_with_group_sync() { - control_barrier::< - { crate::memory::Scope::Workgroup as u32 }, - { crate::memory::Scope::Device as u32 }, - { - crate::memory::Semantics::WORKGROUP_MEMORY.bits() - | crate::memory::Semantics::IMAGE_MEMORY.bits() - | crate::memory::Semantics::UNIFORM_MEMORY.bits() - | crate::memory::Semantics::ACQUIRE_RELEASE.bits() - }, - >(); + unsafe { + control_barrier::< + { crate::memory::Scope::Workgroup as u32 }, + { crate::memory::Scope::Device as u32 }, + { + crate::memory::Semantics::WORKGROUP_MEMORY.bits() + | crate::memory::Semantics::IMAGE_MEMORY.bits() + | crate::memory::Semantics::UNIFORM_MEMORY.bits() + | crate::memory::Semantics::ACQUIRE_RELEASE.bits() + }, + >(); + } } 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 3ac57894c8..2388fbcee9 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 @@ -20,7 +20,9 @@ use core::arch::asm; #[spirv_std_macros::gpu_only] #[doc(alias = "OpDemoteToHelperInvocationEXT", alias = "discard")] pub unsafe fn demote_to_helper_invocation() { - asm!("OpDemoteToHelperInvocationEXT"); + unsafe { + asm!("OpDemoteToHelperInvocationEXT"); + } } /// Returns `true` if the invocation is currently a helper invocation, otherwise diff --git a/crates/spirv-std/src/arch/mesh_shading.rs b/crates/spirv-std/src/arch/mesh_shading.rs index e3806ee86d..cc906a17cf 100644 --- a/crates/spirv-std/src/arch/mesh_shading.rs +++ b/crates/spirv-std/src/arch/mesh_shading.rs @@ -21,10 +21,12 @@ use core::arch::asm; #[doc(alias = "OpSetMeshOutputsEXT")] #[inline] pub unsafe fn set_mesh_outputs_ext(vertex_count: u32, primitive_count: u32) { - asm! { - "OpSetMeshOutputsEXT {vertex_count} {primitive_count}", - vertex_count = in(reg) vertex_count, - primitive_count = in(reg) primitive_count, + unsafe { + asm! { + "OpSetMeshOutputsEXT {vertex_count} {primitive_count}", + vertex_count = in(reg) vertex_count, + primitive_count = in(reg) primitive_count, + } } } @@ -56,12 +58,14 @@ pub unsafe fn set_mesh_outputs_ext(vertex_count: u32, primitive_count: u32) { #[doc(alias = "OpEmitMeshTasksEXT")] #[inline] pub unsafe fn emit_mesh_tasks_ext(group_count_x: u32, group_count_y: u32, group_count_z: u32) -> ! { - asm! { - "OpEmitMeshTasksEXT {group_count_x} {group_count_y} {group_count_z}", - group_count_x = in(reg) group_count_x, - group_count_y = in(reg) group_count_y, - group_count_z = in(reg) group_count_z, - options(noreturn), + unsafe { + asm! { + "OpEmitMeshTasksEXT {group_count_x} {group_count_y} {group_count_z}", + group_count_x = in(reg) group_count_x, + group_count_y = in(reg) group_count_y, + group_count_z = in(reg) group_count_z, + options(noreturn), + } } } @@ -98,12 +102,14 @@ pub unsafe fn emit_mesh_tasks_ext_payload( group_count_z: u32, payload: &mut T, ) -> ! { - asm! { - "OpEmitMeshTasksEXT {group_count_x} {group_count_y} {group_count_z} {payload}", - group_count_x = in(reg) group_count_x, - group_count_y = in(reg) group_count_y, - group_count_z = in(reg) group_count_z, - payload = in(reg) payload, - options(noreturn), + unsafe { + asm! { + "OpEmitMeshTasksEXT {group_count_x} {group_count_y} {group_count_z} {payload}", + group_count_x = in(reg) group_count_x, + group_count_y = in(reg) group_count_y, + group_count_z = in(reg) group_count_z, + payload = in(reg) payload, + options(noreturn), + } } } diff --git a/crates/spirv-std/src/arch/primitive.rs b/crates/spirv-std/src/arch/primitive.rs index 70c592192f..5953c99426 100644 --- a/crates/spirv-std/src/arch/primitive.rs +++ b/crates/spirv-std/src/arch/primitive.rs @@ -11,8 +11,10 @@ use core::arch::asm; #[doc(alias = "OpEmitVertex")] #[inline] pub unsafe fn emit_vertex() { - asm! { - "OpEmitVertex", + unsafe { + asm! { + "OpEmitVertex", + } } } @@ -25,8 +27,10 @@ pub unsafe fn emit_vertex() { #[doc(alias = "OpEndPrimitive")] #[inline] pub unsafe fn end_primitive() { - asm! { - "OpEndPrimitive", + unsafe { + asm! { + "OpEndPrimitive", + } } } @@ -44,11 +48,13 @@ pub unsafe fn end_primitive() { #[doc(alias = "OpEmitStreamVertex")] #[inline] pub unsafe fn emit_stream_vertex() { - asm! { - "%i64 = OpTypeInt 64 1", - "%stream = OpConstant %i64 {stream}", - "OpEmitStreamVertex %stream", - stream = const STREAM, + unsafe { + asm! { + "%i64 = OpTypeInt 64 1", + "%stream = OpConstant %i64 {stream}", + "OpEmitStreamVertex %stream", + stream = const STREAM, + } } } @@ -64,10 +70,12 @@ pub unsafe fn emit_stream_vertex() { #[doc(alias = "OpEndStreamPrimitive")] #[inline] pub unsafe fn end_stream_primitive() { - asm! { - "%i64 = OpTypeInt 64 1", - "%stream = OpConstant %i64 {stream}", - "OpEndStreamPrimitive %stream", - stream = const STREAM, + unsafe { + asm! { + "%i64 = OpTypeInt 64 1", + "%stream = OpConstant %i64 {stream}", + "OpEndStreamPrimitive %stream", + stream = const STREAM, + } } } diff --git a/crates/spirv-std/src/arch/ray_tracing.rs b/crates/spirv-std/src/arch/ray_tracing.rs index 04adaa4bf1..7612ffb3d3 100644 --- a/crates/spirv-std/src/arch/ray_tracing.rs +++ b/crates/spirv-std/src/arch/ray_tracing.rs @@ -22,18 +22,20 @@ use core::arch::asm; #[doc(alias = "OpReportIntersectionKHR")] #[inline] pub unsafe fn report_intersection(hit: f32, hit_kind: u32) -> bool { - let mut result = false; + unsafe { + let mut result = false; - asm! { - "%bool = OpTypeBool", - "%result = OpReportIntersectionKHR %bool {hit} {hit_kind}", - "OpStore {result} %result", - result = in(reg) &mut result, - hit = in(reg) hit, - hit_kind = in(reg) hit_kind, - }; + asm! { + "%bool = OpTypeBool", + "%result = OpReportIntersectionKHR %bool {hit} {hit_kind}", + "OpStore {result} %result", + result = in(reg) &mut result, + hit = in(reg) hit, + hit_kind = in(reg) hit_kind, + }; - result + result + } } /// Ignores the current potential intersection, terminating the invocation that @@ -43,7 +45,9 @@ pub unsafe fn report_intersection(hit: f32, hit_kind: u32) -> bool { #[doc(alias = "OpIgnoreIntersectionKHR")] #[inline] pub unsafe fn ignore_intersection() -> ! { - asm!("OpIgnoreIntersectionKHR", options(noreturn)); + unsafe { + asm!("OpIgnoreIntersectionKHR", options(noreturn)); + } } /// Terminates the invocation that executes it, stops the ray traversal, accepts @@ -54,7 +58,9 @@ pub unsafe fn ignore_intersection() -> ! { #[doc(alias = "OpTerminateRayKHR")] #[inline] pub unsafe fn terminate_ray() -> ! { - asm!("OpTerminateRayKHR", options(noreturn)); + unsafe { + asm!("OpTerminateRayKHR", options(noreturn)); + } } /// Invoke a callable shader. @@ -74,11 +80,13 @@ pub unsafe fn terminate_ray() -> ! { #[doc(alias = "OpExecuteCallableKHR")] #[inline] pub unsafe fn execute_callable(data: &T) { - asm! { - "%u32 = OpTypeInt 32 0", - "%id = OpConstant %u32 {id}", - "OpExecuteCallableKHR %id {data}", - id = const ID, - data = in(reg) data, - }; + unsafe { + asm! { + "%u32 = OpTypeInt 32 0", + "%id = OpConstant %u32 {id}", + "OpExecuteCallableKHR %id {data}", + id = const ID, + data = in(reg) data, + }; + } } diff --git a/crates/spirv-std/src/byte_addressable_buffer.rs b/crates/spirv-std/src/byte_addressable_buffer.rs index f4c6dba491..4a1949c713 100644 --- a/crates/spirv-std/src/byte_addressable_buffer.rs +++ b/crates/spirv-std/src/byte_addressable_buffer.rs @@ -11,15 +11,17 @@ unsafe fn buffer_load_intrinsic( // FIXME(eddyb) should be `usize`. offset: u32, ) -> T { - // NOTE(eddyb) this doesn't work with `rustc_codegen_spirv` and is only here - // for explanatory purposes, and to cause some kind of verbose error if - // `#[spirv(buffer_load_intrinsic)]` fails to replace calls to this function. - buffer - .as_ptr() - .cast::() - .add(offset as usize) - .cast::() - .read() + unsafe { + // NOTE(eddyb) this doesn't work with `rustc_codegen_spirv` and is only here + // for explanatory purposes, and to cause some kind of verbose error if + // `#[spirv(buffer_load_intrinsic)]` fails to replace calls to this function. + buffer + .as_ptr() + .cast::() + .add(offset as usize) + .cast::() + .read() + } } #[spirv(buffer_store_intrinsic)] @@ -32,15 +34,17 @@ unsafe fn buffer_store_intrinsic( offset: u32, value: T, ) { - // NOTE(eddyb) this doesn't work with `rustc_codegen_spirv` and is only here - // for explanatory purposes, and to cause some kind of verbose error if - // `#[spirv(buffer_store_intrinsic)]` fails to replace calls to this function. - buffer - .as_mut_ptr() - .cast::() - .add(offset as usize) - .cast::() - .write(value); + unsafe { + // NOTE(eddyb) this doesn't work with `rustc_codegen_spirv` and is only here + // for explanatory purposes, and to cause some kind of verbose error if + // `#[spirv(buffer_store_intrinsic)]` fails to replace calls to this function. + buffer + .as_mut_ptr() + .cast::() + .add(offset as usize) + .cast::() + .write(value); + } } /// `ByteAddressableBuffer` is a view to an untyped blob of data, allowing @@ -94,7 +98,7 @@ impl<'a> ByteAddressableBuffer<&'a [u32]> { /// See [`Self`]. pub unsafe fn load(&self, byte_index: u32) -> T { bounds_check::(self.data, byte_index); - buffer_load_intrinsic(self.data, byte_index) + unsafe { buffer_load_intrinsic(self.data, byte_index) } } /// Loads an arbitrary type from the buffer. `byte_index` must be a @@ -103,7 +107,7 @@ impl<'a> ByteAddressableBuffer<&'a [u32]> { /// # Safety /// See [`Self`]. Additionally, bounds or alignment checking is not performed. pub unsafe fn load_unchecked(&self, byte_index: u32) -> T { - buffer_load_intrinsic(self.data, byte_index) + unsafe { buffer_load_intrinsic(self.data, byte_index) } } } @@ -127,7 +131,7 @@ impl<'a> ByteAddressableBuffer<&'a mut [u32]> { /// See [`Self`]. #[inline] pub unsafe fn load(&self, byte_index: u32) -> T { - self.as_ref().load(byte_index) + unsafe { self.as_ref().load(byte_index) } } /// Loads an arbitrary type from the buffer. `byte_index` must be a @@ -137,7 +141,7 @@ impl<'a> ByteAddressableBuffer<&'a mut [u32]> { /// See [`Self`]. Additionally, bounds or alignment checking is not performed. #[inline] pub unsafe fn load_unchecked(&self, byte_index: u32) -> T { - self.as_ref().load_unchecked(byte_index) + unsafe { self.as_ref().load_unchecked(byte_index) } } /// Stores an arbitrary type into the buffer. `byte_index` must be a @@ -147,7 +151,9 @@ impl<'a> ByteAddressableBuffer<&'a mut [u32]> { /// See [`Self`]. pub unsafe fn store(&mut self, byte_index: u32, value: T) { bounds_check::(self.data, byte_index); - buffer_store_intrinsic(self.data, byte_index, value); + unsafe { + buffer_store_intrinsic(self.data, byte_index, value); + } } /// Stores an arbitrary type into the buffer. `byte_index` must be a @@ -156,6 +162,8 @@ impl<'a> ByteAddressableBuffer<&'a mut [u32]> { /// # Safety /// See [`Self`]. Additionally, bounds or alignment checking is not performed. pub unsafe fn store_unchecked(&mut self, byte_index: u32, value: T) { - buffer_store_intrinsic(self.data, byte_index, value); + unsafe { + buffer_store_intrinsic(self.data, byte_index, value); + } } } diff --git a/crates/spirv-std/src/image.rs b/crates/spirv-std/src/image.rs index e37fe641df..154f769ec5 100644 --- a/crates/spirv-std/src/image.rs +++ b/crates/spirv-std/src/image.rs @@ -733,14 +733,16 @@ impl< ) where I: Integer, { - asm! { - "%image = OpLoad _ {this}", - "%coordinate = OpLoad _ {coordinate}", - "%texels = OpLoad _ {texels}", - "OpImageWrite %image %coordinate %texels", - this = in(reg) self, - coordinate = in(reg) &coordinate, - texels = in(reg) &texels, + unsafe { + asm! { + "%image = OpLoad _ {this}", + "%coordinate = OpLoad _ {coordinate}", + "%texels = OpLoad _ {texels}", + "OpImageWrite %image %coordinate %texels", + this = in(reg) self, + coordinate = in(reg) &coordinate, + texels = in(reg) &texels, + } } } } @@ -802,14 +804,16 @@ impl< ) where I: Integer, { - asm! { - "%image = OpLoad _ {this}", - "%coordinate = OpLoad _ {coordinate}", - "%texels = OpLoad _ {texels}", - "OpImageWrite %image %coordinate %texels", - this = in(reg) self, - coordinate = in(reg) &coordinate, - texels = in(reg) &texels, + unsafe { + asm! { + "%image = OpLoad _ {this}", + "%coordinate = OpLoad _ {coordinate}", + "%texels = OpLoad _ {texels}", + "OpImageWrite %image %coordinate %texels", + this = in(reg) self, + coordinate = in(reg) &coordinate, + texels = in(reg) &texels, + } } } } diff --git a/crates/spirv-std/src/lib.rs b/crates/spirv-std/src/lib.rs index 61c84dfc47..4a4774823c 100644 --- a/crates/spirv-std/src/lib.rs +++ b/crates/spirv-std/src/lib.rs @@ -42,7 +42,6 @@ clippy::map_err_ignore, clippy::map_flatten, clippy::map_unwrap_or, - clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wildcard_for_single_variants, clippy::mem_forget, diff --git a/crates/spirv-std/src/ray_tracing.rs b/crates/spirv-std/src/ray_tracing.rs index f24de07bab..c35846eeac 100644 --- a/crates/spirv-std/src/ray_tracing.rs +++ b/crates/spirv-std/src/ray_tracing.rs @@ -27,16 +27,18 @@ impl AccelerationStructure { #[doc(alias = "OpConvertUToAccelerationStructureKHR")] #[inline] pub unsafe fn from_u64(id: u64) -> AccelerationStructure { - // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. - let mut result_slot = core::mem::MaybeUninit::uninit(); - asm! { - "%ret = OpTypeAccelerationStructureKHR", - "%result = OpConvertUToAccelerationStructureKHR %ret {id}", - "OpStore {result_slot} %result", - id = in(reg) id, - result_slot = in(reg) result_slot.as_mut_ptr(), + unsafe { + // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. + let mut result_slot = core::mem::MaybeUninit::uninit(); + asm! { + "%ret = OpTypeAccelerationStructureKHR", + "%result = OpConvertUToAccelerationStructureKHR %ret {id}", + "OpStore {result_slot} %result", + id = in(reg) id, + result_slot = in(reg) result_slot.as_mut_ptr(), + } + result_slot.assume_init() } - result_slot.assume_init() } /// Converts a vector of two 32 bit integers into an [`AccelerationStructure`]. @@ -46,17 +48,19 @@ impl AccelerationStructure { #[doc(alias = "OpConvertUToAccelerationStructureKHR")] #[inline] pub unsafe fn from_vec(id: impl Vector) -> AccelerationStructure { - // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. - let mut result_slot = core::mem::MaybeUninit::uninit(); - asm! { - "%ret = OpTypeAccelerationStructureKHR", - "%id = OpLoad _ {id}", - "%result = OpConvertUToAccelerationStructureKHR %ret %id", - "OpStore {result_slot} %result", - id = in(reg) &id, - result_slot = in(reg) result_slot.as_mut_ptr(), + unsafe { + // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. + let mut result_slot = core::mem::MaybeUninit::uninit(); + asm! { + "%ret = OpTypeAccelerationStructureKHR", + "%id = OpLoad _ {id}", + "%result = OpConvertUToAccelerationStructureKHR %ret %id", + "OpStore {result_slot} %result", + id = in(reg) &id, + result_slot = in(reg) result_slot.as_mut_ptr(), + } + result_slot.assume_init() } - result_slot.assume_init() } #[spirv_std_macros::gpu_only] @@ -103,33 +107,35 @@ impl AccelerationStructure { ray_tmax: f32, payload: &mut T, ) { - asm! { - "%acceleration_structure = OpLoad _ {acceleration_structure}", - "%ray_origin = OpLoad _ {ray_origin}", - "%ray_direction = OpLoad _ {ray_direction}", - "OpTraceRayKHR \ - %acceleration_structure \ - {ray_flags} \ - {cull_mask} \ - {sbt_offset} \ - {sbt_stride} \ - {miss_index} \ - %ray_origin \ - {ray_tmin} \ - %ray_direction \ - {ray_tmax} \ - {payload}", - acceleration_structure = in(reg) self, - ray_flags = in(reg) ray_flags.bits(), - cull_mask = in(reg) cull_mask, - sbt_offset = in(reg) sbt_offset, - sbt_stride = in(reg) sbt_stride, - miss_index = in(reg) miss_index, - ray_origin = in(reg) &ray_origin, - ray_tmin = in(reg) ray_tmin, - ray_direction = in(reg) &ray_direction, - ray_tmax = in(reg) ray_tmax, - payload = in(reg) payload, + unsafe { + asm! { + "%acceleration_structure = OpLoad _ {acceleration_structure}", + "%ray_origin = OpLoad _ {ray_origin}", + "%ray_direction = OpLoad _ {ray_direction}", + "OpTraceRayKHR \ + %acceleration_structure \ + {ray_flags} \ + {cull_mask} \ + {sbt_offset} \ + {sbt_stride} \ + {miss_index} \ + %ray_origin \ + {ray_tmin} \ + %ray_direction \ + {ray_tmax} \ + {payload}", + acceleration_structure = in(reg) self, + ray_flags = in(reg) ray_flags.bits(), + cull_mask = in(reg) cull_mask, + sbt_offset = in(reg) sbt_offset, + sbt_stride = in(reg) sbt_stride, + miss_index = in(reg) miss_index, + ray_origin = in(reg) &ray_origin, + ray_tmin = in(reg) ray_tmin, + ray_direction = in(reg) &ray_direction, + ray_tmax = in(reg) ray_tmax, + payload = in(reg) payload, + } } } } @@ -259,27 +265,29 @@ impl RayQuery { ray_direction: impl Vector, ray_tmax: f32, ) { - asm! { - "%acceleration_structure = OpLoad _ {acceleration_structure}", - "%origin = OpLoad _ {ray_origin}", - "%direction = OpLoad _ {ray_direction}", - "OpRayQueryInitializeKHR \ - {ray_query} \ - %acceleration_structure \ - {ray_flags} \ - {cull_mask} \ - %origin \ - {ray_tmin} \ - %direction \ - {ray_tmax}", - ray_query = in(reg) self, - acceleration_structure = in(reg) acceleration_structure, - ray_flags = in(reg) ray_flags.bits(), - cull_mask = in(reg) cull_mask, - ray_origin = in(reg) &ray_origin, - ray_tmin = in(reg) ray_tmin, - ray_direction = in(reg) &ray_direction, - ray_tmax = in(reg) ray_tmax, + unsafe { + asm! { + "%acceleration_structure = OpLoad _ {acceleration_structure}", + "%origin = OpLoad _ {ray_origin}", + "%direction = OpLoad _ {ray_direction}", + "OpRayQueryInitializeKHR \ + {ray_query} \ + %acceleration_structure \ + {ray_flags} \ + {cull_mask} \ + %origin \ + {ray_tmin} \ + %direction \ + {ray_tmax}", + ray_query = in(reg) self, + acceleration_structure = in(reg) acceleration_structure, + ray_flags = in(reg) ray_flags.bits(), + cull_mask = in(reg) cull_mask, + ray_origin = in(reg) &ray_origin, + ray_tmin = in(reg) ray_tmin, + ray_direction = in(reg) &ray_direction, + ray_tmax = in(reg) ray_tmax, + } } } @@ -290,17 +298,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryProceedKHR")] #[inline] pub unsafe fn proceed(&self) -> bool { - let mut result = false; + unsafe { + let mut result = false; + + asm! { + "%bool = OpTypeBool", + "%result = OpRayQueryProceedKHR %bool {ray_query}", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } - asm! { - "%bool = OpTypeBool", - "%result = OpRayQueryProceedKHR %bool {ray_query}", - "OpStore {result} %result", - ray_query = in(reg) self, - result = in(reg) &mut result, + result } - - result } /// Terminates further execution of a ray query; further calls to @@ -311,7 +321,7 @@ impl RayQuery { #[doc(alias = "OpRayQueryTerminateKHR")] #[inline] pub unsafe fn terminate(&self) { - asm!("OpRayQueryTerminateKHR {}", in(reg) self) + unsafe { asm!("OpRayQueryTerminateKHR {}", in(reg) self) } } /// Confirms a triangle intersection to be included in the determination @@ -325,7 +335,7 @@ impl RayQuery { #[doc(alias = "OpRayQueryConfirmIntersectionKHR")] #[inline] pub unsafe fn confirm_intersection(&self) { - asm!("OpRayQueryConfirmIntersectionKHR {}", in(reg) self) + unsafe { asm!("OpRayQueryConfirmIntersectionKHR {}", in(reg) self) } } /// Returns the type of the current candidate intersection. @@ -335,20 +345,22 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionTypeKHR")] #[inline] pub unsafe fn get_candidate_intersection_type(&self) -> CandidateIntersection { - let result: u32; - - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 0", - "{result} = OpRayQueryGetIntersectionTypeKHR %u32 {ray_query} %intersection", - ray_query = in(reg) self, - result = out(reg) result, - } + unsafe { + let result: u32; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 0", + "{result} = OpRayQueryGetIntersectionTypeKHR %u32 {ray_query} %intersection", + ray_query = in(reg) self, + result = out(reg) result, + } - match result { - 0 => CandidateIntersection::Triangle, - 1 => CandidateIntersection::AABB, - _ => CandidateIntersection::Triangle, + match result { + 0 => CandidateIntersection::Triangle, + 1 => CandidateIntersection::AABB, + _ => CandidateIntersection::Triangle, + } } } @@ -357,21 +369,23 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionTypeKHR")] #[inline] pub unsafe fn get_committed_intersection_type(&self) -> CommittedIntersection { - let result: u32; - - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 1", - "{result} = OpRayQueryGetIntersectionTypeKHR %u32 {ray_query} %intersection", - ray_query = in(reg) self, - result = out(reg) result, - } + unsafe { + let result: u32; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 1", + "{result} = OpRayQueryGetIntersectionTypeKHR %u32 {ray_query} %intersection", + ray_query = in(reg) self, + result = out(reg) result, + } - match result { - 0 => CommittedIntersection::None, - 1 => CommittedIntersection::Triangle, - 2 => CommittedIntersection::Generated, - _ => CommittedIntersection::None, + match result { + 0 => CommittedIntersection::None, + 1 => CommittedIntersection::Triangle, + 2 => CommittedIntersection::Generated, + _ => CommittedIntersection::None, + } } } @@ -380,16 +394,18 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetRayTMinKHR")] #[inline] pub unsafe fn get_ray_t_min(&self) -> f32 { - let result; + unsafe { + let result; + + asm! { + "%f32 = OpTypeFloat 32", + "{result} = OpRayQueryGetRayTMinKHR %f32 {ray_query}", + ray_query = in(reg) self, + result = out(reg) result, + } - asm! { - "%f32 = OpTypeFloat 32", - "{result} = OpRayQueryGetRayTMinKHR %f32 {ray_query}", - ray_query = in(reg) self, - result = out(reg) result, + result } - - result } /// Returns the "Ray Flags" value used by the ray query. @@ -397,15 +413,17 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetRayFlagsKHR")] #[inline] pub unsafe fn get_ray_flags(&self) -> RayFlags { - let result; + unsafe { + let result; - asm! { - "{result} = OpRayQueryGetRayFlagsKHR typeof{result} {ray_query}", - ray_query = in(reg) self, - result = out(reg) result, - } + asm! { + "{result} = OpRayQueryGetRayFlagsKHR typeof{result} {ray_query}", + ray_query = in(reg) self, + result = out(reg) result, + } - RayFlags::from_bits_truncate(result) + RayFlags::from_bits_truncate(result) + } } /// Gets the "T" value for the current or previous intersection considered @@ -418,17 +436,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionTKHR")] #[inline] pub unsafe fn get_candidate_intersection_t(&self) -> f32 { - let result; + unsafe { + let result; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 0", + "{result} = OpRayQueryGetIntersectionTKHR typeof{result} {ray_query} %intersection", + ray_query = in(reg) self, + result = out(reg) result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 0", - "{result} = OpRayQueryGetIntersectionTKHR typeof{result} {ray_query} %intersection", - ray_query = in(reg) self, - result = out(reg) result, + result } - - result } /// Gets the "T" value for the current or previous intersection considered @@ -442,17 +462,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionTKHR")] #[inline] pub unsafe fn get_committed_intersection_t(&self) -> f32 { - let result; + unsafe { + let result; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 1", + "{result} = OpRayQueryGetIntersectionTKHR typeof{result} {ray_query} %intersection", + ray_query = in(reg) self, + result = out(reg) result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 1", - "{result} = OpRayQueryGetIntersectionTKHR typeof{result} {ray_query} %intersection", - ray_query = in(reg) self, - result = out(reg) result, + result } - - result } /// Gets the custom index of the instance for the current intersection @@ -463,17 +485,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionInstanceCustomIndexKHR")] #[inline] pub unsafe fn get_candidate_intersection_instance_custom_index(&self) -> u32 { - let result; + unsafe { + let result; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 0", + "{result} = OpRayQueryGetIntersectionInstanceCustomIndexKHR %u32 {ray_query} %intersection", + ray_query = in(reg) self, + result = out(reg) result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 0", - "{result} = OpRayQueryGetIntersectionInstanceCustomIndexKHR %u32 {ray_query} %intersection", - ray_query = in(reg) self, - result = out(reg) result, + result } - - result } /// Gets the custom index of the instance for the current intersection @@ -487,17 +511,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionInstanceCustomIndexKHR")] #[inline] pub unsafe fn get_committed_intersection_instance_custom_index(&self) -> u32 { - let result; + unsafe { + let result; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 1", + "{result} = OpRayQueryGetIntersectionInstanceCustomIndexKHR %u32 {ray_query} %intersection", + ray_query = in(reg) self, + result = out(reg) result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 1", - "{result} = OpRayQueryGetIntersectionInstanceCustomIndexKHR %u32 {ray_query} %intersection", - ray_query = in(reg) self, - result = out(reg) result, + result } - - result } /// Gets the id of the instance for the current intersection considered in a @@ -508,17 +534,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionInstanceIdKHR")] #[inline] pub unsafe fn get_candidate_intersection_instance_id(&self) -> u32 { - let result; + unsafe { + let result; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 0", + "{result} = OpRayQueryGetIntersectionInstanceIdKHR %u32 {ray_query} %intersection", + ray_query = in(reg) self, + result = out(reg) result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 0", - "{result} = OpRayQueryGetIntersectionInstanceIdKHR %u32 {ray_query} %intersection", - ray_query = in(reg) self, - result = out(reg) result, + result } - - result } /// Gets the id of the instance for the current intersection considered in a @@ -532,17 +560,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionInstanceIdKHR")] #[inline] pub unsafe fn get_committed_intersection_instance_id(&self) -> u32 { - let result; + unsafe { + let result; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 1", + "{result} = OpRayQueryGetIntersectionInstanceIdKHR %u32 {ray_query} %intersection", + ray_query = in(reg) self, + result = out(reg) result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 1", - "{result} = OpRayQueryGetIntersectionInstanceIdKHR %u32 {ray_query} %intersection", - ray_query = in(reg) self, - result = out(reg) result, + result } - - result } /// Gets the shader binding table record offset for the current intersection @@ -553,17 +583,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR")] #[inline] pub unsafe fn get_candidate_intersection_shader_binding_table_record_offset(&self) -> u32 { - let result; + unsafe { + let result; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 0", + "{result} = OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR %u32 {ray_query} %intersection", + ray_query = in(reg) self, + result = out(reg) result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 0", - "{result} = OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR %u32 {ray_query} %intersection", - ray_query = in(reg) self, - result = out(reg) result, + result } - - result } /// Gets the shader binding table record offset for the current intersection @@ -577,17 +609,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR")] #[inline] pub unsafe fn get_committed_intersection_shader_binding_table_record_offset(&self) -> u32 { - let result; + unsafe { + let result; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 1", + "{result} = OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR %u32 {ray_query} %intersection", + ray_query = in(reg) self, + result = out(reg) result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 1", - "{result} = OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR %u32 {ray_query} %intersection", - ray_query = in(reg) self, - result = out(reg) result, + result } - - result } /// Gets the geometry index for the current intersection considered in a @@ -598,17 +632,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionGeometryIndexKHR")] #[inline] pub unsafe fn get_candidate_intersection_geometry_index(&self) -> u32 { - let result; + unsafe { + let result; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 0", + "{result} = OpRayQueryGetIntersectionGeometryIndexKHR %u32 {ray_query} %intersection", + ray_query = in(reg) self, + result = out(reg) result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 0", - "{result} = OpRayQueryGetIntersectionGeometryIndexKHR %u32 {ray_query} %intersection", - ray_query = in(reg) self, - result = out(reg) result, + result } - - result } /// Gets the geometry index for the current intersection considered in a @@ -622,17 +658,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionGeometryIndexKHR")] #[inline] pub unsafe fn get_committed_intersection_geometry_index(&self) -> u32 { - let result; + unsafe { + let result; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 1", + "{result} = OpRayQueryGetIntersectionGeometryIndexKHR %u32 {ray_query} %intersection", + ray_query = in(reg) self, + result = out(reg) result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 1", - "{result} = OpRayQueryGetIntersectionGeometryIndexKHR %u32 {ray_query} %intersection", - ray_query = in(reg) self, - result = out(reg) result, + result } - - result } /// Gets the primitive index for the current intersection considered in a @@ -643,17 +681,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionPrimitiveIndexKHR")] #[inline] pub unsafe fn get_candidate_intersection_primitive_index(&self) -> u32 { - let result; + unsafe { + let result; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 0", + "{result} = OpRayQueryGetIntersectionPrimitiveIndexKHR %u32 {ray_query} %intersection", + ray_query = in(reg) self, + result = out(reg) result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 0", - "{result} = OpRayQueryGetIntersectionPrimitiveIndexKHR %u32 {ray_query} %intersection", - ray_query = in(reg) self, - result = out(reg) result, + result } - - result } /// Gets the primitive index for the current intersection considered in a @@ -667,17 +707,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionPrimitiveIndexKHR")] #[inline] pub unsafe fn get_committed_intersection_primitive_index(&self) -> u32 { - let result; + unsafe { + let result; + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 1", + "{result} = OpRayQueryGetIntersectionPrimitiveIndexKHR %u32 {ray_query} %intersection", + ray_query = in(reg) self, + result = out(reg) result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 1", - "{result} = OpRayQueryGetIntersectionPrimitiveIndexKHR %u32 {ray_query} %intersection", - ray_query = in(reg) self, - result = out(reg) result, + result } - - result } /// Gets the second and third barycentric coordinates of the current @@ -690,18 +732,20 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionBarycentricsKHR")] #[inline] pub unsafe fn get_candidate_intersection_barycentrics>(&self) -> V { - let mut result = Default::default(); + unsafe { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 0", + "%result = OpRayQueryGetIntersectionBarycentricsKHR typeof*{result} {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 0", - "%result = OpRayQueryGetIntersectionBarycentricsKHR typeof*{result} {ray_query} %intersection", - "OpStore {result} %result", - ray_query = in(reg) self, - result = in(reg) &mut result, + result } - - result } /// Gets the second and third barycentric coordinates of the current @@ -716,18 +760,20 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionBarycentricsKHR")] #[inline] pub unsafe fn get_committed_intersection_barycentrics>(&self) -> V { - let mut result = Default::default(); + unsafe { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 1", + "%result = OpRayQueryGetIntersectionBarycentricsKHR typeof*{result} {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 1", - "%result = OpRayQueryGetIntersectionBarycentricsKHR typeof*{result} {ray_query} %intersection", - "OpStore {result} %result", - ray_query = in(reg) self, - result = in(reg) &mut result, + result } - - result } /// Returns whether the current intersection considered in a ray query was with @@ -740,19 +786,21 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionFrontFaceKHR")] #[inline] pub unsafe fn get_candidate_intersection_front_face(&self) -> bool { - let mut result = false; + unsafe { + let mut result = false; + + asm! { + "%bool = OpTypeBool", + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 0", + "%result = OpRayQueryGetIntersectionFrontFaceKHR %bool {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } - asm! { - "%bool = OpTypeBool", - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 0", - "%result = OpRayQueryGetIntersectionFrontFaceKHR %bool {ray_query} %intersection", - "OpStore {result} %result", - ray_query = in(reg) self, - result = in(reg) &mut result, + result } - - result } /// Returns whether the current intersection considered in a ray query was with @@ -767,19 +815,21 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionFrontFaceKHR")] #[inline] pub unsafe fn get_committed_intersection_front_face(&self) -> bool { - let mut result = false; + unsafe { + let mut result = false; + + asm! { + "%bool = OpTypeBool", + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 1", + "%result = OpRayQueryGetIntersectionFrontFaceKHR %bool {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } - asm! { - "%bool = OpTypeBool", - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 1", - "%result = OpRayQueryGetIntersectionFrontFaceKHR %bool {ray_query} %intersection", - "OpStore {result} %result", - ray_query = in(reg) self, - result = in(reg) &mut result, + result } - - result } /// Returns whether a candidate intersection considered in a ray query was with @@ -788,17 +838,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR")] #[inline] pub unsafe fn get_intersection_candidate_aabb_opaque(&self) -> bool { - let mut result = false; + unsafe { + let mut result = false; + + asm! { + "%bool = OpTypeBool", + "%result = OpRayQueryGetIntersectionCandidateAABBOpaqueKHR %bool {ray_query}", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } - asm! { - "%bool = OpTypeBool", - "%result = OpRayQueryGetIntersectionCandidateAABBOpaqueKHR %bool {ray_query}", - "OpStore {result} %result", - ray_query = in(reg) self, - result = in(reg) &mut result, + result } - - result } /// Gets the object-space ray direction for the current intersection considered @@ -809,18 +861,20 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionObjectRayDirectionKHR")] #[inline] pub unsafe fn get_candidate_intersection_object_ray_direction>(&self) -> V { - let mut result = Default::default(); + unsafe { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 0", + "%result = OpRayQueryGetIntersectionObjectRayDirectionKHR typeof*{result} {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 0", - "%result = OpRayQueryGetIntersectionObjectRayDirectionKHR typeof*{result} {ray_query} %intersection", - "OpStore {result} %result", - ray_query = in(reg) self, - result = in(reg) &mut result, + result } - - result } /// Gets the object-space ray direction for the current intersection considered @@ -834,18 +888,20 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionObjectRayDirectionKHR")] #[inline] pub unsafe fn get_committed_intersection_object_ray_direction>(&self) -> V { - let mut result = Default::default(); + unsafe { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 1", + "%result = OpRayQueryGetIntersectionObjectRayDirectionKHR typeof*{result} {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 1", - "%result = OpRayQueryGetIntersectionObjectRayDirectionKHR typeof*{result} {ray_query} %intersection", - "OpStore {result} %result", - ray_query = in(reg) self, - result = in(reg) &mut result, + result } - - result } /// Gets the object-space ray origin for the current intersection considered in @@ -856,18 +912,20 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionObjectRayOriginKHR")] #[inline] pub unsafe fn get_candidate_intersection_object_ray_origin>(&self) -> V { - let mut result = Default::default(); + unsafe { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 0", + "%result = OpRayQueryGetIntersectionObjectRayOriginKHR typeof*{result} {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 0", - "%result = OpRayQueryGetIntersectionObjectRayOriginKHR typeof*{result} {ray_query} %intersection", - "OpStore {result} %result", - ray_query = in(reg) self, - result = in(reg) &mut result, + result } - - result } /// Gets the object-space ray origin for the current intersection considered in @@ -881,18 +939,20 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionObjectRayOriginKHR")] #[inline] pub unsafe fn get_committed_intersection_object_ray_origin>(&self) -> V { - let mut result = Default::default(); + unsafe { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%intersection = OpConstant %u32 1", + "%result = OpRayQueryGetIntersectionObjectRayOriginKHR typeof*{result} {ray_query} %intersection", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%intersection = OpConstant %u32 1", - "%result = OpRayQueryGetIntersectionObjectRayOriginKHR typeof*{result} {ray_query} %intersection", - "OpStore {result} %result", - ray_query = in(reg) self, - result = in(reg) &mut result, + result } - - result } /// Gets the world-space direction for the ray traced in a ray query. @@ -900,17 +960,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetWorldRayDirectionKHR")] #[inline] pub unsafe fn get_world_ray_direction>(&self) -> V { - let mut result = Default::default(); + unsafe { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%result = OpRayQueryGetWorldRayDirectionKHR typeof*{result} {ray_query}", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%result = OpRayQueryGetWorldRayDirectionKHR typeof*{result} {ray_query}", - "OpStore {result} %result", - ray_query = in(reg) self, - result = in(reg) &mut result, + result } - - result } /// Gets the world-space origin for the ray traced in a ray query. @@ -918,17 +980,19 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetWorldRayOriginKHR")] #[inline] pub unsafe fn get_world_ray_origin>(&self) -> V { - let mut result = Default::default(); + unsafe { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%result = OpRayQueryGetWorldRayOriginKHR typeof*{result} {ray_query}", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%result = OpRayQueryGetWorldRayOriginKHR typeof*{result} {ray_query}", - "OpStore {result} %result", - ray_query = in(reg) self, - result = in(reg) &mut result, + result } - - result } /// Gets a matrix that transforms values to world-space from the object-space of @@ -939,26 +1003,28 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionObjectToWorldKHR")] #[inline] pub unsafe fn get_candidate_intersection_object_to_world>(&self) -> [V; 4] { - let mut result = Default::default(); + unsafe { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%f32 = OpTypeFloat 32", + "%f32x3 = OpTypeVector %f32 3", + "%f32x3x4 = OpTypeMatrix %f32x3 4", + "%intersection = OpConstant %u32 0", + "%matrix = OpRayQueryGetIntersectionObjectToWorldKHR %f32x3x4 {ray_query} %intersection", + "%col0 = OpCompositeExtract %f32x3 %matrix 0", + "%col1 = OpCompositeExtract %f32x3 %matrix 1", + "%col2 = OpCompositeExtract %f32x3 %matrix 2", + "%col3 = OpCompositeExtract %f32x3 %matrix 3", + "%result = OpCompositeConstruct typeof*{result} %col0 %col1 %col2 %col3", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } - asm! { - "%u32 = OpTypeInt 32 0", - "%f32 = OpTypeFloat 32", - "%f32x3 = OpTypeVector %f32 3", - "%f32x3x4 = OpTypeMatrix %f32x3 4", - "%intersection = OpConstant %u32 0", - "%matrix = OpRayQueryGetIntersectionObjectToWorldKHR %f32x3x4 {ray_query} %intersection", - "%col0 = OpCompositeExtract %f32x3 %matrix 0", - "%col1 = OpCompositeExtract %f32x3 %matrix 1", - "%col2 = OpCompositeExtract %f32x3 %matrix 2", - "%col3 = OpCompositeExtract %f32x3 %matrix 3", - "%result = OpCompositeConstruct typeof*{result} %col0 %col1 %col2 %col3", - "OpStore {result} %result", - ray_query = in(reg) self, - result = in(reg) &mut result, + result } - - result } /// Gets a matrix that transforms values to world-space from the object-space of @@ -972,25 +1038,27 @@ impl RayQuery { #[doc(alias = "OpRayQueryGetIntersectionObjectToWorldKHR")] #[inline] pub unsafe fn get_committed_intersection_object_to_world>(&self) -> [V; 4] { - let mut result = Default::default(); - - asm! { - "%u32 = OpTypeInt 32 0", - "%f32 = OpTypeFloat 32", - "%f32x3 = OpTypeVector %f32 3", - "%f32x3x4 = OpTypeMatrix %f32x3 4", - "%intersection = OpConstant %u32 1", - "%matrix = OpRayQueryGetIntersectionObjectToWorldKHR %f32x3x4 {ray_query} %intersection", - "%col0 = OpCompositeExtract %f32x3 %matrix 0", - "%col1 = OpCompositeExtract %f32x3 %matrix 1", - "%col2 = OpCompositeExtract %f32x3 %matrix 2", - "%col3 = OpCompositeExtract %f32x3 %matrix 3", - "%result = OpCompositeConstruct typeof*{result} %col0 %col1 %col2 %col3", - "OpStore {result} %result", - ray_query = in(reg) self, - result = in(reg) &mut result, - } - - result + unsafe { + let mut result = Default::default(); + + asm! { + "%u32 = OpTypeInt 32 0", + "%f32 = OpTypeFloat 32", + "%f32x3 = OpTypeVector %f32 3", + "%f32x3x4 = OpTypeMatrix %f32x3 4", + "%intersection = OpConstant %u32 1", + "%matrix = OpRayQueryGetIntersectionObjectToWorldKHR %f32x3x4 {ray_query} %intersection", + "%col0 = OpCompositeExtract %f32x3 %matrix 0", + "%col1 = OpCompositeExtract %f32x3 %matrix 1", + "%col2 = OpCompositeExtract %f32x3 %matrix 2", + "%col3 = OpCompositeExtract %f32x3 %matrix 3", + "%result = OpCompositeConstruct typeof*{result} %col0 %col1 %col2 %col3", + "OpStore {result} %result", + ray_query = in(reg) self, + result = in(reg) &mut result, + } + + result + } } } diff --git a/crates/spirv-std/src/runtime_array.rs b/crates/spirv-std/src/runtime_array.rs index 5d5df01dfb..7ce0587e4a 100644 --- a/crates/spirv-std/src/runtime_array.rs +++ b/crates/spirv-std/src/runtime_array.rs @@ -30,16 +30,18 @@ impl RuntimeArray { /// and lead to UB. #[spirv_std_macros::gpu_only] pub unsafe fn index(&self, index: usize) -> &T { - // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. - let mut result_slot = core::mem::MaybeUninit::uninit(); - asm! { - "%result = OpAccessChain _ {arr} {index}", - "OpStore {result_slot} %result", - arr = in(reg) self, - index = in(reg) index, - result_slot = in(reg) result_slot.as_mut_ptr(), + unsafe { + // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. + let mut result_slot = core::mem::MaybeUninit::uninit(); + asm! { + "%result = OpAccessChain _ {arr} {index}", + "OpStore {result_slot} %result", + arr = in(reg) self, + index = in(reg) index, + result_slot = in(reg) result_slot.as_mut_ptr(), + } + result_slot.assume_init() } - result_slot.assume_init() } /// Index the array, returning a mutable reference to an element. Unfortunately, because the @@ -51,15 +53,17 @@ impl RuntimeArray { /// and lead to UB. #[spirv_std_macros::gpu_only] pub unsafe fn index_mut(&mut self, index: usize) -> &mut T { - // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. - let mut result_slot = core::mem::MaybeUninit::uninit(); - asm! { - "%result = OpAccessChain _ {arr} {index}", - "OpStore {result_slot} %result", - arr = in(reg) self, - index = in(reg) index, - result_slot = in(reg) result_slot.as_mut_ptr(), + unsafe { + // FIXME(eddyb) `let mut result = T::default()` uses (for `asm!`), with this. + let mut result_slot = core::mem::MaybeUninit::uninit(); + asm! { + "%result = OpAccessChain _ {arr} {index}", + "OpStore {result_slot} %result", + arr = in(reg) self, + index = in(reg) index, + result_slot = in(reg) result_slot.as_mut_ptr(), + } + result_slot.assume_init() } - result_slot.assume_init() } } diff --git a/examples/runners/ash/src/main.rs b/examples/runners/ash/src/main.rs index 7a006574ca..0e67ec7c22 100644 --- a/examples/runners/ash/src/main.rs +++ b/examples/runners/ash/src/main.rs @@ -36,7 +36,6 @@ clippy::map_err_ignore, clippy::map_flatten, clippy::map_unwrap_or, - clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wildcard_for_single_variants, clippy::mem_forget, @@ -104,6 +103,17 @@ pub struct Options { } pub fn main() { + // Hack: spirv_builder builds into a custom directory if running under cargo, to not + // deadlock, and the default target directory if not. However, packages like `proc-macro2` + // have different configurations when being built here vs. when building + // rustc_codegen_spirv normally, so we *want* to build into a separate target directory, to + // not have to rebuild half the crate graph every time we run. So, pretend we're running + // under cargo by setting these environment variables. + unsafe { + std::env::set_var("OUT_DIR", env!("OUT_DIR")); + std::env::set_var("PROFILE", env!("PROFILE")); + } + let options = Options::parse(); let shaders = compile_shaders(); @@ -128,18 +138,21 @@ pub fn main() { for SpvFile { name, data } in shaders { ctx.insert_shader_module(name, &data); } - ctx.build_pipelines(vk::PipelineCache::null(), vec![( - // HACK(eddyb) used to be `module: "sky_shader"` but we need `multimodule` - // for `debugPrintf` instrumentation to work (see `compile_shaders`). - VertexShaderEntryPoint { - module: "sky_shader::main_vs".into(), - entry_point: "main_vs".into(), - }, - FragmentShaderEntryPoint { - module: "sky_shader::main_fs".into(), - entry_point: "main_fs".into(), - }, - )]); + ctx.build_pipelines( + vk::PipelineCache::null(), + vec![( + // HACK(eddyb) used to be `module: "sky_shader"` but we need `multimodule` + // for `debugPrintf` instrumentation to work (see `compile_shaders`). + VertexShaderEntryPoint { + module: "sky_shader::main_vs".into(), + entry_point: "main_vs".into(), + }, + FragmentShaderEntryPoint { + module: "sky_shader::main_fs".into(), + entry_point: "main_fs".into(), + }, + )], + ); let (compiler_sender, compiler_receiver) = sync_channel(1); @@ -148,7 +161,7 @@ pub fn main() { #[allow(deprecated)] event_loop .run(move |event, event_loop_window_target| match event { - Event::AboutToWait { .. } => { + Event::AboutToWait => { match compiler_receiver.try_recv() { Err(TryRecvError::Empty) => { if ctx.rendering_paused { @@ -236,15 +249,6 @@ pub fn main() { } pub fn compile_shaders() -> Vec { - // Hack: spirv_builder builds into a custom directory if running under cargo, to not - // deadlock, and the default target directory if not. However, packages like `proc-macro2` - // have different configurations when being built here vs. when building - // rustc_codegen_spirv normally, so we *want* to build into a separate target directory, to - // not have to rebuild half the crate graph every time we run. So, pretend we're running - // under cargo by setting these environment variables. - std::env::set_var("OUT_DIR", env!("OUT_DIR")); - std::env::set_var("PROFILE", env!("PROFILE")); - SpirvBuilder::new( concat!(env!("CARGO_MANIFEST_DIR"), "/../../shaders/sky-shader"), "spirv-unknown-vulkan1.1", @@ -1326,7 +1330,9 @@ pub struct FragmentShaderEntryPoint { } unsafe fn any_as_u8_slice(p: &T) -> &[u8] { - ::std::slice::from_raw_parts((p as *const T).cast::(), ::std::mem::size_of::()) + unsafe { + ::std::slice::from_raw_parts((p as *const T).cast::(), ::std::mem::size_of::()) + } } unsafe extern "system" fn vulkan_debug_callback( @@ -1335,19 +1341,19 @@ unsafe extern "system" fn vulkan_debug_callback( p_callback_data: *const vk::DebugUtilsMessengerCallbackDataEXT<'_>, _user_data: *mut std::os::raw::c_void, ) -> vk::Bool32 { - let callback_data = *p_callback_data; + let callback_data = unsafe { *p_callback_data }; let message_id_number: i32 = callback_data.message_id_number; let message_id_name = if callback_data.p_message_id_name.is_null() { Cow::from("") } else { - CStr::from_ptr(callback_data.p_message_id_name).to_string_lossy() + unsafe { CStr::from_ptr(callback_data.p_message_id_name).to_string_lossy() } }; let message = if callback_data.p_message.is_null() { Cow::from("") } else { - CStr::from_ptr(callback_data.p_message).to_string_lossy() + unsafe { CStr::from_ptr(callback_data.p_message).to_string_lossy() } }; println!( diff --git a/examples/runners/cpu/src/main.rs b/examples/runners/cpu/src/main.rs index 813c350222..403f7972e1 100644 --- a/examples/runners/cpu/src/main.rs +++ b/examples/runners/cpu/src/main.rs @@ -36,7 +36,6 @@ clippy::map_err_ignore, clippy::map_flatten, clippy::map_unwrap_or, - clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wildcard_for_single_variants, clippy::mem_forget, @@ -92,9 +91,9 @@ fn color_u32_from_vec4(v: Vec4) -> u32 { let convert = |f: f32| -> u32 { (f.clamp(0.0, 1.0) * 255.0).round() as u32 }; convert(srgb_oetf(v.z)) - | convert(srgb_oetf(v.y)) << 8 - | convert(srgb_oetf(v.x)) << 16 - | convert(v.w) << 24 + | (convert(srgb_oetf(v.y)) << 8) + | (convert(srgb_oetf(v.x)) << 16) + | (convert(v.w) << 24) } fn main() { diff --git a/examples/runners/wgpu/src/lib.rs b/examples/runners/wgpu/src/lib.rs index 11cba07c39..a840839e93 100644 --- a/examples/runners/wgpu/src/lib.rs +++ b/examples/runners/wgpu/src/lib.rs @@ -36,7 +36,6 @@ clippy::map_err_ignore, clippy::map_flatten, clippy::map_unwrap_or, - clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wildcard_for_single_variants, clippy::mem_forget, @@ -99,14 +98,11 @@ impl CompiledShaderModules { wanted_entry: &str, ) -> wgpu::ShaderModuleDescriptorSpirV<'a> { for (name, spv_module) in &self.named_spv_modules { - match name { - Some(name) if name != wanted_entry => continue, - _ => { - return wgpu::ShaderModuleDescriptorSpirV { - label: name.as_deref(), - source: Cow::Borrowed(&spv_module.source), - }; - } + if name.as_ref().is_none_or(|name| name == wanted_entry) { + return wgpu::ShaderModuleDescriptorSpirV { + label: name.as_deref(), + source: Cow::Borrowed(&spv_module.source), + }; } } unreachable!( @@ -129,14 +125,7 @@ fn maybe_watch( { use spirv_builder::{CompileResult, MetadataPrintout, SpirvBuilder}; use std::path::PathBuf; - // Hack: spirv_builder builds into a custom directory if running under cargo, to not - // deadlock, and the default target directory if not. However, packages like `proc-macro2` - // have different configurations when being built here vs. when building - // rustc_codegen_spirv normally, so we *want* to build into a separate target directory, to - // not have to rebuild half the crate graph every time we run. So, pretend we're running - // under cargo by setting these environment variables. - std::env::set_var("OUT_DIR", env!("OUT_DIR")); - std::env::set_var("PROFILE", env!("PROFILE")); + let crate_name = match options.shader { RustGPUShader::Simplest => "simplest-shader", RustGPUShader::Sky => "sky-shader", @@ -231,10 +220,21 @@ pub struct Options { force_spirv_passthru: bool, } -#[cfg_attr(target_os = "android", export_name = "android_main")] +#[cfg_attr(target_os = "android", unsafe(export_name = "android_main"))] pub fn main( #[cfg(target_os = "android")] android_app: winit::platform::android::activity::AndroidApp, ) { + // Hack: spirv_builder builds into a custom directory if running under cargo, to not + // deadlock, and the default target directory if not. However, packages like `proc-macro2` + // have different configurations when being built here vs. when building + // rustc_codegen_spirv normally, so we *want* to build into a separate target directory, to + // not have to rebuild half the crate graph every time we run. So, pretend we're running + // under cargo by setting these environment variables. + unsafe { + std::env::set_var("OUT_DIR", env!("OUT_DIR")); + std::env::set_var("PROFILE", env!("PROFILE")); + } + let options = Options::parse(); #[cfg(not(any(target_os = "android", target_arch = "wasm32")))] diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 551cee7f67..174ba5c1f0 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,7 +1,7 @@ [toolchain] -channel = "nightly-2024-11-22" +channel = "nightly-2025-05-09" components = ["rust-src", "rustc-dev", "llvm-tools"] -# commit_hash = b19329a37cedf2027517ae22c87cf201f93d776e +# commit_hash = 50aa04180709189a03dde5fd1c05751b2625ed37 # 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/src/main.rs b/tests/src/main.rs index 551e6eb92f..78172df859 100644 --- a/tests/src/main.rs +++ b/tests/src/main.rs @@ -155,14 +155,18 @@ impl Runner { let target = format!("{SPIRV_TARGET_PREFIX}{env}"); let libs = build_deps(&self.deps_target_dir, &self.codegen_backend_path, &target); - let mut flags = test_rustc_flags(&self.codegen_backend_path, &libs, &[ - &self - .deps_target_dir - .join(DepKind::SpirvLib.target_dir_suffix(&target)), - &self - .deps_target_dir - .join(DepKind::ProcMacro.target_dir_suffix(&target)), - ]); + let mut flags = test_rustc_flags( + &self.codegen_backend_path, + &libs, + &[ + &self + .deps_target_dir + .join(DepKind::SpirvLib.target_dir_suffix(&target)), + &self + .deps_target_dir + .join(DepKind::ProcMacro.target_dir_suffix(&target)), + ], + ); flags += variation.extra_flags; let config = compiletest::Config { @@ -387,13 +391,10 @@ fn rust_flags(codegen_backend_path: &Path) -> String { fn map_status_to_result(status: std::process::ExitStatus) -> io::Result<()> { match status.success() { true => Ok(()), - false => Err(io::Error::new( - io::ErrorKind::Other, - format!( - "process terminated with non-zero code: {}", - status.code().unwrap_or(0) - ), - )), + false => Err(io::Error::other(format!( + "process terminated with non-zero code: {}", + status.code().unwrap_or(0) + ))), } } diff --git a/tests/ui/arch/all_memory_barrier.stderr b/tests/ui/arch/all_memory_barrier.stderr index 99a24af571..98eac4756b 100644 --- a/tests/ui/arch/all_memory_barrier.stderr +++ b/tests/ui/arch/all_memory_barrier.stderr @@ -1,6 +1,6 @@ %1 = OpFunction %2 None %3 %4 = OpLabel -OpLine %5 75 4 +OpLine %5 78 8 OpMemoryBarrier %6 %7 OpNoLine OpReturn diff --git a/tests/ui/arch/all_memory_barrier_with_group_sync.stderr b/tests/ui/arch/all_memory_barrier_with_group_sync.stderr index ce22a314ef..0b4f02ef01 100644 --- a/tests/ui/arch/all_memory_barrier_with_group_sync.stderr +++ b/tests/ui/arch/all_memory_barrier_with_group_sync.stderr @@ -1,6 +1,6 @@ %1 = OpFunction %2 None %3 %4 = OpLabel -OpLine %5 41 4 +OpLine %5 42 8 OpControlBarrier %6 %7 %8 OpNoLine OpReturn diff --git a/tests/ui/arch/debug_printf_type_checking.stderr b/tests/ui/arch/debug_printf_type_checking.stderr index b8ce41a270..faec0bc0c7 100644 --- a/tests/ui/arch/debug_printf_type_checking.stderr +++ b/tests/ui/arch/debug_printf_type_checking.stderr @@ -73,17 +73,18 @@ help: the return type of this call is `u32` due to the type of the argument pass 21 | debug_printf!("%f", 11_u32); | ^^^^^^^^^^^^^^^^^^^^------^ | | - | this argument influences the return type of `spirv_std` + | this argument influences the return type of `debug_printf_assert_is_type` note: function defined here - --> $SPIRV_STD_SRC/lib.rs:134:8 + --> $SPIRV_STD_SRC/lib.rs:133:8 | -134 | pub fn debug_printf_assert_is_type(ty: T) -> T { +133 | pub fn debug_printf_assert_is_type(ty: T) -> T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) help: change the type of the numeric literal from `u32` to `f32` | -21 | debug_printf!("%f", 11_f32); - | ~~~ +21 - debug_printf!("%f", 11_u32); +21 + debug_printf!("%f", 11_f32); + | error[E0308]: mismatched types --> $DIR/debug_printf_type_checking.rs:22:29 @@ -100,17 +101,18 @@ help: the return type of this call is `f32` due to the type of the argument pass 22 | debug_printf!("%u", 11.0_f32); | ^^^^^^^^^^^^^^^^^^^^--------^ | | - | this argument influences the return type of `spirv_std` + | this argument influences the return type of `debug_printf_assert_is_type` note: function defined here - --> $SPIRV_STD_SRC/lib.rs:134:8 + --> $SPIRV_STD_SRC/lib.rs:133:8 | -134 | pub fn debug_printf_assert_is_type(ty: T) -> T { +133 | pub fn debug_printf_assert_is_type(ty: T) -> T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) help: change the type of the numeric literal from `f32` to `u32` | -22 | debug_printf!("%u", 11u32); - | ~~~ +22 - debug_printf!("%u", 11.0_f32); +22 + debug_printf!("%u", 11u32); + | error[E0277]: the trait bound `{float}: Vector` is not satisfied --> $DIR/debug_printf_type_checking.rs:23:9 @@ -129,12 +131,12 @@ error[E0277]: the trait bound `{float}: Vector` is not satisfied `UVec3` implements `Vector` and 5 others note: required by a bound in `debug_printf_assert_is_vector` - --> $SPIRV_STD_SRC/lib.rs:141:8 + --> $SPIRV_STD_SRC/lib.rs:140:8 | -139 | pub fn debug_printf_assert_is_vector< +138 | pub fn debug_printf_assert_is_vector< | ----------------------------- required by a bound in this function -140 | TY: crate::scalar::Scalar, -141 | V: crate::vector::Vector, +139 | TY: crate::scalar::Scalar, +140 | V: crate::vector::Vector, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `debug_printf_assert_is_vector` = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -153,11 +155,11 @@ help: the return type of this call is `Vec2` due to the type of the argument pas 24 | debug_printf!("%f", Vec2::splat(33.3)); | ^^^^^^^^^^^^^^^^^^^^-----------------^ | | - | this argument influences the return type of `spirv_std` + | this argument influences the return type of `debug_printf_assert_is_type` note: function defined here - --> $SPIRV_STD_SRC/lib.rs:134:8 + --> $SPIRV_STD_SRC/lib.rs:133:8 | -134 | pub fn debug_printf_assert_is_type(ty: T) -> T { +133 | pub fn debug_printf_assert_is_type(ty: T) -> T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/arch/device_memory_barrier.stderr b/tests/ui/arch/device_memory_barrier.stderr index 99a24af571..98eac4756b 100644 --- a/tests/ui/arch/device_memory_barrier.stderr +++ b/tests/ui/arch/device_memory_barrier.stderr @@ -1,6 +1,6 @@ %1 = OpFunction %2 None %3 %4 = OpLabel -OpLine %5 75 4 +OpLine %5 78 8 OpMemoryBarrier %6 %7 OpNoLine OpReturn diff --git a/tests/ui/arch/device_memory_barrier_with_group_sync.stderr b/tests/ui/arch/device_memory_barrier_with_group_sync.stderr index ce22a314ef..0b4f02ef01 100644 --- a/tests/ui/arch/device_memory_barrier_with_group_sync.stderr +++ b/tests/ui/arch/device_memory_barrier_with_group_sync.stderr @@ -1,6 +1,6 @@ %1 = OpFunction %2 None %3 %4 = OpLabel -OpLine %5 41 4 +OpLine %5 42 8 OpControlBarrier %6 %7 %8 OpNoLine OpReturn diff --git a/tests/ui/arch/workgroup_memory_barrier.stderr b/tests/ui/arch/workgroup_memory_barrier.stderr index 99a24af571..98eac4756b 100644 --- a/tests/ui/arch/workgroup_memory_barrier.stderr +++ b/tests/ui/arch/workgroup_memory_barrier.stderr @@ -1,6 +1,6 @@ %1 = OpFunction %2 None %3 %4 = OpLabel -OpLine %5 75 4 +OpLine %5 78 8 OpMemoryBarrier %6 %7 OpNoLine OpReturn diff --git a/tests/ui/arch/workgroup_memory_barrier_with_group_sync.stderr b/tests/ui/arch/workgroup_memory_barrier_with_group_sync.stderr index 37119b71c8..6d4fb50d6d 100644 --- a/tests/ui/arch/workgroup_memory_barrier_with_group_sync.stderr +++ b/tests/ui/arch/workgroup_memory_barrier_with_group_sync.stderr @@ -1,6 +1,6 @@ %1 = OpFunction %2 None %3 %4 = OpLabel -OpLine %5 41 4 +OpLine %5 42 8 OpControlBarrier %6 %6 %7 OpNoLine OpReturn diff --git a/tests/ui/dis/issue-1062.stderr b/tests/ui/dis/issue-1062.stderr index e62cf988bf..50182936c7 100644 --- a/tests/ui/dis/issue-1062.stderr +++ b/tests/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 1199 4 +OpLine %11 1108 4 %12 = OpBitwiseAnd %7 %9 %13 %14 = OpISub %7 %15 %12 %16 = OpShiftLeftLogical %7 %6 %12 diff --git a/tests/ui/dis/panic_builtin_bounds_check.stderr b/tests/ui/dis/panic_builtin_bounds_check.stderr index e1c8f3b28c..47962be2ca 100644 --- a/tests/ui/dis/panic_builtin_bounds_check.stderr +++ b/tests/ui/dis/panic_builtin_bounds_check.stderr @@ -12,27 +12,45 @@ 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" -%5 = OpTypeVoid -%6 = OpTypeFunction %5 -%7 = OpTypeBool +OpDecorate %5 ArrayStride 4 +%6 = OpTypeVoid +%7 = OpTypeFunction %6 %8 = OpTypeInt 32 0 -%9 = OpConstant %8 5 -%10 = OpConstant %8 4 -%11 = OpUndef %8 -%2 = OpFunction %5 None %6 -%12 = OpLabel +%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 +%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 -%13 = OpULessThan %7 %9 %10 +OpStore %20 %21 +%22 = OpULessThan %15 %16 %9 OpNoLine -OpSelectionMerge %14 None -OpBranchConditional %13 %15 %16 -%15 = OpLabel -OpBranch %14 -%16 = OpLabel +OpSelectionMerge %23 None +OpBranchConditional %22 %24 %25 +%24 = OpLabel +OpBranch %23 +%25 = OpLabel OpLine %4 25 4 -%17 = OpExtInst %5 %1 1 %3 %11 %9 +%26 = OpExtInst %6 %1 1 %3 %17 %16 OpNoLine OpReturn -%14 = OpLabel +%23 = OpLabel +OpLine %4 25 4 +%27 = OpIAdd %8 %11 %16 +%28 = OpInBoundsAccessChain %18 %20 %27 +%29 = OpLoad %8 %28 +OpNoLine OpReturn OpFunctionEnd diff --git a/tests/ui/dis/ptr_copy.normal.stderr b/tests/ui/dis/ptr_copy.normal.stderr index e376de2e58..994c1a6e8c 100644 --- a/tests/ui/dis/ptr_copy.normal.stderr +++ b/tests/ui/dis/ptr_copy.normal.stderr @@ -1,13 +1,13 @@ error: cannot memcpy dynamically sized data - --> $CORE_SRC/intrinsics/mod.rs:4158:9 + --> $CORE_SRC/intrinsics/mod.rs:3850:9 | -4158 | copy(src, dst, count) +3850 | copy(src, dst, count) | ^^^^^^^^^^^^^^^^^^^^^ | note: used from within `core::intrinsics::copy::` - --> $CORE_SRC/intrinsics/mod.rs:4134:21 + --> $CORE_SRC/intrinsics/mod.rs:3830:21 | -4134 | pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { +3830 | 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,27 +28,25 @@ note: called by `main` error: cannot cast between pointer types from `*f32` to `*struct () { }` - --> $CORE_SRC/intrinsics/mod.rs:4146:9 + --> $CORE_SRC/intrinsics/mod.rs:3838:9 | -4146 | / ub_checks::assert_unsafe_precondition!( -4147 | | check_language_ub, -4148 | | "ptr::copy requires that both pointer arguments are aligned and non-null", -4149 | | ( +3838 | / ub_checks::assert_unsafe_precondition!( +3839 | | check_language_ub, +3840 | | "ptr::copy requires that both pointer arguments are aligned and non-null", ... | -4156 | | && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) -4157 | | ); +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:4146:9 + --> $CORE_SRC/intrinsics/mod.rs:3838:9 | -4146 | / ub_checks::assert_unsafe_precondition!( -4147 | | check_language_ub, -4148 | | "ptr::copy requires that both pointer arguments are aligned and non-null", -4149 | | ( +3838 | / ub_checks::assert_unsafe_precondition!( +3839 | | check_language_ub, +3840 | | "ptr::copy requires that both pointer arguments are aligned and non-null", ... | -4156 | | && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) -4157 | | ); +3848 | | && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) +3849 | | ); | |_________^ note: called by `ptr_copy::copy_via_raw_ptr` --> $DIR/ptr_copy.rs:28:18 diff --git a/tests/ui/dis/ptr_copy.rs b/tests/ui/dis/ptr_copy.rs index 89f1a83d84..59a08ce76b 100644 --- a/tests/ui/dis/ptr_copy.rs +++ b/tests/ui/dis/ptr_copy.rs @@ -11,9 +11,9 @@ use spirv_std::spirv; fn copy_via_raw_ptr(src: &f32, dst: &mut f32) { #[cfg(via_intrinsic)] { - extern "rust-intrinsic" { - fn copy(src: *const T, dst: *mut T, count: usize); - } + #[rustc_intrinsic] + unsafe fn copy(src: *const T, dst: *mut T, count: usize); + unsafe { copy(src, dst, 1) } } diff --git a/tests/ui/dis/ptr_read.stderr b/tests/ui/dis/ptr_read.stderr index ee8fd2aab4..4d4ea6333d 100644 --- a/tests/ui/dis/ptr_read.stderr +++ b/tests/ui/dis/ptr_read.stderr @@ -2,7 +2,7 @@ %4 = OpFunctionParameter %5 %6 = OpFunctionParameter %5 %7 = OpLabel -OpLine %8 1374 8 +OpLine %8 1455 8 %9 = OpLoad %10 %4 OpLine %11 7 13 OpStore %6 %9 diff --git a/tests/ui/dis/ptr_read_method.stderr b/tests/ui/dis/ptr_read_method.stderr index ee8fd2aab4..4d4ea6333d 100644 --- a/tests/ui/dis/ptr_read_method.stderr +++ b/tests/ui/dis/ptr_read_method.stderr @@ -2,7 +2,7 @@ %4 = OpFunctionParameter %5 %6 = OpFunctionParameter %5 %7 = OpLabel -OpLine %8 1374 8 +OpLine %8 1455 8 %9 = OpLoad %10 %4 OpLine %11 7 13 OpStore %6 %9 diff --git a/tests/ui/dis/ptr_write.stderr b/tests/ui/dis/ptr_write.stderr index 2ca3b239fc..3b757241cc 100644 --- a/tests/ui/dis/ptr_write.stderr +++ b/tests/ui/dis/ptr_write.stderr @@ -4,7 +4,7 @@ %7 = OpLabel OpLine %8 7 35 %9 = OpLoad %10 %4 -OpLine %11 1578 8 +OpLine %11 1655 8 OpStore %6 %9 OpNoLine OpReturn diff --git a/tests/ui/dis/ptr_write_method.stderr b/tests/ui/dis/ptr_write_method.stderr index 5ff386ef8c..701ac3e759 100644 --- a/tests/ui/dis/ptr_write_method.stderr +++ b/tests/ui/dis/ptr_write_method.stderr @@ -4,7 +4,7 @@ %7 = OpLabel OpLine %8 7 37 %9 = OpLoad %10 %4 -OpLine %11 1578 8 +OpLine %11 1655 8 OpStore %6 %9 OpNoLine OpReturn diff --git a/tests/ui/image/query/query_levels_err.stderr b/tests/ui/image/query/query_levels_err.stderr index 2f03a3f426..9db16dc3e4 100644 --- a/tests/ui/image/query/query_levels_err.stderr +++ b/tests/ui/image/query/query_levels_err.stderr @@ -10,12 +10,12 @@ error[E0277]: the trait bound `Image: HasQueryLevels` Image Image note: required by a bound in `Image::::query_levels` - --> $SPIRV_STD_SRC/image.rs:881:15 + --> $SPIRV_STD_SRC/image.rs:885:15 | -879 | pub fn query_levels(&self) -> u32 +883 | pub fn query_levels(&self) -> u32 | ------------ required by a bound in this associated function -880 | where -881 | Self: HasQueryLevels, +884 | where +885 | Self: HasQueryLevels, | ^^^^^^^^^^^^^^ required by this bound in `Image::::query_levels` error: aborting due to 1 previous error diff --git a/tests/ui/image/query/query_lod_err.stderr b/tests/ui/image/query/query_lod_err.stderr index 0b6a9a052c..576116686e 100644 --- a/tests/ui/image/query/query_lod_err.stderr +++ b/tests/ui/image/query/query_lod_err.stderr @@ -10,12 +10,12 @@ error[E0277]: the trait bound `Image: HasQueryLevels` Image Image note: required by a bound in `Image::::query_lod` - --> $SPIRV_STD_SRC/image.rs:907:15 + --> $SPIRV_STD_SRC/image.rs:911:15 | -901 | pub fn query_lod( +905 | pub fn query_lod( | --------- required by a bound in this associated function ... -907 | Self: HasQueryLevels, +911 | Self: HasQueryLevels, | ^^^^^^^^^^^^^^ required by this bound in `Image::::query_lod` error: aborting due to 1 previous error diff --git a/tests/ui/image/query/query_size_err.stderr b/tests/ui/image/query/query_size_err.stderr index b35b9c1298..5ab33e2a36 100644 --- a/tests/ui/image/query/query_size_err.stderr +++ b/tests/ui/image/query/query_size_err.stderr @@ -15,12 +15,12 @@ error[E0277]: the trait bound `Image: HasQuerySize` is Image and 6 others note: required by a bound in `Image::::query_size` - --> $SPIRV_STD_SRC/image.rs:938:15 + --> $SPIRV_STD_SRC/image.rs:942:15 | -936 | pub fn query_size + Default>(&self) -> Size +940 | pub fn query_size + Default>(&self) -> Size | ---------- required by a bound in this associated function -937 | where -938 | Self: HasQuerySize, +941 | where +942 | Self: HasQuerySize, | ^^^^^^^^^^^^ required by this bound in `Image::::query_size` error: aborting due to 1 previous error diff --git a/tests/ui/image/query/query_size_lod_err.stderr b/tests/ui/image/query/query_size_lod_err.stderr index 20464eb29a..eda040bdf6 100644 --- a/tests/ui/image/query/query_size_lod_err.stderr +++ b/tests/ui/image/query/query_size_lod_err.stderr @@ -10,12 +10,12 @@ error[E0277]: the trait bound `Image: HasQuerySizeLod` Image Image note: required by a bound in `Image::::query_size_lod` - --> $SPIRV_STD_SRC/image.rs:982:15 + --> $SPIRV_STD_SRC/image.rs:986:15 | -977 | pub fn query_size_lod + Default>( +981 | pub fn query_size_lod + Default>( | -------------- required by a bound in this associated function ... -982 | Self: HasQuerySizeLod, +986 | Self: HasQuerySizeLod, | ^^^^^^^^^^^^^^^ required by this bound in `Image::::query_size_lod` error: aborting due to 1 previous error diff --git a/tests/ui/lang/core/unwrap_or.stderr b/tests/ui/lang/core/unwrap_or.stderr index 7f46d10973..acb13945ed 100644 --- a/tests/ui/lang/core/unwrap_or.stderr +++ b/tests/ui/lang/core/unwrap_or.stderr @@ -3,10 +3,10 @@ OpLine %5 13 11 %6 = OpCompositeInsert %7 %8 %9 0 %10 = OpCompositeExtract %11 %6 1 -OpLine %12 993 14 +OpLine %12 1024 14 %13 = OpBitcast %14 %8 -OpLine %12 993 8 -%15 = OpIEqual %16 %13 %17 +OpLine %12 1024 8 +%15 = OpINotEqual %16 %13 %17 OpNoLine OpSelectionMerge %18 None OpBranchConditional %15 %19 %20 @@ -15,7 +15,7 @@ OpBranch %18 %20 = OpLabel OpBranch %18 %18 = OpLabel -%21 = OpPhi %11 %22 %19 %10 %20 +%21 = OpPhi %11 %10 %19 %22 %20 OpLine %5 13 4 OpStore %23 %21 OpNoLine diff --git a/tests/ui/spirv-attr/invalid-target.stderr b/tests/ui/spirv-attr/invalid-target.stderr index c8733ab54f..842d832503 100644 --- a/tests/ui/spirv-attr/invalid-target.stderr +++ b/tests/ui/spirv-attr/invalid-target.stderr @@ -2620,5 +2620,33 @@ error: attribute is only valid on a function parameter, not on a foreign functio 87 | uniform, position, descriptor_set = 0, binding = 0, flat, invariant, // param-only | ^^^^^^^^^ -error: aborting due to 437 previous errors +error: unconstrained opaque type + --> $DIR/invalid-target.rs:118:18 + | +118 | type _OpaqueTy = impl Copy; + | ^^^^^^^^^ + | + = note: `_OpaqueTy` must be used in combination with a concrete type within the same crate + +error[E0308]: mismatched types + --> $DIR/invalid-target.rs:121:5 + | +118 | type _OpaqueTy = impl Copy; + | --------- the expected opaque type +119 | +120 | fn _opaque_ty_definer() -> _OpaqueTy { + | --------- expected `_OpaqueTy` because of return type +121 | () + | ^^ expected opaque type, found `()` + | + = note: expected opaque type `_OpaqueTy` + found unit type `()` +note: this item must have a `#[define_opaque(_OpaqueTy)]` attribute to be able to define hidden types + --> $DIR/invalid-target.rs:120:4 + | +120 | fn _opaque_ty_definer() -> _OpaqueTy { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 439 previous errors +For more information about this error, try `rustc --explain E0308`.