diff --git a/docs/SIL.rst b/docs/SIL.rst index b5f73114541d1..69c2d54002984 100644 --- a/docs/SIL.rst +++ b/docs/SIL.rst @@ -5110,13 +5110,15 @@ cond_fail ````````` :: - sil-instruction ::= 'cond_fail' sil-operand + sil-instruction ::= 'cond_fail' sil-operand, string-literal - cond_fail %0 : $Builtin.Int1 + cond_fail %0 : $Builtin.Int1, "failure reason" // %0 must be of type $Builtin.Int1 This instruction produces a `runtime failure`_ if the operand is one. Execution proceeds normally if the operand is zero. +The second operand is a static failure message, which is displayed by the +debugger in case the failure is triggered. Terminators ~~~~~~~~~~~ diff --git a/include/swift/AST/Builtins.def b/include/swift/AST/Builtins.def index 5049ad631a048..06e3e4832adf0 100644 --- a/include/swift/AST/Builtins.def +++ b/include/swift/AST/Builtins.def @@ -314,10 +314,6 @@ BUILTIN_SIL_OPERATION(BeginUnpairedModifyAccess, "beginUnpairedModifyAccess", /// be a pointer to an UnsafeValueBuffer that records an in progress access. BUILTIN_SIL_OPERATION(EndUnpairedAccess, "endUnpairedAccess", Special) -/// condfail(Int1) -> () -/// Triggers a runtime failure if the condition is true. -BUILTIN_SIL_OPERATION(CondFail, "condfail", Special) - /// fixLifetime(T) -> () /// Fixes the lifetime of any heap references in a value. BUILTIN_SIL_OPERATION(FixLifetime, "fixLifetime", Special) @@ -404,6 +400,10 @@ BUILTIN_RUNTIME_CALL(IsOptionalType, "isOptional", "") BUILTIN(Id, Name, Attrs) #endif +/// condfail(Int1, RawPointer) -> () +/// Triggers a runtime failure if the condition is true. +BUILTIN_MISC_OPERATION(CondFail, "condfail", "", Special) + /// Sizeof has type T.Type -> Int BUILTIN_MISC_OPERATION(Sizeof, "sizeof", "n", Special) diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h index 6b24c40e73e1a..9ee2d5c7c70d5 100644 --- a/include/swift/SIL/SILBuilder.h +++ b/include/swift/SIL/SILBuilder.h @@ -1775,15 +1775,15 @@ class SILBuilder { //===--------------------------------------------------------------------===// CondFailInst *createCondFail(SILLocation Loc, SILValue Operand, - bool Inverted = false) { + StringRef Message, bool Inverted = false) { if (Inverted) { SILType Ty = Operand->getType(); SILValue True(createIntegerLiteral(Loc, Ty, 1)); Operand = createBuiltinBinaryFunction(Loc, "xor", Ty, Ty, {Operand, True}); } - return insert(new (getModule()) - CondFailInst(getSILDebugLocation(Loc), Operand)); + return insert(CondFailInst::create(getSILDebugLocation(Loc), Operand, + Message, getModule())); } BuiltinInst *createBuiltinTrap(SILLocation Loc) { diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index 223facefbabc5..42859fbc52ab3 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -2447,7 +2447,8 @@ SILCloner::visitCondFailInst(CondFailInst *Inst) { getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); recordClonedInstruction( Inst, getBuilder().createCondFail(getOpLocation(Inst->getLoc()), - getOpValue(Inst->getOperand()))); + getOpValue(Inst->getOperand()), + Inst->getMessage())); } template diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h index 75668acc62a26..a4dddb5b52c3b 100644 --- a/include/swift/SIL/SILInstruction.h +++ b/include/swift/SIL/SILInstruction.h @@ -6715,14 +6715,28 @@ class ProjectExistentialBoxInst //===----------------------------------------------------------------------===// /// Trigger a runtime failure if the given Int1 value is true. -class CondFailInst +/// +/// Optionally cond_fail has a static failure message, which is displayed in the debugger in case the failure +/// is triggered. +class CondFailInst final : public UnaryInstructionBase + NonValueInstruction>, + private llvm::TrailingObjects { + friend TrailingObjects; friend SILBuilder; - CondFailInst(SILDebugLocation DebugLoc, SILValue Operand) - : UnaryInstructionBase(DebugLoc, Operand) {} + unsigned MessageSize; + + CondFailInst(SILDebugLocation DebugLoc, SILValue Operand, StringRef Message); + + static CondFailInst *create(SILDebugLocation DebugLoc, SILValue Operand, + StringRef Message, SILModule &M); + +public: + StringRef getMessage() const { + return {getTrailingObjects(), MessageSize}; + } }; //===----------------------------------------------------------------------===// diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h index 501514650f58e..361119b98207e 100644 --- a/include/swift/Serialization/ModuleFormat.h +++ b/include/swift/Serialization/ModuleFormat.h @@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 500; // dependency types for protocols +const uint16_t SWIFTMODULE_VERSION_MINOR = 501; // cond_fail messages using DeclIDField = BCFixed<31>; diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp index 546f05a6217f9..71479b1df13e4 100644 --- a/lib/AST/Builtins.cpp +++ b/lib/AST/Builtins.cpp @@ -1037,8 +1037,9 @@ static ValueDecl *getCanBeObjCClassOperation(ASTContext &Context, static ValueDecl *getCondFailOperation(ASTContext &C, Identifier Id) { // Int1 -> () auto CondTy = BuiltinIntegerType::get(1, C); + auto MsgTy = C.TheRawPointerType; auto VoidTy = TupleType::getEmpty(C); - return getBuiltinFunction(Id, {CondTy}, VoidTy); + return getBuiltinFunction(Id, {CondTy, MsgTy}, VoidTy); } static ValueDecl *getAssertConfOperation(ASTContext &C, Identifier Id) { diff --git a/lib/IRGen/GenBuiltin.cpp b/lib/IRGen/GenBuiltin.cpp index e41ba16e60ebe..40537f6e79181 100644 --- a/lib/IRGen/GenBuiltin.cpp +++ b/lib/IRGen/GenBuiltin.cpp @@ -204,7 +204,7 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin, // Emit non-mergeable traps only. if (IGF.Builder.isTrapIntrinsic(IID)) { - IGF.Builder.CreateNonMergeableTrap(IGF.IGM); + IGF.Builder.CreateNonMergeableTrap(IGF.IGM, StringRef()); return; } @@ -359,7 +359,8 @@ if (Builtin.ID == BuiltinValueKind::id) { \ // string literal. If we ever get to the point of executing this builtin // at run time, it implies an incorrect use of the builtin and must result // in a trap. - IGF.emitTrap(/*Unreachable=*/false); + IGF.emitTrap("invalid use of globalStringTablePointer", + /*Unreachable=*/false); auto returnValue = llvm::UndefValue::get(IGF.IGM.Int8PtrTy); // Consume the arguments of the builtin. (void)args.claimAll(); diff --git a/lib/IRGen/GenCast.cpp b/lib/IRGen/GenCast.cpp index 47fec65f1fdb3..5ab80e382fbfd 100644 --- a/lib/IRGen/GenCast.cpp +++ b/lib/IRGen/GenCast.cpp @@ -469,7 +469,7 @@ emitExistentialScalarCastFn(IRGenModule &IGM, } case CheckedCastMode::Unconditional: { - IGF.emitTrap(/*EmitUnreachable=*/true); + IGF.emitTrap("type cast failed", /*EmitUnreachable=*/true); break; } } diff --git a/lib/IRGen/IRBuilder.h b/lib/IRGen/IRBuilder.h index a98287af703af..4c558d32c8652 100644 --- a/lib/IRGen/IRBuilder.h +++ b/lib/IRGen/IRBuilder.h @@ -307,7 +307,7 @@ class IRBuilder : public IRBuilderBase { /// Call the trap intrinsic. If optimizations are enabled, an inline asm /// gadget is emitted before the trap. The gadget inhibits transforms which /// merge trap calls together, which makes debugging crashes easier. - llvm::CallInst *CreateNonMergeableTrap(IRGenModule &IGM); + llvm::CallInst *CreateNonMergeableTrap(IRGenModule &IGM, StringRef failureMsg); /// Split a first-class aggregate value into its component pieces. template diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index c6437285892b7..b7ab08248ddab 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -148,6 +148,9 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { void setCurrentLoc(IRBuilder &Builder, const SILDebugScope *DS, SILLocation Loc); + + void addFailureMessageToCurrentLoc(IRBuilder &Builder, StringRef failureMsg); + void clearLoc(IRBuilder &Builder); void pushLoc(); void popLoc(); @@ -1828,7 +1831,37 @@ void IRGenDebugInfoImpl::setCurrentLoc(IRBuilder &Builder, auto DL = llvm::DebugLoc::get(L.Line, L.Column, Scope, InlinedAt); Builder.SetCurrentDebugLocation(DL); } + +void IRGenDebugInfoImpl::addFailureMessageToCurrentLoc(IRBuilder &Builder, + StringRef failureMsg) { + auto TrapLoc = Builder.getCurrentDebugLocation(); + + // Create a function in the debug info which has failureMsg as name. + // TrapSc is the SIL debug scope which corresponds to TrapSP in the LLVM debug + // info. + RegularLocation ALoc = RegularLocation::getAutoGeneratedLocation(); + const SILDebugScope *TrapSc = new (IGM.getSILModule()) SILDebugScope(ALoc); + + llvm::DISubroutineType *DIFnTy = DBuilder.createSubroutineType(nullptr); + + std::string FuncName = "Swift runtime failure: "; + FuncName += failureMsg; + + llvm::DISubprogram *TrapSP = DBuilder.createFunction( + MainModule, StringRef(), FuncName, TrapLoc->getFile(), 0, DIFnTy, 0, + llvm::DINode::FlagArtificial, llvm::DISubprogram::SPFlagDefinition, + nullptr, nullptr, nullptr); + ScopeCache[TrapSc] = llvm::TrackingMDNodeRef(TrapSP); + LastScope = TrapSc; + + assert(parentScopesAreSane(TrapSc) && "parent scope sanity check failed"); + + // Wrap the existing TrapLoc into the failure function. + auto DL = llvm::DebugLoc::get(0, 0, TrapSP, TrapLoc); + Builder.SetCurrentDebugLocation(DL); +} + void IRGenDebugInfoImpl::clearLoc(IRBuilder &Builder) { LastDebugLoc = {}; LastScope = nullptr; @@ -2320,6 +2353,12 @@ void IRGenDebugInfo::setCurrentLoc(IRBuilder &Builder, const SILDebugScope *DS, static_cast(this)->setCurrentLoc(Builder, DS, Loc); } +void IRGenDebugInfo::addFailureMessageToCurrentLoc(IRBuilder &Builder, + StringRef failureMsg) { + static_cast(this)-> + addFailureMessageToCurrentLoc(Builder, failureMsg); +} + void IRGenDebugInfo::clearLoc(IRBuilder &Builder) { static_cast(this)->clearLoc(Builder); } diff --git a/lib/IRGen/IRGenDebugInfo.h b/lib/IRGen/IRGenDebugInfo.h index adac1ae134866..1a829811ba64e 100644 --- a/lib/IRGen/IRGenDebugInfo.h +++ b/lib/IRGen/IRGenDebugInfo.h @@ -59,6 +59,12 @@ class IRGenDebugInfo { void setCurrentLoc(IRBuilder &Builder, const SILDebugScope *DS, SILLocation Loc); + /// Replace the current debug location in \p Builder with the same location, but contained in an + /// inlined function which is named like \p failureMsg. + /// + /// This lets the debugger display the \p failureMsg as an inlined function frame. + void addFailureMessageToCurrentLoc(IRBuilder &Builder, StringRef failureMsg); + void clearLoc(IRBuilder &Builder); /// Push the current debug location onto a stack and initialize the diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp index 9326963a5025e..4eb3118264e75 100644 --- a/lib/IRGen/IRGenFunction.cpp +++ b/lib/IRGen/IRGenFunction.cpp @@ -31,6 +31,10 @@ using namespace swift; using namespace irgen; +static llvm::cl::opt EnableTrapDebugInfo( + "enable-trap-debug-info", llvm::cl::Hidden, + llvm::cl::desc("Generate failure-message functions in the debug info")); + IRGenFunction::IRGenFunction(IRGenModule &IGM, llvm::Function *Fn, OptimizationMode OptMode, const SILDebugScope *DbgScope, @@ -432,7 +436,8 @@ Address IRGenFunction::emitAddressAtOffset(llvm::Value *base, Offset offset, return Address(slotPtr, objectAlignment); } -llvm::CallInst *IRBuilder::CreateNonMergeableTrap(IRGenModule &IGM) { +llvm::CallInst *IRBuilder::CreateNonMergeableTrap(IRGenModule &IGM, + StringRef failureMsg) { if (IGM.IRGen.Opts.shouldOptimize()) { // Emit unique side-effecting inline asm calls in order to eliminate // the possibility that an LLVM optimization or code generation pass @@ -452,13 +457,16 @@ llvm::CallInst *IRBuilder::CreateNonMergeableTrap(IRGenModule &IGM) { // Emit the trap instruction. llvm::Function *trapIntrinsic = llvm::Intrinsic::getDeclaration(&IGM.Module, llvm::Intrinsic::ID::trap); + if (EnableTrapDebugInfo && IGM.DebugInfo && !failureMsg.empty()) { + IGM.DebugInfo->addFailureMessageToCurrentLoc(*this, failureMsg); + } auto Call = IRBuilderBase::CreateCall(trapIntrinsic, {}); setCallingConvUsingCallee(Call); return Call; } -void IRGenFunction::emitTrap(bool EmitUnreachable) { - Builder.CreateNonMergeableTrap(IGM); +void IRGenFunction::emitTrap(StringRef failureMessage, bool EmitUnreachable) { + Builder.CreateNonMergeableTrap(IGM, failureMessage); if (EmitUnreachable) Builder.CreateUnreachable(); } diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h index c0c5b98f0e9c2..905a3bb2a4337 100644 --- a/lib/IRGen/IRGenFunction.h +++ b/lib/IRGen/IRGenFunction.h @@ -287,7 +287,7 @@ class IRGenFunction { void setDereferenceableLoad(llvm::LoadInst *load, unsigned size); /// Emit a non-mergeable trap call, optionally followed by a terminator. - void emitTrap(bool EmitUnreachable); + void emitTrap(StringRef failureMessage, bool EmitUnreachable); private: llvm::Instruction *AllocaIP; diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index 20ffaa02cf1b9..4a7092ba87857 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -3880,7 +3880,7 @@ static bool hasReferenceSemantics(IRGenSILFunction &IGF, static llvm::Value *emitIsUnique(IRGenSILFunction &IGF, SILValue operand, SourceLoc loc) { if (!hasReferenceSemantics(IGF, operand->getType())) { - IGF.emitTrap(/*EmitUnreachable=*/false); + IGF.emitTrap("isUnique called for a non-reference", /*EmitUnreachable=*/false); return llvm::UndefValue::get(IGF.IGM.Int1Ty); } @@ -4540,7 +4540,7 @@ static void emitTrapAndUndefValue(IRGenSILFunction &IGF, IGF.FailBBs.push_back(failBB); IGF.Builder.emitBlock(failBB); - IGF.emitTrap(/*EmitUnreachable=*/true); + IGF.emitTrap("mismatching type layouts", /*EmitUnreachable=*/true); llvm::BasicBlock *contBB = llvm::BasicBlock::Create(IGF.IGM.getLLVMContext()); IGF.Builder.emitBlock(contBB); @@ -5441,7 +5441,7 @@ void IRGenSILFunction::visitCondFailInst(swift::CondFailInst *i) { // debug location. This is because zero is not an artificial line location // in CodeView. IGM.DebugInfo->setInlinedTrapLocation(Builder, i->getDebugScope()); - emitTrap(/*EmitUnreachable=*/true); + emitTrap(i->getMessage(), /*EmitUnreachable=*/true); Builder.emitBlock(contBB); FailBBs.push_back(failBB); } diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp index 6adc7b8f2d685..c608c8c843f86 100644 --- a/lib/ParseSIL/ParseSIL.cpp +++ b/lib/ParseSIL/ParseSIL.cpp @@ -2635,6 +2635,33 @@ bool SILParser::parseSILInstruction(SILBuilder &B) { break; } + case SILInstructionKind::CondFailInst: { + + if (parseTypedValueRef(Val, B)) + return true; + + SmallVector stringBuffer; + StringRef message; + if (P.consumeIf(tok::comma)) { + // Parse the string. + if (P.Tok.getKind() != tok::string_literal) { + P.diagnose(P.Tok, diag::expected_tok_in_sil_instr, "string"); + return true; + } + SmallVector segments; + P.L->getStringLiteralSegments(P.Tok, segments); + assert(segments.size() == 1); + + P.consumeToken(tok::string_literal); + message = P.L->getEncodedStringSegment(segments.front(), stringBuffer); + } + if (parseSILDebugLocation(InstLoc, B)) + return true; + + ResultVal = B.createCondFail(InstLoc, Val, message); + break; + } + case SILInstructionKind::AllocValueBufferInst: { SILType Ty; if (parseSILType(Ty) || @@ -2887,7 +2914,6 @@ bool SILParser::parseSILInstruction(SILBuilder &B) { UNARY_INSTRUCTION(DestroyAddr) UNARY_INSTRUCTION(CopyValue) UNARY_INSTRUCTION(DestroyValue) - UNARY_INSTRUCTION(CondFail) UNARY_INSTRUCTION(EndBorrow) UNARY_INSTRUCTION(DestructureStruct) UNARY_INSTRUCTION(DestructureTuple) diff --git a/lib/SIL/OperandOwnership.cpp b/lib/SIL/OperandOwnership.cpp index 9012751e73f31..966485f8328a3 100644 --- a/lib/SIL/OperandOwnership.cpp +++ b/lib/SIL/OperandOwnership.cpp @@ -953,6 +953,7 @@ ANY_OWNERSHIP_BUILTIN(AtomicRMW) ANY_OWNERSHIP_BUILTIN(AtomicStore) ANY_OWNERSHIP_BUILTIN(BitCast) ANY_OWNERSHIP_BUILTIN(CanBeObjCClass) +ANY_OWNERSHIP_BUILTIN(CondFail) ANY_OWNERSHIP_BUILTIN(CmpXChg) ANY_OWNERSHIP_BUILTIN(CondUnreachable) ANY_OWNERSHIP_BUILTIN(CopyArray) diff --git a/lib/SIL/SILInstructions.cpp b/lib/SIL/SILInstructions.cpp index 8137a6468791c..3043735cf9939 100644 --- a/lib/SIL/SILInstructions.cpp +++ b/lib/SIL/SILInstructions.cpp @@ -773,6 +773,21 @@ StringLiteralInst *StringLiteralInst::create(SILDebugLocation Loc, return ::new (buf) StringLiteralInst(Loc, text, encoding, Ty); } +CondFailInst::CondFailInst(SILDebugLocation DebugLoc, SILValue Operand, + StringRef Message) + : UnaryInstructionBase(DebugLoc, Operand), + MessageSize(Message.size()) { + memcpy(getTrailingObjects(), Message.data(), Message.size()); +} + +CondFailInst *CondFailInst::create(SILDebugLocation DebugLoc, SILValue Operand, + StringRef Message, SILModule &M) { + + auto Size = totalSizeToAlloc(Message.size()); + auto Buffer = M.allocateInst(Size, alignof(CondFailInst)); + return ::new (Buffer) CondFailInst(DebugLoc, Operand, Message); +} + uint64_t StringLiteralInst::getCodeUnitCount() { auto E = unsigned(Encoding::UTF16); if (SILInstruction::Bits.StringLiteralInst.TheEncoding == E) diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp index 95c4bad6ed891..d0f2f30f9a00d 100644 --- a/lib/SIL/SILPrinter.cpp +++ b/lib/SIL/SILPrinter.cpp @@ -1866,7 +1866,8 @@ class SILPrinter : public SILInstructionVisitor { } void visitCondFailInst(CondFailInst *FI) { - *this << getIDAndType(FI->getOperand()); + *this << getIDAndType(FI->getOperand()) << ", " + << QuotedString(FI->getMessage()); } void visitIndexAddrInst(IndexAddrInst *IAI) { diff --git a/lib/SIL/ValueOwnership.cpp b/lib/SIL/ValueOwnership.cpp index 379ee41eb67d0..6949c69ea0533 100644 --- a/lib/SIL/ValueOwnership.cpp +++ b/lib/SIL/ValueOwnership.cpp @@ -378,6 +378,7 @@ CONSTANT_OWNERSHIP_BUILTIN(Any, And) CONSTANT_OWNERSHIP_BUILTIN(Any, AssumeNonNegative) CONSTANT_OWNERSHIP_BUILTIN(Any, AssumeTrue) CONSTANT_OWNERSHIP_BUILTIN(Any, BitCast) +CONSTANT_OWNERSHIP_BUILTIN(Any, CondFail) CONSTANT_OWNERSHIP_BUILTIN(Any, ExactSDiv) CONSTANT_OWNERSHIP_BUILTIN(Any, ExactUDiv) CONSTANT_OWNERSHIP_BUILTIN(Any, FAdd) diff --git a/lib/SILGen/SILGenBuiltin.cpp b/lib/SILGen/SILGenBuiltin.cpp index cc1c9dcd866ca..bc8ef800fe7ae 100644 --- a/lib/SILGen/SILGenBuiltin.cpp +++ b/lib/SILGen/SILGenBuiltin.cpp @@ -618,18 +618,6 @@ static ManagedValue emitBuiltinEndUnpairedAccess(SILGenFunction &SGF, return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc)); } -/// Specialized emitter for Builtin.condfail. -static ManagedValue emitBuiltinCondFail(SILGenFunction &SGF, - SILLocation loc, - SubstitutionMap substitutions, - ArrayRef args, - SGFContext C) { - assert(args.size() == 1 && "condfail should be given one argument"); - - SGF.B.createCondFail(loc, args[0].getUnmanagedValue()); - return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc)); -} - /// Specialized emitter for Builtin.castReference. static ManagedValue emitBuiltinCastReference(SILGenFunction &SGF, diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 742b8dc107070..21b7779f720b9 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -4851,7 +4851,7 @@ RValue RValueEmitter::emitForceValue(ForceValueExpr *loc, Expr *E, failureBuilder.setTrackingList(SGF.getBuilder().getTrackingList()); auto boolTy = SILType::getBuiltinIntegerType(1, SGF.getASTContext()); auto trueV = failureBuilder.createIntegerLiteral(loc, boolTy, 1); - failureBuilder.createCondFail(loc, trueV); + failureBuilder.createCondFail(loc, trueV, "force unwrapped a nil value"); failureBuilder.createUnreachable(loc); } } @@ -4990,7 +4990,7 @@ RValue RValueEmitter::visitMakeTemporarilyEscapableExpr( auto isEscaping = SGF.B.createIsEscapingClosure( loc, borrowedClosure.getValue(), IsEscapingClosureInst::WithoutActuallyEscaping); - SGF.B.createCondFail(loc, isEscaping); + SGF.B.createCondFail(loc, isEscaping, "non-escaping closure has escaped"); return rvalue; } diff --git a/lib/SILOptimizer/Analysis/SimplifyInstruction.cpp b/lib/SILOptimizer/Analysis/SimplifyInstruction.cpp index 17fe07bcd2193..914650a6bda91 100644 --- a/lib/SILOptimizer/Analysis/SimplifyInstruction.cpp +++ b/lib/SILOptimizer/Analysis/SimplifyInstruction.cpp @@ -454,6 +454,19 @@ SILValue InstSimplifier::visitBeginAccessInst(BeginAccessInst *BAI) { } static SILValue simplifyBuiltin(BuiltinInst *BI) { + + switch (BI->getBuiltinInfo().ID) { + case BuiltinValueKind::IntToPtr: + if (auto *OpBI = dyn_cast(BI->getOperand(0))) { + if (OpBI->getBuiltinInfo().ID == BuiltinValueKind::PtrToInt) { + return OpBI->getOperand(0); + } + } + return SILValue(); + default: + break; + } + const IntrinsicInfo &Intrinsic = BI->getIntrinsicInfo(); switch (Intrinsic.ID) { diff --git a/lib/SILOptimizer/LoopTransforms/ArrayBoundsCheckOpts.cpp b/lib/SILOptimizer/LoopTransforms/ArrayBoundsCheckOpts.cpp index ccecaaa25f939..218cfdd2e3bd9 100644 --- a/lib/SILOptimizer/LoopTransforms/ArrayBoundsCheckOpts.cpp +++ b/lib/SILOptimizer/LoopTransforms/ArrayBoundsCheckOpts.cpp @@ -712,7 +712,7 @@ struct InductionInfo { auto ResultTy = SILType::getBuiltinIntegerType(1, Builder.getASTContext()); auto *CmpSGE = Builder.createBuiltinBinaryFunction( Loc, "cmp_sge", Start->getType(), ResultTy, {Start, End}); - Builder.createCondFail(Loc, CmpSGE); + Builder.createCondFail(Loc, CmpSGE, "loop induction variable overflowed"); IsOverflowCheckInserted = true; // We can now remove the cond fail on the increment the above comparison diff --git a/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp b/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp index cc00c8c79b2c1..126b67ae87190 100644 --- a/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp +++ b/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp @@ -691,7 +691,7 @@ static bool fixupCopyBlockWithoutEscaping(CopyBlockWithoutEscapingInst *cb, SILValue v = sentinelClosure; SILValue isEscaping = b.createIsEscapingClosure( loc, v, IsEscapingClosureInst::ObjCEscaping); - b.createCondFail(loc, isEscaping); + b.createCondFail(loc, isEscaping, "non-escaping closure has escaped"); b.createDestroyValue(loc, v); return true; } @@ -705,7 +705,7 @@ static bool fixupCopyBlockWithoutEscaping(CopyBlockWithoutEscapingInst *cb, SILValue V = sentinelClosure; SILValue isEscaping = B.createIsEscapingClosure( loc, V, IsEscapingClosureInst::ObjCEscaping); - B.createCondFail(loc, isEscaping); + B.createCondFail(loc, isEscaping, "non-escaping closure has escaped"); B.createDestroyValue(loc, V); } @@ -773,7 +773,7 @@ static bool fixupCopyBlockWithoutEscaping(CopyBlockWithoutEscapingInst *cb, SILValue v = updater.GetValueInMiddleOfBlock(singleDestroy->getParent()); SILValue isEscaping = b.createIsEscapingClosure(loc, v, IsEscapingClosureInst::ObjCEscaping); - b.createCondFail(loc, isEscaping); + b.createCondFail(loc, isEscaping, "non-escaping closure has escaped"); b.createDestroyValue(loc, v); } diff --git a/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp b/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp index c87b54135f8dc..3269d4c0c7289 100644 --- a/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp +++ b/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp @@ -48,16 +48,23 @@ static bool cleanFunction(SILFunction &fn) { continue; } - const BuiltinInfo &bInfo = bi->getBuiltinInfo(); - if (bInfo.ID != BuiltinValueKind::PoundAssert && - bInfo.ID != BuiltinValueKind::StaticReport) { - continue; + switch (bi->getBuiltinInfo().ID) { + case BuiltinValueKind::CondFail: { + SILBuilderWithScope Builder(bi); + Builder.createCondFail(bi->getLoc(), bi->getOperand(0), + "unknown program error"); + LLVM_FALLTHROUGH; + } + case BuiltinValueKind::PoundAssert: + case BuiltinValueKind::StaticReport: + // The call to the builtin should get removed before we reach + // IRGen. + recursivelyDeleteTriviallyDeadInstructions(bi, /* Force */ true); + madeChange = true; + break; + default: + break; } - - // The call to the builtin should get removed before we reach - // IRGen. - recursivelyDeleteTriviallyDeadInstructions(bi, /* Force */ true); - madeChange = true; } } diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp index 1c538ffdcdc5f..6f5edb7cf6e90 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp @@ -622,6 +622,15 @@ SILInstruction *SILCombiner::visitBuiltinInst(BuiltinInst *I) { } break; } + case BuiltinValueKind::CondFail: + if (auto *SLI = dyn_cast(I->getOperand(1))) { + if (SLI->getEncoding() == StringLiteralInst::Encoding::UTF8) { + Builder.createCondFail(I->getLoc(), I->getOperand(0), SLI->getValue()); + eraseInstFromFunction(*I); + return nullptr; + } + } + break; default: break; } diff --git a/lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp b/lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp index 049a258ac77c9..ae2150c5edb42 100644 --- a/lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp +++ b/lib/SILOptimizer/Transforms/AccessEnforcementReleaseSinking.cpp @@ -129,6 +129,7 @@ static bool isBarrier(SILInstruction *inst) { case BuiltinValueKind::GetObjCTypeEncoding: case BuiltinValueKind::Swift3ImplicitObjCEntrypoint: case BuiltinValueKind::WillThrow: + case BuiltinValueKind::CondFail: case BuiltinValueKind::PoundAssert: case BuiltinValueKind::GlobalStringTablePointer: return false; diff --git a/lib/SILOptimizer/Transforms/MergeCondFail.cpp b/lib/SILOptimizer/Transforms/MergeCondFail.cpp index e2065864a226e..e8ad4f8fc5c51 100644 --- a/lib/SILOptimizer/Transforms/MergeCondFail.cpp +++ b/lib/SILOptimizer/Transforms/MergeCondFail.cpp @@ -69,7 +69,9 @@ class MergeCondFailInsts : public SILFunctionTransform { // Do not process arithmetic overflow checks. We typically generate more // efficient code with separate jump-on-overflow. - if (CFI && !hasOverflowConditionOperand(CFI)) + if (CFI && !hasOverflowConditionOperand(CFI) && + (CondFailToMerge.empty() || + CFI->getMessage() == CondFailToMerge.front()->getMessage())) CondFailToMerge.push_back(CFI); } @@ -109,12 +111,15 @@ class MergeCondFailInsts : public SILFunctionTransform { {MergedCond, CurCond}); } - CondFailToMerge[I]->eraseFromParent(); MergedCond = CurCond; } // Create a new cond_fail using the merged condition. - Builder.createCondFail(Loc, MergedCond); + Builder.createCondFail(Loc, MergedCond, LastCFI->getMessage()); + + for (CondFailInst *CFI : CondFailToMerge) { + CFI->eraseFromParent(); + } return true; } }; diff --git a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp index 38a0c4cbf756f..1e37a33c7424b 100644 --- a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp +++ b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp @@ -1399,9 +1399,9 @@ static CondFailInst *getUnConditionalFail(SILBasicBlock *BB, SILValue Cond, /// Creates a new cond_fail instruction, optionally with an xor inverted /// condition. -static void createCondFail(CondFailInst *Orig, SILValue Cond, bool inverted, - SILBuilder &Builder) { - Builder.createCondFail(Orig->getLoc(), Cond, inverted); +static void createCondFail(CondFailInst *Orig, SILValue Cond, StringRef Message, + bool inverted, SILBuilder &Builder) { + Builder.createCondFail(Orig->getLoc(), Cond, Message, inverted); } /// Inverts the expected value of 'PotentialExpect' (if it is an expect @@ -1643,7 +1643,7 @@ bool SimplifyCFG::simplifyCondBrBlock(CondBranchInst *BI) { if (auto *TrueCFI = getUnConditionalFail(TrueSide, CFCondition, false)) { LLVM_DEBUG(llvm::dbgs() << "replace with cond_fail:" << *BI); SILBuilderWithScope Builder(BI); - createCondFail(TrueCFI, CFCondition, false, Builder); + createCondFail(TrueCFI, CFCondition, TrueCFI->getMessage(), false, Builder); SILBuilderWithScope(BI).createBranch(BI->getLoc(), FalseSide, FalseArgs); BI->eraseFromParent(); @@ -1655,7 +1655,7 @@ bool SimplifyCFG::simplifyCondBrBlock(CondBranchInst *BI) { if (auto *FalseCFI = getUnConditionalFail(FalseSide, CFCondition, true)) { LLVM_DEBUG(llvm::dbgs() << "replace with inverted cond_fail:" << *BI); SILBuilderWithScope Builder(BI); - createCondFail(FalseCFI, CFCondition, true, Builder); + createCondFail(FalseCFI, CFCondition, FalseCFI->getMessage(), true, Builder); SILBuilderWithScope(BI).createBranch(BI->getLoc(), TrueSide, TrueArgs); BI->eraseFromParent(); @@ -2497,7 +2497,7 @@ static bool tryMoveCondFailToPreds(SILBasicBlock *BB) { SILValue incoming = condArg->getIncomingPhiValue(Pred); SILBuilderWithScope Builder(Pred->getTerminator()); - createCondFail(CFI, incoming, inverted, Builder); + createCondFail(CFI, incoming, CFI->getMessage(), inverted, Builder); } CFI->eraseFromParent(); return true; diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 8ec5b6bc9460f..b258bf597d770 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -1617,6 +1617,13 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, encoding.getValue()); break; } + case SILInstructionKind::CondFailInst: { + SILValue Op = getLocalValue(ValID, getSILType(MF->getType(TyID), \ + (SILValueCategory)TyCategory)); + StringRef StringVal = MF->getIdentifierText(ValID2); + ResultVal = Builder.createCondFail(Loc, Op, StringVal); + break; + } case SILInstructionKind::MarkFunctionEscapeInst: { // Format: a list of typed values. A typed value is expressed by 4 IDs: // TypeID, TypeCategory, ValueID, ValueResultNumber. @@ -1664,7 +1671,6 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, REFCOUNTING_INSTRUCTION(StrongRetain##Name) \ UNARY_INSTRUCTION(Copy##Name##Value) #include "swift/AST/ReferenceStorage.def" - UNARY_INSTRUCTION(CondFail) REFCOUNTING_INSTRUCTION(RetainValue) REFCOUNTING_INSTRUCTION(RetainValueAddr) REFCOUNTING_INSTRUCTION(UnmanagedRetainValue) diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index a5cc2e677fe25..82649e966d799 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -1230,7 +1230,6 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) { NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, "...") \ ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, "...") #include "swift/AST/ReferenceStorage.def" - case SILInstructionKind::CondFailInst: case SILInstructionKind::RetainValueInst: case SILInstructionKind::DestructureStructInst: case SILInstructionKind::DestructureTupleInst: @@ -1399,6 +1398,18 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) { S.addTypeRef(TAI->getTailType().getASTType())); break; } + case SILInstructionKind::CondFailInst: { + auto *CFI = cast(&SI); + SILValue operand = CFI->getOperand(); + SILTwoOperandsLayout::emitRecord(Out, ScratchRecord, + SILAbbrCodes[SILTwoOperandsLayout::Code], + (unsigned)SI.getKind(), /*attributes*/ 0, + S.addTypeRef(operand->getType().getASTType()), + (unsigned)operand->getType().getCategory(), + addValueRef(operand), + 0, 0, S.addUniquedStringRef(CFI->getMessage())); + break; + } case SILInstructionKind::StringLiteralInst: { auto SLI = cast(&SI); StringRef Str = SLI->getValue(); diff --git a/stdlib/public/core/Assert.swift b/stdlib/public/core/Assert.swift index c870ee6ff387b..f45a24e205621 100644 --- a/stdlib/public/core/Assert.swift +++ b/stdlib/public/core/Assert.swift @@ -93,7 +93,7 @@ public func precondition( } } else if _isReleaseAssertConfiguration() { let error = !condition() - Builtin.condfail(error._value) + Builtin.condfail(error._value, StaticString("precondition failure").unsafeRawPointer) } } @@ -171,7 +171,7 @@ public func preconditionFailure( _assertionFailure("Fatal error", message(), file: file, line: line, flags: _fatalErrorFlags()) } else if _isReleaseAssertConfiguration() { - Builtin.int_trap() + Builtin.condfail(true._value, StaticString("precondition failure").unsafeRawPointer) } _conditionallyUnreachable() } @@ -207,12 +207,12 @@ internal func _precondition( // Only check in debug and release mode. In release mode just trap. if _isDebugAssertConfiguration() { if !_fastPath(condition()) { - _fatalErrorMessage("Fatal error", message, file: file, line: line, + _assertionFailure("Fatal error", message, file: file, line: line, flags: _fatalErrorFlags()) } } else if _isReleaseAssertConfiguration() { let error = !condition() - Builtin.condfail(error._value) + Builtin.condfail(error._value, message.unsafeRawPointer) } } @@ -240,7 +240,7 @@ public func _overflowChecked( file: file, line: line, flags: _fatalErrorFlags()) } } else { - Builtin.condfail(error._value) + Builtin.condfail(error._value, StaticString("_overflowChecked failure").unsafeRawPointer) } return result } diff --git a/stdlib/public/core/AssertCommon.swift b/stdlib/public/core/AssertCommon.swift index b225cfe9c6fd1..a082cb0f574a1 100644 --- a/stdlib/public/core/AssertCommon.swift +++ b/stdlib/public/core/AssertCommon.swift @@ -172,35 +172,7 @@ internal func _fatalErrorMessage( file: StaticString, line: UInt, flags: UInt32 ) -> Never { -#if INTERNAL_CHECKS_ENABLED - prefix.withUTF8Buffer() { - (prefix) in - message.withUTF8Buffer() { - (message) in - file.withUTF8Buffer() { - (file) in - _swift_stdlib_reportFatalErrorInFile( - prefix.baseAddress!, CInt(prefix.count), - message.baseAddress!, CInt(message.count), - file.baseAddress!, CInt(file.count), UInt32(line), - flags) - } - } - } -#else - prefix.withUTF8Buffer() { - (prefix) in - message.withUTF8Buffer() { - (message) in - _swift_stdlib_reportFatalError( - prefix.baseAddress!, CInt(prefix.count), - message.baseAddress!, CInt(message.count), - flags) - } - } -#endif - - Builtin.int_trap() + _assertionFailure(prefix, message, file: file, line: line, flags: flags) } /// Prints a fatal error message when an unimplemented initializer gets diff --git a/stdlib/public/core/IntegerTypes.swift.gyb b/stdlib/public/core/IntegerTypes.swift.gyb index 794199d2e5b54..ed0630408ad1c 100644 --- a/stdlib/public/core/IntegerTypes.swift.gyb +++ b/stdlib/public/core/IntegerTypes.swift.gyb @@ -1234,7 +1234,7 @@ ${assignmentOperatorComment(x.operator, True)} Builtin.${u}${x.llvmName}_with_overflow_Int${bits}( lhs._value, rhs._value, true._value) % end - Builtin.condfail(overflow) + Builtin.condfail(overflow, StaticString("arithmetic overflow").unsafeRawPointer) lhs = ${Self}(result) } % end diff --git a/stdlib/public/core/Optional.swift b/stdlib/public/core/Optional.swift index 421a46f976167..1f1be2e74170e 100644 --- a/stdlib/public/core/Optional.swift +++ b/stdlib/public/core/Optional.swift @@ -302,14 +302,21 @@ func _diagnoseUnexpectedNilOptional(_filenameStart: Builtin.RawPointer, _isImplicitUnwrap: Builtin.Int1) { // Cannot use _preconditionFailure as the file and line info would not be // printed. - preconditionFailure( - Bool(_isImplicitUnwrap) - ? "Unexpectedly found nil while implicitly unwrapping an Optional value" - : "Unexpectedly found nil while unwrapping an Optional value", - file: StaticString(_start: _filenameStart, - utf8CodeUnitCount: _filenameLength, - isASCII: _filenameIsASCII), - line: UInt(_line)) + if Bool(_isImplicitUnwrap) { + _preconditionFailure( + "Unexpectedly found nil while implicitly unwrapping an Optional value", + file: StaticString(_start: _filenameStart, + utf8CodeUnitCount: _filenameLength, + isASCII: _filenameIsASCII), + line: UInt(_line)) + } else { + _preconditionFailure( + "Unexpectedly found nil while unwrapping an Optional value", + file: StaticString(_start: _filenameStart, + utf8CodeUnitCount: _filenameLength, + isASCII: _filenameIsASCII), + line: UInt(_line)) + } } extension Optional : Equatable where Wrapped : Equatable { diff --git a/stdlib/public/core/StaticString.swift b/stdlib/public/core/StaticString.swift index 10709dec53d70..fc3c0f287a033 100644 --- a/stdlib/public/core/StaticString.swift +++ b/stdlib/public/core/StaticString.swift @@ -94,6 +94,11 @@ public struct StaticString return Int(_utf8CodeUnitCount) } + @_alwaysEmitIntoClient @_transparent + internal var unsafeRawPointer: Builtin.RawPointer { + return Builtin.inttoptr_Word(_startPtrOrData) + } + /// A Boolean value indicating whether the static string stores a pointer to /// ASCII or UTF-8 code units. @_transparent diff --git a/test/DebugInfo/doubleinlines.swift b/test/DebugInfo/doubleinlines.swift index 00d80d86f312f..4be4cf10291e0 100644 --- a/test/DebugInfo/doubleinlines.swift +++ b/test/DebugInfo/doubleinlines.swift @@ -2,15 +2,15 @@ // RUN: -debug-info-format=codeview -O -parse-as-library \ // RUN: -module-name DoubleInlines -o - | %FileCheck %s -func condFail(arg: Builtin.Int1 ) { - Builtin.condfail(arg) +func condFail(arg: Builtin.Int1, msg: Builtin.RawPointer) { + Builtin.condfail(arg, msg) } -func callCondFail(arg: Builtin.Int1) { - condFail(arg: arg) +func callCondFail(arg: Builtin.Int1, msg: Builtin.RawPointer) { + condFail(arg: arg, msg: msg) } -// CHECK: define hidden swiftcc void @"$s13DoubleInlines12callCondFail3argyBi1__tF"{{.*}} !dbg ![[FUNCSCOPE:.*]] { +// CHECK: define hidden swiftcc void @"$s13DoubleInlines12callCondFail3arg3msgyBi1__BptF"{{.*}} !dbg ![[FUNCSCOPE:.*]] { // CHECK: tail call void asm sideeffect "", "n"(i32 0) #3, !dbg ![[SCOPEONE:.*]] // CHECK: ![[FUNCSCOPEOTHER:.*]] = distinct !DISubprogram(name: "condFail",{{.*}} // CHECK: ![[SCOPEFIVE:.*]] = distinct !DILexicalBlock(scope: ![[FUNCSCOPE]], file: ![[FILE:.*]], line: 9) diff --git a/test/DebugInfo/linetable-codeview.swift b/test/DebugInfo/linetable-codeview.swift index 778421dc1bbbd..19bdeefbf1108 100644 --- a/test/DebugInfo/linetable-codeview.swift +++ b/test/DebugInfo/linetable-codeview.swift @@ -1,4 +1,4 @@ -// RUN: %swiftc_driver %s -g -debug-info-format=codeview -emit-ir -o - | %FileCheck %s +// RUN: %swiftc_driver %s -g -debug-info-format=codeview -Xllvm -enable-trap-debug-info -emit-ir -o - | %FileCheck %s func markUsed(_ t: T) {} func arithmetic(_ a: Int64, _ b: Int64) { markUsed(a + b) // line 4 @@ -36,7 +36,7 @@ func foo() { // between other instructions for the division. We want to make sure // all instructions from the division have the same debug location and // are contiguous. - // CHECK: call {{.*}} @"$ss18_fatalErrorMessage__4file4line5flagss5NeverOs12StaticStringV_A2HSus6UInt32VtF"{{.*}}, !dbg ![[DIV:[0-9]+]] + // CHECK: call {{.*}} @"$ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_A2HSus6UInt32VtF"{{.*}}, !dbg ![[DIV:[0-9]+]] // CHECK-NEXT: unreachable, !dbg ![[DIV]] // CHECK: sdiv i64 %0, %1, !dbg ![[DIV]] // CHECK: call void @llvm.trap(), !dbg ![[INLINEDADD:[0-9]+]] @@ -78,7 +78,9 @@ func foo() { // CHECK-DAG: ![[DIV]] = !DILocation(line: 5, scope: // FIXME: The location of ``@llvm.trap`` should be in Integers.swift.gyb // instead of being artificial. -// CHECK-DAG: ![[INLINEDADD]] = !DILocation(line: 0, scope: !{{[0-9]+}}, inlinedAt: ![[ADD]] +// CHECK: ![[INLINEDADD]] = !DILocation(line: 0, scope: ![[FAILURE_FUNC:[0-9]+]], inlinedAt: ![[INLINELOC:[0-9]+]] +// CHECK-DAG: !{{.*}} = distinct !DISubprogram(linkageName: "Swift runtime failure: arithmetic overflow", scope: {{.*}}, flags: DIFlagArtificial, spFlags: DISPFlagDefinition, {{.*}}) +// CHECK-DAG: ![[INLINELOC]] = !DILocation(line: 0, scope: !{{[0-9]+}}, inlinedAt: ![[ADD]] // NOTE: These prologue instructions are given artificial line locations for // LLDB, but for CodeView they should have the location of the function diff --git a/test/IRGen/builtins.swift b/test/IRGen/builtins.swift index 85455ab1a2c6d..d5a1dda8b0461 100644 --- a/test/IRGen/builtins.swift +++ b/test/IRGen/builtins.swift @@ -1,5 +1,5 @@ -// RUN: %target-swift-frontend -module-name builtins -parse-stdlib -primary-file %s -emit-ir -o - -disable-objc-attr-requires-foundation-module | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime +// RUN: %target-swift-frontend -module-name builtins -parse-stdlib -disable-access-control -primary-file %s -emit-ir -o - -disable-objc-attr-requires-foundation-module | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime // REQUIRES: CPU=x86_64 @@ -315,10 +315,10 @@ func testStaticReport(_ b: Bool, ptr: Builtin.RawPointer) -> () { // CHECK-LABEL: define hidden {{.*}}void @"$s8builtins12testCondFail{{[_0-9a-zA-Z]*}}F"(i1, i1) func testCondFail(_ b: Bool, c: Bool) { // CHECK: br i1 %0, label %[[FAIL:.*]], label %[[CONT:.*]] - Builtin.condfail(b) + Builtin.condfail(b, StaticString("message").unsafeRawPointer) // CHECK: