Skip to content

Several minor changes in preparation for accessor coroutines #17752

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 5, 2018
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
7 changes: 5 additions & 2 deletions include/swift/AST/ASTScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,11 +489,14 @@ class ASTScope {
/// introduced by this statement.
static ASTScope *createIfNeeded(const ASTScope *parent, Stmt *stmt);

/// Create a new AST scope if one is needed for the given expression.
/// Create a new AST scope if one is needed for the given child expression(s).
/// In the first variant, the expression can be \c null.
///
/// \returns the newly-created AST scope, or \c null if there is no scope
/// introduced by this expression.
static ASTScope *createIfNeeded(const ASTScope *parent, Expr *Expr);
static ASTScope *createIfNeeded(const ASTScope *parent, Expr *expr);
static ASTScope *createIfNeeded(const ASTScope *parent,
ArrayRef<Expr *> exprs);

/// Create a new AST scope if one is needed for the given AST node.
///
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4134,6 +4134,9 @@ class AbstractStorageDecl : public ValueDecl {
/// is a member. Currently only variables can be static.
inline bool isStatic() const; // defined in this header

/// \brief Return the interface type of the stored value.
Type getValueInterfaceType() const;

/// \brief Determine how this storage is implemented.
StorageImplInfo getImplInfo() const {
if (auto ptr = Accessors.getPointer())
Expand Down
17 changes: 11 additions & 6 deletions lib/AST/ASTScope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1070,9 +1070,8 @@ ASTScope *ASTScope::createIfNeeded(const ASTScope *parent, Stmt *stmt) {
}

/// Find all of the (non-nested) closures referenced within this expression.
static SmallVector<ClosureExpr *, 4> findClosures(Expr *expr) {
SmallVector<ClosureExpr *, 4> closures;
if (!expr) return closures;
static void findClosures(Expr *expr, SmallVectorImpl<ClosureExpr *> &closures) {
if (!expr) return;

/// AST walker that finds top-level closures in an expression.
class ClosureFinder : public ASTWalker {
Expand Down Expand Up @@ -1110,14 +1109,20 @@ static SmallVector<ClosureExpr *, 4> findClosures(Expr *expr) {
};

expr->walk(ClosureFinder(closures));
return closures;
}

ASTScope *ASTScope::createIfNeeded(const ASTScope *parent, Expr *expr) {
if (!expr) return nullptr;
return createIfNeeded(parent, llvm::makeArrayRef(expr));
}

ASTScope *ASTScope::createIfNeeded(const ASTScope *parent,
ArrayRef<Expr *> exprs) {
SmallVector<ClosureExpr*, 4> closures;

// Dig out closure expressions within the given expression.
auto closures = findClosures(expr);
// Dig out closure expressions within the given expressions.
for (auto expr: exprs)
findClosures(expr, closures);
if (closures.empty())
return nullptr;

Expand Down
6 changes: 6 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4071,6 +4071,12 @@ SourceLoc AbstractStorageDecl::getOverrideLoc() const {
return SourceLoc();
}

Type AbstractStorageDecl::getValueInterfaceType() const {
if (auto var = dyn_cast<VarDecl>(this))
return var->getInterfaceType();
return cast<SubscriptDecl>(this)->getElementInterfaceType();
}

Type VarDecl::getType() const {
if (!typeInContext) {
const_cast<VarDecl *>(this)->typeInContext =
Expand Down
6 changes: 2 additions & 4 deletions lib/ClangImporter/ImporterImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -625,11 +625,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
} else if (auto *CD = dyn_cast<ConstructorDecl>(decl)) {
assert(CD->getInterfaceType());
ty = CD->getResultInterfaceType();
} else if (auto *SD = dyn_cast<SubscriptDecl>(decl)) {
ty = SD->getElementInterfaceType();
} else {
auto *VD = cast<VarDecl>(decl);
ty = VD->getInterfaceType()->getReferenceStorageReferent();
ty = cast<AbstractStorageDecl>(decl)->getValueInterfaceType()
->getReferenceStorageReferent();
}
#endif

Expand Down
18 changes: 10 additions & 8 deletions lib/SILGen/Cleanup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ void CleanupManager::popTopDeadCleanups(CleanupsDepth end) {
}

void CleanupManager::emitCleanups(CleanupsDepth depth, CleanupLocation loc,
bool popCleanups) {
ForUnwind_t forUnwind, bool popCleanups) {
auto begin = stack.stable_begin();
while (begin != depth) {
auto iter = stack.find(begin);
Expand All @@ -76,7 +76,7 @@ void CleanupManager::emitCleanups(CleanupsDepth depth, CleanupLocation loc,
stack.pop();

if (cleanup.isActive() && SGF.B.hasValidInsertionPoint())
cleanup.emit(SGF, loc);
cleanup.emit(SGF, loc, forUnwind);

stack.checkIterator(begin);
}
Expand All @@ -95,7 +95,7 @@ void CleanupManager::endScope(CleanupsDepth depth, CleanupLocation loc) {

// Iteratively mark cleanups dead and pop them.
// Maybe we'd get better results if we marked them all dead in one shot?
emitCleanups(depth, loc);
emitCleanups(depth, loc, NotForUnwind);
}

bool CleanupManager::hasAnyActiveCleanups(CleanupsDepth from,
Expand All @@ -111,35 +111,37 @@ bool CleanupManager::hasAnyActiveCleanups(CleanupsDepth from) {
/// threading out through any cleanups we might need to run. This does not
/// pop the cleanup stack.
void CleanupManager::emitBranchAndCleanups(JumpDest dest, SILLocation branchLoc,
ArrayRef<SILValue> args) {
ArrayRef<SILValue> args,
ForUnwind_t forUnwind) {
SILGenBuilder &builder = SGF.getBuilder();
assert(builder.hasValidInsertionPoint() && "Emitting branch in invalid spot");
emitCleanups(dest.getDepth(), dest.getCleanupLocation(),
/*popCleanups=*/false);
forUnwind, /*popCleanups=*/false);
builder.createBranch(branchLoc, dest.getBlock(), args);
}

void CleanupManager::emitCleanupsForReturn(CleanupLocation loc) {
SILGenBuilder &builder = SGF.getBuilder();
assert(builder.hasValidInsertionPoint() && "Emitting return in invalid spot");
(void)builder;
emitCleanups(stack.stable_end(), loc, /*popCleanups=*/false);
emitCleanups(stack.stable_end(), loc, NotForUnwind, /*popCleanups=*/false);
}

/// Emit a new block that jumps to the specified location and runs necessary
/// cleanups based on its level. If there are no cleanups to run, this just
/// returns the dest block.
SILBasicBlock *CleanupManager::emitBlockForCleanups(JumpDest dest,
SILLocation branchLoc,
ArrayRef<SILValue> args) {
ArrayRef<SILValue> args,
ForUnwind_t forUnwind) {
// If there are no cleanups to run, just return the Dest block directly.
if (!hasAnyActiveCleanups(dest.getDepth()))
return dest.getBlock();

// Otherwise, create and emit a new block.
auto *newBlock = SGF.createBasicBlock();
SILGenSavedInsertionPoint IPRAII(SGF, newBlock);
emitBranchAndCleanups(dest, branchLoc, args);
emitBranchAndCleanups(dest, branchLoc, args, forUnwind);
return newBlock;
}

Expand Down
25 changes: 22 additions & 3 deletions lib/SILGen/Cleanup.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@ class ManagedValue;
class SharedBorrowFormalAccess;
class FormalEvaluationScope;

/// Is a cleanup being executed as a result of some sort of forced
/// unwinding, such as an error being thrown, or are we just cleaning up
/// after some operation?
///
/// Most cleanups don't care, but the cleanups tied to l-value accesses do:
/// the access will be aborted rather than ended normally, which may cause
/// e.g. writebacks to be skipped. It is also important that no actions
/// be undertaken by an unwind cleanup that might change control flow,
/// such as throwing an error. In contrast, non-unwinding cleanups are
/// permitted to change control flow.
enum ForUnwind_t : bool {
NotForUnwind,
IsForUnwind
};

/// The valid states that a cleanup can be in.
enum class CleanupState {
/// The cleanup is inactive but may be activated later.
Expand Down Expand Up @@ -80,7 +95,8 @@ class LLVM_LIBRARY_VISIBILITY Cleanup {
bool isActive() const { return state >= CleanupState::Active; }
bool isDead() const { return state == CleanupState::Dead; }

virtual void emit(SILGenFunction &SGF, CleanupLocation loc) = 0;
virtual void emit(SILGenFunction &SGF, CleanupLocation loc,
ForUnwind_t forUnwind) = 0;
virtual void dump(SILGenFunction &SGF) const = 0;
};

Expand Down Expand Up @@ -120,6 +136,7 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager {

void popTopDeadCleanups(CleanupsDepth end);
void emitCleanups(CleanupsDepth depth, CleanupLocation l,
ForUnwind_t forUnwind,
bool popCleanups=true);
void endScope(CleanupsDepth depth, CleanupLocation l);

Expand Down Expand Up @@ -151,7 +168,8 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager {
/// \param branchLoc The location of the branch instruction.
/// \param args Arguments to pass to the destination block.
void emitBranchAndCleanups(JumpDest dest, SILLocation branchLoc,
ArrayRef<SILValue> args = {});
ArrayRef<SILValue> args = {},
ForUnwind_t forUnwind = NotForUnwind);

/// emitCleanupsForReturn - Emit the top-level cleanups needed prior to a
/// return from the function.
Expand All @@ -161,7 +179,8 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager {
/// cleanups based on its level. If there are no cleanups to run, this just
/// returns the dest block.
SILBasicBlock *emitBlockForCleanups(JumpDest dest, SILLocation branchLoc,
ArrayRef<SILValue> args = {});
ArrayRef<SILValue> args = {},
ForUnwind_t forUnwind = NotForUnwind);

/// pushCleanup - Push a new cleanup.
template<class T, class... A>
Expand Down
4 changes: 2 additions & 2 deletions lib/SILGen/SILGenApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3338,7 +3338,7 @@ class DeallocateUninitializedBox : public Cleanup {
public:
DeallocateUninitializedBox(SILValue box) : box(box) {}

void emit(SILGenFunction &SGF, CleanupLocation l) override {
void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override {
SGF.B.createDeallocBox(l, box);
}

Expand Down Expand Up @@ -4830,7 +4830,7 @@ namespace {
DeallocateUninitializedArray(SILValue array)
: Array(array) {}

void emit(SILGenFunction &SGF, CleanupLocation l) override {
void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override {
SGF.emitUninitializedArrayDeallocation(l, Array);
}

Expand Down
24 changes: 16 additions & 8 deletions lib/SILGen/SILGenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ namespace {
SILValue closure;
public:
CleanupClosureConstant(SILValue closure) : closure(closure) {}
void emit(SILGenFunction &SGF, CleanupLocation l) override {
void emit(SILGenFunction &SGF, CleanupLocation l,
ForUnwind_t forUnwind) override {
SGF.B.emitDestroyValueOperation(l, closure);
}
void dump(SILGenFunction &) const override {
Expand Down Expand Up @@ -250,7 +251,8 @@ class EndBorrowCleanup : public Cleanup {
EndBorrowCleanup(SILValue original, SILValue borrowed)
: original(original), borrowed(borrowed) {}

void emit(SILGenFunction &SGF, CleanupLocation l) override {
void emit(SILGenFunction &SGF, CleanupLocation l,
ForUnwind_t forUnwind) override {
SGF.B.createEndBorrow(l, borrowed, original);
}

Expand All @@ -271,7 +273,8 @@ class ReleaseValueCleanup : public Cleanup {
public:
ReleaseValueCleanup(SILValue v) : v(v) {}

void emit(SILGenFunction &SGF, CleanupLocation l) override {
void emit(SILGenFunction &SGF, CleanupLocation l,
ForUnwind_t forUnwind) override {
if (v->getType().isAddress())
SGF.B.createDestroyAddr(l, v);
else
Expand All @@ -295,7 +298,8 @@ class DeallocStackCleanup : public Cleanup {
public:
DeallocStackCleanup(SILValue addr) : Addr(addr) {}

void emit(SILGenFunction &SGF, CleanupLocation l) override {
void emit(SILGenFunction &SGF, CleanupLocation l,
ForUnwind_t forUnwind) override {
SGF.B.createDeallocStack(l, Addr);
}

Expand All @@ -316,7 +320,8 @@ class DestroyLocalVariable : public Cleanup {
public:
DestroyLocalVariable(VarDecl *var) : Var(var) {}

void emit(SILGenFunction &SGF, CleanupLocation l) override {
void emit(SILGenFunction &SGF, CleanupLocation l,
ForUnwind_t forUnwind) override {
SGF.destroyLocalVariable(l, Var);
}

Expand Down Expand Up @@ -349,7 +354,8 @@ class DeallocateUninitializedLocalVariable : public Cleanup {
public:
DeallocateUninitializedLocalVariable(VarDecl *var) : Var(var) {}

void emit(SILGenFunction &SGF, CleanupLocation l) override {
void emit(SILGenFunction &SGF, CleanupLocation l,
ForUnwind_t forUnwind) override {
SGF.deallocateUninitializedLocalVariable(l, Var);
}

Expand Down Expand Up @@ -1304,7 +1310,8 @@ namespace {
concreteFormalType(concreteFormalType),
repr(repr) {}

void emit(SILGenFunction &SGF, CleanupLocation l) override {
void emit(SILGenFunction &SGF, CleanupLocation l,
ForUnwind_t forUnwind) override {
switch (repr) {
case ExistentialRepresentation::None:
case ExistentialRepresentation::Class:
Expand Down Expand Up @@ -1481,7 +1488,8 @@ struct FormalAccessReleaseValueCleanup : Cleanup {
state = newState;
}

void emit(SILGenFunction &SGF, CleanupLocation l) override {
void emit(SILGenFunction &SGF, CleanupLocation l,
ForUnwind_t forUnwind) override {
getEvaluation(SGF).finish(SGF);
}

Expand Down
10 changes: 6 additions & 4 deletions lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ struct EndBorrowCleanup : Cleanup {
EndBorrowCleanup(SILValue originalValue, SILValue borrowedValue)
: originalValue(originalValue), borrowedValue(borrowedValue) {}

void emit(SILGenFunction &SGF, CleanupLocation l) override {
void emit(SILGenFunction &SGF, CleanupLocation l,
ForUnwind_t forUnwind) override {
SGF.B.createEndBorrow(l, borrowedValue, originalValue);
}

Expand All @@ -187,7 +188,7 @@ struct FormalEvaluationEndBorrowCleanup : Cleanup {

FormalEvaluationEndBorrowCleanup() : Depth() {}

void emit(SILGenFunction &SGF, CleanupLocation l) override {
void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override {
getEvaluation(SGF).finish(SGF);
}

Expand Down Expand Up @@ -276,7 +277,8 @@ struct EndBorrowArgumentCleanup : Cleanup {

EndBorrowArgumentCleanup(SILPHIArgument *arg) : arg(arg) {}

void emit(SILGenFunction &SGF, CleanupLocation l) override {
void emit(SILGenFunction &SGF, CleanupLocation l,
ForUnwind_t forUnwind) override {
SGF.B.createEndBorrowArgument(l, arg);
}

Expand Down Expand Up @@ -708,7 +710,7 @@ struct DelegateInitSelfWritebackCleanup : Cleanup {
SILValue value)
: loc(loc), lvalueAddress(lvalueAddress), value(value) {}

void emit(SILGenFunction &SGF, CleanupLocation) override {
void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override {
SILValue valueToStore = value;
SILType lvalueObjTy = lvalueAddress->getType().getObjectType();

Expand Down
7 changes: 5 additions & 2 deletions lib/SILGen/SILGenLValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ struct LValueWritebackCleanup : Cleanup {

LValueWritebackCleanup() : Depth() {}

void emit(SILGenFunction &SGF, CleanupLocation loc) override {
void emit(SILGenFunction &SGF, CleanupLocation loc,
ForUnwind_t forUnwind) override {
// TODO: honor forUnwind!
auto &evaluation = *SGF.FormalEvalContext.find(Depth);
assert(evaluation.getKind() == FormalAccess::Exclusive);
auto &lvalue = static_cast<ExclusiveBorrowFormalAccess &>(evaluation);
Expand Down Expand Up @@ -554,7 +556,8 @@ struct UnenforcedAccessCleanup : Cleanup {

UnenforcedAccessCleanup() : Depth() {}

void emit(SILGenFunction &SGF, CleanupLocation loc) override {
void emit(SILGenFunction &SGF, CleanupLocation loc,
ForUnwind_t forUnwind) override {
auto &evaluation = *SGF.FormalEvalContext.find(Depth);
assert(evaluation.getKind() == FormalAccess::Unenforced);
auto &formalAccess = static_cast<UnenforcedFormalAccess &>(evaluation);
Expand Down
3 changes: 2 additions & 1 deletion lib/SILGen/SILGenMaterializeForSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,8 @@ namespace {
public:
DeallocateValueBuffer(SILType valueType, SILValue buffer)
: Buffer(buffer), ValueType(valueType) {}
void emit(SILGenFunction &SGF, CleanupLocation loc) override {
void emit(SILGenFunction &SGF, CleanupLocation loc,
ForUnwind_t forUnwind) override {
SGF.B.createDeallocValueBuffer(loc, ValueType, Buffer);
}
void dump(SILGenFunction &) const override {
Expand Down
Loading