Skip to content

Commit 05ccd97

Browse files
committed
SIL: Introduce ThrowAddrInst
1 parent a8d43c7 commit 05ccd97

29 files changed

+165
-31
lines changed

SwiftCompilerSources/Sources/SIL/Instruction.swift

+4
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,10 @@ final public class ThrowInst : TermInst, UnaryInstruction {
10941094
public override var isFunctionExiting: Bool { true }
10951095
}
10961096

1097+
final public class ThrowAddrInst : TermInst {
1098+
public override var isFunctionExiting: Bool { true }
1099+
}
1100+
10971101
final public class YieldInst : TermInst {
10981102
}
10991103

SwiftCompilerSources/Sources/SIL/Registration.swift

+1
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ public func registerSILClasses() {
172172
register(UnreachableInst.self)
173173
register(ReturnInst.self)
174174
register(ThrowInst.self)
175+
register(ThrowAddrInst.self)
175176
register(YieldInst.self)
176177
register(UnwindInst.self)
177178
register(TryApplyInst.self)

docs/SIL.rst

+24-2
Original file line numberDiff line numberDiff line change
@@ -613,8 +613,8 @@ the caller. A non-autoreleased ``apply`` of a function that is defined
613613
with an autoreleased result has the effect of performing an
614614
autorelease in the callee.
615615

616-
- SIL function types may provide an optional error result, written by
617-
placing ``@error`` on a result. An error result is always
616+
- SIL function types may provide an optional direct error result, written by
617+
placing ``@error`` on a result. A direct error result is always
618618
implicitly ``@owned``. Only functions with a native calling
619619
convention may have an error result.
620620

@@ -8006,6 +8006,28 @@ the basic block argument will be the operand of the ``throw``.
80068006

80078007
A function must not contain more than one ``throw`` instruction.
80088008

8009+
throw_addr
8010+
``````````
8011+
::
8012+
8013+
sil-terminator ::= 'throw_addr'
8014+
8015+
throw_addr
8016+
// indirect error result must be initialized at this point
8017+
8018+
Exits the current function and returns control to the calling
8019+
function. The current function must have an indirect error result,
8020+
and so the function must have been invoked with a ``try_apply``
8021+
instruction. Control will resume in the error destination of
8022+
that instruction.
8023+
8024+
The function is responsible for initializing its error result
8025+
before the ``throw_addr``.
8026+
8027+
``throw_addr`` does not retain or release any values.
8028+
8029+
A function must not contain more than one ``throw_addr`` instruction.
8030+
80098031
yield
80108032
`````
80118033
::

include/swift/SIL/AddressWalker.h

+1
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ TransitiveAddressWalker<Impl>::walk(SILValue projectedAddress) && {
150150

151151
case TermKind::UnreachableInst:
152152
case TermKind::UnwindInst:
153+
case TermKind::ThrowAddrInst:
153154
llvm_unreachable("Should never be used");
154155
case TermKind::SwitchEnumInst:
155156
case TermKind::SwitchValueInst:

include/swift/SIL/SILBuilder.h

+5
Original file line numberDiff line numberDiff line change
@@ -2484,6 +2484,11 @@ class SILBuilder {
24842484
new (getModule()) ThrowInst(getSILDebugLocation(Loc), errorValue));
24852485
}
24862486

2487+
ThrowAddrInst *createThrowAddr(SILLocation Loc) {
2488+
return insertTerminator(
2489+
new (getModule()) ThrowAddrInst(getSILDebugLocation(Loc)));
2490+
}
2491+
24872492
UnwindInst *createUnwind(SILLocation loc) {
24882493
return insertTerminator(
24892494
new (getModule()) UnwindInst(getSILDebugLocation(loc)));

include/swift/SIL/SILCloner.h

+8
Original file line numberDiff line numberDiff line change
@@ -3134,6 +3134,14 @@ SILCloner<ImplClass>::visitThrowInst(ThrowInst *Inst) {
31343134
getOpValue(Inst->getOperand())));
31353135
}
31363136

3137+
template<typename ImplClass>
3138+
void
3139+
SILCloner<ImplClass>::visitThrowAddrInst(ThrowAddrInst *Inst) {
3140+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
3141+
recordClonedInstruction(
3142+
Inst, getBuilder().createThrowAddr(getOpLocation(Inst->getLoc())));
3143+
}
3144+
31373145
template<typename ImplClass>
31383146
void
31393147
SILCloner<ImplClass>::visitUnwindInst(UnwindInst *Inst) {

include/swift/SIL/SILInstruction.h

+26-2
Original file line numberDiff line numberDiff line change
@@ -9168,6 +9168,7 @@ class TermInst : public NonValueInstruction {
91689168
case TermKind::UnreachableInst:
91699169
case TermKind::ReturnInst:
91709170
case TermKind::ThrowInst:
9171+
case TermKind::ThrowAddrInst:
91719172
case TermKind::YieldInst:
91729173
case TermKind::CondBranchInst:
91739174
case TermKind::BranchInst:
@@ -9295,8 +9296,7 @@ class ReturnInst
92959296
}
92969297
};
92979298

9298-
/// ThrowInst - Throw a typed error (which, in our system, is
9299-
/// essentially just a funny kind of return).
9299+
/// ThrowInst - Throw a typed error, returning it via the direct error result.
93009300
class ThrowInst
93019301
: public UnaryInstructionBase<SILInstructionKind::ThrowInst, TermInst>
93029302
{
@@ -9317,6 +9317,30 @@ class ThrowInst
93179317
}
93189318
};
93199319

9320+
/// ThrowAddrInst - Throw a typed error, previously stored in the indirect
9321+
/// error result.
9322+
class ThrowAddrInst
9323+
: public InstructionBase<SILInstructionKind::ThrowAddrInst, TermInst>
9324+
{
9325+
friend SILBuilder;
9326+
9327+
/// Constructs a ThrowAddrInst representing a throw out of the current
9328+
/// function.
9329+
///
9330+
/// \param DebugLoc The location of the throw.
9331+
ThrowAddrInst(SILDebugLocation DebugLoc)
9332+
: InstructionBase(DebugLoc) {}
9333+
9334+
public:
9335+
SuccessorListTy getSuccessors() {
9336+
// No successors.
9337+
return SuccessorListTy();
9338+
}
9339+
9340+
ArrayRef<Operand> getAllOperands() const { return {}; }
9341+
MutableArrayRef<Operand> getAllOperands() { return {}; }
9342+
};
9343+
93209344
/// UnwindInst - Continue unwinding out of this function. Currently this is
93219345
/// only used in coroutines as the eventual terminator of the unwind edge
93229346
/// out of a 'yield'.

include/swift/SIL/SILNodes.def

+2
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,8 @@ ABSTRACT_INST(TermInst, SILInstruction)
722722
TermInst, None, DoesNotRelease)
723723
TERMINATOR(ThrowInst, throw,
724724
TermInst, None, DoesNotRelease)
725+
TERMINATOR(ThrowAddrInst, throw_addr,
726+
TermInst, None, DoesNotRelease)
725727
TERMINATOR(YieldInst, yield,
726728
TermInst, MayHaveSideEffects, MayRelease)
727729
TERMINATOR(UnwindInst, unwind,

include/swift/SILOptimizer/Utils/SCCVisitor.h

+1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ class SCCVisitor {
132132
case TermKind::ReturnInst:
133133
case TermKind::SwitchValueInst:
134134
case TermKind::ThrowInst:
135+
case TermKind::ThrowAddrInst:
135136
case TermKind::UnwindInst:
136137
llvm_unreachable("Did not expect terminator that does not have args!");
137138

lib/IRGen/IRGenSIL.cpp

+58-22
Original file line numberDiff line numberDiff line change
@@ -1469,6 +1469,7 @@ class IRGenSILFunction :
14691469
void visitCondBranchInst(CondBranchInst *i);
14701470
void visitReturnInst(ReturnInst *i);
14711471
void visitThrowInst(ThrowInst *i);
1472+
void visitThrowAddrInst(ThrowAddrInst *i);
14721473
void visitUnwindInst(UnwindInst *i);
14731474
void visitYieldInst(YieldInst *i);
14741475
void visitSwitchValueInst(SwitchValueInst *i);
@@ -4251,23 +4252,34 @@ void IRGenSILFunction::visitReturnInst(swift::ReturnInst *i) {
42514252
void IRGenSILFunction::visitThrowInst(swift::ThrowInst *i) {
42524253
SILFunctionConventions conv(CurSILFn->getLoweredFunctionType(),
42534254
getSILModule());
4255+
assert(!conv.hasIndirectSILErrorResults());
4256+
42544257
if (!isAsync()) {
42554258
if (conv.isTypedError()) {
42564259
llvm::Constant *flag = llvm::ConstantInt::get(IGM.IntPtrTy, 1);
42574260
flag = llvm::ConstantExpr::getIntToPtr(flag, IGM.Int8PtrTy);
4258-
if (!conv.hasIndirectSILErrorResults()) {
4259-
Explosion errorResult = getLoweredExplosion(i->getOperand());
4260-
auto &ti = cast<LoadableTypeInfo>(IGM.getTypeInfo(conv.getSILErrorType(
4261-
IGM.getMaximalTypeExpansionContext())));
4262-
ti.initialize(*this, errorResult, getCallerTypedErrorResultSlot(), false);
4263-
}
4261+
Explosion errorResult = getLoweredExplosion(i->getOperand());
4262+
auto &ti = cast<LoadableTypeInfo>(IGM.getTypeInfo(conv.getSILErrorType(
4263+
IGM.getMaximalTypeExpansionContext())));
4264+
ti.initialize(*this, errorResult, getCallerTypedErrorResultSlot(), false);
4265+
42644266
Builder.CreateStore(flag, getCallerErrorResultSlot());
42654267
} else {
42664268
Explosion errorResult = getLoweredExplosion(i->getOperand());
42674269
Builder.CreateStore(errorResult.claimNext(), getCallerErrorResultSlot());
42684270
}
4269-
// Async functions just return to the continuation.
4270-
} else if (isAsync()) {
4271+
4272+
// Create a normal return, but leaving the return value undefined.
4273+
auto fnTy = CurFn->getFunctionType();
4274+
auto retTy = fnTy->getReturnType();
4275+
if (retTy->isVoidTy()) {
4276+
Builder.CreateRetVoid();
4277+
} else {
4278+
Builder.CreateRet(llvm::UndefValue::get(retTy));
4279+
}
4280+
4281+
// Async functions just return to the continuation.
4282+
} else {
42714283
// Store the exception to the error slot.
42724284
auto exn = getLoweredExplosion(i->getOperand());
42734285

@@ -4276,13 +4288,9 @@ void IRGenSILFunction::visitThrowInst(swift::ThrowInst *i) {
42764288
conv.getSILResultType(IGM.getMaximalTypeExpansionContext()));
42774289

42784290
if (conv.isTypedError()) {
4279-
if (conv.hasIndirectSILErrorResults()) {
4280-
(void)exn.claimAll();
4281-
} else {
4282-
auto &ti = cast<LoadableTypeInfo>(IGM.getTypeInfo(conv.getSILErrorType(
4283-
IGM.getMaximalTypeExpansionContext())));
4284-
ti.initialize(*this, exn, getCallerTypedErrorResultSlot(), false);
4285-
}
4291+
auto &ti = cast<LoadableTypeInfo>(IGM.getTypeInfo(conv.getSILErrorType(
4292+
IGM.getMaximalTypeExpansionContext())));
4293+
ti.initialize(*this, exn, getCallerTypedErrorResultSlot(), false);
42864294
llvm::Constant *flag = llvm::ConstantInt::get(IGM.IntPtrTy, 1);
42874295
flag = llvm::ConstantExpr::getIntToPtr(flag, IGM.Int8PtrTy);
42884296
assert(exn.empty() && "Unclaimed typed error results");
@@ -4293,16 +4301,44 @@ void IRGenSILFunction::visitThrowInst(swift::ThrowInst *i) {
42934301
Explosion empty;
42944302
emitAsyncReturn(*this, layout, funcResultType,
42954303
i->getFunction()->getLoweredFunctionType(), empty, exn);
4296-
return;
42974304
}
4305+
}
42984306

4299-
// Create a normal return, but leaving the return value undefined.
4300-
auto fnTy = CurFn->getFunctionType();
4301-
auto retTy = fnTy->getReturnType();
4302-
if (retTy->isVoidTy()) {
4303-
Builder.CreateRetVoid();
4307+
void IRGenSILFunction::visitThrowAddrInst(swift::ThrowAddrInst *i) {
4308+
SILFunctionConventions conv(CurSILFn->getLoweredFunctionType(),
4309+
getSILModule());
4310+
assert(conv.isTypedError());
4311+
assert(conv.hasIndirectSILErrorResults());
4312+
4313+
if (!isAsync()) {
4314+
llvm::Constant *flag = llvm::ConstantInt::get(IGM.IntPtrTy, 1);
4315+
flag = llvm::ConstantExpr::getIntToPtr(flag, IGM.Int8PtrTy);
4316+
Builder.CreateStore(flag, getCallerErrorResultSlot());
4317+
4318+
// Create a normal return, but leaving the return value undefined.
4319+
auto fnTy = CurFn->getFunctionType();
4320+
auto retTy = fnTy->getReturnType();
4321+
if (retTy->isVoidTy()) {
4322+
Builder.CreateRetVoid();
4323+
} else {
4324+
Builder.CreateRet(llvm::UndefValue::get(retTy));
4325+
}
4326+
4327+
// Async functions just return to the continuation.
43044328
} else {
4305-
Builder.CreateRet(llvm::UndefValue::get(retTy));
4329+
auto layout = getAsyncContextLayout(*this);
4330+
auto funcResultType = CurSILFn->mapTypeIntoContext(
4331+
conv.getSILResultType(IGM.getMaximalTypeExpansionContext()));
4332+
4333+
llvm::Constant *flag = llvm::ConstantInt::get(IGM.IntPtrTy, 1);
4334+
flag = llvm::ConstantExpr::getIntToPtr(flag, IGM.Int8PtrTy);
4335+
4336+
Explosion exn;
4337+
exn.add(flag);
4338+
4339+
Explosion empty;
4340+
emitAsyncReturn(*this, layout, funcResultType,
4341+
i->getFunction()->getLoweredFunctionType(), empty, exn);
43064342
}
43074343
}
43084344

lib/SIL/IR/OperandOwnership.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ SHOULD_NEVER_VISIT_INST(StringLiteral)
120120
SHOULD_NEVER_VISIT_INST(StrongRetain)
121121
SHOULD_NEVER_VISIT_INST(Unreachable)
122122
SHOULD_NEVER_VISIT_INST(Unwind)
123+
SHOULD_NEVER_VISIT_INST(ThrowAddr)
123124
SHOULD_NEVER_VISIT_INST(ReleaseValue)
124125
SHOULD_NEVER_VISIT_INST(ReleaseValueAddr)
125126
SHOULD_NEVER_VISIT_INST(StrongRelease)

lib/SIL/IR/SILArgument.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ getSingleTerminatorOperandForPred(const SILBasicBlock *parentBlock,
312312
case TermKind::UnreachableInst:
313313
case TermKind::ReturnInst:
314314
case TermKind::ThrowInst:
315+
case TermKind::ThrowAddrInst:
315316
case TermKind::UnwindInst:
316317
llvm_unreachable("Have terminator that implies no successors?!");
317318
case TermKind::TryApplyInst:

lib/SIL/IR/SILInstructions.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1699,6 +1699,7 @@ bool TermInst::isFunctionExiting() const {
16991699
return false;
17001700
case TermKind::ReturnInst:
17011701
case TermKind::ThrowInst:
1702+
case TermKind::ThrowAddrInst:
17021703
case TermKind::UnwindInst:
17031704
return true;
17041705
}
@@ -1719,6 +1720,7 @@ bool TermInst::isProgramTerminating() const {
17191720
case TermKind::CheckedCastAddrBranchInst:
17201721
case TermKind::ReturnInst:
17211722
case TermKind::ThrowInst:
1723+
case TermKind::ThrowAddrInst:
17221724
case TermKind::UnwindInst:
17231725
case TermKind::TryApplyInst:
17241726
case TermKind::YieldInst:
@@ -1745,6 +1747,7 @@ const Operand *TermInst::forwardedOperand() const {
17451747
case TermKind::UnreachableInst:
17461748
case TermKind::ReturnInst:
17471749
case TermKind::ThrowInst:
1750+
case TermKind::ThrowAddrInst:
17481751
case TermKind::YieldInst:
17491752
case TermKind::TryApplyInst:
17501753
case TermKind::CondBranchInst:

lib/SIL/IR/SILPrinter.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -2625,6 +2625,10 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
26252625
*this << getIDAndType(TI->getOperand());
26262626
}
26272627

2628+
void visitThrowAddrInst(ThrowAddrInst *TAI) {
2629+
// no operands
2630+
}
2631+
26282632
void visitUnwindInst(UnwindInst *UI) {
26292633
// no operands
26302634
}

lib/SIL/Parser/ParseSIL.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -5457,6 +5457,12 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
54575457
ResultVal = B.createThrow(InstLoc, Val);
54585458
break;
54595459
}
5460+
case SILInstructionKind::ThrowAddrInst: {
5461+
if (parseSILDebugLocation(InstLoc, B))
5462+
return true;
5463+
ResultVal = B.createThrowAddr(InstLoc);
5464+
break;
5465+
}
54605466
case SILInstructionKind::UnwindInst: {
54615467
if (parseSILDebugLocation(InstLoc, B))
54625468
return true;

lib/SIL/Utils/BasicBlockUtils.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ void swift::getEdgeArgs(TermInst *T, unsigned edgeIdx, SILBasicBlock *newEdgeBB,
232232

233233
case SILInstructionKind::ReturnInst:
234234
case SILInstructionKind::ThrowInst:
235+
case SILInstructionKind::ThrowAddrInst:
235236
case SILInstructionKind::UnwindInst:
236237
case SILInstructionKind::UnreachableInst:
237238
llvm_unreachable("terminator never has successors");

lib/SIL/Utils/InstructionUtils.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType)
524524
case SILInstructionKind::UnreachableInst:
525525
case SILInstructionKind::ReturnInst:
526526
case SILInstructionKind::ThrowInst:
527+
case SILInstructionKind::ThrowAddrInst:
527528
case SILInstructionKind::YieldInst:
528529
case SILInstructionKind::UnwindInst:
529530
case SILInstructionKind::BranchInst:

lib/SIL/Verifier/SILVerifier.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -6244,7 +6244,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
62446244
require(!FoundReturnBlock,
62456245
"more than one return block in function");
62466246
FoundReturnBlock = true;
6247-
} else if (isa<ThrowInst>(BB.getTerminator())) {
6247+
} else if (isa<ThrowInst>(BB.getTerminator()) ||
6248+
isa<ThrowAddrInst>(BB.getTerminator())) {
62486249
require(!FoundThrowBlock,
62496250
"more than one throw block in function");
62506251
FoundThrowBlock = true;

lib/SILOptimizer/ARC/ARCSequenceOptUtils.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ bool isARCSignificantTerminator(TermInst *TI) {
2828
// Be conservative for now. These actually perform some sort of operation
2929
// against the operand or can use the value in some way.
3030
case TermKind::ThrowInst:
31+
case TermKind::ThrowAddrInst:
3132
case TermKind::ReturnInst:
3233
case TermKind::UnwindInst:
3334
case TermKind::YieldInst:

lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -2754,6 +2754,7 @@ bool AllocOptimize::tryToRemoveDeadAllocation() {
27542754
LLVM_FALLTHROUGH;
27552755
case TermKind::ReturnInst:
27562756
case TermKind::ThrowInst:
2757+
case TermKind::ThrowAddrInst:
27572758
case TermKind::UnwindInst:
27582759
case TermKind::YieldInst: {
27592760
// These terminators can never be non-consuming uses of an owned

0 commit comments

Comments
 (0)