27
27
namespace swift {
28
28
namespace irgen {
29
29
class FunctionPointer ;
30
+ class IRGenModule ;
30
31
31
32
typedef llvm::IRBuilder<> IRBuilderBase;
32
33
@@ -41,6 +42,7 @@ class IRBuilder : public IRBuilderBase {
41
42
// / point was last cleared. Used only for preserving block
42
43
// / ordering.
43
44
llvm::BasicBlock *ClearedIP;
45
+ unsigned NumTrapBarriers = 0 ;
44
46
45
47
#ifndef NDEBUG
46
48
// / Whether debug information is requested. Only used in assertions.
@@ -300,6 +302,14 @@ class IRBuilder : public IRBuilderBase {
300
302
// llvm::IRBuilder::CreateCall in order to push code towards using
301
303
// FunctionPointer.
302
304
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
+
303
313
llvm::CallInst *CreateCall (llvm::Value *Callee, ArrayRef<llvm::Value *> Args,
304
314
const Twine &Name = " " ,
305
315
llvm::MDNode *FPMathTag = nullptr ) = delete;
@@ -309,6 +319,7 @@ class IRBuilder : public IRBuilderBase {
309
319
const Twine &Name = " " ,
310
320
llvm::MDNode *FPMathTag = nullptr ) {
311
321
assert ((!DebugInfo || getCurrentDebugLocation ()) && " no debugloc on call" );
322
+ assert (!isTrapIntrinsic (Callee) && " Use CreateNonMergeableTrap" );
312
323
auto Call = IRBuilderBase::CreateCall (FTy, Callee, Args, Name, FPMathTag);
313
324
setCallingConvUsingCallee (Call);
314
325
return Call;
@@ -320,6 +331,7 @@ class IRBuilder : public IRBuilderBase {
320
331
llvm::MDNode *FPMathTag = nullptr ) {
321
332
// assert((!DebugInfo || getCurrentDebugLocation()) && "no debugloc on
322
333
// call");
334
+ assert (!isTrapIntrinsic (Callee) && " Use CreateNonMergeableTrap" );
323
335
auto Call = IRBuilderBase::CreateCall (Callee, Args, Name, FPMathTag);
324
336
setCallingConvUsingCallee (Call);
325
337
return Call;
@@ -337,6 +349,7 @@ class IRBuilder : public IRBuilderBase {
337
349
llvm::CallInst *CreateIntrinsicCall (llvm::Intrinsic::ID intrinsicID,
338
350
ArrayRef<llvm::Value *> args,
339
351
const Twine &name = " " ) {
352
+ assert (!isTrapIntrinsic (intrinsicID) && " Use CreateNonMergeableTrap" );
340
353
auto intrinsicFn =
341
354
llvm::Intrinsic::getDeclaration (getModule (), intrinsicID);
342
355
return CreateCall (intrinsicFn, args, name);
@@ -347,10 +360,16 @@ class IRBuilder : public IRBuilderBase {
347
360
ArrayRef<llvm::Type*> typeArgs,
348
361
ArrayRef<llvm::Value *> args,
349
362
const Twine &name = " " ) {
363
+ assert (!isTrapIntrinsic (intrinsicID) && " Use CreateNonMergeableTrap" );
350
364
auto intrinsicFn =
351
365
llvm::Intrinsic::getDeclaration (getModule (), intrinsicID, typeArgs);
352
366
return CreateCall (intrinsicFn, args, name);
353
367
}
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);
354
373
};
355
374
356
375
} // end namespace irgen
0 commit comments