[llvm] [BOLT] Keep instrumentation diagnostics out of line (PR #225986)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 23 18:21:09 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-bolt

Author: Ilias (iliasabk)

<details>
<summary>Changes</summary>

The instrumentation runtime's diagnostics reserve a 32 KiB scratch buffer on the stack. When `assert()` or `reportNumber()` get inlined into callers on instrumented code paths, the buffer inflates every caller frame — on small thread stacks a single such frame already overflows the guard region and the profiled binary segfaults even when no assertion fires.

Move the `assert()` failure path into a `noinline` helper (`reportAssertFailure`) and mark `reportNumber()` `noinline` as well, so the scratch buffer is only reserved when a diagnostic is actually emitted. This matches the fix sketched in the issue report.

Verified: `common.h` syntax-checks clean in the freestanding runtime build; the only behavioral change is where the buffer lives.

Fixes #<!-- -->225479


---
Full diff: https://github.com/llvm/llvm-project/pull/225986.diff


1 Files Affected:

- (modified) bolt/runtime/common.h (+13-3) 


``````````diff
diff --git a/bolt/runtime/common.h b/bolt/runtime/common.h
index 36fb7c89dd7db..208c1feda4995 100644
--- a/bolt/runtime/common.h
+++ b/bolt/runtime/common.h
@@ -235,6 +235,10 @@ void *strStr(const char *const Haystack, const char *const Needle) {
   return nullptr;
 }
 
+// Diagnostic helpers allocate a large on-stack scratch buffer. Keep them
+// out of line: if inlined, the buffer is reserved in every caller frame and
+// can overflow small thread stacks even when the report is never emitted.
+__attribute__((noinline))
 void reportNumber(const char *Msg, uint64_t Num, uint32_t Base) {
 #if !defined(ANDROID_AARCH64)
   char Buf[BufSize];
@@ -326,9 +330,10 @@ void reportError(const char *Msg, uint64_t Size) {
 #endif
 }
 
-void assert(bool Assertion, const char *Msg) {
-  if (Assertion)
-    return;
+// Failure path of assert() kept out of line so its large on-stack buffer is
+// not reserved in every inlined caller frame (see reportNumber above).
+__attribute__((noinline))
+void reportAssertFailure(const char *Msg) {
 #if defined(ANDROID_AARCH64)
   (void)Msg;
   boltHandleFatalAndRecover();
@@ -342,6 +347,11 @@ void assert(bool Assertion, const char *Msg) {
 #endif
 }
 
+void assert(bool Assertion, const char *Msg) {
+  if (!Assertion)
+    reportAssertFailure(Msg);
+}
+
 #define SIG_BLOCK 0
 #define SIG_UNBLOCK 1
 #define SIG_SETMASK 2

``````````

</details>


https://github.com/llvm/llvm-project/pull/225986


More information about the llvm-commits mailing list