Skip to content
Snippets Groups Projects
Commit 04d57c7b authored by Bill Wendling's avatar Bill Wendling
Browse files

Register the GCOV writeout functions so that they're emitted serially.

We don't want to write out >1000 files at the same time. That could make things
prohibitively expensive. Instead, register the "writeout" function so that it's
emitted serially.
<rdar://problem/12439551>

llvm-svn: 177437
parent e647659d
No related branches found
No related tags found
No related merge requests found
......@@ -101,6 +101,7 @@ namespace {
Constant *getIncrementIndirectCounterFunc();
Constant *getEmitFunctionFunc();
Constant *getEmitArcsFunc();
Constant *getDeleteWriteoutFunctionListFunc();
Constant *getDeleteFlushFunctionListFunc();
Constant *getEndFileFunc();
......@@ -550,8 +551,8 @@ bool GCOVProfiler::emitProfileArcs() {
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.
// 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);
......@@ -564,21 +565,36 @@ bool GCOVProfiler::emitProfileArcs() {
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);
// Register the local writeout function.
Constant *RegWriteout =
M->getOrInsertFunction("llvm_register_writeout_function", FTy);
Builder.CreateCall(RegWriteout, WriteoutF);
// Register the local flush function.
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());
if (M->getFunction("main")) {
Constant *AtExitFn = M->getOrInsertFunction("atexit", FTy);
// In the module that has the 'main' function, make sure that the flush
// and writeout function lists are deleted. Also make sure that the
// writeout function list is deleted.
Builder.CreateCall(AtExitFn, getDeleteWriteoutFunctionListFunc());
Builder.CreateCall(AtExitFn, getDeleteFlushFunctionListFunc());
// Make sure we write out all files when exiting. Note: This is called
// first from atexit().
FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
Builder.CreateCall(AtExitFn,
M->getOrInsertFunction("__llvm_writeout_files", FTy));
}
Builder.CreateRetVoid();
appendToGlobalCtors(*M, F, 0);
......@@ -677,6 +693,11 @@ Constant *GCOVProfiler::getEmitArcsFunc() {
return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy);
}
Constant *GCOVProfiler::getDeleteWriteoutFunctionListFunc() {
FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
return M->getOrInsertFunction("llvm_delete_writeout_function_list", FTy);
}
Constant *GCOVProfiler::getDeleteFlushFunctionListFunc() {
FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
return M->getOrInsertFunction("llvm_delete_flush_function_list", FTy);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment