@@ -115,7 +115,8 @@ class GCOVProfiler {
115115 // list.
116116 Function *
117117 insertCounterWriteout (ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
118- Function *insertFlush (ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
118+ Function *insertReset (ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
119+ Function *insertFlush (Function *ResetF);
119120
120121 void AddFlushBeforeForkAndExec ();
121122
@@ -631,35 +632,76 @@ static bool shouldKeepInEntry(BasicBlock::iterator It) {
631632}
632633
633634void GCOVProfiler::AddFlushBeforeForkAndExec () {
634- SmallVector<Instruction *, 2 > ForkAndExecs;
635+ SmallVector<CallInst *, 2 > Forks;
636+ SmallVector<CallInst *, 2 > Execs;
635637 for (auto &F : M->functions ()) {
636638 auto *TLI = &GetTLI (F);
637639 for (auto &I : instructions (F)) {
638640 if (CallInst *CI = dyn_cast<CallInst>(&I)) {
639641 if (Function *Callee = CI->getCalledFunction ()) {
640642 LibFunc LF;
641- if (TLI->getLibFunc (*Callee, LF) &&
642- (LF == LibFunc_fork || LF == LibFunc_execl ||
643- LF == LibFunc_execle || LF == LibFunc_execlp ||
644- LF == LibFunc_execv || LF == LibFunc_execvp ||
645- LF == LibFunc_execve || LF == LibFunc_execvpe ||
646- LF == LibFunc_execvP)) {
647- ForkAndExecs.push_back (&I);
643+ if (TLI->getLibFunc (*Callee, LF)) {
644+ if (LF == LibFunc_fork) {
645+ #if !defined(_WIN32)
646+ Forks.push_back (CI);
647+ #endif
648+ } else if (LF == LibFunc_execl || LF == LibFunc_execle ||
649+ LF == LibFunc_execlp || LF == LibFunc_execv ||
650+ LF == LibFunc_execvp || LF == LibFunc_execve ||
651+ LF == LibFunc_execvpe || LF == LibFunc_execvP) {
652+ Execs.push_back (CI);
653+ }
648654 }
649655 }
650656 }
651657 }
652658 }
653659
654- // We need to split the block after the fork/exec call
655- // because else the counters for the lines after will be
656- // the same as before the call.
657- for (auto I : ForkAndExecs) {
658- IRBuilder<> Builder (I);
660+ for (auto F : Forks) {
661+ IRBuilder<> Builder (F);
662+ BasicBlock *Parent = F->getParent ();
663+ auto NextInst = ++F->getIterator ();
664+
665+ // We've a fork so just reset the counters in the child process
666+ FunctionType *FTy = FunctionType::get (Builder.getInt32Ty (), {}, false );
667+ FunctionCallee GCOVFork = M->getOrInsertFunction (" __gcov_fork" , FTy);
668+ F->setCalledFunction (GCOVFork);
669+
670+ // We split just after the fork to have a counter for the lines after
671+ // Anyway there's a bug:
672+ // void foo() { fork(); }
673+ // void bar() { foo(); blah(); }
674+ // then "blah();" will be called 2 times but showed as 1
675+ // because "blah()" belongs to the same block as "foo();"
676+ Parent->splitBasicBlock (NextInst);
677+
678+ // back() is a br instruction with a debug location
679+ // equals to the one from NextAfterFork
680+ // So to avoid to have two debug locs on two blocks just change it
681+ DebugLoc Loc = F->getDebugLoc ();
682+ Parent->back ().setDebugLoc (Loc);
683+ }
684+
685+ for (auto E : Execs) {
686+ IRBuilder<> Builder (E);
687+ BasicBlock *Parent = E->getParent ();
688+ auto NextInst = ++E->getIterator ();
689+
690+ // Since the process is replaced by a new one we need to write out gcdas
691+ // No need to reset the counters since they'll be lost after the exec**
659692 FunctionType *FTy = FunctionType::get (Builder.getVoidTy (), {}, false );
660- FunctionCallee GCOVFlush = M->getOrInsertFunction (" __gcov_flush" , FTy);
661- Builder.CreateCall (GCOVFlush);
662- I->getParent ()->splitBasicBlock (I);
693+ FunctionCallee WriteoutF =
694+ M->getOrInsertFunction (" llvm_writeout_files" , FTy);
695+ Builder.CreateCall (WriteoutF);
696+
697+ DebugLoc Loc = E->getDebugLoc ();
698+ Builder.SetInsertPoint (&*NextInst);
699+ // If the exec** fails we must reset the counters since they've been
700+ // dumped
701+ FunctionCallee ResetF = M->getOrInsertFunction (" llvm_reset_counters" , FTy);
702+ Builder.CreateCall (ResetF)->setDebugLoc (Loc);
703+ Parent->splitBasicBlock (NextInst);
704+ Parent->back ().setDebugLoc (Loc);
663705 }
664706}
665707
@@ -851,7 +893,8 @@ bool GCOVProfiler::emitProfileArcs() {
851893 }
852894
853895 Function *WriteoutF = insertCounterWriteout (CountersBySP);
854- Function *FlushF = insertFlush (CountersBySP);
896+ Function *ResetF = insertReset (CountersBySP);
897+ Function *FlushF = insertFlush (ResetF);
855898
856899 // Create a small bit of code that registers the "__llvm_gcov_writeout" to
857900 // be executed at exit and the "__llvm_gcov_flush" function to be executed
@@ -869,16 +912,14 @@ bool GCOVProfiler::emitProfileArcs() {
869912 IRBuilder<> Builder (BB);
870913
871914 FTy = FunctionType::get (Type::getVoidTy (*Ctx), false );
872- Type *Params[] = {
873- PointerType::get (FTy, 0 ),
874- PointerType::get (FTy, 0 )
875- };
915+ Type *Params[] = {PointerType::get (FTy, 0 ), PointerType::get (FTy, 0 ),
916+ PointerType::get (FTy, 0 )};
876917 FTy = FunctionType::get (Builder.getVoidTy (), Params, false );
877918
878- // Initialize the environment and register the local writeout and flush
879- // functions.
919+ // Initialize the environment and register the local writeout, flush and
920+ // reset functions.
880921 FunctionCallee GCOVInit = M->getOrInsertFunction (" llvm_gcov_init" , FTy);
881- Builder.CreateCall (GCOVInit, {WriteoutF, FlushF});
922+ Builder.CreateCall (GCOVInit, {WriteoutF, FlushF, ResetF });
882923 Builder.CreateRetVoid ();
883924
884925 appendToGlobalCtors (*M, F, 0 );
@@ -1191,8 +1232,43 @@ Function *GCOVProfiler::insertCounterWriteout(
11911232 return WriteoutF;
11921233}
11931234
1194- Function *GCOVProfiler::
1195- insertFlush (ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) {
1235+ Function *GCOVProfiler::insertReset (
1236+ ArrayRef<std::pair<GlobalVariable *, MDNode *>> CountersBySP) {
1237+ FunctionType *FTy = FunctionType::get (Type::getVoidTy (*Ctx), false );
1238+ Function *ResetF = M->getFunction (" __llvm_gcov_reset" );
1239+ if (!ResetF)
1240+ ResetF = Function::Create (FTy, GlobalValue::InternalLinkage,
1241+ " __llvm_gcov_reset" , M);
1242+ else
1243+ ResetF->setLinkage (GlobalValue::InternalLinkage);
1244+ ResetF->setUnnamedAddr (GlobalValue::UnnamedAddr::Global);
1245+ ResetF->addFnAttr (Attribute::NoInline);
1246+ if (Options.NoRedZone )
1247+ ResetF->addFnAttr (Attribute::NoRedZone);
1248+
1249+ BasicBlock *Entry = BasicBlock::Create (*Ctx, " entry" , ResetF);
1250+ IRBuilder<> Builder (Entry);
1251+
1252+ // Zero out the counters.
1253+ for (const auto &I : CountersBySP) {
1254+ GlobalVariable *GV = I.first ;
1255+ Constant *Null = Constant::getNullValue (GV->getValueType ());
1256+ Builder.CreateStore (Null, GV);
1257+ }
1258+
1259+ Type *RetTy = ResetF->getReturnType ();
1260+ if (RetTy->isVoidTy ())
1261+ Builder.CreateRetVoid ();
1262+ else if (RetTy->isIntegerTy ())
1263+ // Used if __llvm_gcov_reset was implicitly declared.
1264+ Builder.CreateRet (ConstantInt::get (RetTy, 0 ));
1265+ else
1266+ report_fatal_error (" invalid return type for __llvm_gcov_reset" );
1267+
1268+ return ResetF;
1269+ }
1270+
1271+ Function *GCOVProfiler::insertFlush (Function *ResetF) {
11961272 FunctionType *FTy = FunctionType::get (Type::getVoidTy (*Ctx), false );
11971273 Function *FlushF = M->getFunction (" __llvm_gcov_flush" );
11981274 if (!FlushF)
@@ -1213,16 +1289,10 @@ insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) {
12131289
12141290 IRBuilder<> Builder (Entry);
12151291 Builder.CreateCall (WriteoutF, {});
1216-
1217- // Zero out the counters.
1218- for (const auto &I : CountersBySP) {
1219- GlobalVariable *GV = I.first ;
1220- Constant *Null = Constant::getNullValue (GV->getValueType ());
1221- Builder.CreateStore (Null, GV);
1222- }
1292+ Builder.CreateCall (ResetF, {});
12231293
12241294 Type *RetTy = FlushF->getReturnType ();
1225- if (RetTy == Type::getVoidTy (*Ctx ))
1295+ if (RetTy-> isVoidTy ( ))
12261296 Builder.CreateRetVoid ();
12271297 else if (RetTy->isIntegerTy ())
12281298 // Used if __llvm_gcov_flush was implicitly declared.
0 commit comments