diff --git a/compiler-rt/test/profile/Linux/coverage-linkage-lld.cpp b/compiler-rt/test/profile/Linux/coverage-linkage-lld.cpp new file mode 100644 index 0000000000000..549633867c759 --- /dev/null +++ b/compiler-rt/test/profile/Linux/coverage-linkage-lld.cpp @@ -0,0 +1,8 @@ +// REQUIRES: lld-available +/// With lld --gc-sections we can ensure discarded[01] and their profc/profd +/// variables are discarded. + +// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -fuse-ld=lld -Wl,--gc-sections %S/coverage-linkage.cpp -o %t +// RUN: llvm-nm %t | FileCheck %s + +// CHECK-NOT: discarded{{.*}} diff --git a/compiler-rt/test/profile/Linux/coverage-linkage.cpp b/compiler-rt/test/profile/Linux/coverage-linkage.cpp new file mode 100644 index 0000000000000..df0674ec0329f --- /dev/null +++ b/compiler-rt/test/profile/Linux/coverage-linkage.cpp @@ -0,0 +1,46 @@ +/// Test instrumentation can handle various linkages. +// RUN: %clang_profgen -fcoverage-mapping %s -o %t +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s + +// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -Wl,--gc-sections %s -o %t +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s + +// CHECK: {{.*}}external{{.*}}: +// CHECK-NEXT: Hash: +// CHECK-NEXT: Counters: 1 +// CHECK-NEXT: Function count: 1 +// CHECK: {{.*}}weak{{.*}}: +// CHECK-NEXT: Hash: +// CHECK-NEXT: Counters: 1 +// CHECK-NEXT: Function count: 1 +// CHECK: main: +// CHECK-NEXT: Hash: +// CHECK-NEXT: Counters: 1 +// CHECK-NEXT: Function count: 1 +// CHECK: {{.*}}internal{{.*}}: +// CHECK-NEXT: Hash: +// CHECK-NEXT: Counters: 1 +// CHECK-NEXT: Function count: 1 +// CHECK: {{.*}}linkonce_odr{{.*}}: +// CHECK-NEXT: Hash: +// CHECK-NEXT: Counters: 1 +// CHECK-NEXT: Function count: 1 + +#include + +void discarded0() {} +__attribute__((weak)) void discarded1() {} + +void external() { puts("external"); } +__attribute__((weak)) void weak() { puts("weak"); } +static void internal() { puts("internal"); } +__attribute__((noinline)) inline void linkonce_odr() { puts("linkonce_odr"); } + +int main() { + internal(); + external(); + weak(); + linkonce_odr(); +} diff --git a/compiler-rt/test/profile/Linux/coverage-weak-lld.cpp b/compiler-rt/test/profile/Linux/coverage-weak-lld.cpp new file mode 100644 index 0000000000000..de624dd73b859 --- /dev/null +++ b/compiler-rt/test/profile/Linux/coverage-weak-lld.cpp @@ -0,0 +1,103 @@ +// REQUIRES: lld-available + +// RUN: %clang_profgen -fcoverage-mapping -c %s -o %t0.o +// RUN: %clang_profgen -fcoverage-mapping -c %s -DOBJ_1 -o %t1.o +// RUN: %clang_profgen -fcoverage-mapping -c %s -DOBJ_2 -o %t2.o + +/// An external symbol can override a weak external symbol. +// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld %t0.o %t1.o -o %t1 +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1 +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1_NOGC +// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,--gc-sections %t0.o %t1.o -o %t1 +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1 +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1_NOGC + +// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld %t0.o %t2.o -o %t2 +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t2 | FileCheck %s --check-prefix=CHECK2 +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE2_NOGC +// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,--gc-sections %t0.o %t2.o -o %t2 +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t2 | FileCheck %s --check-prefix=CHECK2 +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE2_GC + +/// Repeat the above tests with -ffunction-sections. +// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -c %s -o %t0.o +// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -c %s -DOBJ_1 -o %t1.o +// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -c %s -DOBJ_2 -o %t2.o + +// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld %t0.o %t1.o -o %t1 +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1 +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1_NOGC +// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,--gc-sections %t0.o %t1.o -o %t1 +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1 +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1_GC + +// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld %t0.o %t2.o -o %t2 +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t2 | FileCheck %s --check-prefix=CHECK2 +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE2_NOGC +// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,--gc-sections %t0.o %t2.o -o %t2 +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t2 | FileCheck %s --check-prefix=CHECK2 +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE2_GC + +// CHECK1: strong +// CHECK1: strong + +/// __profc__Z4weakv in %t1.o is local and has a zero value. +/// Without GC it takes a duplicate entry. +// PROFILE1_NOGC: _Z4weakv: +// PROFILE1_NOGC-NEXT: Hash: +// PROFILE1_NOGC-NEXT: Counters: 1 +// PROFILE1_NOGC-NEXT: Function count: 0 +// PROFILE1_NOGC: _Z4weakv: +// PROFILE1_NOGC-NEXT: Hash: +// PROFILE1_NOGC-NEXT: Counters: 1 +// PROFILE1_NOGC-NEXT: Function count: 2 + +// PROFILE1_GC: _Z4weakv: +// PROFILE1_GC-NEXT: Hash: +// PROFILE1_GC-NEXT: Counters: 1 +// PROFILE1_GC-NEXT: Function count: 2 +// PROFILE1_GC-NOT: _Z4weakv: + +// CHECK2: weak +// CHECK2: weak + +/// __profc__Z4weakv in %t2.o is weak and resolves to the value of %t0.o's copy. +/// Without GC it takes a duplicate entry. +// PROFILE2_NOGC: _Z4weakv: +// PROFILE2_NOGC-NEXT: Hash: +// PROFILE2_NOGC-NEXT: Counters: 1 +// PROFILE2_NOGC-NEXT: Function count: 2 +// PROFILE2_NOGC: _Z4weakv: +// PROFILE2_NOGC-NEXT: Hash: +// PROFILE2_NOGC-NEXT: Counters: 1 +// PROFILE2_NOGC-NEXT: Function count: 2 + +// PROFILE2_GC: _Z4weakv: +// PROFILE2_GC-NEXT: Hash: +// PROFILE2_GC-NEXT: Counters: 1 +// PROFILE2_GC-NEXT: Function count: 2 +// PROFILE2_GC-NOT: _Z4weakv: + +#ifdef OBJ_1 +#include + +void weak() { puts("strong"); } +void foo() { weak(); } + +#elif defined(OBJ_2) +#include + +__attribute__((weak)) void weak() { puts("unreachable"); } +void foo() { weak(); } + +#else +#include + +__attribute__((weak)) void weak() { puts("weak"); } +void foo(); + +int main() { + foo(); + weak(); +} +#endif diff --git a/compiler-rt/test/profile/Windows/coverage-linkage-lld.cpp b/compiler-rt/test/profile/Windows/coverage-linkage-lld.cpp new file mode 100644 index 0000000000000..714e4513bc20f --- /dev/null +++ b/compiler-rt/test/profile/Windows/coverage-linkage-lld.cpp @@ -0,0 +1,11 @@ +// REQUIRES: lld-available +/// With lld -opt:ref we can ensure discarded[01] and their profc/profd +/// variables are discarded. + +// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -fuse-ld=lld -Wl,-debug:symtab,-opt:noref %S/coverage-linkage.cpp -o %t +// RUN: llvm-nm %t | FileCheck %s --check-prefix=NOGC +// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -fuse-ld=lld -Wl,-debug:symtab,-opt:ref %S/coverage-linkage.cpp -o %t +// RUN: llvm-nm %t | FileCheck %s --check-prefix=GC + +// NOGC: T ?discarded{{.*}} +// GC-NOT: T ?discarded{{.*}} diff --git a/compiler-rt/test/profile/Windows/coverage-linkage.cpp b/compiler-rt/test/profile/Windows/coverage-linkage.cpp new file mode 100644 index 0000000000000..648b3fb73a5d4 --- /dev/null +++ b/compiler-rt/test/profile/Windows/coverage-linkage.cpp @@ -0,0 +1,46 @@ +/// Test instrumentation can handle various linkages. +// RUN: %clang_profgen -fcoverage-mapping %s -o %t +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s + +// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -Wl,-opt:ref %s -o %t +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s + +// CHECK: {{.*}}external{{.*}}: +// CHECK-NEXT: Hash: +// CHECK-NEXT: Counters: 1 +// CHECK-NEXT: Function count: 1 +// CHECK: {{.*}}weak{{.*}}: +// CHECK-NEXT: Hash: +// CHECK-NEXT: Counters: 1 +// CHECK-NEXT: Function count: 1 +// CHECK: main: +// CHECK-NEXT: Hash: +// CHECK-NEXT: Counters: 1 +// CHECK-NEXT: Function count: 1 +// CHECK: {{.*}}internal{{.*}}: +// CHECK-NEXT: Hash: +// CHECK-NEXT: Counters: 1 +// CHECK-NEXT: Function count: 1 +// CHECK: {{.*}}linkonce_odr{{.*}}: +// CHECK-NEXT: Hash: +// CHECK-NEXT: Counters: 1 +// CHECK-NEXT: Function count: 1 + +#include + +void discarded0() {} +__attribute__((weak)) void discarded1() {} + +void external() { puts("external"); } +__attribute__((weak)) void weak() { puts("weak"); } +static void internal() { puts("internal"); } +__attribute__((noinline)) inline void linkonce_odr() { puts("linkonce_odr"); } + +int main() { + internal(); + external(); + weak(); + linkonce_odr(); +} diff --git a/compiler-rt/test/profile/Windows/coverage-weak-lld.cpp b/compiler-rt/test/profile/Windows/coverage-weak-lld.cpp new file mode 100644 index 0000000000000..b1708433cec22 --- /dev/null +++ b/compiler-rt/test/profile/Windows/coverage-weak-lld.cpp @@ -0,0 +1,85 @@ +// REQUIRES: lld-available + +// RUN: %clang_profgen -fcoverage-mapping -c %s -o %t0.o +// RUN: %clang_profgen -fcoverage-mapping -c %s -DOBJ_1 -o %t1.o +// RUN: %clang_profgen -fcoverage-mapping -c %s -DOBJ_2 -o %t2.o + +/// An external symbol can override a weak external symbol. +// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,-opt:noref %t0.o %t1.o -o %t1 +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1 +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1 +// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,-opt:ref %t0.o %t1.o -o %t1 +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1 +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1 + +/// link.exe does not support weak overridding weak. +// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,-lldmingw,-opt:ref %t0.o %t2.o -o %t2 +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t2 | FileCheck %s --check-prefix=CHECK2 +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE2 + +/// Repeat the above tests with -ffunction-sections (associative comdat). +// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -c %s -o %t0.o +// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -c %s -DOBJ_1 -o %t1.o +// RUN: %clang_profgen -fcoverage-mapping -ffunction-sections -c %s -DOBJ_2 -o %t2.o + +// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,-opt:noref %t0.o %t1.o -o %t1 +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1 +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1 +// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,-opt:ref %t0.o %t1.o -o %t1 +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t1 | FileCheck %s --check-prefix=CHECK1 +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE1 + +// RUN: %clang_profgen -fcoverage-mapping -fuse-ld=lld -Wl,-lldmingw,-opt:ref %t0.o %t2.o -o %t2 +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t2 | FileCheck %s --check-prefix=CHECK2 +// RUN: llvm-profdata show %t.profraw --all-functions | FileCheck %s --check-prefix=PROFILE2 + +// CHECK1: strong +// CHECK1: strong + +/// Document the current behavior: +/// __profc_?weak@@YAXXZ in %t1.o is local and has a zero value. +/// Without GC it takes a duplicate entry. +// PROFILE1: ?weak@@YAXXZ: +// PROFILE1-NEXT: Hash: +// PROFILE1-NEXT: Counters: 1 +// PROFILE1-NEXT: Function count: 0 +// PROFILE1: ?weak@@YAXXZ: +// PROFILE1-NEXT: Hash: +// PROFILE1-NEXT: Counters: 1 +// PROFILE1-NEXT: Function count: 2 + +// CHECK2: weak +// CHECK2: weak + +// PROFILE2: ?weak@@YAXXZ: +// PROFILE2-NEXT: Hash: +// PROFILE2-NEXT: Counters: 1 +// PROFILE2-NEXT: Function count: 2 +// PROFILE2: ?weak@@YAXXZ: +// PROFILE2-NEXT: Hash: +// PROFILE2-NEXT: Counters: 1 +// PROFILE2-NEXT: Function count: 0 + +#ifdef OBJ_1 +#include + +void weak() { puts("strong"); } +void foo() { weak(); } + +#elif defined(OBJ_2) +#include + +__attribute__((weak)) void weak() { puts("unreachable"); } +void foo() { weak(); } + +#else +#include + +__attribute__((weak)) void weak() { puts("weak"); } +void foo(); + +int main() { + foo(); + weak(); +} +#endif