Skip to content
Merged
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
10 changes: 10 additions & 0 deletions rustc_codegen_spirv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,16 @@ impl Drop for DumpModuleOnPanic<'_, '_, '_> {
/// This is the entrypoint for a hot plugged rustc_codegen_spirv
#[no_mangle]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
// Override rustc's panic hook with our own to override the ICE error
// message, and direct people to `rust-gpu`.
std::panic::set_hook(Box::new(|panic_info| {
rustc_driver::report_ice(
panic_info,
"https://github.com/EmbarkStudios/rust-gpu/issues/new",
);
eprintln!("note: `rust-gpu` version {}\n", env!("CARGO_PKG_VERSION"));
}));

Box::new(SpirvCodegenBackend)
}

Expand Down
96 changes: 70 additions & 26 deletions rustc_codegen_spirv/src/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_codegen_ssa::CodegenResults;
use rustc_data_structures::owning_ref::OwningRef;
use rustc_data_structures::rustc_erase_owner;
use rustc_data_structures::sync::MetadataRef;
use rustc_errors::FatalError;
use rustc_errors::{DiagnosticBuilder, FatalError};
use rustc_middle::dep_graph::WorkProduct;
use rustc_middle::middle::cstore::NativeLib;
use rustc_middle::middle::dependency_format::Linkage;
Expand Down Expand Up @@ -132,40 +132,84 @@ fn link_exe(

fn do_spirv_opt(sess: &Session, filename: &Path) {
let tmp = filename.with_extension("opt.spv");
let output = Command::new("spirv-opt")
.args(&["-Os", "--eliminate-dead-const", "--strip-debug"])
.arg(&filename)
.arg("-o")
.arg(&tmp)
.output()
.expect("spirv-opt failed to execute");
if output.status.success() {
let output = output_spriv_tool(
sess,
"spirv-opt",
|cmd| {
cmd.args(&["-Os", "--eliminate-dead-const", "--strip-debug"])
.arg(&filename)
.arg("-o")
.arg(&tmp)
},
|_| {
let mut err = sess.struct_warn("spirv-opt failed, leaving as unoptimized");
err.note(&format!("module {:?}", filename));
err
},
);

if output.is_some() {
std::fs::rename(tmp, filename).unwrap();
} else {
let mut warn = sess.struct_warn("spirv-opt failed, leaving as unoptimized");
if !output.stdout.is_empty() {
warn.note(&String::from_utf8(output.stdout).unwrap());
}
if !output.stderr.is_empty() {
warn.note(&String::from_utf8(output.stderr).unwrap());
}
warn.emit();
}
}

fn do_spirv_val(sess: &Session, filename: &Path) {
let output = Command::new("spirv-val").arg(&filename).output();
let output = output.expect("spirv-val failed to execute");
if !output.status.success() {
let mut err = sess.struct_err(&format!("spirv-val failed with {}", output.status));
err.note(&format!("module {:?}", filename));
output_spriv_tool(
sess,
"spirv-val",
|cmd| cmd.arg(&filename),
|status| {
let mut err = sess.struct_err(&format!("spirv-val failed with {}", status));
err.note(&format!("module {:?}", filename));
err
},
);
}

/// Runs a given SPIR-V `tool`, configured with `builder`, erroring if not found
/// or returns a non-zero exit code. All errors will be emitted using the
/// diagnostics builder provided by `diagnostics.`
fn output_spriv_tool<'a, F, D>(
sess: &Session,
tool: &str,
builder: F,
diagnostics: D,
) -> Option<std::process::Output>
where
F: FnOnce(&mut Command) -> &mut Command,
D: FnOnce(std::process::ExitStatus) -> DiagnosticBuilder<'a>,
{
let mut cmd = Command::new(tool);
(builder)(&mut cmd);

let output = match cmd.output() {
Ok(output) => output,
_ => {
let mut err =
sess.struct_err(&format!("Couldn't find `{}` SPRI-V tool in PATH.", tool));
err.note(
"Please ensure that you have `spirv-tools` installed on \
your system and available in your PATH.",
);
err.emit();
return None;
}
};

if output.status.success() {
Some(output)
} else {
let mut diagnostics = (diagnostics)(output.status);

if !output.stdout.is_empty() {
err.note(&String::from_utf8(output.stdout).unwrap());
diagnostics.note(&String::from_utf8(output.stdout).unwrap());
}
if !output.stderr.is_empty() {
err.note(&String::from_utf8(output.stderr).unwrap());
diagnostics.note(&String::from_utf8(output.stderr).unwrap());
}
err.emit();

diagnostics.emit();
None
}
}

Expand Down