Index: compiler-rt/trunk/lib/profile/CMakeLists.txt =================================================================== --- compiler-rt/trunk/lib/profile/CMakeLists.txt +++ compiler-rt/trunk/lib/profile/CMakeLists.txt @@ -11,6 +11,15 @@ InstrProfilingRuntime.cc InstrProfilingUtil.c) +if(UNIX) + set(EXTRA_FLAGS + -fPIC + -Wno-pedantic) +else() + set(EXTRA_FLAGS + -fPIC) +endif() + if(APPLE) add_compiler_rt_runtime(clang_rt.profile STATIC @@ -22,7 +31,7 @@ add_compiler_rt_runtime(clang_rt.profile STATIC ARCHS ${PROFILE_SUPPORTED_ARCH} - CFLAGS -fPIC + CFLAGS ${EXTRA_FLAGS} SOURCES ${PROFILE_SOURCES} PARENT_TARGET profile) endif() Index: compiler-rt/trunk/lib/profile/InstrProfilingBuffer.c =================================================================== --- compiler-rt/trunk/lib/profile/InstrProfilingBuffer.c +++ compiler-rt/trunk/lib/profile/InstrProfilingBuffer.c @@ -79,6 +79,10 @@ /* Create the header. */ __llvm_profile_header Header; + + if (!DataSize) + return 0; + Header.Magic = __llvm_profile_get_magic(); Header.Version = __llvm_profile_get_version(); Header.DataSize = DataSize; Index: compiler-rt/trunk/lib/profile/InstrProfilingFile.c =================================================================== --- compiler-rt/trunk/lib/profile/InstrProfilingFile.c +++ compiler-rt/trunk/lib/profile/InstrProfilingFile.c @@ -36,6 +36,10 @@ /* Create the header. */ __llvm_profile_header Header; + + if (!DataSize) + return 0; + Header.Magic = __llvm_profile_get_magic(); Header.Version = __llvm_profile_get_version(); Header.DataSize = DataSize; Index: compiler-rt/trunk/lib/profile/InstrProfilingPlatformLinux.c =================================================================== --- compiler-rt/trunk/lib/profile/InstrProfilingPlatformLinux.c +++ compiler-rt/trunk/lib/profile/InstrProfilingPlatformLinux.c @@ -21,6 +21,13 @@ extern char __start___llvm_prf_names __attribute__((visibility("hidden"))); extern char __stop___llvm_prf_names __attribute__((visibility("hidden"))); +/* Add dummy data to ensure the section is always created. */ +__llvm_profile_data __llvm_prof_sect_data[0] + __attribute__((section("__llvm_prf_data"))); +uint64_t __llvm_prof_cnts_sect_data[0] + __attribute__((section("__llvm_prf_cnts"))); +char __llvm_prof_nms_sect_data[0] __attribute__((section("__llvm_prf_names"))); + __attribute__((visibility("hidden"))) const __llvm_profile_data * __llvm_profile_begin_data(void) { return &__start___llvm_prf_data; Index: compiler-rt/trunk/test/profile/Inputs/instrprof-shared-lib.c =================================================================== --- compiler-rt/trunk/test/profile/Inputs/instrprof-shared-lib.c +++ compiler-rt/trunk/test/profile/Inputs/instrprof-shared-lib.c @@ -0,0 +1,9 @@ +int g1 = 0; +int g2 = 1; + +void foo(int n) { + if (n % 5 == 0) + g1++; + else + g2++; +} Index: compiler-rt/trunk/test/profile/Inputs/instrprof-shared-main.c =================================================================== --- compiler-rt/trunk/test/profile/Inputs/instrprof-shared-main.c +++ compiler-rt/trunk/test/profile/Inputs/instrprof-shared-main.c @@ -0,0 +1,13 @@ +extern int g1, g2; +extern void foo(int n); + +int main() { + int i, j; + for (i = 0; i < 1000; i++) + for (j = 0; j < 1000; j++) + foo(i * j); + + if (g2 - g1 == 280001) + return 0; + return 1; +} Index: compiler-rt/trunk/test/profile/instrprof-shared.test =================================================================== --- compiler-rt/trunk/test/profile/instrprof-shared.test +++ compiler-rt/trunk/test/profile/instrprof-shared.test @@ -0,0 +1,75 @@ +""" +This test produces three shared libraries: + +1. libt-instr.so is instrumented +2. libt-no-instr1.so is not instrumented +3. libt-no-instr2.so is compiled with instrumentation enabled, but the object file is built + with instrumentation turned off. + +After the libraries are built, the main program is then built with/without instrumentation and linked +against 3 libraries above. + +The test is to verify that programs linked against these shared objects with and without instrumentation +enabled behave as expected. +""" + +RUN: mkdir -p %t.d +RUN: %clang_profgen -o %t.d/libt-instr.so -fPIC -shared %S/Inputs/instrprof-shared-lib.c +RUN: %clang -o %t.d/libt-no-instr1.so -fPIC -shared %S/Inputs/instrprof-shared-lib.c +RUN: %clang -c -o %t.d/instrprof-shared-lib-no-instr2.o -fPIC %S/Inputs/instrprof-shared-lib.c +RUN: %clang_profgen -o %t.d/libt-no-instr2.so -fPIC -shared %t.d/instrprof-shared-lib-no-instr2.o + +RUN: %clang_profgen -o %t-instr-instr -L%t.d -rpath %t.d -lt-instr %S/Inputs/instrprof-shared-main.c +RUN: %clang_profgen -o %t-instr-no-instr1 -L%t.d -rpath %t.d -lt-no-instr1 %S/Inputs/instrprof-shared-main.c +RUN: %clang_profgen -o %t-instr-no-instr2 -L%t.d -rpath %t.d -lt-no-instr2 %S/Inputs/instrprof-shared-main.c +RUN: %clang -o %t-no-instr1-instr -L%t.d -rpath %t.d -lt-instr %S/Inputs/instrprof-shared-main.c +RUN: %clang -o %t-no-instr1-no-instr1 -L%t.d -rpath %t.d -lt-no-instr1 %S/Inputs/instrprof-shared-main.c +RUN: %clang -o %t-no-instr1-no-instr2 -L%t.d -rpath %t.d -lt-no-instr2 %S/Inputs/instrprof-shared-main.c +RUN: %clang -c -o %t.d/instrprof-shared-main-no-instr2.o %S/Inputs/instrprof-shared-main.c +RUN: %clang -o %t-no-instr2-instr -L%t.d -rpath %t.d -lt-instr %t.d/instrprof-shared-main-no-instr2.o +RUN: %clang -o %t-no-instr2-no-instr1 -L%t.d -rpath %t.d -lt-no-instr1 %t.d/instrprof-shared-main-no-instr2.o +RUN: %clang -o %t-no-instr2-no-instr2 -L%t.d -rpath %t.d -lt-no-instr2 %t.d/instrprof-shared-main-no-instr2.o + +RUN: env LLVM_PROFILE_FILE=%t-instr-instr.profraw %run %t-instr-instr +RUN: env LLVM_PROFILE_FILE=%t-instr-no-instr1.profraw %run %t-instr-no-instr1 +RUN: env LLVM_PROFILE_FILE=%t-instr-no-instr2.profraw %run %t-instr-no-instr2 +RUN: env LLVM_PROFILE_FILE=%t-no-instr1-instr.profraw %run %t-no-instr1-instr +RUN: env LLVM_PROFILE_FILE=%t-no-instr2-instr.profraw %run %t-no-instr2-instr +RUN: env LLVM_PROFILE_FILE=%t-no-instr1-no-instr1.profraw %run %t-no-instr1-no-instr1 +RUN: env LLVM_PROFILE_FILE=%t-no-instr1-no-instr2.profraw %run %t-no-instr1-no-instr2 +RUN: env LLVM_PROFILE_FILE=%t-no-instr2-no-instr1.profraw %run %t-no-instr2-no-instr1 +RUN: env LLVM_PROFILE_FILE=%t-no-instr2-no-instr2.profraw %run %t-no-instr2-no-instr2 + +RUN: llvm-profdata merge -o %t-instr-instr.profdata %t-instr-instr.profraw +RUN: llvm-profdata merge -o %t-instr-no-instr1.profdata %t-instr-no-instr1.profraw +RUN: llvm-profdata merge -o %t-instr-no-instr2.profdata %t-instr-no-instr2.profraw +RUN: llvm-profdata merge -o %t-no-instr1-instr.profdata %t-no-instr1-instr.profraw +RUN: llvm-profdata merge -o %t-no-instr2-instr.profdata %t-no-instr2-instr.profraw + +RUN: not llvm-profdata merge -o %t-no-instr1-no-instr1.profdata %t-no-instr1-no-instr1.profraw 2>&1 | FileCheck %s --check-prefix=MISSING-FILE +RUN: not llvm-profdata merge -o %t-no-instr2-no-instr1.profdata %t-no-instr2-no-instr1.profraw 2>&1 | FileCheck %s --check-prefix=MISSING-FILE +MISSING-FILE: profraw + +RUN: llvm-profdata show -counts --function main %t-instr-instr.profdata | grep -v 'Total\|Maximum' > %t-main-1 +RUN: llvm-profdata show -counts --function main %t-instr-no-instr1.profdata | grep -v 'Total\|Maximum' > %t-main-2 +RUN: llvm-profdata show -counts --function main %t-instr-no-instr2.profdata | grep -v 'Total\|Maximum' > %t-main-3 +RUN: llvm-profdata show -counts --function foo %t-instr-instr.profdata | grep -v 'Total\|Maximum' > %t-foo-1 +RUN: llvm-profdata show -counts --function foo %t-no-instr1-instr.profdata | grep -v 'Total\|Maximum' > %t-foo-2 +RUN: llvm-profdata show -counts --function foo %t-no-instr2-instr.profdata | grep -v 'Total\|Maximum' > %t-foo-3 + +RUN: %clang_profuse=%t-instr-instr.profdata -o %t-main-instr-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-main.c +RUN: %clang_profuse=%t-instr-no-instr1.profdata -o %t-main-instr-no-instr1.ll -S -emit-llvm %S/Inputs/instrprof-shared-main.c +RUN: %clang_profuse=%t-instr-no-instr2.profdata -o %t-main-instr-no-instr2.ll -S -emit-llvm %S/Inputs/instrprof-shared-main.c +RUN: %clang_profuse=%t-instr-instr.profdata -o %t-lib-instr-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-lib.c +RUN: %clang_profuse=%t-no-instr1-instr.profdata -o %t-lib-no-instr1-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-lib.c +RUN: %clang_profuse=%t-no-instr2-instr.profdata -o %t-lib-no-instr2-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-lib.c +RUN: %clang_profuse=%t-instr-instr.profdata -o %t-lib-instr-instr.ll -S -emit-llvm %S/Inputs/instrprof-shared-lib.c + +RUN: diff %t-main-instr-no-instr1.ll %t-main-instr-no-instr2.ll +RUN: diff %t-lib-no-instr1-instr.ll %t-lib-no-instr2-instr.ll + +RUN: diff %t-main-1 %t-main-2 +RUN: diff %t-main-1 %t-main-3 +RUN: diff %t-foo-1 %t-foo-2 +RUN: diff %t-foo-1 %t-foo-3 +