Skip to content

Commit 85e4df3

Browse files
committed
Include identifying information (e.g. crate names) in --dump-* filenames.
1 parent 6fb35ff commit 85e4df3

File tree

9 files changed

+201
-91
lines changed

9 files changed

+201
-91
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3333
- [PR#959](https://github.com/EmbarkStudios/rust-gpu/pull/959) added two `spirv-builder` environment variables to customize *only* the `rustc` invocations for shader crates and their dependencies:
3434
- `RUSTGPU_RUSTFLAGS="..."` for shader `RUSTFLAGS="..."`
3535
- `RUSTGPU_CODEGEN_ARGS="..."` for shader "codegen args" (i.e. `RUSTFLAGS=-Cllvm-args="..."`)
36-
(check out ["codegen args" docs](docs/src/codegen-args.md), or run with `RUSTGPU_CODEGEN_ARGS=--help` to see the full list of options)
36+
(check out [the "codegen args" docs](docs/src/codegen-args.md), or run with `RUSTGPU_CODEGEN_ARGS=--help` to see the full list of options)
3737
- [PR#940](https://github.com/EmbarkStudios/rust-gpu/pull/940) integrated the experimental [`SPIR-🇹` shader IR framework](https://github.com/EmbarkStudios/spirt) into the linker
3838
(opt-in via `RUSTGPU_CODEGEN_ARGS=--spirt`, see also [the `--spirt` docs](docs/src/codegen-args.md#--spirt), for more details)
3939

4040
### Changed 🛠️
4141
- [PR#958](https://github.com/EmbarkStudios/rust-gpu/pull/958) updated toolchain to `nightly-2022-10-29`
4242
- [PR#941](https://github.com/EmbarkStudios/rust-gpu/pull/941) applied workspace inheritance to `Cargo.toml` files
4343
- [PR#959](https://github.com/EmbarkStudios/rust-gpu/pull/959) moved `rustc_codegen_spirv` debugging functionality from environment variables to "codegen args" options/flags (see [the updated docs](docs/src/codegen-args.md) for more details)
44+
- [PR#967](https://github.com/EmbarkStudios/rust-gpu/pull/967) made `--dump-*` ["codegen args"](docs/src/codegen-args.md) include identifying information (e.g. crate names) in the names of files they emit
4445

4546
### Removed 🔥
4647
- [PR#946](https://github.com/EmbarkStudios/rust-gpu/pull/946) removed the `fn`/closure `#[spirv(unroll_loops)]` attribute, as it has no users, is becoming non-trivial to support, and requires redesign for better ergonomics (e.g. `#[spirv(unroll)]` applied to individual loops, not the whole `fn`/closure)

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/rustc_codegen_spirv-types/src/compile_result.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ impl ModuleResult {
3232

3333
#[derive(Debug, Serialize, Deserialize)]
3434
pub struct CompileResult {
35-
pub module: ModuleResult,
3635
pub entry_points: Vec<String>,
36+
pub module: ModuleResult,
3737
}
3838

3939
impl CompileResult {

crates/rustc_codegen_spirv/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ regex = { version = "1", features = ["perf"] }
4747

4848
# Normal dependencies.
4949
ar = "0.9.0"
50+
either = "1.8.0"
5051
indexmap = "1.6.0"
5152
rspirv = "0.11"
5253
rustc-demangle = "0.1.21"

crates/rustc_codegen_spirv/src/codegen_cx/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,8 @@ impl CodegenArgs {
362362
opts.optopt(
363363
"",
364364
"dump-post-merge",
365-
"dump the merged module immediately after merging, to FILE",
366-
"FILE",
365+
"dump the merged module immediately after merging, to a file in DIR",
366+
"DIR",
367367
);
368368
opts.optopt(
369369
"",
@@ -374,8 +374,8 @@ impl CodegenArgs {
374374
opts.optopt(
375375
"",
376376
"dump-spirt-passes",
377-
"dump the SPIR-T module across passes, to FILE and FILE.html",
378-
"FILE",
377+
"dump the SPIR-T module across passes, to a (pair of) file(s) in DIR",
378+
"DIR",
379379
);
380380
opts.optflag(
381381
"",
@@ -532,9 +532,9 @@ impl CodegenArgs {
532532

533533
// NOTE(eddyb) these are debugging options that used to be env vars
534534
// (for more information see `docs/src/codegen-args.md`).
535-
dump_post_merge: matches_opt_path("dump-post-merge"),
535+
dump_post_merge: matches_opt_dump_dir_path("dump-post-merge"),
536536
dump_post_split: matches_opt_dump_dir_path("dump-post-split"),
537-
dump_spirt_passes: matches_opt_path("dump-spirt-passes"),
537+
dump_spirt_passes: matches_opt_dump_dir_path("dump-spirt-passes"),
538538
specializer_debug: matches.opt_present("specializer-debug"),
539539
specializer_dump_instances: matches_opt_path("specializer-dump-instances"),
540540
print_all_zombie: matches.opt_present("print-all-zombie"),

crates/rustc_codegen_spirv/src/link.rs

Lines changed: 92 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::codegen_cx::{CodegenArgs, SpirvMetadata};
22
use crate::{linker, SpirvCodegenBackend, SpirvModuleBuffer, SpirvThinBuffer};
33
use ar::{Archive, GnuBuilder, Header};
44
use rspirv::binary::Assemble;
5+
use rspirv::dr::Module;
56
use rustc_ast::CRATE_NODE_ID;
67
use rustc_codegen_spirv_types::{CompileResult, ModuleResult};
78
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
@@ -17,7 +18,8 @@ use rustc_session::config::{CrateType, DebugInfo, Lto, OptLevel, OutputFilenames
1718
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
1819
use rustc_session::utils::NativeLibKind;
1920
use rustc_session::Session;
20-
use std::ffi::CString;
21+
use std::collections::BTreeMap;
22+
use std::ffi::{CString, OsStr};
2123
use std::fs::File;
2224
use std::io::{BufWriter, Read};
2325
use std::iter;
@@ -62,7 +64,21 @@ pub fn link<'a>(
6264
link_rlib(sess, codegen_results, &out_filename);
6365
}
6466
CrateType::Executable | CrateType::Cdylib | CrateType::Dylib => {
65-
link_exe(sess, crate_type, &out_filename, codegen_results);
67+
// HACK(eddyb) there's no way way to access `outputs.filestem`,
68+
// so we pay the cost of building a whole `PathBuf` instead.
69+
let disambiguated_crate_name_for_dumps = outputs
70+
.with_extension("")
71+
.file_name()
72+
.unwrap()
73+
.to_os_string();
74+
75+
link_exe(
76+
sess,
77+
crate_type,
78+
&out_filename,
79+
codegen_results,
80+
&disambiguated_crate_name_for_dumps,
81+
);
6682
}
6783
other => {
6884
sess.err(format!("CrateType {:?} not supported yet", other));
@@ -117,6 +133,7 @@ fn link_exe(
117133
crate_type: CrateType,
118134
out_filename: &Path,
119135
codegen_results: &CodegenResults,
136+
disambiguated_crate_name_for_dumps: &OsStr,
120137
) {
121138
let mut objects = Vec::new();
122139
let mut rlibs = Vec::new();
@@ -140,38 +157,49 @@ fn link_exe(
140157
// HACK(eddyb) this removes the `.json` in `.spv.json`, from `out_filename`.
141158
let out_path_spv = out_filename.with_extension("");
142159

143-
let compile_result = match do_link(sess, &cg_args, &objects, &rlibs) {
160+
let link_result = do_link(
161+
sess,
162+
&cg_args,
163+
&objects,
164+
&rlibs,
165+
disambiguated_crate_name_for_dumps,
166+
);
167+
let compile_result = match link_result {
144168
linker::LinkResult::SingleModule(module) => {
145-
let module_filename = out_path_spv;
146-
post_link_single_module(sess, &cg_args, module.assemble(), &module_filename);
147-
cg_args.do_disassemble(&module);
148-
let module_result = ModuleResult::SingleModule(module_filename);
169+
let entry_points = entry_points(&module);
170+
post_link_single_module(sess, &cg_args, *module, &out_path_spv, None);
149171
CompileResult {
150-
module: module_result,
151-
entry_points: entry_points(&module),
172+
entry_points,
173+
module: ModuleResult::SingleModule(out_path_spv),
152174
}
153175
}
154-
linker::LinkResult::MultipleModules(map) => {
176+
linker::LinkResult::MultipleModules {
177+
file_stem_to_entry_name_and_module,
178+
} => {
155179
let out_dir = out_path_spv.with_extension("spvs");
156180
if !out_dir.is_dir() {
157181
std::fs::create_dir_all(&out_dir).unwrap();
158182
}
159183

160-
let entry_points = map.keys().cloned().collect();
161-
let map = map
184+
let entry_name_to_file_path: BTreeMap<_, _> = file_stem_to_entry_name_and_module
162185
.into_iter()
163-
.map(|(name, module)| {
164-
let mut module_filename = out_dir.clone();
165-
module_filename.push(sanitize_filename::sanitize(&name));
166-
module_filename.set_extension("spv");
167-
post_link_single_module(sess, &cg_args, module.assemble(), &module_filename);
168-
(name, module_filename)
186+
.map(|(file_stem, (entry_name, module))| {
187+
let mut out_file_name = file_stem;
188+
out_file_name.push(".spv");
189+
let out_file_path = out_dir.join(out_file_name);
190+
post_link_single_module(
191+
sess,
192+
&cg_args,
193+
module,
194+
&out_file_path,
195+
Some(disambiguated_crate_name_for_dumps),
196+
);
197+
(entry_name, out_file_path)
169198
})
170199
.collect();
171-
let module_result = ModuleResult::MultiModule(map);
172200
CompileResult {
173-
module: module_result,
174-
entry_points,
201+
entry_points: entry_name_to_file_path.keys().cloned().collect(),
202+
module: ModuleResult::MultiModule(entry_name_to_file_path),
175203
}
176204
}
177205
};
@@ -192,15 +220,21 @@ fn entry_points(module: &rspirv::dr::Module) -> Vec<String> {
192220
fn post_link_single_module(
193221
sess: &Session,
194222
cg_args: &CodegenArgs,
195-
spv_binary: Vec<u32>,
223+
module: Module,
196224
out_filename: &Path,
225+
dump_prefix: Option<&OsStr>,
197226
) {
227+
cg_args.do_disassemble(&module);
228+
let spv_binary = module.assemble();
229+
198230
if let Some(dir) = &cg_args.dump_post_link {
199-
std::fs::write(
200-
dir.join(out_filename.file_name().unwrap()),
201-
spirv_tools::binary::from_binary(&spv_binary),
202-
)
203-
.unwrap();
231+
// FIXME(eddyb) rename `filename` with `file_path` to make this less confusing.
232+
let out_filename_file_name = out_filename.file_name().unwrap();
233+
let dump_path = match dump_prefix {
234+
Some(prefix) => dir.join(prefix).with_extension(out_filename_file_name),
235+
None => dir.join(out_filename_file_name),
236+
};
237+
std::fs::write(dump_path, spirv_tools::binary::from_binary(&spv_binary)).unwrap();
204238
}
205239

206240
let val_options = spirv_tools::val::ValidatorOptions {
@@ -514,20 +548,34 @@ fn do_link(
514548
cg_args: &CodegenArgs,
515549
objects: &[PathBuf],
516550
rlibs: &[PathBuf],
551+
disambiguated_crate_name_for_dumps: &OsStr,
517552
) -> linker::LinkResult {
518-
fn load(bytes: &[u8]) -> rspirv::dr::Module {
519-
let mut loader = rspirv::dr::Loader::new();
520-
rspirv::binary::parse_bytes(bytes, &mut loader).unwrap();
521-
loader.module()
522-
}
523-
524553
let load_modules_timer = sess.timer("link_load_modules");
554+
525555
let mut modules = Vec::new();
556+
let mut add_module = |file_name: &OsStr, bytes: &[u8]| {
557+
let module = {
558+
let mut loader = rspirv::dr::Loader::new();
559+
rspirv::binary::parse_bytes(bytes, &mut loader).unwrap();
560+
loader.module()
561+
};
562+
if let Some(dir) = &cg_args.dump_pre_link {
563+
// FIXME(eddyb) is it a good idea to re-`assemble` the `rspirv::dr`
564+
// module, or should this just save the original bytes?
565+
std::fs::write(
566+
dir.join(file_name).with_extension("spv"),
567+
spirv_tools::binary::from_binary(&module.assemble()),
568+
)
569+
.unwrap();
570+
}
571+
modules.push(module);
572+
};
573+
526574
// `objects` are the plain obj files we need to link - usually produced by the final crate.
527575
for obj in objects {
528-
let bytes = std::fs::read(obj).unwrap();
529-
modules.push(load(&bytes));
576+
add_module(obj.file_name().unwrap(), &std::fs::read(obj).unwrap());
530577
}
578+
531579
// `rlibs` are archive files we've created in `create_archive`, usually produced by crates that are being
532580
// referenced. We need to unpack them and add the modules inside.
533581
for rlib in rlibs {
@@ -539,24 +587,22 @@ fn do_link(
539587
// https://github.com/rust-lang/rust/blob/72868e017bdade60603a25889e253f556305f996/library/std/src/fs.rs#L200-L202
540588
let mut bytes = Vec::with_capacity(entry.header().size() as usize + 1);
541589
entry.read_to_end(&mut bytes).unwrap();
542-
modules.push(load(&bytes));
590+
591+
let file_name = std::str::from_utf8(entry.header().identifier()).unwrap();
592+
add_module(OsStr::new(file_name), &bytes);
543593
}
544594
}
545595
}
546596

547-
if let Some(dir) = &cg_args.dump_pre_link {
548-
for (num, module) in modules.iter().enumerate() {
549-
std::fs::write(
550-
dir.join(format!("mod_{}.spv", num)),
551-
spirv_tools::binary::from_binary(&module.assemble()),
552-
)
553-
.unwrap();
554-
}
555-
}
556597
drop(load_modules_timer);
557598

558599
// Do the link...
559-
let link_result = linker::link(sess, modules, &cg_args.linker_opts);
600+
let link_result = linker::link(
601+
sess,
602+
modules,
603+
&cg_args.linker_opts,
604+
disambiguated_crate_name_for_dumps,
605+
);
560606

561607
match link_result {
562608
Ok(v) => v,

0 commit comments

Comments
 (0)