llvm.org GIT mirror llvm / bb74632
[GCOV] Flush counters before to avoid counting the execution before fork twice and for exec** functions we must flush before the call Summary: This is replacement for patch in https://reviews.llvm.org/D49460. When we fork, the counters are duplicate as they're and so the values are finally wrong when writing gcda for parent and child. So just before to fork, we flush the counters and so the parent and the child have new counters set to zero. For exec** functions, we need to flush before the call to have some data. Reviewers: vsk, davidxl, marco-c Reviewed By: marco-c Subscribers: llvm-commits, sylvestre.ledru, marco-c Differential Revision: https://reviews.llvm.org/D53593 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@346313 91177308-0d34-0410-b5e6-96231b3b80d8 Calixte Denizet 11 months ago
3 changed file(s) with 87 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
564564 /// char *ctermid(char *s);
565565 TLI_DEFINE_ENUM_INTERNAL(ctermid)
566566 TLI_DEFINE_STRING_INTERNAL("ctermid")
567 /// int execl(const char *path, const char *arg, ...);
568 TLI_DEFINE_ENUM_INTERNAL(execl)
569 TLI_DEFINE_STRING_INTERNAL("execl")
570 /// int execle(const char *file, const char *arg, ..., char * const envp[]);
571 TLI_DEFINE_ENUM_INTERNAL(execle)
572 TLI_DEFINE_STRING_INTERNAL("execle")
573 /// int execlp(const char *file, const char *arg, ...);
574 TLI_DEFINE_ENUM_INTERNAL(execlp)
575 TLI_DEFINE_STRING_INTERNAL("execlp")
576 /// int execv(const char *path, char *const argv[]);
577 TLI_DEFINE_ENUM_INTERNAL(execv)
578 TLI_DEFINE_STRING_INTERNAL("execv")
579 /// int execvP(const char *file, const char *search_path, char *const argv[]);
580 TLI_DEFINE_ENUM_INTERNAL(execvP)
581 TLI_DEFINE_STRING_INTERNAL("execvP")
582 /// int execve(const char *filename, char *const argv[], char *const envp[]);
583 TLI_DEFINE_ENUM_INTERNAL(execve)
584 TLI_DEFINE_STRING_INTERNAL("execve")
585 /// int execvp(const char *file, char *const argv[]);
586 TLI_DEFINE_ENUM_INTERNAL(execvp)
587 TLI_DEFINE_STRING_INTERNAL("execvp")
588 /// int execvpe(const char *file, char *const argv[], char *const envp[]);
589 TLI_DEFINE_ENUM_INTERNAL(execvpe)
590 TLI_DEFINE_STRING_INTERNAL("execvpe")
567591 /// double exp(double x);
568592 TLI_DEFINE_ENUM_INTERNAL(exp)
569593 TLI_DEFINE_STRING_INTERNAL("exp")
708732 /// FILE *fopen64(const char *filename, const char *opentype)
709733 TLI_DEFINE_ENUM_INTERNAL(fopen64)
710734 TLI_DEFINE_STRING_INTERNAL("fopen64")
735 /// int fork();
736 TLI_DEFINE_ENUM_INTERNAL(fork)
737 TLI_DEFINE_STRING_INTERNAL("fork")
711738 /// int fprintf(FILE *stream, const char *format, ...);
712739 TLI_DEFINE_ENUM_INTERNAL(fprintf)
713740 TLI_DEFINE_STRING_INTERNAL("fprintf")
612612 unsigned NumParams = FTy.getNumParams();
613613
614614 switch (F) {
615 case LibFunc_execl:
616 case LibFunc_execlp:
617 return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() &&
618 FTy.getParamType(1)->isPointerTy() &&
619 FTy.getReturnType()->isIntegerTy(32));
620 case LibFunc_execle:
621 return (NumParams >= 3 && FTy.getParamType(0)->isPointerTy() &&
622 FTy.getParamType(1)->isPointerTy() &&
623 FTy.getParamType(NumParams - 1)->isPointerTy() &&
624 FTy.getReturnType()->isIntegerTy(32));
625 case LibFunc_execv:
626 case LibFunc_execvp:
627 return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() &&
628 FTy.getParamType(1)->isPointerTy() &&
629 FTy.getReturnType()->isIntegerTy(32));
630 case LibFunc_execvP:
631 case LibFunc_execvpe:
632 case LibFunc_execve:
633 return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() &&
634 FTy.getParamType(1)->isPointerTy() &&
635 FTy.getParamType(2)->isPointerTy() &&
636 FTy.getReturnType()->isIntegerTy(32));
615637 case LibFunc_strlen:
616638 return (NumParams == 1 && FTy.getParamType(0)->isPointerTy() &&
617639 FTy.getReturnType()->isIntegerTy());
862884 return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
863885 FTy.getParamType(0)->isPointerTy() &&
864886 FTy.getParamType(1)->isPointerTy());
887 case LibFunc_fork:
888 return (NumParams == 0 && FTy.getReturnType()->isIntegerTy(32));
865889 case LibFunc_fdopen:
866890 return (NumParams == 2 && FTy.getReturnType()->isPointerTy() &&
867891 FTy.getParamType(1)->isPointerTy());
108108 insertCounterWriteout(ArrayRef>);
109109 Function *insertFlush(ArrayRef>);
110110
111 void AddFlushBeforeForkAndExec();
112
111113 enum class GCovFileType { GCNO, GCDA };
112114 std::string mangleName(const DICompileUnit *CU, GCovFileType FileType);
113115
467469 this->TLI = &TLI;
468470 Ctx = &M.getContext();
469471
472 AddFlushBeforeForkAndExec();
473
470474 if (Options.EmitNotes) emitProfileNotes();
471475 if (Options.EmitData) return emitProfileArcs();
472476 return false;
521525 }
522526
523527 return false;
528 }
529
530 void GCOVProfiler::AddFlushBeforeForkAndExec() {
531 SmallVector ForkAndExecs;
532 for (auto &F : M->functions()) {
533 for (auto &I : instructions(F)) {
534 if (CallInst *CI = dyn_cast(&I)) {
535 if (Function *Callee = CI->getCalledFunction()) {
536 LibFunc LF;
537 if (TLI->getLibFunc(*Callee, LF) &&
538 (LF == LibFunc_fork || LF == LibFunc_execl ||
539 LF == LibFunc_execle || LF == LibFunc_execlp ||
540 LF == LibFunc_execv || LF == LibFunc_execvp ||
541 LF == LibFunc_execve || LF == LibFunc_execvpe ||
542 LF == LibFunc_execvP)) {
543 ForkAndExecs.push_back(&I);
544 }
545 }
546 }
547 }
548 }
549
550 // We need to split the block after the fork/exec call
551 // because else the counters for the lines after will be
552 // the same as before the call.
553 for (auto I : ForkAndExecs) {
554 IRBuilder<> Builder(I);
555 FunctionType *FTy = FunctionType::get(Builder.getVoidTy(), {}, false);
556 Constant *GCOVFlush = M->getOrInsertFunction("__gcov_flush", FTy);
557 Builder.CreateCall(GCOVFlush);
558 I->getParent()->splitBasicBlock(I);
559 }
524560 }
525561
526562 void GCOVProfiler::emitProfileNotes() {