Skip to content

Commit 079c5c4

Browse files
committed
SILGen: Support for 'throw' and 'try_apply' with indirect error result
1 parent 863604e commit 079c5c4

File tree

8 files changed

+219
-57
lines changed

8 files changed

+219
-57
lines changed

lib/SILGen/JumpDest.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,31 @@ namespace swift {
2727

2828
namespace Lowering {
2929

30+
struct LLVM_LIBRARY_VISIBILITY ThrownErrorInfo {
31+
SILValue IndirectErrorResult;
32+
33+
explicit ThrownErrorInfo(SILValue IndirectErrorResult)
34+
: IndirectErrorResult(IndirectErrorResult) {}
35+
};
36+
3037
/// The destination of a direct jump. Swift currently does not
3138
/// support indirect branches or goto, so the jump mechanism only
3239
/// needs to worry about branches out of scopes, not into them.
3340
class LLVM_LIBRARY_VISIBILITY JumpDest {
3441
SILBasicBlock *Block = nullptr;
3542
CleanupsDepth Depth = CleanupsDepth::invalid();
3643
CleanupLocation CleanupLoc;
44+
llvm::Optional<ThrownErrorInfo> ThrownError;
45+
3746
public:
3847
JumpDest(CleanupLocation L) : CleanupLoc(L) {}
3948

40-
JumpDest(SILBasicBlock *block, CleanupsDepth depth, CleanupLocation l)
41-
: Block(block), Depth(depth), CleanupLoc(l) {}
49+
JumpDest(SILBasicBlock *block,
50+
CleanupsDepth depth,
51+
CleanupLocation l,
52+
llvm::Optional<ThrownErrorInfo> ThrownError = llvm::None)
53+
: Block(block), Depth(depth), CleanupLoc(l),
54+
ThrownError(ThrownError) {}
4255

4356
SILBasicBlock *getBlock() const { return Block; }
4457
SILBasicBlock *takeBlock() {
@@ -49,7 +62,14 @@ class LLVM_LIBRARY_VISIBILITY JumpDest {
4962
CleanupsDepth getDepth() const { return Depth; }
5063
CleanupLocation getCleanupLocation() const { return CleanupLoc; }
5164

65+
ThrownErrorInfo getThrownError() const {
66+
assert(ThrownError);
67+
return *ThrownError;
68+
}
69+
5270
JumpDest translate(CleanupsDepth NewDepth) && {
71+
assert(!ThrownError);
72+
5373
JumpDest NewValue(Block, NewDepth, CleanupLoc);
5474
Block = nullptr;
5575
Depth = CleanupsDepth::invalid();

lib/SILGen/SILGenApply.cpp

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,6 +1856,7 @@ static void emitRawApply(SILGenFunction &SGF,
18561856
CanSILFunctionType substFnType,
18571857
ApplyOptions options,
18581858
ArrayRef<SILValue> indirectResultAddrs,
1859+
SILValue indirectErrorAddr,
18591860
SmallVectorImpl<SILValue> &rawResults,
18601861
ExecutorBreadcrumb prevExecutor) {
18611862
SILFunctionConventions substFnConv(substFnType, SGF.SGM.M);
@@ -1880,6 +1881,10 @@ static void emitRawApply(SILGenFunction &SGF,
18801881
#endif
18811882
argValues.append(indirectResultAddrs.begin(), indirectResultAddrs.end());
18821883

1884+
assert(!!indirectErrorAddr == substFnConv.hasIndirectSILErrorResults());
1885+
if (indirectErrorAddr)
1886+
argValues.push_back(indirectErrorAddr);
1887+
18831888
auto inputParams = substFnType->getParameters();
18841889
assert(inputParams.size() == args.size());
18851890

@@ -1978,6 +1983,7 @@ static void emitRawApply(SILGenFunction &SGF,
19781983
SILBasicBlock *errorBB =
19791984
SGF.getTryApplyErrorDest(loc, substFnType, prevExecutor,
19801985
substFnType->getErrorResult(),
1986+
indirectErrorAddr,
19811987
options.contains(ApplyFlags::DoesNotThrow));
19821988

19831989
options -= ApplyFlags::DoesNotThrow;
@@ -4876,7 +4882,8 @@ SILGenFunction::emitBeginApply(SILLocation loc, ManagedValue fn,
48764882
// Emit the call.
48774883
SmallVector<SILValue, 4> rawResults;
48784884
emitRawApply(*this, loc, fn, subs, args, substFnType, options,
4879-
/*indirect results*/ {}, rawResults, ExecutorBreadcrumb());
4885+
/*indirect results*/ {}, /*indirect errors*/ {},
4886+
rawResults, ExecutorBreadcrumb());
48804887

48814888
auto token = rawResults.pop_back_val();
48824889
auto yieldValues = llvm::makeArrayRef(rawResults);
@@ -5411,6 +5418,16 @@ RValue SILGenFunction::emitApply(
54115418
SmallVector<SILValue, 4> indirectResultAddrs;
54125419
resultPlan->gatherIndirectResultAddrs(*this, loc, indirectResultAddrs);
54135420

5421+
SILValue indirectErrorAddr;
5422+
if (substFnType->hasErrorResult()) {
5423+
auto errorResult = substFnType->getErrorResult();
5424+
if (errorResult.getConvention() == ResultConvention::Indirect) {
5425+
auto loweredErrorResultType = getSILType(errorResult, substFnType);
5426+
indirectErrorAddr = B.createAllocStack(loc, loweredErrorResultType);
5427+
enterDeallocStackCleanup(indirectErrorAddr);
5428+
}
5429+
}
5430+
54145431
// If the function returns an inner pointer, we'll need to lifetime-extend
54155432
// the 'self' parameter.
54165433
SILValue lifetimeExtendedSelf;
@@ -5540,7 +5557,8 @@ RValue SILGenFunction::emitApply(
55405557
{
55415558
SmallVector<SILValue, 1> rawDirectResults;
55425559
emitRawApply(*this, loc, fn, subs, args, substFnType, options,
5543-
indirectResultAddrs, rawDirectResults, breadcrumb);
5560+
indirectResultAddrs, indirectErrorAddr,
5561+
rawDirectResults, breadcrumb);
55445562
assert(rawDirectResults.size() == 1);
55455563
rawDirectResult = rawDirectResults[0];
55465564
}
@@ -5709,12 +5727,22 @@ SILValue SILGenFunction::emitApplyWithRethrow(SILLocation loc, SILValue fn,
57095727
// Emit the rethrow logic.
57105728
{
57115729
B.emitBlock(errorBB);
5712-
SILValue error = errorBB->createPhiArgument(
5713-
fnConv.getSILErrorType(getTypeExpansionContext()),
5714-
OwnershipKind::Owned);
5730+
5731+
SILValue error;
5732+
bool indirectError = fnConv.hasIndirectSILErrorResults();
5733+
5734+
if (!indirectError) {
5735+
error = errorBB->createPhiArgument(
5736+
fnConv.getSILErrorType(getTypeExpansionContext()),
5737+
OwnershipKind::Owned);
5738+
}
57155739

57165740
Cleanups.emitCleanupsForReturn(CleanupLocation(loc), IsForUnwind);
5717-
B.createThrow(loc, error);
5741+
5742+
if (!indirectError)
5743+
B.createThrow(loc, error);
5744+
else
5745+
B.createThrowAddr(loc);
57185746
}
57195747

57205748
// Enter the normal path.

lib/SILGen/SILGenDistributed.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@ void SILGenFunction::emitDistributedActorFactory(FuncDecl *fd) { // TODO(distrib
479479
OwnershipKind::Owned);
480480

481481
Cleanups.emitCleanupsForReturn(CleanupLocation(loc), IsForUnwind);
482+
483+
// FIXME: typed throws
482484
B.createThrow(loc, error);
483485
}
484486
}

lib/SILGen/SILGenEpilog.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ void SILGenFunction::prepareRethrowEpilog(
9090
rethrowBB->createPhiArgument(loweredErrorType, OwnershipKind::Owned);
9191
}
9292

93-
ThrowDest = JumpDest(rethrowBB, getCleanupsDepth(), cleanupLoc);
93+
ThrowDest = JumpDest(rethrowBB, getCleanupsDepth(), cleanupLoc,
94+
ThrownErrorInfo(IndirectErrorResult));
9495
}
9596

9697
void SILGenFunction::prepareCoroutineUnwindEpilog(CleanupLocation cleanupLoc) {
@@ -403,12 +404,21 @@ static bool prepareExtraEpilog(SILGenFunction &SGF, JumpDest &dest,
403404
void SILGenFunction::emitRethrowEpilog(SILLocation topLevel) {
404405
SILValue exn;
405406
SILLocation throwLoc = topLevel;
406-
if (!prepareExtraEpilog(*this, ThrowDest, throwLoc, &exn))
407+
408+
if (!prepareExtraEpilog(*this, ThrowDest, throwLoc,
409+
!IndirectErrorResult ? &exn : nullptr)) {
407410
return;
411+
}
408412

409413
Cleanups.emitCleanupsForReturn(ThrowDest.getCleanupLocation(), IsForUnwind);
410414

411-
B.createThrow(CleanupLocation(throwLoc), exn);
415+
// FIXME: opaque values
416+
if (!IndirectErrorResult) {
417+
B.createThrow(CleanupLocation(throwLoc), exn);
418+
} else {
419+
assert(IndirectErrorResult);
420+
B.createThrowAddr(CleanupLocation(throwLoc));
421+
}
412422

413423
ThrowDest = JumpDest::invalid();
414424
}

lib/SILGen/SILGenExpr.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,8 +1147,15 @@ SILGenFunction::ForceTryEmission::ForceTryEmission(SILGenFunction &SGF,
11471147

11481148
// Set up a "catch" block for when an error occurs.
11491149
SILBasicBlock *catchBB = SGF.createBasicBlock(FunctionSection::Postmatter);
1150+
1151+
// FIXME: typed throws
1152+
ASTContext &ctx = SGF.getASTContext();
1153+
(void) catchBB->createPhiArgument(SILType::getExceptionType(ctx),
1154+
OwnershipKind::Owned);
1155+
11501156
SGF.ThrowDest = JumpDest(catchBB, SGF.Cleanups.getCleanupsDepth(),
1151-
CleanupLocation(loc));
1157+
CleanupLocation(loc),
1158+
ThrownErrorInfo(/*indirectErrorAddr=*/nullptr));
11521159
}
11531160

11541161
void SILGenFunction::ForceTryEmission::finish() {
@@ -1164,10 +1171,11 @@ void SILGenFunction::ForceTryEmission::finish() {
11641171
// Otherwise, we need to emit it.
11651172
SILGenSavedInsertionPoint scope(SGF, catchBB, FunctionSection::Postmatter);
11661173

1167-
if (auto diagnoseError = SGF.getASTContext().getDiagnoseUnexpectedError()) {
1168-
ASTContext &ctx = SGF.getASTContext();
1169-
auto error = SGF.B.createTermResult(SILType::getExceptionType(ctx),
1170-
OwnershipKind::Owned);
1174+
// FIXME: typed throws
1175+
auto error = ManagedValue::forForwardedRValue(SGF, catchBB->getArgument(0));
1176+
1177+
ASTContext &ctx = SGF.getASTContext();
1178+
if (auto diagnoseError = ctx.getDiagnoseUnexpectedError()) {
11711179
auto args = SGF.emitSourceLocationArgs(Loc->getExclaimLoc(), Loc);
11721180

11731181
SGF.emitApplyOfLibraryIntrinsic(
@@ -1237,9 +1245,15 @@ RValue RValueEmitter::visitOptionalTryExpr(OptionalTryExpr *E, SGFContext C) {
12371245

12381246
// Set up a "catch" block for when an error occurs.
12391247
SILBasicBlock *catchBB = SGF.createBasicBlock(FunctionSection::Postmatter);
1248+
1249+
// FIXME: typed throws
1250+
auto *errorArg = catchBB->createPhiArgument(
1251+
SILType::getExceptionType(SGF.getASTContext()), OwnershipKind::Owned);
1252+
12401253
llvm::SaveAndRestore<JumpDest> throwDest{
12411254
SGF.ThrowDest,
1242-
JumpDest(catchBB, SGF.Cleanups.getCleanupsDepth(), E)};
1255+
JumpDest(catchBB, SGF.Cleanups.getCleanupsDepth(), E,
1256+
ThrownErrorInfo(/*indirectErrorAddr=*/nullptr))};
12431257

12441258
SILValue branchArg;
12451259
if (shouldWrapInOptional) {
@@ -1298,8 +1312,6 @@ RValue RValueEmitter::visitOptionalTryExpr(OptionalTryExpr *E, SGFContext C) {
12981312
// result type.
12991313
SGF.B.emitBlock(catchBB);
13001314
FullExpr catchCleanups(SGF.Cleanups, E);
1301-
auto *errorArg = catchBB->createPhiArgument(
1302-
SILType::getExceptionType(SGF.getASTContext()), OwnershipKind::Owned);
13031315
(void) SGF.emitManagedRValueWithCleanup(errorArg);
13041316
catchCleanups.pop();
13051317

lib/SILGen/SILGenFunction.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
389389
JumpDest FailDest = JumpDest::invalid();
390390

391391
/// The destination for throws. The block will always be in the
392-
/// postmatter and takes a BB argument of the exception type.
392+
/// postmatter. For a direct error return, it takes a BB argument
393+
/// of the exception type.
393394
JumpDest ThrowDest = JumpDest::invalid();
394395

395396
/// Support for typed throws.
@@ -1989,7 +1990,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
19891990
SILBasicBlock *getTryApplyErrorDest(SILLocation loc,
19901991
CanSILFunctionType fnTy,
19911992
ExecutorBreadcrumb prevExecutor,
1992-
SILResultInfo exnResult,
1993+
SILResultInfo errorResult,
1994+
SILValue indirectErrorAddr,
19931995
bool isSuppressed);
19941996

19951997
/// Emit a dynamic member reference.

0 commit comments

Comments
 (0)