Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions include/swift/SIL/ApplySite.h
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,25 @@ class FullApplySite : public ApplySite {
llvm_unreachable("Covered switch isn't covered?!");
}

// For a direct error result, as a result of an @error convention, if any.
SILValue getDirectErrorResult() const {
switch (getKind()) {
case FullApplySiteKind::ApplyInst:
case FullApplySiteKind::BeginApplyInst:
return SILValue();
case FullApplySiteKind::TryApplyInst: {
if (getNumIndirectSILErrorResults())
return SILValue(); // Not a direct @error convention.

auto *errBlock = cast<TryApplyInst>(getInstruction())->getErrorBB();
assert(errBlock->getNumArguments() == 1 &&
"Expected this try_apply to have a single direct error result");
return errBlock->getArgument(0);
}
}
llvm_unreachable("Covered switch isn't covered?!");
}

unsigned getNumIndirectSILResults() const {
return getSubstCalleeConv().getNumIndirectSILResults();
}
Expand Down
26 changes: 23 additions & 3 deletions include/swift/SIL/SILFunctionConventions.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ class SILModuleConventions {

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

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

bool isTypeIndirectForIndirectParamConvention(CanType paramTy) {
Expand Down Expand Up @@ -261,9 +270,20 @@ class SILFunctionConventions {
}

bool isArgumentIndexOfIndirectErrorResult(unsigned idx) {
unsigned indirectResults = getNumIndirectSILResults();
return idx >= indirectResults &&
idx < indirectResults + getNumIndirectSILErrorResults();
if (auto errorIdx = getArgumentIndexOfIndirectErrorResult())
return idx == *errorIdx;

return false;
}

std::optional<unsigned> getArgumentIndexOfIndirectErrorResult() {
unsigned hasIndirectErrorResult = getNumIndirectSILErrorResults();
if (!hasIndirectErrorResult)
return std::nullopt;

assert(hasIndirectErrorResult == 1);
// Error index is the first one after the indirect return results, if any.
return getNumIndirectSILResults();
}

unsigned getNumAutoDiffSemanticResults() const {
Expand Down
12 changes: 5 additions & 7 deletions lib/SILGen/Cleanup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,19 +167,17 @@ void CleanupManager::emitBranchAndCleanups(JumpDest dest,
SILLocation branchLoc,
ArrayRef<SILValue> args,
ForUnwind_t forUnwind) {
emitCleanupsForBranch(dest, branchLoc, args, forUnwind);
emitCleanupsBeforeBranch(dest, forUnwind);
SGF.getBuilder().createBranch(branchLoc, dest.getBlock(), args);
}

/// emitBranchAndCleanups - Emit the cleanups necessary before branching to
/// emitCleanupsBeforeBranch - Emit the cleanups necessary before branching to
/// the given jump destination. This does not pop the cleanup stack, nor does
/// it emit the actual branch.
void CleanupManager::emitCleanupsForBranch(JumpDest dest,
SILLocation branchLoc,
ArrayRef<SILValue> args,
ForUnwind_t forUnwind) {
void CleanupManager::emitCleanupsBeforeBranch(JumpDest dest,
ForUnwind_t forUnwind) {
SILGenBuilder &builder = SGF.getBuilder();
assert(builder.hasValidInsertionPoint() && "Emitting branch in invalid spot");
assert(builder.hasValidInsertionPoint() && "no insertion point for cleanups");
emitCleanups(dest.getDepth(), dest.getCleanupLocation(),
forUnwind, /*popCleanups=*/false);
}
Expand Down
12 changes: 5 additions & 7 deletions lib/SILGen/Cleanup.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,15 +226,13 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager {
ArrayRef<SILValue> args = {},
ForUnwind_t forUnwind = NotForUnwind);

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

/// emitCleanupsForReturn - Emit the top-level cleanups needed prior to a
Expand Down
17 changes: 12 additions & 5 deletions lib/SILGen/SILGenApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2089,10 +2089,17 @@ static void emitRawApply(SILGenFunction &SGF,
auto result = normalBB->createPhiArgument(resultType, OwnershipKind::Owned);
rawResults.push_back(result);

// If the error is not passed indirectly, include the expected error type
// according to the SILFunctionConvention.
std::optional<TaggedUnion<SILValue, SILType>> errorAddrOrType;
if (indirectErrorAddr)
errorAddrOrType = indirectErrorAddr;
else
errorAddrOrType = substFnConv.getSILErrorType(SGF.getTypeExpansionContext());

SILBasicBlock *errorBB =
SGF.getTryApplyErrorDest(loc, substFnType, prevExecutor,
substFnType->getErrorResult(),
indirectErrorAddr,
*errorAddrOrType,
options.contains(ApplyFlags::DoesNotThrow));

options -= ApplyFlags::DoesNotThrow;
Expand Down Expand Up @@ -5962,9 +5969,9 @@ RValue SILGenFunction::emitApply(

SILValue indirectErrorAddr;
if (substFnType->hasErrorResult()) {
auto errorResult = substFnType->getErrorResult();
if (errorResult.getConvention() == ResultConvention::Indirect) {
auto loweredErrorResultType = getSILType(errorResult, substFnType);
auto convention = silConv.getFunctionConventions(substFnType);
if (auto errorResult = convention.getIndirectErrorResult()) {
auto loweredErrorResultType = getSILType(*errorResult, substFnType);
indirectErrorAddr = B.createAllocStack(loc, loweredErrorResultType);
enterDeallocStackCleanup(indirectErrorAddr);
}
Expand Down
5 changes: 2 additions & 3 deletions lib/SILGen/SILGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -2388,9 +2388,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
SILBasicBlock *getTryApplyErrorDest(SILLocation loc,
CanSILFunctionType fnTy,
ExecutorBreadcrumb prevExecutor,
SILResultInfo errorResult,
SILValue indirectErrorAddr,
bool isSuppressed);
TaggedUnion<SILValue, SILType> errorAddrOrType,
bool suppressErrorPath);

/// Emit a dynamic member reference.
RValue emitDynamicMemberRef(SILLocation loc, SILValue operand,
Expand Down
36 changes: 18 additions & 18 deletions lib/SILGen/SILGenStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1564,23 +1564,29 @@ void StmtEmitter::visitFailStmt(FailStmt *S) {

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

SILValue errorValue;
if (errorResult.getConvention() == ResultConvention::Owned) {
errorValue = destBB->createPhiArgument(getSILType(errorResult, fnTy),
OwnershipKind::Owned);
if (auto ownedErrorTy = errorAddrOrType.dyn_cast<SILType>()) {
errorValue = destBB->createPhiArgument(*ownedErrorTy,
OwnershipKind::Owned);
} else {
errorValue = indirectErrorAddr;
auto errorAddr = errorAddrOrType.get<SILValue>();
assert(errorAddr->getType().isAddress());
errorValue = errorAddr;
}

assert(B.hasValidInsertionPoint() && B.insertingAtEndOfBlock());
Expand Down Expand Up @@ -1653,9 +1659,6 @@ void SILGenFunction::emitThrow(SILLocation loc, ManagedValue exnMV,
} else {
// Call the _willThrowTyped entrypoint, which handles
// arbitrary error types.
SILValue tmpBuffer;
SILValue error;

FuncDecl *entrypoint = ctx.getWillThrowTyped();
auto genericSig = entrypoint->getGenericSignature();
SubstitutionMap subMap = SubstitutionMap::get(
Expand All @@ -1668,18 +1671,15 @@ void SILGenFunction::emitThrow(SILLocation loc, ManagedValue exnMV,
// Materialize the error so we can pass the address down to the
// swift_willThrowTyped.
exnMV = exnMV.materialize(*this, loc);
error = exnMV.getValue();
exn = exnMV.forward(*this);
} else {
// Claim the exception value.
exn = exnMV.forward(*this);
error = exn;
}

emitApplyOfLibraryIntrinsic(
loc, entrypoint, subMap,
{ ManagedValue::forForwardedRValue(*this, error) },
{ exnMV },
SGFContext());

// Claim the exception value.
exn = exnMV.forward(*this);
}
} else {
// Claim the exception value.
Expand Down Expand Up @@ -1749,8 +1749,8 @@ void SILGenFunction::emitThrow(SILLocation loc, ManagedValue exnMV,
B.createDestroyAddr(loc, exn);
}

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

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