Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/test/CodeGen/attr-function-return.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 16 additions & 7 deletions clang/test/CodeGen/code-coverage.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -49,10 +55,13 @@ 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]+]]
// CHECK: void @__llvm_gcov_init() unnamed_addr [[NRZ]]
// CHECK-ELF: void @__llvm_gcov_init() unnamed_addr [[NRZ]]

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

Expand Down
22 changes: 22 additions & 0 deletions compiler-rt/include/profile/InstrProfData.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
*/
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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
Expand Down
19 changes: 19 additions & 0 deletions compiler-rt/lib/profile/GCDAProfiling.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,25 @@ 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 =
__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);
}
}
#endif

void __gcov_dump(void) {
for (struct fn_node *f = writeout_fn_list.head; f; f = f->next)
f->fn();
Expand Down
11 changes: 11 additions & 0 deletions compiler-rt/lib/profile/InstrProfiling.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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_ */
5 changes: 4 additions & 1 deletion compiler-rt/lib/profile/InstrProfilingPlatformAIX.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
16 changes: 16 additions & 0 deletions compiler-rt/lib/profile/InstrProfilingPlatformLinux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
52 changes: 52 additions & 0 deletions compiler-rt/test/profile/AIX/gcov-undef-sym.test
Original file line number Diff line number Diff line change
@@ -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: %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: %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: %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();
}
22 changes: 22 additions & 0 deletions llvm/include/llvm/ProfileData/InstrProfData.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
*/
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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
Expand Down
23 changes: 23 additions & 0 deletions llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -2962,13 +2964,34 @@ 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.
if (M.empty() && TOCDataGlobalVars.empty())
return;

emitPGORefs(M);
emitGCOVRefs();

// Switch to section to emit TOC base.
OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());
Expand Down
Loading