Skip to content

Commit a528c5c

Browse files
authored
Merge pull request #84734 from kavon/opaque-values/fixes-2
OpaqueValues: support typed throws
2 parents 1413d37 + 37eafa9 commit a528c5c

File tree

10 files changed

+470
-105
lines changed

10 files changed

+470
-105
lines changed

include/swift/SIL/ApplySite.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,25 @@ class FullApplySite : public ApplySite {
790790
llvm_unreachable("Covered switch isn't covered?!");
791791
}
792792

793+
// For a direct error result, as a result of an @error convention, if any.
794+
SILValue getDirectErrorResult() const {
795+
switch (getKind()) {
796+
case FullApplySiteKind::ApplyInst:
797+
case FullApplySiteKind::BeginApplyInst:
798+
return SILValue();
799+
case FullApplySiteKind::TryApplyInst: {
800+
if (getNumIndirectSILErrorResults())
801+
return SILValue(); // Not a direct @error convention.
802+
803+
auto *errBlock = cast<TryApplyInst>(getInstruction())->getErrorBB();
804+
assert(errBlock->getNumArguments() == 1 &&
805+
"Expected this try_apply to have a single direct error result");
806+
return errBlock->getArgument(0);
807+
}
808+
}
809+
llvm_unreachable("Covered switch isn't covered?!");
810+
}
811+
793812
unsigned getNumIndirectSILResults() const {
794813
return getSubstCalleeConv().getNumIndirectSILResults();
795814
}

include/swift/SIL/SILFunctionConventions.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ class SILModuleConventions {
101101

102102
SILModule &getModule() const { return *M; }
103103

104+
/// Is the current convention to represent address-only types in their final,
105+
/// lowered form of a raw address?
106+
///
107+
/// Otherwise, address-only types are instead represented opaquely as SSA
108+
/// values, until the mandatory SIL pass AddressLowering has run.
109+
///
110+
/// See the -enable-sil-opaque-values flag.
111+
///
112+
/// \returns true iff address-only types are represented as raw addresses
104113
bool useLoweredAddresses() const { return loweredAddresses; }
105114

106115
bool isTypeIndirectForIndirectParamConvention(CanType paramTy) {
@@ -261,9 +270,20 @@ class SILFunctionConventions {
261270
}
262271

263272
bool isArgumentIndexOfIndirectErrorResult(unsigned idx) {
264-
unsigned indirectResults = getNumIndirectSILResults();
265-
return idx >= indirectResults &&
266-
idx < indirectResults + getNumIndirectSILErrorResults();
273+
if (auto errorIdx = getArgumentIndexOfIndirectErrorResult())
274+
return idx == *errorIdx;
275+
276+
return false;
277+
}
278+
279+
std::optional<unsigned> getArgumentIndexOfIndirectErrorResult() {
280+
unsigned hasIndirectErrorResult = getNumIndirectSILErrorResults();
281+
if (!hasIndirectErrorResult)
282+
return std::nullopt;
283+
284+
assert(hasIndirectErrorResult == 1);
285+
// Error index is the first one after the indirect return results, if any.
286+
return getNumIndirectSILResults();
267287
}
268288

269289
unsigned getNumAutoDiffSemanticResults() const {

lib/SILGen/Cleanup.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,19 +167,17 @@ void CleanupManager::emitBranchAndCleanups(JumpDest dest,
167167
SILLocation branchLoc,
168168
ArrayRef<SILValue> args,
169169
ForUnwind_t forUnwind) {
170-
emitCleanupsForBranch(dest, branchLoc, args, forUnwind);
170+
emitCleanupsBeforeBranch(dest, forUnwind);
171171
SGF.getBuilder().createBranch(branchLoc, dest.getBlock(), args);
172172
}
173173

174-
/// emitBranchAndCleanups - Emit the cleanups necessary before branching to
174+
/// emitCleanupsBeforeBranch - Emit the cleanups necessary before branching to
175175
/// the given jump destination. This does not pop the cleanup stack, nor does
176176
/// it emit the actual branch.
177-
void CleanupManager::emitCleanupsForBranch(JumpDest dest,
178-
SILLocation branchLoc,
179-
ArrayRef<SILValue> args,
180-
ForUnwind_t forUnwind) {
177+
void CleanupManager::emitCleanupsBeforeBranch(JumpDest dest,
178+
ForUnwind_t forUnwind) {
181179
SILGenBuilder &builder = SGF.getBuilder();
182-
assert(builder.hasValidInsertionPoint() && "Emitting branch in invalid spot");
180+
assert(builder.hasValidInsertionPoint() && "no insertion point for cleanups");
183181
emitCleanups(dest.getDepth(), dest.getCleanupLocation(),
184182
forUnwind, /*popCleanups=*/false);
185183
}

lib/SILGen/Cleanup.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -226,15 +226,13 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager {
226226
ArrayRef<SILValue> args = {},
227227
ForUnwind_t forUnwind = NotForUnwind);
228228

229-
/// Emit a branch to the given jump destination,
230-
/// threading out through any cleanups we need to run. This does not pop the
231-
/// cleanup stack.
229+
/// Emit the cleanups necessary before branching to
230+
/// the given jump destination. This does not pop the cleanup stack, nor does
231+
/// it emit the actual branch.
232232
///
233233
/// \param dest The destination scope and block.
234-
/// \param branchLoc The location of the branch instruction.
235-
/// \param args Arguments to pass to the destination block.
236-
void emitCleanupsForBranch(JumpDest dest, SILLocation branchLoc,
237-
ArrayRef<SILValue> args = {},
234+
/// \param forUnwind Whether the cleanups for this dest is for unwinding.
235+
void emitCleanupsBeforeBranch(JumpDest dest,
238236
ForUnwind_t forUnwind = NotForUnwind);
239237

240238
/// emitCleanupsForReturn - Emit the top-level cleanups needed prior to a

lib/SILGen/SILGenApply.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2089,10 +2089,17 @@ static void emitRawApply(SILGenFunction &SGF,
20892089
auto result = normalBB->createPhiArgument(resultType, OwnershipKind::Owned);
20902090
rawResults.push_back(result);
20912091

2092+
// If the error is not passed indirectly, include the expected error type
2093+
// according to the SILFunctionConvention.
2094+
std::optional<TaggedUnion<SILValue, SILType>> errorAddrOrType;
2095+
if (indirectErrorAddr)
2096+
errorAddrOrType = indirectErrorAddr;
2097+
else
2098+
errorAddrOrType = substFnConv.getSILErrorType(SGF.getTypeExpansionContext());
2099+
20922100
SILBasicBlock *errorBB =
20932101
SGF.getTryApplyErrorDest(loc, substFnType, prevExecutor,
2094-
substFnType->getErrorResult(),
2095-
indirectErrorAddr,
2102+
*errorAddrOrType,
20962103
options.contains(ApplyFlags::DoesNotThrow));
20972104

20982105
options -= ApplyFlags::DoesNotThrow;
@@ -5989,9 +5996,9 @@ RValue SILGenFunction::emitApply(
59895996

59905997
SILValue indirectErrorAddr;
59915998
if (substFnType->hasErrorResult()) {
5992-
auto errorResult = substFnType->getErrorResult();
5993-
if (errorResult.getConvention() == ResultConvention::Indirect) {
5994-
auto loweredErrorResultType = getSILType(errorResult, substFnType);
5999+
auto convention = silConv.getFunctionConventions(substFnType);
6000+
if (auto errorResult = convention.getIndirectErrorResult()) {
6001+
auto loweredErrorResultType = getSILType(*errorResult, substFnType);
59956002
indirectErrorAddr = B.createAllocStack(loc, loweredErrorResultType);
59966003
enterDeallocStackCleanup(indirectErrorAddr);
59976004
}

lib/SILGen/SILGenFunction.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2400,9 +2400,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
24002400
SILBasicBlock *getTryApplyErrorDest(SILLocation loc,
24012401
CanSILFunctionType fnTy,
24022402
ExecutorBreadcrumb prevExecutor,
2403-
SILResultInfo errorResult,
2404-
SILValue indirectErrorAddr,
2405-
bool isSuppressed);
2403+
TaggedUnion<SILValue, SILType> errorAddrOrType,
2404+
bool suppressErrorPath);
24062405

24072406
/// Emit a dynamic member reference.
24082407
RValue emitDynamicMemberRef(SILLocation loc, SILValue operand,

lib/SILGen/SILGenStmt.cpp

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,23 +1672,29 @@ void StmtEmitter::visitFailStmt(FailStmt *S) {
16721672

16731673
/// Return a basic block suitable to be the destination block of a
16741674
/// try_apply instruction. The block is implicitly emitted and filled in.
1675+
///
1676+
/// \param errorAddrOrType Either the address of the indirect error result where
1677+
/// the result will be stored, or the type of the expected Owned error value.
1678+
///
1679+
/// \param suppressErrorPath Should the error path be emitted as unreachable?
16751680
SILBasicBlock *
16761681
SILGenFunction::getTryApplyErrorDest(SILLocation loc,
16771682
CanSILFunctionType fnTy,
16781683
ExecutorBreadcrumb prevExecutor,
1679-
SILResultInfo errorResult,
1680-
SILValue indirectErrorAddr,
1684+
TaggedUnion<SILValue, SILType> errorAddrOrType,
16811685
bool suppressErrorPath) {
16821686
// For now, don't try to re-use destination blocks for multiple
16831687
// failure sites.
16841688
SILBasicBlock *destBB = createBasicBlock(FunctionSection::Postmatter);
16851689

16861690
SILValue errorValue;
1687-
if (errorResult.getConvention() == ResultConvention::Owned) {
1688-
errorValue = destBB->createPhiArgument(getSILType(errorResult, fnTy),
1689-
OwnershipKind::Owned);
1691+
if (auto ownedErrorTy = errorAddrOrType.dyn_cast<SILType>()) {
1692+
errorValue = destBB->createPhiArgument(*ownedErrorTy,
1693+
OwnershipKind::Owned);
16901694
} else {
1691-
errorValue = indirectErrorAddr;
1695+
auto errorAddr = errorAddrOrType.get<SILValue>();
1696+
assert(errorAddr->getType().isAddress());
1697+
errorValue = errorAddr;
16921698
}
16931699

16941700
assert(B.hasValidInsertionPoint() && B.insertingAtEndOfBlock());
@@ -1761,9 +1767,6 @@ void SILGenFunction::emitThrow(SILLocation loc, ManagedValue exnMV,
17611767
} else {
17621768
// Call the _willThrowTyped entrypoint, which handles
17631769
// arbitrary error types.
1764-
SILValue tmpBuffer;
1765-
SILValue error;
1766-
17671770
FuncDecl *entrypoint = ctx.getWillThrowTyped();
17681771
auto genericSig = entrypoint->getGenericSignature();
17691772
SubstitutionMap subMap = SubstitutionMap::get(
@@ -1776,18 +1779,15 @@ void SILGenFunction::emitThrow(SILLocation loc, ManagedValue exnMV,
17761779
// Materialize the error so we can pass the address down to the
17771780
// swift_willThrowTyped.
17781781
exnMV = exnMV.materialize(*this, loc);
1779-
error = exnMV.getValue();
1780-
exn = exnMV.forward(*this);
1781-
} else {
1782-
// Claim the exception value.
1783-
exn = exnMV.forward(*this);
1784-
error = exn;
17851782
}
17861783

17871784
emitApplyOfLibraryIntrinsic(
17881785
loc, entrypoint, subMap,
1789-
{ ManagedValue::forForwardedRValue(*this, error) },
1786+
{ exnMV },
17901787
SGFContext());
1788+
1789+
// Claim the exception value.
1790+
exn = exnMV.forward(*this);
17911791
}
17921792
} else {
17931793
// Claim the exception value.
@@ -1857,8 +1857,8 @@ void SILGenFunction::emitThrow(SILLocation loc, ManagedValue exnMV,
18571857
B.createDestroyAddr(loc, exn);
18581858
}
18591859

1860-
// Branch to the cleanup destination.
1861-
Cleanups.emitCleanupsForBranch(ThrowDest, loc, args, IsForUnwind);
1860+
// Emit clean-ups needed prior to entering throw block.
1861+
Cleanups.emitCleanupsBeforeBranch(ThrowDest, IsForUnwind);
18621862

18631863
if (indirectErrorAddr && !exn->getType().isAddress()) {
18641864
// Forward the error value into the return slot now. This has to happen

0 commit comments

Comments
 (0)