summaryrefslogtreecommitdiffstats
path: root/tests/run-make/coverage-llvmir
diff options
context:
space:
mode:
Diffstat (limited to 'tests/run-make/coverage-llvmir')
-rw-r--r--tests/run-make/coverage-llvmir/Makefile64
-rw-r--r--tests/run-make/coverage-llvmir/filecheck.testprog.txt50
-rw-r--r--tests/run-make/coverage-llvmir/testprog.rs38
3 files changed, 152 insertions, 0 deletions
diff --git a/tests/run-make/coverage-llvmir/Makefile b/tests/run-make/coverage-llvmir/Makefile
new file mode 100644
index 000000000..7be655053
--- /dev/null
+++ b/tests/run-make/coverage-llvmir/Makefile
@@ -0,0 +1,64 @@
+# needs-profiler-support
+
+# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
+# corresponding with LLVM versions 12 and 13, respectively.
+# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
+# version during testing, with an additional directive at the top of this file
+# that sets, for example: `min-llvm-version: 12.0`
+
+include ../coverage/coverage_tools.mk
+
+BASEDIR=../coverage-llvmir
+
+ifeq ($(UNAME),Darwin)
+ INSTR_PROF_DATA_SUFFIX=,regular,live_support
+ DATA_SECTION_PREFIX=__DATA,
+ LLVM_COV_SECTION_PREFIX=__LLVM_COV,
+ COMDAT_IF_SUPPORTED=
+else
+ INSTR_PROF_DATA_SUFFIX=
+ DATA_SECTION_PREFIX=
+ LLVM_COV_SECTION_PREFIX=
+ COMDAT_IF_SUPPORTED=, comdat
+endif
+
+DEFINE_INTERNAL=define internal
+
+ifdef IS_WINDOWS
+ LLVM_FILECHECK_OPTIONS=\
+ -check-prefixes=CHECK,WINDOWS \
+ -DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \
+ -DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \
+ -DINSTR_PROF_DATA='.lprfd$$M' \
+ -DINSTR_PROF_NAME='.lprfn$$M' \
+ -DINSTR_PROF_CNTS='.lprfc$$M' \
+ -DINSTR_PROF_VALS='.lprfv$$M' \
+ -DINSTR_PROF_VNODES='.lprfnd$$M' \
+ -DINSTR_PROF_COVMAP='.lcovmap$$M' \
+ -DINSTR_PROF_COVFUN='.lcovfun$$M' \
+ -DINSTR_PROF_ORDERFILE='.lorderfile$$M'
+else
+ LLVM_FILECHECK_OPTIONS=\
+ -check-prefixes=CHECK \
+ -DDEFINE_INTERNAL='$(DEFINE_INTERNAL)' \
+ -DCOMDAT_IF_SUPPORTED='$(COMDAT_IF_SUPPORTED)' \
+ -DINSTR_PROF_DATA='$(DATA_SECTION_PREFIX)__llvm_prf_data$(INSTR_PROF_DATA_SUFFIX)' \
+ -DINSTR_PROF_NAME='$(DATA_SECTION_PREFIX)__llvm_prf_names' \
+ -DINSTR_PROF_CNTS='$(DATA_SECTION_PREFIX)__llvm_prf_cnts' \
+ -DINSTR_PROF_VALS='$(DATA_SECTION_PREFIX)__llvm_prf_vals' \
+ -DINSTR_PROF_VNODES='$(DATA_SECTION_PREFIX)__llvm_prf_vnds' \
+ -DINSTR_PROF_COVMAP='$(LLVM_COV_SECTION_PREFIX)__llvm_covmap' \
+ -DINSTR_PROF_COVFUN='$(LLVM_COV_SECTION_PREFIX)__llvm_covfun' \
+ -DINSTR_PROF_ORDERFILE='$(DATA_SECTION_PREFIX)__llvm_orderfile'
+endif
+
+all: test_llvm_ir
+
+test_llvm_ir:
+ # Compile the test program with non-experimental coverage instrumentation, and generate LLVM IR
+ $(RUSTC) $(BASEDIR)/testprog.rs \
+ -Cinstrument-coverage \
+ --emit=llvm-ir
+
+ cat "$(TMPDIR)"/testprog.ll | \
+ "$(LLVM_FILECHECK)" $(BASEDIR)/filecheck.testprog.txt $(LLVM_FILECHECK_OPTIONS)
diff --git a/tests/run-make/coverage-llvmir/filecheck.testprog.txt b/tests/run-make/coverage-llvmir/filecheck.testprog.txt
new file mode 100644
index 000000000..c943261d7
--- /dev/null
+++ b/tests/run-make/coverage-llvmir/filecheck.testprog.txt
@@ -0,0 +1,50 @@
+# 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: @__covrec_{{[A-F0-9]+}}u = linkonce_odr hidden constant
+CHECK-SAME: section "[[INSTR_PROF_COVFUN]]"[[COMDAT_IF_SUPPORTED]], align 8
+
+CHECK: @__llvm_coverage_mapping = private constant
+CHECK-SAME: section "[[INSTR_PROF_COVMAP]]", 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: %pgocount = load i64, {{i64\*|ptr}}
+CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
+
+CHECK: declare void @llvm.instrprof.increment({{i8\*|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, {{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 }
diff --git a/tests/run-make/coverage-llvmir/testprog.rs b/tests/run-make/coverage-llvmir/testprog.rs
new file mode 100644
index 000000000..358c25677
--- /dev/null
+++ b/tests/run-make/coverage-llvmir/testprog.rs
@@ -0,0 +1,38 @@
+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, ""));
+ }
+}