Skip to content

Miscellaneous NFC patches #18750

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 4 commits into from
Aug 16, 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
51 changes: 29 additions & 22 deletions include/swift/AST/AnyFunctionRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,29 +83,14 @@ class AnyFunctionRef {
return TheFunction.get<AbstractClosureExpr *>()->getResultType();
}

struct YieldResult {
Type Ty;
VarDecl::Specifier Specifier;
};
ArrayRef<AnyFunctionType::Yield>
getYieldResults(SmallVectorImpl<AnyFunctionType::Yield> &buffer) const {
return getYieldResultsImpl(buffer, /*mapIntoContext*/ false);
}

ArrayRef<YieldResult>
getBodyYieldResults(SmallVectorImpl<YieldResult> &buffer) const {
assert(buffer.empty());
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
if (auto *AD = dyn_cast<AccessorDecl>(AFD)) {
if (AD->isCoroutine()) {
auto valueTy = AD->getStorage()->getValueInterfaceType();
valueTy = AD->mapTypeIntoContext(valueTy);
auto specifier =
AD->getAccessorKind() == AccessorKind::Modify
? VarDecl::Specifier::InOut
: VarDecl::Specifier::Shared;
buffer.push_back({valueTy, specifier});
return buffer;
}
}
}
return {};
ArrayRef<AnyFunctionType::Yield>
getBodyYieldResults(SmallVectorImpl<AnyFunctionType::Yield> &buffer) const {
return getYieldResultsImpl(buffer, /*mapIntoContext*/ true);
}

BraceStmt *getBody() const {
Expand Down Expand Up @@ -196,6 +181,28 @@ class AnyFunctionRef {
}
llvm_unreachable("unexpected AnyFunctionRef representation");
}

private:
ArrayRef<AnyFunctionType::Yield>
getYieldResultsImpl(SmallVectorImpl<AnyFunctionType::Yield> &buffer,
bool mapIntoContext) const {
assert(buffer.empty());
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
if (auto *AD = dyn_cast<AccessorDecl>(AFD)) {
if (AD->isCoroutine()) {
auto valueTy = AD->getStorage()->getValueInterfaceType();
if (mapIntoContext)
valueTy = AD->mapTypeIntoContext(valueTy);
YieldTypeFlags flags(AD->getAccessorKind() == AccessorKind::Modify
? ValueOwnership::InOut
: ValueOwnership::Shared);
buffer.push_back(AnyFunctionType::Yield(valueTy, flags));
return buffer;
}
}
}
return {};
}
};
#if SWIFT_COMPILER_IS_MSVC
#pragma warning(pop)
Expand Down
13 changes: 7 additions & 6 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4143,15 +4143,15 @@ class AbstractStorageDecl : public ValueDecl {

protected:
AbstractStorageDecl(DeclKind Kind, DeclContext *DC, DeclName Name,
SourceLoc NameLoc, bool supportsMutation)
SourceLoc NameLoc, StorageIsMutable_t supportsMutation)
: ValueDecl(Kind, DC, Name, NameLoc) {
Bits.AbstractStorageDecl.HasStorage = true;
Bits.AbstractStorageDecl.SupportsMutation = supportsMutation;
Bits.AbstractStorageDecl.IsGetterMutating = false;
Bits.AbstractStorageDecl.IsSetterMutating = true;
}

void setSupportsMutationIfStillStored(bool supportsMutation) {
void setSupportsMutationIfStillStored(StorageIsMutable_t supportsMutation) {
if (auto ptr = Accessors.getPointer()) {
auto impl = ptr->getImplInfo();
if (!impl.isSimpleStored()) return;
Expand Down Expand Up @@ -4210,8 +4210,8 @@ class AbstractStorageDecl : public ValueDecl {
/// don't support mutation (e.g. to initialize them), and sometimes we
/// can't mutate things that do support mutation (e.g. because their
/// setter is private).
bool supportsMutation() const {
return Bits.AbstractStorageDecl.SupportsMutation;
StorageIsMutable_t supportsMutation() const {
return StorageIsMutable_t(Bits.AbstractStorageDecl.SupportsMutation);
}

/// Are there any accessors for this declaration, including implicit ones?
Expand Down Expand Up @@ -4452,7 +4452,8 @@ class VarDecl : public AbstractStorageDecl {

VarDecl(DeclKind Kind, bool IsStatic, Specifier Sp, bool IsCaptureList,
SourceLoc NameLoc, Identifier Name, DeclContext *DC)
: AbstractStorageDecl(Kind, DC, Name, NameLoc, !isImmutableSpecifier(Sp))
: AbstractStorageDecl(Kind, DC, Name, NameLoc,
StorageIsMutable_t(!isImmutableSpecifier(Sp)))
{
Bits.VarDecl.IsStatic = IsStatic;
Bits.VarDecl.Specifier = static_cast<unsigned>(Sp);
Expand Down Expand Up @@ -4853,7 +4854,7 @@ class SubscriptDecl : public GenericContext, public AbstractStorageDecl {
GenericParamList *GenericParams)
: GenericContext(DeclContextKind::SubscriptDecl, Parent),
AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc,
/*supports mutation (will be overwritten)*/ true),
/*will be overwritten*/ StorageIsNotMutable),
ArrowLoc(ArrowLoc), Indices(nullptr), ElementTy(ElementTy) {
setIndices(Indices);
setGenericParams(GenericParams);
Expand Down
29 changes: 18 additions & 11 deletions include/swift/AST/StorageImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@

namespace swift {

enum StorageIsMutable_t : bool {
StorageIsNotMutable = false,
StorageIsMutable = true
};

// Note that the values of these enums line up with %select values in
// diagnostics.
enum class AccessorKind {
Expand Down Expand Up @@ -309,16 +314,17 @@ class StorageImplInfo {
#endif
}

static StorageImplInfo getSimpleStored(bool supportsMutation) {
static StorageImplInfo getSimpleStored(StorageIsMutable_t isMutable) {
return { ReadImplKind::Stored,
supportsMutation ? WriteImplKind::Stored
: WriteImplKind::Immutable,
supportsMutation ? ReadWriteImplKind::Stored
: ReadWriteImplKind::Immutable };
isMutable ? WriteImplKind::Stored
: WriteImplKind::Immutable,
isMutable ? ReadWriteImplKind::Stored
: ReadWriteImplKind::Immutable };
}

static StorageImplInfo getOpaque(bool supportsMutation) {
return (supportsMutation ? getMutableOpaque() : getImmutableOpaque());
static StorageImplInfo getOpaque(StorageIsMutable_t isMutable) {
return (isMutable ? getMutableOpaque()
: getImmutableOpaque());
}

/// Describe the implementation of a immutable property implemented opaquely.
Expand All @@ -332,8 +338,9 @@ class StorageImplInfo {
ReadWriteImplKind::MaterializeForSet };
}

static StorageImplInfo getComputed(bool supportsMutation) {
return (supportsMutation ? getMutableComputed() : getImmutableComputed());
static StorageImplInfo getComputed(StorageIsMutable_t isMutable) {
return (isMutable ? getMutableComputed()
: getImmutableComputed());
}

/// Describe the implementation of an immutable property implemented
Expand Down Expand Up @@ -362,8 +369,8 @@ class StorageImplInfo {
}

/// Does this describe storage that supports mutation?
bool supportsMutation() const {
return getWriteImpl() != WriteImplKind::Immutable;
StorageIsMutable_t supportsMutation() const {
return StorageIsMutable_t(getWriteImpl() != WriteImplKind::Immutable);
}

ReadImplKind getReadImpl() const {
Expand Down
114 changes: 113 additions & 1 deletion include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1745,6 +1745,70 @@ class ParameterTypeFlags {
uint8_t toRaw() const { return value.toRaw(); }
};

class YieldTypeFlags {
enum YieldFlags : uint8_t {
None = 0,
InOut = 1 << 1,
Shared = 1 << 2,
Owned = 1 << 3,

NumBits = 3
};
OptionSet<YieldFlags> value;

static_assert(NumBits < 8 * sizeof(OptionSet<YieldFlags>), "overflowed");

YieldTypeFlags(OptionSet<YieldFlags, uint8_t> val) : value(val) {}

public:
YieldTypeFlags() = default;
static YieldTypeFlags fromRaw(uint8_t raw) {
return YieldTypeFlags(OptionSet<YieldFlags>(raw));
}

YieldTypeFlags(ValueOwnership ownership)
: value((ownership == ValueOwnership::InOut ? InOut : 0) |
(ownership == ValueOwnership::Shared ? Shared : 0) |
(ownership == ValueOwnership::Owned ? Owned : 0)) {}

bool isInOut() const { return value.contains(InOut); }
bool isShared() const { return value.contains(Shared); }
bool isOwned() const { return value.contains(Owned); }

ValueOwnership getValueOwnership() const {
if (isInOut())
return ValueOwnership::InOut;
else if (isShared())
return ValueOwnership::Shared;
else if (isOwned())
return ValueOwnership::Owned;

return ValueOwnership::Default;
}

YieldTypeFlags withInOut(bool isInout) const {
return YieldTypeFlags(isInout ? value | InOut : value - InOut);
}

YieldTypeFlags withShared(bool isShared) const {
return YieldTypeFlags(isShared ? value | Shared : value - Shared);
}

YieldTypeFlags withOwned(bool isOwned) const {
return YieldTypeFlags(isOwned ? value | Owned : value - Owned);
}

bool operator ==(const YieldTypeFlags &other) const {
return value.toRaw() == other.value.toRaw();
}

bool operator!=(const YieldTypeFlags &other) const {
return value.toRaw() != other.value.toRaw();
}

uint8_t toRaw() const { return value.toRaw(); }
};

/// ParenType - A paren type is a type that's been written in parentheses.
class ParenType : public SugarType {
friend class ASTContext;
Expand Down Expand Up @@ -2560,7 +2624,7 @@ class AnyFunctionType : public TypeBase {

public:
using Representation = FunctionTypeRepresentation;

class Param {
public:
explicit Param(const TupleTypeElt &tte);
Expand Down Expand Up @@ -2635,6 +2699,50 @@ class AnyFunctionType : public TypeBase {
using CanParamArrayRef =
ArrayRefView<Param,CanParam,CanParam::getFromParam,/*AccessOriginal*/true>;

class CanYield;
class Yield {
Type Ty;
YieldTypeFlags Flags;
public:
explicit Yield(Type type, YieldTypeFlags flags)
: Ty(type), Flags(flags) {}

Type getType() const { return Ty; }

YieldTypeFlags getFlags() const { return Flags; }
ValueOwnership getValueOwnership() const {
return getFlags().getValueOwnership();
}
bool isInOut() const { return getFlags().isInOut(); }

CanYield getCanonical() const;

Yield subst(SubstitutionMap subs, SubstOptions options = None) const {
return Yield(getType().subst(subs, options), getFlags());
}

bool operator==(const Yield &other) const {
return getType()->isEqual(other.getType()) &&
getFlags() == other.getFlags();
}
bool operator!=(const Yield &other) const {
return !operator==(other);
}
};

class CanYield : public Yield {
public:
explicit CanYield(CanType type, YieldTypeFlags flags)
: Yield(type, flags) {}

CanType getType() const { return CanType(Yield::getType()); }

CanYield subst(SubstitutionMap subs, SubstOptions options = None) const {
return CanYield(getType().subst(subs, options)->getCanonicalType(),
getFlags());
}
};

/// \brief A class which abstracts out some details necessary for
/// making a call.
class ExtInfo {
Expand Down Expand Up @@ -2896,6 +3004,10 @@ BEGIN_CAN_TYPE_WRAPPER(AnyFunctionType, Type)
}
END_CAN_TYPE_WRAPPER(AnyFunctionType, Type)

inline AnyFunctionType::CanYield AnyFunctionType::Yield::getCanonical() const {
return CanYield(getType()->getCanonicalType(), getFlags());
}

/// FunctionType - A monomorphic function type, specified with an arrow.
///
/// For example:
Expand Down
3 changes: 2 additions & 1 deletion lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4577,7 +4577,8 @@ bool VarDecl::isSelfParameter() const {

void VarDecl::setSpecifier(Specifier specifier) {
Bits.VarDecl.Specifier = static_cast<unsigned>(specifier);
setSupportsMutationIfStillStored(!isImmutableSpecifier(specifier));
setSupportsMutationIfStillStored(
StorageIsMutable_t(!isImmutableSpecifier(specifier)));
}

bool VarDecl::isAnonClosureParam() const {
Expand Down
2 changes: 1 addition & 1 deletion lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4768,7 +4768,7 @@ Parser::ParsedAccessors::classify(Parser &P, AbstractStorageDecl *storage,
// Allow the sil_stored attribute to override all the accessors we parsed
// when making the final classification.
if (attrs.hasAttribute<SILStoredAttr>()) {
return StorageImplInfo::getSimpleStored(Set != nullptr);
return StorageImplInfo::getSimpleStored(StorageIsMutable_t(Set != nullptr));
}

return StorageImplInfo(readImpl, writeImpl, readWriteImpl);
Expand Down
5 changes: 3 additions & 2 deletions lib/SILGen/Cleanup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,12 @@ void CleanupManager::emitBranchAndCleanups(JumpDest dest, SILLocation branchLoc,
builder.createBranch(branchLoc, dest.getBlock(), args);
}

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

/// Emit a new block that jumps to the specified location and runs necessary
Expand Down
2 changes: 1 addition & 1 deletion lib/SILGen/Cleanup.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager {

/// emitCleanupsForReturn - Emit the top-level cleanups needed prior to a
/// return from the function.
void emitCleanupsForReturn(CleanupLocation loc);
void emitCleanupsForReturn(CleanupLocation loc, ForUnwind_t forUnwind);

/// 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
Expand Down
30 changes: 16 additions & 14 deletions lib/SILGen/FormalEvaluation.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,23 +148,25 @@ class FormalEvaluationContext {
void dump(SILGenFunction &SGF);
};

/// A scope associated with the beginning of the formal evaluation of an lvalue.
/// A scope associated with the beginning of the evaluation of an lvalue.
///
/// A formal evaluation of an lvalue occurs when emitting:
/// The evaluation of an l-value is split into two stages: its formal
/// evaluation, which evaluates any independent r-values embedded in the l-value
/// expression (e.g. class references and subscript indices), and its formal
/// access duration, which delimits the span of time for which the referenced
/// storage is actually accessed.
///
/// 1. accessors.
/// 2. getters.
/// 3. materializeForSets.
/// Note that other evaluations can be interleaved between the formal evaluation
/// and the beginning of the formal access. For example, in a simple assignment
/// statement, the left-hand side of the assignment is first formally evaluated
/// as an l-value, then the right-hand side is evaluated as an r-value, and only
/// then does the write access begin to the l-value.
///
/// for lvalues. The general form of such an evaluation is:
///
/// formally evaluate the lvalue "x" into memory
/// begin formal access to "x"
/// end formal access to "x"
/// ... *more formal access*
/// begin formal access to "x"
/// end formal access to "x"
/// end formal evaluation of lvalue into memory
/// Note also that the formal evaluation of an l-value will sometimes require
/// its component l-values to be formally accessed. For example, the formal
/// access of the l-value `x?.prop` will initiate an access to `x` immediately
/// because the downstream evaluation must be skipped if `x` has no value, which
/// cannot be determined without beginning the access.
///
/// *NOTE* All formal access contain a pointer to a cleanup in the normal
/// cleanup stack. This is to ensure that when SILGen calls
Expand Down
Loading