Register the flush function for each compile unit.

For each compile unit, we want to register a function that will flush that
compile unit. Otherwise, __gcov_flush() would only flush the counters within the
current compile unit, and not any outside of it.

PR15191 & <rdar://problem/13167507>


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177340 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bill Wendling 2013-03-18 23:04:39 +00:00
parent 4a8dbb7da3
commit d195eb6b83

View File

@ -101,6 +101,7 @@ namespace {
Constant *getIncrementIndirectCounterFunc(); Constant *getIncrementIndirectCounterFunc();
Constant *getEmitFunctionFunc(); Constant *getEmitFunctionFunc();
Constant *getEmitArcsFunc(); Constant *getEmitArcsFunc();
Constant *getDeleteFlushFunctionListFunc();
Constant *getEndFileFunc(); Constant *getEndFileFunc();
// Create or retrieve an i32 state value that is used to represent the // Create or retrieve an i32 state value that is used to represent the
@ -116,9 +117,10 @@ namespace {
// Add the function to write out all our counters to the global destructor // Add the function to write out all our counters to the global destructor
// list. // list.
void insertCounterWriteout(ArrayRef<std::pair<GlobalVariable*, MDNode*> >); Function *insertCounterWriteout(ArrayRef<std::pair<GlobalVariable*,
MDNode*> >);
Function *insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> >);
void insertIndirectCounterIncrement(); void insertIndirectCounterIncrement();
void insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> >);
std::string mangleName(DICompileUnit CU, const char *NewStem); std::string mangleName(DICompileUnit CU, const char *NewStem);
@ -538,8 +540,42 @@ bool GCOVProfiler::emitProfileArcs() {
} }
} }
insertCounterWriteout(CountersBySP); Function *WriteoutF = insertCounterWriteout(CountersBySP);
insertFlush(CountersBySP); Function *FlushF = insertFlush(CountersBySP);
// Create a small bit of code that registers the "__llvm_gcov_writeout" to
// be executed at exit and the "__llvm_gcov_flush" function to be executed
// when "__gcov_flush" is called.
FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
Function *F = Function::Create(FTy, GlobalValue::InternalLinkage,
"__llvm_gcov_init", M);
F->setUnnamedAddr(true);
F->setLinkage(GlobalValue::InternalLinkage);
F->addFnAttr(Attribute::NoInline);
if (Options.NoRedZone)
F->addFnAttr(Attribute::NoRedZone);
BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F);
IRBuilder<> Builder(BB);
FTy = FunctionType::get(Builder.getInt32Ty(),
PointerType::get(FTy, 0), false);
Constant *AtExitFn = M->getOrInsertFunction("atexit", FTy);
Builder.CreateCall(AtExitFn, WriteoutF);
// Register the local flush function.
FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
FTy = FunctionType::get(Builder.getVoidTy(),
PointerType::get(FTy, 0), false);
Constant *RegFlush =
M->getOrInsertFunction("llvm_register_flush_function", FTy);
Builder.CreateCall(RegFlush, FlushF);
// Make sure that all the flush function list is deleted.
Builder.CreateCall(AtExitFn, getDeleteFlushFunctionListFunc());
Builder.CreateRetVoid();
appendToGlobalCtors(*M, F, 0);
} }
if (InsertIndCounterIncrCode) if (InsertIndCounterIncrCode)
@ -635,6 +671,11 @@ Constant *GCOVProfiler::getEmitArcsFunc() {
return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy); return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy);
} }
Constant *GCOVProfiler::getDeleteFlushFunctionListFunc() {
FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
return M->getOrInsertFunction("llvm_delete_flush_function_list", FTy);
}
Constant *GCOVProfiler::getEndFileFunc() { Constant *GCOVProfiler::getEndFileFunc() {
FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
return M->getOrInsertFunction("llvm_gcda_end_file", FTy); return M->getOrInsertFunction("llvm_gcda_end_file", FTy);
@ -653,7 +694,7 @@ GlobalVariable *GCOVProfiler::getEdgeStateValue() {
return GV; return GV;
} }
void GCOVProfiler::insertCounterWriteout( Function *GCOVProfiler::insertCounterWriteout(
ArrayRef<std::pair<GlobalVariable *, MDNode *> > CountersBySP) { ArrayRef<std::pair<GlobalVariable *, MDNode *> > CountersBySP) {
FunctionType *WriteoutFTy = FunctionType::get(Type::getVoidTy(*Ctx), false); FunctionType *WriteoutFTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
Function *WriteoutF = M->getFunction("__llvm_gcov_writeout"); Function *WriteoutF = M->getFunction("__llvm_gcov_writeout");
@ -700,29 +741,9 @@ void GCOVProfiler::insertCounterWriteout(
Builder.CreateCall(EndFile); Builder.CreateCall(EndFile);
} }
} }
Builder.CreateRetVoid(); Builder.CreateRetVoid();
return WriteoutF;
// Create a small bit of code that registers the "__llvm_gcov_writeout"
// function to be executed at exit.
FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
Function *F = Function::Create(FTy, GlobalValue::InternalLinkage,
"__llvm_gcov_init", M);
F->setUnnamedAddr(true);
F->setLinkage(GlobalValue::InternalLinkage);
F->addFnAttr(Attribute::NoInline);
if (Options.NoRedZone)
F->addFnAttr(Attribute::NoRedZone);
BB = BasicBlock::Create(*Ctx, "entry", F);
Builder.SetInsertPoint(BB);
FTy = FunctionType::get(Builder.getInt32Ty(),
PointerType::get(FTy, 0), false);
Constant *AtExitFn = M->getOrInsertFunction("atexit", FTy);
Builder.CreateCall(AtExitFn, WriteoutF);
Builder.CreateRetVoid();
appendToGlobalCtors(*M, F, 0);
} }
void GCOVProfiler::insertIndirectCounterIncrement() { void GCOVProfiler::insertIndirectCounterIncrement() {
@ -776,13 +797,13 @@ void GCOVProfiler::insertIndirectCounterIncrement() {
Builder.CreateRetVoid(); Builder.CreateRetVoid();
} }
void GCOVProfiler:: Function *GCOVProfiler::
insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) { insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) {
FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
Function *FlushF = M->getFunction("__gcov_flush"); Function *FlushF = M->getFunction("__llvm_gcov_flush");
if (!FlushF) if (!FlushF)
FlushF = Function::Create(FTy, GlobalValue::InternalLinkage, FlushF = Function::Create(FTy, GlobalValue::InternalLinkage,
"__gcov_flush", M); "__llvm_gcov_flush", M);
else else
FlushF->setLinkage(GlobalValue::InternalLinkage); FlushF->setLinkage(GlobalValue::InternalLinkage);
FlushF->setUnnamedAddr(true); FlushF->setUnnamedAddr(true);
@ -812,8 +833,10 @@ insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) {
if (RetTy == Type::getVoidTy(*Ctx)) if (RetTy == Type::getVoidTy(*Ctx))
Builder.CreateRetVoid(); Builder.CreateRetVoid();
else if (RetTy->isIntegerTy()) else if (RetTy->isIntegerTy())
// Used if __gcov_flush was implicitly declared. // Used if __llvm_gcov_flush was implicitly declared.
Builder.CreateRet(ConstantInt::get(RetTy, 0)); Builder.CreateRet(ConstantInt::get(RetTy, 0));
else else
report_fatal_error("invalid return type for __gcov_flush"); report_fatal_error("invalid return type for __llvm_gcov_flush");
return FlushF;
} }