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..16d67c37838 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-07-03" components = ["rust-src", "rustc-dev", "llvm-tools"] -# commit_hash = e96c36b6f76833388c519561d145492d2c08db4e"#; +# commit_hash = c397dae808f70caebab1fc4e11b3edf7e59f58c7"#; fn rustc_output(arg: &str) -> Result> { let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".into()); @@ -256,6 +256,10 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {", ); } + if relative_path == Path::new("src/mir/mod.rs") { + src = src.replace("fx.fill_function_debug_context(&mut start_bx);", ""); + } + fs::write(out_path, src)?; } } diff --git a/crates/rustc_codegen_spirv/src/abi.rs b/crates/rustc_codegen_spirv/src/abi.rs index 0eb0a2722c2..781f48efb28 100644 --- a/crates/rustc_codegen_spirv/src/abi.rs +++ b/crates/rustc_codegen_spirv/src/abi.rs @@ -92,15 +92,6 @@ pub(crate) fn provide(providers: &mut Providers) { // 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; @@ -414,7 +405,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() { @@ -490,7 +484,7 @@ pub fn scalar_pair_element_backend_type<'tcx>( ty: TyAndLayout<'tcx>, index: usize, ) -> Word { - let [a, b] = match ty.layout.backend_repr() { + let [a, b] = match ty.backend_repr { BackendRepr::ScalarPair(a, b) => [a, b], other => span_bug!( span, @@ -500,7 +494,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/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index 25cd1c66ce1..b2b50694428 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"); @@ -1928,7 +1928,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { 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..a188400f5bc 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,9 +66,14 @@ 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() { @@ -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,10 @@ 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( + instance.def_id(), + instance.args, + )); } }; @@ -368,7 +379,7 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { .val .store(self, result); } - Ok(()) + IntrinsicResult::WroteIntoPlace } fn codegen_llvm_intrinsic_call( @@ -402,16 +413,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/codegen_cx/constant.rs b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs index 2932f3e4234..d4f0cbbb3a3 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/constant.rs @@ -8,7 +8,9 @@ use crate::spirv_type::SpirvType; use itertools::Itertools as _; use rspirv::spirv::Word; use rustc_abi::{self as abi, AddressSpace, Float, HasDataLayout, Integer, Primitive, Size}; -use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods}; +use rustc_codegen_ssa::traits::{ + ConstCodegenMethods, MiscCodegenMethods, PacMetadata, StaticCodegenMethods, +}; use rustc_middle::mir::interpret::{AllocError, ConstAllocation, GlobalAlloc, Scalar, alloc_range}; use rustc_middle::ty::layout::LayoutOf; use rustc_span::{DUMMY_SP, Span}; @@ -226,6 +228,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, + ) -> Self::Value { + self.scalar_to_backend(cv, layout, ty) + } + fn scalar_to_backend( &self, scalar: Scalar, @@ -268,7 +280,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..a7450c10aff 100644 --- a/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs +++ b/crates/rustc_codegen_spirv/src/codegen_cx/entry.rs @@ -12,6 +12,8 @@ use rspirv::spirv::{ BuiltIn, Decoration, Dim, ExecutionModel, FunctionControl, StorageClass, Word, }; use rustc_abi::FieldsShape; +use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; +use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, MiscCodegenMethods as _}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::MultiSpan; @@ -87,22 +89,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 +178,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 +504,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 +626,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 +672,22 @@ 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 OperandRef { + val: OperandValue::Pair(v0, v1), + .. + } = bx.load_operand(PlaceRef::new_sized( + value_ptr.unwrap(), + entry_arg_abi.layout, + )) + else { + unreachable!(); + }; + call_args.extend([v0, 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..f08cdb819f8 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, + MiscCodegenMethods, PacMetadata, }; 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_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,7 @@ 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) -> Self::Value { let function = self.get_fn(instance); let span = self.tcx.def_span(instance.def_id()); @@ -951,6 +948,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 +963,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/lib.rs b/crates/rustc_codegen_spirv/src/lib.rs index 857255dbfa3..df16829a6be 100644 --- a/crates/rustc_codegen_spirv/src/lib.rs +++ b/crates/rustc_codegen_spirv/src/lib.rs @@ -152,11 +152,10 @@ 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}; @@ -258,7 +257,7 @@ impl CodegenBackend for SpirvCodegenBackend { sess: &Session, _outputs: &OutputFilenames, crate_info: &CrateInfo, - ) -> (CompiledModules, FxIndexMap) { + ) -> (CompiledModules, WorkProductMap) { ongoing_codegen .downcast::>() .expect("Expected OngoingCodegen, found Box") @@ -411,6 +410,7 @@ impl WriteBackendMethods for SpirvCodegenBackend { name, kind, object: Some(path), + global_asm_object: None, dwarf_object: None, bytecode: None, assembly: None, @@ -434,6 +434,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/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..3e36ae224b4 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,7 +1,7 @@ [toolchain] -channel = "nightly-2026-05-22" +channel = "nightly-2026-07-03" components = ["rust-src", "rustc-dev", "llvm-tools"] -# commit_hash = e96c36b6f76833388c519561d145492d2c08db4e +# commit_hash = c397dae808f70caebab1fc4e11b3edf7e59f58c7 # 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/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_write.stderr b/tests/compiletests/ui/dis/ptr_write.stderr index df6879d3aeb..f83f52d41af 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 1941 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..d29b867dff5 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 1941 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..af7314f9f1c 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 1245 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/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/differ.rs b/tests/difftests/runner/src/differ.rs index 592046dd175..66c3e000402 100644 --- a/tests/difftests/runner/src/differ.rs +++ b/tests/difftests/runner/src/differ.rs @@ -302,6 +302,7 @@ impl Default for NumericDiffer { } impl OutputDiffer for NumericDiffer { + #[expect(clippy::chunks_exact_to_as_chunks)] fn compare(&self, output1: &[u8], output2: &[u8], epsilon: Option) -> Vec { if output1.len() != output2.len() { return vec![Difference { @@ -450,6 +451,7 @@ impl DifferenceDisplay for NumericDiffer { self.format_table(diffs, pkg1, pkg2) } + #[expect(clippy::chunks_exact_to_as_chunks)] fn write_human_readable(&self, output: &[u8], path: &std::path::Path) -> std::io::Result<()> { use std::io::Write; let mut file = std::fs::File::create(path)?; 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],