Skip to content

Commit 05271d3

Browse files
authored
Merge pull request #69529 from slavapestov/sil-throw-addr
SILGen support for throwing indirect errors
2 parents a315cca + 079c5c4 commit 05271d3

39 files changed

+409
-97
lines changed

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 4 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 24 additions & 2 deletions
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

Lines changed: 1 addition & 0 deletions
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/ApplySite.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,14 @@ class FullApplySite : public ApplySite {
741741
&& (getCalleeArgIndex(op) < getNumIndirectSILResults());
742742
}
743743

744+
/// Returns true if \p op is an operand that passes an indirect
745+
/// result argument to the apply site.
746+
bool isIndirectErrorResultOperand(const Operand &op) const {
747+
return isArgumentOperand(op)
748+
&& (getCalleeArgIndex(op) >= getNumIndirectSILResults())
749+
&& (getCalleeArgIndex(op) < getNumIndirectSILErrorResults());
750+
}
751+
744752
static FullApplySite getFromOpaqueValue(void *p) { return FullApplySite(p); }
745753

746754
static bool classof(const SILInstruction *inst) {

include/swift/SIL/SILBuilder.h

Lines changed: 5 additions & 0 deletions
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

Lines changed: 8 additions & 0 deletions
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

Lines changed: 26 additions & 2 deletions
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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

0 commit comments

Comments
 (0)