Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow tests to specify a //@ filecheck-flags: header #120656

Merged
merged 6 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/tools/compiletest/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ pub struct TestProps {
/// Extra flags to pass to `llvm-cov` when producing coverage reports.
/// Only used by the "coverage-run" test mode.
pub llvm_cov_flags: Vec<String>,
/// Extra flags to pass to LLVM's `filecheck` tool, in tests that use it.
pub filecheck_flags: Vec<String>,
}

mod directives {
Expand Down Expand Up @@ -236,6 +238,7 @@ mod directives {
pub const REMAP_SRC_BASE: &'static str = "remap-src-base";
pub const COMPARE_OUTPUT_LINES_BY_SUBSET: &'static str = "compare-output-lines-by-subset";
pub const LLVM_COV_FLAGS: &'static str = "llvm-cov-flags";
pub const FILECHECK_FLAGS: &'static str = "filecheck-flags";
// This isn't a real directive, just one that is probably mistyped often
pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags";
}
Expand Down Expand Up @@ -286,6 +289,7 @@ impl TestProps {
mir_unit_test: None,
remap_src_base: false,
llvm_cov_flags: vec![],
filecheck_flags: vec![],
}
}

Expand Down Expand Up @@ -542,6 +546,10 @@ impl TestProps {
if let Some(flags) = config.parse_name_value_directive(ln, LLVM_COV_FLAGS) {
self.llvm_cov_flags.extend(split_flags(&flags));
}

if let Some(flags) = config.parse_name_value_directive(ln, FILECHECK_FLAGS) {
self.filecheck_flags.extend(split_flags(&flags));
}
},
);

Expand Down
39 changes: 23 additions & 16 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2906,25 +2906,32 @@ impl<'test> TestCx<'test> {
fn verify_with_filecheck(&self, output: &Path) -> ProcRes {
let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap());
filecheck.arg("--input-file").arg(output).arg(&self.testpaths.file);
// It would be more appropriate to make most of the arguments configurable through
// a comment-attribute similar to `compile-flags`. For example, --check-prefixes is a very
// useful flag.
//
// For now, though…
let prefix_for_target =
if self.config.target.contains("msvc") { "MSVC" } else { "NONMSVC" };
let prefixes = if let Some(rev) = self.revision {
format!("CHECK,{},{}", prefix_for_target, rev)
} else {
format!("CHECK,{}", prefix_for_target)
};
if self.config.llvm_version.unwrap_or(0) >= 130000 {
filecheck.args(&["--allow-unused-prefixes", "--check-prefixes", &prefixes]);
} else {
filecheck.args(&["--check-prefixes", &prefixes]);

// FIXME: Consider making some of these prefix flags opt-in per test,
// via `filecheck-flags` or by adding new header directives.

// Because we use custom prefixes, we also have to register the default prefix.
filecheck.arg("--check-prefix=CHECK");

// Some tests use the current revision name as a check prefix.
if let Some(rev) = self.revision {
filecheck.arg("--check-prefix").arg(rev);
}

// Some tests also expect either the MSVC or NONMSVC prefix to be defined.
let msvc_or_not = if self.config.target.contains("msvc") { "MSVC" } else { "NONMSVC" };
filecheck.arg("--check-prefix").arg(msvc_or_not);

// The filecheck tool normally fails if a prefix is defined but not used.
// However, we define several prefixes globally for all tests.
filecheck.arg("--allow-unused-prefixes");

// Provide more context on failures.
filecheck.args(&["--dump-input-context", "100"]);

// Add custom flags supplied by the `filecheck-flags:` test header.
filecheck.args(&self.props.filecheck_flags);

self.compose_and_run(filecheck, "", None, None)
}

Expand Down
120 changes: 120 additions & 0 deletions tests/codegen/instrument-coverage/testprog.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//@ edition: 2021
//@ needs-profiler-support
//@ compile-flags: -Cinstrument-coverage -Copt-level=0
//@ revisions: LINUX DARWIN WINDOWS

//@ [LINUX] only-linux
//@ [LINUX] filecheck-flags: -DINSTR_PROF_DATA=__llvm_prf_data
//@ [LINUX] filecheck-flags: -DINSTR_PROF_NAME=__llvm_prf_names
//@ [LINUX] filecheck-flags: -DINSTR_PROF_CNTS=__llvm_prf_cnts
//@ [LINUX] filecheck-flags: -DINSTR_PROF_COVMAP=__llvm_covmap
//@ [LINUX] filecheck-flags: -DINSTR_PROF_COVFUN=__llvm_covfun
//@ [LINUX] filecheck-flags: '-DCOMDAT_IF_SUPPORTED=, comdat'

//@ [DARWIN] only-macos
//@ [DARWIN] filecheck-flags: -DINSTR_PROF_DATA=__DATA,__llvm_prf_data,regular,live_support
//@ [DARWIN] filecheck-flags: -DINSTR_PROF_NAME=__DATA,__llvm_prf_names
//@ [DARWIN] filecheck-flags: -DINSTR_PROF_CNTS=__DATA,__llvm_prf_cnts
//@ [DARWIN] filecheck-flags: -DINSTR_PROF_COVMAP=__LLVM_COV,__llvm_covmap
//@ [DARWIN] filecheck-flags: -DINSTR_PROF_COVFUN=__LLVM_COV,__llvm_covfun
//@ [DARWIN] filecheck-flags: -DCOMDAT_IF_SUPPORTED=

//@ [WINDOWS] only-windows
//@ [WINDOWS] filecheck-flags: -DINSTR_PROF_DATA=.lprfd$M
//@ [WINDOWS] filecheck-flags: -DINSTR_PROF_NAME=.lprfn$M
//@ [WINDOWS] filecheck-flags: -DINSTR_PROF_CNTS=.lprfc$M
//@ [WINDOWS] filecheck-flags: -DINSTR_PROF_COVMAP=.lcovmap$M
//@ [WINDOWS] filecheck-flags: -DINSTR_PROF_COVFUN=.lcovfun$M
//@ [WINDOWS] filecheck-flags: '-DCOMDAT_IF_SUPPORTED=, comdat'

// ignore-tidy-linelength

pub fn will_be_called() -> &'static str {
let val = "called";
println!("{}", val);
val
}

pub fn will_not_be_called() -> bool {
println!("should not have been called");
false
}

pub fn print<T>(left: &str, value: T, right: &str)
where
T: std::fmt::Display,
{
println!("{}{}{}", left, value, right);
}

pub fn wrap_with<F, T>(inner: T, should_wrap: bool, wrapper: F)
where
F: FnOnce(&T)
{
if should_wrap {
wrapper(&inner)
}
}

fn main() {
let less = 1;
let more = 100;

if less < more {
wrap_with(will_be_called(), less < more, |inner| print(" ***", inner, "*** "));
wrap_with(will_be_called(), more < less, |inner| print(" ***", inner, "*** "));
} else {
wrap_with(will_not_be_called(), true, |inner| print("wrapped result is: ", inner, ""));
}
}

// Check for metadata, variables, declarations, and function definitions injected
// into LLVM IR when compiling with -Cinstrument-coverage.

// WINDOWS: $__llvm_profile_runtime_user = comdat any

// CHECK: @__llvm_coverage_mapping = private constant
// CHECK-SAME: section "[[INSTR_PROF_COVMAP]]", align 8

// CHECK: @__covrec_{{[A-F0-9]+}}u = linkonce_odr hidden constant
// CHECK-SAME: section "[[INSTR_PROF_COVFUN]]"[[COMDAT_IF_SUPPORTED]], align 8

// WINDOWS: @__llvm_profile_runtime = external{{.*}}global i32

// CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global
// CHECK-SAME: section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8

// CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global
// CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called
// CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8

// CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main = {{private|internal}} global
// CHECK-SAME: section "[[INSTR_PROF_CNTS]]"{{.*}}, align 8

// CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog4main = {{private|internal}} global
// CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main
// CHECK-SAME: section "[[INSTR_PROF_DATA]]"{{.*}}, align 8

// CHECK: @__llvm_prf_nm = private constant
// CHECK-SAME: section "[[INSTR_PROF_NAME]]", align 1

// CHECK: @llvm.used = appending global
// CHECK-SAME: @__llvm_coverage_mapping
// CHECK-SAME: @__llvm_prf_nm
// CHECK-SAME: section "llvm.metadata"

// CHECK: define internal { {{.*}} } @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called() unnamed_addr #{{[0-9]+}} {
// CHECK-NEXT: start:
// CHECK-NOT: define internal
// CHECK: atomicrmw add ptr
// CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,

// CHECK: declare void @llvm.instrprof.increment(ptr, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]

// WINDOWS: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {
// WINDOWS-NEXT: %1 = load i32, ptr @__llvm_profile_runtime
// WINDOWS-NEXT: ret i32 %1
// WINDOWS-NEXT: }

// CHECK: attributes #[[LLVM_INSTRPROF_INCREMENT_ATTR]] = { nounwind }
// WINDOWS: attributes #[[LLVM_PROFILE_RUNTIME_USER_ATTR]] = { noinline }
4 changes: 4 additions & 0 deletions tests/codegen/meta-filecheck/check-prefix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Simple test that uses the default CHECK prefix and should always succeed.

// CHECK: main
fn main() {}
8 changes: 8 additions & 0 deletions tests/codegen/meta-filecheck/filecheck-flags.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Arguments provided via `filecheck-flags` should be passed to `filecheck`.

//@ revisions: good bad
//@ [good] filecheck-flags: --check-prefix=CUSTOM
//@ [bad] should-fail

// CUSTOM: main
fn main() {}
7 changes: 7 additions & 0 deletions tests/codegen/meta-filecheck/msvc-prefix-bad.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// This is exactly like `msvc-prefix-good.rs`, except that it should always fail.

//@ should-fail

// MSVC: text that should not match
// NONMSVC: text that should not match
fn main() {}
7 changes: 7 additions & 0 deletions tests/codegen/meta-filecheck/msvc-prefix-good.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// One of MSVC or NONMSVC should always be defined, so this test should pass.

// (one of these should always be present)

// MSVC: main
// NONMSVC: main
fn main() {}
5 changes: 5 additions & 0 deletions tests/codegen/meta-filecheck/no-directives.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// A test that doesn't include any filecheck directives should fail.

//@ should-fail

fn main() {}
8 changes: 8 additions & 0 deletions tests/codegen/meta-filecheck/revision-prefix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// The current revision name is registered as a filecheck prefix.

//@ revisions: GOOD BAD
//@ [BAD] should-fail

// GOOD: main
// BAD: text that should not match
fn main() {}
64 changes: 0 additions & 64 deletions tests/run-make/coverage-llvmir/Makefile

This file was deleted.

50 changes: 0 additions & 50 deletions tests/run-make/coverage-llvmir/filecheck.testprog.txt

This file was deleted.

Loading
Loading