[llvm-branch-commits] [clang] [llvm] [Instrumentor] Add unreachable support; unreachable stack trace printing (PR #195408)
Johannes Doerfert via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri May 1 21:24:08 PDT 2026
https://github.com/jdoerfert created https://github.com/llvm/llvm-project/pull/195408
Allow to instrument unreachable and provide a use case for stack trace printing.
>From 6d46b0bc29a7f5fecf065870288d0c6f89c6dcdb Mon Sep 17 00:00:00 2001
From: Johannes Doerfert <jdoerfert.llvm at gmail.com>
Date: Fri, 1 May 2026 21:21:25 -0700
Subject: [PATCH] [Instrumentor] Add unreachable support; unreachable stack
trace printing
Allow to instrument unreachable and provide a use case for stack trace
printing.
---
.../Instrumentor/InstrumentorUnreachable.cpp | 20 +++++++++++++++++
clang/test/Instrumentor/UnreachableRT.cpp | 20 +++++++++++++++++
clang/test/Instrumentor/UnreachableRT.json | 15 +++++++++++++
clang/test/Instrumentor/lit.local.cfg | 6 ++++-
.../llvm/Transforms/IPO/Instrumentor.h | 22 +++++++++++++++++++
llvm/lib/Transforms/IPO/Instrumentor.cpp | 14 +++++++++++-
6 files changed, 95 insertions(+), 2 deletions(-)
create mode 100644 clang/test/Instrumentor/InstrumentorUnreachable.cpp
create mode 100644 clang/test/Instrumentor/UnreachableRT.cpp
create mode 100644 clang/test/Instrumentor/UnreachableRT.json
diff --git a/clang/test/Instrumentor/InstrumentorUnreachable.cpp b/clang/test/Instrumentor/InstrumentorUnreachable.cpp
new file mode 100644
index 0000000000000..7a716bed62d53
--- /dev/null
+++ b/clang/test/Instrumentor/InstrumentorUnreachable.cpp
@@ -0,0 +1,20 @@
+// NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+// RUN: %clangxx -O0 -I%llvm_bin_dir/include/ -I%llvm_src_dir/include/ %S/UnreachableRT.cpp -o %t.UnreachableRT.o -c
+// RUN: %clangxx -O0 -L%llvm_bin_dir/lib -lLLVMSupport -lLLVMDemangle -mllvm -enable-instrumentor -mllvm -instrumentor-read-config-file=%S/UnreachableRT.json %t.UnreachableRT.o -o %t %s
+// RUN: not %t 2>&1 | FileCheck %s --check-prefix=FIRST
+// RUN: not %t arg 2>&1 | FileCheck %s --check-prefix=SECOND
+
+static int foobar() {
+ __builtin_unreachable();
+}
+
+
+int main(int argc, char **argv) {
+ if (argc > 1)
+ foobar();
+ else
+ __builtin_unreachable();
+}
+
+// FIRST: Hit unreachable #1
+// SECOND: Hit unreachable #2
diff --git a/clang/test/Instrumentor/UnreachableRT.cpp b/clang/test/Instrumentor/UnreachableRT.cpp
new file mode 100644
index 0000000000000..4e1d54ee7958a
--- /dev/null
+++ b/clang/test/Instrumentor/UnreachableRT.cpp
@@ -0,0 +1,20 @@
+//===-- examples/Instrumentor/stack_usage.c - An example Instrumentor use -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/raw_ostream.h"
+
+extern "C" {
+void __unreachable_pre_unreachable(int64_t ID) {
+ llvm::errs() << "Hit unreachable #" << ID << "\n";
+ llvm::sys::PrintStackTrace(llvm::errs());
+}
+}
diff --git a/clang/test/Instrumentor/UnreachableRT.json b/clang/test/Instrumentor/UnreachableRT.json
new file mode 100644
index 0000000000000..9f4b1b76ef4b4
--- /dev/null
+++ b/clang/test/Instrumentor/UnreachableRT.json
@@ -0,0 +1,15 @@
+{
+ "configuration": {
+ "runtime_prefix": "__unreachable_",
+ "runtime_prefix.description": "The runtime API prefix.",
+ "demangle_function_names": true,
+ "demangle_function_names.description": "Demangle functions names passed to the runtime."
+ },
+ "instruction_pre": {
+ "unreachable": {
+ "enabled": true,
+ "id": true,
+ "id.description": "A unique ID associated with the given instrumentor call"
+ }
+ }
+}
diff --git a/clang/test/Instrumentor/lit.local.cfg b/clang/test/Instrumentor/lit.local.cfg
index afb6cf1a99e25..ae3b82b9dc78e 100644
--- a/clang/test/Instrumentor/lit.local.cfg
+++ b/clang/test/Instrumentor/lit.local.cfg
@@ -1,2 +1,6 @@
+
config.suffixes.add(".cpp")
-config.excludes = ["StackUsageRT.cpp"]
+config.excludes = ["StackUsageRT.cpp", "UnreachableRT.cpp"]
+
+config.substitutions.append(("%llvm_bin_dir", config.llvm_obj_root))
+config.substitutions.append(("%llvm_src_dir", config.llvm_src_root))
diff --git a/llvm/include/llvm/Transforms/IPO/Instrumentor.h b/llvm/include/llvm/Transforms/IPO/Instrumentor.h
index af3e3282944b3..9bd809230d14d 100644
--- a/llvm/include/llvm/Transforms/IPO/Instrumentor.h
+++ b/llvm/include/llvm/Transforms/IPO/Instrumentor.h
@@ -647,6 +647,28 @@ struct AllocaIO : public InstructionIO<Instruction::Alloca> {
}
};
+struct UnreachableIO : public InstructionIO<Instruction::Unreachable> {
+ UnreachableIO() : InstructionIO<Instruction::Unreachable>(/*IsPRE*/ true) {}
+ virtual ~UnreachableIO() {};
+
+ enum ConfigKind {
+ PassId,
+ NumConfig,
+ };
+
+ using ConfigTy = BaseConfigTy<ConfigKind>;
+ ConfigTy Config;
+
+ void init(InstrumentationConfig &IConf, LLVMContext &Ctx,
+ ConfigTy *UserConfig = nullptr);
+
+ static void populate(InstrumentationConfig &IConf, LLVMContext &Ctx,
+ ConfigTy *UserConfig = nullptr) {
+ auto *AIC = IConf.allocate<UnreachableIO>();
+ AIC->init(IConf, Ctx, UserConfig);
+ }
+};
+
/// The instrumentation opportunity for store instructions.
struct StoreIO : public InstructionIO<Instruction::Store> {
virtual ~StoreIO() {};
diff --git a/llvm/lib/Transforms/IPO/Instrumentor.cpp b/llvm/lib/Transforms/IPO/Instrumentor.cpp
index e4ba5c7632c42..0265447832357 100644
--- a/llvm/lib/Transforms/IPO/Instrumentor.cpp
+++ b/llvm/lib/Transforms/IPO/Instrumentor.cpp
@@ -233,7 +233,7 @@ bool InstrumentorImpl::instrumentFunction(Function &Fn) {
for (auto &It : RPOT) {
for (auto &I : *It)
Changed |= instrumentInstruction(I, ICaches);
-
+
auto *TI = It->getTerminator();
if (!TI->getNumSuccessors())
FinalTIs.push_back(TI);
@@ -349,6 +349,7 @@ BaseConfigurationOption::getStringOption(InstrumentationConfig &IConf,
void InstrumentationConfig::populate(InstrumentorIRBuilderTy &IIRB) {
/// List of all instrumentation opportunities.
FunctionIO::populate(*this, IIRB.Ctx);
+ UnreachableIO::populate(*this, IIRB.Ctx);
AllocaIO::populate(*this, IIRB.Ctx);
LoadIO::populate(*this, IIRB);
StoreIO::populate(*this, IIRB);
@@ -747,6 +748,17 @@ Value *FunctionIO::isMainFunction(Value &V, Type &Ty,
///}
+/// UnreachableIO
+///{
+void UnreachableIO::init(InstrumentationConfig &IConf, LLVMContext &Ctx,
+ ConfigTy *UserConfig) {
+ if (UserConfig)
+ Config = *UserConfig;
+ addCommonArgs(IConf, Ctx, Config.has(PassId));
+ IConf.addChoice(*this, Ctx);
+}
+///}
+
/// AllocaIO
///{
void AllocaIO::init(InstrumentationConfig &IConf, LLVMContext &Ctx,
More information about the llvm-branch-commits
mailing list