diff --git a/Cargo.lock b/Cargo.lock
index 64ee62a4795..c1d4a283b84 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2941,6 +2941,7 @@ dependencies = [
"lazy_static",
"libc",
"log",
+ "naga",
"object 0.37.3",
"pretty_assertions",
"regex",
@@ -2953,6 +2954,7 @@ dependencies = [
"spirt",
"spirv-std-types",
"spirv-tools",
+ "strum",
"termcolor",
"thorin-dwp",
"tracing",
diff --git a/crates/rustc_codegen_spirv/Cargo.toml b/crates/rustc_codegen_spirv/Cargo.toml
index ed72fbd2800..7cd9eaf1fbe 100644
--- a/crates/rustc_codegen_spirv/Cargo.toml
+++ b/crates/rustc_codegen_spirv/Cargo.toml
@@ -20,15 +20,16 @@ crate-type = ["dylib"]
default = ["use-compiled-tools"]
# If enabled, uses spirv-tools binaries installed in PATH, instead of
# compiling and linking the spirv-tools C++ code
-use-installed-tools = ["spirv-tools/use-installed-tools"]
+use-installed-tools = ["spirv-tools/use-installed-tools", "naga"]
# If enabled will compile and link the C++ code for the spirv tools, the compiled
# version is preferred if both this and `use-installed-tools` are enabled
-use-compiled-tools = ["spirv-tools/use-compiled-tools"]
+use-compiled-tools = ["spirv-tools/use-compiled-tools", "naga"]
# If enabled, this will not check whether the current rustc version is set to the
# appropriate channel. rustc_cogeden_spirv requires a specific nightly version,
# and will likely produce compile errors when built against a different toolchain.
# Enable this feature to be able to experiment with other versions.
skip-toolchain-check = []
+naga = ["dep:naga"]
[dependencies]
# HACK(eddyb) these only exist to unify features across dependency trees,
@@ -61,6 +62,8 @@ itertools = "0.14.0"
tracing.workspace = true
tracing-subscriber.workspace = true
tracing-tree = "0.4.0"
+naga = { version = "27.0.3", features = ["spv-in", "wgsl-out"], optional = true }
+strum = { version = "0.27.2", features = ["derive"] }
[dev-dependencies]
pretty_assertions = "1.0"
diff --git a/crates/rustc_codegen_spirv/src/lib.rs b/crates/rustc_codegen_spirv/src/lib.rs
index 5c891706ea8..fb68dcf687b 100644
--- a/crates/rustc_codegen_spirv/src/lib.rs
+++ b/crates/rustc_codegen_spirv/src/lib.rs
@@ -127,6 +127,7 @@ mod custom_decorations;
mod custom_insts;
mod link;
mod linker;
+mod naga_transpile;
mod spirv_type;
mod spirv_type_constraints;
mod symbols;
diff --git a/crates/rustc_codegen_spirv/src/link.rs b/crates/rustc_codegen_spirv/src/link.rs
index fd903a52d08..ebefbcae4a1 100644
--- a/crates/rustc_codegen_spirv/src/link.rs
+++ b/crates/rustc_codegen_spirv/src/link.rs
@@ -3,6 +3,7 @@ use crate::maybe_pqp_cg_ssa as rustc_codegen_ssa;
use crate::codegen_cx::{CodegenArgs, SpirvMetadata};
use crate::linker;
+use crate::naga_transpile::should_transpile;
use crate::target::{SpirvTarget, SpirvTargetVariant};
use ar::{Archive, GnuBuilder, Header};
use rspirv::binary::Assemble;
@@ -319,6 +320,10 @@ fn post_link_single_module(
drop(save_modules_timer);
}
+
+ if let Ok(Some(transpile)) = should_transpile(sess) {
+ transpile(sess, cg_args, &spv_binary, out_filename).ok();
+ }
}
fn do_spirv_opt(
diff --git a/crates/rustc_codegen_spirv/src/naga_transpile.rs b/crates/rustc_codegen_spirv/src/naga_transpile.rs
new file mode 100644
index 00000000000..6f6b8131107
--- /dev/null
+++ b/crates/rustc_codegen_spirv/src/naga_transpile.rs
@@ -0,0 +1,89 @@
+use crate::codegen_cx::CodegenArgs;
+use crate::target::{NagaTarget, SpirvTarget};
+use rustc_session::Session;
+use rustc_span::ErrorGuaranteed;
+use std::path::Path;
+
+pub type NagaTranspile = fn(
+ sess: &Session,
+ cg_args: &CodegenArgs,
+ spv_binary: &[u32],
+ out_filename: &Path,
+) -> Result<(), ErrorGuaranteed>;
+
+pub fn should_transpile(sess: &Session) -> Result