Skip to content

Commit f886945

Browse files
authored
Merge pull request swiftlang#25978 from eeckstein/confail-messages
Better runtime failure messages (not yet enabled by default)
2 parents fdecd00 + bc48b3d commit f886945

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+296
-137
lines changed

docs/SIL.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5110,13 +5110,15 @@ cond_fail
51105110
`````````
51115111
::
51125112

5113-
sil-instruction ::= 'cond_fail' sil-operand
5113+
sil-instruction ::= 'cond_fail' sil-operand, string-literal
51145114

5115-
cond_fail %0 : $Builtin.Int1
5115+
cond_fail %0 : $Builtin.Int1, "failure reason"
51165116
// %0 must be of type $Builtin.Int1
51175117

51185118
This instruction produces a `runtime failure`_ if the operand is one.
51195119
Execution proceeds normally if the operand is zero.
5120+
The second operand is a static failure message, which is displayed by the
5121+
debugger in case the failure is triggered.
51205122

51215123
Terminators
51225124
~~~~~~~~~~~

include/swift/AST/Builtins.def

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -314,10 +314,6 @@ BUILTIN_SIL_OPERATION(BeginUnpairedModifyAccess, "beginUnpairedModifyAccess",
314314
/// be a pointer to an UnsafeValueBuffer that records an in progress access.
315315
BUILTIN_SIL_OPERATION(EndUnpairedAccess, "endUnpairedAccess", Special)
316316

317-
/// condfail(Int1) -> ()
318-
/// Triggers a runtime failure if the condition is true.
319-
BUILTIN_SIL_OPERATION(CondFail, "condfail", Special)
320-
321317
/// fixLifetime(T) -> ()
322318
/// Fixes the lifetime of any heap references in a value.
323319
BUILTIN_SIL_OPERATION(FixLifetime, "fixLifetime", Special)
@@ -404,6 +400,10 @@ BUILTIN_RUNTIME_CALL(IsOptionalType, "isOptional", "")
404400
BUILTIN(Id, Name, Attrs)
405401
#endif
406402

403+
/// condfail(Int1, RawPointer) -> ()
404+
/// Triggers a runtime failure if the condition is true.
405+
BUILTIN_MISC_OPERATION(CondFail, "condfail", "", Special)
406+
407407
/// Sizeof has type T.Type -> Int
408408
BUILTIN_MISC_OPERATION(Sizeof, "sizeof", "n", Special)
409409

include/swift/SIL/SILBuilder.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,15 +1775,15 @@ class SILBuilder {
17751775
//===--------------------------------------------------------------------===//
17761776

17771777
CondFailInst *createCondFail(SILLocation Loc, SILValue Operand,
1778-
bool Inverted = false) {
1778+
StringRef Message, bool Inverted = false) {
17791779
if (Inverted) {
17801780
SILType Ty = Operand->getType();
17811781
SILValue True(createIntegerLiteral(Loc, Ty, 1));
17821782
Operand =
17831783
createBuiltinBinaryFunction(Loc, "xor", Ty, Ty, {Operand, True});
17841784
}
1785-
return insert(new (getModule())
1786-
CondFailInst(getSILDebugLocation(Loc), Operand));
1785+
return insert(CondFailInst::create(getSILDebugLocation(Loc), Operand,
1786+
Message, getModule()));
17871787
}
17881788

17891789
BuiltinInst *createBuiltinTrap(SILLocation Loc) {

include/swift/SIL/SILCloner.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2447,7 +2447,8 @@ SILCloner<ImplClass>::visitCondFailInst(CondFailInst *Inst) {
24472447
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
24482448
recordClonedInstruction(
24492449
Inst, getBuilder().createCondFail(getOpLocation(Inst->getLoc()),
2450-
getOpValue(Inst->getOperand())));
2450+
getOpValue(Inst->getOperand()),
2451+
Inst->getMessage()));
24512452
}
24522453

24532454
template<typename ImplClass>

include/swift/SIL/SILInstruction.h

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6715,14 +6715,28 @@ class ProjectExistentialBoxInst
67156715
//===----------------------------------------------------------------------===//
67166716

67176717
/// Trigger a runtime failure if the given Int1 value is true.
6718-
class CondFailInst
6718+
///
6719+
/// Optionally cond_fail has a static failure message, which is displayed in the debugger in case the failure
6720+
/// is triggered.
6721+
class CondFailInst final
67196722
: public UnaryInstructionBase<SILInstructionKind::CondFailInst,
6720-
NonValueInstruction>
6723+
NonValueInstruction>,
6724+
private llvm::TrailingObjects<CondFailInst, char>
67216725
{
6726+
friend TrailingObjects;
67226727
friend SILBuilder;
67236728

6724-
CondFailInst(SILDebugLocation DebugLoc, SILValue Operand)
6725-
: UnaryInstructionBase(DebugLoc, Operand) {}
6729+
unsigned MessageSize;
6730+
6731+
CondFailInst(SILDebugLocation DebugLoc, SILValue Operand, StringRef Message);
6732+
6733+
static CondFailInst *create(SILDebugLocation DebugLoc, SILValue Operand,
6734+
StringRef Message, SILModule &M);
6735+
6736+
public:
6737+
StringRef getMessage() const {
6738+
return {getTrailingObjects<char>(), MessageSize};
6739+
}
67266740
};
67276741

67286742
//===----------------------------------------------------------------------===//

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 500; // dependency types for protocols
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 501; // cond_fail messages
5656

5757
using DeclIDField = BCFixed<31>;
5858

lib/AST/Builtins.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1037,8 +1037,9 @@ static ValueDecl *getCanBeObjCClassOperation(ASTContext &Context,
10371037
static ValueDecl *getCondFailOperation(ASTContext &C, Identifier Id) {
10381038
// Int1 -> ()
10391039
auto CondTy = BuiltinIntegerType::get(1, C);
1040+
auto MsgTy = C.TheRawPointerType;
10401041
auto VoidTy = TupleType::getEmpty(C);
1041-
return getBuiltinFunction(Id, {CondTy}, VoidTy);
1042+
return getBuiltinFunction(Id, {CondTy, MsgTy}, VoidTy);
10421043
}
10431044

10441045
static ValueDecl *getAssertConfOperation(ASTContext &C, Identifier Id) {

lib/IRGen/GenBuiltin.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
204204

205205
// Emit non-mergeable traps only.
206206
if (IGF.Builder.isTrapIntrinsic(IID)) {
207-
IGF.Builder.CreateNonMergeableTrap(IGF.IGM);
207+
IGF.Builder.CreateNonMergeableTrap(IGF.IGM, StringRef());
208208
return;
209209
}
210210

@@ -359,7 +359,8 @@ if (Builtin.ID == BuiltinValueKind::id) { \
359359
// string literal. If we ever get to the point of executing this builtin
360360
// at run time, it implies an incorrect use of the builtin and must result
361361
// in a trap.
362-
IGF.emitTrap(/*Unreachable=*/false);
362+
IGF.emitTrap("invalid use of globalStringTablePointer",
363+
/*Unreachable=*/false);
363364
auto returnValue = llvm::UndefValue::get(IGF.IGM.Int8PtrTy);
364365
// Consume the arguments of the builtin.
365366
(void)args.claimAll();

lib/IRGen/GenCast.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ emitExistentialScalarCastFn(IRGenModule &IGM,
469469
}
470470

471471
case CheckedCastMode::Unconditional: {
472-
IGF.emitTrap(/*EmitUnreachable=*/true);
472+
IGF.emitTrap("type cast failed", /*EmitUnreachable=*/true);
473473
break;
474474
}
475475
}

lib/IRGen/IRBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ class IRBuilder : public IRBuilderBase {
307307
/// Call the trap intrinsic. If optimizations are enabled, an inline asm
308308
/// gadget is emitted before the trap. The gadget inhibits transforms which
309309
/// merge trap calls together, which makes debugging crashes easier.
310-
llvm::CallInst *CreateNonMergeableTrap(IRGenModule &IGM);
310+
llvm::CallInst *CreateNonMergeableTrap(IRGenModule &IGM, StringRef failureMsg);
311311

312312
/// Split a first-class aggregate value into its component pieces.
313313
template <unsigned N>

0 commit comments

Comments
 (0)