Skip to content

Commit f64d885

Browse files
committed
[IRGen] Prevent mergeable traps from being created
PR #14729 made more calls to llvm.trap() non-mergeable. This follow-up adds asserts to IRBuilder which make it harder to accidentally introduce mergeable calls to llvm.trap() in the future. The newly-added assertions exposed an issue in GenBuiltin while compiling parts of the stdlib. This PR fixes the issue. Suggested by Adrian Prantl! rdar://32772768
1 parent 9cde346 commit f64d885

File tree

5 files changed

+36
-5
lines changed

5 files changed

+36
-5
lines changed

lib/IRGen/GenBuiltin.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,12 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
194194
const IntrinsicInfo &IInfo = IGF.getSILModule().getIntrinsicInfo(FnId);
195195
llvm::Intrinsic::ID IID = IInfo.ID;
196196

197+
// Emit non-mergeable traps only.
198+
if (IGF.Builder.isTrapIntrinsic(IID)) {
199+
IGF.Builder.CreateNonMergeableTrap(IGF.IGM);
200+
return;
201+
}
202+
197203
// Calls to the int_instrprof_increment intrinsic are emitted during SILGen.
198204
// At that stage, the function name GV used by the profiling pass is hidden.
199205
// Fix the intrinsic call here by pointing it to the correct GV.

lib/IRGen/GenCall.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,6 +1601,7 @@ llvm::CallSite CallEmission::emitCallSite() {
16011601

16021602
llvm::CallInst *IRBuilder::CreateCall(const FunctionPointer &fn,
16031603
ArrayRef<llvm::Value*> args) {
1604+
assert(!isTrapIntrinsic(fn.getPointer()) && "Use CreateNonMergeableTrap");
16041605
llvm::CallInst *call = IRBuilderBase::CreateCall(fn.getPointer(), args);
16051606
call->setAttributes(fn.getAttributes());
16061607
call->setCallingConv(fn.getCallingConv());

lib/IRGen/IRBuilder.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
namespace swift {
2828
namespace irgen {
2929
class FunctionPointer;
30+
class IRGenModule;
3031

3132
typedef llvm::IRBuilder<> IRBuilderBase;
3233

@@ -41,6 +42,7 @@ class IRBuilder : public IRBuilderBase {
4142
/// point was last cleared. Used only for preserving block
4243
/// ordering.
4344
llvm::BasicBlock *ClearedIP;
45+
unsigned NumTrapBarriers = 0;
4446

4547
#ifndef NDEBUG
4648
/// Whether debug information is requested. Only used in assertions.
@@ -300,6 +302,14 @@ class IRBuilder : public IRBuilderBase {
300302
// llvm::IRBuilder::CreateCall in order to push code towards using
301303
// FunctionPointer.
302304

305+
bool isTrapIntrinsic(llvm::Value *Callee) {
306+
return Callee == llvm::Intrinsic::getDeclaration(getModule(),
307+
llvm::Intrinsic::ID::trap);
308+
}
309+
bool isTrapIntrinsic(llvm::Intrinsic::ID intrinsicID) {
310+
return intrinsicID == llvm::Intrinsic::ID::trap;
311+
}
312+
303313
llvm::CallInst *CreateCall(llvm::Value *Callee, ArrayRef<llvm::Value *> Args,
304314
const Twine &Name = "",
305315
llvm::MDNode *FPMathTag = nullptr) = delete;
@@ -309,6 +319,7 @@ class IRBuilder : public IRBuilderBase {
309319
const Twine &Name = "",
310320
llvm::MDNode *FPMathTag = nullptr) {
311321
assert((!DebugInfo || getCurrentDebugLocation()) && "no debugloc on call");
322+
assert(!isTrapIntrinsic(Callee) && "Use CreateNonMergeableTrap");
312323
auto Call = IRBuilderBase::CreateCall(FTy, Callee, Args, Name, FPMathTag);
313324
setCallingConvUsingCallee(Call);
314325
return Call;
@@ -320,6 +331,7 @@ class IRBuilder : public IRBuilderBase {
320331
llvm::MDNode *FPMathTag = nullptr) {
321332
// assert((!DebugInfo || getCurrentDebugLocation()) && "no debugloc on
322333
// call");
334+
assert(!isTrapIntrinsic(Callee) && "Use CreateNonMergeableTrap");
323335
auto Call = IRBuilderBase::CreateCall(Callee, Args, Name, FPMathTag);
324336
setCallingConvUsingCallee(Call);
325337
return Call;
@@ -337,6 +349,7 @@ class IRBuilder : public IRBuilderBase {
337349
llvm::CallInst *CreateIntrinsicCall(llvm::Intrinsic::ID intrinsicID,
338350
ArrayRef<llvm::Value *> args,
339351
const Twine &name = "") {
352+
assert(!isTrapIntrinsic(intrinsicID) && "Use CreateNonMergeableTrap");
340353
auto intrinsicFn =
341354
llvm::Intrinsic::getDeclaration(getModule(), intrinsicID);
342355
return CreateCall(intrinsicFn, args, name);
@@ -347,10 +360,16 @@ class IRBuilder : public IRBuilderBase {
347360
ArrayRef<llvm::Type*> typeArgs,
348361
ArrayRef<llvm::Value *> args,
349362
const Twine &name = "") {
363+
assert(!isTrapIntrinsic(intrinsicID) && "Use CreateNonMergeableTrap");
350364
auto intrinsicFn =
351365
llvm::Intrinsic::getDeclaration(getModule(), intrinsicID, typeArgs);
352366
return CreateCall(intrinsicFn, args, name);
353367
}
368+
369+
/// Call the trap intrinsic. If optimizations are enabled, an inline asm
370+
/// gadget is emitted before the trap. The gadget inhibits transforms which
371+
/// merge trap calls together, which makes debugging crashes easier.
372+
llvm::CallInst *CreateNonMergeableTrap(IRGenModule &IGM);
354373
};
355374

356375
} // end namespace irgen

lib/IRGen/IRGenFunction.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ Address IRGenFunction::emitAddressAtOffset(llvm::Value *base, Offset offset,
432432
return Address(slotPtr, objectAlignment);
433433
}
434434

435-
void IRGenFunction::emitTrap(bool EmitUnreachable) {
435+
llvm::CallInst *IRBuilder::CreateNonMergeableTrap(IRGenModule &IGM) {
436436
if (IGM.IRGen.Opts.shouldOptimize()) {
437437
// Emit unique side-effecting inline asm calls in order to eliminate
438438
// the possibility that an LLVM optimization or code generation pass
@@ -445,14 +445,20 @@ void IRGenFunction::emitTrap(bool EmitUnreachable) {
445445
llvm::FunctionType::get(IGM.VoidTy, argTys, false /* = isVarArg */);
446446
llvm::InlineAsm *inlineAsm =
447447
llvm::InlineAsm::get(asmFnTy, "", "n", true /* = SideEffects */);
448-
Builder.CreateAsmCall(inlineAsm,
449-
llvm::ConstantInt::get(asmArgTy, NumTrapBarriers++));
448+
CreateAsmCall(inlineAsm,
449+
llvm::ConstantInt::get(asmArgTy, NumTrapBarriers++));
450450
}
451451

452452
// Emit the trap instruction.
453453
llvm::Function *trapIntrinsic =
454454
llvm::Intrinsic::getDeclaration(&IGM.Module, llvm::Intrinsic::ID::trap);
455-
Builder.CreateCall(trapIntrinsic, {});
455+
auto Call = IRBuilderBase::CreateCall(trapIntrinsic, {});
456+
setCallingConvUsingCallee(Call);
457+
return Call;
458+
}
459+
460+
void IRGenFunction::emitTrap(bool EmitUnreachable) {
461+
Builder.CreateNonMergeableTrap(IGM);
456462
if (EmitUnreachable)
457463
Builder.CreateUnreachable();
458464
}

lib/IRGen/IRGenFunction.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,6 @@ class IRGenFunction {
280280
void emitTrap(bool EmitUnreachable);
281281

282282
private:
283-
unsigned NumTrapBarriers = 0;
284283
llvm::Instruction *AllocaIP;
285284
const SILDebugScope *DbgScope;
286285

0 commit comments

Comments
 (0)