Skip to content

Commit

Permalink
SIL type lowering: Compute IsTypeExpansionSensitive and use it instea…
Browse files Browse the repository at this point in the history
…d of TypeBase's hasOpaqueArchetypePropertiesOrCases

A type is IsTypeExpansionSensitive if it contains an opaque result type that influences how the type is lowered.

This could be because the type mentions an opaque archetype and
therefore we would look through to the underlying type depending on the
type expansion and could get a different SIL type. For example
'() -> out some P' could lower to '() -> @out Int'.

Or this could be because when we lower an aggregate type some of its
fields are opaque types that could be looked through and therefore the
aggregate has different lowering (e.g address vs. loadable) in different
type expansion contexts.

By replacing it this change also fixes an infinite recursion in
hasOpaqueArchetypePropertiesOrCases.

rdar://68798822
  • Loading branch information
aschwaighofer committed Sep 29, 2020
1 parent 0ff5f60 commit 8e8c57c
Show file tree
Hide file tree
Showing 5 changed files with 340 additions and 211 deletions.
3 changes: 0 additions & 3 deletions include/swift/AST/Types.h
Expand Up @@ -600,9 +600,6 @@ class alignas(1 << TypeAlignInBits) TypeBase {
bool hasOpaqueArchetype() const {
return getRecursiveProperties().hasOpaqueArchetype();
}
/// Determine whether the type has any stored properties or enum cases that
/// involve an opaque type.
bool hasOpaqueArchetypePropertiesOrCases();

/// Determine whether the type is an opened existential type.
///
Expand Down
75 changes: 47 additions & 28 deletions include/swift/SIL/TypeLowering.h
Expand Up @@ -147,16 +147,23 @@ enum IsResilient_t : bool {
IsResilient = true
};

/// Does this type contain an opaque result type that affects type lowering?
enum IsTypeExpansionSensitive_t : bool {
IsNotTypeExpansionSensitive = false,
IsTypeExpansionSensitive = true
};

/// Extended type information used by SIL.
class TypeLowering {
public:
class RecursiveProperties {
// These are chosen so that bitwise-or merges the flags properly.
enum : unsigned {
NonTrivialFlag = 1 << 0,
NonFixedABIFlag = 1 << 1,
AddressOnlyFlag = 1 << 2,
ResilientFlag = 1 << 3,
NonTrivialFlag = 1 << 0,
NonFixedABIFlag = 1 << 1,
AddressOnlyFlag = 1 << 2,
ResilientFlag = 1 << 3,
TypeExpansionSensitiveFlag = 1 << 4,
};

uint8_t Flags;
Expand All @@ -165,15 +172,17 @@ class TypeLowering {
/// a trivial, loadable, fixed-layout type.
constexpr RecursiveProperties() : Flags(0) {}

constexpr RecursiveProperties(IsTrivial_t isTrivial,
IsFixedABI_t isFixedABI,
IsAddressOnly_t isAddressOnly,
IsResilient_t isResilient)
: Flags((isTrivial ? 0U : NonTrivialFlag) |
(isFixedABI ? 0U : NonFixedABIFlag) |
(isAddressOnly ? AddressOnlyFlag : 0U) |
(isResilient ? ResilientFlag : 0U)) {}

constexpr RecursiveProperties(
IsTrivial_t isTrivial, IsFixedABI_t isFixedABI,
IsAddressOnly_t isAddressOnly, IsResilient_t isResilient,
IsTypeExpansionSensitive_t isTypeExpansionSensitive =
IsNotTypeExpansionSensitive)
: Flags((isTrivial ? 0U : NonTrivialFlag) |
(isFixedABI ? 0U : NonFixedABIFlag) |
(isAddressOnly ? AddressOnlyFlag : 0U) |
(isResilient ? ResilientFlag : 0U) |
(isTypeExpansionSensitive ? TypeExpansionSensitiveFlag : 0U)) {}

constexpr bool operator==(RecursiveProperties p) const {
return Flags == p.Flags;
}
Expand All @@ -183,7 +192,7 @@ class TypeLowering {
}

static constexpr RecursiveProperties forReference() {
return {IsNotTrivial, IsFixedABI, IsNotAddressOnly, IsNotResilient };
return {IsNotTrivial, IsFixedABI, IsNotAddressOnly, IsNotResilient};
}

static constexpr RecursiveProperties forOpaque() {
Expand All @@ -194,6 +203,7 @@ class TypeLowering {
return {IsTrivial, IsFixedABI, IsNotAddressOnly, IsResilient};
}


void addSubobject(RecursiveProperties other) {
Flags |= other.Flags;
}
Expand All @@ -210,10 +220,19 @@ class TypeLowering {
IsResilient_t isResilient() const {
return IsResilient_t((Flags & ResilientFlag) != 0);
}
IsTypeExpansionSensitive_t isTypeExpansionSensitive() const {
return IsTypeExpansionSensitive_t(
(Flags & TypeExpansionSensitiveFlag) != 0);
}

void setNonTrivial() { Flags |= NonTrivialFlag; }
void setNonFixedABI() { Flags |= NonFixedABIFlag; }
void setAddressOnly() { Flags |= AddressOnlyFlag; }
void setTypeExpansionSensitive(
IsTypeExpansionSensitive_t isTypeExpansionSensitive) {
Flags = (Flags & ~TypeExpansionSensitiveFlag) |
(isTypeExpansionSensitive ? TypeExpansionSensitiveFlag : 0);
}
};

private:
Expand Down Expand Up @@ -305,6 +324,12 @@ class TypeLowering {
return Properties.isResilient();
}

/// Does this type contain an opaque result type that could influence how the
/// type is lowered if we could look through to the underlying type.
bool isTypeExpansionSensitive() const {
return Properties.isTypeExpansionSensitive();
}

ResilienceExpansion getResilienceExpansion() const {
return expansionContext.getResilienceExpansion();
}
Expand Down Expand Up @@ -705,8 +730,6 @@ class TypeConverter {

llvm::DenseMap<SILDeclRef, CaptureInfo> LoweredCaptures;

llvm::DenseMap<CanType, bool> opaqueArchetypeFields;

/// Cache of loadable SILType to number of (estimated) fields
///
/// Second element is a ResilienceExpansion.
Expand All @@ -719,17 +742,15 @@ class TypeConverter {
Optional<CanType> BridgedType##Ty;
#include "swift/SIL/BridgedTypes.def"

const TypeLowering &
getTypeLoweringForLoweredType(AbstractionPattern origType,
CanType loweredType,
TypeExpansionContext forExpansion,
bool origHadOpaqueTypeArchetype);
const TypeLowering &getTypeLoweringForLoweredType(
AbstractionPattern origType, CanType loweredType,
TypeExpansionContext forExpansion,
IsTypeExpansionSensitive_t isTypeExpansionSensitive);

const TypeLowering *
getTypeLoweringForExpansion(TypeKey key,
TypeExpansionContext forExpansion,
const TypeLowering *lowering,
bool origHadOpaqueTypeArchetype);
const TypeLowering *getTypeLoweringForExpansion(
TypeKey key, TypeExpansionContext forExpansion,
const TypeLowering *minimalExpansionLowering,
IsTypeExpansionSensitive_t isOrigTypeExpansionSensitive);

public:
ModuleDecl &M;
Expand Down Expand Up @@ -885,8 +906,6 @@ class TypeConverter {

CanType getLoweredTypeOfGlobal(VarDecl *var);

bool hasOpaqueArchetypeOrPropertiesOrCases(CanType ty);

/// Return the SILFunctionType for a native function value of the
/// given type.
CanSILFunctionType getSILFunctionType(TypeExpansionContext context,
Expand Down
21 changes: 0 additions & 21 deletions lib/AST/Type.cpp
Expand Up @@ -5048,27 +5048,6 @@ Type TypeBase::openAnyExistentialType(OpenedArchetypeType *&opened) {
return opened;
}

bool TypeBase::hasOpaqueArchetypePropertiesOrCases() {
if (auto *structDecl = getStructOrBoundGenericStruct()) {
for (auto *field : structDecl->getStoredProperties()) {
auto fieldTy = field->getInterfaceType()->getCanonicalType();
if (fieldTy->hasOpaqueArchetype() ||
fieldTy->hasOpaqueArchetypePropertiesOrCases())
return true;
}
}

if (auto *enumDecl = getEnumOrBoundGenericEnum()) {
for (auto *elt : enumDecl->getAllElements()) {
auto eltType = elt->getInterfaceType();
if (eltType->hasOpaqueArchetype() ||
eltType->getCanonicalType()->hasOpaqueArchetypePropertiesOrCases())
return true;
}
}
return false;
}

CanType swift::substOpaqueTypesWithUnderlyingTypes(CanType ty,
TypeExpansionContext context,
bool allowLoweredTypes) {
Expand Down

0 comments on commit 8e8c57c

Please sign in to comment.