diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index ba4524c150c..2397fa767d8 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -30,7 +30,8 @@ pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc}; pub use clang::{clang, Clang}; pub use diff::{diff, Diff}; pub use llvm::{ - llvm_filecheck, llvm_profdata, llvm_readobj, LlvmFilecheck, LlvmProfdata, LlvmReadobj, + llvm_filecheck, llvm_objdump, llvm_profdata, llvm_readobj, LlvmFilecheck, LlvmObjdump, + LlvmProfdata, LlvmReadobj, }; pub use run::{cmd, run, run_fail, run_with_args}; pub use rustc::{aux_build, rustc, Rustc}; diff --git a/src/tools/run-make-support/src/llvm.rs b/src/tools/run-make-support/src/llvm.rs index 414251abda2..d9eb25eec84 100644 --- a/src/tools/run-make-support/src/llvm.rs +++ b/src/tools/run-make-support/src/llvm.rs @@ -20,6 +20,12 @@ pub fn llvm_filecheck() -> LlvmFilecheck { LlvmFilecheck::new() } +/// Construct a new `llvm-objdump` invocation. This assumes that `llvm-objdump` is available +/// at `$LLVM_BIN_DIR/llvm-objdump`. +pub fn llvm_objdump() -> LlvmObjdump { + LlvmObjdump::new() +} + /// A `llvm-readobj` invocation builder. #[derive(Debug)] #[must_use] @@ -41,9 +47,17 @@ pub struct LlvmFilecheck { cmd: Command, } +/// A `llvm-objdump` invocation builder. +#[derive(Debug)] +#[must_use] +pub struct LlvmObjdump { + cmd: Command, +} + crate::impl_common_helpers!(LlvmReadobj); crate::impl_common_helpers!(LlvmProfdata); crate::impl_common_helpers!(LlvmFilecheck); +crate::impl_common_helpers!(LlvmObjdump); /// Generate the path to the bin directory of LLVM. #[must_use] @@ -125,3 +139,19 @@ impl LlvmFilecheck { self } } + +impl LlvmObjdump { + /// Construct a new `llvm-objdump` invocation. This assumes that `llvm-objdump` is available + /// at `$LLVM_BIN_DIR/llvm-objdump`. + pub fn new() -> Self { + let llvm_objdump = llvm_bin_dir().join("llvm-objdump"); + let cmd = Command::new(llvm_objdump); + Self { cmd } + } + + /// Provide an input file. + pub fn input>(&mut self, path: P) -> &mut Self { + self.cmd.arg(path.as_ref()); + self + } +} diff --git a/src/tools/run-make-support/src/llvm_readobj.rs b/src/tools/run-make-support/src/llvm_readobj.rs deleted file mode 100644 index 3c719356e8f..00000000000 --- a/src/tools/run-make-support/src/llvm_readobj.rs +++ /dev/null @@ -1,45 +0,0 @@ -use std::path::{Path, PathBuf}; - -use crate::command::Command; -use crate::env_var; - -/// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available -/// at `$LLVM_BIN_DIR/llvm-readobj`. -#[track_caller] -pub fn llvm_readobj() -> LlvmReadobj { - LlvmReadobj::new() -} - -/// A `llvm-readobj` invocation builder. -#[derive(Debug)] -#[must_use] -pub struct LlvmReadobj { - cmd: Command, -} - -crate::impl_common_helpers!(LlvmReadobj); - -impl LlvmReadobj { - /// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available - /// at `$LLVM_BIN_DIR/llvm-readobj`. - #[track_caller] - pub fn new() -> Self { - let llvm_bin_dir = env_var("LLVM_BIN_DIR"); - let llvm_bin_dir = PathBuf::from(llvm_bin_dir); - let llvm_readobj = llvm_bin_dir.join("llvm-readobj"); - let cmd = Command::new(llvm_readobj); - Self { cmd } - } - - /// Provide an input file. - pub fn input>(&mut self, path: P) -> &mut Self { - self.cmd.arg(path.as_ref()); - self - } - - /// Pass `--file-header` to display file headers. - pub fn file_header(&mut self) -> &mut Self { - self.cmd.arg("--file-header"); - self - } -} diff --git a/tests/run-make/issue-64153/Makefile b/tests/run-make/issue-64153/Makefile deleted file mode 100644 index f42ea620fb9..00000000000 --- a/tests/run-make/issue-64153/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -include ../tools.mk - -# `llvm-objdump`'s output looks different on windows than on other platforms. -# It should be enough to check on Unix platforms, so: -# ignore-windows - -# Staticlibs don't include Rust object files from upstream crates if the same -# code was already pulled into the lib via LTO. However, the bug described in -# https://github.com/rust-lang/rust/issues/64153 lead to this exclusion not -# working properly if the upstream crate was compiled with an explicit filename -# (via `-o`). -# -# This test makes sure that functions defined in the upstream crates do not -# appear twice in the final staticlib when listing all the symbols from it. - -all: - $(RUSTC) --crate-type rlib upstream.rs -o $(TMPDIR)/libupstream.rlib -Ccodegen-units=1 - $(RUSTC) --crate-type staticlib downstream.rs -Clto -Ccodegen-units=1 -o $(TMPDIR)/libdownstream.a - # Dump all the symbols from the staticlib into `syms` - "$(LLVM_BIN_DIR)"/llvm-objdump -t $(TMPDIR)/libdownstream.a > $(TMPDIR)/syms - # Count the global instances of `issue64153_test_function`. There'll be 2 - # if the `upstream` object file got erroneously included twice. - # The line we are testing for with the regex looks something like: - # 0000000000000000 g F .text.issue64153_test_function 00000023 issue64153_test_function - grep -c -e "[[:space:]]g[[:space:]]*F[[:space:]].*issue64153_test_function" $(TMPDIR)/syms > $(TMPDIR)/count - [ "$$(cat $(TMPDIR)/count)" -eq "1" ] diff --git a/tests/run-make/issue-64153/downstream.rs b/tests/run-make/lto-avoid-object-duplication/downstream.rs similarity index 100% rename from tests/run-make/issue-64153/downstream.rs rename to tests/run-make/lto-avoid-object-duplication/downstream.rs diff --git a/tests/run-make/lto-avoid-object-duplication/rmake.rs b/tests/run-make/lto-avoid-object-duplication/rmake.rs new file mode 100644 index 00000000000..018e6a25b92 --- /dev/null +++ b/tests/run-make/lto-avoid-object-duplication/rmake.rs @@ -0,0 +1,37 @@ +// Staticlibs don't include Rust object files from upstream crates if the same +// code was already pulled into the lib via LTO. However, the bug described in +// https://github.com/rust-lang/rust/issues/64153 lead to this exclusion not +// working properly if the upstream crate was compiled with an explicit filename +// (via `-o`). + +// This test makes sure that functions defined in the upstream crates do not +// appear twice in the final staticlib when listing all the symbols from it. + +//@ ignore-windows +// Reason: `llvm-objdump`'s output looks different on windows than on other platforms. +// Only checking on Unix platforms should suffice. + +use run_make_support::{llvm_objdump, regex, rust_lib_name, rustc, static_lib_name}; + +fn main() { + rustc() + .crate_type("rlib") + .input("upstream.rs") + .output(rust_lib_name("upstream")) + .codegen_units(1) + .run(); + rustc() + .crate_type("staticlib") + .input("downstream.rs") + .arg("-Clto") + .output(static_lib_name("downstream")) + .codegen_units(1) + .run(); + let syms = llvm_objdump().arg("-t").input(static_lib_name("downstream")).run().stdout_utf8(); + let re = regex::Regex::new(r#"(?m)\s*g\s*F\s.*issue64153_test_function"#).unwrap(); + // Count the global instances of `issue64153_test_function`. There'll be 2 + // if the `upstream` object file got erroneously included twice. + // The line we are testing for with the regex looks something like: + // 0000000000000000 g F .text.issue64153_test_function 00000023 issue64153_test_function + assert_eq!(re.find_iter(syms.as_str()).count(), 1); +} diff --git a/tests/run-make/issue-64153/upstream.rs b/tests/run-make/lto-avoid-object-duplication/upstream.rs similarity index 100% rename from tests/run-make/issue-64153/upstream.rs rename to tests/run-make/lto-avoid-object-duplication/upstream.rs