Skip to content

Commit f9d0789

Browse files
authored
[PGO] Initialize GCOV Writeout and Reset Functions in the Runtime on AIX (#108570)
This PR registers the writeout and reset functions for `gcov` for all modules in the PGO runtime, instead of registering them using global constructors in each module. The change is made for AIX only, but the same mechanism works on Linux on Power. When registering such functions using global constructors in each module without `-ffunction-sections`, the AIX linker cannot garbage collect unused undefined symbols, because such symbols are grouped in the same section as the `__sinit` symbol. Keeping such undefined symbols causes link errors (see test case https://github.com/llvm/llvm-project/pull/108570/files#diff-500a7e1ba871e1b6b61b523700d5e30987900002add306e1b5e4972cf6d5a4f1R1 for this scenario). This PR implements the initialization in the runtime, hence avoiding introducing `__sinit` into each module. The implementation adds a new global variable `__llvm_covinit_functions` to each module. This new global variable contains the function pointers to the `Writeout` and `Reset` functions. `__llvm_covinit_functions`'s section is the named section `__llvm_covinit`. The linker will aggregate all the `__llvm_covinit` sections from each module to form one single named section in the final binary. The pair of functions ``` const __llvm_gcov_init_func_struct *__llvm_profile_begin_covinit(); const __llvm_gcov_init_func_struct *__llvm_profile_end_covinit(); ``` are implemented to return the start and end address of this named section in the final binary, and they are used in function ``` __llvm_profile_gcov_initialize() ``` (which is a constructor function in the runtime) so the runtime knows the addresses of all the `Writeout` and `Reset` functions from all the modules. One noticeable implementation detail relevant to AIX is that to preserve the `__llvm_covinit` from the linker's garbage collection, a `.ref` pseudo instruction is inserted into them, referring to the section that contains the `__llvm_gcov_ctr` variables, which are used in the instrumented code. The `__llvm_gcov_ctr` variables did not belong to named sections before, but this PR added them to the `__llvm_gcov_ctr_section` named section, so we can add a `.ref` pseudo instruction that refers to them in the `__llvm_covinit` section.
1 parent 3f17da1 commit f9d0789

File tree

14 files changed

+408
-20
lines changed

14 files changed

+408
-20
lines changed

clang/test/CodeGen/code-coverage.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@
33
/// 4.7 enables cfg_checksum.
44
/// 4.8 (default, compatible with gcov 7) emits the exit block the second.
55
// RUN: rm -rf %t && mkdir %t && cd %t
6-
// RUN: %clang_cc1 -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='304*' %s -o - | \
7-
// RUN: FileCheck --check-prefixes=CHECK,304 %s
8-
// RUN: %clang_cc1 -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='407*' %s -o - | \
9-
// RUN: FileCheck --check-prefixes=CHECK,407 %s
10-
// RUN: %clang_cc1 -emit-llvm -disable-red-zone -coverage-data-file=/dev/null %s -o - | \
11-
// RUN: FileCheck --check-prefixes=CHECK,408 %s
6+
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='304*' %s -o - | \
7+
// RUN: FileCheck --check-prefixes=CHECK,CHECK-CTOR-INIT,304 %s
8+
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='407*' %s -o - | \
9+
// RUN: FileCheck --check-prefixes=CHECK,CHECK-CTOR-INIT,407 %s
10+
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-red-zone -coverage-data-file=/dev/null %s -o - | \
11+
// RUN: FileCheck --check-prefixes=CHECK,CHECK-CTOR-INIT,408 %s
12+
// RUN: %clang_cc1 -triple powerpc64-ibm-aix -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='304*' %s -o - | \
13+
// RUN: FileCheck --check-prefixes=CHECK,CHECK-RT-INIT,304 %s
14+
// RUN: %clang_cc1 -triple powerpc64-ibm-aix -emit-llvm -disable-red-zone -coverage-data-file=/dev/null -coverage-version='407*' %s -o - | \
15+
// RUN: FileCheck --check-prefixes=CHECK,CHECK-RT-INIT,407 %s
16+
// RUN: %clang_cc1 -triple powerpc64-ibm-aix -emit-llvm -disable-red-zone -coverage-data-file=/dev/null %s -o - | \
17+
// RUN: FileCheck --check-prefixes=CHECK,CHECK-RT-INIT,408 %s
1218

1319
// 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
1420

@@ -49,10 +55,13 @@ int test2(int b) {
4955
/// 0x3430382a '4' '0' '8' '*'
5056
// 408-SAME: i32 875575338
5157

58+
// Check for gcov initialization function pointers.
59+
// CHECK-RT-INIT: @__llvm_covinit_functions = private constant { ptr, ptr } { ptr @__llvm_gcov_writeout, ptr @__llvm_gcov_reset }, section "__llvm_covinit"
60+
5261
// Check that the noredzone flag is set on the generated functions.
5362

5463
// CHECK: void @__llvm_gcov_writeout() unnamed_addr [[NRZ:#[0-9]+]]
55-
// CHECK: void @__llvm_gcov_init() unnamed_addr [[NRZ]]
64+
// CHECK-CTOR-INIT: void @__llvm_gcov_init() unnamed_addr [[NRZ]]
5665

5766
// CHECK: attributes [[NRZ]] = { {{.*}}noredzone{{.*}} }
5867

compiler-rt/include/profile/InstrProfData.inc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,18 @@ COVMAP_HEADER(uint32_t, Int32Ty, Version, \
303303
#undef COVMAP_HEADER
304304
/* COVMAP_HEADER end. */
305305

306+
/* COVINIT_FUNC start */
307+
#ifndef COVINIT_FUNC
308+
#define COVINIT_FUNC(Type, LLVMType, Name, Initializer)
309+
#else
310+
#define INSTR_PROF_DATA_DEFINED
311+
#endif
312+
COVINIT_FUNC(IntPtrT, llvm::PointerType::getUnqual(Ctx), WriteoutFunction, \
313+
WriteoutF)
314+
COVINIT_FUNC(IntPtrT, llvm::PointerType::getUnqual(Ctx), ResetFunction, \
315+
ResetF)
316+
#undef COVINIT_FUNC
317+
/* COVINIT_FUNC end */
306318

307319
#ifdef INSTR_PROF_SECT_ENTRY
308320
#define INSTR_PROF_DATA_DEFINED
@@ -345,6 +357,9 @@ INSTR_PROF_SECT_ENTRY(IPSK_covdata, \
345357
INSTR_PROF_SECT_ENTRY(IPSK_covname, \
346358
INSTR_PROF_QUOTE(INSTR_PROF_COVNAME_COMMON), \
347359
INSTR_PROF_COVNAME_COFF, "__LLVM_COV,")
360+
INSTR_PROF_SECT_ENTRY(IPSK_covinit, \
361+
INSTR_PROF_QUOTE(INSTR_PROF_COVINIT_COMMON), \
362+
INSTR_PROF_COVINIT_COFF, "__LLVM_COV,")
348363

349364
#undef INSTR_PROF_SECT_ENTRY
350365
#endif
@@ -761,6 +776,8 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
761776
#define INSTR_PROF_COVDATA_COMMON __llvm_covdata
762777
#define INSTR_PROF_COVNAME_COMMON __llvm_covnames
763778
#define INSTR_PROF_ORDERFILE_COMMON __llvm_orderfile
779+
#define INSTR_PROF_COVINIT_COMMON __llvm_covinit
780+
764781
/* Windows section names. Because these section names contain dollar characters,
765782
* they must be quoted.
766783
*/
@@ -781,6 +798,10 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
781798
#define INSTR_PROF_COVNAME_COFF ".lcovn"
782799
#define INSTR_PROF_ORDERFILE_COFF ".lorderfile$M"
783800

801+
// FIXME: Placeholder for Windows. Windows currently does not initialize
802+
// the GCOV functions in the runtime.
803+
#define INSTR_PROF_COVINIT_COFF ".lcovd$M"
804+
784805
#ifdef _WIN32
785806
/* Runtime section names and name strings. */
786807
#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COFF
@@ -800,6 +821,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
800821
#define INSTR_PROF_COVDATA_SECT_NAME INSTR_PROF_COVDATA_COFF
801822
#define INSTR_PROF_COVNAME_SECT_NAME INSTR_PROF_COVNAME_COFF
802823
#define INSTR_PROF_ORDERFILE_SECT_NAME INSTR_PROF_ORDERFILE_COFF
824+
#define INSTR_PROF_COVINIT_SECT_NAME INSTR_PROF_COVINIT_COFF
803825
#else
804826
/* Runtime section names and name strings. */
805827
#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON)
@@ -821,6 +843,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
821843
/* Order file instrumentation. */
822844
#define INSTR_PROF_ORDERFILE_SECT_NAME \
823845
INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON)
846+
#define INSTR_PROF_COVINIT_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVINIT_COMMON)
824847
#endif
825848

826849
#define INSTR_PROF_ORDERFILE_BUFFER_NAME _llvm_order_file_buffer

compiler-rt/lib/profile/GCDAProfiling.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,25 @@ void llvm_gcov_init(fn_ptr wfn, fn_ptr rfn) {
624624
}
625625
}
626626

627+
#if defined(_AIX)
628+
COMPILER_RT_VISIBILITY __attribute__((constructor)) void
629+
__llvm_profile_gcov_initialize() {
630+
const __llvm_gcov_init_func_struct *InitFuncStart =
631+
__llvm_profile_begin_covinit();
632+
const __llvm_gcov_init_func_struct *InitFuncEnd =
633+
__llvm_profile_end_covinit();
634+
635+
for (const __llvm_gcov_init_func_struct *Ptr = InitFuncStart;
636+
Ptr != InitFuncEnd; ++Ptr) {
637+
fn_ptr wfn = (fn_ptr)Ptr->WriteoutFunction;
638+
fn_ptr rfn = (fn_ptr)Ptr->ResetFunction;
639+
if (!(wfn && rfn))
640+
continue;
641+
llvm_gcov_init(wfn, rfn);
642+
}
643+
}
644+
#endif
645+
627646
void __gcov_dump(void) {
628647
for (struct fn_node *f = writeout_fn_list.head; f; f = f->next)
629648
f->fn();

compiler-rt/lib/profile/InstrProfiling.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ typedef struct COMPILER_RT_ALIGNAS(INSTR_PROF_DATA_ALIGNMENT) VTableProfData {
5454
#include "profile/InstrProfData.inc"
5555
} VTableProfData;
5656

57+
typedef struct COMPILER_RT_ALIGNAS(INSTR_PROF_DATA_ALIGNMENT)
58+
__llvm_gcov_init_func_struct {
59+
#define COVINIT_FUNC(Type, LLVMType, Name, Initializer) Type Name;
60+
#include "profile/InstrProfData.inc"
61+
} __llvm_gcov_init_func_struct;
62+
5763
/*!
5864
* \brief Return 1 if profile counters are continuously synced to the raw
5965
* profile via an mmap(). This is in contrast to the default mode, in which
@@ -208,6 +214,9 @@ void __llvm_profile_initialize_file(void);
208214
/*! \brief Initialize the profile runtime. */
209215
void __llvm_profile_initialize(void);
210216

217+
/*! \brief Initialize the gcov profile runtime. */
218+
void __llvm_profile_gcov_initialize(void);
219+
211220
/*!
212221
* \brief Return path prefix (excluding the base filename) of the profile data.
213222
* This is useful for users using \c -fprofile-generate=./path_prefix who do
@@ -324,4 +333,6 @@ COMPILER_RT_VISIBILITY extern uint64_t
324333
*/
325334
extern char INSTR_PROF_PROFILE_NAME_VAR[1]; /* __llvm_profile_filename. */
326335

336+
const __llvm_gcov_init_func_struct *__llvm_profile_begin_covinit();
337+
const __llvm_gcov_init_func_struct *__llvm_profile_end_covinit();
327338
#endif /* PROFILE_INSTRPROFILING_H_ */

compiler-rt/lib/profile/InstrProfilingPlatformAIX.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ static int dummy_vname[0] COMPILER_RT_SECTION(
202202
COMPILER_RT_SEG INSTR_PROF_VNAME_SECT_NAME);
203203
static int dummy_vtab[0] COMPILER_RT_SECTION(
204204
COMPILER_RT_SEG INSTR_PROF_VTAB_SECT_NAME);
205+
static int dummy_covinit_funcs[0] COMPILER_RT_SECTION(
206+
COMPILER_RT_SEG INSTR_PROF_COVINIT_SECT_NAME);
205207

206208
// To avoid GC'ing of the dummy variables by the linker, reference them in an
207209
// array and reference the array in the runtime registration code
@@ -214,7 +216,8 @@ COMPILER_RT_VISIBILITY
214216
void *__llvm_profile_keep[] = {(void *)&dummy_cnts, (void *)&dummy_bits,
215217
(void *)&dummy_data, (void *)&dummy_name,
216218
(void *)&dummy_vnds, (void *)&dummy_orderfile,
217-
(void *)&dummy_vname, (void *)&dummy_vtab};
219+
(void *)&dummy_vname, (void *)&dummy_vtab,
220+
(void *)&dummy_covinit_funcs};
218221
#ifdef __GNUC__
219222
#pragma GCC diagnostic pop
220223
#endif

compiler-rt/lib/profile/InstrProfilingPlatformLinux.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
#define PROF_ORDERFILE_START INSTR_PROF_SECT_START(INSTR_PROF_ORDERFILE_COMMON)
3636
#define PROF_VNODES_START INSTR_PROF_SECT_START(INSTR_PROF_VNODES_COMMON)
3737
#define PROF_VNODES_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_VNODES_COMMON)
38+
#define PROF_COVINIT_START INSTR_PROF_SECT_START(INSTR_PROF_COVINIT_COMMON)
39+
#define PROF_COVINIT_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_COVINIT_COMMON)
3840

3941
/* Declare section start and stop symbols for various sections
4042
* generated by compiler instrumentation.
@@ -56,6 +58,10 @@ extern char PROF_NAME_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
5658
extern char PROF_NAME_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
5759
extern ValueProfNode PROF_VNODES_START COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
5860
extern ValueProfNode PROF_VNODES_STOP COMPILER_RT_VISIBILITY COMPILER_RT_WEAK;
61+
extern __llvm_gcov_init_func_struct PROF_COVINIT_START COMPILER_RT_VISIBILITY
62+
COMPILER_RT_WEAK;
63+
extern __llvm_gcov_init_func_struct PROF_COVINIT_STOP COMPILER_RT_VISIBILITY
64+
COMPILER_RT_WEAK;
5965

6066
COMPILER_RT_VISIBILITY const __llvm_profile_data *
6167
__llvm_profile_begin_data(void) {
@@ -110,6 +116,16 @@ COMPILER_RT_VISIBILITY ValueProfNode *__llvm_profile_end_vnodes(void) {
110116
COMPILER_RT_VISIBILITY ValueProfNode *CurrentVNode = &PROF_VNODES_START;
111117
COMPILER_RT_VISIBILITY ValueProfNode *EndVNode = &PROF_VNODES_STOP;
112118

119+
COMPILER_RT_VISIBILITY const __llvm_gcov_init_func_struct *
120+
__llvm_profile_begin_covinit() {
121+
return &PROF_COVINIT_START;
122+
}
123+
124+
COMPILER_RT_VISIBILITY const __llvm_gcov_init_func_struct *
125+
__llvm_profile_end_covinit() {
126+
return &PROF_COVINIT_STOP;
127+
}
128+
113129
#ifdef NT_GNU_BUILD_ID
114130
static size_t RoundUp(size_t size, size_t align) {
115131
return (size + align - 1) & ~(align - 1);
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// The undefined symbol should not cause link errors, and we should
2+
// obtain the expected coverage report.
3+
4+
// Test the --coverage option.
5+
RUN: rm -rf %t0 && split-file %s %t0 && cd %t0
6+
RUN: %clang bar.c main.c undef.c --coverage -c
7+
RUN: ar -X32_64 -rv libfoo.a undef.o bar.o
8+
RUN: %clang main.o -L. -lfoo --coverage -o main.exe
9+
RUN: %run ./main.exe
10+
RUN: llvm-cov gcov -t main.gcda | FileCheck --check-prefix=MAIN %s
11+
RUN: llvm-cov gcov -t bar.gcda | FileCheck --check-prefix=BAR %s
12+
13+
// Test the pgogen -fprofile-arcs -ftest-coverage option combination.
14+
RUN: rm -rf %t1 && split-file %s %t1 && cd %t1
15+
RUN: %clang_pgogen bar.c main.c undef.c -fprofile-arcs -ftest-coverage -c
16+
RUN: ar -X32_64 -rv libfoo.a undef.o bar.o
17+
RUN: %clang_pgogen main.o -L. -lfoo -fprofile-generate -fprofile-arcs -ftest-coverage -o main.exe
18+
RUN: %run ./main.exe
19+
RUN: llvm-cov gcov -t main.gcda | FileCheck --check-prefix=MAIN %s
20+
RUN: llvm-cov gcov -t bar.gcda | FileCheck --check-prefix=BAR %s
21+
22+
// Test the pgogen -Wl,-bcdtors:mbr option combination.
23+
RUN: rm -rf %t2 && split-file %s %t2 && cd %t2
24+
RUN: %clang_pgogen bar.c main.c undef.c -fprofile-arcs -ftest-coverage -c
25+
RUN: ar -X32_64 -rv libfoo.a undef.o bar.o
26+
RUN: %clang_pgogen main.o -L. -lfoo -fprofile-generate -fprofile-arcs -ftest-coverage -Wl,-bcdtors:mbr -o main.exe
27+
RUN: %run ./main.exe
28+
RUN: llvm-cov gcov -t main.gcda | FileCheck --check-prefix=MAIN %s
29+
RUN: llvm-cov gcov -t bar.gcda | FileCheck --check-prefix=BAR %s
30+
31+
MAIN: 1: 2:int main() {
32+
MAIN: 1: 3: return bar();
33+
BAR: 1: 1:int bar() {
34+
BAR: 1: 2: return 0;
35+
36+
//--- main.c
37+
int bar();
38+
int main() {
39+
return bar();
40+
}
41+
42+
43+
//--- bar.c
44+
int bar() {
45+
return 0;
46+
}
47+
48+
//--- undef.c
49+
void undef_func();
50+
void foo() {
51+
undef_func();
52+
}

llvm/include/llvm/ProfileData/InstrProfData.inc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,18 @@ COVMAP_HEADER(uint32_t, Int32Ty, Version, \
303303
#undef COVMAP_HEADER
304304
/* COVMAP_HEADER end. */
305305

306+
/* COVINIT_FUNC start */
307+
#ifndef COVINIT_FUNC
308+
#define COVINIT_FUNC(Type, LLVMType, Name, Initializer)
309+
#else
310+
#define INSTR_PROF_DATA_DEFINED
311+
#endif
312+
COVINIT_FUNC(IntPtrT, llvm::PointerType::getUnqual(Ctx), WriteoutFunction, \
313+
WriteoutF)
314+
COVINIT_FUNC(IntPtrT, llvm::PointerType::getUnqual(Ctx), ResetFunction, \
315+
ResetF)
316+
#undef COVINIT_FUNC
317+
/* COVINIT_FUNC end */
306318

307319
#ifdef INSTR_PROF_SECT_ENTRY
308320
#define INSTR_PROF_DATA_DEFINED
@@ -345,6 +357,9 @@ INSTR_PROF_SECT_ENTRY(IPSK_covdata, \
345357
INSTR_PROF_SECT_ENTRY(IPSK_covname, \
346358
INSTR_PROF_QUOTE(INSTR_PROF_COVNAME_COMMON), \
347359
INSTR_PROF_COVNAME_COFF, "__LLVM_COV,")
360+
INSTR_PROF_SECT_ENTRY(IPSK_covinit, \
361+
INSTR_PROF_QUOTE(INSTR_PROF_COVINIT_COMMON), \
362+
INSTR_PROF_COVINIT_COFF, "__LLVM_COV,")
348363

349364
#undef INSTR_PROF_SECT_ENTRY
350365
#endif
@@ -761,6 +776,8 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
761776
#define INSTR_PROF_COVDATA_COMMON __llvm_covdata
762777
#define INSTR_PROF_COVNAME_COMMON __llvm_covnames
763778
#define INSTR_PROF_ORDERFILE_COMMON __llvm_orderfile
779+
#define INSTR_PROF_COVINIT_COMMON __llvm_covinit
780+
764781
/* Windows section names. Because these section names contain dollar characters,
765782
* they must be quoted.
766783
*/
@@ -781,6 +798,10 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
781798
#define INSTR_PROF_COVNAME_COFF ".lcovn"
782799
#define INSTR_PROF_ORDERFILE_COFF ".lorderfile$M"
783800

801+
// FIXME: Placeholder for Windows. Windows currently does not initialize
802+
// the GCOV functions in the runtime.
803+
#define INSTR_PROF_COVINIT_COFF ".lcovd$M"
804+
784805
#ifdef _WIN32
785806
/* Runtime section names and name strings. */
786807
#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COFF
@@ -800,6 +821,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
800821
#define INSTR_PROF_COVDATA_SECT_NAME INSTR_PROF_COVDATA_COFF
801822
#define INSTR_PROF_COVNAME_SECT_NAME INSTR_PROF_COVNAME_COFF
802823
#define INSTR_PROF_ORDERFILE_SECT_NAME INSTR_PROF_ORDERFILE_COFF
824+
#define INSTR_PROF_COVINIT_SECT_NAME INSTR_PROF_COVINIT_COFF
803825
#else
804826
/* Runtime section names and name strings. */
805827
#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON)
@@ -821,6 +843,7 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
821843
/* Order file instrumentation. */
822844
#define INSTR_PROF_ORDERFILE_SECT_NAME \
823845
INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON)
846+
#define INSTR_PROF_COVINIT_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVINIT_COMMON)
824847
#endif
825848

826849
#define INSTR_PROF_ORDERFILE_BUFFER_NAME _llvm_order_file_buffer

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,8 @@ class PPCAIXAsmPrinter : public PPCAsmPrinter {
290290

291291
void emitPGORefs(Module &M);
292292

293+
void emitGCOVRefs();
294+
293295
void emitEndOfAsmFile(Module &) override;
294296

295297
void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const override;
@@ -2962,13 +2964,39 @@ void PPCAIXAsmPrinter::emitPGORefs(Module &M) {
29622964
}
29632965
}
29642966

2967+
void PPCAIXAsmPrinter::emitGCOVRefs() {
2968+
if (!OutContext.hasXCOFFSection(
2969+
"__llvm_gcov_ctr_section",
2970+
XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))
2971+
return;
2972+
2973+
MCSection *CtrSection = OutContext.getXCOFFSection(
2974+
"__llvm_gcov_ctr_section", SectionKind::getData(),
2975+
XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD),
2976+
/*MultiSymbolsAllowed*/ true);
2977+
2978+
OutStreamer->switchSection(CtrSection);
2979+
const XCOFF::StorageMappingClass MappingClass =
2980+
TM.Options.XCOFFReadOnlyPointers ? XCOFF::XMC_RO : XCOFF::XMC_RW;
2981+
if (OutContext.hasXCOFFSection(
2982+
"__llvm_covinit",
2983+
XCOFF::CsectProperties(MappingClass, XCOFF::XTY_SD))) {
2984+
const char *SymbolStr = TM.Options.XCOFFReadOnlyPointers
2985+
? "__llvm_covinit[RO]"
2986+
: "__llvm_covinit[RW]";
2987+
MCSymbol *S = OutContext.getOrCreateSymbol(SymbolStr);
2988+
OutStreamer->emitXCOFFRefDirective(S);
2989+
}
2990+
}
2991+
29652992
void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
29662993
// If there are no functions and there are no toc-data definitions in this
29672994
// module, we will never need to reference the TOC base.
29682995
if (M.empty() && TOCDataGlobalVars.empty())
29692996
return;
29702997

29712998
emitPGORefs(M);
2999+
emitGCOVRefs();
29723000

29733001
// Switch to section to emit TOC base.
29743002
OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());

0 commit comments

Comments
 (0)