Author: Vitaly Buka Date: 2024-12-17T22:07:14-08:00 New Revision: 55e87a79b9c3e0cb80503a4b6eec0fab404b2966
URL: https://github.com/llvm/llvm-project/commit/55e87a79b9c3e0cb80503a4b6eec0fab404b2966 DIFF: https://github.com/llvm/llvm-project/commit/55e87a79b9c3e0cb80503a4b6eec0fab404b2966.diff LOG: [BoundsChecking] Add parameters to pass (#119894) This check is a part of UBSAN, but does not support verbose output like other UBSAN checks. This is a step to fix that. Added: llvm/test/Instrumentation/BoundsChecking/runtimes.ll Modified: clang/lib/CodeGen/BackendUtil.cpp llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h llvm/lib/Passes/PassBuilder.cpp llvm/lib/Passes/PassRegistry.def llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp Removed: ################################################################################ diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index f3b7c23d9c248d..b1003f2ce5032e 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1029,7 +1029,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)); }); // Don't add sanitizers if we are here from ThinLTO PostLink. That already diff --git a/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h b/llvm/include/llvm/Transforms/Instrumentation/BoundsChecking.h index b1b1ece3eff5a0..1876e5b72e8c99 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<BoundsCheckingPass> { +class BoundsCheckingPass : public PassInfoMixin<BoundsCheckingPass> { +public: + enum class ReportingMode { + Trap, + MinRuntime, + MinRuntimeAbort, + FullRuntime, + FullRuntimeAbort, + }; + +private: + ReportingMode Mode = ReportingMode::Trap; + +public: + BoundsCheckingPass(ReportingMode Mode) : Mode(Mode) {} PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); static bool isRequired() { return true; } + void printPipeline(raw_ostream &OS, + function_ref<StringRef(StringRef)> MapClassName2PassName); }; } // end namespace llvm diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index eaf1d861051a51..aa5b9077376e05 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -1282,6 +1282,33 @@ parseRegAllocFastPassOptions(PassBuilder &PB, StringRef Params) { return Opts; } +Expected<BoundsCheckingPass::ReportingMode> +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<StringError>( + 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 ec291167da699f..a40eb1a2f79bb2 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -340,7 +340,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()) @@ -622,6 +621,12 @@ FUNCTION_PASS_WITH_PARAMS( return WinEHPreparePass(DemoteCatchSwitchPHIOnly); }, parseWinEHPrepareOptions, "demote-catchswitch-only") +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/Instrumentation/BoundsChecking.cpp b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp index b398a13383b9eb..c86d967716a5a0 100644 --- a/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp +++ b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp @@ -229,3 +229,26 @@ PreservedAnalyses BoundsCheckingPass::run(Function &F, FunctionAnalysisManager & return PreservedAnalyses::none(); } + +void BoundsCheckingPass::printPipeline( + raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { + static_cast<PassInfoMixin<BoundsCheckingPass> *>(this)->printPipeline( + OS, MapClassName2PassName); + switch (Mode) { + case ReportingMode::Trap: + OS << "<trap>"; + break; + case ReportingMode::MinRuntime: + OS << "<min-rt>"; + break; + case ReportingMode::MinRuntimeAbort: + OS << "<min-rt-abort>"; + break; + case ReportingMode::FullRuntime: + OS << "<rt>"; + break; + case ReportingMode::FullRuntimeAbort: + OS << "<rt-abort>"; + break; + } +} \ No newline at end of file diff --git a/llvm/test/Instrumentation/BoundsChecking/runtimes.ll b/llvm/test/Instrumentation/BoundsChecking/runtimes.ll new file mode 100644 index 00000000000000..fd27694c155d2b --- /dev/null +++ b/llvm/test/Instrumentation/BoundsChecking/runtimes.ll @@ -0,0 +1,95 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt < %s -passes=bounds-checking -S | FileCheck %s --check-prefixes=TR +; RUN: opt < %s -passes='bounds-checking<trap>' -S | FileCheck %s --check-prefixes=TR +; RUN: opt < %s -passes='bounds-checking<rt>' -S | FileCheck %s --check-prefixes=RT +; RUN: opt < %s -passes='bounds-checking<rt-abort>' -S | FileCheck %s --check-prefixes=RTABORT +; RUN: opt < %s -passes='bounds-checking<min-rt>' -S | FileCheck %s --check-prefixes=MINRT +; RUN: opt < %s -passes='bounds-checking<min-rt-abort>' -S | FileCheck %s --check-prefixes=MINRTABORT + +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-S128" + +define void @f1(i64 %x) nounwind { +; TR-LABEL: define void @f1( +; TR-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; TR-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]] +; TR-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8 +; TR-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0 +; TR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16 +; TR-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]] +; TR-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]] +; TR-NEXT: br i1 [[TMP6]], label %[[TRAP:.*]], label %[[BB7:.*]] +; TR: [[BB7]]: +; TR-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4 +; TR-NEXT: ret void +; TR: [[TRAP]]: +; TR-NEXT: call void @llvm.trap() #[[ATTR2:[0-9]+]] +; TR-NEXT: unreachable +; +; RT-LABEL: define void @f1( +; RT-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; RT-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]] +; RT-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8 +; RT-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0 +; RT-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16 +; RT-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]] +; RT-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]] +; RT-NEXT: br i1 [[TMP6]], label %[[TRAP:.*]], label %[[BB7:.*]] +; RT: [[BB7]]: +; RT-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4 +; RT-NEXT: ret void +; RT: [[TRAP]]: +; RT-NEXT: call void @llvm.trap() #[[ATTR2:[0-9]+]] +; RT-NEXT: unreachable +; +; RTABORT-LABEL: define void @f1( +; RTABORT-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; RTABORT-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]] +; RTABORT-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8 +; RTABORT-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0 +; RTABORT-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16 +; RTABORT-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]] +; RTABORT-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]] +; RTABORT-NEXT: br i1 [[TMP6]], label %[[TRAP:.*]], label %[[BB7:.*]] +; RTABORT: [[BB7]]: +; RTABORT-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4 +; RTABORT-NEXT: ret void +; RTABORT: [[TRAP]]: +; RTABORT-NEXT: call void @llvm.trap() #[[ATTR2:[0-9]+]] +; RTABORT-NEXT: unreachable +; +; MINRT-LABEL: define void @f1( +; MINRT-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; MINRT-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]] +; MINRT-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8 +; MINRT-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0 +; MINRT-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16 +; MINRT-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]] +; MINRT-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]] +; MINRT-NEXT: br i1 [[TMP6]], label %[[TRAP:.*]], label %[[BB7:.*]] +; MINRT: [[BB7]]: +; MINRT-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4 +; MINRT-NEXT: ret void +; MINRT: [[TRAP]]: +; MINRT-NEXT: call void @llvm.trap() #[[ATTR2:[0-9]+]] +; MINRT-NEXT: unreachable +; +; MINRTABORT-LABEL: define void @f1( +; MINRTABORT-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; MINRTABORT-NEXT: [[TMP1:%.*]] = mul i64 16, [[X]] +; MINRTABORT-NEXT: [[TMP2:%.*]] = alloca i128, i64 [[X]], align 8 +; MINRTABORT-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], 0 +; MINRTABORT-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], 16 +; MINRTABORT-NEXT: [[TMP5:%.*]] = or i1 false, [[TMP4]] +; MINRTABORT-NEXT: [[TMP6:%.*]] = or i1 false, [[TMP5]] +; MINRTABORT-NEXT: br i1 [[TMP6]], label %[[TRAP:.*]], label %[[BB7:.*]] +; MINRTABORT: [[BB7]]: +; MINRTABORT-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4 +; MINRTABORT-NEXT: ret void +; MINRTABORT: [[TRAP]]: +; MINRTABORT-NEXT: call void @llvm.trap() #[[ATTR2:[0-9]+]] +; MINRTABORT-NEXT: unreachable +; + %1 = alloca i128, i64 %x + %3 = load i128, ptr %1, align 4 + ret void +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits