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/3] 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/3] 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/3] 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]+]] _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits