Skip to content

Commit 132bb19

Browse files
committed
[IRGen] Avoid generating mergeable traps
Factor out and reuse logic in the lowering of CondFailInst to emit non-mergeable traps, everywhere we emit traps. This should address a debugging quality issue with ambiguous ud2 instructions. rdar://32772768
1 parent f4718be commit 132bb19

File tree

6 files changed

+40
-38
lines changed

6 files changed

+40
-38
lines changed

lib/IRGen/GenCast.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -422,10 +422,7 @@ emitExistentialScalarCastFn(IRGenModule &IGM,
422422
}
423423

424424
case CheckedCastMode::Unconditional: {
425-
llvm::Function *trapIntrinsic = llvm::Intrinsic::getDeclaration(&IGM.Module,
426-
llvm::Intrinsic::ID::trap);
427-
IGF.Builder.CreateCall(trapIntrinsic, {});
428-
IGF.Builder.CreateUnreachable();
425+
IGF.emitTrap(/*EmitUnreachable=*/true);
429426
break;
430427
}
431428
}

lib/IRGen/GenProto.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1968,10 +1968,7 @@ llvm::Constant *WitnessTableBuilder::buildInstantiationFunction() {
19681968

19691969
// The counts didn't match; abort.
19701970
IGF.Builder.emitBlock(failBB);
1971-
llvm::Function *trapIntrinsic =
1972-
llvm::Intrinsic::getDeclaration(&IGM.Module, llvm::Intrinsic::ID::trap);
1973-
IGF.Builder.CreateCall(trapIntrinsic, {});
1974-
IGF.Builder.CreateUnreachable();
1971+
IGF.emitTrap(/*EmitUnreachable=*/true);
19751972

19761973
return fn;
19771974
}

lib/IRGen/IRGenFunction.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,3 +431,28 @@ Address IRGenFunction::emitAddressAtOffset(llvm::Value *base, Offset offset,
431431
auto slotPtr = emitByteOffsetGEP(base, offsetValue, objectTy);
432432
return Address(slotPtr, objectAlignment);
433433
}
434+
435+
void IRGenFunction::emitTrap(bool EmitUnreachable) {
436+
if (IGM.IRGen.Opts.shouldOptimize()) {
437+
// Emit unique side-effecting inline asm calls in order to eliminate
438+
// the possibility that an LLVM optimization or code generation pass
439+
// will merge these blocks back together again. We emit an empty asm
440+
// string with the side-effect flag set, and with a unique integer
441+
// argument for each cond_fail we see in the function.
442+
llvm::IntegerType *asmArgTy = IGM.Int32Ty;
443+
llvm::Type *argTys = {asmArgTy};
444+
llvm::FunctionType *asmFnTy =
445+
llvm::FunctionType::get(IGM.VoidTy, argTys, false /* = isVarArg */);
446+
llvm::InlineAsm *inlineAsm =
447+
llvm::InlineAsm::get(asmFnTy, "", "n", true /* = SideEffects */);
448+
Builder.CreateAsmCall(inlineAsm,
449+
llvm::ConstantInt::get(asmArgTy, NumTrapBarriers++));
450+
}
451+
452+
// Emit the trap instruction.
453+
llvm::Function *trapIntrinsic =
454+
llvm::Intrinsic::getDeclaration(&IGM.Module, llvm::Intrinsic::ID::trap);
455+
Builder.CreateCall(trapIntrinsic, {});
456+
if (EmitUnreachable)
457+
Builder.CreateUnreachable();
458+
}

lib/IRGen/IRGenFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,11 @@ class IRGenFunction {
276276
/// Mark a load as dereferenceable to `size` bytes.
277277
void setDereferenceableLoad(llvm::LoadInst *load, unsigned size);
278278

279+
/// Emit a non-mergeable trap call, optionally followed by a terminator.
280+
void emitTrap(bool EmitUnreachable);
281+
279282
private:
283+
unsigned NumTrapBarriers = 0;
280284
llvm::Instruction *AllocaIP;
281285
const SILDebugScope *DbgScope;
282286

lib/IRGen/IRGenSIL.cpp

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,6 @@ class IRGenSILFunction :
388388
/// Holds the DominancePoint of values that are storage for a source variable.
389389
SmallVector<std::pair<llvm::Instruction *, DominancePoint>, 8> ValueDomPoints;
390390
unsigned NumAnonVars = 0;
391-
unsigned NumCondFails = 0;
392391

393392
/// Accumulative amount of allocated bytes on the stack. Used to limit the
394393
/// size for stack promoted objects.
@@ -3851,9 +3850,7 @@ static bool hasReferenceSemantics(IRGenSILFunction &IGF,
38513850
static llvm::Value *emitIsUnique(IRGenSILFunction &IGF, SILValue operand,
38523851
SourceLoc loc, bool checkPinned) {
38533852
if (!hasReferenceSemantics(IGF, operand->getType())) {
3854-
llvm::Function *trapIntrinsic = llvm::Intrinsic::getDeclaration(
3855-
&IGF.IGM.Module, llvm::Intrinsic::ID::trap);
3856-
IGF.Builder.CreateCall(trapIntrinsic, {});
3853+
IGF.emitTrap(/*EmitUnreachable=*/false);
38573854
return llvm::UndefValue::get(IGF.IGM.Int1Ty);
38583855
}
38593856

@@ -4480,10 +4477,7 @@ static void emitTrapAndUndefValue(IRGenSILFunction &IGF,
44804477
IGF.FailBBs.push_back(failBB);
44814478

44824479
IGF.Builder.emitBlock(failBB);
4483-
llvm::Function *trapIntrinsic = llvm::Intrinsic::getDeclaration(
4484-
&IGF.IGM.Module, llvm::Intrinsic::ID::trap);
4485-
IGF.Builder.CreateCall(trapIntrinsic, {});
4486-
IGF.Builder.CreateUnreachable();
4480+
IGF.emitTrap(/*EmitUnreachable=*/true);
44874481

44884482
llvm::BasicBlock *contBB = llvm::BasicBlock::Create(IGF.IGM.getLLVMContext());
44894483
IGF.Builder.emitBlock(contBB);
@@ -5377,28 +5371,7 @@ void IRGenSILFunction::visitCondFailInst(swift::CondFailInst *i) {
53775371
llvm::BasicBlock *contBB = llvm::BasicBlock::Create(IGM.getLLVMContext());
53785372
Builder.CreateCondBr(cond, failBB, contBB);
53795373
Builder.emitBlock(failBB);
5380-
5381-
if (IGM.IRGen.Opts.shouldOptimize()) {
5382-
// Emit unique side-effecting inline asm calls in order to eliminate
5383-
// the possibility that an LLVM optimization or code generation pass
5384-
// will merge these blocks back together again. We emit an empty asm
5385-
// string with the side-effect flag set, and with a unique integer
5386-
// argument for each cond_fail we see in the function.
5387-
llvm::IntegerType *asmArgTy = IGM.Int32Ty;
5388-
llvm::Type *argTys = { asmArgTy };
5389-
llvm::FunctionType *asmFnTy =
5390-
llvm::FunctionType::get(IGM.VoidTy, argTys, false /* = isVarArg */);
5391-
llvm::InlineAsm *inlineAsm =
5392-
llvm::InlineAsm::get(asmFnTy, "", "n", true /* = SideEffects */);
5393-
Builder.CreateAsmCall(inlineAsm,
5394-
llvm::ConstantInt::get(asmArgTy, NumCondFails++));
5395-
}
5396-
5397-
// Emit the trap instruction.
5398-
llvm::Function *trapIntrinsic =
5399-
llvm::Intrinsic::getDeclaration(&IGM.Module, llvm::Intrinsic::ID::trap);
5400-
Builder.CreateCall(trapIntrinsic, {});
5401-
Builder.CreateUnreachable();
5374+
emitTrap(/*EmitUnreachable=*/true);
54025375
Builder.emitBlock(contBB);
54035376
FailBBs.push_back(failBB);
54045377
}

test/IRGen/bitcast_different_size.sil

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir %s -verify | %FileCheck %s
2+
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir -O %s -verify | %FileCheck %s --check-prefix=OPT
23

34
// REQUIRES: CPU=i386 || CPU=x86_64
45

@@ -8,6 +9,11 @@ import Swift
89

910
// CHECK-LABEL: define{{( protected)?}} swiftcc i64 @bitcast_different_size1
1011

12+
// OPT-LABEL: define{{.*}}@bitcast_different_size1(i32)
13+
// OPT: tail call void asm sideeffect "", "n"(i32 0) #2
14+
// OPT-NEXT: tail call void @llvm.trap()
15+
// OPT-NEXT: unreachable
16+
1117
sil @bitcast_different_size1 : $@convention(thin) (Int32) -> Int64 {
1218
entry(%i : $Int32):
1319
// CHECK: ret {{.*}}undef

0 commit comments

Comments
 (0)