Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
32 changes: 30 additions & 2 deletions crates/rustc_codegen_spirv/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, Box<dyn Error>> {
let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".into());
Expand Down Expand Up @@ -256,6 +256,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") {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated to the main changes, but this is a kind of silly way to do patches. It can silently fail when things change around: replace does not assert the OG source contains the lines we want to replace, and fails silently if it does not. It might be worth it to add a helper like this:

fn apply_patch(src:&str, og:&str, new:&str)->String{
    assert!(src.contains(og), "ppg_cg_ssa patch does not apply!");
    src.replace(og,new)
}

Would make the failure mode louder, and easier to debug.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've thought about replacing it with a directory of *.patch files before. In fact I tripped up on a replace failing due to upstream changes and it not causing a compilation error but simply a behavior change. Luckily, I added that regex just a month ago so I knew what failed.

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)?;
}
}
Expand Down
10 changes: 8 additions & 2 deletions crates/rustc_codegen_spirv/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,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() {
Expand Down Expand Up @@ -471,7 +474,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)
Expand Down
11 changes: 8 additions & 3 deletions crates/rustc_codegen_spirv/src/builder/builder_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1854,7 +1854,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 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems problematic to ignore Align like this - how about checking that default_align is equal to this Align, or, better yet - use this align instead of b.primitive().default_align(self).abi?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be completely honest, I have no idea what this function is even supposed to do. Sure you can probably find some unsafe rust code that reaches it, but like what it's supposed to do from the shader codegen perspective.

This is sadly the case with quite a bit of code in rustc_codegen_spirv, where I highly suspect it's effectively unreachable for any sane shader, there is no compiletest that reaches that code, so I really don't know what it's really supposed to do.

// 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");
Expand Down Expand Up @@ -1909,7 +1909,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 {
Expand Down Expand Up @@ -1993,7 +1993,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)
Expand Down Expand Up @@ -3484,4 +3485,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");
}
}
40 changes: 21 additions & 19 deletions crates/rustc_codegen_spirv/src/builder/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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<PlaceValue<Self::Value>>,
_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() {
Expand Down Expand Up @@ -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);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Align::ONE? The argument is seemingly ignored for now, but this is an issue for the future, when it will not. You already got the layout - why not just get the align from there?

if !result.layout.is_zst() {
self.store(load, result.val.llval, result.val.align);
}
return Ok(());
return IntrinsicResult::WroteIntoPlace;
}

sym::prefetch_read_data
Expand All @@ -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 => {
Expand Down Expand Up @@ -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,
));
}
};

Expand All @@ -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(
Expand Down Expand Up @@ -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<Self::Value>) {
bug!("retag not supported")
Expand Down
68 changes: 53 additions & 15 deletions crates/rustc_codegen_spirv/src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`).
Expand Down Expand Up @@ -185,24 +185,15 @@ impl<'a, 'tcx> DebugInfoBuilderMethods<'_> for Builder<'a, 'tcx> {
_indirect_offsets: &[Size],
_fragment: &Option<Range<Size>>,
) {
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,
Expand All @@ -216,7 +207,54 @@ impl<'a, 'tcx> DebugInfoBuilderMethods<'_> for Builder<'a, 'tcx> {
// if this is a fragment of a composite `DIVariable`.
_fragment: &Option<Range<Size>>,
) {
todo!()
}

fn dbg_scope_fn(
&mut self,
_instance: Instance<'_>,
_fn_abi: &FnAbi<'_, Ty<'_>>,
_maybe_definition_llfn: Option<Self::Function>,
) -> 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<Self::DILocation> {
None
}

fn dbg_loc(
&mut self,
_scope: Self::DIScope,
_inlined_at: Option<Self::DILocation>,
_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 {
}
}

Expand Down
16 changes: 14 additions & 2 deletions crates/rustc_codegen_spirv/src/codegen_cx/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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<PacMetadata>,
) -> Self::Value {
self.scalar_to_backend(cv, layout, ty)
}

fn scalar_to_backend(
&self,
scalar: Scalar,
Expand Down Expand Up @@ -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) => {
Expand Down
2 changes: 1 addition & 1 deletion crates/rustc_codegen_spirv/src/codegen_cx/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,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,
Expand Down
Loading
Loading