Auto merge of #77117 - davidtwco:issue-34651-split-dwarf, r=nagisa

cg_llvm: split dwarf support

cc #34651

This PR adds initial support for Split DWARF to rustc, based on the implementation in Clang.

##### Current Status
This PR currently has functioning split-dwarf, running rustc with `-Zsplit-dwarf=split` when compiling a binary will produce a `dwp` alongside the binary, which contains the linked dwarf objects.

```shell-session
$ rustc -Cdebuginfo=2 -Zsplit-dwarf=split -C save-temps ./foo.rs
$ ls foo*
foo
foo.belfx9afw9cmv8.rcgu.dwo
foo.belfx9afw9cmv8.rcgu.o
foo.foo.7rcbfp3g-cgu.0.rcgu.dwo
foo.foo.7rcbfp3g-cgu.0.rcgu.o
foo.foo.7rcbfp3g-cgu.1.rcgu.dwo
foo.foo.7rcbfp3g-cgu.1.rcgu.o
foo.foo.7rcbfp3g-cgu.2.rcgu.dwo
foo.foo.7rcbfp3g-cgu.2.rcgu.o
foo.foo.7rcbfp3g-cgu.3.rcgu.dwo
foo.foo.7rcbfp3g-cgu.3.rcgu.o
foo.foo.7rcbfp3g-cgu.4.rcgu.dwo
foo.foo.7rcbfp3g-cgu.4.rcgu.o
foo.foo.7rcbfp3g-cgu.5.rcgu.dwo
foo.foo.7rcbfp3g-cgu.5.rcgu.o
foo.foo.7rcbfp3g-cgu.6.rcgu.dwo
foo.foo.7rcbfp3g-cgu.6.rcgu.o
foo.foo.7rcbfp3g-cgu.7.rcgu.dwo
foo.foo.7rcbfp3g-cgu.7.rcgu.o
foo.dwp
foo.rs
$ readelf -wi foo.foo.7rcbfp3g-cgu.0.rcgu.o
# ...
  Compilation Unit @ offset 0x90:
   Length:        0x2c (32-bit)
   Version:       4
   Abbrev Offset: 0x5b
   Pointer Size:  8
 <0><9b>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <9c>   DW_AT_stmt_list   : 0xe8
    <a0>   DW_AT_comp_dir    : (indirect string, offset: 0x13b): /home/david/Projects/rust/rust0
    <a4>   DW_AT_GNU_dwo_name: (indirect string, offset: 0x15b): foo.foo.7rcbfp3g-cgu.0.rcgu.dwo
    <a8>   DW_AT_GNU_dwo_id  : 0x357472a2b032d7b9
    <b0>   DW_AT_low_pc      : 0x0
    <b8>   DW_AT_ranges      : 0x40
    <bc>   DW_AT_GNU_addr_base: 0x0
# ...
```

##### To-Do
I've opened this PR as a draft to get feedback and work out how we'd expect rustc to work when Split DWARF is requested. It might be easier to read the PR commit-by-commit.

- [ ] Add error when Split DWARF is requested on platforms where it doesn't make sense.
- [x] Determine whether or not there should be a single `dwo` output from rustc, or one per codegen-unit as exists currently.
- [x] Add tests.
- [x] Fix `single` mode - currently single mode doesn't change the invocation of `addPassesToEmitFile`, which is correct, but it also needs to change the split dwarf path provided to `createCompileUnit` and `createTargetMachine` so that it's just the final binary (currently it is still a non-existent `dwo` file).

r? `@nagisa`
cc `@michaelwoerister` `@eddyb` `@alexcrichton` `@rust-lang/wg-incr-comp`
This commit is contained in:
bors 2020-12-16 12:51:42 +00:00
commit 2ba7ca2bbb
22 changed files with 431 additions and 127 deletions

View file

@ -969,15 +969,25 @@ impl Step for Assemble {
copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
// We prepend this bin directory to the user PATH when linking Rust binaries. To
// avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`.
let libdir = builder.sysroot_libdir(target_compiler, target_compiler.host);
let libdir_bin = libdir.parent().unwrap().join("bin");
t!(fs::create_dir_all(&libdir_bin));
if let Some(lld_install) = lld_install {
let src_exe = exe("lld", target_compiler.host);
let dst_exe = exe("rust-lld", target_compiler.host);
// we prepend this bin directory to the user PATH when linking Rust binaries. To
// avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`.
let dst = libdir.parent().unwrap().join("bin");
t!(fs::create_dir_all(&dst));
builder.copy(&lld_install.join("bin").join(&src_exe), &dst.join(&dst_exe));
builder.copy(&lld_install.join("bin").join(&src_exe), &libdir_bin.join(&dst_exe));
}
// Similarly, copy `llvm-dwp` into libdir for Split DWARF.
{
let src_exe = exe("llvm-dwp", target_compiler.host);
let dst_exe = exe("rust-llvm-dwp", target_compiler.host);
let llvm_config_bin = builder.ensure(native::Llvm { target: target_compiler.host });
let llvm_bin_dir = llvm_config_bin.parent().unwrap();
builder.copy(&llvm_bin_dir.join(&src_exe), &libdir_bin.join(&dst_exe));
}
// Ensure that `libLLVM.so` ends up in the newly build compiler directory,

View file

@ -523,17 +523,20 @@ impl Step for Rustc {
// component for now.
maybe_install_llvm_runtime(builder, host, image);
let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin");
let dst_dir = image.join("lib/rustlib").join(&*host.triple).join("bin");
t!(fs::create_dir_all(&dst_dir));
// Copy over lld if it's there
if builder.config.lld_enabled {
let exe = exe("rust-lld", compiler.host);
let src =
builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin").join(&exe);
// for the rationale about this rename check `compile::copy_lld_to_sysroot`
let dst = image.join("lib/rustlib").join(&*host.triple).join("bin").join(&exe);
t!(fs::create_dir_all(&dst.parent().unwrap()));
builder.copy(&src, &dst);
builder.copy(&src_dir.join(&exe), &dst_dir.join(&exe));
}
// Copy over llvm-dwp if it's there
let exe = exe("rust-llvm-dwp", compiler.host);
builder.copy(&src_dir.join(&exe), &dst_dir.join(&exe));
// Man pages
t!(fs::create_dir_all(image.join("share/man/man1")));
let man_src = builder.src.join("src/doc/man");

View file

@ -897,7 +897,12 @@ default_test!(Incremental {
suite: "incremental"
});
default_test!(Debuginfo { path: "src/test/debuginfo", mode: "debuginfo", suite: "debuginfo" });
default_test_with_compare_mode!(Debuginfo {
path: "src/test/debuginfo",
mode: "debuginfo",
suite: "debuginfo",
compare_mode: "split-dwarf"
});
host_test!(UiFullDeps { path: "src/test/ui-fulldeps", mode: "ui", suite: "ui-fulldeps" });

View file

@ -0,0 +1,8 @@
-include ../tools.mk
# only-linux
all:
$(RUSTC) -Z split-dwarf=split foo.rs
rm $(TMPDIR)/foo.dwp
rm $(TMPDIR)/$(call BIN,foo)

View file

@ -0,0 +1 @@
fn main() {}

View file

@ -127,6 +127,8 @@ pub enum CompareMode {
Nll,
Polonius,
Chalk,
SplitDwarf,
SplitDwarfSingle,
}
impl CompareMode {
@ -135,6 +137,8 @@ impl CompareMode {
CompareMode::Nll => "nll",
CompareMode::Polonius => "polonius",
CompareMode::Chalk => "chalk",
CompareMode::SplitDwarf => "split-dwarf",
CompareMode::SplitDwarfSingle => "split-dwarf-single",
}
}
@ -143,6 +147,8 @@ impl CompareMode {
"nll" => CompareMode::Nll,
"polonius" => CompareMode::Polonius,
"chalk" => CompareMode::Chalk,
"split-dwarf" => CompareMode::SplitDwarf,
"split-dwarf-single" => CompareMode::SplitDwarfSingle,
x => panic!("unknown --compare-mode option: {}", x),
}
}

View file

@ -852,6 +852,8 @@ impl Config {
Some(CompareMode::Nll) => name == "compare-mode-nll",
Some(CompareMode::Polonius) => name == "compare-mode-polonius",
Some(CompareMode::Chalk) => name == "compare-mode-chalk",
Some(CompareMode::SplitDwarf) => name == "compare-mode-split-dwarf",
Some(CompareMode::SplitDwarfSingle) => name == "compare-mode-split-dwarf-single",
None => false,
} ||
(cfg!(debug_assertions) && name == "debug") ||

View file

@ -2017,6 +2017,12 @@ impl<'test> TestCx<'test> {
Some(CompareMode::Chalk) => {
rustc.args(&["-Zchalk"]);
}
Some(CompareMode::SplitDwarf) => {
rustc.args(&["-Zsplit-dwarf=split"]);
}
Some(CompareMode::SplitDwarfSingle) => {
rustc.args(&["-Zsplit-dwarf=single"]);
}
None => {}
}