};
}
+static void emitRuntimeHook(CodeGenModule &CGM) {
+ constexpr const char *RuntimeVarName = "__llvm_profile_runtime";
+ constexpr const char *RuntimeUserName = "__llvm_profile_runtime_user";
+ if (CGM.getModule().getGlobalVariable(RuntimeVarName))
+ return;
+
+ // Declare the runtime hook.
+ llvm::LLVMContext &Ctx = CGM.getLLVMContext();
+ auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
+ auto *Var = new llvm::GlobalVariable(CGM.getModule(), Int32Ty, false,
+ llvm::GlobalValue::ExternalLinkage,
+ nullptr, RuntimeVarName);
+
+ // Make a function that uses it.
+ auto *User = llvm::Function::Create(llvm::FunctionType::get(Int32Ty, false),
+ llvm::GlobalValue::LinkOnceODRLinkage,
+ RuntimeUserName, &CGM.getModule());
+ User->addFnAttr(llvm::Attribute::NoInline);
+ if (CGM.getCodeGenOpts().DisableRedZone)
+ User->addFnAttr(llvm::Attribute::NoRedZone);
+ CGBuilderTy Builder(llvm::BasicBlock::Create(CGM.getLLVMContext(), "", User));
+ auto *Load = Builder.CreateLoad(Var);
+ Builder.CreateRet(Load);
+
+ // Create a use of the function. Now the definition of the runtime variable
+ // should get pulled in, along with any static initializears.
+ CGM.addUsedGlobal(User);
+}
+
void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) {
bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate;
PGOProfileData *PGOData = CGM.getPGOData();
}
mapRegionCounters(D);
- if (InstrumentRegions)
+ if (InstrumentRegions) {
+ emitRuntimeHook(CGM);
emitCounterVariables();
+ }
if (PGOData) {
loadRegionCounts(PGOData);
computeRegionCounts(D);
Args.hasArg(options::OPT_fprofile_instr_generate) ||
Args.hasArg(options::OPT_fcreate_profile) ||
Args.hasArg(options::OPT_coverage)) {
- // Pull in runtime for -fprofile-inst-generate. This is required since
- // there are no calls to the runtime in the code.
- if (Args.hasArg(options::OPT_fprofile_instr_generate)) {
- CmdArgs.push_back("-u");
- CmdArgs.push_back("___llvm_profile_runtime");
- }
-
// Select the appropriate runtime library for the target.
if (isTargetIOSBased())
AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_ios.a");
Args.hasArg(options::OPT_coverage)))
return;
- // Pull in runtime for -fprofile-inst-generate. This is required since there
- // are no calls to the runtime in the code.
- if (Args.hasArg(options::OPT_fprofile_instr_generate)) {
- CmdArgs.push_back("-u");
- CmdArgs.push_back("___llvm_profile_runtime");
- }
-
SmallString<128> LibProfile = getCompilerRTLibDir(TC);
llvm::sys::path::append(LibProfile,
Twine("libclang_rt.profile-") + getArchNameForCompilerRTLib(TC) + ".a");
// Check the data structures emitted by instrumentation.
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-linkage.c %s -o - -emit-llvm -fprofile-instr-generate | FileCheck %s
+// CHECK: @__llvm_profile_runtime = external global i32
// CHECK: @__llvm_profile_counters_foo = global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
// CHECK: @__llvm_profile_name_foo = constant [3 x i8] c"foo", section "__DATA,__llvm_prf_names", align 1
// CHECK: @__llvm_profile_data_foo = constant { i32, i32, i64, i8*, i64* } { i32 3, i32 1, i64 1, i8* getelementptr inbounds ([3 x i8]* @__llvm_profile_name_foo, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters_foo, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
// CHECK: @__llvm_profile_data_foo_internal = internal constant { i32, i32, i64, i8*, i64* } { i32 24, i32 3, i64 3, i8* getelementptr inbounds ([24 x i8]* @__llvm_profile_name_foo_internal, i32 0, i32 0), i64* getelementptr inbounds ([3 x i64]* @__llvm_profile_counters_foo_internal, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
static void foo_internal(void) { if (0){} if (0){} }
-// CHECK: @llvm.used = appending global [4 x i8*] [i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo_weak to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo_internal to i8*)], section "llvm.metadata"
+// CHECK: @llvm.used = appending global [5 x i8*] [i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo_weak to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_foo_internal to i8*)], section "llvm.metadata"
+
+// CHECK: define linkonce_odr i32 @__llvm_profile_runtime_user() {{.*}} {
+// CHECK: %[[REG:.*]] = load i32* @__llvm_profile_runtime
+// CHECK: ret i32 %[[REG]]
+// CHECK: }
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9.0 -emit-llvm -main-file-name cxx-linkage.cpp %s -o - -fprofile-instr-generate | FileCheck %s
+// CHECK: @__llvm_profile_runtime = external global i32
// CHECK: @__llvm_profile_counters__Z3foov = global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8
// CHECK: @__llvm_profile_name__Z3foov = constant [7 x i8] c"_Z3foov", section "__DATA,__llvm_prf_names", align 1
// CHECK: @__llvm_profile_data__Z3foov = constant { i32, i32, i64, i8*, i64* } { i32 7, i32 1, i64 1, i8* getelementptr inbounds ([7 x i8]* @__llvm_profile_name__Z3foov, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64]* @__llvm_profile_counters__Z3foov, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
// CHECK: @__llvm_profile_data__Z10foo_inlinev = linkonce_odr constant { i32, i32, i64, i8*, i64* } { i32 15, i32 7, i64 7, i8* getelementptr inbounds ([15 x i8]* @__llvm_profile_name__Z10foo_inlinev, i32 0, i32 0), i64* getelementptr inbounds ([7 x i64]* @__llvm_profile_counters__Z10foo_inlinev, i32 0, i32 0) }, section "__DATA,__llvm_prf_data", align 8
inline void foo_inline(void) { if (0){} if (0){} if (0){} if (0){} if (0){} if (0){}}
-// CHECK: @llvm.used = appending global [4 x i8*] [i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z3foov to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z8foo_weakv to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z10foo_inlinev to i8*)], section "llvm.metadata"
+// CHECK: @llvm.used = appending global [5 x i8*] [i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z3foov to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z8foo_weakv to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data_main to i8*), i8* bitcast ({ i32, i32, i64, i8*, i64* }* @__llvm_profile_data__Z10foo_inlinev to i8*)], section "llvm.metadata"
+
+// CHECK: define linkonce_odr i32 @__llvm_profile_runtime_user() {{.*}} {
+// CHECK: %[[REG:.*]] = load i32* @__llvm_profile_runtime
+// CHECK: ret i32 %[[REG]]
+// CHECK: }