Skip to content

[WIP] SIL type lowering cleanups #5524

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

Closed
Closed
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: 4 additions & 3 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ namespace swift {
class ExtensionDecl;
class ForeignRepresentationInfo;
class FuncDecl;
class GenericEnvironment;
class InFlightDiagnostic;
class LazyResolver;
class PatternBindingDecl;
Expand Down Expand Up @@ -773,10 +774,10 @@ class ASTContext {
/// not necessarily loaded.
void getVisibleTopLevelClangModules(SmallVectorImpl<clang::Module*> &Modules) const;

/// Retrieve or create the stored archetype builder for the given
/// Retrieve or create the canonical GenericEnvironment for the given
/// canonical generic signature and module.
ArchetypeBuilder *getOrCreateArchetypeBuilder(CanGenericSignature sig,
ModuleDecl *mod);
GenericEnvironment *getCanonicalGenericEnvironment(CanGenericSignature sig,
ModuleDecl *mod);

/// Retrieve the inherited name set for the given class.
const InheritedNameSet *getAllPropertyNames(ClassDecl *classDecl,
Expand Down
27 changes: 7 additions & 20 deletions include/swift/AST/ArchetypeBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ class ProtocolConformance;
class ProtocolDecl;
class Requirement;
class RequirementRepr;
class SILModule;
class SourceLoc;
class Type;
class TypeRepr;
Expand Down Expand Up @@ -220,6 +219,13 @@ class ArchetypeBuilder {
ProtocolDecl *RootProtocol,
Identifier ParamName);

/// \brief Resolve the given dependent type using our context archetypes.
///
/// Given an arbitrary type, this will substitute dependent type parameters
/// structurally with their corresponding archetypes and resolve dependent
/// member types to the appropriate associated types.
Type substDependentType(Type type);

public:
/// \brief Add a new generic parameter for which there may be requirements.
void addGenericParameter(GenericTypeParamDecl *GenericParam);
Expand Down Expand Up @@ -306,13 +312,6 @@ class ArchetypeBuilder {
/// For any type that cannot refer to an archetype, this routine returns null.
PotentialArchetype *resolveArchetype(Type type);

/// \brief Resolve the given dependent type using our context archetypes.
///
/// Given an arbitrary type, this will substitute dependent type parameters
/// structurally with their corresponding archetypes and resolve dependent
/// member types to the appropriate associated types.
Type substDependentType(Type type);

/// Map an interface type to a contextual type.
static Type mapTypeIntoContext(const DeclContext *dc, Type type);

Expand All @@ -336,18 +335,6 @@ class ArchetypeBuilder {

/// Dump all of the requirements to the given output stream.
void dump(llvm::raw_ostream &out);

// In SILFunction.cpp:

/// \brief Resolve the given dependent type using our context archetypes.
///
/// Given an arbitrary type, this will substitute dependent type parameters
/// structurally with their corresponding archetypes and resolve dependent
/// member types to the appropriate associated types. It will reabstract
/// dependent types according to the abstraction level of their associated
/// type requirements.
SILType substDependentType(SILModule &M,
SILType type);
};

class ArchetypeBuilder::PotentialArchetype {
Expand Down
7 changes: 3 additions & 4 deletions include/swift/AST/GenericSignature.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
static ASTContext &getASTContext(ArrayRef<GenericTypeParamType *> params,
ArrayRef<Requirement> requirements);

/// Retrieve the archetype builder for the given generic signature.
ArchetypeBuilder *getArchetypeBuilder(ModuleDecl &mod);
/// Retrieve the canonical generic environment for this generic signature.
GenericEnvironment *getCanonicalGenericEnvironment(ModuleDecl &mod);

public:
/// Create a new generic signature with the given type parameters and
Expand Down Expand Up @@ -233,10 +233,9 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
/// Determine the superclass bound on the given dependent type.
Type getSuperclassBound(Type type, ModuleDecl &mod);

using ConformsToArray = SmallVector<ProtocolDecl *, 2>;
/// Determine the set of protocols to which the given dependent type
/// must conform.
ConformsToArray getConformsTo(Type type, ModuleDecl &mod);
ArrayRef<ProtocolDecl *> getConformsTo(Type type, ModuleDecl &mod);

/// Determine whether the given dependent type is equal to a concrete type.
bool isConcreteType(Type type, ModuleDecl &mod);
Expand Down
4 changes: 4 additions & 0 deletions include/swift/SIL/SILFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,10 @@ class SILFunction
/// therefore contain context archetypes, to an interface type.
Type mapTypeOutOfContext(Type type) const;

/// Map the given type, which is based on a contextual SILFunctionType and may
/// therefore contain context archetypes, to an interface type.
SILType mapTypeOutOfContext(SILType type) const;

/// Converts the given function definition to a declaration.
void convertToDeclaration();

Expand Down
7 changes: 5 additions & 2 deletions include/swift/SIL/SILType.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ class SILType {

/// Apply a substitution to the type to produce another lowered SIL type.
static SILType substType(SILModule &silModule, ModuleDecl *astModule,
const TypeSubstitutionMap &subs, SILType SrcTy);
const TypeSubstitutionMap &subs, SILType SrcTy,
CanGenericSignature genericSig=CanGenericSignature());

/// Apply a substitution to the function type.
static CanSILFunctionType substFuncType(SILModule &silModule,
Expand Down Expand Up @@ -448,7 +449,8 @@ class SILType {
ArrayRef<Substitution> Subs) const;

SILType subst(SILModule &silModule, ModuleDecl *astModule,
const TypeSubstitutionMap &subs) const;
const TypeSubstitutionMap &subs,
CanGenericSignature genericSig=CanGenericSignature()) const;

/// If this is a specialized generic type, return all substitutions used to
/// generate it.
Expand Down Expand Up @@ -548,6 +550,7 @@ NON_SIL_TYPE(LValue)
CanSILFunctionType getNativeSILFunctionType(SILModule &M,
Lowering::AbstractionPattern orig,
CanAnyFunctionType substInterface,
CanGenericSignature genericSig,
Optional<SILDeclRef> constant = None,
SILDeclRef::Kind kind = SILDeclRef::Kind::Func);

Expand Down
125 changes: 44 additions & 81 deletions include/swift/SIL/TypeLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,6 @@ inline CanSILFunctionType adjustFunctionType(CanSILFunctionType t,
}


/// Flag used to place context-dependent TypeLowerings in their own arena which
/// can be disposed when a generic context is exited.
enum IsDependent_t : unsigned {
IsNotDependent = false,
IsDependent = true
};

/// Extended type information used by SIL.
class TypeLowering {
public:
Expand Down Expand Up @@ -335,10 +328,8 @@ class TypeLowering {
}

/// Allocate a new TypeLowering using the TypeConverter's allocator.
void *operator new(size_t size, TypeConverter &tc,
IsDependent_t dependent);
void *operator new[](size_t size, TypeConverter &tc,
IsDependent_t dependent);
void *operator new(size_t size, TypeConverter &tc);
void *operator new[](size_t size, TypeConverter &tc);

// Forbid 'new FooTypeLowering' and try to forbid 'delete tl'.
// The latter is made challenging because the existence of the
Expand Down Expand Up @@ -399,9 +390,6 @@ class TypeConverter {
friend class TypeLowering;

llvm::BumpPtrAllocator IndependentBPA;
/// BumpPtrAllocator for types dependent on contextual generic parameters,
/// which is reset when the generic context is popped.
llvm::BumpPtrAllocator DependentBPA;

enum : unsigned {
/// There is a unique entry with this uncurry level in the
Expand All @@ -411,15 +399,17 @@ class TypeConverter {
};

struct CachingTypeKey {
GenericSignature *Sig;
GenericSignature *OrigSig;
AbstractionPattern::CachingKey OrigType;
GenericSignature *SubstSig;
CanType SubstType;
unsigned UncurryLevel;

friend bool operator==(const CachingTypeKey &lhs,
const CachingTypeKey &rhs) {
return lhs.Sig == rhs.Sig
return lhs.OrigSig == rhs.OrigSig
&& lhs.OrigType == rhs.OrigType
&& lhs.SubstSig == rhs.SubstSig
&& lhs.SubstType == rhs.SubstType
&& lhs.UncurryLevel == rhs.UncurryLevel;
}
Expand All @@ -433,6 +423,10 @@ class TypeConverter {
/// An unsubstituted version of a type, dictating its abstraction patterns.
AbstractionPattern OrigType;

/// The generic signature describing dependent types in the substituted
/// type.
CanGenericSignature SubstSig;

/// The substituted version of the type, dictating the types that
/// should be used in the lowered type.
CanType SubstType;
Expand All @@ -446,26 +440,23 @@ class TypeConverter {
? OrigType.getGenericSignature()
: nullptr),
OrigType.getCachingKey(),
SubstSig,
SubstType,
UncurryLevel };
}

bool isCacheable() const {
return OrigType.hasCachingKey();
}

IsDependent_t isDependent() const {
if (SubstType->hasTypeParameter())
return IsDependent;
return IsNotDependent;
}
};

friend struct llvm::DenseMapInfo<CachingTypeKey>;

TypeKey getTypeKey(AbstractionPattern origTy, CanType substTy,
TypeKey getTypeKey(AbstractionPattern origTy,
CanGenericSignature substSig,
CanType substTy,
unsigned uncurryLevel) {
return {origTy, substTy, uncurryLevel};
return {origTy, substSig, substTy, uncurryLevel};
}

struct OverrideKey {
Expand All @@ -491,12 +482,7 @@ class TypeConverter {
/// Insert a mapping into the cache.
void insert(TypeKey k, const TypeLowering *tl);

/// Mapping for types independent on contextual generic parameters, which is
/// cleared when the generic context is popped.
llvm::DenseMap<CachingTypeKey, const TypeLowering *> IndependentTypes;
/// Mapping for types dependent on contextual generic parameters, which is
/// cleared when the generic context is popped.
llvm::DenseMap<CachingTypeKey, const TypeLowering *> DependentTypes;

llvm::DenseMap<SILDeclRef, SILConstantInfo> ConstantTypes;

Expand Down Expand Up @@ -577,31 +563,42 @@ class TypeConverter {

/// Lowers a Swift type to a SILType, and returns the SIL TypeLowering
/// for that type.
const TypeLowering &getTypeLowering(Type t, unsigned uncurryLevel = 0) {
AbstractionPattern pattern(CurGenericContext, t->getCanonicalType());
return getTypeLowering(pattern, t, uncurryLevel);
const TypeLowering &getTypeLowering(Type t, unsigned uncurryLevel = 0,
CanGenericSignature genericSig
= CanGenericSignature()) {
if (!genericSig)
genericSig = CurGenericContext;
AbstractionPattern pattern(genericSig, t->getCanonicalType());
return getTypeLowering(pattern, t, uncurryLevel, genericSig);
}

/// Lowers a Swift type to a SILType according to the abstraction
/// patterns of the given original type.
const TypeLowering &getTypeLowering(AbstractionPattern origType,
Type substType,
unsigned uncurryLevel = 0);
unsigned uncurryLevel = 0,
CanGenericSignature genericSig
= CanGenericSignature());

/// Returns the SIL TypeLowering for an already lowered SILType. If the
/// SILType is an address, returns the TypeLowering for the pointed-to
/// type.
const TypeLowering &getTypeLowering(SILType t);

// Returns the lowered SIL type for a Swift type.
SILType getLoweredType(Type t, unsigned uncurryLevel = 0) {
return getTypeLowering(t, uncurryLevel).getLoweredType();
SILType getLoweredType(Type t, unsigned uncurryLevel = 0,
CanGenericSignature genericSig
= CanGenericSignature()) {
return getTypeLowering(t, uncurryLevel, genericSig).getLoweredType();
}

// Returns the lowered SIL type for a Swift type.
SILType getLoweredType(AbstractionPattern origType, Type substType,
unsigned uncurryLevel = 0) {
return getTypeLowering(origType, substType, uncurryLevel).getLoweredType();
unsigned uncurryLevel = 0,
CanGenericSignature genericSig
= CanGenericSignature()) {
return getTypeLowering(origType, substType, uncurryLevel, genericSig)
.getLoweredType();
}

SILType getLoweredLoadableType(Type t, unsigned uncurryLevel = 0) {
Expand Down Expand Up @@ -736,24 +733,6 @@ class TypeConverter {
CanGenericSignature getEffectiveGenericSignature(AnyFunctionRef fn,
CaptureInfo captureInfo);

/// Push a generic function context. See GenericContextScope for an RAII
/// interface to this function.
///
/// Types containing generic parameter references must be lowered in a generic
/// context. There can be at most one level of generic context active at any
/// point in time.
void pushGenericContext(CanGenericSignature sig);

/// Return the current generic context. This should only be used in
/// the type-conversion routines.
CanGenericSignature getCurGenericContext() const {
return CurGenericContext;
}

/// Pop a generic function context. See GenericContextScope for an RAII
/// interface to this function. There must be an active generic context.
void popGenericContext(CanGenericSignature sig);

/// Known types for bridging.
#define BRIDGING_KNOWN_TYPE(BridgedModule,BridgedType) \
CanType get##BridgedType##Type();
Expand Down Expand Up @@ -797,7 +776,8 @@ class TypeConverter {
CanAnyFunctionType origInterfaceType);
private:
CanType getLoweredRValueType(AbstractionPattern origType, CanType substType,
unsigned uncurryLevel);
unsigned uncurryLevel,
CanGenericSignature genericSig);

Type getLoweredCBridgedType(AbstractionPattern pattern, Type t,
bool canBridgeBool,
Expand Down Expand Up @@ -826,26 +806,6 @@ TypeLowering::getSemanticTypeLowering(TypeConverter &TC) const {
return *this;
}

/// RAII interface to push a generic context.
class GenericContextScope {
TypeConverter &TC;
CanGenericSignature Sig;
public:
GenericContextScope(TypeConverter &TC, CanGenericSignature sig)
: TC(TC), Sig(sig)
{
TC.pushGenericContext(sig);
}

~GenericContextScope() {
TC.popGenericContext(Sig);
}

private:
GenericContextScope(const GenericContextScope&) = delete;
GenericContextScope &operator=(const GenericContextScope&) = delete;
};

} // namespace Lowering
} // namespace swift

Expand All @@ -860,19 +820,22 @@ namespace llvm {

// Use the second field because the first field can validly be null.
static CachingTypeKey getEmptyKey() {
return {nullptr, APCachingKey(), CanTypeInfo::getEmptyKey(), 0};
return {nullptr, APCachingKey(), nullptr, CanTypeInfo::getEmptyKey(), 0};
}
static CachingTypeKey getTombstoneKey() {
return {nullptr, APCachingKey(), CanTypeInfo::getTombstoneKey(), 0};
return {nullptr, APCachingKey(), nullptr, CanTypeInfo::getTombstoneKey(), 0};
}
static unsigned getHashValue(CachingTypeKey val) {
auto hashSig =
DenseMapInfo<swift::GenericSignature *>::getHashValue(val.Sig);
auto hashOrigSig =
DenseMapInfo<swift::GenericSignature *>::getHashValue(val.OrigSig);
auto hashOrig =
CachingKeyInfo::getHashValue(val.OrigType);
auto hashSubst =
DenseMapInfo<swift::CanType>::getHashValue(val.SubstType);
return hash_combine(hashSig, hashOrig, hashSubst, val.UncurryLevel);
auto hashSubstSig =
DenseMapInfo<swift::GenericSignature *>::getHashValue(val.SubstSig);
return hash_combine(hashOrigSig, hashOrig, hashSubstSig, hashSubst,
val.UncurryLevel);
}
static bool isEqual(CachingTypeKey LHS, CachingTypeKey RHS) {
return LHS == RHS;
Expand Down
Loading