https://github.com/thejh updated 
https://github.com/llvm/llvm-project/pull/185972

>From 5194d55c426c5a47ebb7d28aa88e1ccf6ef718b7 Mon Sep 17 00:00:00 2001
From: Jann Horn <[email protected]>
Date: Tue, 10 Mar 2026 22:37:20 +0100
Subject: [PATCH 1/3] [sancov] add -fsanitize-coverage=trace-pc-entry-exit

Add a SanCov flag for calling dedicated hook functions on function entry
and exit. This flag can be used either in combination with
-fsanitize-coverage=trace-pc (in which case this patch changes which hook
is called for the entry BB, and generates an additional hook call before
return), or it can be used by itself (in which case only the dedicated
entry/exit callbacks are invoked).

This can be used to track the call stack throughout a sancov trace.
---
 clang/docs/SanitizerCoverage.rst              |  6 ++++
 clang/include/clang/Basic/CodeGenOptions.def  |  2 ++
 clang/include/clang/Options/Options.td        |  7 +++-
 clang/lib/CodeGen/BackendUtil.cpp             |  1 +
 clang/lib/Driver/SanitizerArgs.cpp            | 18 ++++++----
 .../llvm/Transforms/Utils/Instrumentation.h   |  1 +
 .../Instrumentation/SanitizerCoverage.cpp     | 36 ++++++++++++++++---
 .../SanitizerCoverage/trace-pc-entry-exit.ll  | 26 ++++++++++++++
 8 files changed, 85 insertions(+), 12 deletions(-)
 create mode 100644 
llvm/test/Instrumentation/SanitizerCoverage/trace-pc-entry-exit.ll

diff --git a/clang/docs/SanitizerCoverage.rst b/clang/docs/SanitizerCoverage.rst
index 4ab2d09366f4f..baac1612bd592 100644
--- a/clang/docs/SanitizerCoverage.rst
+++ b/clang/docs/SanitizerCoverage.rst
@@ -201,6 +201,12 @@ With ``-fsanitize-coverage=trace-pc`` the compiler will 
insert
 ``__sanitizer_cov_trace_pc()`` on every edge.
 With an additional ``...=trace-pc,indirect-calls`` flag
 ``__sanitizer_cov_trace_pc_indirect(void *callee)`` will be inserted on every 
indirect call.
+With ``-fsanitize-coverage=trace-pc-entry-exit`` the compiler will insert
+``__sanitizer_cov_trace_pc_entry()`` on function entry (and will not emit
+``__sanitizer_cov_trace_pc()`` for this basic block), and insert
+``__sanitizer_cov_trace_pc_exit()`` on function return;
+``-fsanitize-coverage=trace-pc`` must still be passed to instrument other edges
+as well.
 These callbacks are not implemented in the Sanitizer run-time and should be 
defined
 by the user.
 This mechanism is used for fuzzing the Linux kernel
diff --git a/clang/include/clang/Basic/CodeGenOptions.def 
b/clang/include/clang/Basic/CodeGenOptions.def
index 3d8db87a185b4..0096f76bdd3c6 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -306,6 +306,8 @@ CODEGENOPT(SanitizeCoverage8bitCounters, 1, 0, Benign) ///< 
Use 8-bit frequency
                                                        ///< in sanitizer 
coverage.
 CODEGENOPT(SanitizeCoverageTracePC, 1, 0, Benign) ///< Enable PC tracing
                                                   ///< in sanitizer coverage.
+CODEGENOPT(SanitizeCoverageTracePCEntryExit, 1, 0, Benign) ///< Trace function 
entry/exit
+                                                           ///< in sanitizer 
coverage.
 CODEGENOPT(SanitizeCoverageTracePCGuard, 1, 0, Benign) ///< Enable PC tracing 
with guard
                                                        ///< in sanitizer 
coverage.
 CODEGENOPT(SanitizeCoverageInline8bitCounters, 1, 0, Benign) ///< Use inline 
8bit counters.
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 4bbdd9c8c0e58..82c1aa060a2fb 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2485,7 +2485,7 @@ def fno_sanitize_coverage : CommaJoined<["-"], 
"fno-sanitize-coverage=">,
   Group<fsan_cov_Group>, Visibility<[ClangOption, CLOption]>,
   HelpText<"Disable features of coverage instrumentation for Sanitizers">,
   Values<"func,bb,edge,indirect-calls,trace-bb,trace-cmp,trace-div,trace-gep,"
-         "8bit-counters,trace-pc,trace-pc-guard,no-prune,inline-8bit-counters,"
+         
"8bit-counters,trace-pc,trace-pc-entry-exit,trace-pc-guard,no-prune,inline-8bit-counters,"
          "inline-bool-flag">;
 def fsanitize_coverage_allowlist : Joined<["-"], 
"fsanitize-coverage-allowlist=">,
     Group<fsan_cov_Group>, Visibility<[ClangOption, CLOption]>,
@@ -8260,6 +8260,11 @@ def fsanitize_coverage_trace_pc
       Group<fsan_cov_Group>,
       HelpText<"Enable PC tracing in sanitizer coverage">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTracePC">>;
+def fsanitize_coverage_trace_pc_entry_exit
+    : Flag<["-"], "fsanitize-coverage-trace-pc-entry-exit">,
+      Group<fsan_cov_Group>,
+      HelpText<"Enable function entry/exit tracing in sanitizer coverage">,
+      MarshallingInfoFlag<CodeGenOpts<"SanitizeCoverageTracePCEntryExit">>;
 def fsanitize_coverage_trace_pc_guard
     : Flag<["-"], "fsanitize-coverage-trace-pc-guard">,
       Group<fsan_cov_Group>,
diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index 754bcc5d12b9b..843a91d163b06 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -241,6 +241,7 @@ getSancovOptsFromCGOpts(const CodeGenOptions &CGOpts) {
   Opts.TraceGep = CGOpts.SanitizeCoverageTraceGep;
   Opts.Use8bitCounters = CGOpts.SanitizeCoverage8bitCounters;
   Opts.TracePC = CGOpts.SanitizeCoverageTracePC;
+  Opts.TracePCEntryExit = CGOpts.SanitizeCoverageTracePCEntryExit;
   Opts.TracePCGuard = CGOpts.SanitizeCoverageTracePCGuard;
   Opts.NoPrune = CGOpts.SanitizeCoverageNoPrune;
   Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters;
diff --git a/clang/lib/Driver/SanitizerArgs.cpp 
b/clang/lib/Driver/SanitizerArgs.cpp
index ce1e971110caf..78010b9e659d8 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -108,6 +108,7 @@ enum CoverageFeature {
   CoverageTraceLoads = 1 << 16,
   CoverageTraceStores = 1 << 17,
   CoverageControlFlow = 1 << 18,
+  CoverageTracePCEntryExit = 1 << 19,
 };
 
 enum BinaryMetadataFeature {
@@ -963,10 +964,10 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
   }
 
   int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;
-  int InstrumentationTypes = CoverageTracePC | CoverageTracePCGuard |
-                             CoverageInline8bitCounters | CoverageTraceLoads |
-                             CoverageTraceStores | CoverageInlineBoolFlag |
-                             CoverageControlFlow;
+  int InstrumentationTypes = CoverageTracePC | CoverageTracePCEntryExit |
+                             CoverageTracePCGuard | CoverageInline8bitCounters 
|
+                             CoverageTraceLoads | CoverageTraceStores |
+                             CoverageInlineBoolFlag | CoverageControlFlow;
   if ((CoverageFeatures & InsertionPointTypes) &&
       !(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
     D.Diag(clang::diag::warn_drv_deprecated_arg)
@@ -977,9 +978,9 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
 
   // trace-pc w/o func/bb/edge implies edge.
   if (!(CoverageFeatures & InsertionPointTypes)) {
-    if (CoverageFeatures &
-        (CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters |
-         CoverageInlineBoolFlag | CoverageControlFlow))
+    if (CoverageFeatures & (CoverageTracePC | CoverageTracePCEntryExit |
+                            CoverageTracePCGuard | CoverageInline8bitCounters |
+                            CoverageInlineBoolFlag | CoverageControlFlow))
       CoverageFeatures |= CoverageEdge;
 
     if (CoverageFeatures & CoverageStackDepth)
@@ -1327,6 +1328,8 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const 
llvm::opt::ArgList &Args,
       std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),
       std::make_pair(Coverage8bitCounters, 
"-fsanitize-coverage-8bit-counters"),
       std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),
+      std::make_pair(CoverageTracePCEntryExit,
+                     "-fsanitize-coverage-trace-pc-entry-exit"),
       std::make_pair(CoverageTracePCGuard,
                      "-fsanitize-coverage-trace-pc-guard"),
       std::make_pair(CoverageInline8bitCounters,
@@ -1716,6 +1719,7 @@ int parseCoverageFeatures(const Driver &D, const 
llvm::opt::Arg *A,
                 .Case("trace-gep", CoverageTraceGep)
                 .Case("8bit-counters", Coverage8bitCounters)
                 .Case("trace-pc", CoverageTracePC)
+                .Case("trace-pc-entry-exit", CoverageTracePCEntryExit)
                 .Case("trace-pc-guard", CoverageTracePCGuard)
                 .Case("no-prune", CoverageNoPrune)
                 .Case("inline-8bit-counters", CoverageInline8bitCounters)
diff --git a/llvm/include/llvm/Transforms/Utils/Instrumentation.h 
b/llvm/include/llvm/Transforms/Utils/Instrumentation.h
index 93ab8c693607f..95a985ba3f0c4 100644
--- a/llvm/include/llvm/Transforms/Utils/Instrumentation.h
+++ b/llvm/include/llvm/Transforms/Utils/Instrumentation.h
@@ -154,6 +154,7 @@ struct SanitizerCoverageOptions {
   bool TraceGep = false;
   bool Use8bitCounters = false;
   bool TracePC = false;
+  bool TracePCEntryExit = false;
   bool TracePCGuard = false;
   bool Inline8bitCounters = false;
   bool InlineBoolFlag = false;
diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp 
b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index 7f061e2259711..31ca9e6f544df 100644
--- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -35,6 +35,7 @@
 #include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/TargetParser/Triple.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/EscapeEnumerator.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 
 using namespace llvm;
@@ -43,6 +44,8 @@ using namespace llvm;
 
 const char SanCovTracePCIndirName[] = "__sanitizer_cov_trace_pc_indir";
 const char SanCovTracePCName[] = "__sanitizer_cov_trace_pc";
+const char SanCovTracePCEntryName[] = "__sanitizer_cov_trace_pc_entry";
+const char SanCovTracePCExitName[] = "__sanitizer_cov_trace_pc_exit";
 const char SanCovTraceCmp1[] = "__sanitizer_cov_trace_cmp1";
 const char SanCovTraceCmp2[] = "__sanitizer_cov_trace_cmp2";
 const char SanCovTraceCmp4[] = "__sanitizer_cov_trace_cmp4";
@@ -99,6 +102,10 @@ static cl::opt<int> ClCoverageLevel(
 static cl::opt<bool> ClTracePC("sanitizer-coverage-trace-pc",
                                cl::desc("Experimental pc tracing"), 
cl::Hidden);
 
+static cl::opt<bool> ClTracePCEntryExit(
+    "sanitizer-coverage-trace-pc-entry-exit",
+    cl::desc("pc tracing with separate entry/exit callbacks"), cl::Hidden);
+
 static cl::opt<bool> ClTracePCGuard("sanitizer-coverage-trace-pc-guard",
                                     cl::desc("pc tracing with a guard"),
                                     cl::Hidden);
@@ -208,6 +215,7 @@ SanitizerCoverageOptions 
OverrideFromCL(SanitizerCoverageOptions Options) {
   Options.TraceDiv |= ClDIVTracing;
   Options.TraceGep |= ClGEPTracing;
   Options.TracePC |= ClTracePC;
+  Options.TracePCEntryExit |= ClTracePCEntryExit;
   Options.TracePCGuard |= ClTracePCGuard;
   Options.Inline8bitCounters |= ClInline8bitCounters;
   Options.InlineBoolFlag |= ClInlineBoolFlag;
@@ -219,7 +227,7 @@ SanitizerCoverageOptions 
OverrideFromCL(SanitizerCoverageOptions Options) {
   Options.TraceLoads |= ClLoadTracing;
   Options.TraceStores |= ClStoreTracing;
   Options.GatedCallbacks |= ClGatedCallbacks;
-  if (!Options.TracePCGuard && !Options.TracePC &&
+  if (!Options.TracePCGuard && !Options.TracePC && !Options.TracePCEntryExit &&
       !Options.Inline8bitCounters && !Options.StackDepth &&
       !Options.InlineBoolFlag && !Options.TraceLoads && !Options.TraceStores)
     Options.TracePCGuard = true; // TracePCGuard is default.
@@ -256,6 +264,7 @@ class ModuleSanitizerCoverage {
                          ArrayRef<GetElementPtrInst *> GepTraceTargets);
   void InjectTraceForLoadsAndStores(Function &F, ArrayRef<LoadInst *> Loads,
                                     ArrayRef<StoreInst *> Stores);
+  void InjectTraceForExits(Function &F);
   void InjectTraceForSwitch(Function &F,
                             ArrayRef<Instruction *> SwitchTraceTargets,
                             Value *&FunctionGateCmp);
@@ -288,6 +297,7 @@ class ModuleSanitizerCoverage {
   FunctionCallee SanCovStackDepthCallback;
   FunctionCallee SanCovTracePCIndir;
   FunctionCallee SanCovTracePC, SanCovTracePCGuard;
+  FunctionCallee SanCovTracePCEntry, SanCovTracePCExit;
   std::array<FunctionCallee, 4> SanCovTraceCmpFunction;
   std::array<FunctionCallee, 4> SanCovTraceConstCmpFunction;
   std::array<FunctionCallee, 5> SanCovLoadFunction;
@@ -527,6 +537,8 @@ bool ModuleSanitizerCoverage::instrumentModule() {
   }
 
   SanCovTracePC = M.getOrInsertFunction(SanCovTracePCName, VoidTy);
+  SanCovTracePCEntry = M.getOrInsertFunction(SanCovTracePCEntryName, VoidTy);
+  SanCovTracePCExit = M.getOrInsertFunction(SanCovTracePCExitName, VoidTy);
   SanCovTracePCGuard =
       M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, PtrTy);
 
@@ -752,6 +764,9 @@ void ModuleSanitizerCoverage::instrumentFunction(Function 
&F) {
   InjectTraceForDiv(F, DivTraceTargets);
   InjectTraceForGep(F, GepTraceTargets);
   InjectTraceForLoadsAndStores(F, Loads, Stores);
+
+  if (Options.TracePCEntryExit)
+    InjectTraceForExits(F);
 }
 
 GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection(
@@ -864,6 +879,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function &F,
   CreateFunctionLocalArrays(F, AllBlocks);
   for (size_t i = 0, N = AllBlocks.size(); i < N; i++)
     InjectCoverageAtBlock(F, *AllBlocks[i], i, FunctionGateCmp, IsLeafFunc);
+
   return true;
 }
 
@@ -878,7 +894,7 @@ void 
ModuleSanitizerCoverage::InjectCoverageForIndirectCalls(
     Function &F, ArrayRef<Instruction *> IndirCalls) {
   if (IndirCalls.empty())
     return;
-  assert(Options.TracePC || Options.TracePCGuard ||
+  assert(Options.TracePC || Options.TracePCEntryExit || Options.TracePCGuard ||
          Options.Inline8bitCounters || Options.InlineBoolFlag);
   for (auto *I : IndirCalls) {
     InstrumentationIRBuilder IRB(I);
@@ -997,6 +1013,15 @@ void 
ModuleSanitizerCoverage::InjectTraceForLoadsAndStores(
   }
 }
 
+void ModuleSanitizerCoverage::InjectTraceForExits(Function &F) {
+  EscapeEnumerator EE(F, "sancov_exit");
+  while (IRBuilder<> *AtExit = EE.Next()) {
+    InstrumentationIRBuilder::ensureDebugInfo(*AtExit, F);
+    AtExit->CreateCall(SanCovTracePCExit, {})
+        ->setTailCallKind(CallInst::TCK_NoTail);
+  }
+}
+
 void ModuleSanitizerCoverage::InjectTraceForCmp(
     Function &F, ArrayRef<Instruction *> CmpTraceTargets,
     Value *&FunctionGateCmp) {
@@ -1062,8 +1087,11 @@ void 
ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
   InstrumentationIRBuilder IRB(&*IP);
   if (EntryLoc)
     IRB.SetCurrentDebugLocation(EntryLoc);
-  if (Options.TracePC) {
-    IRB.CreateCall(SanCovTracePC)
+  if (Options.TracePC || (IsEntryBB && Options.TracePCEntryExit)) {
+    FunctionCallee Callee = IsEntryBB && Options.TracePCEntryExit
+                                ? SanCovTracePCEntry
+                                : SanCovTracePC;
+    IRB.CreateCall(Callee)
         ->setCannotMerge(); // gets the PC using GET_CALLER_PC.
   }
   if (Options.TracePCGuard) {
diff --git a/llvm/test/Instrumentation/SanitizerCoverage/trace-pc-entry-exit.ll 
b/llvm/test/Instrumentation/SanitizerCoverage/trace-pc-entry-exit.ll
new file mode 100644
index 0000000000000..822a1ec99663b
--- /dev/null
+++ b/llvm/test/Instrumentation/SanitizerCoverage/trace-pc-entry-exit.ll
@@ -0,0 +1,26 @@
+; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=2 
-sanitizer-coverage-trace-pc-entry-exit -S | FileCheck %s 
--check-prefix=CHECK_EE_ONLY
+; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=2 
-sanitizer-coverage-trace-pc-entry-exit -sanitizer-coverage-trace-pc -S | 
FileCheck %s --check-prefix=CHECK_EE_COMBINED
+
+target datalayout = 
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+target triple = "x86_64-unknown-linux-gnu"
+define void @foo(ptr %a) #0 {
+entry:
+  %tobool = icmp eq ptr %a, null
+  br i1 %tobool, label %if.end, label %if.then
+
+  if.then:                                          ; preds = %entry
+  store i32 0, ptr %a, align 4
+  br label %if.end
+
+  if.end:                                           ; preds = %entry, %if.then
+  ret void
+}
+attributes #0 = { nounwind }
+
+; CHECK_EE_ONLY: call void @__sanitizer_cov_trace_pc_entry
+; CHECK_EE_ONLY-NOT: call void @__sanitizer_cov_trace_pc
+; CHECK_EE_ONLY: call void @__sanitizer_cov_trace_pc_exit
+
+; CHECK_EE_COMBINED: call void @__sanitizer_cov_trace_pc_entry
+; CHECK_EE_COMBINED: call void @__sanitizer_cov_trace_pc
+; CHECK_EE_COMBINED: call void @__sanitizer_cov_trace_pc_exit

>From 14a3e4d8a6600e882598f316950be21ac1e28dc6 Mon Sep 17 00:00:00 2001
From: Jann Horn <[email protected]>
Date: Thu, 12 Mar 2026 13:16:49 +0100
Subject: [PATCH 2/3] fixup! [sancov] add
 -fsanitize-coverage=trace-pc-entry-exit

---
 clang/test/Driver/autocomplete.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/clang/test/Driver/autocomplete.c b/clang/test/Driver/autocomplete.c
index 1fd60929751ee..297d2e40d6d83 100644
--- a/clang/test/Driver/autocomplete.c
+++ b/clang/test/Driver/autocomplete.c
@@ -69,6 +69,7 @@
 // FNOSANICOVERALL-NEXT: trace-div
 // FNOSANICOVERALL-NEXT: trace-gep
 // FNOSANICOVERALL-NEXT: trace-pc
+// FNOSANICOVERALL-NEXT: trace-pc-entry-exit
 // FNOSANICOVERALL-NEXT: trace-pc-guard
 // RUN: %clang --autocomplete=-ffp-contract= | FileCheck %s 
-check-prefix=FFPALL
 // FFPALL: fast

>From 07d5cefbad902da28e1a54605684f91c5a39a1b2 Mon Sep 17 00:00:00 2001
From: Jann Horn <[email protected]>
Date: Fri, 13 Mar 2026 16:42:34 +0100
Subject: [PATCH 3/3] fixup! fixup! [sancov] add
 -fsanitize-coverage=trace-pc-entry-exit

---
 clang/docs/SanitizerCoverage.rst              | 18 ++++--
 .../SanitizerCoverage/trace-pc-entry-exit.ll  | 60 +++++++++++++------
 2 files changed, 57 insertions(+), 21 deletions(-)

diff --git a/clang/docs/SanitizerCoverage.rst b/clang/docs/SanitizerCoverage.rst
index baac1612bd592..c01863adebb2d 100644
--- a/clang/docs/SanitizerCoverage.rst
+++ b/clang/docs/SanitizerCoverage.rst
@@ -201,12 +201,22 @@ With ``-fsanitize-coverage=trace-pc`` the compiler will 
insert
 ``__sanitizer_cov_trace_pc()`` on every edge.
 With an additional ``...=trace-pc,indirect-calls`` flag
 ``__sanitizer_cov_trace_pc_indirect(void *callee)`` will be inserted on every 
indirect call.
+
 With ``-fsanitize-coverage=trace-pc-entry-exit`` the compiler will insert
-``__sanitizer_cov_trace_pc_entry()`` on function entry (and will not emit
-``__sanitizer_cov_trace_pc()`` for this basic block), and insert
+``__sanitizer_cov_trace_pc_entry()`` on function entry, and insert
 ``__sanitizer_cov_trace_pc_exit()`` on function return;
-``-fsanitize-coverage=trace-pc`` must still be passed to instrument other edges
-as well.
+``-fsanitize-coverage=trace-pc`` or ``-fsanitize-coverage=trace-pc-guard`` must
+still be passed to instrument all basic blocks.
+
+With the combination ``-fsanitize-coverage=trace-pc-entry-exit,trace-pc``,
+``__sanitizer_cov_trace_pc()`` will be omitted in the entry basic block because
+the block is already covered by ``__sanitizer_cov_trace_pc_entry()``, which can
+be used to both record that the function has been entered and record coverage 
of
+the entry basic block.
+However, with ``-fsanitize-coverage=trace-pc-entry-exit,trace-pc-guard``, both
+callbacks are called for the entry block because
+``__sanitizer_cov_trace_pc_entry()`` does not provide a `guard_variable`.
+
 These callbacks are not implemented in the Sanitizer run-time and should be 
defined
 by the user.
 This mechanism is used for fuzzing the Linux kernel
diff --git a/llvm/test/Instrumentation/SanitizerCoverage/trace-pc-entry-exit.ll 
b/llvm/test/Instrumentation/SanitizerCoverage/trace-pc-entry-exit.ll
index 822a1ec99663b..7766674d2e19a 100644
--- a/llvm/test/Instrumentation/SanitizerCoverage/trace-pc-entry-exit.ll
+++ b/llvm/test/Instrumentation/SanitizerCoverage/trace-pc-entry-exit.ll
@@ -1,26 +1,52 @@
-; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=2 
-sanitizer-coverage-trace-pc-entry-exit -S | FileCheck %s 
--check-prefix=CHECK_EE_ONLY
-; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=2 
-sanitizer-coverage-trace-pc-entry-exit -sanitizer-coverage-trace-pc -S | 
FileCheck %s --check-prefix=CHECK_EE_COMBINED
+; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=2 
-sanitizer-coverage-trace-pc-entry-exit -S | FileCheck %s --check-prefix=CHECK
+; RUN: opt < %s -passes='module(sancov-module)' -sanitizer-coverage-level=2 
-sanitizer-coverage-trace-pc-entry-exit -sanitizer-coverage-trace-pc -S | 
FileCheck %s --check-prefix=CHECK,CHECK_BBCOV
 
 target datalayout = 
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
 target triple = "x86_64-unknown-linux-gnu"
-define void @foo(ptr %a) #0 {
+
+declare i32 @callee_a(i32)
+declare i32 @callee_b()
+
+define i32 @func_multi_return(i32 noundef %a) #0 {
 entry:
-  %tobool = icmp eq ptr %a, null
-  br i1 %tobool, label %if.end, label %if.then
+  %tobool.not = icmp eq i32 %a, 0
+  br i1 %tobool.not, label %if.else, label %if.then
 
-  if.then:                                          ; preds = %entry
-  store i32 0, ptr %a, align 4
-  br label %if.end
+if.then:
+  %call = call i32 @callee_a(i32 noundef %a)
+  ret i32 %call
 
-  if.end:                                           ; preds = %entry, %if.then
-  ret void
+if.else:
+  %call1 = call i32 @callee_b()
+  ret i32 %call1
 }
-attributes #0 = { nounwind }
 
-; CHECK_EE_ONLY: call void @__sanitizer_cov_trace_pc_entry
-; CHECK_EE_ONLY-NOT: call void @__sanitizer_cov_trace_pc
-; CHECK_EE_ONLY: call void @__sanitizer_cov_trace_pc_exit
+; CHECK: define i32 @func_multi_return
+; CHECK-NOT: call void @__sanitizer_cov_trace_pc()
+; CHECK: call void @__sanitizer_cov_trace_pc_entry()
+; CHECK-NOT: call void @__sanitizer_cov_trace_pc()
+; CHECK: br
+; CHECK_BBCOV: call void @__sanitizer_cov_trace_pc()
+; CHECK: call i32 @callee_a
+; CHECK: notail call void @__sanitizer_cov_trace_pc_exit()
+; CHECK: ret
+; CHECK_BBCOV: call void @__sanitizer_cov_trace_pc()
+; CHECK: call i32 @callee_b
+; CHECK: notail call void @__sanitizer_cov_trace_pc_exit()
+; CHECK: ret
+; CHECK: }
+
 
-; CHECK_EE_COMBINED: call void @__sanitizer_cov_trace_pc_entry
-; CHECK_EE_COMBINED: call void @__sanitizer_cov_trace_pc
-; CHECK_EE_COMBINED: call void @__sanitizer_cov_trace_pc_exit
+define i32 @func_musttail(i32 noundef %a) #0 {
+  %call = musttail call i32 @callee_a(i32 noundef %a)
+  ret i32 %call
+}
+
+; CHECK: define i32 @func_musttail
+; CHECK: call void @__sanitizer_cov_trace_pc_entry()
+; CHECK: notail call void @__sanitizer_cov_trace_pc_exit()
+; CHECK: musttail call i32 @callee_a
+; CHECK: ret
+; CHECK: }
+
+attributes #0 = { nounwind }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to