https://github.com/qiongsiwu updated https://github.com/llvm/llvm-project/pull/108570
>From e1b5e886f3f7642ec691a08378a1f2cdc9e2465f Mon Sep 17 00:00:00 2001 From: Qiongsi Wu <q...@ibm.com> Date: Wed, 11 Sep 2024 14:56:58 -0400 Subject: [PATCH 1/6] Initial commit. --- clang/test/CodeGen/attr-function-return.c | 5 +- clang/test/CodeGen/code-coverage.c | 5 +- clang/test/CodeGen/coverage-target-attr.c | 5 +- compiler-rt/include/profile/InstrProfData.inc | 22 ++++++++ compiler-rt/lib/profile/GCDAProfiling.c | 17 ++++++ compiler-rt/lib/profile/InstrProfiling.h | 11 ++++ .../lib/profile/InstrProfilingPlatformAIX.c | 5 +- .../lib/profile/InstrProfilingPlatformLinux.c | 16 ++++++ .../test/profile/AIX/gcov-undef-sym.test | 52 +++++++++++++++++++ .../llvm/ProfileData/InstrProfData.inc | 22 ++++++++ llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 23 ++++++++ .../Instrumentation/GCOVProfiling.cpp | 48 ++++++++++------- .../GCOVProfiling/kcfi-normalize.ll | 7 +-- llvm/test/Transforms/GCOVProfiling/kcfi.ll | 7 +-- .../Transforms/GCOVProfiling/module-flags.ll | 4 +- 15 files changed, 218 insertions(+), 31 deletions(-) create mode 100644 compiler-rt/test/profile/AIX/gcov-undef-sym.test diff --git a/clang/test/CodeGen/attr-function-return.c b/clang/test/CodeGen/attr-function-return.c index df2cabf28693a3..9c5cbca5640843 100644 --- a/clang/test/CodeGen/attr-function-return.c +++ b/clang/test/CodeGen/attr-function-return.c @@ -17,6 +17,9 @@ // RUN: -mfunction-return=thunk-extern -fsanitize=thread \ // RUN: | FileCheck %s --check-prefix=CHECK-TSAN +// Check for gcov initialization function pointers. +// CHECK-GCOV: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" + #if !__has_attribute(function_return) #error "missing attribute support for function_return" #endif @@ -104,7 +107,7 @@ void no_attrs(void) {} // Test synthetic functions. // CHECK-GCOV: @__llvm_gcov_writeout() unnamed_addr [[EXTERNGCOV:#[0-9]+]] // CHECK-GCOV: @__llvm_gcov_reset() unnamed_addr [[EXTERNGCOV]] -// CHECK-GCOV: @__llvm_gcov_init() unnamed_addr [[EXTERNGCOV]] +// CHECK-GCOV-NOT: @__llvm_gcov_init() unnamed_addr [[EXTERNGCOV]] // CHECK-ASAN: @asan.module_ctor() [[EXTERNASAN:#[0-9]+]] // CHECK-TSAN: @tsan.module_ctor() [[EXTERNTSAN:#[0-9]+]] diff --git a/clang/test/CodeGen/code-coverage.c b/clang/test/CodeGen/code-coverage.c index d7994bab35d81a..4e3f0aba8c4098 100644 --- a/clang/test/CodeGen/code-coverage.c +++ b/clang/test/CodeGen/code-coverage.c @@ -49,10 +49,13 @@ int test2(int b) { /// 0x3430382a '4' '0' '8' '*' // 408-SAME: i32 875575338 +// Check for gcov initialization function pointers. +// CHECK: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" + // Check that the noredzone flag is set on the generated functions. // CHECK: void @__llvm_gcov_writeout() unnamed_addr [[NRZ:#[0-9]+]] -// CHECK: void @__llvm_gcov_init() unnamed_addr [[NRZ]] +// CHECK-NOT: void @__llvm_gcov_init() unnamed_addr [[NRZ]] // CHECK: attributes [[NRZ]] = { {{.*}}noredzone{{.*}} } diff --git a/clang/test/CodeGen/coverage-target-attr.c b/clang/test/CodeGen/coverage-target-attr.c index d46299f5bee223..156e48ba6a31a2 100644 --- a/clang/test/CodeGen/coverage-target-attr.c +++ b/clang/test/CodeGen/coverage-target-attr.c @@ -1,9 +1,12 @@ // RUN: %clang_cc1 -emit-llvm -coverage-notes-file=/dev/null -coverage-data-file=/dev/null -triple aarch64-linux-android30 -target-cpu generic -target-feature +tagged-globals -fsanitize=hwaddress %s -o %t // RUN: FileCheck %s < %t +// Check for gcov initialization function pointers. +// CHECK: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" + // CHECK: define internal void @__llvm_gcov_writeout() unnamed_addr [[ATTR:#[0-9]+]] // CHECK: define internal void @__llvm_gcov_reset() unnamed_addr [[ATTR]] -// CHECK: define internal void @__llvm_gcov_init() unnamed_addr [[ATTR]] +// CHECK-NOT: define internal void @__llvm_gcov_init() unnamed_addr [[ATTR]] // CHECK: define internal void @hwasan.module_ctor() [[ATTR2:#[0-9]+]] // CHECK: attributes [[ATTR]] = {{.*}} "target-cpu"="generic" "target-features"="+tagged-globals" // CHECK: attributes [[ATTR2]] = {{.*}} "target-cpu"="generic" "target-features"="+tagged-globals" diff --git a/compiler-rt/include/profile/InstrProfData.inc b/compiler-rt/include/profile/InstrProfData.inc index b9df3266fbcf8f..591fc1401e1aab 100644 --- a/compiler-rt/include/profile/InstrProfData.inc +++ b/compiler-rt/include/profile/InstrProfData.inc @@ -303,6 +303,18 @@ COVMAP_HEADER(uint32_t, Int32Ty, Version, \ #undef COVMAP_HEADER /* COVMAP_HEADER end. */ +/* COVINIT_FUNC start */ +#ifndef COVINIT_FUNC +#define COVINIT_FUNC(Type, LLVMType, Name, Initializer) +#else +#define INSTR_PROF_DATA_DEFINED +#endif +COVINIT_FUNC(IntPtrT, llvm::PointerType::getUnqual(Ctx), WriteoutFunction, \ + WriteoutF) +COVINIT_FUNC(IntPtrT, llvm::PointerType::getUnqual(Ctx), ResetFunction, \ + ResetF) +#undef COVINIT_FUNC +/* COVINIT_FUNC end */ #ifdef INSTR_PROF_SECT_ENTRY #define INSTR_PROF_DATA_DEFINED @@ -345,6 +357,9 @@ INSTR_PROF_SECT_ENTRY(IPSK_covdata, \ INSTR_PROF_SECT_ENTRY(IPSK_covname, \ INSTR_PROF_QUOTE(INSTR_PROF_COVNAME_COMMON), \ INSTR_PROF_COVNAME_COFF, "__LLVM_COV,") +INSTR_PROF_SECT_ENTRY(IPSK_covinit, \ + INSTR_PROF_QUOTE(INSTR_PROF_COVINIT_COMMON), \ + INSTR_PROF_COVINIT_COFF, "__LLVM_COV,") #undef INSTR_PROF_SECT_ENTRY #endif @@ -761,6 +776,8 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, #define INSTR_PROF_COVDATA_COMMON __llvm_covdata #define INSTR_PROF_COVNAME_COMMON __llvm_covnames #define INSTR_PROF_ORDERFILE_COMMON __llvm_orderfile +#define INSTR_PROF_COVINIT_COMMON __llvm_covinit + /* Windows section names. Because these section names contain dollar characters, * they must be quoted. */ @@ -781,6 +798,9 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, #define INSTR_PROF_COVNAME_COFF ".lcovn" #define INSTR_PROF_ORDERFILE_COFF ".lorderfile$M" +// TODO: Placeholder for Windows. We need to revise when we upstream this. +#define INSTR_PROF_COVINIT_COFF ".lcovd$M" + #ifdef _WIN32 /* Runtime section names and name strings. */ #define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COFF @@ -800,6 +820,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, #define INSTR_PROF_COVDATA_SECT_NAME INSTR_PROF_COVDATA_COFF #define INSTR_PROF_COVNAME_SECT_NAME INSTR_PROF_COVNAME_COFF #define INSTR_PROF_ORDERFILE_SECT_NAME INSTR_PROF_ORDERFILE_COFF +#define INSTR_PROF_COVINIT_SECT_NAME INSTR_PROF_COVINIT_COFF #else /* Runtime section names and name strings. */ #define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON) @@ -821,6 +842,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, /* Order file instrumentation. */ #define INSTR_PROF_ORDERFILE_SECT_NAME \ INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON) +#define INSTR_PROF_COVINIT_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVINIT_COMMON) #endif #define INSTR_PROF_ORDERFILE_BUFFER_NAME _llvm_order_file_buffer diff --git a/compiler-rt/lib/profile/GCDAProfiling.c b/compiler-rt/lib/profile/GCDAProfiling.c index d6e2175169e4a5..f430dd4e36ce37 100644 --- a/compiler-rt/lib/profile/GCDAProfiling.c +++ b/compiler-rt/lib/profile/GCDAProfiling.c @@ -624,6 +624,23 @@ void llvm_gcov_init(fn_ptr wfn, fn_ptr rfn) { } } +COMPILER_RT_VISIBILITY __attribute__((constructor)) void +__llvm_profile_gcov_initialize() { + const __llvm_gcov_init_func_struct *InitFuncStart = + __llvm_profile_begin_covinit(); + const __llvm_gcov_init_func_struct *InitFuncEnd = + __llvm_profile_end_covinit(); + + for (const __llvm_gcov_init_func_struct *Ptr = InitFuncStart; + Ptr != InitFuncEnd; ++Ptr) { + fn_ptr wfn = (fn_ptr)Ptr->WriteoutFunction; + fn_ptr rfn = (fn_ptr)Ptr->ResetFunction; + if (!(wfn && rfn)) + continue; + llvm_gcov_init(wfn, rfn); + } +} + void __gcov_dump(void) { for (struct fn_node *f = writeout_fn_list.head; f; f = f->next) f->fn(); diff --git a/compiler-rt/lib/profile/InstrProfiling.h b/compiler-rt/lib/profile/InstrProfiling.h index 6906d52eacaf1b..a62eca738327a9 100644 --- a/compiler-rt/lib/profile/InstrProfiling.h +++ b/compiler-rt/lib/profile/InstrProfiling.h @@ -54,6 +54,12 @@ typedef struct COMPILER_RT_ALIGNAS(INSTR_PROF_DATA_ALIGNMENT) VTableProfData { #include "profile/InstrProfData.inc" } VTableProfData; +typedef struct COMPILER_RT_ALIGNAS(INSTR_PROF_DATA_ALIGNMENT) + __llvm_gcov_init_func_struct { +#define COVINIT_FUNC(Type, LLVMType, Name, Initializer) Type Name; +#include "profile/InstrProfData.inc" +} __llvm_gcov_init_func_struct; + /*! * \brief Return 1 if profile counters are continuously synced to the raw * profile via an mmap(). This is in contrast to the default mode, in which @@ -208,6 +214,9 @@ void __llvm_profile_initialize_file(void); /*! \brief Initialize the profile runtime. */ void __llvm_profile_initialize(void); +/*! \brief Initialize the gcov profile runtime. */ +void __llvm_profile_gcov_initialize(void); + /*! * \brief Return path prefix (excluding the base filename) of the profile data. * This is useful for users using \c -fprofile-generate=./path_prefix who do @@ -324,4 +333,6 @@ COMPILER_RT_VISIBILITY extern uint64_t */ extern char INSTR_PROF_PROFILE_NAME_VAR[1]; /* __llvm_profile_filename. */ +const __llvm_gcov_init_func_struct *__llvm_profile_begin_covinit(); +const __llvm_gcov_init_func_struct *__llvm_profile_end_covinit(); #endif /* PROFILE_INSTRPROFILING_H_ */ diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformAIX.c b/compiler-rt/lib/profile/InstrProfilingPlatformAIX.c index b9d51b698b414f..651f8785d0b940 100644 --- a/compiler-rt/lib/profile/InstrProfilingPlatformAIX.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformAIX.c @@ -202,6 +202,8 @@ static int dummy_vname[0] COMPILER_RT_SECTION( COMPILER_RT_SEG INSTR_PROF_VNAME_SECT_NAME); static int dummy_vtab[0] COMPILER_RT_SECTION( COMPILER_RT_SEG INSTR_PROF_VTAB_SECT_NAME); +static int dummy_covinit_funcs[0] COMPILER_RT_SECTION( + COMPILER_RT_SEG INSTR_PROF_COVINIT_SECT_NAME); // To avoid GC'ing of the dummy variables by the linker, reference them in an // array and reference the array in the runtime registration code @@ -214,7 +216,8 @@ COMPILER_RT_VISIBILITY void *__llvm_profile_keep[] = {(void *)&dummy_cnts, (void *)&dummy_bits, (void *)&dummy_data, (void *)&dummy_name, (void *)&dummy_vnds, (void *)&dummy_orderfile, - (void *)&dummy_vname, (void *)&dummy_vtab}; + (void *)&dummy_vname, (void *)&dummy_vtab, + (void *)&dummy_covinit_funcs}; #ifdef __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c index b766436497b741..4c22bf42eac569 100644 --- a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c @@ -35,6 +35,8 @@ #define PROF_ORDERFILE_START INSTR_PROF_SECT_START(INSTR_PROF_ORDERFILE_COMMON) #define PROF_VNODES_START INSTR_PROF_SECT_START(INSTR_PROF_VNODES_COMMON) #define PROF_VNODES_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_VNODES_COMMON) +#define PROF_COVINIT_START INSTR_PROF_SECT_START(INSTR_PROF_COVINIT_COMMON) +#define PROF_COVINIT_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_COVINIT_COMMON) /* Declare section start and stop symbols for various sections * generated by compiler instrumentation. @@ -56,6 +58,10 @@ extern char PROF_NAME_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK; extern char PROF_NAME_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK; extern ValueProfNode PROF_VNODES_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK; extern ValueProfNode PROF_VNODES_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK; +extern __llvm_gcov_init_func_struct PROF_COVINIT_START COMPILER_RT_VISIBILITY + COMPILER_RT_WEAK; +extern __llvm_gcov_init_func_struct PROF_COVINIT_STOP COMPILER_RT_VISIBILITY + COMPILER_RT_WEAK; COMPILER_RT_VISIBILITY const __llvm_profile_data * __llvm_profile_begin_data(void) { @@ -110,6 +116,16 @@ COMPILER_RT_VISIBILITY ValueProfNode *__llvm_profile_end_vnodes(void) { COMPILER_RT_VISIBILITY ValueProfNode *CurrentVNode = &PROF_VNODES_START; COMPILER_RT_VISIBILITY ValueProfNode *EndVNode = &PROF_VNODES_STOP; +COMPILER_RT_VISIBILITY const __llvm_gcov_init_func_struct * +__llvm_profile_begin_covinit() { + return &PROF_COVINIT_START; +} + +COMPILER_RT_VISIBILITY const __llvm_gcov_init_func_struct * +__llvm_profile_end_covinit() { + return &PROF_COVINIT_STOP; +} + #ifdef NT_GNU_BUILD_ID static size_t RoundUp(size_t size, size_t align) { return (size + align - 1) & ~(align - 1); diff --git a/compiler-rt/test/profile/AIX/gcov-undef-sym.test b/compiler-rt/test/profile/AIX/gcov-undef-sym.test new file mode 100644 index 00000000000000..e377b321ca66cd --- /dev/null +++ b/compiler-rt/test/profile/AIX/gcov-undef-sym.test @@ -0,0 +1,52 @@ +// The undefined symbol should not cause link errors, and we should +// obtain the expected coverage report. + +// Test the --coverage option. +RUN: rm -rf %t0 && split-file %s %t0 && cd %t0 +RUN: %clang bar.c main.c undef.c --coverage -c +RUN: ar -X32_64 -rv libfoo.a undef.o bar.o +RUN: %clang main.o -L. -lfoo --coverage -o main.exe +RUN: main.exe +RUN: llvm-cov gcov -t main.gcda | FileCheck --check-prefix=MAIN %s +RUN: llvm-cov gcov -t bar.gcda | FileCheck --check-prefix=BAR %s + +// Test the pgogen -fprofile-arcs -ftest-coverage option combination. +RUN: rm -rf %t1 && split-file %s %t1 && cd %t1 +RUN: %clang_pgogen bar.c main.c undef.c -fprofile-arcs -ftest-coverage -c +RUN: ar -X32_64 -rv libfoo.a undef.o bar.o +RUN: %clang_pgogen main.o -L. -lfoo -fprofile-generate -fprofile-arcs -ftest-coverage -o main.exe +RUN: main.exe +RUN: llvm-cov gcov -t main.gcda | FileCheck --check-prefix=MAIN %s +RUN: llvm-cov gcov -t bar.gcda | FileCheck --check-prefix=BAR %s + +// Test the pgogen -Wl,-bcdtors:mbr option combination. +RUN: rm -rf %t2 && split-file %s %t2 && cd %t2 +RUN: %clang_pgogen bar.c main.c undef.c -fprofile-arcs -ftest-coverage -c +RUN: ar -X32_64 -rv libfoo.a undef.o bar.o +RUN: %clang_pgogen main.o -L. -lfoo -fprofile-generate -fprofile-arcs -ftest-coverage -Wl,-bcdtors:mbr -o main.exe +RUN: main.exe +RUN: llvm-cov gcov -t main.gcda | FileCheck --check-prefix=MAIN %s +RUN: llvm-cov gcov -t bar.gcda | FileCheck --check-prefix=BAR %s + +MAIN: 1: 2:int main() { +MAIN: 1: 3: return bar(); +BAR: 1: 1:int bar() { +BAR: 1: 2: return 0; + +//--- main.c +int bar(); +int main() { + return bar(); +} + + +//--- bar.c +int bar() { + return 0; +} + +//--- undef.c +void undef_func(); +void foo() { + undef_func(); +} diff --git a/llvm/include/llvm/ProfileData/InstrProfData.inc b/llvm/include/llvm/ProfileData/InstrProfData.inc index b9df3266fbcf8f..591fc1401e1aab 100644 --- a/llvm/include/llvm/ProfileData/InstrProfData.inc +++ b/llvm/include/llvm/ProfileData/InstrProfData.inc @@ -303,6 +303,18 @@ COVMAP_HEADER(uint32_t, Int32Ty, Version, \ #undef COVMAP_HEADER /* COVMAP_HEADER end. */ +/* COVINIT_FUNC start */ +#ifndef COVINIT_FUNC +#define COVINIT_FUNC(Type, LLVMType, Name, Initializer) +#else +#define INSTR_PROF_DATA_DEFINED +#endif +COVINIT_FUNC(IntPtrT, llvm::PointerType::getUnqual(Ctx), WriteoutFunction, \ + WriteoutF) +COVINIT_FUNC(IntPtrT, llvm::PointerType::getUnqual(Ctx), ResetFunction, \ + ResetF) +#undef COVINIT_FUNC +/* COVINIT_FUNC end */ #ifdef INSTR_PROF_SECT_ENTRY #define INSTR_PROF_DATA_DEFINED @@ -345,6 +357,9 @@ INSTR_PROF_SECT_ENTRY(IPSK_covdata, \ INSTR_PROF_SECT_ENTRY(IPSK_covname, \ INSTR_PROF_QUOTE(INSTR_PROF_COVNAME_COMMON), \ INSTR_PROF_COVNAME_COFF, "__LLVM_COV,") +INSTR_PROF_SECT_ENTRY(IPSK_covinit, \ + INSTR_PROF_QUOTE(INSTR_PROF_COVINIT_COMMON), \ + INSTR_PROF_COVINIT_COFF, "__LLVM_COV,") #undef INSTR_PROF_SECT_ENTRY #endif @@ -761,6 +776,8 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, #define INSTR_PROF_COVDATA_COMMON __llvm_covdata #define INSTR_PROF_COVNAME_COMMON __llvm_covnames #define INSTR_PROF_ORDERFILE_COMMON __llvm_orderfile +#define INSTR_PROF_COVINIT_COMMON __llvm_covinit + /* Windows section names. Because these section names contain dollar characters, * they must be quoted. */ @@ -781,6 +798,9 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, #define INSTR_PROF_COVNAME_COFF ".lcovn" #define INSTR_PROF_ORDERFILE_COFF ".lorderfile$M" +// TODO: Placeholder for Windows. We need to revise when we upstream this. +#define INSTR_PROF_COVINIT_COFF ".lcovd$M" + #ifdef _WIN32 /* Runtime section names and name strings. */ #define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COFF @@ -800,6 +820,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, #define INSTR_PROF_COVDATA_SECT_NAME INSTR_PROF_COVDATA_COFF #define INSTR_PROF_COVNAME_SECT_NAME INSTR_PROF_COVNAME_COFF #define INSTR_PROF_ORDERFILE_SECT_NAME INSTR_PROF_ORDERFILE_COFF +#define INSTR_PROF_COVINIT_SECT_NAME INSTR_PROF_COVINIT_COFF #else /* Runtime section names and name strings. */ #define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON) @@ -821,6 +842,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, /* Order file instrumentation. */ #define INSTR_PROF_ORDERFILE_SECT_NAME \ INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON) +#define INSTR_PROF_COVINIT_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVINIT_COMMON) #endif #define INSTR_PROF_ORDERFILE_BUFFER_NAME _llvm_order_file_buffer diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index dcde86388dcd9d..3251340aa67a6a 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -290,6 +290,8 @@ class PPCAIXAsmPrinter : public PPCAsmPrinter { void emitPGORefs(Module &M); + void emitGCOVRefs(); + void emitEndOfAsmFile(Module &) override; void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const override; @@ -2962,6 +2964,26 @@ void PPCAIXAsmPrinter::emitPGORefs(Module &M) { } } +void PPCAIXAsmPrinter::emitGCOVRefs() { + if (!OutContext.hasXCOFFSection( + "__llvm_gcov_ctr_section", + XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) + return; + + MCSection *CtrSection = OutContext.getXCOFFSection( + "__llvm_gcov_ctr_section", SectionKind::getData(), + XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD), + /*MultiSymbolsAllowed*/ true); + + OutStreamer->switchSection(CtrSection); + if (OutContext.hasXCOFFSection( + "__llvm_covinit", + XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) { + MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_covinit[RW]"); + OutStreamer->emitXCOFFRefDirective(S); + } +} + void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) { // If there are no functions and there are no toc-data definitions in this // module, we will never need to reference the TOC base. @@ -2969,6 +2991,7 @@ void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) { return; emitPGORefs(M); + emitGCOVRefs(); // Switch to section to emit TOC base. OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection()); diff --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp index c7f6f2a43c17f5..e6a7cdf3f80a9e 100644 --- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -29,6 +29,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" +#include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/CRC.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -121,7 +122,7 @@ class GCOVProfiler { Function *createInternalFunction(FunctionType *FTy, StringRef Name, StringRef MangledType = ""); - void emitGlobalConstructor( + void emitModuleInitFunctionPtrs( SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP); bool isFunctionInstrumented(const Function &F); @@ -914,6 +915,7 @@ bool GCOVProfiler::emitProfileNotes( GlobalVariable *Counters = new GlobalVariable( *M, CounterTy, false, GlobalValue::InternalLinkage, Constant::getNullValue(CounterTy), "__llvm_gcov_ctr"); + Counters->setSection("__llvm_gcov_ctr_section"); CountersBySP.emplace_back(Counters, SP); for (size_t I : llvm::seq<size_t>(0, Measured)) { @@ -980,7 +982,7 @@ bool GCOVProfiler::emitProfileNotes( } if (EmitGCDA) { - emitGlobalConstructor(CountersBySP); + emitModuleInitFunctionPtrs(CountersBySP); EmitGCDA = false; } } @@ -1001,32 +1003,38 @@ Function *GCOVProfiler::createInternalFunction(FunctionType *FTy, return F; } -void GCOVProfiler::emitGlobalConstructor( +void GCOVProfiler::emitModuleInitFunctionPtrs( SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP) { Function *WriteoutF = insertCounterWriteout(CountersBySP); Function *ResetF = insertReset(CountersBySP); - // Create a small bit of code that registers the "__llvm_gcov_writeout" to - // be executed at exit and the "__llvm_gcov_reset" function to be executed - // when "__gcov_flush" is called. - FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); - Function *F = createInternalFunction(FTy, "__llvm_gcov_init", "_ZTSFvvE"); - F->addFnAttr(Attribute::NoInline); + // Instead of creating a function call and add it to the constructors list, + // create a global variable in the __llvm_covinit section so the functions + // can be registered by a constructor in the runtime. - BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F); - IRBuilder<> Builder(BB); + auto &Ctx = M->getContext(); + + Type *InitFuncDataTy[] = { +#define COVINIT_FUNC(Type, LLVMType, Name, Init) LLVMType, +#include "llvm/ProfileData/InstrProfData.inc" + }; - FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); - auto *PFTy = PointerType::get(FTy, 0); - FTy = FunctionType::get(Builder.getVoidTy(), {PFTy, PFTy}, false); + auto STy = StructType::get(Ctx, ArrayRef(InitFuncDataTy)); - // Initialize the environment and register the local writeout, flush and - // reset functions. - FunctionCallee GCOVInit = M->getOrInsertFunction("llvm_gcov_init", FTy); - Builder.CreateCall(GCOVInit, {WriteoutF, ResetF}); - Builder.CreateRetVoid(); + Constant *InitFuncPtrs[] = { +#define COVINIT_FUNC(Type, LLVMType, Name, Init) Init, +#include "llvm/ProfileData/InstrProfData.inc" + }; - appendToGlobalCtors(*M, F, 0); + auto *CovInitGV = + new GlobalVariable(*M, STy, false, GlobalValue::PrivateLinkage, nullptr, + "__llvm_covinit_functions"); + CovInitGV->setInitializer(ConstantStruct::get(STy, InitFuncPtrs)); + CovInitGV->setVisibility(GlobalValue::VisibilityTypes::DefaultVisibility); + CovInitGV->setSection(getInstrProfSectionName( + IPSK_covinit, Triple(M->getTargetTriple()).getObjectFormat())); + CovInitGV->setAlignment(Align(INSTR_PROF_DATA_ALIGNMENT)); + CovInitGV->setConstant(true); } FunctionCallee GCOVProfiler::getStartFileFunc(const TargetLibraryInfo *TLI) { diff --git a/llvm/test/Transforms/GCOVProfiling/kcfi-normalize.ll b/llvm/test/Transforms/GCOVProfiling/kcfi-normalize.ll index 19122b920d1ca4..be53595e9201a0 100644 --- a/llvm/test/Transforms/GCOVProfiling/kcfi-normalize.ll +++ b/llvm/test/Transforms/GCOVProfiling/kcfi-normalize.ll @@ -1,8 +1,11 @@ -;; Ensure __llvm_gcov_(writeout|reset|init) have the correct !kcfi_type +;; Ensure __llvm_gcov_(writeout|reset) have the correct !kcfi_type ;; with integer normalization. ; RUN: mkdir -p %t && cd %t ; RUN: opt < %s -S -passes=insert-gcov-profiling | FileCheck %s +; Check for gcov initialization function pointers. +; CHECK: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" + target triple = "x86_64-unknown-linux-gnu" define dso_local void @empty() !dbg !5 { @@ -29,7 +32,5 @@ entry: ; CHECK-SAME: !kcfi_type ![[#TYPE:]] ; CHECK: define internal void @__llvm_gcov_reset() ; CHECK-SAME: !kcfi_type ![[#TYPE]] -; CHECK: define internal void @__llvm_gcov_init() -; CHECK-SAME: !kcfi_type ![[#TYPE]] ; CHECK: ![[#TYPE]] = !{i32 -440107680} diff --git a/llvm/test/Transforms/GCOVProfiling/kcfi.ll b/llvm/test/Transforms/GCOVProfiling/kcfi.ll index 1b97d25294cd65..35f863e0fd0752 100644 --- a/llvm/test/Transforms/GCOVProfiling/kcfi.ll +++ b/llvm/test/Transforms/GCOVProfiling/kcfi.ll @@ -1,7 +1,10 @@ -;; Ensure __llvm_gcov_(writeout|reset|init) have !kcfi_type with KCFI. +;; Ensure __llvm_gcov_(writeout|reset) have !kcfi_type with KCFI. ; RUN: mkdir -p %t && cd %t ; RUN: opt < %s -S -passes=insert-gcov-profiling | FileCheck %s +; Check for gcov initialization function pointers. +; CHECK: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" + target triple = "x86_64-unknown-linux-gnu" define dso_local void @empty() !dbg !5 { @@ -27,7 +30,5 @@ entry: ; CHECK-SAME: !kcfi_type ![[#TYPE:]] ; CHECK: define internal void @__llvm_gcov_reset() ; CHECK-SAME: !kcfi_type ![[#TYPE]] -; CHECK: define internal void @__llvm_gcov_init() -; CHECK-SAME: !kcfi_type ![[#TYPE]] ; CHECK: ![[#TYPE]] = !{i32 -1522505972} diff --git a/llvm/test/Transforms/GCOVProfiling/module-flags.ll b/llvm/test/Transforms/GCOVProfiling/module-flags.ll index 919dd41ea20348..ac8f983055985c 100644 --- a/llvm/test/Transforms/GCOVProfiling/module-flags.ll +++ b/llvm/test/Transforms/GCOVProfiling/module-flags.ll @@ -1,6 +1,9 @@ ; RUN: mkdir -p %t && cd %t ; RUN: opt < %s -S -passes=insert-gcov-profiling | FileCheck %s +; Check for gcov initialization function pointers. +; CHECK: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" + target triple = "x86_64-unknown-linux-gnu" define dso_local void @empty() !dbg !5 { @@ -30,5 +33,4 @@ entry: ;; Infer uwtable and "frame-pointer" from the module flags. ; CHECK: define internal void @__llvm_gcov_writeout() unnamed_addr #[[#ATTR:]] ; CHECK: define internal void @__llvm_gcov_reset() unnamed_addr #[[#ATTR]] -; CHECK: define internal void @__llvm_gcov_init() unnamed_addr #[[#ATTR]] ; CHECK: attributes #[[#ATTR]] = { noinline nounwind uwtable "frame-pointer"="all" } >From 7c6b1d734a23ddbffc67fdafd171ea0f5515891d Mon Sep 17 00:00:00 2001 From: Qiongsi Wu <q...@ibm.com> Date: Thu, 12 Sep 2024 17:43:42 -0400 Subject: [PATCH 2/6] Special code for AIX only. --- clang/test/CodeGen/attr-function-return.c | 7 +--- clang/test/CodeGen/code-coverage.c | 26 ++++++++----- clang/test/CodeGen/coverage-target-attr.c | 5 +-- compiler-rt/lib/profile/GCDAProfiling.c | 2 + .../Instrumentation/GCOVProfiling.cpp | 37 ++++++++++++++++++- .../GCOVProfiling/kcfi-normalize.ll | 17 ++++++--- llvm/test/Transforms/GCOVProfiling/kcfi.ll | 17 ++++++--- .../Transforms/GCOVProfiling/module-flags.ll | 14 ++++--- 8 files changed, 88 insertions(+), 37 deletions(-) diff --git a/clang/test/CodeGen/attr-function-return.c b/clang/test/CodeGen/attr-function-return.c index 9c5cbca5640843..1aca3b1bfa5b59 100644 --- a/clang/test/CodeGen/attr-function-return.c +++ b/clang/test/CodeGen/attr-function-return.c @@ -9,7 +9,7 @@ // RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-EXTERN // RUN: %clang_cc1 -std=gnu2x -triple x86_64-linux-gnu %s -emit-llvm -o - \ // RUN: -mfunction-return=thunk-extern -coverage-data-file=/dev/null \ -// RUN: | FileCheck %s --check-prefix=CHECK-GCOV +// RUN: | FileCheck %s --check-prefixes=CHECK-GCOV // RUN: %clang_cc1 -std=gnu2x -triple x86_64-linux-gnu %s -emit-llvm -o - \ // RUN: -mfunction-return=thunk-extern -fsanitize=address \ // RUN: | FileCheck %s --check-prefix=CHECK-ASAN @@ -17,9 +17,6 @@ // RUN: -mfunction-return=thunk-extern -fsanitize=thread \ // RUN: | FileCheck %s --check-prefix=CHECK-TSAN -// Check for gcov initialization function pointers. -// CHECK-GCOV: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" - #if !__has_attribute(function_return) #error "missing attribute support for function_return" #endif @@ -107,7 +104,7 @@ void no_attrs(void) {} // Test synthetic functions. // CHECK-GCOV: @__llvm_gcov_writeout() unnamed_addr [[EXTERNGCOV:#[0-9]+]] // CHECK-GCOV: @__llvm_gcov_reset() unnamed_addr [[EXTERNGCOV]] -// CHECK-GCOV-NOT: @__llvm_gcov_init() unnamed_addr [[EXTERNGCOV]] +// CHECK-GCOV: @__llvm_gcov_init() unnamed_addr [[EXTERNGCOV]] // CHECK-ASAN: @asan.module_ctor() [[EXTERNASAN:#[0-9]+]] // CHECK-TSAN: @tsan.module_ctor() [[EXTERNTSAN:#[0-9]+]] diff --git a/clang/test/CodeGen/code-coverage.c b/clang/test/CodeGen/code-coverage.c index 4e3f0aba8c4098..30c59d58380def 100644 --- a/clang/test/CodeGen/code-coverage.c +++ b/clang/test/CodeGen/code-coverage.c @@ -3,12 +3,18 @@ /// 4.7 enables cfg_checksum. /// 4.8 (default, compatible with gcov 7) emits the exit block the second. // RUN: rm -rf %t && mkdir %t && cd %t -// RUN: %clang_cc1 -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='304*' %s -o - | \ -// RUN: FileCheck --check-prefixes=CHECK,304 %s -// RUN: %clang_cc1 -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='407*' %s -o - | \ -// RUN: FileCheck --check-prefixes=CHECK,407 %s -// RUN: %clang_cc1 -emit-llvm -disable-red-zone -coverage-data-file=/dev/null %s -o - | \ -// RUN: FileCheck --check-prefixes=CHECK,408 %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='304*' %s -o - | \ +// RUN: FileCheck --check-prefixes=CHECK,CHECK-ELF,304 %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='407*' %s -o - | \ +// RUN: FileCheck --check-prefixes=CHECK,CHECK-ELF,407 %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-red-zone -coverage-data-file=/dev/null %s -o - | \ +// RUN: FileCheck --check-prefixes=CHECK,CHECK-ELF,408 %s +// RUN: %clang_cc1 -triple powerpc64-ibm-aix -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='304*' %s -o - | \ +// RUN: FileCheck --check-prefixes=CHECK,CHECK-XCOFF,304 %s +// RUN: %clang_cc1 -triple powerpc64-ibm-aix -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='407*' %s -o - | \ +// RUN: FileCheck --check-prefixes=CHECK,CHECK-XCOFF,407 %s +// RUN: %clang_cc1 -triple powerpc64-ibm-aix -emit-llvm -disable-red-zone -coverage-data-file=/dev/null %s -o - | \ +// RUN: FileCheck --check-prefixes=CHECK,CHECK-XCOFF,408 %s // RUN: %clang_cc1 -emit-llvm -disable-red-zone -coverage-notes-file=aaa.gcno -coverage-data-file=bbb.gcda -debug-info-kind=limited -dwarf-version=4 %s -o - | FileCheck %s --check-prefix GCOV_FILE_INFO @@ -23,6 +29,9 @@ // NEWPM-O3: Running pass: ForceFunctionAttrsPass // NEWPM-O3: Running pass: GCOVProfilerPass +// Check for gcov initialization function pointers. +// CHECK-XCOFF: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" + int test1(int a) { switch (a % 2) { case 0: @@ -49,13 +58,10 @@ int test2(int b) { /// 0x3430382a '4' '0' '8' '*' // 408-SAME: i32 875575338 -// Check for gcov initialization function pointers. -// CHECK: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" - // Check that the noredzone flag is set on the generated functions. // CHECK: void @__llvm_gcov_writeout() unnamed_addr [[NRZ:#[0-9]+]] -// CHECK-NOT: void @__llvm_gcov_init() unnamed_addr [[NRZ]] +// CHECK-ELF: void @__llvm_gcov_init() unnamed_addr [[NRZ]] // CHECK: attributes [[NRZ]] = { {{.*}}noredzone{{.*}} } diff --git a/clang/test/CodeGen/coverage-target-attr.c b/clang/test/CodeGen/coverage-target-attr.c index 156e48ba6a31a2..d46299f5bee223 100644 --- a/clang/test/CodeGen/coverage-target-attr.c +++ b/clang/test/CodeGen/coverage-target-attr.c @@ -1,12 +1,9 @@ // RUN: %clang_cc1 -emit-llvm -coverage-notes-file=/dev/null -coverage-data-file=/dev/null -triple aarch64-linux-android30 -target-cpu generic -target-feature +tagged-globals -fsanitize=hwaddress %s -o %t // RUN: FileCheck %s < %t -// Check for gcov initialization function pointers. -// CHECK: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" - // CHECK: define internal void @__llvm_gcov_writeout() unnamed_addr [[ATTR:#[0-9]+]] // CHECK: define internal void @__llvm_gcov_reset() unnamed_addr [[ATTR]] -// CHECK-NOT: define internal void @__llvm_gcov_init() unnamed_addr [[ATTR]] +// CHECK: define internal void @__llvm_gcov_init() unnamed_addr [[ATTR]] // CHECK: define internal void @hwasan.module_ctor() [[ATTR2:#[0-9]+]] // CHECK: attributes [[ATTR]] = {{.*}} "target-cpu"="generic" "target-features"="+tagged-globals" // CHECK: attributes [[ATTR2]] = {{.*}} "target-cpu"="generic" "target-features"="+tagged-globals" diff --git a/compiler-rt/lib/profile/GCDAProfiling.c b/compiler-rt/lib/profile/GCDAProfiling.c index f430dd4e36ce37..452a62fcc9d21e 100644 --- a/compiler-rt/lib/profile/GCDAProfiling.c +++ b/compiler-rt/lib/profile/GCDAProfiling.c @@ -624,6 +624,7 @@ void llvm_gcov_init(fn_ptr wfn, fn_ptr rfn) { } } +#if defined(_AIX) COMPILER_RT_VISIBILITY __attribute__((constructor)) void __llvm_profile_gcov_initialize() { const __llvm_gcov_init_func_struct *InitFuncStart = @@ -640,6 +641,7 @@ __llvm_profile_gcov_initialize() { llvm_gcov_init(wfn, rfn); } } +#endif void __gcov_dump(void) { for (struct fn_node *f = writeout_fn_list.head; f; f = f->next) diff --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp index e6a7cdf3f80a9e..4a399ad438215a 100644 --- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -122,6 +122,9 @@ class GCOVProfiler { Function *createInternalFunction(FunctionType *FTy, StringRef Name, StringRef MangledType = ""); + + void emitGlobalConstructor( + SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP); void emitModuleInitFunctionPtrs( SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP); @@ -982,7 +985,11 @@ bool GCOVProfiler::emitProfileNotes( } if (EmitGCDA) { - emitModuleInitFunctionPtrs(CountersBySP); + const llvm::Triple &Triple = llvm::Triple(M->getTargetTriple()); + if (Triple.getObjectFormat() == llvm::Triple::XCOFF) + emitModuleInitFunctionPtrs(CountersBySP); + else + emitGlobalConstructor(CountersBySP); EmitGCDA = false; } } @@ -1003,6 +1010,34 @@ Function *GCOVProfiler::createInternalFunction(FunctionType *FTy, return F; } +void GCOVProfiler::emitGlobalConstructor( + SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP) { + Function *WriteoutF = insertCounterWriteout(CountersBySP); + Function *ResetF = insertReset(CountersBySP); + + // Create a small bit of code that registers the "__llvm_gcov_writeout" to + // be executed at exit and the "__llvm_gcov_reset" function to be executed + // when "__gcov_flush" is called. + FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); + Function *F = createInternalFunction(FTy, "__llvm_gcov_init", "_ZTSFvvE"); + F->addFnAttr(Attribute::NoInline); + + BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F); + IRBuilder<> Builder(BB); + + FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); + auto *PFTy = PointerType::get(FTy, 0); + FTy = FunctionType::get(Builder.getVoidTy(), {PFTy, PFTy}, false); + + // Initialize the environment and register the local writeout, flush and + // reset functions. + FunctionCallee GCOVInit = M->getOrInsertFunction("llvm_gcov_init", FTy); + Builder.CreateCall(GCOVInit, {WriteoutF, ResetF}); + Builder.CreateRetVoid(); + + appendToGlobalCtors(*M, F, 0); +} + void GCOVProfiler::emitModuleInitFunctionPtrs( SmallVectorImpl<std::pair<GlobalVariable *, MDNode *>> &CountersBySP) { Function *WriteoutF = insertCounterWriteout(CountersBySP); diff --git a/llvm/test/Transforms/GCOVProfiling/kcfi-normalize.ll b/llvm/test/Transforms/GCOVProfiling/kcfi-normalize.ll index be53595e9201a0..fa19fcfe271e07 100644 --- a/llvm/test/Transforms/GCOVProfiling/kcfi-normalize.ll +++ b/llvm/test/Transforms/GCOVProfiling/kcfi-normalize.ll @@ -1,12 +1,15 @@ -;; Ensure __llvm_gcov_(writeout|reset) have the correct !kcfi_type +;; Ensure __llvm_gcov_(writeout|reset|init) have the correct !kcfi_type ;; with integer normalization. ; RUN: mkdir -p %t && cd %t -; RUN: opt < %s -S -passes=insert-gcov-profiling | FileCheck %s +; RUN: opt < %s -S -passes=insert-gcov-profiling \ +; RUN: -mtriple=x86_64-unknown-linux-gnu | FileCheck \ +; RUN: --check-prefixes=CHECK,CHECK-ELF %s +; RUN: opt < %s -S -passes=insert-gcov-profiling \ +; RUN: -mtriple=powerpc64-ibm-aix | FileCheck \ +; RUN: --check-prefixes=CHECK,CHECK-XCOFF %s -; Check for gcov initialization function pointers. -; CHECK: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" - -target triple = "x86_64-unknown-linux-gnu" +; Check for gcov initialization function pointers for XCOFF. +; CHECK-XCOFF: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" define dso_local void @empty() !dbg !5 { entry: @@ -32,5 +35,7 @@ entry: ; CHECK-SAME: !kcfi_type ![[#TYPE:]] ; CHECK: define internal void @__llvm_gcov_reset() ; CHECK-SAME: !kcfi_type ![[#TYPE]] +; CHECK-ELF: define internal void @__llvm_gcov_init() +; CHECK-ELF-SAME: !kcfi_type ![[#TYPE]] ; CHECK: ![[#TYPE]] = !{i32 -440107680} diff --git a/llvm/test/Transforms/GCOVProfiling/kcfi.ll b/llvm/test/Transforms/GCOVProfiling/kcfi.ll index 35f863e0fd0752..bfa3a6403578f2 100644 --- a/llvm/test/Transforms/GCOVProfiling/kcfi.ll +++ b/llvm/test/Transforms/GCOVProfiling/kcfi.ll @@ -1,11 +1,14 @@ -;; Ensure __llvm_gcov_(writeout|reset) have !kcfi_type with KCFI. +;; Ensure __llvm_gcov_(writeout|reset|init) have !kcfi_type with KCFI. ; RUN: mkdir -p %t && cd %t -; RUN: opt < %s -S -passes=insert-gcov-profiling | FileCheck %s +; RUN: opt < %s -S -passes=insert-gcov-profiling \ +; RUN: -mtriple=x86_64-unknown-linux-gnu | FileCheck \ +; RUN: --check-prefixes=CHECK,CHECK-ELF %s +; RUN: opt < %s -S -passes=insert-gcov-profiling \ +; RUN: -mtriple=powerpc64-ibm-aix | FileCheck \ +; RUN: --check-prefixes=CHECK,CHECK-XCOFF %s -; Check for gcov initialization function pointers. -; CHECK: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" - -target triple = "x86_64-unknown-linux-gnu" +; Check for gcov initialization function pointers for XCOFF. +; CHECK-XCOFF: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" define dso_local void @empty() !dbg !5 { entry: @@ -30,5 +33,7 @@ entry: ; CHECK-SAME: !kcfi_type ![[#TYPE:]] ; CHECK: define internal void @__llvm_gcov_reset() ; CHECK-SAME: !kcfi_type ![[#TYPE]] +; CHECK-ELF: define internal void @__llvm_gcov_init() +; CHECK-ELF-SAME: !kcfi_type ![[#TYPE]] ; CHECK: ![[#TYPE]] = !{i32 -1522505972} diff --git a/llvm/test/Transforms/GCOVProfiling/module-flags.ll b/llvm/test/Transforms/GCOVProfiling/module-flags.ll index ac8f983055985c..77fc77bfe18cc3 100644 --- a/llvm/test/Transforms/GCOVProfiling/module-flags.ll +++ b/llvm/test/Transforms/GCOVProfiling/module-flags.ll @@ -1,10 +1,13 @@ ; RUN: mkdir -p %t && cd %t -; RUN: opt < %s -S -passes=insert-gcov-profiling | FileCheck %s +; RUN: opt < %s -S -passes=insert-gcov-profiling \ +; RUN: -mtriple=x86_64-unknown-linux-gnu | FileCheck \ +; RUN: --check-prefixes=CHECK,CHECK-ELF %s +; RUN: opt < %s -S -passes=insert-gcov-profiling \ +; RUN: -mtriple=powerpc64-ibm-aix | FileCheck \ +; RUN: --check-prefixes=CHECK,CHECK-XCOFF %s -; Check for gcov initialization function pointers. -; CHECK: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" - -target triple = "x86_64-unknown-linux-gnu" +; Check for gcov initialization function pointers for XCOFF. +; CHECK-XCOFF: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" define dso_local void @empty() !dbg !5 { entry: @@ -33,4 +36,5 @@ entry: ;; Infer uwtable and "frame-pointer" from the module flags. ; CHECK: define internal void @__llvm_gcov_writeout() unnamed_addr #[[#ATTR:]] ; CHECK: define internal void @__llvm_gcov_reset() unnamed_addr #[[#ATTR]] +; CHECK-ELF: define internal void @__llvm_gcov_init() unnamed_addr #[[#ATTR]] ; CHECK: attributes #[[#ATTR]] = { noinline nounwind uwtable "frame-pointer"="all" } >From 258103e9a6813e353f203d4ca10db059a0d0902d Mon Sep 17 00:00:00 2001 From: Qiongsi Wu <q...@ibm.com> Date: Mon, 16 Sep 2024 09:27:07 -0400 Subject: [PATCH 3/6] Fix lit test. --- clang/test/CodeGen/code-coverage.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/test/CodeGen/code-coverage.c b/clang/test/CodeGen/code-coverage.c index 30c59d58380def..b65a1fe118b738 100644 --- a/clang/test/CodeGen/code-coverage.c +++ b/clang/test/CodeGen/code-coverage.c @@ -29,9 +29,6 @@ // NEWPM-O3: Running pass: ForceFunctionAttrsPass // NEWPM-O3: Running pass: GCOVProfilerPass -// Check for gcov initialization function pointers. -// CHECK-XCOFF: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" - int test1(int a) { switch (a % 2) { case 0: @@ -58,6 +55,9 @@ int test2(int b) { /// 0x3430382a '4' '0' '8' '*' // 408-SAME: i32 875575338 +// Check for gcov initialization function pointers. +// CHECK-XCOFF: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" + // Check that the noredzone flag is set on the generated functions. // CHECK: void @__llvm_gcov_writeout() unnamed_addr [[NRZ:#[0-9]+]] >From b1eaf18d91252feb3826afc53bc8975c86848bde Mon Sep 17 00:00:00 2001 From: Qiongsi Wu <q...@ibm.com> Date: Wed, 18 Sep 2024 10:37:46 -0400 Subject: [PATCH 4/6] Improve new test. --- compiler-rt/test/profile/AIX/gcov-undef-sym.test | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler-rt/test/profile/AIX/gcov-undef-sym.test b/compiler-rt/test/profile/AIX/gcov-undef-sym.test index e377b321ca66cd..db9053952d95b7 100644 --- a/compiler-rt/test/profile/AIX/gcov-undef-sym.test +++ b/compiler-rt/test/profile/AIX/gcov-undef-sym.test @@ -6,7 +6,7 @@ RUN: rm -rf %t0 && split-file %s %t0 && cd %t0 RUN: %clang bar.c main.c undef.c --coverage -c RUN: ar -X32_64 -rv libfoo.a undef.o bar.o RUN: %clang main.o -L. -lfoo --coverage -o main.exe -RUN: main.exe +RUN: %run ./main.exe RUN: llvm-cov gcov -t main.gcda | FileCheck --check-prefix=MAIN %s RUN: llvm-cov gcov -t bar.gcda | FileCheck --check-prefix=BAR %s @@ -15,7 +15,7 @@ RUN: rm -rf %t1 && split-file %s %t1 && cd %t1 RUN: %clang_pgogen bar.c main.c undef.c -fprofile-arcs -ftest-coverage -c RUN: ar -X32_64 -rv libfoo.a undef.o bar.o RUN: %clang_pgogen main.o -L. -lfoo -fprofile-generate -fprofile-arcs -ftest-coverage -o main.exe -RUN: main.exe +RUN: %run ./main.exe RUN: llvm-cov gcov -t main.gcda | FileCheck --check-prefix=MAIN %s RUN: llvm-cov gcov -t bar.gcda | FileCheck --check-prefix=BAR %s @@ -24,7 +24,7 @@ RUN: rm -rf %t2 && split-file %s %t2 && cd %t2 RUN: %clang_pgogen bar.c main.c undef.c -fprofile-arcs -ftest-coverage -c RUN: ar -X32_64 -rv libfoo.a undef.o bar.o RUN: %clang_pgogen main.o -L. -lfoo -fprofile-generate -fprofile-arcs -ftest-coverage -Wl,-bcdtors:mbr -o main.exe -RUN: main.exe +RUN: %run ./main.exe RUN: llvm-cov gcov -t main.gcda | FileCheck --check-prefix=MAIN %s RUN: llvm-cov gcov -t bar.gcda | FileCheck --check-prefix=BAR %s >From 11793f38a9a7b6d05cd2cfdf5c1a09f3bf3cc5c3 Mon Sep 17 00:00:00 2001 From: Qiongsi Wu <q...@ibm.com> Date: Fri, 4 Oct 2024 17:55:23 -0400 Subject: [PATCH 5/6] Address review comments. --- clang/test/CodeGen/attr-function-return.c | 2 +- clang/test/CodeGen/code-coverage.c | 16 +-- compiler-rt/include/profile/InstrProfData.inc | 3 +- .../llvm/ProfileData/InstrProfData.inc | 3 +- .../Instrumentation/GCOVProfiling.cpp | 4 +- .../test/CodeGen/PowerPC/gcov_ctr_ref_init.ll | 126 ++++++++++++++++++ .../GCOVProfiling/kcfi-normalize.ll | 13 +- llvm/test/Transforms/GCOVProfiling/kcfi.ll | 13 +- .../Transforms/GCOVProfiling/module-flags.ll | 11 +- 9 files changed, 162 insertions(+), 29 deletions(-) create mode 100644 llvm/test/CodeGen/PowerPC/gcov_ctr_ref_init.ll diff --git a/clang/test/CodeGen/attr-function-return.c b/clang/test/CodeGen/attr-function-return.c index 1aca3b1bfa5b59..df2cabf28693a3 100644 --- a/clang/test/CodeGen/attr-function-return.c +++ b/clang/test/CodeGen/attr-function-return.c @@ -9,7 +9,7 @@ // RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-EXTERN // RUN: %clang_cc1 -std=gnu2x -triple x86_64-linux-gnu %s -emit-llvm -o - \ // RUN: -mfunction-return=thunk-extern -coverage-data-file=/dev/null \ -// RUN: | FileCheck %s --check-prefixes=CHECK-GCOV +// RUN: | FileCheck %s --check-prefix=CHECK-GCOV // RUN: %clang_cc1 -std=gnu2x -triple x86_64-linux-gnu %s -emit-llvm -o - \ // RUN: -mfunction-return=thunk-extern -fsanitize=address \ // RUN: | FileCheck %s --check-prefix=CHECK-ASAN diff --git a/clang/test/CodeGen/code-coverage.c b/clang/test/CodeGen/code-coverage.c index b65a1fe118b738..4e3364df217854 100644 --- a/clang/test/CodeGen/code-coverage.c +++ b/clang/test/CodeGen/code-coverage.c @@ -4,17 +4,17 @@ /// 4.8 (default, compatible with gcov 7) emits the exit block the second. // RUN: rm -rf %t && mkdir %t && cd %t // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='304*' %s -o - | \ -// RUN: FileCheck --check-prefixes=CHECK,CHECK-ELF,304 %s +// RUN: FileCheck --check-prefixes=CHECK,CHECK-CTOR-INIT,304 %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='407*' %s -o - | \ -// RUN: FileCheck --check-prefixes=CHECK,CHECK-ELF,407 %s +// RUN: FileCheck --check-prefixes=CHECK,CHECK-CTOR-INIT,407 %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-red-zone -coverage-data-file=/dev/null %s -o - | \ -// RUN: FileCheck --check-prefixes=CHECK,CHECK-ELF,408 %s +// RUN: FileCheck --check-prefixes=CHECK,CHECK-CTOR-INIT,408 %s // RUN: %clang_cc1 -triple powerpc64-ibm-aix -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='304*' %s -o - | \ -// RUN: FileCheck --check-prefixes=CHECK,CHECK-XCOFF,304 %s +// RUN: FileCheck --check-prefixes=CHECK,CHECK-RT-INIT,304 %s // RUN: %clang_cc1 -triple powerpc64-ibm-aix -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='407*' %s -o - | \ -// RUN: FileCheck --check-prefixes=CHECK,CHECK-XCOFF,407 %s +// RUN: FileCheck --check-prefixes=CHECK,CHECK-RT-INIT,407 %s // RUN: %clang_cc1 -triple powerpc64-ibm-aix -emit-llvm -disable-red-zone -coverage-data-file=/dev/null %s -o - | \ -// RUN: FileCheck --check-prefixes=CHECK,CHECK-XCOFF,408 %s +// RUN: FileCheck --check-prefixes=CHECK,CHECK-RT-INIT,408 %s // RUN: %clang_cc1 -emit-llvm -disable-red-zone -coverage-notes-file=aaa.gcno -coverage-data-file=bbb.gcda -debug-info-kind=limited -dwarf-version=4 %s -o - | FileCheck %s --check-prefix GCOV_FILE_INFO @@ -56,12 +56,12 @@ int test2(int b) { // 408-SAME: i32 875575338 // Check for gcov initialization function pointers. -// CHECK-XCOFF: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" +// CHECK-RT-INIT: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" // Check that the noredzone flag is set on the generated functions. // CHECK: void @__llvm_gcov_writeout() unnamed_addr [[NRZ:#[0-9]+]] -// CHECK-ELF: void @__llvm_gcov_init() unnamed_addr [[NRZ]] +// CHECK-CTOR-INIT: void @__llvm_gcov_init() unnamed_addr [[NRZ]] // CHECK: attributes [[NRZ]] = { {{.*}}noredzone{{.*}} } diff --git a/compiler-rt/include/profile/InstrProfData.inc b/compiler-rt/include/profile/InstrProfData.inc index 591fc1401e1aab..c66b0465a0b548 100644 --- a/compiler-rt/include/profile/InstrProfData.inc +++ b/compiler-rt/include/profile/InstrProfData.inc @@ -798,7 +798,8 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, #define INSTR_PROF_COVNAME_COFF ".lcovn" #define INSTR_PROF_ORDERFILE_COFF ".lorderfile$M" -// TODO: Placeholder for Windows. We need to revise when we upstream this. +// FIXME: Placeholder for Windows. Windows currently does not initialize +// the GCOV functions in the runtime. #define INSTR_PROF_COVINIT_COFF ".lcovd$M" #ifdef _WIN32 diff --git a/llvm/include/llvm/ProfileData/InstrProfData.inc b/llvm/include/llvm/ProfileData/InstrProfData.inc index 591fc1401e1aab..c66b0465a0b548 100644 --- a/llvm/include/llvm/ProfileData/InstrProfData.inc +++ b/llvm/include/llvm/ProfileData/InstrProfData.inc @@ -798,7 +798,8 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure, #define INSTR_PROF_COVNAME_COFF ".lcovn" #define INSTR_PROF_ORDERFILE_COFF ".lorderfile$M" -// TODO: Placeholder for Windows. We need to revise when we upstream this. +// FIXME: Placeholder for Windows. Windows currently does not initialize +// the GCOV functions in the runtime. #define INSTR_PROF_COVINIT_COFF ".lcovd$M" #ifdef _WIN32 diff --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp index 4a399ad438215a..3cc9484dfe73cd 100644 --- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -918,7 +918,9 @@ bool GCOVProfiler::emitProfileNotes( GlobalVariable *Counters = new GlobalVariable( *M, CounterTy, false, GlobalValue::InternalLinkage, Constant::getNullValue(CounterTy), "__llvm_gcov_ctr"); - Counters->setSection("__llvm_gcov_ctr_section"); + const llvm::Triple &Triple = llvm::Triple(M->getTargetTriple()); + if (Triple.getObjectFormat() == llvm::Triple::XCOFF) + Counters->setSection("__llvm_gcov_ctr_section"); CountersBySP.emplace_back(Counters, SP); for (size_t I : llvm::seq<size_t>(0, Measured)) { diff --git a/llvm/test/CodeGen/PowerPC/gcov_ctr_ref_init.ll b/llvm/test/CodeGen/PowerPC/gcov_ctr_ref_init.ll new file mode 100644 index 00000000000000..91f55fd71aa19a --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/gcov_ctr_ref_init.ll @@ -0,0 +1,126 @@ +; Tests if the __llvm_gcov_ctr section contains a .ref pseudo-op +; referring to the __llvm_covinit section. +; RUN: llc < %s | FileCheck %s + +target datalayout = "E-m:a-p:32:32-Fi32-i64:64-n32" +target triple = "powerpc-ibm-aix" + +; CHECK: .csect __llvm_covinit[RW],3 +; CHECK: .vbyte 4, __llvm_gcov_writeout[DS] +; CHECK-NEXT: .vbyte 4, __llvm_gcov_reset[DS] +; CHECK: __llvm_gcov_ctr.1: +; CHECK-NEXT: .extern .llvm_gcda_start_file[PR] +; CHECK-NEXT: .extern .llvm_gcda_emit_function[PR] +; CHECK-NEXT: .extern .llvm_gcda_emit_arcs[PR] +; CHECK-NEXT: .extern .llvm_gcda_summary_info[PR] +; CHECK-NEXT: .extern .llvm_gcda_end_file[PR] +; CHECK-NEXT: .ref __llvm_covinit[RW] + +%emit_function_args_ty = type { i32, i32, i32 } +%emit_arcs_args_ty = type { i32, ptr } +%file_info = type { %start_file_args_ty, i32, ptr, ptr } +%start_file_args_ty = type { ptr, i32, i32 } + +@__llvm_gcov_ctr = internal global [1 x i64] zeroinitializer, section "__llvm_gcov_ctr_section" +@__llvm_gcov_ctr.1 = internal global [1 x i64] zeroinitializer, section "__llvm_gcov_ctr_section" +@0 = private unnamed_addr constant [10 x i8] c"test.gcda\00", align 1 +@__llvm_internal_gcov_emit_function_args.0 = internal unnamed_addr constant [2 x %emit_function_args_ty] [%emit_function_args_ty { i32 0, i32 1961870044, i32 -801444649 }, %emit_function_args_ty { i32 1, i32 1795396728, i32 -801444649 }] +@__llvm_internal_gcov_emit_arcs_args.0 = internal unnamed_addr constant [2 x %emit_arcs_args_ty] [%emit_arcs_args_ty { i32 1, ptr @__llvm_gcov_ctr }, %emit_arcs_args_ty { i32 1, ptr @__llvm_gcov_ctr.1 }] +@__llvm_internal_gcov_emit_file_info = internal unnamed_addr constant [1 x %file_info] [%file_info { %start_file_args_ty { ptr @0, i32 875575338, i32 -801444649 }, i32 2, ptr @__llvm_internal_gcov_emit_function_args.0, ptr @__llvm_internal_gcov_emit_arcs_args.0 }] +@__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit", align 8 + +define i32 @bar() { +entry: + %gcov_ctr = load i64, ptr @__llvm_gcov_ctr, align 8 + %0 = add i64 %gcov_ctr, 1 + store i64 %0, ptr @__llvm_gcov_ctr, align 8 + ret i32 1 +} + +define i32 @main() { +entry: + %gcov_ctr = load i64, ptr @__llvm_gcov_ctr.1, align 8 + %0 = add i64 %gcov_ctr, 1 + store i64 %0, ptr @__llvm_gcov_ctr.1, align 8 + %retval = alloca i32, align 4 + store i32 0, ptr %retval, align 4 + %call = call i32 @bar() + %sub = sub nsw i32 %call, 1 + ret i32 %sub +} + +define internal void @__llvm_gcov_writeout() unnamed_addr { +entry: + br label %file.loop.header + +file.loop.header: ; preds = %file.loop.latch, %entry + %file_idx = phi i32 [ 0, %entry ], [ %next_file_idx, %file.loop.latch ] + %0 = getelementptr inbounds [1 x %file_info], ptr @__llvm_internal_gcov_emit_file_info, i32 0, i32 %file_idx + %start_file_args = getelementptr inbounds nuw %file_info, ptr %0, i32 0, i32 0 + %1 = getelementptr inbounds nuw %start_file_args_ty, ptr %start_file_args, i32 0, i32 0 + %filename = load ptr, ptr %1, align 4 + %2 = getelementptr inbounds nuw %start_file_args_ty, ptr %start_file_args, i32 0, i32 1 + %version = load i32, ptr %2, align 4 + %3 = getelementptr inbounds nuw %start_file_args_ty, ptr %start_file_args, i32 0, i32 2 + %stamp = load i32, ptr %3, align 4 + call void @llvm_gcda_start_file(ptr %filename, i32 %version, i32 %stamp) + %4 = getelementptr inbounds nuw %file_info, ptr %0, i32 0, i32 1 + %num_ctrs = load i32, ptr %4, align 4 + %5 = getelementptr inbounds nuw %file_info, ptr %0, i32 0, i32 2 + %emit_function_args = load ptr, ptr %5, align 4 + %6 = getelementptr inbounds nuw %file_info, ptr %0, i32 0, i32 3 + %emit_arcs_args = load ptr, ptr %6, align 4 + %7 = icmp slt i32 0, %num_ctrs + br i1 %7, label %counter.loop.header, label %file.loop.latch + +counter.loop.header: ; preds = %counter.loop.header, %file.loop.header + %ctr_idx = phi i32 [ 0, %file.loop.header ], [ %15, %counter.loop.header ] + %8 = getelementptr inbounds %emit_function_args_ty, ptr %emit_function_args, i32 %ctr_idx + %9 = getelementptr inbounds nuw %emit_function_args_ty, ptr %8, i32 0, i32 0 + %ident = load i32, ptr %9, align 4 + %10 = getelementptr inbounds nuw %emit_function_args_ty, ptr %8, i32 0, i32 1 + %func_checkssum = load i32, ptr %10, align 4 + %11 = getelementptr inbounds nuw %emit_function_args_ty, ptr %8, i32 0, i32 2 + %cfg_checksum = load i32, ptr %11, align 4 + call void @llvm_gcda_emit_function(i32 %ident, i32 %func_checkssum, i32 %cfg_checksum) + %12 = getelementptr inbounds %emit_arcs_args_ty, ptr %emit_arcs_args, i32 %ctr_idx + %13 = getelementptr inbounds nuw %emit_arcs_args_ty, ptr %12, i32 0, i32 0 + %num_counters = load i32, ptr %13, align 4 + %14 = getelementptr inbounds nuw %emit_arcs_args_ty, ptr %12, i32 0, i32 1 + %counters = load ptr, ptr %14, align 4 + call void @llvm_gcda_emit_arcs(i32 %num_counters, ptr %counters) + %15 = add i32 %ctr_idx, 1 + %16 = icmp slt i32 %15, %num_ctrs + br i1 %16, label %counter.loop.header, label %file.loop.latch + +file.loop.latch: ; preds = %counter.loop.header, %file.loop.header + call void @llvm_gcda_summary_info() + call void @llvm_gcda_end_file() + %next_file_idx = add i32 %file_idx, 1 + %17 = icmp slt i32 %next_file_idx, 1 + br i1 %17, label %file.loop.header, label %exit + +exit: ; preds = %file.loop.latch + ret void +} + +declare void @llvm_gcda_start_file(ptr, i32, i32) + +declare void @llvm_gcda_emit_function(i32, i32, i32) + +declare void @llvm_gcda_emit_arcs(i32, ptr) + +declare void @llvm_gcda_summary_info() + +declare void @llvm_gcda_end_file() + +define internal void @__llvm_gcov_reset() unnamed_addr { +entry: + call void @llvm.memset.p0.i64(ptr @__llvm_gcov_ctr, i8 0, i64 8, i1 false) + call void @llvm.memset.p0.i64(ptr @__llvm_gcov_ctr.1, i8 0, i64 8, i1 false) + ret void +} + +declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) + + diff --git a/llvm/test/Transforms/GCOVProfiling/kcfi-normalize.ll b/llvm/test/Transforms/GCOVProfiling/kcfi-normalize.ll index fa19fcfe271e07..9ad0418025e56c 100644 --- a/llvm/test/Transforms/GCOVProfiling/kcfi-normalize.ll +++ b/llvm/test/Transforms/GCOVProfiling/kcfi-normalize.ll @@ -3,13 +3,14 @@ ; RUN: mkdir -p %t && cd %t ; RUN: opt < %s -S -passes=insert-gcov-profiling \ ; RUN: -mtriple=x86_64-unknown-linux-gnu | FileCheck \ -; RUN: --check-prefixes=CHECK,CHECK-ELF %s +; RUN: --check-prefixes=CHECK,CHECK-CTOR-INIT %s ; RUN: opt < %s -S -passes=insert-gcov-profiling \ ; RUN: -mtriple=powerpc64-ibm-aix | FileCheck \ -; RUN: --check-prefixes=CHECK,CHECK-XCOFF %s +; RUN: --check-prefixes=CHECK,CHECK-RT-INIT %s -; Check for gcov initialization function pointers for XCOFF. -; CHECK-XCOFF: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" +; Check for gcov initialization function pointers when we initialize +; the writeout and reset functions in the runtime. +; CHECK-RT-INIT: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" define dso_local void @empty() !dbg !5 { entry: @@ -35,7 +36,7 @@ entry: ; CHECK-SAME: !kcfi_type ![[#TYPE:]] ; CHECK: define internal void @__llvm_gcov_reset() ; CHECK-SAME: !kcfi_type ![[#TYPE]] -; CHECK-ELF: define internal void @__llvm_gcov_init() -; CHECK-ELF-SAME: !kcfi_type ![[#TYPE]] +; CHECK-CTOR-INIT: define internal void @__llvm_gcov_init() +; CHECK-CTOR-INIT-SAME: !kcfi_type ![[#TYPE]] ; CHECK: ![[#TYPE]] = !{i32 -440107680} diff --git a/llvm/test/Transforms/GCOVProfiling/kcfi.ll b/llvm/test/Transforms/GCOVProfiling/kcfi.ll index bfa3a6403578f2..5e0e91fc92f5f7 100644 --- a/llvm/test/Transforms/GCOVProfiling/kcfi.ll +++ b/llvm/test/Transforms/GCOVProfiling/kcfi.ll @@ -2,13 +2,14 @@ ; RUN: mkdir -p %t && cd %t ; RUN: opt < %s -S -passes=insert-gcov-profiling \ ; RUN: -mtriple=x86_64-unknown-linux-gnu | FileCheck \ -; RUN: --check-prefixes=CHECK,CHECK-ELF %s +; RUN: --check-prefixes=CHECK,CHECK-CTOR-INIT %s ; RUN: opt < %s -S -passes=insert-gcov-profiling \ ; RUN: -mtriple=powerpc64-ibm-aix | FileCheck \ -; RUN: --check-prefixes=CHECK,CHECK-XCOFF %s +; RUN: --check-prefixes=CHECK,CHECK-RT-INIT %s -; Check for gcov initialization function pointers for XCOFF. -; CHECK-XCOFF: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" +; Check for gcov initialization function pointers when we initialize +; the writeout and reset functions in the runtime. +; CHECK-RT-INIT: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" define dso_local void @empty() !dbg !5 { entry: @@ -33,7 +34,7 @@ entry: ; CHECK-SAME: !kcfi_type ![[#TYPE:]] ; CHECK: define internal void @__llvm_gcov_reset() ; CHECK-SAME: !kcfi_type ![[#TYPE]] -; CHECK-ELF: define internal void @__llvm_gcov_init() -; CHECK-ELF-SAME: !kcfi_type ![[#TYPE]] +; CHECK-CTOR-INIT: define internal void @__llvm_gcov_init() +; CHECK-CTOR-INIT-SAME: !kcfi_type ![[#TYPE]] ; CHECK: ![[#TYPE]] = !{i32 -1522505972} diff --git a/llvm/test/Transforms/GCOVProfiling/module-flags.ll b/llvm/test/Transforms/GCOVProfiling/module-flags.ll index 77fc77bfe18cc3..59f116d0d7e655 100644 --- a/llvm/test/Transforms/GCOVProfiling/module-flags.ll +++ b/llvm/test/Transforms/GCOVProfiling/module-flags.ll @@ -1,13 +1,14 @@ ; RUN: mkdir -p %t && cd %t ; RUN: opt < %s -S -passes=insert-gcov-profiling \ ; RUN: -mtriple=x86_64-unknown-linux-gnu | FileCheck \ -; RUN: --check-prefixes=CHECK,CHECK-ELF %s +; RUN: --check-prefixes=CHECK,CHECK-CTOR-INIT %s ; RUN: opt < %s -S -passes=insert-gcov-profiling \ ; RUN: -mtriple=powerpc64-ibm-aix | FileCheck \ -; RUN: --check-prefixes=CHECK,CHECK-XCOFF %s +; RUN: --check-prefixes=CHECK,CHECK-RT-INIT %s -; Check for gcov initialization function pointers for XCOFF. -; CHECK-XCOFF: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" +; Check for gcov initialization function pointers when we initialize +; the writeout and reset functions in the runtime. +; CHECK-RT-INIT: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit" define dso_local void @empty() !dbg !5 { entry: @@ -36,5 +37,5 @@ entry: ;; Infer uwtable and "frame-pointer" from the module flags. ; CHECK: define internal void @__llvm_gcov_writeout() unnamed_addr #[[#ATTR:]] ; CHECK: define internal void @__llvm_gcov_reset() unnamed_addr #[[#ATTR]] -; CHECK-ELF: define internal void @__llvm_gcov_init() unnamed_addr #[[#ATTR]] +; CHECK-CTOR-INIT: define internal void @__llvm_gcov_init() unnamed_addr #[[#ATTR]] ; CHECK: attributes #[[#ATTR]] = { noinline nounwind uwtable "frame-pointer"="all" } >From b7c470ad6ce64bbd4cd7d513be98a57f7d1740f1 Mon Sep 17 00:00:00 2001 From: Qiongsi Wu <q...@ibm.com> Date: Fri, 4 Oct 2024 19:20:02 -0400 Subject: [PATCH 6/6] Fix the code that inserts the .ref pseudo-op when xcoff-roptr is in effect. --- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 9 +++++++-- llvm/test/CodeGen/PowerPC/gcov_ctr_ref_init.ll | 9 ++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 3251340aa67a6a..e32ba66dd13d05 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -2976,10 +2976,15 @@ void PPCAIXAsmPrinter::emitGCOVRefs() { /*MultiSymbolsAllowed*/ true); OutStreamer->switchSection(CtrSection); + const XCOFF::StorageMappingClass MappingClass = + TM.Options.XCOFFReadOnlyPointers ? XCOFF::XMC_RO : XCOFF::XMC_RW; if (OutContext.hasXCOFFSection( "__llvm_covinit", - XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) { - MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_covinit[RW]"); + XCOFF::CsectProperties(MappingClass, XCOFF::XTY_SD))) { + const char *SymbolStr = TM.Options.XCOFFReadOnlyPointers + ? "__llvm_covinit[RO]" + : "__llvm_covinit[RW]"; + MCSymbol *S = OutContext.getOrCreateSymbol(SymbolStr); OutStreamer->emitXCOFFRefDirective(S); } } diff --git a/llvm/test/CodeGen/PowerPC/gcov_ctr_ref_init.ll b/llvm/test/CodeGen/PowerPC/gcov_ctr_ref_init.ll index 91f55fd71aa19a..990fed30a059e4 100644 --- a/llvm/test/CodeGen/PowerPC/gcov_ctr_ref_init.ll +++ b/llvm/test/CodeGen/PowerPC/gcov_ctr_ref_init.ll @@ -1,11 +1,13 @@ ; Tests if the __llvm_gcov_ctr section contains a .ref pseudo-op ; referring to the __llvm_covinit section. -; RUN: llc < %s | FileCheck %s +; RUN: llc < %s | FileCheck --check-prefixes=CHECK,CHECK-RW %s +; RUN: llc -mxcoff-roptr < %s | FileCheck --check-prefixes=CHECK,CHECK-RO %s target datalayout = "E-m:a-p:32:32-Fi32-i64:64-n32" target triple = "powerpc-ibm-aix" -; CHECK: .csect __llvm_covinit[RW],3 +; CHECK-RW: .csect __llvm_covinit[RW],3 +; CHECK-RO: .csect __llvm_covinit[RO],3 ; CHECK: .vbyte 4, __llvm_gcov_writeout[DS] ; CHECK-NEXT: .vbyte 4, __llvm_gcov_reset[DS] ; CHECK: __llvm_gcov_ctr.1: @@ -14,7 +16,8 @@ target triple = "powerpc-ibm-aix" ; CHECK-NEXT: .extern .llvm_gcda_emit_arcs[PR] ; CHECK-NEXT: .extern .llvm_gcda_summary_info[PR] ; CHECK-NEXT: .extern .llvm_gcda_end_file[PR] -; CHECK-NEXT: .ref __llvm_covinit[RW] +; CHECK-RW-NEXT: .ref __llvm_covinit[RW] +; CHECK-RO-NEXT: .ref __llvm_covinit[RO] %emit_function_args_ty = type { i32, i32, i32 } %emit_arcs_args_ty = type { i32, ptr } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits