Index: compiler-rt/lib/profile/InstrProfilingPlatformLinux.c =================================================================== --- compiler-rt/lib/profile/InstrProfilingPlatformLinux.c +++ compiler-rt/lib/profile/InstrProfilingPlatformLinux.c @@ -54,6 +54,38 @@ extern ValueProfNode PROF_VNODES_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK; extern ValueProfNode PROF_VNODES_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK; +#ifdef _AIX +// Empty stubs to allow linking object files using the registration-based scheme +COMPILER_RT_VISIBILITY +void __llvm_profile_register_function(void *Data_) {} + +COMPILER_RT_VISIBILITY +void __llvm_profile_register_names_function(void *NamesStart, + uint64_t NamesSize) {} + +// The __start_SECNAME and __stop_SECNAME symbols (for SECNAME \in +// {"__llvm_prf_cnts", "__llvm_prf_data", "__llvm_prf_name", "__llvm_prf_vnds"}) +// are always live when linking on AIX, regardless if the .o's being linked +// reference symbols from the profile library (for example when no files were +// compiled with -fprofile-generate). That's because these symbols are kept +// alive through references in constructor functions that are always live in the +// default linking model on AIX (-bcdtors:all). The __start_SECNAME and +// __stop_SECNAME symbols are only resolved by the linker when the SECNAME +// section exists. So for the scenario where the user objects have no such +// section (i.e. when they are compiled with -fno-profile-generate), we always +// define these zero length variables in each of the above 4 sections. +static int dummy_cnts[0] COMPILER_RT_SECTION( + COMPILER_RT_SEG INSTR_PROF_CNTS_SECT_NAME); +static int dummy_data[0] COMPILER_RT_SECTION( + COMPILER_RT_SEG INSTR_PROF_DATA_SECT_NAME); +static const int dummy_name[0] COMPILER_RT_SECTION( + COMPILER_RT_SEG INSTR_PROF_NAME_SECT_NAME); +static int dummy_vnds[0] COMPILER_RT_SECTION( + COMPILER_RT_SEG INSTR_PROF_VNODES_SECT_NAME); +static void *volatile keep[] = {(void *)&dummy_cnts, (void *)&dummy_data, + (void *)&dummy_name, (void *)&dummy_vnds}; +#endif + COMPILER_RT_VISIBILITY const __llvm_profile_data * __llvm_profile_begin_data(void) { return &PROF_DATA_START; @@ -83,6 +115,11 @@ return &PROF_VNODES_START; } COMPILER_RT_VISIBILITY ValueProfNode *__llvm_profile_end_vnodes(void) { +#ifdef _AIX + // Avoid GC'ing of the dummy variables by the linker. Also, this binds the + // liveness of the dummy vars with that of the __start_* and __stop_* symbols. + (void)keep[0]; +#endif return &PROF_VNODES_STOP; } COMPILER_RT_VISIBILITY ValueProfNode *CurrentVNode = &PROF_VNODES_START; @@ -230,43 +267,4 @@ } #endif -#if defined(_AIX) -// Empty stubs to allow linking object files using the registration-based scheme -COMPILER_RT_VISIBILITY -void __llvm_profile_register_function(void *Data_) {} - -COMPILER_RT_VISIBILITY -void __llvm_profile_register_names_function(void *NamesStart, - uint64_t NamesSize) {} - -// The __start_SECNAME and __stop_SECNAME symbols (for SECNAME \in -// {"__llvm_prf_cnts", "__llvm_prf_data", "__llvm_prf_name", "__llvm_prf_vnds"}) -// are always live when linking on AIX, regardless if the .o's being linked -// reference symbols from the profile library (for example when no files were -// compiled with -fprofile-generate). That's because these symbols are kept -// alive through references in constructor functions that are always live in the -// default linking model on AIX (-bcdtors:all). The __start_SECNAME and -// __stop_SECNAME symbols are only resolved by the linker when the SECNAME -// section exists. So for the scenario where the user objects have no such -// section (i.e. when they are compiled with -fno-profile-generate), we always -// define these zero length variables in each of the above 4 sections. -COMPILER_RT_VISIBILITY int dummy_cnts[0] COMPILER_RT_SECTION( - COMPILER_RT_SEG INSTR_PROF_CNTS_SECT_NAME); -COMPILER_RT_VISIBILITY int dummy_data[0] COMPILER_RT_SECTION( - COMPILER_RT_SEG INSTR_PROF_DATA_SECT_NAME); -COMPILER_RT_VISIBILITY const int dummy_name[0] COMPILER_RT_SECTION( - COMPILER_RT_SEG INSTR_PROF_NAME_SECT_NAME); -COMPILER_RT_VISIBILITY int dummy_vnds[0] COMPILER_RT_SECTION( - COMPILER_RT_SEG INSTR_PROF_VNODES_SECT_NAME); - -// Create a fake reference to avoid GC'ing of the dummy variables by the linker. -// Ideally, we create a ".ref" of each variable inside the function -// __llvm_profile_begin_counters(), but there's no source level construct -// that allows us to generate that. -__attribute__((destructor)) void keep() { - int volatile use = &dummy_cnts < &dummy_data && &dummy_name < &dummy_vnds; - (void)use; -} -#endif - #endif Index: compiler-rt/test/profile/AIX/lit.local.cfg.py =================================================================== --- /dev/null +++ compiler-rt/test/profile/AIX/lit.local.cfg.py @@ -0,0 +1,9 @@ +def getRoot(config): + if not config.parent: + return config + return getRoot(config.parent) + +root = getRoot(config) + +if root.host_os not in ['AIX']: + config.unsupported = True Index: compiler-rt/test/profile/AIX/shared-bexpall-pgo.c =================================================================== --- /dev/null +++ compiler-rt/test/profile/AIX/shared-bexpall-pgo.c @@ -0,0 +1,14 @@ +// RUN: split-file %s %t +// RUN: cd %t +// +// RUN: %clang_pgogen foo.c -c -o foo.o +// RUN: %clang_pgogen -shared foo.o -o libfoo.so -bexpall +// RUN: %clang_pgogen -L%t user.c libfoo.so -o user1 +// RUN: ./user1 + +//--- foo.c +void foo() {} + +//--- user.c +void foo(); +int main() { foo(); }