From 25544ce2df0daa4304c07e64b9c8b0f7df60c11d Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 10 May 2020 12:47:45 -0700 Subject: [PATCH] [gcov] Default coverage version to '407*' and delete CC1 option -coverage-cfg-checksum Defaulting to -Xclang -coverage-version='407*' makes .gcno/.gcda compatible with gcov [4.7,8) In addition, delete clang::CodeGenOptionsBase::CoverageExtraChecksum and GCOVOptions::UseCfgChecksum. We can infer the information from the version. With this change, .gcda files produced by `clang --coverage a.o` linked executable can be read by gcov 4.7~7. We don't need other -Xclang -coverage* options. There may be a mismatching version warning, though. (Note, GCC r173147 "split checksum into cfg checksum and line checksum" made gcov 4.7 incompatible with previous versions.) --- clang/include/clang/Basic/CodeGenOptions.def | 1 - clang/include/clang/Driver/CC1Options.td | 2 -- clang/lib/Basic/CodeGenOptions.cpp | 2 +- clang/lib/CodeGen/BackendUtil.cpp | 1 - clang/lib/Frontend/CompilerInvocation.cpp | 1 - clang/test/CodeGen/code-coverage.c | 15 +++++++++-- compiler-rt/lib/profile/GCDAProfiling.c | 15 ++++++++++- llvm/include/llvm/Transforms/Instrumentation.h | 4 --- .../Transforms/Instrumentation/GCOVProfiling.cpp | 30 ++++++++-------------- .../Transforms/GCOVProfiling/function-numbering.ll | 7 ++--- llvm/test/Transforms/GCOVProfiling/version.ll | 12 ++++----- 11 files changed, 47 insertions(+), 43 deletions(-) diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index caf652a..61982da 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -39,7 +39,6 @@ CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe CODEGENOPT(Backchain , 1, 0) ///< -mbackchain CODEGENOPT(ControlFlowGuardNoChecks , 1, 0) ///< -cfguard-no-checks CODEGENOPT(ControlFlowGuard , 1, 0) ///< -cfguard -CODEGENOPT(CoverageExtraChecksum, 1, 0) ///< Whether we need a second checksum for functions in GCNO files. CODEGENOPT(CoverageExitBlockBeforeBody, 1, 0) ///< Whether to emit the exit block before the body blocks in GCNO files. CODEGENOPT(CXAAtExit , 1, 1) ///< Use __cxa_atexit for calling destructors. CODEGENOPT(RegisterGlobalDtorsWithAtExit, 1, 1) ///< Use atexit or __cxa_atexit to register global destructors. diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 7d04d80..85407ce 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -262,8 +262,6 @@ def coverage_notes_file : Separate<["-"], "coverage-notes-file">, HelpText<"Emit coverage notes to this filename.">; def coverage_notes_file_EQ : Joined<["-"], "coverage-notes-file=">, Alias; -def coverage_cfg_checksum : Flag<["-"], "coverage-cfg-checksum">, - HelpText<"Emit CFG checksum for functions in .gcno files.">; def coverage_exit_block_before_body : Flag<["-"], "coverage-exit-block-before-body">, HelpText<"Emit the exit block before the body blocks in .gcno files.">; def coverage_version_EQ : Joined<["-"], "coverage-version=">, diff --git a/clang/lib/Basic/CodeGenOptions.cpp b/clang/lib/Basic/CodeGenOptions.cpp index fa18638..8d3aeda 100644 --- a/clang/lib/Basic/CodeGenOptions.cpp +++ b/clang/lib/Basic/CodeGenOptions.cpp @@ -17,7 +17,7 @@ CodeGenOptions::CodeGenOptions() { #include "clang/Basic/CodeGenOptions.def" RelocationModel = llvm::Reloc::PIC_; - memcpy(CoverageVersion, "402*", 4); + memcpy(CoverageVersion, "407*", 4); } bool CodeGenOptions::isNoBuiltinFunc(const char *Name) const { diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 0c31bc0..ba4b48d 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -530,7 +530,6 @@ static Optional getGCOVOptions(const CodeGenOptions &CodeGenOpts) { Options.EmitNotes = CodeGenOpts.EmitGcovNotes; Options.EmitData = CodeGenOpts.EmitGcovArcs; llvm::copy(CodeGenOpts.CoverageVersion, std::begin(Options.Version)); - Options.UseCfgChecksum = CodeGenOpts.CoverageExtraChecksum; Options.NoRedZone = CodeGenOpts.DisableRedZone; Options.Filter = CodeGenOpts.ProfileFilterFiles; Options.Exclude = CodeGenOpts.ProfileExcludeFiles; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 6a358f2..e3a57d6 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1017,7 +1017,6 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, std::string(Args.getLastArgValue(OPT_coverage_data_file)); Opts.CoverageNotesFile = std::string(Args.getLastArgValue(OPT_coverage_notes_file)); - Opts.CoverageExtraChecksum = Args.hasArg(OPT_coverage_cfg_checksum); Opts.ProfileFilterFiles = std::string(Args.getLastArgValue(OPT_fprofile_filter_files_EQ)); Opts.ProfileExcludeFiles = diff --git a/clang/test/CodeGen/code-coverage.c b/clang/test/CodeGen/code-coverage.c index c93624a..5c73760 100644 --- a/clang/test/CodeGen/code-coverage.c +++ b/clang/test/CodeGen/code-coverage.c @@ -1,4 +1,12 @@ -// RUN: %clang_cc1 -emit-llvm -disable-red-zone -femit-coverage-data %s -o - | FileCheck %s +/// We support coverage versions 4.2 and 4.7. +/// 4.7 (default, compatible with gcov 7) enables cfg_checksum. +// RUN: %clang_cc1 -emit-llvm -disable-red-zone -femit-coverage-data -coverage-version='402*' %s -o - | \ +// RUN: FileCheck --check-prefixes=CHECK,402 %s +// RUN: %clang_cc1 -emit-llvm -disable-red-zone -femit-coverage-data -coverage-version='407*' %s -o - | \ +// RUN: FileCheck --check-prefixes=CHECK,407 %s +// RUN: %clang_cc1 -emit-llvm -disable-red-zone -femit-coverage-data %s -o - | \ +// RUN: FileCheck --check-prefixes=CHECK,407 %s + // RUN: %clang_cc1 -emit-llvm -disable-red-zone -femit-coverage-data -coverage-notes-file=aaa.gcno -coverage-data-file=bbb.gcda -dwarf-column-info -debug-info-kind=limited -dwarf-version=4 %s -o - | FileCheck %s --check-prefix GCOV_FILE_INFO // RUN: %clang_cc1 -emit-llvm-bc -o /dev/null -fexperimental-new-pass-manager -fdebug-pass-manager -femit-coverage-data %s 2>&1 | FileCheck --check-prefix=NEWPM %s @@ -26,8 +34,11 @@ int test2(int b) { return b * 2; } +// 402: private unnamed_addr constant [5 x i8] c"*204\00" +// 407: private unnamed_addr constant [5 x i8] c"*704\00" + // CHECK: @__llvm_internal_gcov_emit_function_args.0 = internal unnamed_addr constant [2 x %0] -// CHECK-SAME: [%0 zeroinitializer, %0 { i32 1, i32 0, i8 0, i32 0 }] +// CHECK-SAME: [%0 zeroinitializer, %0 { i32 1, i32 0, i32 0 }] // Check that the noredzone flag is set on the generated functions. diff --git a/compiler-rt/lib/profile/GCDAProfiling.c b/compiler-rt/lib/profile/GCDAProfiling.c index 401969b..6833609 100644 --- a/compiler-rt/lib/profile/GCDAProfiling.c +++ b/compiler-rt/lib/profile/GCDAProfiling.c @@ -89,6 +89,7 @@ static uint64_t cur_buffer_size = 0; static uint64_t cur_pos = 0; static uint64_t file_size = 0; static int new_file = 0; +static int gcov_version; #if defined(_WIN32) static HANDLE mmap_handle = NULL; #endif @@ -414,6 +415,18 @@ void llvm_gcda_start_file(const char *orig_filename, const char version[4], } /* gcda file, version, stamp checksum. */ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + gcov_version = version[3] >= 'A' + ? (version[3] - 'A') * 100 + (version[2] - '0') * 10 + + version[1] - '0' + : (version[3] - '0') * 10 + version[1] - '0'; +#else + gcov_version = version[0] >= 'A' + ? (version[0] - 'A') * 100 + (version[1] - '0') * 10 + + version[2] - '0' + : (version[0] - '0') * 10 + version[2] - '0'; +#endif + write_bytes("adcg", 4); write_bytes(version, 4); write_32bit_value(checksum); @@ -451,9 +464,9 @@ void llvm_gcda_increment_indirect_counter(uint32_t *predecessor, COMPILER_RT_VISIBILITY void llvm_gcda_emit_function(uint32_t ident, uint32_t func_checksum, - uint8_t use_extra_checksum, uint32_t cfg_checksum) { uint32_t len = 2; + int use_extra_checksum = gcov_version >= 47; if (use_extra_checksum) len++; diff --git a/llvm/include/llvm/Transforms/Instrumentation.h b/llvm/include/llvm/Transforms/Instrumentation.h index bedd6f1..6f594d7 100644 --- a/llvm/include/llvm/Transforms/Instrumentation.h +++ b/llvm/include/llvm/Transforms/Instrumentation.h @@ -63,10 +63,6 @@ struct GCOVOptions { // gcc's gcov-io.h char Version[4]; - // Emit a "cfg checksum" that follows the "line number checksum" of a - // function. This affects both .gcno and .gcda files. - bool UseCfgChecksum; - // Add the 'noredzone' attribute to added runtime library calls. bool NoRedZone; diff --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp index 0df316e..cad1071 100644 --- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -49,9 +49,9 @@ using namespace llvm; #define DEBUG_TYPE "insert-gcov-profiling" -static cl::opt -DefaultGCOVVersion("default-gcov-version", cl::init("402*"), cl::Hidden, - cl::ValueRequired); +static cl::opt DefaultGCOVVersion("default-gcov-version", + cl::init("407*"), cl::Hidden, + cl::ValueRequired); static cl::opt DefaultExitBlockBeforeBody("gcov-exit-block-before-body", cl::init(false), cl::Hidden); @@ -59,7 +59,6 @@ GCOVOptions GCOVOptions::getDefault() { GCOVOptions Options; Options.EmitNotes = true; Options.EmitData = true; - Options.UseCfgChecksum = false; Options.NoRedZone = false; Options.ExitBlockBeforeBody = DefaultExitBlockBeforeBody; @@ -747,9 +746,10 @@ void GCOVProfiler::emitProfileNotes() { ++It; EntryBlock.splitBasicBlock(It); - Funcs.push_back(std::make_unique(SP, &F, &out, FunctionIdent++, - Options.UseCfgChecksum, - Options.ExitBlockBeforeBody)); + bool UseCfgChecksum = strncmp(Options.Version, "407", 3) >= 0; + Funcs.push_back(std::make_unique( + SP, &F, &out, FunctionIdent++, UseCfgChecksum, + Options.ExitBlockBeforeBody)); GCOVFunction &Func = *Funcs.back(); // Add the function line number to the lines of the entry block @@ -945,16 +945,14 @@ FunctionCallee GCOVProfiler::getEmitFunctionFunc(const TargetLibraryInfo *TLI) { Type *Args[] = { Type::getInt32Ty(*Ctx), // uint32_t ident Type::getInt32Ty(*Ctx), // uint32_t func_checksum - Type::getInt8Ty(*Ctx), // uint8_t use_extra_checksum Type::getInt32Ty(*Ctx), // uint32_t cfg_checksum }; FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false); AttributeList AL; if (auto AK = TLI->getExtAttrForI32Param(false)) { AL = AL.addParamAttribute(*Ctx, 0, AK); + AL = AL.addParamAttribute(*Ctx, 1, AK); AL = AL.addParamAttribute(*Ctx, 2, AK); - AL = AL.addParamAttribute(*Ctx, 3, AK); - AL = AL.addParamAttribute(*Ctx, 4, AK); } return M->getOrInsertFunction("llvm_gcda_emit_function", FTy); } @@ -1014,9 +1012,8 @@ Function *GCOVProfiler::insertCounterWriteout( // walk to write out everything. StructType *StartFileCallArgsTy = StructType::create( {Builder.getInt8PtrTy(), Builder.getInt8PtrTy(), Builder.getInt32Ty()}); - StructType *EmitFunctionCallArgsTy = - StructType::create({Builder.getInt32Ty(), Builder.getInt32Ty(), - Builder.getInt8Ty(), Builder.getInt32Ty()}); + StructType *EmitFunctionCallArgsTy = StructType::create( + {Builder.getInt32Ty(), Builder.getInt32Ty(), Builder.getInt32Ty()}); StructType *EmitArcsCallArgsTy = StructType::create( {Builder.getInt32Ty(), Builder.getInt64Ty()->getPointerTo()}); StructType *FileInfoTy = @@ -1051,7 +1048,6 @@ Function *GCOVProfiler::insertCounterWriteout( EmitFunctionCallArgsTy, {Builder.getInt32(j), Builder.getInt32(FuncChecksum), - Builder.getInt8(Options.UseCfgChecksum), Builder.getInt32(CfgChecksum)})); GlobalVariable *GV = CountersBySP[j].first; @@ -1180,16 +1176,12 @@ Function *GCOVProfiler::insertCounterWriteout( EmitFunctionCallArgsPtr, 1)), Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(2), Builder.CreateStructGEP(EmitFunctionCallArgsTy, - EmitFunctionCallArgsPtr, 2)), - Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(3), - Builder.CreateStructGEP(EmitFunctionCallArgsTy, EmitFunctionCallArgsPtr, - 3))}); + 2))}); if (auto AK = TLI->getExtAttrForI32Param(false)) { EmitFunctionCall->addParamAttr(0, AK); EmitFunctionCall->addParamAttr(1, AK); EmitFunctionCall->addParamAttr(2, AK); - EmitFunctionCall->addParamAttr(3, AK); } auto *EmitArcsCallArgsPtr = Builder.CreateInBoundsGEP(EmitArcsCallArgsTy, EmitArcsCallArgsArray, JV); diff --git a/llvm/test/Transforms/GCOVProfiling/function-numbering.ll b/llvm/test/Transforms/GCOVProfiling/function-numbering.ll index dfaacc8..973b29f 100644 --- a/llvm/test/Transforms/GCOVProfiling/function-numbering.ll +++ b/llvm/test/Transforms/GCOVProfiling/function-numbering.ll @@ -52,13 +52,10 @@ target triple = "x86_64-apple-macosx10.10.0" ; GCDA-NEXT: %[[EMIT_FUN_ARG_1_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_FUN_ARGS]], i32 0, i32 1 ; GCDA-NEXT: %[[EMIT_FUN_ARG_1:.*]] = load i32, i32* %[[EMIT_FUN_ARG_1_PTR]] ; GCDA-NEXT: %[[EMIT_FUN_ARG_2_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_FUN_ARGS]], i32 0, i32 2 -; GCDA-NEXT: %[[EMIT_FUN_ARG_2:.*]] = load i8, i8* %[[EMIT_FUN_ARG_2_PTR]] -; GCDA-NEXT: %[[EMIT_FUN_ARG_3_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_FUN_ARGS]], i32 0, i32 3 -; GCDA-NEXT: %[[EMIT_FUN_ARG_3:.*]] = load i32, i32* %[[EMIT_FUN_ARG_3_PTR]] +; GCDA-NEXT: %[[EMIT_FUN_ARG_2:.*]] = load i32, i32* %[[EMIT_FUN_ARG_2_PTR]] ; GCDA-NEXT: call void @llvm_gcda_emit_function(i32 %[[EMIT_FUN_ARG_0]], ; GCDA-SAME: i32 %[[EMIT_FUN_ARG_1]], -; GCDA-SAME: i8 %[[EMIT_FUN_ARG_2]], -; GCDA-SAME: i32 %[[EMIT_FUN_ARG_3]]) +; GCDA-SAME: i32 %[[EMIT_FUN_ARG_2]]) ; GCDA-NEXT: %[[EMIT_ARCS_ARGS:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_ARCS_ARGS_ARRAY]], i32 %[[JV]] ; GCDA-NEXT: %[[EMIT_ARCS_ARG_0_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_ARCS_ARGS]], i32 0, i32 0 ; GCDA-NEXT: %[[EMIT_ARCS_ARG_0:.*]] = load i32, i32* %[[EMIT_ARCS_ARG_0_PTR]] diff --git a/llvm/test/Transforms/GCOVProfiling/version.ll b/llvm/test/Transforms/GCOVProfiling/version.ll index c72b642..c135803 100644 --- a/llvm/test/Transforms/GCOVProfiling/version.ll +++ b/llvm/test/Transforms/GCOVProfiling/version.ll @@ -2,19 +2,19 @@ ; RUN: echo '!9 = !{!"%/t/version.ll", !0}' > %t/1 ; RUN: cat %s %t/1 > %t/2 ; RUN: opt -insert-gcov-profiling -disable-output < %t/2 -; RUN: head -c8 %t/version.gcno | grep '^oncg.204' +; RUN: head -c8 %t/version.gcno | grep '^oncg.704' ; RUN: rm %t/version.gcno ; RUN: not --crash opt -insert-gcov-profiling -default-gcov-version=asdfasdf -disable-output < %t/2 -; RUN: opt -insert-gcov-profiling -default-gcov-version=407* -disable-output < %t/2 -; RUN: head -c8 %t/version.gcno | grep '^oncg.704' +; RUN: opt -insert-gcov-profiling -default-gcov-version='402*' -disable-output < %t/2 +; RUN: head -c8 %t/version.gcno | grep '^oncg.204' ; RUN: rm %t/version.gcno ; RUN: opt -passes=insert-gcov-profiling -disable-output < %t/2 -; RUN: head -c8 %t/version.gcno | grep '^oncg.204' +; RUN: head -c8 %t/version.gcno | grep '^oncg.704' ; RUN: rm %t/version.gcno ; RUN: not --crash opt -passes=insert-gcov-profiling -default-gcov-version=asdfasdf -disable-output < %t/2 -; RUN: opt -passes=insert-gcov-profiling -default-gcov-version=407* -disable-output < %t/2 -; RUN: head -c8 %t/version.gcno | grep '^oncg.704' +; RUN: opt -passes=insert-gcov-profiling -default-gcov-version='402*' -disable-output < %t/2 +; RUN: head -c8 %t/version.gcno | grep '^oncg.204' ; RUN: rm %t/version.gcno define void @test() !dbg !5 { -- 2.7.4