diff --git a/.cargo/config.toml b/.cargo/config.toml index e0072bb0c5e..240a843bbb2 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -45,7 +45,6 @@ rustflags = [ "-Wclippy::flat_map_option", "-Wclippy::float_cmp_const", "-Wclippy::fn_params_excessive_bools", - "-Wclippy::from_iter_instead_of_collect", "-Wclippy::if_let_mutex", "-Wclippy::implicit_clone", "-Wclippy::imprecise_flops", diff --git a/crates/rustc_codegen_spirv/build.rs b/crates/rustc_codegen_spirv/build.rs index 135151e5431..5f955a22fb7 100644 --- a/crates/rustc_codegen_spirv/build.rs +++ b/crates/rustc_codegen_spirv/build.rs @@ -19,9 +19,9 @@ use std::{env, fs, mem}; /// `cargo publish`. We need to figure out a way to do this properly, but let's hardcode it for now :/ //const REQUIRED_RUST_TOOLCHAIN: &str = include_str!("../../rust-toolchain.toml"); const REQUIRED_RUST_TOOLCHAIN: &str = r#"[toolchain] -channel = "nightly-2026-05-22" +channel = "nightly-2026-08-06" components = ["rust-src", "rustc-dev", "llvm-tools"] -# commit_hash = e96c36b6f76833388c519561d145492d2c08db4e"#; +# commit_hash = 7608eb7b07eaf93f16d7cf5bcb2098eca87503df"#; fn rustc_output(arg: &str) -> Result> { let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".into()); @@ -153,7 +153,10 @@ fn generate_pqp_cg_ssa() -> Result<(), Box> { for line in mem::take(&mut src).lines() { if line.starts_with("#!") { src += "// "; - if !line.starts_with("#![doc(") && line != "#![warn(unreachable_pub)]" { + if !line.starts_with("#![doc(") + && line != "#![warn(unreachable_pub)]" + && !line.starts_with("#![cfg_attr(bootstrap,") + { writeln(&mut cg_ssa_lib_rc_attrs, line); } } else if line == "#[macro_use]" || line.starts_with("extern crate ") { @@ -256,6 +259,34 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {", ); } + // HACK(firestar99): Undo code cleanup that prevents passing ScalarPairs as `PassMode::Direct` + // https://github.com/rust-lang/rust/commit/dfc475d018c780475ea962f15d86cfa05a50a148 + if relative_path == Path::new("src/mir/mod.rs") { + src = src.replace( + " + debug_assert!(bx.is_backend_immediate(arg.layout)); + return local(OperandRef { + val: OperandValue::Immediate(llarg), + layout: arg.layout, + move_annotation: None, + });", + " + return local(OperandRef::from_immediate_or_packed_pair( + bx, llarg, arg.layout, + ));", + ); + src = src.replace("fx.fill_function_debug_context(&mut start_bx);", ""); + } + if relative_path == Path::new("src/mir/block.rs") { + src = src.replace( + r#" + PassMode::Direct(_) => (op.immediate(), arg.layout.align.abi, false), + PassMode::Ignore | PassMode::Pair(..) => unreachable!("handled above"),"#, + "\ + _ => (op.immediate_or_packed_pair(bx), arg.layout.align.abi, false),", + ); + } + fs::write(out_path, src)?; } } diff --git a/crates/rustc_codegen_spirv/src/abi.rs b/crates/rustc_codegen_spirv/src/abi.rs index da589937f4f..cacba3431c8 100644 --- a/crates/rustc_codegen_spirv/src/abi.rs +++ b/crates/rustc_codegen_spirv/src/abi.rs @@ -87,20 +87,11 @@ pub(crate) fn provide(providers: &mut Providers) { fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>, ) -> &'tcx FnAbi<'tcx, Ty<'tcx>> { let readjust_arg_abi = |arg: &ArgAbi<'tcx, Ty<'tcx>>| { - let mut arg = ArgAbi::new(&tcx, arg.layout, |_, _| ArgAttributes::new()); + let mut arg = ArgAbi::new(arg.layout, |_, _| ArgAttributes::new()); // FIXME: this is bad! https://github.com/rust-lang/rust/issues/115666 // arg.make_direct_deprecated(); - // FIXME(eddyb) detect `#[rust_gpu::vector::v1]` more specifically, - // to avoid affecting anything should actually be passed as a pair. - if let PassMode::Pair(..) = arg.mode { - // HACK(eddyb) this avoids breaking e.g. `&[T]` pairs. - if let TyKind::Adt(..) = arg.layout.ty.kind() { - arg.mode = PassMode::Direct(ArgAttributes::new()); - } - } - // Avoid pointlessly passing ZSTs, just like the official Rust ABI. if arg.layout.is_zst() { arg.mode = PassMode::Ignore; @@ -364,7 +355,7 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { } .def_with_name(cx, span, TyLayoutNameKey::from(*self)), BackendRepr::Scalar(scalar) => trans_scalar(cx, span, *self, scalar, Size::ZERO), - BackendRepr::ScalarPair(a, b) => { + BackendRepr::ScalarPair { a, b, .. } => { // NOTE(eddyb) unlike `BackendRepr::Scalar`'s simpler newtype-unpacking // behavior, `BackendRepr::ScalarPair` can be composed in two ways: // * two `BackendRepr::Scalar` fields (and any number of ZST fields), @@ -402,7 +393,10 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { // Note: We can't use auto_struct_layout here because the spirv types here might be undefined due to // recursive pointer types. let a_offset = Size::ZERO; - let b_offset = a.primitive().size(cx).align_to(b.primitive().align(cx).abi); + let b_offset = a + .primitive() + .size(cx) + .align_to(b.primitive().default_align(cx).abi); let a = trans_scalar(cx, span, *self, a, a_offset); let b = trans_scalar(cx, span, *self, b, b_offset); let size = if self.is_unsized() { @@ -438,7 +432,7 @@ impl<'tcx> ConvSpirvType<'tcx> for TyAndLayout<'tcx> { let elem_spirv = trans_scalar(cx, span, *self, element, Size::ZERO); SpirvType::Vector { element: elem_spirv, - count: count as u32, + count: count.as_u32(), size: self.size, align: self.align.abi, } @@ -461,8 +455,8 @@ pub fn scalar_pair_element_backend_type<'tcx>( ty: TyAndLayout<'tcx>, index: usize, ) -> Word { - let [a, b] = match ty.layout.backend_repr() { - BackendRepr::ScalarPair(a, b) => [a, b], + let [a, b] = match ty.backend_repr { + BackendRepr::ScalarPair { a, b, .. } => [a, b], other => span_bug!( span, "scalar_pair_element_backend_type invalid abi: {:?}", @@ -471,7 +465,10 @@ pub fn scalar_pair_element_backend_type<'tcx>( }; let offset = match index { 0 => Size::ZERO, - 1 => a.primitive().size(cx).align_to(b.primitive().align(cx).abi), + 1 => a + .primitive() + .size(cx) + .align_to(b.primitive().default_align(cx).abi), _ => unreachable!(), }; trans_scalar(cx, span, ty, [a, b][index], offset) diff --git a/crates/rustc_codegen_spirv/src/attr.rs b/crates/rustc_codegen_spirv/src/attr.rs index ae1651120b6..6fe22385eac 100644 --- a/crates/rustc_codegen_spirv/src/attr.rs +++ b/crates/rustc_codegen_spirv/src/attr.rs @@ -7,7 +7,7 @@ use crate::symbols::Symbols; use rspirv::spirv::{BuiltIn, ExecutionMode, ExecutionModel, StorageClass}; use rustc_ast::{LitKind, MetaItemInner, MetaItemLit}; use rustc_hir as hir; -use rustc_hir::def_id::LocalModDefId; +use rustc_hir::def_id::LocalModId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Attribute, CRATE_HIR_ID, HirId, MethodKind, Target}; use rustc_middle::hir::nested_filter; @@ -433,19 +433,19 @@ impl<'tcx> Visitor<'tcx> for CheckSpirvAttrVisitor<'tcx> { } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - let target = Target::from_item(item); + let target = Target::from(item); self.check_spirv_attributes(item.hir_id(), target); intravisit::walk_item(self, item); } fn visit_generic_param(&mut self, generic_param: &'tcx hir::GenericParam<'tcx>) { - let target = Target::from_generic_param(generic_param); + let target = Target::from(generic_param); self.check_spirv_attributes(generic_param.hir_id, target); intravisit::walk_generic_param(self, generic_param); } fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { - let target = Target::from_trait_item(trait_item); + let target = Target::from(trait_item); self.check_spirv_attributes(trait_item.hir_id(), target); intravisit::walk_trait_item(self, trait_item); } @@ -461,7 +461,7 @@ impl<'tcx> Visitor<'tcx> for CheckSpirvAttrVisitor<'tcx> { } fn visit_foreign_item(&mut self, f_item: &'tcx hir::ForeignItem<'tcx>) { - let target = Target::from_foreign_item(f_item); + let target = Target::from(f_item); self.check_spirv_attributes(f_item.hir_id(), target); intravisit::walk_foreign_item(self, f_item); } @@ -503,7 +503,7 @@ impl<'tcx> Visitor<'tcx> for CheckSpirvAttrVisitor<'tcx> { } // FIXME(eddyb) DRY this somehow and make it reusable from somewhere in `rustc`. -fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { +fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalModId) { let check_spirv_attr_visitor = &mut CheckSpirvAttrVisitor { tcx, sym: Symbols::get(), diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index 25cd1c66ce1..ab94b5217a0 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -1873,7 +1873,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { self.bitcast(loaded_val, ty) } - fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value) -> Self::Value { + fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value, _align: Align) -> Self::Value { // TODO: Implement this let result = self.load(ty, ptr, Align::from_bytes(0).unwrap()); self.zombie(result.def(self), "volatile load is not supported yet"); @@ -1917,18 +1917,18 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { let val = if place.val.llextra.is_some() { OperandValue::Ref(place.val) - } else if self.cx.is_backend_immediate(place.layout) { + } else if place.layout.backend_repr.is_scalar_or_simd() { let llval = self.load( place.layout.spirv_type(self.span(), self), place.val.llval, place.val.align, ); OperandValue::Immediate(llval) - } else if let BackendRepr::ScalarPair(a, b) = place.layout.backend_repr { + } else if let BackendRepr::ScalarPair { a, b, .. } = place.layout.backend_repr { let b_offset = a .primitive() .size(self) - .align_to(b.primitive().align(self).abi); + .align_to(b.primitive().default_align(self).abi); let mut load = |i, scalar: Scalar, align| { let llptr = if i == 0 { @@ -2012,7 +2012,8 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { align: Align, flags: MemFlags, ) -> Self::Value { - if flags != MemFlags::empty() { + let allowed_flags = MemFlags::CAPTURES_READ_ONLY; + if !(flags & !allowed_flags).is_empty() { self.err(format!("store_with_flags is not supported yet: {flags:?}")); } self.store(val, ptr, align) @@ -3503,4 +3504,8 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { fn alloca_with_ty(&mut self, _layout: TyAndLayout<'tcx>) -> Self::Value { bug!("scalable alloca is not supported in SPIR-V backend") } + + fn vscale(&mut self, _ty: Self::Type) -> Self::Value { + self.fatal("scalable vectors not supported"); + } } diff --git a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs index 2c8e4835f3f..16b2a0fd41c 100644 --- a/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs +++ b/crates/rustc_codegen_spirv/src/builder/format_args_decompiler.rs @@ -557,16 +557,19 @@ impl<'tcx> DecodedFormatArgs<'tcx> { if let Some((template_id, template_ty_id, rt_args_ptr_id, rt_args_ptr_ty_id)) = split_fmt_args { - let ctor = if let (Some(template_len), Some(rt_args_count)) = ( + if let (Some(template_len), Some(rt_args_count)) = ( const_ptr_to_composite_len(template_id) .or_else(|| array_len_from_ptr_type(template_ty_id)), const_ptr_to_composite_len(rt_args_ptr_id) .or_else(|| array_len_from_ptr_type(rt_args_ptr_ty_id)), ) { - FmtArgsCtor::NewTemplate { - template_len, - rt_args_count, - } + ( + FmtArgsCtor::NewTemplate { + template_len, + rt_args_count, + }, + SmallVec::<[Word; 8]>::from_slice(&[template_id, rt_args_ptr_id]), + ) } else if let Some(&[Inst::Call(_, callee_id, ref call_args)]) = try_rev_take(-1).as_deref() && call_args.len() == 2 @@ -574,18 +577,40 @@ impl<'tcx> DecodedFormatArgs<'tcx> { { // Consume the matched call instruction. try_rev_take(1).unwrap(); - lookup_fmt_args_ctor(callee_id)? + ( + lookup_fmt_args_ctor(callee_id)?, + SmallVec::<[Word; 8]>::from_slice(&[template_id, rt_args_ptr_id]), + ) + } else if let Some( + &[ + Inst::Call(call_ret_id, callee_id, ref call_args), + Inst::CompositeExtract(extracted0, from0, 0), + Inst::CompositeExtract(extracted1, from1, 1), + ], + ) = try_rev_take(-3).as_deref() + && [from0, from1] == [call_ret_id; 2] + && [extracted0, extracted1] == [template_id, rt_args_ptr_id] + { + // Newer rustc, since `BackendRepr::ScalarPair` args are no + // longer forced to `PassMode::Direct`, returns the whole + // `fmt::Arguments` from its `new_*` constructor as a scalar + // pair, and splits it (via `OpCompositeExtract`s) into the + // two scalar values passed to the panic entry-point. + // + // The constructor's own arguments (i.e. `pieces`/`template` + // and the `rt::Argument` slice pointers) still carry the + // recoverable const data, so use those, like the aggregate + // (non-split) `Call`+`extract`+`insert` case does below. + let call_args_storage = call_args.iter().copied().collect(); + // Consume the matched call + both `OpCompositeExtract`s. + try_rev_take(3).unwrap(); + (lookup_fmt_args_ctor(callee_id)?, call_args_storage) } else { // We failed to recover constructor metadata for an already-split // `fmt::Arguments` value. Keep panic lowering sound by falling // back to an unknown panic message, without requiring decompilation. return Ok(decoded_format_args); - }; - - ( - ctor, - SmallVec::<[Word; 8]>::from_slice(&[template_id, rt_args_ptr_id]), - ) + } } else { // Newer rustc can pass the `fmt::Arguments::new_*` result directly to // panic entry points (single trailing call), while older versions go diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index 041ca3463fe..622347b8a08 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -9,9 +9,11 @@ use crate::custom_insts::CustomInst; use crate::spirv_type::SpirvType; use rspirv::dr::Operand; use rspirv::spirv::GlslStd450Op as GLOp; +use rustc_abi::Align; use rustc_codegen_ssa::RetagInfo; +use rustc_codegen_ssa::mir::IntrinsicResult; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; -use rustc_codegen_ssa::mir::place::PlaceRef; +use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; use rustc_codegen_ssa::traits::{BuilderMethods, IntrinsicCallBuilderMethods}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{FnDef, Instance, Ty, TyKind, TypingEnv}; @@ -64,13 +66,18 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { &mut self, instance: Instance<'tcx>, args: &[OperandRef<'tcx, Self::Value>], - result: PlaceRef<'tcx, Self::Value>, + result_layout: ty::layout::TyAndLayout<'tcx>, + result_place: Option>, _span: Span, - ) -> Result<(), ty::Instance<'tcx>> { + ) -> IntrinsicResult<'tcx, Self::Value> { + let result = PlaceRef { + val: result_place.unwrap(), + layout: result_layout, + }; let callee_ty = instance.ty(self.tcx, TypingEnv::fully_monomorphized()); let (def_id, fn_args) = match *callee_ty.kind() { - FnDef(def_id, fn_args) => (def_id, fn_args), + FnDef(def_id, fn_args) => (def_id, fn_args.skip_binder()), _ => bug!("expected fn item type, found {}", callee_ty), }; @@ -95,17 +102,18 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { sym::breakpoint => { self.abort(); assert!(result.layout.ty.is_unit()); - return Ok(()); + return IntrinsicResult::WroteIntoPlace; } sym::volatile_load | sym::unaligned_volatile_load => { let ptr = args[0].immediate(); let layout = self.layout_of(fn_args.type_at(0)); - let load = self.volatile_load(layout.spirv_type(self.span(), self), ptr); + let load = + self.volatile_load(layout.spirv_type(self.span(), self), ptr, Align::ONE); if !result.layout.is_zst() { self.store(load, result.val.llval, result.val.align); } - return Ok(()); + return IntrinsicResult::WroteIntoPlace; } sym::prefetch_read_data @@ -114,7 +122,7 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { | sym::prefetch_write_instruction => { // ignore assert!(result.layout.ty.is_unit()); - return Ok(()); + return IntrinsicResult::WroteIntoPlace; } sym::saturating_add => { @@ -352,7 +360,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_raw(instance.def_id(), instance.args)); + return IntrinsicResult::Fallback(Instance::new_raw(def_id, instance.args)); } }; @@ -368,7 +376,7 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { .val .store(self, result); } - Ok(()) + IntrinsicResult::WroteIntoPlace } fn codegen_llvm_intrinsic_call( @@ -402,16 +410,7 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { todo!() } - fn va_start(&mut self, val: Self::Value) -> Self::Value { - // SPIR-V backend has no variadic ABI support; keep the placeholder - // operand unchanged so MIR lowering can proceed without crashing. - val - } - - fn va_end(&mut self, val: Self::Value) -> Self::Value { - // See `va_start` above. - val - } + fn va_start(&mut self, _val: Self::Value) {} fn retag_mem(&mut self, _place: Self::Value, _info: &RetagInfo) { bug!("retag not supported") diff --git a/crates/rustc_codegen_spirv/src/builder/mod.rs b/crates/rustc_codegen_spirv/src/builder/mod.rs index ba4af829a98..19a5771ac8e 100644 --- a/crates/rustc_codegen_spirv/src/builder/mod.rs +++ b/crates/rustc_codegen_spirv/src/builder/mod.rs @@ -7,7 +7,7 @@ pub mod libm_intrinsics; mod spirv_asm; pub use ext_inst::ExtInst; -use rustc_span::DUMMY_SP; +use rustc_span::{BytePos, DUMMY_SP, SourceFile, Symbol}; pub use spirv_asm::InstructionTable; // HACK(eddyb) avoids rewriting all of the imports (see `lib.rs` and `build.rs`). @@ -185,24 +185,15 @@ impl<'a, 'tcx> DebugInfoBuilderMethods<'_> for Builder<'a, 'tcx> { _indirect_offsets: &[Size], _fragment: &Option>, ) { - todo!() } - fn set_dbg_loc(&mut self, _: Self::DILocation) { - todo!() - } + fn set_dbg_loc(&mut self, _: Self::DILocation) {} - fn clear_dbg_loc(&mut self) { - todo!() - } + fn clear_dbg_loc(&mut self) {} - fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) { - todo!() - } + fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {} - fn set_var_name(&mut self, _value: Self::Value, _name: &str) { - todo!() - } + fn set_var_name(&mut self, _value: Self::Value, _name: &str) {} fn dbg_var_value( &mut self, @@ -216,7 +207,54 @@ impl<'a, 'tcx> DebugInfoBuilderMethods<'_> for Builder<'a, 'tcx> { // if this is a fragment of a composite `DIVariable`. _fragment: &Option>, ) { - todo!() + } + + fn dbg_scope_fn( + &mut self, + _instance: Instance<'_>, + _fn_abi: &FnAbi<'_, Ty<'_>>, + _maybe_definition_llfn: Option, + ) -> Self::DIScope { + } + + fn dbg_create_lexical_block( + &mut self, + _pos: BytePos, + _parent_scope: Self::DIScope, + ) -> Self::DIScope { + } + + fn dbg_location_clone_with_discriminator( + &mut self, + _loc: Self::DILocation, + _discriminator: u32, + ) -> Option { + None + } + + fn dbg_loc( + &mut self, + _scope: Self::DIScope, + _inlined_at: Option, + _span: Span, + ) -> Self::DILocation { + } + + fn extend_scope_to_file( + &mut self, + _scope_metadata: Self::DIScope, + _file: &SourceFile, + ) -> Self::DIScope { + } + + fn create_dbg_var( + &mut self, + _variable_name: Symbol, + _variable_type: Ty<'_>, + _scope_metadata: Self::DIScope, + _variable_kind: rustc_codegen_ssa::mir::debuginfo::VariableKind, + _span: Span, + ) -> Self::DIVariable { } } diff --git a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs index e83ca9f0ed4..86f380fa621 100644 --- a/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs +++ b/crates/rustc_codegen_spirv/src/builder/spirv_asm.rs @@ -3,8 +3,10 @@ use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa; use super::Builder; use crate::abi::ConvSpirvType; -use crate::builder_spirv::{SpirvValue, SpirvValueExt, SpirvValueKind}; +use crate::builder_spirv::{SpirvBlockCursor, SpirvValue, SpirvValueExt, SpirvValueKind}; use crate::codegen_cx::CodegenCx; +use crate::maybe_pqp_cg_ssa::mir::operand::OperandRef; +use crate::maybe_pqp_cg_ssa::traits::BackendTypes; use crate::spirv_type::SpirvType; use rspirv::dr; use rspirv::grammar::{LogicalOperand, OperandKind, OperandQuantifier, reflect}; @@ -17,11 +19,12 @@ use rustc_abi::{BackendRepr, Primitive}; use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::mir::operand::OperandValue; use rustc_codegen_ssa::mir::place::PlaceRef; -use rustc_codegen_ssa::traits::{ - AsmBuilderMethods, BackendTypes, BuilderMethods, InlineAsmOperandRef, -}; +use rustc_codegen_ssa::traits::{AsmBuilderMethods, BuilderMethods, InlineAsmOperandRef}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_middle::{bug, ty::Instance}; +use rustc_middle::mir::interpret::Scalar; +use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::{bug, span_bug, ty::Instance}; +use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, Span}; use rustc_target::asm::{InlineAsmRegClass, InlineAsmRegOrRegClass, SpirVInlineAsmRegClass}; use smallvec::SmallVec; @@ -40,32 +43,80 @@ impl InstructionTable { } } -// HACK(eddyb) `InlineAsmOperandRef` lacks `#[derive(Clone)]` -fn inline_asm_operand_ref_clone<'tcx, B: BackendTypes + ?Sized>( - operand: &InlineAsmOperandRef<'tcx, B>, -) -> InlineAsmOperandRef<'tcx, B> { - use InlineAsmOperandRef::*; - - match operand { - &In { reg, value } => In { reg, value }, - &Out { reg, late, place } => Out { reg, late, place }, - &InOut { - reg, - late, - in_value, - out_place, - } => InOut { - reg, - late, - in_value, - out_place, - }, - Const { string } => Const { - string: string.clone(), - }, - &SymFn { instance } => SymFn { instance }, - &SymStatic { def_id } => SymStatic { def_id }, - &Label { label } => Label { label }, +#[expect( + dead_code, + reason = "keep asm structs like upstream with minimal changes" +)] +#[derive(Debug)] +pub enum SpvInlineAsmOperandRef<'tcx> { + In { + reg: InlineAsmRegOrRegClass, + value: OperandRef<'tcx, SpirvValue>, + }, + Out { + reg: InlineAsmRegOrRegClass, + late: bool, + place: Option>, + }, + InOut { + reg: InlineAsmRegOrRegClass, + late: bool, + in_value: OperandRef<'tcx, SpirvValue>, + out_place: Option>, + }, + Const { + string: String, + }, + SymThreadLocalStatic { + def_id: DefId, + }, + Label { + label: SpirvBlockCursor, + }, +} + +impl<'tcx> SpvInlineAsmOperandRef<'tcx> { + fn from + ?Sized>( + cx: &CodegenCx<'tcx>, + operand: &InlineAsmOperandRef<'tcx, B>, + span: Span, + ) -> Self { + match *operand { + InlineAsmOperandRef::In { reg, value } => Self::In { reg, value }, + InlineAsmOperandRef::Out { reg, late, place } => Self::Out { reg, late, place }, + InlineAsmOperandRef::InOut { + reg, + late, + in_value, + out_place, + } => Self::InOut { + reg, + late, + in_value, + out_place, + }, + InlineAsmOperandRef::Const { value, ty } => match value { + Scalar::Int(value) => { + let string = rustc_codegen_ssa::common::asm_const_to_str( + cx.tcx, + span, + value, + cx.layout_of(ty), + ); + Self::Const { string } + } + Scalar::Ptr(_, _) => { + span_bug!( + span, + "spirv can't handle `InlineAsmOperandRef::Const {{ value: Scalar::Ptr(_, _) }}`", + ) + } + }, + InlineAsmOperandRef::Label { label } => Self::Label { label }, + InlineAsmOperandRef::SymThreadLocalStatic { def_id } => { + Self::SymThreadLocalStatic { def_id } + } + } } } @@ -109,22 +160,24 @@ impl<'a, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'tcx> { // HACK(eddyb) get more accurate pointers types, for pointer operands, // from the Rust types available in their respective `OperandRef`s. - let mut operands: SmallVec<[_; 8]> = - operands.iter().map(inline_asm_operand_ref_clone).collect(); + let span = line_spans.first().copied().unwrap_or_default(); + let mut operands: SmallVec<[_; 8]> = operands + .iter() + .map(|operand| SpvInlineAsmOperandRef::from(self.cx, operand, span)) + .collect(); for operand in &mut operands { let (in_value, out_place) = match operand { - InlineAsmOperandRef::In { value, .. } => (Some(value), None), - InlineAsmOperandRef::InOut { + SpvInlineAsmOperandRef::In { value, .. } => (Some(value), None), + SpvInlineAsmOperandRef::InOut { in_value, out_place, .. } => (Some(in_value), out_place.as_mut()), - InlineAsmOperandRef::Out { place, .. } => (None, place.as_mut()), + SpvInlineAsmOperandRef::Out { place, .. } => (None, place.as_mut()), - InlineAsmOperandRef::Const { .. } - | InlineAsmOperandRef::SymFn { .. } - | InlineAsmOperandRef::SymStatic { .. } - | InlineAsmOperandRef::Label { .. } => (None, None), + SpvInlineAsmOperandRef::Const { .. } + | SpvInlineAsmOperandRef::Label { .. } + | SpvInlineAsmOperandRef::SymThreadLocalStatic { .. } => (None, None), }; if let Some(in_value) = in_value @@ -201,7 +254,9 @@ impl<'a, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'tcx> { Token::Typeof(&operands[operand_idx], span, kind); } None => match &operands[operand_idx] { - InlineAsmOperandRef::Const { string } => line.push(Token::Word(string)), + SpvInlineAsmOperandRef::Const { string } => { + line.push(Token::Word(string)); + } item => line.push(Token::Placeholder(item, span)), }, } @@ -213,7 +268,7 @@ impl<'a, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'tcx> { let mut defined_ids = FxHashSet::default(); let mut id_to_type_map = FxHashMap::default(); for operand in &operands { - if let InlineAsmOperandRef::In { reg: _, value } = operand { + if let SpvInlineAsmOperandRef::In { reg: _, value } = operand { let value = value.immediate(); id_to_type_map.insert(value.def(self), value.ty); } @@ -275,15 +330,11 @@ enum TypeofKind { Dereference, } -enum Token<'a, 'cx, 'tcx> { +enum Token<'a, 'tcx> { Word(&'a str), String(String), - Placeholder(&'a InlineAsmOperandRef<'tcx, Builder<'cx, 'tcx>>, Span), - Typeof( - &'a InlineAsmOperandRef<'tcx, Builder<'cx, 'tcx>>, - Span, - TypeofKind, - ), + Placeholder(&'a SpvInlineAsmOperandRef<'tcx>, Span), + Typeof(&'a SpvInlineAsmOperandRef<'tcx>, Span, TypeofKind), } enum OutRegister<'tcx> { @@ -297,7 +348,7 @@ enum AsmBlock { } impl<'cx, 'tcx> Builder<'cx, 'tcx> { - fn lex_word<'a>(&self, line: &mut std::str::Chars<'a>) -> Option> { + fn lex_word<'a>(&self, line: &mut std::str::Chars<'a>) -> Option> { loop { let start = line.as_str(); match line.next()? { @@ -512,7 +563,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { defined_ids: &mut FxHashSet, id_to_type_map: &mut FxHashMap, asm_block: &mut AsmBlock, - mut tokens: impl Iterator>, + mut tokens: impl Iterator>, ) where 'cx: 'a, 'tcx: 'a, @@ -601,7 +652,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { &mut self, id_map: &mut FxHashMap<&'a str, Word>, id_to_type_map: &FxHashMap, - mut tokens: impl Iterator>, + mut tokens: impl Iterator>, instruction: &mut dr::Instruction, ) where 'cx: 'a, @@ -909,7 +960,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { &mut self, id_map: &mut FxHashMap<&'a str, Word>, defined_ids: &mut FxHashSet, - token: Token<'a, 'cx, 'tcx>, + token: Token<'a, 'tcx>, ) -> Option> { match token { Token::Word(word) => { @@ -937,14 +988,14 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { None } Token::Placeholder(hole, span) => match hole { - InlineAsmOperandRef::In { reg, value: _ } => { + SpvInlineAsmOperandRef::In { reg, value: _ } => { self.check_reg(span, reg); self.tcx .dcx() .span_err(span, "in register cannot be assigned to"); None } - InlineAsmOperandRef::Out { + SpvInlineAsmOperandRef::Out { reg, late: _, place, @@ -957,7 +1008,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { None } } - InlineAsmOperandRef::InOut { + SpvInlineAsmOperandRef::InOut { reg, late: _, in_value: _, @@ -971,28 +1022,22 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { None } } - InlineAsmOperandRef::Const { string: _ } => { + SpvInlineAsmOperandRef::Const { .. } => { self.tcx .dcx() .span_err(span, "cannot write to const asm argument"); None } - InlineAsmOperandRef::SymFn { instance: _ } => { - self.tcx - .dcx() - .span_err(span, "cannot write to function asm argument"); - None - } - InlineAsmOperandRef::SymStatic { def_id: _ } => { + SpvInlineAsmOperandRef::Label { label: _ } => { self.tcx .dcx() - .span_err(span, "cannot write to static variable asm argument"); + .span_err(span, "cannot write to label asm argument"); None } - InlineAsmOperandRef::Label { label: _ } => { + SpvInlineAsmOperandRef::SymThreadLocalStatic { .. } => { self.tcx .dcx() - .span_err(span, "cannot write to label asm argument"); + .span_err(span, "cannot write to SymThreadLocalStatic asm argument"); None } }, @@ -1002,7 +1047,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { fn parse_id_in<'a>( &mut self, id_map: &mut FxHashMap<&'a str, Word>, - token: Token<'a, 'cx, 'tcx>, + token: Token<'a, 'tcx>, ) -> Option { match token { Token::Word(word) => { @@ -1018,7 +1063,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { None } Token::Typeof(hole, span, kind) => match hole { - InlineAsmOperandRef::In { reg, value } => { + SpvInlineAsmOperandRef::In { reg, value } => { self.check_reg(span, reg); let ty = value.immediate().ty; Some(match kind { @@ -1038,7 +1083,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { }, }) } - InlineAsmOperandRef::Out { + SpvInlineAsmOperandRef::Out { reg, late: _, place, @@ -1065,7 +1110,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { None } } - InlineAsmOperandRef::InOut { + SpvInlineAsmOperandRef::InOut { reg, late: _, in_value, @@ -1074,38 +1119,31 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { self.check_reg(span, reg); Some(in_value.immediate().ty) } - InlineAsmOperandRef::Const { string: _ } => { + SpvInlineAsmOperandRef::Const { .. } => { self.tcx .dcx() .span_err(span, "cannot take the type of a const asm argument"); None } - InlineAsmOperandRef::SymFn { instance: _ } => { + SpvInlineAsmOperandRef::Label { label: _ } => { self.tcx .dcx() - .span_err(span, "cannot take the type of a function asm argument"); - None - } - InlineAsmOperandRef::SymStatic { def_id: _ } => { - self.tcx.dcx().span_err( - span, - "cannot take the type of a static variable asm argument", - ); + .span_err(span, "cannot take the type of a label asm argument"); None } - InlineAsmOperandRef::Label { label: _ } => { + SpvInlineAsmOperandRef::SymThreadLocalStatic { .. } => { self.tcx .dcx() - .span_err(span, "cannot take the type of a label asm argument"); + .span_err(span, "cannot write to SymThreadLocalStatic asm argument"); None } }, Token::Placeholder(hole, span) => match hole { - InlineAsmOperandRef::In { reg, value } => { + SpvInlineAsmOperandRef::In { reg, value } => { self.check_reg(span, reg); Some(value.immediate().def(self)) } - InlineAsmOperandRef::Out { + SpvInlineAsmOperandRef::Out { reg, late: _, place: _, @@ -1116,7 +1154,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { .span_err(span, "out register cannot be used as a value"); None } - InlineAsmOperandRef::InOut { + SpvInlineAsmOperandRef::InOut { reg, late: _, in_value, @@ -1125,28 +1163,22 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { self.check_reg(span, reg); Some(in_value.immediate().def(self)) } - InlineAsmOperandRef::Const { string: _ } => { + SpvInlineAsmOperandRef::Const { .. } => { self.tcx .dcx() .span_err(span, "const asm argument not supported yet"); None } - InlineAsmOperandRef::SymFn { instance: _ } => { + SpvInlineAsmOperandRef::Label { label: _ } => { self.tcx .dcx() - .span_err(span, "function asm argument not supported yet"); - None - } - InlineAsmOperandRef::SymStatic { def_id: _ } => { - self.tcx - .dcx() - .span_err(span, "static variable asm argument not supported yet"); + .span_err(span, "label asm argument not supported yet"); None } - InlineAsmOperandRef::Label { label: _ } => { + SpvInlineAsmOperandRef::SymThreadLocalStatic { .. } => { self.tcx .dcx() - .span_err(span, "label asm argument not supported yet"); + .span_err(span, "cannot write to SymThreadLocalStatic asm argument"); None } }, @@ -1158,7 +1190,7 @@ impl<'cx, 'tcx> Builder<'cx, 'tcx> { id_map: &mut FxHashMap<&'a str, Word>, inst: &mut dr::Instruction, kind: OperandKind, - tokens: &mut impl Iterator>, + tokens: &mut impl Iterator>, ) -> bool where 'cx: 'a, diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs index 2932f3e4234..0ef855f63d7 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs @@ -11,6 +11,7 @@ use rustc_abi::{self as abi, AddressSpace, Float, HasDataLayout, Integer, Primit use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods}; use rustc_middle::mir::interpret::{AllocError, ConstAllocation, GlobalAlloc, Scalar, alloc_range}; use rustc_middle::ty::layout::LayoutOf; +use rustc_session::PointerAuthSchema; use rustc_span::{DUMMY_SP, Span}; impl<'tcx> CodegenCx<'tcx> { @@ -226,6 +227,16 @@ impl ConstCodegenMethods for CodegenCx<'_> { self.builder.lookup_const_scalar(v) } + fn scalar_to_backend_with_pac( + &self, + cv: Scalar, + layout: rustc_abi::Scalar, + ty: Self::Type, + _pac: Option<&PointerAuthSchema>, + ) -> Self::Value { + self.scalar_to_backend(cv, layout, ty) + } + fn scalar_to_backend( &self, scalar: Scalar, @@ -268,7 +279,7 @@ impl ConstCodegenMethods for CodegenCx<'_> { (value, AddressSpace::ZERO) } GlobalAlloc::Function { instance } => ( - self.get_fn_addr(instance), + self.get_fn_addr(instance, None), self.data_layout().instruction_address_space, ), GlobalAlloc::VTable(vty, dyn_ty) => { diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs index 601f2b093d5..d9fbd9573bd 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs @@ -12,7 +12,10 @@ use rspirv::spirv::{ BuiltIn, Decoration, Dim, ExecutionModel, FunctionControl, StorageClass, Word, }; use rustc_abi::FieldsShape; -use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, MiscCodegenMethods as _}; +use rustc_codegen_ssa::traits::{ + BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, LayoutTypeCodegenMethods, + MiscCodegenMethods as _, +}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::MultiSpan; use rustc_hir as hir; @@ -87,22 +90,7 @@ impl<'tcx> CodegenCx<'tcx> { }; for (arg_abi, hir_param) in fn_abi.args.iter().zip(hir_params) { match arg_abi.mode { - PassMode::Direct(_) | PassMode::Ignore => {} - PassMode::Pair(..) => { - // FIXME(eddyb) implement `ScalarPair` `Input`s, or change - // the `FnAbi` readjustment to only use `PassMode::Pair` for - // pointers to `!Sized` types, but not other `ScalarPair`s. - if !matches!(arg_abi.layout.ty.kind(), ty::Ref(..)) { - self.tcx.dcx().span_err( - hir_param.ty_span, - format!( - "entry point parameter type not yet supported \ - (`{}` has `ScalarPair` ABI but is not a `&T`)", - arg_abi.layout.ty - ), - ); - } - } + PassMode::Direct(_) | PassMode::Pair(..) | PassMode::Ignore => {} _ => span_bug!( hir_param.ty_span, "query hooks should've made this `PassMode` impossible: {:#?}", @@ -191,7 +179,7 @@ impl<'tcx> CodegenCx<'tcx> { self.get_fn(entry_instance).ty, None, Some(entry_fn_abi), - self.get_fn_addr(entry_instance), + self.get_fn_addr(entry_instance, None), &call_args, None, None, @@ -517,14 +505,6 @@ impl<'tcx> CodegenCx<'tcx> { vs layout:\n{value_layout:#?}", entry_arg_abi.layout.ty ); - if is_pair && !is_unsized { - // If PassMode is Pair, then we need to fill in the second part of the pair with a - // value. We currently only do that with unsized types, so if a type is a pair for some - // other reason (e.g. a tuple), we bail. - self.tcx - .dcx() - .span_fatal(hir_param.ty_span, "pair type not supported yet") - } // FIXME(eddyb) should this talk about "typed buffers" instead of "interface blocks"? // FIXME(eddyb) should we talk about "descriptor indexing" or // actually use more reasonable terms like "resource arrays"? @@ -647,8 +627,8 @@ impl<'tcx> CodegenCx<'tcx> { } } - let value_len = if is_pair { - // We've already emitted an error, fill in a placeholder value + let value_len = if is_pair && is_unsized { + // For wide references (e.g., slices), the second component is a length. Some(bx.undef(self.type_isize())) } else { None @@ -693,6 +673,31 @@ impl<'tcx> CodegenCx<'tcx> { call_args.push(value); assert_eq!(value_len, None); } + PassMode::Pair(..) => { + // Load both elements of the scalar pair from the input variable. + assert_eq!(storage_class, Ok(StorageClass::Input)); + let layout = entry_arg_abi.layout; + let rustc_abi::BackendRepr::ScalarPair { b_offset, .. } = layout.backend_repr + else { + span_bug!( + hir_param.ty_span, + "ScalarPair expected for entry param, found {:?}", + layout.backend_repr + ) + }; + + let elem0_ty = self.scalar_pair_element_backend_type(layout, 0, false); + let elem1_ty = self.scalar_pair_element_backend_type(layout, 1, false); + + let base_ptr = value_ptr.unwrap(); + let ptr1 = bx.inbounds_ptradd(base_ptr, self.const_usize(b_offset.bytes())); + + let v0 = bx.load(elem0_ty, base_ptr, layout.align.abi); + let v1 = bx.load(elem1_ty, ptr1, layout.align.restrict_for_offset(b_offset)); + call_args.push(v0); + call_args.push(v1); + assert_eq!(value_len, None); + } _ => unreachable!(), } } diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs index 4008496c20a..236bc5f4adf 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/mod.rs @@ -21,21 +21,18 @@ use rspirv::dr::{Module, Operand}; use rspirv::spirv::{Decoration, LinkageType, 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::{ AsmCodegenMethods, BackendTypes, DebugInfoCodegenMethods, GlobalAsmOperandRef, MiscCodegenMethods, }; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::DefId; -use rustc_middle::mir; use rustc_middle::mono::CodegenUnit; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypingEnv}; -use rustc_session::Session; +use rustc_session::{PointerAuthSchema, Session}; use rustc_span::symbol::Symbol; -use rustc_span::{DUMMY_SP, SourceFile, Span}; -use rustc_target::callconv::FnAbi; +use rustc_span::{DUMMY_SP, Span}; use rustc_target::spec::{HasTargetSpec, Target, TargetTuple}; use std::cell::RefCell; use std::collections::BTreeSet; @@ -911,7 +908,11 @@ impl<'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'tcx> { // NOTE(eddyb) see the comment on `SpirvValueKind::FnAddr`, this should // be fixed upstream, so we never see any "function pointer" values being // created just to perform direct calls. - fn get_fn_addr(&self, instance: Instance<'tcx>) -> Self::Value { + fn get_fn_addr( + &self, + instance: Instance<'tcx>, + _pac: Option<&PointerAuthSchema>, + ) -> Self::Value { let function = self.get_fn(instance); let span = self.tcx.def_span(instance.def_id()); @@ -951,6 +952,10 @@ impl<'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'tcx> { fn declare_c_main(&self, _fn_type: Self::FunctionSignature) -> Option { todo!() } + + fn intrinsic_call_expects_place_always(&self, _: Symbol) -> bool { + true + } } impl<'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'tcx> { @@ -962,53 +967,6 @@ impl<'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'tcx> { ) { // Ignore. } - - fn dbg_scope_fn( - &self, - _: rustc_middle::ty::Instance<'tcx>, - _: &FnAbi<'tcx, Ty<'tcx>>, - _: Option, - ) -> Self::DIScope { - todo!() - } - - fn dbg_loc(&self, _: Self::DIScope, _: Option, _: Span) -> Self::DILocation { - todo!() - } - - fn create_function_debug_context( - &self, - _instance: Instance<'tcx>, - _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, - _llfn: Self::Function, - _mir: &mir::Body<'tcx>, - ) -> Option> { - // TODO: This is ignored. Do we want to implement this at some point? - None - } - - fn extend_scope_to_file( - &self, - _scope_metadata: Self::DIScope, - _file: &SourceFile, - ) -> Self::DIScope { - todo!() - } - - fn debuginfo_finalize(&self) { - todo!() - } - - fn create_dbg_var( - &self, - _variable_name: Symbol, - _variable_type: Ty<'tcx>, - _scope_metadata: Self::DIScope, - _variable_kind: VariableKind, - _span: Span, - ) -> Self::DIVariable { - todo!() - } } impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'tcx> { diff --git a/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs b/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs index c2ef34ee283..f9c146d0bd0 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/type_.rs @@ -5,7 +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_abi::{AddressSpace, Reg}; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, LayoutTypeCodegenMethods}; use rustc_middle::ty::Ty; @@ -94,26 +94,6 @@ impl<'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'tcx> { layout.spirv_type(DUMMY_SP, self) } - fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool { - match layout.backend_repr { - BackendRepr::Scalar(_) - | BackendRepr::SimdScalableVector { .. } - | BackendRepr::SimdVector { .. } => true, - BackendRepr::ScalarPair(..) => false, - BackendRepr::Memory { .. } => layout.is_zst(), - } - } - - fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool { - match layout.backend_repr { - BackendRepr::ScalarPair(..) => true, - BackendRepr::Scalar(_) - | BackendRepr::SimdScalableVector { .. } - | BackendRepr::SimdVector { .. } - | BackendRepr::Memory { .. } => false, - } - } - fn scalar_pair_element_backend_type( &self, layout: TyAndLayout<'tcx>, diff --git a/crates/rustc_codegen_spirv/src/lib.rs b/crates/rustc_codegen_spirv/src/lib.rs index 857255dbfa3..bbcf14e7f02 100644 --- a/crates/rustc_codegen_spirv/src/lib.rs +++ b/crates/rustc_codegen_spirv/src/lib.rs @@ -2,7 +2,7 @@ #![feature(deref_patterns)] #![feature(file_buffered)] #![feature(negative_impls)] -#![feature(string_from_utf8_lossy_owned)] +#![feature(option_into_flat_iter)] #![feature(trait_alias)] #![feature(try_blocks)] #![recursion_limit = "256"] @@ -152,16 +152,15 @@ use maybe_pqp_cg_ssa::{ }; use rspirv::binary::Assemble; use rustc_ast::expand::allocator::AllocatorMethod; -use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::DiagCtxtHandle; use rustc_metadata::EncodedMetadata; -use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; +use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; use rustc_middle::mono::{MonoItem, MonoItemData}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{InstanceKind, TyCtxt}; -use rustc_session::Session; use rustc_session::config::{self, OutputFilenames, OutputType}; +use rustc_session::{IncrCompSession, Session}; use rustc_span::symbol::Symbol; use std::any::Any; use std::fs; @@ -256,13 +255,14 @@ impl CodegenBackend for SpirvCodegenBackend { &self, ongoing_codegen: Box, sess: &Session, + incr_comp_session: Option<&IncrCompSession>, _outputs: &OutputFilenames, crate_info: &CrateInfo, - ) -> (CompiledModules, FxIndexMap) { + ) -> (CompiledModules, WorkProductMap) { ongoing_codegen .downcast::>() .expect("Expected OngoingCodegen, found Box") - .join(sess, crate_info) + .join(sess, incr_comp_session, crate_info) } fn link( @@ -411,6 +411,7 @@ impl WriteBackendMethods for SpirvCodegenBackend { name, kind, object: Some(path), + global_asm_object: None, dwarf_object: None, bytecode: None, assembly: None, @@ -434,6 +435,8 @@ impl WriteBackendMethods for SpirvCodegenBackend { } impl ExtraBackendMethods for SpirvCodegenBackend { + type Module = rspirv::dr::Module; + fn codegen_allocator(&self, _: TyCtxt<'_>, _: &str, _: &[AllocatorMethod]) -> Self::Module { todo!() } diff --git a/crates/rustc_codegen_spirv/src/linker/test.rs b/crates/rustc_codegen_spirv/src/linker/test.rs index d1560409b21..e06a861e3c3 100644 --- a/crates/rustc_codegen_spirv/src/linker/test.rs +++ b/crates/rustc_codegen_spirv/src/linker/test.rs @@ -98,7 +98,7 @@ fn link_with_linker_opts( // is really a silent unwinding device, that should be treated the same as // `Err(ErrorGuaranteed)` returns from `link`). rustc_driver::catch_fatal_errors(|| { - rustc_data_structures::jobserver::initialize_checked(|err| { + rustc_data_structures::jobserver::initialize(99, |err| { unreachable!("jobserver error: {err}"); }); diff --git a/examples/runners/wgpu/src/compute.rs b/examples/runners/wgpu/src/compute.rs index f81282d1c48..4cb646c5f25 100644 --- a/examples/runners/wgpu/src/compute.rs +++ b/examples/runners/wgpu/src/compute.rs @@ -248,8 +248,10 @@ async fn start_internal(options: &Options, compiled_shader_modules: CompiledShad .get_mapped_range() .unwrap(); let timings = timing_data - .chunks_exact(8) - .map(|b| u64::from_ne_bytes(b.try_into().unwrap())) + .as_chunks::<8>() + .0 + .iter() + .map(|b| u64::from_ne_bytes(*b)) .collect::>(); println!( @@ -265,8 +267,10 @@ async fn start_internal(options: &Options, compiled_shader_modules: CompiledShad let data = buffer_slice.get_mapped_range().unwrap(); let result = data - .chunks_exact(4) - .map(|b| u32::from_ne_bytes(b.try_into().unwrap())) + .as_chunks::<4>() + .0 + .iter() + .map(|b| u32::from_ne_bytes(*b)) .collect::>(); drop(data); readback_buffer.unmap(); diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 195e4c217d8..f5f633ab355 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,7 +1,7 @@ [toolchain] -channel = "nightly-2026-05-22" +channel = "nightly-2026-08-06" components = ["rust-src", "rustc-dev", "llvm-tools"] -# commit_hash = e96c36b6f76833388c519561d145492d2c08db4e +# commit_hash = 7608eb7b07eaf93f16d7cf5bcb2098eca87503df # Whenever changing the nightly channel, update the commit hash above, and # change `REQUIRED_RUST_TOOLCHAIN` in `crates/rustc_codegen_spirv/build.rs` too. diff --git a/tests/compiletests/src/main.rs b/tests/compiletests/src/main.rs index 23407eb9e51..1b3a37defd7 100644 --- a/tests/compiletests/src/main.rs +++ b/tests/compiletests/src/main.rs @@ -45,8 +45,8 @@ impl DepKind { fn target_dir_suffix(self, target: &SpirvTarget) -> String { match self { - Self::SpirvLib => format!("{}/debug/deps", target.target()), - Self::ProcMacro => "debug/deps".into(), + Self::SpirvLib => format!("{}/debug/build", target.target()), + Self::ProcMacro => "debug/build".into(), } } } @@ -101,27 +101,17 @@ impl Runner { /// RUSTFLAGS passed to all test files. fn test_rustc_flags( codegen_backend_path: &Path, - deps: &TestDeps, - indirect_deps_dirs: &[&Path], + deps: &[TestDep], + search_dirs: &[PathBuf], ) -> String { [ &*rust_flags(codegen_backend_path), - &*indirect_deps_dirs + &*search_dirs .iter() .map(|dir| format!("-L dependency={}", dir.display())) - .fold(String::new(), |a, b| b + " " + &a), + .join(" "), "--edition 2021", - &*format!("--extern noprelude:core={}", deps.core.display()), - &*format!( - "--extern noprelude:compiler_builtins={}", - deps.compiler_builtins.display() - ), - &*format!( - "--extern spirv_std_macros={}", - deps.spirv_std_macros.display() - ), - &*format!("--extern spirv_std={}", deps.spirv_std.display()), - &*format!("--extern glam={}", deps.glam.display()), + &*deps.iter().map(TestDep::to_rustc_extern).join(" "), "--crate-type dylib", "-Zunstable-options", "-Zcrate-attr=no_std", @@ -166,18 +156,8 @@ impl Runner { .unwrap(); let libs = self.build_deps(&target, &target_spec); - 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 search_dirs = self.dep_search_dirs(&target); + let mut flags = test_rustc_flags(&self.codegen_backend_path, &libs, &search_dirs); flags += variation.extra_flags; let config = compiletest::Config { @@ -199,7 +179,7 @@ impl Runner { } /// Runs the processes needed to build `spirv-std` & other deps. - fn build_deps(&self, target: &SpirvTarget, target_spec: &TargetSpec) -> TestDeps { + fn build_deps(&self, target: &SpirvTarget, target_spec: &TargetSpec) -> Vec { // Build compiletests-deps-helper let mut cmd = std::process::Command::new("cargo"); cmd.args([ @@ -208,6 +188,7 @@ impl Runner { "compiletests-deps-helper", "-Zbuild-std=core", "-Zbuild-std-features=compiler-builtins-mem", + "-Zbuild-dir-new-layout", ]); target_spec.append_to_cmd(&mut cmd); cmd.arg("--target-dir") @@ -219,44 +200,23 @@ impl Runner { .and_then(map_status_to_result) .unwrap(); - let compiler_builtins = self.find_lib("compiler_builtins", DepKind::SpirvLib, target); - let core = self.find_lib("core", DepKind::SpirvLib, target); - let spirv_std = self.find_lib("spirv_std", DepKind::SpirvLib, target); - let glam = self.find_lib("glam", DepKind::SpirvLib, target); - let spirv_std_macros = self.find_lib("spirv_std_macros", DepKind::ProcMacro, target); - - let all_libs = [ - &compiler_builtins, - &core, - &spirv_std, - &glam, - &spirv_std_macros, - ]; - if all_libs.iter().any(|r| r.is_err()) { - // FIXME(eddyb) `missing_count` should always be `0` anyway. - // FIXME(eddyb) use `--message-format=json-render-diagnostics` to - // avoid caring about duplicates (or search within files at all). - let missing_count = all_libs - .iter() - .filter(|r| matches!(r, Err(FindLibError::Missing))) - .count(); - let duplicate_count = all_libs - .iter() - .filter(|r| matches!(r, Err(FindLibError::Duplicate))) - .count(); - eprintln!( - "warning: cleaning deps ({missing_count} missing libs, {duplicate_count} duplicated libs)" - ); + let all_deps: Result<_, ()> = (|| { + Ok([ + self.find_lib("compiler_builtins", DepKind::SpirvLib, target)? + .no_prelude(), + self.find_lib("core", DepKind::SpirvLib, target)? + .no_prelude(), + self.find_lib("spirv-std", DepKind::SpirvLib, target)?, + self.find_lib("glam", DepKind::SpirvLib, target)?, + self.find_lib("spirv-std-macros", DepKind::ProcMacro, target)?, + ]) + })(); + if let Ok(all_deps) = all_deps { + Vec::from(all_deps) + } else { + eprintln!("warning: cleaning and rebuilding deps"); self.clean_deps(); self.build_deps(target, target_spec) - } else { - TestDeps { - core: core.ok().unwrap(), - glam: glam.ok().unwrap(), - compiler_builtins: compiler_builtins.ok().unwrap(), - spirv_std: spirv_std.ok().unwrap(), - spirv_std_macros: spirv_std_macros.ok().unwrap(), - } } } @@ -271,81 +231,83 @@ impl Runner { } } -enum FindLibError { - Missing, - Duplicate, -} - impl Runner { + /// search for `out` dirs for all compiled libraries + fn dep_search_dirs(&self, target: &SpirvTarget) -> Vec { + [ + self.deps_target_dir + .join(DepKind::SpirvLib.target_dir_suffix(target)), + self.deps_target_dir + .join(DepKind::ProcMacro.target_dir_suffix(target)), + ] + .iter() + .filter_map(|build_dir| std::fs::read_dir(build_dir).ok()) + .flatten() + .filter_map(|crate_dir| std::fs::read_dir(crate_dir.ok()?.path()).ok()) + .flatten() + .filter_map(|hash_dir| { + let out_dir = hash_dir.ok()?.path().join("out"); + out_dir.is_dir().then_some(out_dir) + }) + .collect() + } + /// Attempt find the rlib that matches `base`, if multiple rlibs are found then /// a clean build is required and `Err(FindLibError::Duplicate)` is returned. - fn find_lib( - &self, - base: impl AsRef, - dep_kind: DepKind, - target: &SpirvTarget, - ) -> Result { - let base = base.as_ref(); - let (expected_prefix, expected_extension) = dep_kind.prefix_and_extension(); - let expected_name = format!("{}{}", expected_prefix, base.display()); - - let dir = self + fn find_lib(&self, name: &str, dep_kind: DepKind, target: &SpirvTarget) -> Result { + let ident_name = name.replace("-", "_"); + let (expected_prefix, expected_suffix) = dep_kind.prefix_and_extension(); + let expected_prefix = format!("{expected_prefix}{}", ident_name); + let build_dir = self .deps_target_dir - .join(dep_kind.target_dir_suffix(target)); - - std::fs::read_dir(dir) - .unwrap() - .map(|entry| entry.unwrap().path()) - .filter(move |path| { - let name = { - let name = path.file_stem(); - if name.is_none() { - return false; - } - name.unwrap() - }; - - let name_matches = name.to_str().unwrap().starts_with(&expected_name) - && name.len() == expected_name.len() + 17 // we expect our name, '-', and then 16 hexadecimal digits - && ends_with_dash_hash(name.to_str().unwrap()); - let extension_matches = path - .extension() - .is_some_and(|ext| ext == expected_extension); - - name_matches && extension_matches + .join(dep_kind.target_dir_suffix(target)) + .join(name); + + let rlib = std::fs::read_dir(&build_dir) + .unwrap_or_else(|_| panic!("Couldn't read dir {}", build_dir.display())) + .filter_map(|entry| { + let out_dir = entry.ok()?.path().join("out"); + std::fs::read_dir(out_dir).ok() }) - .exactly_one() - .map_err(|mut iter| { - if iter.next().is_none() { - FindLibError::Missing - } else { - FindLibError::Duplicate - } + .flatten() + .filter_map(|entry| { + let path = entry.ok()?.path(); + let file_name = path.file_name()?.to_str()?; + (file_name.starts_with(&expected_prefix) && file_name.ends_with(expected_suffix)) + .then_some(path) }) + .exactly_one() + .map_err(|_e| ())?; + Ok(TestDep::new(ident_name, rlib)) } } -/// Returns whether this string ends with a dash ('-'), followed by 16 lowercase hexadecimal characters -fn ends_with_dash_hash(s: &str) -> bool { - let n = s.len(); - if n < 17 { - return false; - } - let mut bytes = s.bytes().skip(n - 17); - if bytes.next() != Some(b'-') { - return false; +struct TestDep { + name: String, + rlib: PathBuf, + no_prelude: bool, +} + +impl TestDep { + pub fn new(name: String, rlib: PathBuf) -> Self { + Self { + name, + rlib, + no_prelude: false, + } } - bytes.all(|b| b.is_ascii_hexdigit()) -} + pub fn no_prelude(self) -> Self { + Self { + no_prelude: true, + ..self + } + } -/// Paths to all of the library artifacts of dependencies needed to compile tests. -struct TestDeps { - core: PathBuf, - compiler_builtins: PathBuf, - spirv_std: PathBuf, - spirv_std_macros: PathBuf, - glam: PathBuf, + pub fn to_rustc_extern(&self) -> String { + let noprelude = if self.no_prelude { "noprelude:" } else { "" }; + format!("--extern {noprelude}{}={}", self.name, self.rlib.display()) + } } /// The RUSTFLAGS passed to all SPIR-V builds. diff --git a/tests/compiletests/ui/arch/debug_printf_type_checking.stderr b/tests/compiletests/ui/arch/debug_printf_type_checking.stderr index 0e6cd5e4546..4def80e80af 100644 --- a/tests/compiletests/ui/arch/debug_printf_type_checking.stderr +++ b/tests/compiletests/ui/arch/debug_printf_type_checking.stderr @@ -112,7 +112,10 @@ error[E0277]: the trait bound `{float}: spirv_std::Vector` is not satisf --> $DIR/debug_printf_type_checking.rs:24:9 | LL | debug_printf!("%v2f", 11.0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `spirv_std::Vector` is not implemented for `{float}` + | ^^^^^^^^^^^^^^^^^^^^^^----^ + | | | + | | `{float}` doesn't satisfy the trait bound + | the trait `spirv_std::Vector` is not implemented for `{float}` | help: the trait `spirv_std::Vector` is implemented for `Vec2` --> $SPIRV_STD_SRC/vector.rs:71:12 diff --git a/tests/compiletests/ui/arch/subgroup/subgroup_composite_all_equals.stderr b/tests/compiletests/ui/arch/subgroup/subgroup_composite_all_equals.stderr index 08ae7961ea4..ced7a20296a 100644 --- a/tests/compiletests/ui/arch/subgroup/subgroup_composite_all_equals.stderr +++ b/tests/compiletests/ui/arch/subgroup/subgroup_composite_all_equals.stderr @@ -1,15 +1,22 @@ - %1 = OpFunction %2 None %3 - %4 = OpFunctionParameter %5 - %6 = OpLabel - %8 = OpCompositeExtract %9 %4 0 - %11 = OpGroupNonUniformAllEqual %2 %12 %8 - %13 = OpLogicalAnd %2 %14 %11 - %15 = OpCompositeExtract %16 %4 1 - %17 = OpGroupNonUniformAllEqual %2 %12 %15 - %18 = OpLogicalAnd %2 %13 %17 - %19 = OpCompositeExtract %20 %4 2 - %21 = OpGroupNonUniformAllEqual %2 %12 %19 - %22 = OpLogicalAnd %2 %18 %21 - OpNoLine - OpReturnValue %22 - OpFunctionEnd +error: `u8` type used without `OpCapability Int8` + | + = note: used by unnamed constant + = note: used from within `spirv_std::arch::subgroup::subgroup_all_equal::` +note: called by `subgroup_composite_all_equals::disassembly` + --> <$DIR/subgroup_composite_all_equals.rs>:27:5 + | +LL | subgroup_all_equal(my_struct) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: called by `subgroup_composite_all_equals::main` + --> <$DIR/subgroup_composite_all_equals.rs>:44:20 + | +LL | let bool = disassembly(my_struct); + | ^^^^^^^^^^^^^^^^^^^^^^ +note: called by GLCompute entry-point `main` + --> <$DIR/subgroup_composite_all_equals.rs>:31:8 + | +LL | pub fn main( + | ^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/compiletests/ui/dis/complex_image_sample_inst.stderr b/tests/compiletests/ui/dis/complex_image_sample_inst.stderr index 0c4548c3709..7ec86b91766 100644 --- a/tests/compiletests/ui/dis/complex_image_sample_inst.stderr +++ b/tests/compiletests/ui/dis/complex_image_sample_inst.stderr @@ -2,19 +2,17 @@ %4 = OpFunctionParameter %2 %5 = OpFunctionParameter %6 %7 = OpFunctionParameter %6 - %8 = OpLabel - %9 = OpCompositeExtract %10 %5 0 - %11 = OpCompositeExtract %10 %5 1 - %12 = OpCompositeConstruct %6 %9 %11 - %13 = OpCompositeExtract %10 %7 0 - %14 = OpCompositeExtract %10 %7 1 - %15 = OpCompositeConstruct %6 %13 %14 - OpLine %16 29 13 - %17 = OpAccessChain %18 %19 %20 - OpLine %16 30 13 - %21 = OpLoad %22 %17 - OpLine %16 34 13 - %23 = OpImageSampleProjExplicitLod %2 %21 %4 Grad %12 %15 + %8 = OpFunctionParameter %6 + %9 = OpFunctionParameter %6 + %10 = OpLabel + %11 = OpCompositeConstruct %12 %5 %7 + %13 = OpCompositeConstruct %12 %8 %9 + OpLine %14 29 13 + %15 = OpAccessChain %16 %17 %18 + OpLine %14 30 13 + %19 = OpLoad %20 %15 + OpLine %14 34 13 + %21 = OpImageSampleProjExplicitLod %2 %19 %4 Grad %11 %13 OpNoLine - OpReturnValue %23 + OpReturnValue %21 OpFunctionEnd diff --git a/tests/compiletests/ui/dis/ptr_copy.normal.stderr b/tests/compiletests/ui/dis/ptr_copy.normal.stderr index e4fd211dcca..f94204759ab 100644 --- a/tests/compiletests/ui/dis/ptr_copy.normal.stderr +++ b/tests/compiletests/ui/dis/ptr_copy.normal.stderr @@ -1,11 +1,11 @@ error: cannot memcpy dynamically sized data - --> <$CORE_SRC/ptr/mod.rs>:642:9 + --> <$CORE_SRC/ptr/mod.rs>:664:9 | LL | crate::intrinsics::copy(src, dst, count) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: used from within `core::ptr::copy::` - --> <$CORE_SRC/ptr/mod.rs>:627:21 + --> <$CORE_SRC/ptr/mod.rs>:649:21 | LL | pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { | ^^^^ @@ -28,7 +28,7 @@ LL | pub fn main(i: f32, o: &mut f32) { error: cannot cast between pointer types from `*f32` to `*struct () { }` - --> <$CORE_SRC/ptr/mod.rs>:630:9 + --> <$CORE_SRC/ptr/mod.rs>:652:9 | LL | / ub_checks::assert_unsafe_precondition!( LL | | check_language_ub, @@ -39,7 +39,7 @@ LL | | ); | |_________^ | note: used from within `core::ptr::copy::` - --> <$CORE_SRC/ptr/mod.rs>:630:9 + --> <$CORE_SRC/ptr/mod.rs>:652:9 | LL | / ub_checks::assert_unsafe_precondition!( LL | | check_language_ub, diff --git a/tests/compiletests/ui/dis/ptr_read.stderr b/tests/compiletests/ui/dis/ptr_read.stderr index 944037e5252..0a6e73aa798 100644 --- a/tests/compiletests/ui/dis/ptr_read.stderr +++ b/tests/compiletests/ui/dis/ptr_read.stderr @@ -2,7 +2,7 @@ %4 = OpFunctionParameter %5 %6 = OpFunctionParameter %5 %7 = OpLabel - OpLine %8 1733 8 + OpLine %8 1755 8 %9 = OpLoad %10 %4 OpLine %11 7 13 OpStore %6 %9 diff --git a/tests/compiletests/ui/dis/ptr_read_method.stderr b/tests/compiletests/ui/dis/ptr_read_method.stderr index 944037e5252..0a6e73aa798 100644 --- a/tests/compiletests/ui/dis/ptr_read_method.stderr +++ b/tests/compiletests/ui/dis/ptr_read_method.stderr @@ -2,7 +2,7 @@ %4 = OpFunctionParameter %5 %6 = OpFunctionParameter %5 %7 = OpLabel - OpLine %8 1733 8 + OpLine %8 1755 8 %9 = OpLoad %10 %4 OpLine %11 7 13 OpStore %6 %9 diff --git a/tests/compiletests/ui/dis/ptr_write.stderr b/tests/compiletests/ui/dis/ptr_write.stderr index df6879d3aeb..6c0a63b4546 100644 --- a/tests/compiletests/ui/dis/ptr_write.stderr +++ b/tests/compiletests/ui/dis/ptr_write.stderr @@ -4,7 +4,7 @@ %7 = OpLabel OpLine %8 7 35 %9 = OpLoad %10 %4 - OpLine %11 1933 40 + OpLine %11 1963 40 OpStore %6 %9 OpNoLine OpReturn diff --git a/tests/compiletests/ui/dis/ptr_write_method.stderr b/tests/compiletests/ui/dis/ptr_write_method.stderr index 37410271bcd..5a09df7d418 100644 --- a/tests/compiletests/ui/dis/ptr_write_method.stderr +++ b/tests/compiletests/ui/dis/ptr_write_method.stderr @@ -4,7 +4,7 @@ %7 = OpLabel OpLine %8 7 37 %9 = OpLoad %10 %4 - OpLine %11 1933 40 + OpLine %11 1963 40 OpStore %6 %9 OpNoLine OpReturn diff --git a/tests/compiletests/ui/lang/abi/scalar_pair.rs b/tests/compiletests/ui/lang/abi/scalar_pair.rs new file mode 100644 index 00000000000..ed79952fb66 --- /dev/null +++ b/tests/compiletests/ui/lang/abi/scalar_pair.rs @@ -0,0 +1,27 @@ +// build-pass +// compile-flags: -C target-feature=+Int64 + +use spirv_std::spirv; + +#[spirv(fragment)] +pub fn main_future_proof( + #[spirv(flat)] input: (u64, u32), + out: &mut (u64, u32), + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] buffer_in: &(u64, u32), + #[spirv(storage_buffer, descriptor_set = 1, binding = 0)] buffer_out: &mut (u64, u32), +) { + *out = trans0(trans_ref(buffer_in)); + *buffer_out = trans1(input); +} + +pub fn trans0(arg: (u64, u32)) -> (u64, u32) { + (arg.0 + 1, arg.1 - 1) +} + +pub fn trans1((a, b): (u64, u32)) -> (u64, u32) { + (a * 2, b * 3) +} + +pub fn trans_ref((a, b): &(u64, u32)) -> (u64, u32) { + (a - 1, b - 1) +} diff --git a/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr b/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr index 3bed27b94c9..34d9e7d8420 100644 --- a/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr +++ b/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr @@ -8,7 +8,7 @@ warning: black_box intrinsic does not prevent optimization in Rust GPU %10 = OpIAdd %7 %11 %12 OpLine %5 47 8 %13 = OpBitcast %7 %14 - OpLine %15 1244 17 + OpLine %15 1284 17 %16 = OpBitcast %7 %17 OpLine %5 46 4 %18 = OpCompositeConstruct %2 %13 %16 %19 %20 %21 %22 %6 %23 %10 %24 %24 %24 diff --git a/tests/compiletests/ui/lang/core/ref/member_ref_arg_tuples.stderr b/tests/compiletests/ui/lang/core/ref/member_ref_arg_tuples.stderr index 26a651c3ebc..2f81d211870 100644 --- a/tests/compiletests/ui/lang/core/ref/member_ref_arg_tuples.stderr +++ b/tests/compiletests/ui/lang/core/ref/member_ref_arg_tuples.stderr @@ -34,5 +34,19 @@ LL | fn h_newtyped(xyz: ((&u32, &u32, &u32),)) -> (u32, u32, u32) { = note: inlining was required due to illegal parameter type = note: called from `member_ref_arg_tuples::main` -warning: 4 warnings emitted +error: `u64` type used without `OpCapability Int64` + | + = note: used by unnamed constant +note: used from within `member_ref_arg_tuples::main` + --> <$DIR/member_ref_arg_tuples.rs>:44:13 + | +LL | let s = S { x: 2, y: 2 }; + | ^^^^^^^^^^^^^^^^ +note: called by Fragment entry-point `main` + --> <$DIR/member_ref_arg_tuples.rs>:43:8 + | +LL | pub fn main() { + | ^^^^ + +error: aborting due to 1 previous error; 4 warnings emitted diff --git a/tests/compiletests/ui/lang/core/unwrap_or.stderr b/tests/compiletests/ui/lang/core/unwrap_or.stderr index 37cee548757..274ced88f6a 100644 --- a/tests/compiletests/ui/lang/core/unwrap_or.stderr +++ b/tests/compiletests/ui/lang/core/unwrap_or.stderr @@ -1,8 +1,8 @@ %1 = OpFunction %2 None %3 %4 = OpLabel - OpLine %5 1039 14 + OpLine %5 1040 14 %6 = OpBitcast %7 %8 - OpLine %5 1039 8 + OpLine %5 1040 8 %9 = OpINotEqual %10 %6 %11 OpNoLine OpSelectionMerge %12 None diff --git a/tests/difftests/runner/src/runner.rs b/tests/difftests/runner/src/runner.rs index 25711e28a6c..3900645431f 100644 --- a/tests/difftests/runner/src/runner.rs +++ b/tests/difftests/runner/src/runner.rs @@ -474,14 +474,18 @@ impl Runner { None => output1 == output2, // Exact comparison if no epsilon Some(eps) => { let floats1: Vec = output1 - .chunks_exact(4) + .as_chunks::<4>() + .0 + .iter() .map(|chunk| { f32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]) }) .collect(); let floats2: Vec = output2 - .chunks_exact(4) + .as_chunks::<4>() + .0 + .iter() .map(|chunk| { f32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]) }) @@ -503,7 +507,9 @@ impl Runner { None => output1 == output2, // Exact comparison if no epsilon Some(eps) => { let floats1: Vec = output1 - .chunks_exact(8) + .as_chunks::<8>() + .0 + .iter() .map(|chunk| { f64::from_le_bytes([ chunk[0], chunk[1], chunk[2], chunk[3], chunk[4], chunk[5], @@ -513,7 +519,9 @@ impl Runner { .collect(); let floats2: Vec = output2 - .chunks_exact(8) + .as_chunks::<8>() + .0 + .iter() .map(|chunk| { f64::from_le_bytes([ chunk[0], chunk[1], chunk[2], chunk[3], chunk[4], chunk[5],