Skip to content

Commit

Permalink
Auto merge of #57514 - michaelwoerister:xlto-tests, r=<try>
Browse files Browse the repository at this point in the history
compiletest: Support opt-in Clang-based run-make tests and use them for testing xLTO.

Some cross-language run-make tests need a Clang compiler that matches the LLVM version of `rustc`. Since such a compiler usually isn't available these tests (marked with the `needs-matching-clang`
directive) are ignored by default.

For some CI jobs we do need these tests to run unconditionally though. In order to support this a `--force-clang-based-tests` flag is added to compiletest. If this flag is specified, `compiletest` will fail if it can't detect an appropriate version of Clang.

@rust-lang/infra The PR doesn't yet enable the tests yet. Do you have any recommendation for which jobs to enable them?

cc #57438

r? @alexcrichton
  • Loading branch information
bors committed Jan 24, 2019
2 parents 01f8e25 + 0644eb6 commit adad6fb
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ matrix:
- env: IMAGE=x86_64-gnu-llvm-6.0 RUST_BACKTRACE=1
if: type = pull_request OR branch = auto

- env: IMAGE=dist-x86_64-linux DEPLOY=1
- env: IMAGE=x86_64-gnu-debug
if: branch = try OR branch = auto

# "alternate" deployments, these are "nightlies" but have LLVM assertions
Expand Down
24 changes: 21 additions & 3 deletions src/bootstrap/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1088,9 +1088,7 @@ impl Step for Compiletest {
};
let lldb_exe = if builder.config.lldb_enabled && !target.contains("emscripten") {
// Test against the lldb that was just built.
builder.llvm_out(target)
.join("bin")
.join("lldb")
builder.llvm_out(target).join("bin").join("lldb")
} else {
PathBuf::from("lldb")
};
Expand All @@ -1107,6 +1105,26 @@ impl Step for Compiletest {
}
}

if let Some(var) = env::var_os("RUSTBUILD_FORCE_CLANG_BASED_TESTS") {
match &var.to_string_lossy().to_lowercase()[..] {
"1" | "yes" | "on" => {
assert!(builder.config.lldb_enabled,
"RUSTBUILD_FORCE_CLANG_BASED_TESTS needs Clang/LLDB to \
be built.");
let clang_exe = builder.llvm_out(target).join("bin").join("clang");
cmd.arg("--run-clang-based-tests-with").arg(clang_exe);
}
"0" | "no" | "off" => {
// Nothing to do.
}
other => {
// Let's make sure typos don't get unnoticed
panic!("Unrecognized option '{}' set in \
RUSTBUILD_FORCE_CLANG_BASED_TESTS", other);
}
}
}

// Get paths from cmd args
let paths = match &builder.config.cmd {
Subcommand::Test { ref paths, .. } => &paths[..],
Expand Down
14 changes: 13 additions & 1 deletion src/ci/docker/x86_64-gnu-debug/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
ca-certificates \
python2.7 \
python2.7-dev \
libxml2-dev \
libncurses-dev \
libedit-dev \
swig \
doxygen \
git \
cmake \
sudo \
Expand All @@ -16,9 +22,15 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh

ENV RUSTBUILD_FORCE_CLANG_BASED_TESTS 1
ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1

ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
--enable-debug \
--enable-lld \
--enable-lldb \
--enable-optimize
ENV SCRIPT python2.7 ../x.py build
ENV SCRIPT \
python2.7 ../x.py build && \
python2.7 ../x.py test src/test/run-make-fulldeps --test-args clang
25 changes: 25 additions & 0 deletions src/test/run-make-fulldeps/cross-lang-lto-clang/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# needs-matching-clang

# 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) -Zcross-lang-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-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-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) -Zcross-lang-lto=on -L$(TMPDIR) -Copt-level=2 -Clinker=$(CLANG) -Clink-arg=-fuse-ld=lld ./main.rs -o $(TMPDIR)/rsmain
llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -e "call.*c_never_inlined"
llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -v -e "call.*c_always_inlined"
9 changes: 9 additions & 0 deletions src/test/run-make-fulldeps/cross-lang-lto-clang/clib.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <stdint.h>

uint32_t c_always_inlined() {
return 1234;
}

__attribute__((noinline)) uint32_t c_never_inlined() {
return 12345;
}
12 changes: 12 additions & 0 deletions src/test/run-make-fulldeps/cross-lang-lto-clang/cmain.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <stdint.h>

// A trivial function defined in Rust, returning a constant value. This should
// always be inlined.
uint32_t rust_always_inlined();


uint32_t rust_never_inlined();

int main(int argc, char** argv) {
return rust_never_inlined() + rust_always_inlined();
}
11 changes: 11 additions & 0 deletions src/test/run-make-fulldeps/cross-lang-lto-clang/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#[link(name = "xyz")]
extern "C" {
fn c_always_inlined() -> u32;
fn c_never_inlined() -> u32;
}

fn main() {
unsafe {
println!("blub: {}", c_always_inlined() + c_never_inlined());
}
}
12 changes: 12 additions & 0 deletions src/test/run-make-fulldeps/cross-lang-lto-clang/rustlib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#![crate_type="staticlib"]

#[no_mangle]
pub extern "C" fn rust_always_inlined() -> u32 {
42
}

#[no_mangle]
#[inline(never)]
pub extern "C" fn rust_never_inlined() -> u32 {
421
}
4 changes: 4 additions & 0 deletions src/tools/compiletest/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ pub struct Config {
/// (or, alternatively, to silently run them like regular run-pass tests).
pub force_valgrind: bool,

/// The path to the Clang executable to run Clang-based tests with. If
/// `None` then these tests will be ignored.
pub run_clang_based_tests_with: Option<String>,

/// The directory containing the tests to run
pub src_base: PathBuf,

Expand Down
9 changes: 9 additions & 0 deletions src/tools/compiletest/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ impl EarlyProps {
if ignore_llvm(config, ln) {
props.ignore = Ignore::Ignore;
}

if config.run_clang_based_tests_with.is_none() &&
config.parse_needs_matching_clang(ln) {
props.ignore = Ignore::Ignore;
}
}

if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoBoth) &&
Expand Down Expand Up @@ -705,6 +710,10 @@ impl Config {
}
}

fn parse_needs_matching_clang(&self, line: &str) -> bool {
self.parse_name_directive(line, "needs-matching-clang")
}

/// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86`
/// or `normalize-stderr-32bit`.
fn parse_cfg_name_directive(&self, line: &str, prefix: &str) -> ParsedNameDirective {
Expand Down
7 changes: 7 additions & 0 deletions src/tools/compiletest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
"force-valgrind",
"fail if Valgrind tests cannot be run under Valgrind",
)
.optopt(
"",
"run-clang-based-tests-with",
"path to Clang executable",
"PATH",
)
.optopt(
"",
"llvm-filecheck",
Expand Down Expand Up @@ -298,6 +304,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
docck_python: matches.opt_str("docck-python").unwrap(),
valgrind_path: matches.opt_str("valgrind-path"),
force_valgrind: matches.opt_present("force-valgrind"),
run_clang_based_tests_with: matches.opt_str("run-clang-based-tests-with"),
llvm_filecheck: matches.opt_str("llvm-filecheck").map(|s| PathBuf::from(&s)),
src_base,
build_base: opt_path(matches, "build-base"),
Expand Down
4 changes: 4 additions & 0 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2587,6 +2587,10 @@ impl<'test> TestCx<'test> {
cmd.env("RUSTC_LINKER", linker);
}

if let Some(ref clang) = self.config.run_clang_based_tests_with {
cmd.env("CLANG", clang);
}

// We don't want RUSTFLAGS set from the outside to interfere with
// compiler flags set in the test cases:
cmd.env_remove("RUSTFLAGS");
Expand Down

0 comments on commit adad6fb

Please sign in to comment.