diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile index fa31801269afe..292dbfd20a509 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile @@ -49,9 +49,7 @@ ENV RUST_CONFIGURE_ARGS \ # (without necessarily testing the result). # - That the tests with `//@ needs-force-clang-based-tests` pass, since they # don't run by default unless RUSTBUILD_FORCE_CLANG_BASED_TESTS is set. -# - FIXME(https://github.com/rust-lang/rust/pull/126155#issuecomment-2156314273): -# Currently we only run the subset of tests with "clang" in their name. ENV SCRIPT \ python3 ../x.py --stage 2 build && \ - python3 ../x.py --stage 2 test tests/run-make --test-args clang + python3 ../x.py --stage 2 test tests/run-make diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 2b6366040490e..52c97907b6a23 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -253,7 +253,9 @@ auto: <<: *job-linux-4c - image: x86_64-gnu-debug - <<: *job-linux-4c + # This seems to be needed because a full stage 2 build + run-make tests + # overwhelms the storage capacity of the standard 4c runner. + <<: *job-linux-4c-largedisk - image: x86_64-gnu-distcheck <<: *job-linux-8c diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index 6b58173b34304..9e09527d6d08d 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -222,6 +222,12 @@ pub struct CompletedProcess { } impl CompletedProcess { + #[must_use] + #[track_caller] + pub fn stdout(&self) -> Vec { + self.output.stdout.clone() + } + #[must_use] #[track_caller] pub fn stdout_utf8(&self) -> String { @@ -234,12 +240,24 @@ impl CompletedProcess { String::from_utf8_lossy(&self.output.stdout.clone()).to_string() } + #[must_use] + #[track_caller] + pub fn stderr(&self) -> Vec { + self.output.stderr.clone() + } + #[must_use] #[track_caller] pub fn stderr_utf8(&self) -> String { String::from_utf8(self.output.stderr.clone()).expect("stderr is not valid UTF-8") } + #[must_use] + #[track_caller] + pub fn invalid_stderr_utf8(&self) -> String { + String::from_utf8_lossy(&self.output.stderr.clone()).to_string() + } + #[must_use] pub fn status(&self) -> ExitStatus { self.output.status diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index 38a9ac923b4dc..9a6e35da3fe20 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -60,6 +60,18 @@ pub fn llvm_pdbutil() -> LlvmPdbutil { LlvmPdbutil::new() } +/// Construct a new `llvm-dis` invocation. This assumes that `llvm-dis` is available +/// at `$LLVM_BIN_DIR/llvm-dis`. +pub fn llvm_dis() -> LlvmDis { + LlvmDis::new() +} + +/// Construct a new `llvm-objcopy` invocation. This assumes that `llvm-objcopy` is available +/// at `$LLVM_BIN_DIR/llvm-objcopy`. +pub fn llvm_objcopy() -> LlvmObjcopy { + LlvmObjcopy::new() +} + /// A `llvm-readobj` invocation builder. #[derive(Debug)] #[must_use] @@ -123,6 +135,20 @@ pub struct LlvmPdbutil { cmd: Command, } +/// A `llvm-dis` invocation builder. +#[derive(Debug)] +#[must_use] +pub struct LlvmDis { + cmd: Command, +} + +/// A `llvm-objcopy` invocation builder. +#[derive(Debug)] +#[must_use] +pub struct LlvmObjcopy { + cmd: Command, +} + crate::macros::impl_common_helpers!(LlvmReadobj); crate::macros::impl_common_helpers!(LlvmProfdata); crate::macros::impl_common_helpers!(LlvmFilecheck); @@ -132,6 +158,8 @@ crate::macros::impl_common_helpers!(LlvmNm); crate::macros::impl_common_helpers!(LlvmBcanalyzer); crate::macros::impl_common_helpers!(LlvmDwarfdump); crate::macros::impl_common_helpers!(LlvmPdbutil); +crate::macros::impl_common_helpers!(LlvmDis); +crate::macros::impl_common_helpers!(LlvmObjcopy); /// Generate the path to the bin directory of LLVM. #[must_use] @@ -390,3 +418,41 @@ impl LlvmPdbutil { self } } + +impl LlvmObjcopy { + /// Construct a new `llvm-objcopy` invocation. This assumes that `llvm-objcopy` is available + /// at `$LLVM_BIN_DIR/llvm-objcopy`. + pub fn new() -> Self { + let llvm_objcopy = llvm_bin_dir().join("llvm-objcopy"); + let cmd = Command::new(llvm_objcopy); + Self { cmd } + } + + /// Dump the contents of `section` into the file at `path`. + #[track_caller] + pub fn dump_section, P: AsRef>( + &mut self, + section_name: S, + path: P, + ) -> &mut Self { + self.cmd.arg("--dump-section"); + self.cmd.arg(format!("{}={}", section_name.as_ref(), path.as_ref().to_str().unwrap())); + self + } +} + +impl LlvmDis { + /// Construct a new `llvm-dis` invocation. This assumes that `llvm-dis` is available + /// at `$LLVM_BIN_DIR/llvm-dis`. + pub fn new() -> Self { + let llvm_dis = llvm_bin_dir().join("llvm-dis"); + let cmd = Command::new(llvm_dis); + 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/lib.rs b/src/tools/run-make-support/src/lib.rs index 15d813ccf5300..368b98c9f0dfd 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -49,14 +49,17 @@ pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rust // These rely on external dependencies. pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc}; -pub use c_build::{build_native_dynamic_lib, build_native_static_lib, build_native_static_lib_optimized, build_native_static_lib_cxx}; +pub use c_build::{ + build_native_dynamic_lib, build_native_static_lib, build_native_static_lib_cxx, + build_native_static_lib_optimized, +}; pub use cargo::cargo; pub use clang::{clang, Clang}; pub use htmldocck::htmldocck; pub use llvm::{ - llvm_ar, llvm_bcanalyzer, llvm_dwarfdump, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, - llvm_readobj, LlvmAr, LlvmBcanalyzer, LlvmDwarfdump, LlvmFilecheck, LlvmNm, LlvmObjdump, - LlvmProfdata, LlvmReadobj, + llvm_ar, llvm_bcanalyzer, llvm_dis, llvm_dwarfdump, llvm_filecheck, llvm_nm, llvm_objcopy, + llvm_objdump, llvm_profdata, llvm_readobj, LlvmAr, LlvmBcanalyzer, LlvmDis, LlvmDwarfdump, + LlvmFilecheck, LlvmNm, LlvmObjcopy, LlvmObjdump, LlvmProfdata, LlvmReadobj, }; pub use python::python_command; pub use rustc::{aux_build, bare_rustc, rustc, rustc_path, Rustc}; diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 7a0f98d59f00d..0e156b9d1ac9a 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -2,7 +2,6 @@ run-make/branch-protection-check-IBT/Makefile run-make/cat-and-grep-sanity-check/Makefile run-make/extern-fn-reachable/Makefile run-make/incr-add-rust-src-component/Makefile -run-make/issue-84395-lto-embed-bitcode/Makefile run-make/jobserver-error/Makefile run-make/libs-through-symlinks/Makefile run-make/split-debuginfo/Makefile diff --git a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs index 92573353a741b..e595dbea94d61 100644 --- a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs +++ b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs @@ -1,21 +1,20 @@ -//! Make sure that cross-language LTO works on riscv targets, -//! which requires extra `target-abi` metadata to be emitted. +//! Make sure that cross-language LTO works on riscv targets, which requires extra `target-abi` +//! metadata to be emitted. //@ needs-force-clang-based-tests -//@ needs-llvm-components riscv +//@ needs-llvm-components: riscv -//@ needs-force-clang-based-tests -// FIXME(#126180): This test can only run on `x86_64-gnu-debug`, because that CI job sets -// RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their -// name. -// However, this test does not run at all as its name does not contain "clang". - -use std::path::PathBuf; -use std::process::{Command, Output}; -use std::{env, str}; +// ignore-tidy-linelength -use run_make_support::{bin_name, clang, llvm_readobj, rustc}; +use object::elf; +use object::read::elf as readelf; +use run_make_support::{bin_name, clang, object, rfs, rustc}; -fn check_target(target: &str, clang_target: &str, carch: &str, is_double_float: bool) { +fn check_target>( + target: &str, + clang_target: &str, + carch: &str, + is_double_float: bool, +) { eprintln!("Checking target {target}"); // Rust part rustc() @@ -39,16 +38,55 @@ fn check_target(target: &str, clang_target: &str, carch: &str, is_double_float: // Check that the built binary has correct float abi let executable = bin_name("riscv-xlto"); - let output = llvm_readobj().input(&executable).file_header().run(); - let stdout = String::from_utf8_lossy(&output.stdout); - eprintln!("obj:\n{}", stdout); - - assert!(!(is_double_float ^ stdout.contains("EF_RISCV_FLOAT_ABI_DOUBLE"))); + let data = rfs::read(&executable); + let header = ::parse(&*data).unwrap(); + let endian = match header.e_ident().data { + elf::ELFDATA2LSB => object::Endianness::Little, + elf::ELFDATA2MSB => object::Endianness::Big, + x => unreachable!("invalid e_ident data: {:#010b}", x), + }; + // Check `(e_flags & EF_RISCV_FLOAT_ABI) == EF_RISCV_FLOAT_ABI_DOUBLE`. + // + // See + // . + if is_double_float { + assert_eq!( + header.e_flags(endian) & elf::EF_RISCV_FLOAT_ABI, + elf::EF_RISCV_FLOAT_ABI_DOUBLE, + "expected {target} to use double ABI, but it did not" + ); + } else { + assert_ne!( + header.e_flags(endian) & elf::EF_RISCV_FLOAT_ABI, + elf::EF_RISCV_FLOAT_ABI_DOUBLE, + "did not expected {target} to use double ABI" + ); + } } fn main() { - check_target("riscv64gc-unknown-linux-gnu", "riscv64-linux-gnu", "rv64gc", true); - check_target("riscv64imac-unknown-none-elf", "riscv64-unknown-elf", "rv64imac", false); - check_target("riscv32imac-unknown-none-elf", "riscv32-unknown-elf", "rv32imac", false); - check_target("riscv32gc-unknown-linux-gnu", "riscv32-linux-gnu", "rv32gc", true); + check_target::>( + "riscv64gc-unknown-linux-gnu", + "riscv64-linux-gnu", + "rv64gc", + true, + ); + check_target::>( + "riscv64imac-unknown-none-elf", + "riscv64-unknown-elf", + "rv64imac", + false, + ); + check_target::>( + "riscv32imac-unknown-none-elf", + "riscv32-unknown-elf", + "rv32imac", + false, + ); + check_target::>( + "riscv32gc-unknown-linux-gnu", + "riscv32-linux-gnu", + "rv32gc", + true, + ); } diff --git a/tests/run-make/issue-84395-lto-embed-bitcode/Makefile b/tests/run-make/issue-84395-lto-embed-bitcode/Makefile deleted file mode 100644 index aabe90754a654..0000000000000 --- a/tests/run-make/issue-84395-lto-embed-bitcode/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# needs-force-clang-based-tests - -# FIXME(#126180): This test doesn't actually run anywhere, because the only -# CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests. - -# This test makes sure the embed bitcode in elf created with -# lto-embed-bitcode=optimized is valid llvm BC module. - -include ../tools.mk - -all: - $(RUSTC) test.rs --target $(TARGET) -Clink-arg=-fuse-ld=lld -Clinker-plugin-lto -Clinker=$(CLANG) -Clink-arg=-Wl,--plugin-opt=-lto-embed-bitcode=optimized -Zemit-thin-lto=no - $(LLVM_BIN_DIR)/objcopy --dump-section .llvmbc=$(TMPDIR)/test.bc $(TMPDIR)/test - $(LLVM_BIN_DIR)/llvm-dis $(TMPDIR)/test.bc diff --git a/tests/run-make/issue-84395-lto-embed-bitcode/rmake.rs b/tests/run-make/issue-84395-lto-embed-bitcode/rmake.rs new file mode 100644 index 0000000000000..450d8a9f099b4 --- /dev/null +++ b/tests/run-make/issue-84395-lto-embed-bitcode/rmake.rs @@ -0,0 +1,27 @@ +//! Smoke test to make sure the embed bitcode in elf created with +//! `--plugin-opt=-lto-embed-bitcode=optimized` is valid llvm BC module. +//! +//! See where passing +//! `-lto-embed-bitcode=optimized` to lld when linking rust code via `linker-plugin-lto` doesn't +//! produce the expected result. +//! +//! See PR which initially introduced this test. + +//@ needs-force-clang-based-tests + +use run_make_support::{env_var, llvm_dis, llvm_objcopy, rustc}; + +fn main() { + rustc() + .input("test.rs") + .arg("-Clink-arg=-fuse-ld=lld") + .arg("-Clinker-plugin-lto") + .arg(format!("-Clinker={}", env_var("CLANG"))) + .arg("-Clink-arg=-Wl,--plugin-opt=-lto-embed-bitcode=optimized") + .arg("-Zemit-thin-lto=no") + .run(); + + llvm_objcopy().dump_section(".llvmbc", "test.bc").arg("test").run(); + + llvm_dis().arg("test.bc").run(); +}