[clang] [llvm] [BoundsChecking] Add parameters to pass (PR #119923)

2024-12-13 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Vitaly Buka (vitalybuka)


Changes

This check is a part of UBSAN, but does not support
verbose output like other UBSAN checks.

This is a step to fix that.


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


6 Files Affected:

- (modified) clang/lib/CodeGen/BackendUtil.cpp (+2-1) 
- (modified) llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h 
(+17-1) 
- (modified) llvm/lib/Passes/PassBuilder.cpp (+27) 
- (modified) llvm/lib/Passes/PassRegistry.def (+6-1) 
- (modified) llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp (+23) 
- (added) llvm/test/Instrumentation/BoundsChecking/runtimes.ll (+95) 


``diff
diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index 8cf44592a17475..ae0e8b132aa356 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1020,7 +1020,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
 if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds))
   PB.registerScalarOptimizerLateEPCallback(
   [](FunctionPassManager &FPM, OptimizationLevel Level) {
-FPM.addPass(BoundsCheckingPass());
+FPM.addPass(
+BoundsCheckingPass(BoundsCheckingPass::ReportingMode::Trap));
   });
 
 if (LangOpts.Sanitize.has(SanitizerKind::Realtime)) {
diff --git a/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h 
b/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
index b1b1ece3eff5a0..29959acc29101a 100644
--- a/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
+++ b/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
@@ -16,9 +16,25 @@ class Function;
 
 /// A pass to instrument code and perform run-time bounds checking on loads,
 /// stores, and other memory intrinsics.
-struct BoundsCheckingPass : PassInfoMixin {
+class BoundsCheckingPass : public PassInfoMixin {
+public:
+  enum class ReportingMode {
+Trap,
+MinRuntime,
+MinRuntimeAbort,
+FullRuntime,
+FullRuntimeAbort,
+  };
+
+private:
+  ReportingMode Mode = ReportingMode::Trap;
+
+public:
+  BoundsCheckingPass(ReportingMode Mode) {}
   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
   static bool isRequired() { return true; }
+  void printPipeline(raw_ostream &OS,
+ function_ref MapClassName2PassName);
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 260a34f2e060d6..78df7eed10f31a 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -1286,6 +1286,33 @@ Expected 
parseRtSanPassOptions(StringRef Params) {
   return Result;
 }
 
+Expected
+parseBoundsCheckingOptions(StringRef Params) {
+  BoundsCheckingPass::ReportingMode Mode =
+  BoundsCheckingPass::ReportingMode::Trap;
+  while (!Params.empty()) {
+StringRef ParamName;
+std::tie(ParamName, Params) = Params.split(';');
+if (ParamName == "trap") {
+  Mode = BoundsCheckingPass::ReportingMode::Trap;
+} else if (ParamName == "rt") {
+  Mode = BoundsCheckingPass::ReportingMode::FullRuntime;
+} else if (ParamName == "rt-abort") {
+  Mode = BoundsCheckingPass::ReportingMode::FullRuntimeAbort;
+} else if (ParamName == "min-rt") {
+  Mode = BoundsCheckingPass::ReportingMode::MinRuntime;
+} else if (ParamName == "min-rt-abort") {
+  Mode = BoundsCheckingPass::ReportingMode::MinRuntimeAbort;
+} else {
+  return make_error(
+  formatv("invalid BoundsChecking pass parameter '{0}' ", ParamName)
+  .str(),
+  inconvertibleErrorCode());
+}
+  }
+  return Mode;
+}
+
 } // namespace
 
 /// Tests whether a pass name starts with a valid prefix for a default pipeline
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 825f2f7f9a494a..c86ff0b5a042c2 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -339,7 +339,6 @@ FUNCTION_PASS("assume-builder", AssumeBuilderPass())
 FUNCTION_PASS("assume-simplify", AssumeSimplifyPass())
 FUNCTION_PASS("atomic-expand", AtomicExpandPass(TM))
 FUNCTION_PASS("bdce", BDCEPass())
-FUNCTION_PASS("bounds-checking", BoundsCheckingPass())
 FUNCTION_PASS("break-crit-edges", BreakCriticalEdgesPass())
 FUNCTION_PASS("callbr-prepare", CallBrPreparePass())
 FUNCTION_PASS("callsite-splitting", CallSiteSplittingPass())
@@ -624,6 +623,12 @@ FUNCTION_PASS_WITH_PARAMS(
 "rtsan", "RealtimeSanitizerPass",
 [](RealtimeSanitizerOptions Opts) { return RealtimeSanitizerPass(Opts); },
 parseRtSanPassOptions, "")
+FUNCTION_PASS_WITH_PARAMS(
+"bounds-checking", "BoundsCheckingPass",
+[](BoundsCheckingPass::ReportingMode Mode) {
+  return BoundsCheckingPass(Mode);
+},
+parseBoundsCheckingOptions, "trap")
 #undef FUNCTION_PASS_WITH_PARAMS
 
 #ifndef LOOPNEST_PASS
diff --git a/llvm/lib/Transforms/I

[clang] [llvm] [BoundsChecking] Add parameters to pass (PR #119923)

2024-12-13 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-codegen

Author: Vitaly Buka (vitalybuka)


Changes

This check is a part of UBSAN, but does not support
verbose output like other UBSAN checks.

This is a step to fix that.


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


6 Files Affected:

- (modified) clang/lib/CodeGen/BackendUtil.cpp (+2-1) 
- (modified) llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h 
(+17-1) 
- (modified) llvm/lib/Passes/PassBuilder.cpp (+27) 
- (modified) llvm/lib/Passes/PassRegistry.def (+6-1) 
- (modified) llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp (+23) 
- (added) llvm/test/Instrumentation/BoundsChecking/runtimes.ll (+95) 


``diff
diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index 8cf44592a17475..ae0e8b132aa356 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1020,7 +1020,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
 if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds))
   PB.registerScalarOptimizerLateEPCallback(
   [](FunctionPassManager &FPM, OptimizationLevel Level) {
-FPM.addPass(BoundsCheckingPass());
+FPM.addPass(
+BoundsCheckingPass(BoundsCheckingPass::ReportingMode::Trap));
   });
 
 if (LangOpts.Sanitize.has(SanitizerKind::Realtime)) {
diff --git a/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h 
b/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
index b1b1ece3eff5a0..29959acc29101a 100644
--- a/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
+++ b/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
@@ -16,9 +16,25 @@ class Function;
 
 /// A pass to instrument code and perform run-time bounds checking on loads,
 /// stores, and other memory intrinsics.
-struct BoundsCheckingPass : PassInfoMixin {
+class BoundsCheckingPass : public PassInfoMixin {
+public:
+  enum class ReportingMode {
+Trap,
+MinRuntime,
+MinRuntimeAbort,
+FullRuntime,
+FullRuntimeAbort,
+  };
+
+private:
+  ReportingMode Mode = ReportingMode::Trap;
+
+public:
+  BoundsCheckingPass(ReportingMode Mode) {}
   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
   static bool isRequired() { return true; }
+  void printPipeline(raw_ostream &OS,
+ function_ref MapClassName2PassName);
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 260a34f2e060d6..78df7eed10f31a 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -1286,6 +1286,33 @@ Expected 
parseRtSanPassOptions(StringRef Params) {
   return Result;
 }
 
+Expected
+parseBoundsCheckingOptions(StringRef Params) {
+  BoundsCheckingPass::ReportingMode Mode =
+  BoundsCheckingPass::ReportingMode::Trap;
+  while (!Params.empty()) {
+StringRef ParamName;
+std::tie(ParamName, Params) = Params.split(';');
+if (ParamName == "trap") {
+  Mode = BoundsCheckingPass::ReportingMode::Trap;
+} else if (ParamName == "rt") {
+  Mode = BoundsCheckingPass::ReportingMode::FullRuntime;
+} else if (ParamName == "rt-abort") {
+  Mode = BoundsCheckingPass::ReportingMode::FullRuntimeAbort;
+} else if (ParamName == "min-rt") {
+  Mode = BoundsCheckingPass::ReportingMode::MinRuntime;
+} else if (ParamName == "min-rt-abort") {
+  Mode = BoundsCheckingPass::ReportingMode::MinRuntimeAbort;
+} else {
+  return make_error(
+  formatv("invalid BoundsChecking pass parameter '{0}' ", ParamName)
+  .str(),
+  inconvertibleErrorCode());
+}
+  }
+  return Mode;
+}
+
 } // namespace
 
 /// Tests whether a pass name starts with a valid prefix for a default pipeline
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 825f2f7f9a494a..c86ff0b5a042c2 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -339,7 +339,6 @@ FUNCTION_PASS("assume-builder", AssumeBuilderPass())
 FUNCTION_PASS("assume-simplify", AssumeSimplifyPass())
 FUNCTION_PASS("atomic-expand", AtomicExpandPass(TM))
 FUNCTION_PASS("bdce", BDCEPass())
-FUNCTION_PASS("bounds-checking", BoundsCheckingPass())
 FUNCTION_PASS("break-crit-edges", BreakCriticalEdgesPass())
 FUNCTION_PASS("callbr-prepare", CallBrPreparePass())
 FUNCTION_PASS("callsite-splitting", CallSiteSplittingPass())
@@ -624,6 +623,12 @@ FUNCTION_PASS_WITH_PARAMS(
 "rtsan", "RealtimeSanitizerPass",
 [](RealtimeSanitizerOptions Opts) { return RealtimeSanitizerPass(Opts); },
 parseRtSanPassOptions, "")
+FUNCTION_PASS_WITH_PARAMS(
+"bounds-checking", "BoundsCheckingPass",
+[](BoundsCheckingPass::ReportingMode Mode) {
+  return BoundsCheckingPass(Mode);
+},
+parseBoundsCheckingOptions, "trap")
 #undef FUNCTION_PASS_WITH_PARAMS
 
 #ifndef LOOPNEST_PASS
diff --git a/llvm/lib/Tran

[clang] [llvm] [BoundsChecking] Add parameters to pass (PR #119923)

2024-12-13 Thread Vitaly Buka via cfe-commits

https://github.com/vitalybuka converted_to_draft 
https://github.com/llvm/llvm-project/pull/119923
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [BoundsChecking] Add parameters to pass (PR #119923)

2024-12-13 Thread Vitaly Buka via cfe-commits

https://github.com/vitalybuka created 
https://github.com/llvm/llvm-project/pull/119923

This check is a part of UBSAN, but does not support
verbose output like other UBSAN checks.

This is a step to fix that.


>From 064dadb7544c00f810f08e11860f6c403a6f336a Mon Sep 17 00:00:00 2001
From: Vitaly Buka 
Date: Fri, 13 Dec 2024 12:48:50 -0800
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
 =?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.4
---
 clang/lib/CodeGen/BackendUtil.cpp |  3 +-
 .../Instrumentation/BoundsChecking.h  | 18 +++-
 llvm/lib/Passes/PassBuilder.cpp   | 27 ++
 llvm/lib/Passes/PassRegistry.def  |  7 +-
 .../Instrumentation/BoundsChecking.cpp| 23 +
 .../BoundsChecking/runtimes.ll| 95 +++
 6 files changed, 170 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/Instrumentation/BoundsChecking/runtimes.ll

diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index 8cf44592a17475..ae0e8b132aa356 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1020,7 +1020,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
 if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds))
   PB.registerScalarOptimizerLateEPCallback(
   [](FunctionPassManager &FPM, OptimizationLevel Level) {
-FPM.addPass(BoundsCheckingPass());
+FPM.addPass(
+BoundsCheckingPass(BoundsCheckingPass::ReportingMode::Trap));
   });
 
 if (LangOpts.Sanitize.has(SanitizerKind::Realtime)) {
diff --git a/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h 
b/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
index b1b1ece3eff5a0..29959acc29101a 100644
--- a/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
+++ b/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h
@@ -16,9 +16,25 @@ class Function;
 
 /// A pass to instrument code and perform run-time bounds checking on loads,
 /// stores, and other memory intrinsics.
-struct BoundsCheckingPass : PassInfoMixin {
+class BoundsCheckingPass : public PassInfoMixin {
+public:
+  enum class ReportingMode {
+Trap,
+MinRuntime,
+MinRuntimeAbort,
+FullRuntime,
+FullRuntimeAbort,
+  };
+
+private:
+  ReportingMode Mode = ReportingMode::Trap;
+
+public:
+  BoundsCheckingPass(ReportingMode Mode) {}
   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
   static bool isRequired() { return true; }
+  void printPipeline(raw_ostream &OS,
+ function_ref MapClassName2PassName);
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 260a34f2e060d6..78df7eed10f31a 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -1286,6 +1286,33 @@ Expected 
parseRtSanPassOptions(StringRef Params) {
   return Result;
 }
 
+Expected
+parseBoundsCheckingOptions(StringRef Params) {
+  BoundsCheckingPass::ReportingMode Mode =
+  BoundsCheckingPass::ReportingMode::Trap;
+  while (!Params.empty()) {
+StringRef ParamName;
+std::tie(ParamName, Params) = Params.split(';');
+if (ParamName == "trap") {
+  Mode = BoundsCheckingPass::ReportingMode::Trap;
+} else if (ParamName == "rt") {
+  Mode = BoundsCheckingPass::ReportingMode::FullRuntime;
+} else if (ParamName == "rt-abort") {
+  Mode = BoundsCheckingPass::ReportingMode::FullRuntimeAbort;
+} else if (ParamName == "min-rt") {
+  Mode = BoundsCheckingPass::ReportingMode::MinRuntime;
+} else if (ParamName == "min-rt-abort") {
+  Mode = BoundsCheckingPass::ReportingMode::MinRuntimeAbort;
+} else {
+  return make_error(
+  formatv("invalid BoundsChecking pass parameter '{0}' ", ParamName)
+  .str(),
+  inconvertibleErrorCode());
+}
+  }
+  return Mode;
+}
+
 } // namespace
 
 /// Tests whether a pass name starts with a valid prefix for a default pipeline
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 825f2f7f9a494a..c86ff0b5a042c2 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -339,7 +339,6 @@ FUNCTION_PASS("assume-builder", AssumeBuilderPass())
 FUNCTION_PASS("assume-simplify", AssumeSimplifyPass())
 FUNCTION_PASS("atomic-expand", AtomicExpandPass(TM))
 FUNCTION_PASS("bdce", BDCEPass())
-FUNCTION_PASS("bounds-checking", BoundsCheckingPass())
 FUNCTION_PASS("break-crit-edges", BreakCriticalEdgesPass())
 FUNCTION_PASS("callbr-prepare", CallBrPreparePass())
 FUNCTION_PASS("callsite-splitting", CallSiteSplittingPass())
@@ -624,6 +623,12 @@ FUNCTION_PASS_WITH_PARAMS(
 "rtsan", "RealtimeSanitizerPass",
 [](RealtimeSanitizerOptions Opts) { return RealtimeSanitizerPass(Opts); },
 p