about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/run-make-support/src/external_deps/clang.rs5
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt1
-rw-r--r--tests/run-make/cross-lang-lto-clang/_Makefile29
-rw-r--r--tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile (renamed from tests/run-make/cross-lang-lto-pgo-smoketest/Makefile)4
-rw-r--r--tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs111
5 files changed, 147 insertions, 3 deletions
diff --git a/src/tools/run-make-support/src/external_deps/clang.rs b/src/tools/run-make-support/src/external_deps/clang.rs
index 2b0712541cd..2d110c6825e 100644
--- a/src/tools/run-make-support/src/external_deps/clang.rs
+++ b/src/tools/run-make-support/src/external_deps/clang.rs
@@ -1,7 +1,7 @@
 use std::path::Path;
 
 use crate::command::Command;
-use crate::{bin_name, env_var};
+use crate::{bin_name, cwd, env_var};
 
 /// Construct a new `clang` invocation. `clang` is not always available for all targets.
 #[track_caller]
@@ -23,7 +23,8 @@ impl Clang {
     #[track_caller]
     pub fn new() -> Self {
         let clang = env_var("CLANG");
-        let cmd = Command::new(clang);
+        let mut cmd = Command::new(clang);
+        cmd.arg("-L").arg(cwd());
         Self { cmd }
     }
 
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index b04f472e5bf..46fe73ee5ae 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -1,7 +1,6 @@
 run-make/branch-protection-check-IBT/Makefile
 run-make/cat-and-grep-sanity-check/Makefile
 run-make/cdylib-dylib-linkage/Makefile
-run-make/cross-lang-lto-pgo-smoketest/Makefile
 run-make/cross-lang-lto-upstream-rlibs/Makefile
 run-make/dep-info-doesnt-run-much/Makefile
 run-make/dep-info-spaces/Makefile
diff --git a/tests/run-make/cross-lang-lto-clang/_Makefile b/tests/run-make/cross-lang-lto-clang/_Makefile
new file mode 100644
index 00000000000..b039328b0f9
--- /dev/null
+++ b/tests/run-make/cross-lang-lto-clang/_Makefile
@@ -0,0 +1,29 @@
+# FIXME(Oneirical): This is already implemented as an rmake.rs file, but due to #126180,
+# the rmake.rs is not ran on CI. Once the rmake test has been proven to work, remove this
+# Makefile.
+
+# needs-force-clang-based-tests
+
+# This test makes sure that cross-language inlining actually works by checking
+# the generated machine code.
+
+include ../tools.mk
+
+all: cpp-executable rust-executable
+
+cpp-executable:
+	$(RUSTC) -Clinker-plugin-lto=on -o $(TMPDIR)/librustlib-xlto.a -Copt-level=2 -Ccodegen-units=1 ./rustlib.rs
+	$(CLANG) -flto=thin -fuse-ld=lld -L $(TMPDIR) -lrustlib-xlto -o $(TMPDIR)/cmain ./cmain.c -O3
+	# Make sure we don't find a call instruction to the function we expect to
+	# always be inlined.
+	"$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -v -e "call.*rust_always_inlined"
+	# As a sanity check, make sure we do find a call instruction to a
+	# non-inlined function
+	"$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -e "call.*rust_never_inlined"
+
+rust-executable:
+	$(CLANG) ./clib.c -flto=thin -c -o $(TMPDIR)/clib.o -O2
+	(cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o)
+	$(RUSTC) -Clinker-plugin-lto=on -L$(TMPDIR) -Copt-level=2 -Clinker=$(CLANG) -Clink-arg=-fuse-ld=lld ./main.rs -o $(TMPDIR)/rsmain
+	"$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -e "call.*c_never_inlined"
+	"$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -v -e "call.*c_always_inlined"
diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/Makefile b/tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile
index 738e23f9c66..737f066b4da 100644
--- a/tests/run-make/cross-lang-lto-pgo-smoketest/Makefile
+++ b/tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile
@@ -1,3 +1,7 @@
+# FIXME(Oneirical): This is already implemented as an rmake.rs file, but due to #126180,
+# the rmake.rs is not ran on CI. Once the rmake test has been proven to work, remove this
+# Makefile.
+
 # needs-force-clang-based-tests
 
 # FIXME(#126180): This test doesn't actually run anywhere, because the only
diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs b/tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs
new file mode 100644
index 00000000000..e4d8879607f
--- /dev/null
+++ b/tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs
@@ -0,0 +1,111 @@
+// This test makes sure that cross-language inlining can be used in conjunction
+// with profile-guided optimization. The test only tests that the whole workflow
+// can be executed without anything crashing. It does not test whether PGO or
+// xLTO have any specific effect on the generated code.
+// See https://github.com/rust-lang/rust/pull/61036
+
+//@ 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.
+
+//FIXME(Oneirical): There was a strange workaround for MSVC on this test
+// which added -C panic=abort to every RUSTC call. It was justified as follows:
+// LLVM doesn't support instrumenting binaries that use SEH:
+// https://bugs.llvm.org/show_bug.cgi?id=41279
+// Things work fine with -Cpanic=abort though.
+
+use run_make_support::{
+    clang, env_var, has_extension, has_prefix, llvm_ar, llvm_profdata, rfs, run, rustc,
+    shallow_find_files, static_lib_name,
+};
+
+fn main() {
+    rustc()
+        .linker_plugin_lto("on")
+        .output(static_lib_name("rustlib-xlto"))
+        .opt_level("3")
+        .codegen_units(1)
+        .input("rustlib.rs")
+        .arg("-Cprofile-generate=cpp-profdata")
+        .run();
+    clang()
+        .lto("thin")
+        .arg("-fprofile-generate=cpp-profdata")
+        .use_ld("lld")
+        .arg("-lrustlib-xlto")
+        .out_exe("cmain")
+        .input("cmain.c")
+        .arg("-O3")
+        .run();
+    run("cmain");
+    // Postprocess the profiling data so it can be used by the compiler
+    let profraw_files = shallow_find_files("cpp-profdata", |path| {
+        has_prefix(path, "default") && has_extension(path, "profraw")
+    });
+    let profraw_file = profraw_files.get(0).unwrap();
+    llvm_profdata().merge().output("cpp-profdata/merged.profdata").input(profraw_file).run();
+    rustc()
+        .linker_plugin_lto("on")
+        .profile_use("cpp-profdata/merged.profdata")
+        .output(static_lib_name("rustlib-xlto"))
+        .opt_level("3")
+        .codegen_units(1)
+        .input("rustlib.rs")
+        .run();
+    clang()
+        .lto("thin")
+        .arg("-fprofile-use=cpp-profdata/merged.profdata")
+        .use_ld("lld")
+        .arg("-lrustlib-xlto")
+        .out_exe("cmain")
+        .input("cmain.c")
+        .arg("-O3")
+        .run();
+
+    clang()
+        .input("clib.c")
+        .arg("-fprofile-generate=rs-profdata")
+        .lto("thin")
+        .arg("-c")
+        .out_exe("clib.o")
+        .arg("-O3")
+        .run();
+    llvm_ar().obj_to_ar().output_input(static_lib_name("xyz"), "clib.o").run();
+    rustc()
+        .linker_plugin_lto("on")
+        .opt_level("3")
+        .codegen_units(1)
+        .arg("-Cprofile-generate=rs-profdata")
+        .linker(&env_var("CLANG"))
+        .link_arg("-fuse-ld=lld")
+        .input("main.rs")
+        .output("rsmain")
+        .run();
+    run("rsmain");
+    // Postprocess the profiling data so it can be used by the compiler
+    let profraw_files = shallow_find_files("rs-profdata", |path| {
+        has_prefix(path, "default") && has_extension(path, "profraw")
+    });
+    let profraw_file = profraw_files.get(0).unwrap();
+    llvm_profdata().merge().output("rs-profdata/merged.profdata").input(profraw_file).run();
+    clang()
+        .input("clib.c")
+        .arg("-fprofile-use=rs-profdata/merged.profdata")
+        .arg("-c")
+        .lto("thin")
+        .out_exe("clib.o")
+        .arg("-O3")
+        .run();
+    rfs::remove_file(static_lib_name("xyz"));
+    llvm_ar().obj_to_ar().output_input(static_lib_name("xyz"), "clib.o").run();
+    rustc()
+        .linker_plugin_lto("on")
+        .opt_level("3")
+        .codegen_units(1)
+        .arg("-Cprofile-use=rs-profdata/merged.profdata")
+        .linker(&env_var("CLANG"))
+        .link_arg("-fuse-ld=lld")
+        .input("main.rs")
+        .output("rsmain")
+        .run();
+}