Skip to content

Commit 8455ed2

Browse files
committed
[𝘀𝗽𝗿] changes to main this commit is based on
Created using spr 1.3.4 [skip ci]
1 parent 2691b96 commit 8455ed2

File tree

2 files changed

+87
-27
lines changed

2 files changed

+87
-27
lines changed

llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp

Lines changed: 81 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "llvm/Transforms/Instrumentation/BoundsChecking.h"
1010
#include "llvm/ADT/Statistic.h"
11+
#include "llvm/ADT/StringRef.h"
1112
#include "llvm/ADT/Twine.h"
1213
#include "llvm/Analysis/MemoryBuiltins.h"
1314
#include "llvm/Analysis/ScalarEvolution.h"
@@ -104,6 +105,29 @@ static Value *getBoundsCheckCond(Value *Ptr, Value *InstVal,
104105
return Or;
105106
}
106107

108+
static CallInst *InsertTrap(BuilderTy &IRB) {
109+
if (!DebugTrapBB)
110+
return IRB.CreateIntrinsic(Intrinsic::trap, {}, {});
111+
return IRB.CreateIntrinsic(
112+
Intrinsic::ubsantrap, {},
113+
ConstantInt::get(IRB.getInt8Ty(),
114+
IRB.GetInsertBlock()->getParent()->size()));
115+
}
116+
117+
static CallInst *InsertCall(BuilderTy &IRB, bool MayReturn, StringRef Name) {
118+
Function *Fn = IRB.GetInsertBlock()->getParent();
119+
LLVMContext &Ctx = Fn->getContext();
120+
llvm::AttrBuilder B(Ctx);
121+
B.addAttribute(llvm::Attribute::NoUnwind);
122+
if (!MayReturn)
123+
B.addAttribute(llvm::Attribute::NoReturn);
124+
FunctionCallee Callee = Fn->getParent()->getOrInsertFunction(
125+
Name,
126+
llvm::AttributeList::get(Ctx, llvm::AttributeList::FunctionIndex, B),
127+
Type::getVoidTy(Ctx));
128+
return IRB.CreateCall(Callee);
129+
}
130+
107131
/// Adds run-time bounds checks to memory accessing instructions.
108132
///
109133
/// \p Or is the condition that should guard the trap.
@@ -126,20 +150,53 @@ static void insertBoundsCheck(Value *Or, BuilderTy &IRB, GetTrapBBT GetTrapBB) {
126150
BasicBlock *Cont = OldBB->splitBasicBlock(SplitI);
127151
OldBB->getTerminator()->eraseFromParent();
128152

153+
BasicBlock *TrapBB = GetTrapBB(IRB, Cont);
154+
129155
if (C) {
130156
// If we have a constant zero, unconditionally branch.
131157
// FIXME: We should really handle this differently to bypass the splitting
132158
// the block.
133-
BranchInst::Create(GetTrapBB(IRB), OldBB);
159+
BranchInst::Create(TrapBB, OldBB);
134160
return;
135161
}
136162

137163
// Create the conditional branch.
138-
BranchInst::Create(GetTrapBB(IRB), Cont, Or, OldBB);
164+
BranchInst::Create(TrapBB, Cont, Or, OldBB);
139165
}
140166

167+
struct ReportingOpts {
168+
bool MayReturn = false;
169+
bool UseTrap = false;
170+
bool MinRuntime = false;
171+
StringRef Name;
172+
173+
ReportingOpts(BoundsCheckingPass::ReportingMode Mode) {
174+
switch (Mode) {
175+
case BoundsCheckingPass::ReportingMode::Trap:
176+
UseTrap = true;
177+
break;
178+
case BoundsCheckingPass::ReportingMode::MinRuntime:
179+
Name = "__ubsan_handle_local_out_of_bounds_minimal";
180+
MinRuntime = true;
181+
MayReturn = true;
182+
break;
183+
case BoundsCheckingPass::ReportingMode::MinRuntimeAbort:
184+
Name = "__ubsan_handle_local_out_of_bounds_minimal_abort";
185+
MinRuntime = true;
186+
break;
187+
case BoundsCheckingPass::ReportingMode::FullRuntime:
188+
Name = "__ubsan_handle_local_out_of_bounds";
189+
MayReturn = true;
190+
break;
191+
case BoundsCheckingPass::ReportingMode::FullRuntimeAbort:
192+
Name = "__ubsan_handle_local_out_of_bounds_abort";
193+
break;
194+
}
195+
}
196+
};
197+
141198
static bool addBoundsChecking(Function &F, TargetLibraryInfo &TLI,
142-
ScalarEvolution &SE) {
199+
ScalarEvolution &SE, const ReportingOpts &Opts) {
143200
if (F.hasFnAttribute(Attribute::NoSanitizeBounds))
144201
return false;
145202

@@ -180,37 +237,40 @@ static bool addBoundsChecking(Function &F, TargetLibraryInfo &TLI,
180237
// Create a trapping basic block on demand using a callback. Depending on
181238
// flags, this will either create a single block for the entire function or
182239
// will create a fresh block every time it is called.
183-
BasicBlock *TrapBB = nullptr;
184-
auto GetTrapBB = [&TrapBB](BuilderTy &IRB) {
240+
BasicBlock *ReuseTrapBB = nullptr;
241+
auto GetTrapBB = [&ReuseTrapBB, &Opts](BuilderTy &IRB, BasicBlock *Cont) {
185242
Function *Fn = IRB.GetInsertBlock()->getParent();
186243
auto DebugLoc = IRB.getCurrentDebugLocation();
187244
IRBuilder<>::InsertPointGuard Guard(IRB);
188245

189-
if (TrapBB && SingleTrapBB && !DebugTrapBB)
190-
return TrapBB;
246+
// Create a trapping basic block on demand using a callback. Depending on
247+
// flags, this will either create a single block for the entire function or
248+
// will create a fresh block every time it is called.
249+
if (ReuseTrapBB)
250+
return ReuseTrapBB;
191251

192-
TrapBB = BasicBlock::Create(Fn->getContext(), "trap", Fn);
252+
BasicBlock *TrapBB = BasicBlock::Create(Fn->getContext(), "trap", Fn);
193253
IRB.SetInsertPoint(TrapBB);
194254

195-
Intrinsic::ID IntrID = DebugTrapBB ? Intrinsic::ubsantrap : Intrinsic::trap;
255+
CallInst *TrapCall = Opts.UseTrap
256+
? InsertTrap(IRB)
257+
: InsertCall(IRB, Opts.MayReturn, Opts.Name);
196258

197-
CallInst *TrapCall;
198-
if (DebugTrapBB) {
199-
TrapCall = IRB.CreateIntrinsic(
200-
IntrID, {}, ConstantInt::get(IRB.getInt8Ty(), Fn->size()));
259+
TrapCall->setDoesNotThrow();
260+
TrapCall->setDebugLoc(DebugLoc);
261+
if (Opts.MayReturn) {
262+
IRB.CreateBr(Cont);
201263
} else {
202-
TrapCall = IRB.CreateIntrinsic(IntrID, {}, {});
264+
TrapCall->setDoesNotReturn();
265+
IRB.CreateUnreachable();
203266
}
204267

205-
TrapCall->setDoesNotReturn();
206-
TrapCall->setDoesNotThrow();
207-
TrapCall->setDebugLoc(DebugLoc);
208-
IRB.CreateUnreachable();
268+
if (!Opts.MayReturn && SingleTrapBB && !DebugTrapBB)
269+
ReuseTrapBB = TrapBB;
209270

210271
return TrapBB;
211272
};
212273

213-
// Add the checks.
214274
for (const auto &Entry : TrapInfo) {
215275
Instruction *Inst = Entry.first;
216276
BuilderTy IRB(Inst->getParent(), BasicBlock::iterator(Inst), TargetFolder(DL));
@@ -224,7 +284,7 @@ PreservedAnalyses BoundsCheckingPass::run(Function &F, FunctionAnalysisManager &
224284
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
225285
auto &SE = AM.getResult<ScalarEvolutionAnalysis>(F);
226286

227-
if (!addBoundsChecking(F, TLI, SE))
287+
if (!addBoundsChecking(F, TLI, SE, ReportingOpts(Mode)))
228288
return PreservedAnalyses::all();
229289

230290
return PreservedAnalyses::none();
@@ -251,4 +311,4 @@ void BoundsCheckingPass::printPipeline(
251311
OS << "<rt-abort>";
252312
break;
253313
}
254-
}
314+
}

llvm/test/Instrumentation/BoundsChecking/runtimes.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ define void @f1(i64 %x) nounwind {
3838
; RT-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4
3939
; RT-NEXT: ret void
4040
; RT: [[TRAP]]:
41-
; RT-NEXT: call void @llvm.trap() #[[ATTR2:[0-9]+]]
42-
; RT-NEXT: unreachable
41+
; RT-NEXT: call void @__ubsan_handle_local_out_of_bounds() #[[ATTR0]]
42+
; RT-NEXT: br label %[[BB7]]
4343
;
4444
; RTABORT-LABEL: define void @f1(
4545
; RTABORT-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] {
@@ -54,7 +54,7 @@ define void @f1(i64 %x) nounwind {
5454
; RTABORT-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4
5555
; RTABORT-NEXT: ret void
5656
; RTABORT: [[TRAP]]:
57-
; RTABORT-NEXT: call void @llvm.trap() #[[ATTR2:[0-9]+]]
57+
; RTABORT-NEXT: call void @__ubsan_handle_local_out_of_bounds_abort() #[[ATTR1:[0-9]+]]
5858
; RTABORT-NEXT: unreachable
5959
;
6060
; MINRT-LABEL: define void @f1(
@@ -70,8 +70,8 @@ define void @f1(i64 %x) nounwind {
7070
; MINRT-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4
7171
; MINRT-NEXT: ret void
7272
; MINRT: [[TRAP]]:
73-
; MINRT-NEXT: call void @llvm.trap() #[[ATTR2:[0-9]+]]
74-
; MINRT-NEXT: unreachable
73+
; MINRT-NEXT: call void @__ubsan_handle_local_out_of_bounds_minimal() #[[ATTR0]]
74+
; MINRT-NEXT: br label %[[BB7]]
7575
;
7676
; MINRTABORT-LABEL: define void @f1(
7777
; MINRTABORT-SAME: i64 [[X:%.*]]) #[[ATTR0:[0-9]+]] {
@@ -86,7 +86,7 @@ define void @f1(i64 %x) nounwind {
8686
; MINRTABORT-NEXT: [[TMP8:%.*]] = load i128, ptr [[TMP2]], align 4
8787
; MINRTABORT-NEXT: ret void
8888
; MINRTABORT: [[TRAP]]:
89-
; MINRTABORT-NEXT: call void @llvm.trap() #[[ATTR2:[0-9]+]]
89+
; MINRTABORT-NEXT: call void @__ubsan_handle_local_out_of_bounds_minimal_abort() #[[ATTR1:[0-9]+]]
9090
; MINRTABORT-NEXT: unreachable
9191
;
9292
%1 = alloca i128, i64 %x

0 commit comments

Comments
 (0)