Skip to content

Commit 581776b

Browse files
committed
SILGen: Emit indirect error result argument
1 parent 4ed2dc4 commit 581776b

10 files changed

+182
-80
lines changed

lib/SILGen/SILGenBackDeploy.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ void SILGenFunction::emitBackDeploymentThunk(SILDeclRef thunk) {
237237
paramsForForwarding.emplace_back(param.forward(*this));
238238
}
239239

240-
prepareEpilog(getResultInterfaceType(AFD),
240+
prepareEpilog(AFD,
241+
getResultInterfaceType(AFD),
241242
AFD->getEffectiveThrownErrorType(),
242243
CleanupLocation(AFD));
243244

lib/SILGen/SILGenBridging.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -2134,7 +2134,10 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) {
21342134
// Set up the throw destination if necessary.
21352135
CleanupLocation cleanupLoc(fd);
21362136
if (thrownErrorType) {
2137-
prepareRethrowEpilog(*thrownErrorType, cleanupLoc);
2137+
prepareRethrowEpilog(fd,
2138+
AbstractionPattern(*thrownErrorType),
2139+
*thrownErrorType,
2140+
cleanupLoc);
21382141
}
21392142

21402143
SILValue result;

lib/SILGen/SILGenConstructor.cpp

+23-13
Original file line numberDiff line numberDiff line change
@@ -658,10 +658,11 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
658658
assert(selfLV);
659659

660660
// Emit the prolog.
661-
emitBasicProlog(ctor->getParameters(),
661+
emitBasicProlog(ctor,
662+
ctor->getParameters(),
662663
/*selfParam=*/nullptr,
663-
ctor->getResultInterfaceType(), ctor,
664-
ctor->hasThrows(),
664+
ctor->getResultInterfaceType(),
665+
ctor->getEffectiveThrownErrorType(),
665666
ctor->getThrowsLoc(),
666667
/*ignored parameters*/ 1);
667668
emitConstructorMetatypeArg(*this, ctor);
@@ -680,7 +681,9 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
680681
// Create a basic block to jump to for the implicit 'self' return.
681682
// We won't emit this until after we've emitted the body.
682683
// The epilog takes a void return because the return of 'self' is implicit.
683-
prepareEpilog(llvm::None, ctor->getEffectiveThrownErrorType(),
684+
prepareEpilog(ctor,
685+
llvm::None,
686+
ctor->getEffectiveThrownErrorType(),
684687
CleanupLocation(ctor));
685688

686689
// If the constructor can fail, set up an alternative epilog for constructor
@@ -1105,9 +1108,11 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
11051108

11061109
// Emit the prolog for the non-self arguments.
11071110
// FIXME: Handle self along with the other body patterns.
1108-
uint16_t ArgNo = emitBasicProlog(ctor->getParameters(), /*selfParam=*/nullptr,
1109-
TupleType::getEmpty(F.getASTContext()), ctor,
1110-
ctor->hasThrows(), ctor->getThrowsLoc(),
1111+
uint16_t ArgNo = emitBasicProlog(ctor,
1112+
ctor->getParameters(), /*selfParam=*/nullptr,
1113+
TupleType::getEmpty(F.getASTContext()),
1114+
ctor->getEffectiveThrownErrorType(),
1115+
ctor->getThrowsLoc(),
11111116
/*ignored parameters*/ 1);
11121117

11131118
SILType selfTy = getLoweredLoadableType(selfDecl->getTypeInContext());
@@ -1185,7 +1190,9 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
11851190

11861191
// Create a basic block to jump to for the implicit 'self' return.
11871192
// We won't emit the block until after we've emitted the body.
1188-
prepareEpilog(llvm::None, ctor->getEffectiveThrownErrorType(),
1193+
prepareEpilog(ctor,
1194+
llvm::None,
1195+
ctor->getEffectiveThrownErrorType(),
11891196
CleanupLocation(endOfInitLoc));
11901197

11911198
auto resultType = ctor->mapTypeIntoContext(ctor->getResultInterfaceType());
@@ -1680,7 +1687,7 @@ void SILGenFunction::emitIVarInitializer(SILDeclRef ivarInitializer) {
16801687
VarLocs[selfDecl] = VarLoc::get(selfArg);
16811688

16821689
auto cleanupLoc = CleanupLocation(loc);
1683-
prepareEpilog(llvm::None, llvm::None, cleanupLoc);
1690+
prepareEpilog(cd, llvm::None, llvm::None, cleanupLoc);
16841691

16851692
// Emit the initializers.
16861693
emitMemberInitializers(cd, selfDecl, cd);
@@ -1732,9 +1739,11 @@ void SILGenFunction::emitInitAccessor(AccessorDecl *accessor) {
17321739
auto accessedProperties = accessor->getAccessedProperties();
17331740

17341741
// Emit `newValue` argument.
1735-
emitBasicProlog(accessor->getParameters(), /*selfParam=*/nullptr,
1736-
TupleType::getEmpty(F.getASTContext()), accessor,
1737-
/*throws=*/false, /*throwsLoc=*/SourceLoc(),
1742+
emitBasicProlog(accessor,
1743+
accessor->getParameters(), /*selfParam=*/nullptr,
1744+
TupleType::getEmpty(F.getASTContext()),
1745+
/*errorType=*/llvm::None,
1746+
/*throwsLoc=*/SourceLoc(),
17381747
/*ignored parameters*/
17391748
accessedProperties.size());
17401749

@@ -1750,7 +1759,8 @@ void SILGenFunction::emitInitAccessor(AccessorDecl *accessor) {
17501759
}
17511760
}
17521761

1753-
prepareEpilog(accessor->getResultInterfaceType(),
1762+
prepareEpilog(accessor,
1763+
accessor->getResultInterfaceType(),
17541764
accessor->getEffectiveThrownErrorType(),
17551765
CleanupLocation(accessor));
17561766

lib/SILGen/SILGenDestructor.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) {
4545
// Create a basic block to jump to for the implicit destruction behavior
4646
// of releasing the elements and calling the superclass destructor.
4747
// We won't actually emit the block until we finish with the destructor body.
48-
prepareEpilog(llvm::None, llvm::None, CleanupLocation(Loc));
48+
prepareEpilog(dd, llvm::None, llvm::None, CleanupLocation(Loc));
4949

5050
auto cleanupLoc = CleanupLocation(Loc);
5151

@@ -248,7 +248,7 @@ void SILGenFunction::emitDeallocatingMoveOnlyDestructor(DestructorDecl *dd) {
248248
// Create a basic block to jump to for the implicit destruction behavior
249249
// of releasing the elements and calling the superclass destructor.
250250
// We won't actually emit the block until we finish with the destructor body.
251-
prepareEpilog(llvm::None, llvm::None, CleanupLocation(loc));
251+
prepareEpilog(dd, llvm::None, llvm::None, CleanupLocation(loc));
252252

253253
auto cleanupLoc = CleanupLocation(loc);
254254

@@ -286,7 +286,7 @@ void SILGenFunction::emitIVarDestroyer(SILDeclRef ivarDestroyer) {
286286
assert(selfValue);
287287

288288
auto cleanupLoc = CleanupLocation(loc);
289-
prepareEpilog(llvm::None, llvm::None, cleanupLoc);
289+
prepareEpilog(cd, llvm::None, llvm::None, cleanupLoc);
290290
{
291291
Scope S(*this, cleanupLoc);
292292
// Self is effectively guaranteed for the duration of any destructor. For
@@ -577,7 +577,7 @@ void SILGenFunction::emitObjCDestructor(SILDeclRef dtor) {
577577
// Create a basic block to jump to for the implicit destruction behavior
578578
// of releasing the elements and calling the superclass destructor.
579579
// We won't actually emit the block until we finish with the destructor body.
580-
prepareEpilog(llvm::None, llvm::None, CleanupLocation(loc));
580+
prepareEpilog(dd, llvm::None, llvm::None, CleanupLocation(loc));
581581

582582
emitProfilerIncrement(dd->getTypecheckedBody());
583583
// Emit the destructor body.

lib/SILGen/SILGenEpilog.cpp

+21-8
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
using namespace swift;
2121
using namespace Lowering;
2222

23-
void SILGenFunction::prepareEpilog(llvm::Optional<Type> directResultType,
24-
llvm::Optional<Type> exnType,
25-
CleanupLocation CleanupL) {
23+
void SILGenFunction::prepareEpilog(DeclContext *DC,
24+
llvm::Optional<Type> directResultType,
25+
llvm::Optional<Type> errorType,
26+
CleanupLocation CleanupL,
27+
llvm::Optional<AbstractionPattern> origClosureType) {
2628
auto *epilogBB = createBasicBlock();
2729

2830
// If we have any direct results, receive them via BB arguments.
@@ -63,8 +65,14 @@ void SILGenFunction::prepareEpilog(llvm::Optional<Type> directResultType,
6365

6466
ReturnDest = JumpDest(epilogBB, getCleanupsDepth(), CleanupL);
6567

66-
if (exnType) {
67-
prepareRethrowEpilog(*exnType, CleanupL);
68+
if (errorType) {
69+
auto genericSig = DC->getGenericSignatureOfContext();
70+
AbstractionPattern origErrorType = origClosureType
71+
? *origClosureType->getFunctionThrownErrorType()
72+
: AbstractionPattern(genericSig.getCanonicalSignature(),
73+
(*errorType)->getCanonicalType());
74+
75+
prepareRethrowEpilog(DC, origErrorType, *errorType, CleanupL);
6876
}
6977

7078
if (F.getLoweredFunctionType()->isCoroutine()) {
@@ -73,10 +81,15 @@ void SILGenFunction::prepareEpilog(llvm::Optional<Type> directResultType,
7381
}
7482

7583
void SILGenFunction::prepareRethrowEpilog(
76-
Type exnType, CleanupLocation cleanupLoc) {
77-
SILType loweredExnType = getLoweredType(exnType);
84+
DeclContext *dc, AbstractionPattern origErrorType, Type errorType,
85+
CleanupLocation cleanupLoc) {
86+
7887
SILBasicBlock *rethrowBB = createBasicBlock(FunctionSection::Postmatter);
79-
rethrowBB->createPhiArgument(loweredExnType, OwnershipKind::Owned);
88+
if (!IndirectErrorResult) {
89+
SILType loweredErrorType = getLoweredType(origErrorType, errorType);
90+
rethrowBB->createPhiArgument(loweredErrorType, OwnershipKind::Owned);
91+
}
92+
8093
ThrowDest = JumpDest(rethrowBB, getCleanupsDepth(), cleanupLoc);
8194
}
8295

lib/SILGen/SILGenFunction.cpp

+29-20
Original file line numberDiff line numberDiff line change
@@ -1043,15 +1043,18 @@ void SILGenFunction::emitFunction(FuncDecl *fd) {
10431043
MagicFunctionName = SILGenModule::getMagicFunctionName(fd);
10441044

10451045
auto captureInfo = SGM.M.Types.getLoweredLocalCaptures(SILDeclRef(fd));
1046-
emitProlog(captureInfo, fd->getParameters(), fd->getImplicitSelfDecl(), fd,
1047-
fd->getResultInterfaceType(), fd->hasThrows(), fd->getThrowsLoc());
1046+
emitProlog(fd, captureInfo, fd->getParameters(), fd->getImplicitSelfDecl(),
1047+
fd->getResultInterfaceType(), fd->getEffectiveThrownErrorType(),
1048+
fd->getThrowsLoc());
10481049

10491050
if (fd->isDistributedActorFactory()) {
10501051
// Synthesize the factory function body
10511052
emitDistributedActorFactory(fd);
10521053
} else {
1053-
prepareEpilog(fd->getResultInterfaceType(),
1054-
fd->getEffectiveThrownErrorType(), CleanupLocation(fd));
1054+
prepareEpilog(fd,
1055+
fd->getResultInterfaceType(),
1056+
fd->getEffectiveThrownErrorType(),
1057+
CleanupLocation(fd));
10551058

10561059
if (fd->requiresUnavailableDeclABICompatibilityStubs())
10571060
emitApplyOfUnavailableCodeReached();
@@ -1071,15 +1074,17 @@ void SILGenFunction::emitFunction(FuncDecl *fd) {
10711074
void SILGenFunction::emitClosure(AbstractClosureExpr *ace) {
10721075
MagicFunctionName = SILGenModule::getMagicFunctionName(ace);
10731076
OrigFnType = SGM.M.Types.getConstantAbstractionPattern(SILDeclRef(ace));
1074-
1077+
10751078
auto resultIfaceTy = ace->getResultType()->mapTypeOutOfContext();
1079+
llvm::Optional<Type> errorIfaceTy;
1080+
if (auto optErrorTy = ace->getEffectiveThrownType())
1081+
errorIfaceTy = (*optErrorTy)->mapTypeOutOfContext();
10761082
auto captureInfo = SGM.M.Types.getLoweredLocalCaptures(
10771083
SILDeclRef(ace));
1078-
emitProlog(captureInfo, ace->getParameters(), /*selfParam=*/nullptr,
1079-
ace, resultIfaceTy, ace->isBodyThrowing(), ace->getLoc(),
1080-
OrigFnType);
1081-
prepareEpilog(resultIfaceTy, ace->getEffectiveThrownType(),
1082-
CleanupLocation(ace));
1084+
emitProlog(ace, captureInfo, ace->getParameters(), /*selfParam=*/nullptr,
1085+
resultIfaceTy, errorIfaceTy, ace->getLoc(), OrigFnType);
1086+
prepareEpilog(ace, resultIfaceTy, errorIfaceTy,
1087+
CleanupLocation(ace), OrigFnType);
10831088

10841089
emitProfilerIncrement(ace);
10851090
if (auto *ce = dyn_cast<ClosureExpr>(ace)) {
@@ -1553,15 +1558,15 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value,
15531558

15541559
auto captureInfo = SGM.M.Types.getLoweredLocalCaptures(function);
15551560
auto interfaceType = value->getType()->mapTypeOutOfContext();
1556-
emitProlog(captureInfo, params, /*selfParam=*/nullptr,
1557-
dc, interfaceType, /*throws=*/false, SourceLoc());
1561+
emitProlog(dc, captureInfo, params, /*selfParam=*/nullptr, interfaceType,
1562+
/*errorType=*/llvm::None, SourceLoc());
15581563
if (EmitProfilerIncrement) {
15591564
// Emit a profiler increment for the top-level value, not looking through
15601565
// any function conversions. This is necessary as the counter would have
15611566
// been recorded for this expression, not the sub-expression.
15621567
emitProfilerIncrement(topLevelValue);
15631568
}
1564-
prepareEpilog(interfaceType, llvm::None, CleanupLocation(Loc));
1569+
prepareEpilog(dc, interfaceType, llvm::None, CleanupLocation(Loc));
15651570

15661571
{
15671572
llvm::Optional<SILGenFunction::OpaqueValueRAII> opaqueValue;
@@ -1621,10 +1626,14 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, VarDecl *var) {
16211626
}
16221627
}
16231628

1624-
emitBasicProlog(/*paramList*/ nullptr, /*selfParam*/ nullptr,
1625-
interfaceType, dc, /*throws=*/ false,SourceLoc(),
1629+
emitBasicProlog(dc,
1630+
/*paramList*/ nullptr,
1631+
/*selfParam*/ nullptr,
1632+
interfaceType,
1633+
/*errorType=*/llvm::None,
1634+
/*throwsLoc=*/SourceLoc(),
16261635
/*ignored parameters*/ 0);
1627-
prepareEpilog(interfaceType, llvm::None, CleanupLocation(loc));
1636+
prepareEpilog(dc, interfaceType, llvm::None, CleanupLocation(loc));
16281637

16291638
auto pbd = var->getParentPatternBinding();
16301639
const auto i = pbd->getPatternEntryIndexForVarDecl(var);
@@ -1676,11 +1685,11 @@ void SILGenFunction::emitGeneratorFunction(
16761685

16771686
auto *dc = function.getDecl()->getInnermostDeclContext();
16781687
auto captureInfo = SGM.M.Types.getLoweredLocalCaptures(function);
1679-
emitProlog(captureInfo, ParameterList::createEmpty(getASTContext()),
1680-
/*selfParam=*/nullptr, dc, resultInterfaceType, /*throws=*/false,
1681-
SourceLoc(), pattern);
1688+
emitProlog(dc, captureInfo, ParameterList::createEmpty(getASTContext()),
1689+
/*selfParam=*/nullptr, resultInterfaceType,
1690+
/*errorType=*/llvm::None, SourceLoc(), pattern);
16821691

1683-
prepareEpilog(resultInterfaceType, llvm::None, CleanupLocation(loc));
1692+
prepareEpilog(dc, resultInterfaceType, llvm::None, CleanupLocation(loc));
16841693

16851694
emitStmt(body);
16861695

lib/SILGen/SILGenFunction.h

+22-11
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
392392
/// postmatter and takes a BB argument of the exception type.
393393
JumpDest ThrowDest = JumpDest::invalid();
394394

395+
/// Support for typed throws.
396+
SILArgument *IndirectErrorResult = nullptr;
397+
395398
/// The destination for coroutine unwinds. The block will always
396399
/// be in the postmatter.
397400
JumpDest CoroutineUnwindDest = JumpDest::invalid();
@@ -1144,15 +1147,15 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
11441147
/// emitProlog - Generates prolog code to allocate and clean up mutable
11451148
/// storage for closure captures and local arguments.
11461149
void
1147-
emitProlog(CaptureInfo captureInfo, ParameterList *paramList,
1148-
ParamDecl *selfParam, DeclContext *DC, Type resultType,
1149-
bool throws, SourceLoc throwsLoc,
1150+
emitProlog(DeclContext *DC, CaptureInfo captureInfo, ParameterList *paramList,
1151+
ParamDecl *selfParam, Type resultType,
1152+
llvm::Optional<Type> errorType, SourceLoc throwsLoc,
11501153
llvm::Optional<AbstractionPattern> origClosureType = llvm::None);
11511154
/// A simpler version of emitProlog
11521155
/// \returns the number of variables in paramPatterns.
11531156
uint16_t emitBasicProlog(
1154-
ParameterList *paramList, ParamDecl *selfParam, Type resultType,
1155-
DeclContext *DC, bool throws, SourceLoc throwsLoc,
1157+
DeclContext *DC, ParameterList *paramList, ParamDecl *selfParam,
1158+
Type resultType, llvm::Optional<Type> errorType, SourceLoc throwsLoc,
11561159
unsigned numIgnoredTrailingParameters,
11571160
llvm::Optional<AbstractionPattern> origClosureType = llvm::None);
11581161

@@ -1169,17 +1172,25 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
11691172
/// Create (but do not emit) the epilog branch, and save the
11701173
/// current cleanups depth as the destination for return statement branches.
11711174
///
1175+
/// \param dc The declaration context whose generic signature to use for
1176+
/// interpreting interface types.
11721177
/// \param directResultType If given a value, the epilog block will be
11731178
/// created with arguments for each direct result of this
11741179
/// function, corresponding to the formal return type.
1175-
/// \param exnType If not None, create an error epilog block with the given
1176-
/// exception type.
1180+
/// \param errorType If not None, create an error epilog block with the given
1181+
/// thrown error type.
11771182
/// \param L The SILLocation which should be associated with
11781183
/// cleanup instructions.
1179-
void prepareEpilog(llvm::Optional<Type> directResultType,
1180-
llvm::Optional<Type> exnType,
1181-
CleanupLocation L);
1182-
void prepareRethrowEpilog(Type exnType, CleanupLocation l);
1184+
/// \param origClosureType Overrides the abstraction pattern for lowering the
1185+
/// error type.
1186+
void prepareEpilog(DeclContext *dc,
1187+
llvm::Optional<Type> directResultType,
1188+
llvm::Optional<Type> errorType,
1189+
CleanupLocation L,
1190+
llvm::Optional<AbstractionPattern> origClosureType = llvm::None);
1191+
void prepareRethrowEpilog(DeclContext *dc,
1192+
AbstractionPattern origErrorType,
1193+
Type errorType, CleanupLocation l);
11831194
void prepareCoroutineUnwindEpilog(CleanupLocation l);
11841195

11851196
/// Branch to and emit the epilog basic block. This will fuse

0 commit comments

Comments
 (0)