diff --git a/include/swift/AST/SubstitutionMap.h b/include/swift/AST/SubstitutionMap.h index 6d9ce0fb38ace..0ae98500eb524 100644 --- a/include/swift/AST/SubstitutionMap.h +++ b/include/swift/AST/SubstitutionMap.h @@ -20,6 +20,7 @@ #include "swift/AST/GenericSignature.h" #include "swift/AST/ProtocolConformanceRef.h" #include "swift/AST/Type.h" +#include "swift/AST/TypeExpansionContext.h" #include "swift/Basic/Debug.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMapInfo.h" @@ -176,7 +177,13 @@ class SubstitutionMap { SubstitutionMap subst(TypeSubstitutionFn subs, LookupConformanceFn conformances, SubstOptions options=None) const; - + + /// Apply type expansion lowering to all types in the substitution map. Opaque + /// archetypes will be lowered to their underlying types if the type expansion + /// context allows. + SubstitutionMap mapIntoTypeExpansionContext( + TypeExpansionContext context) const; + /// Create a substitution map for a protocol conformance. static SubstitutionMap getProtocolSubstitutions(ProtocolDecl *protocol, diff --git a/include/swift/AST/TypeExpansionContext.h b/include/swift/AST/TypeExpansionContext.h new file mode 100644 index 0000000000000..761fa53217bd5 --- /dev/null +++ b/include/swift/AST/TypeExpansionContext.h @@ -0,0 +1,145 @@ +//===--- TypeExpansionContext.h - Swift Type Expansion Context --*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This file defines the TypeExpansionContext class. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_TYPEEXPANSIONCONTEXT_H +#define SWIFT_TYPEEXPANSIONCONTEXT_H + +#include "swift/AST/ResilienceExpansion.h" +#include "llvm/ADT/DenseMap.h" + +namespace swift { + class DeclContext; + class SILFunction; + +/// Describes the context in which SIL types should eventually be expanded. +/// Required for lowering resilient types and deciding whether to look through +/// opaque result types to their underlying type. +class TypeExpansionContext { + ResilienceExpansion expansion; + // The context (module, function, ...) we are expanding the type in. + const DeclContext *inContext; + // Is the context in which we are expanding in the whole module. + bool isContextWholeModule; + + // The minimal expansion. + TypeExpansionContext() { + inContext = nullptr; + expansion = ResilienceExpansion::Minimal; + isContextWholeModule = false; + } + +public: + + // Infer the expansion for the SIL function. + TypeExpansionContext(const SILFunction &f); + + TypeExpansionContext(ResilienceExpansion expansion, + const DeclContext *inContext, bool isWholeModuleContext) + : expansion(expansion), inContext(inContext), + isContextWholeModule(isWholeModuleContext) {} + + ResilienceExpansion getResilienceExpansion() const { return expansion; } + + const DeclContext *getContext() const { return inContext; } + + bool isWholeModuleContext() const { return isContextWholeModule; } + + bool shouldLookThroughOpaqueTypeArchetypes() const { + return inContext != nullptr; + } + + bool isMinimal() const { return *this == TypeExpansionContext(); } + + static TypeExpansionContext minimal() { + return TypeExpansionContext(); + } + + static TypeExpansionContext maximal(const DeclContext *inContext, + bool isContextWholeModule) { + return TypeExpansionContext(ResilienceExpansion::Maximal, inContext, + isContextWholeModule); + } + + static TypeExpansionContext maximalResilienceExpansionOnly() { + return maximal(nullptr, false); + } + + static TypeExpansionContext + noOpaqueTypeArchetypesSubstitution(ResilienceExpansion expansion) { + return TypeExpansionContext(expansion, nullptr, false); + } + + bool operator==(const TypeExpansionContext &other) const { + assert(other.inContext != this->inContext || + other.isContextWholeModule == this->isContextWholeModule); + return other.inContext == this->inContext && + other.expansion == this->expansion; + } + + bool operator<(const TypeExpansionContext other) const { + assert(other.inContext != this->inContext || + other.isContextWholeModule == this->isContextWholeModule); + if (this->expansion == other.expansion) + return this->inContext < other.inContext; + return this->expansion < other.expansion; + } + + bool operator>(const TypeExpansionContext other) const { + assert(other.inContext != this->inContext || + other.isContextWholeModule == this->isContextWholeModule); + if (this->expansion == other.expansion) + return this->inContext > other.inContext; + return this->expansion > other.expansion; + } + + uintptr_t getHashKey() const { + uintptr_t key = (uintptr_t)inContext | (uintptr_t)expansion; + return key; + } +}; + +} // namespace swift + +namespace llvm { +template <> struct DenseMapInfo { + using TypeExpansionContext = swift::TypeExpansionContext; + + static TypeExpansionContext getEmptyKey() { + return TypeExpansionContext( + swift::ResilienceExpansion::Minimal, + reinterpret_cast( + DenseMapInfo::getEmptyKey()), + false); + } + static TypeExpansionContext getTombstoneKey() { + return TypeExpansionContext( + swift::ResilienceExpansion::Minimal, + reinterpret_cast( + DenseMapInfo::getTombstoneKey()), + false); + } + + static unsigned getHashValue(TypeExpansionContext val) { + return DenseMapInfo::getHashValue(val.getHashKey()); + } + + static bool isEqual(TypeExpansionContext LHS, TypeExpansionContext RHS) { + return LHS == RHS; + } +}; +} // namespace llvm + +#endif diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 89bb823f7633c..5984a303fc945 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -27,6 +27,7 @@ #include "swift/AST/SubstitutionMap.h" #include "swift/AST/Type.h" #include "swift/AST/TypeAlignments.h" +#include "swift/AST/TypeExpansionContext.h" #include "swift/Basic/ArrayRefView.h" #include "swift/Basic/Debug.h" #include "swift/Basic/InlineBitfield.h" @@ -582,7 +583,10 @@ 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. /// /// To determine whether there is an opened existential type @@ -3687,6 +3691,17 @@ enum class SILCoroutineKind : uint8_t { class SILFunctionConventions; + +CanType substOpaqueTypesWithUnderlyingTypes(CanType type, + TypeExpansionContext context, + bool allowLoweredTypes = false); +ProtocolConformanceRef +substOpaqueTypesWithUnderlyingTypes(ProtocolConformanceRef ref, Type origType, + TypeExpansionContext context); +namespace Lowering { + class TypeConverter; +}; + /// SILFunctionType - The lowered type of a function value, suitable /// for use by SIL. /// @@ -4205,10 +4220,14 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, SILFunction &context) const; CanSILFunctionType substGenericArgs(SILModule &silModule, - SubstitutionMap subs); + SubstitutionMap subs, + TypeExpansionContext context); CanSILFunctionType substGenericArgs(SILModule &silModule, TypeSubstitutionFn subs, - LookupConformanceFn conformances); + LookupConformanceFn conformances, + TypeExpansionContext context); + CanSILFunctionType substituteOpaqueArchetypes(Lowering::TypeConverter &TC, + TypeExpansionContext context); SILType substInterfaceType(SILModule &M, SILType interfaceType) const; @@ -4963,9 +4982,12 @@ class ReplaceOpaqueTypesWithUnderlyingTypes { public: const DeclContext *inContext; ResilienceExpansion contextExpansion; + bool isContextWholeModule; ReplaceOpaqueTypesWithUnderlyingTypes(const DeclContext *inContext, - ResilienceExpansion contextExpansion) - : inContext(inContext), contextExpansion(contextExpansion) {} + ResilienceExpansion contextExpansion, + bool isWholeModuleContext) + : inContext(inContext), contextExpansion(contextExpansion), + isContextWholeModule(isWholeModuleContext) {} /// TypeSubstitutionFn Type operator()(SubstitutableType *maybeOpaqueType) const; @@ -5752,5 +5774,5 @@ struct DenseMapInfo { }; } - + #endif diff --git a/include/swift/SIL/Projection.h b/include/swift/SIL/Projection.h index 1e4324e07b29f..1ccc0fad703bc 100644 --- a/include/swift/SIL/Projection.h +++ b/include/swift/SIL/Projection.h @@ -293,7 +293,8 @@ class Projection { /// /// WARNING: This is not a constant time operation because it is implemented /// in terms of getVarDecl, which requests all BaseType's stored properties. - SILType getType(SILType BaseType, SILModule &M) const; + SILType getType(SILType BaseType, SILModule &M, + TypeExpansionContext context) const; VarDecl *getVarDecl(SILType BaseType) const { assert(isValid()); @@ -402,6 +403,7 @@ class Projection { /// Given a specific SILType, return all first level projections if it is an /// aggregate. static void getFirstLevelProjections(SILType V, SILModule &Mod, + TypeExpansionContext context, llvm::SmallVectorImpl &Out); /// Is this cast which only allows for equality? @@ -584,6 +586,7 @@ class ProjectionPath { /// is a leaf node in the type tree. static void expandTypeIntoLeafProjectionPaths(SILType BaseType, SILModule *Mod, + TypeExpansionContext context, ProjectionPathList &P); /// Return true if the given projection paths in \p CPaths does not cover @@ -626,26 +629,27 @@ class ProjectionPath { SILType getBaseType() const { return BaseType; } /// Returns the most derived type of the projection path. - SILType getMostDerivedType(SILModule &M) { + SILType getMostDerivedType(SILModule &M, TypeExpansionContext context) { if (Path.empty()) return getBaseType(); if (MostDerivedType) return MostDerivedType; - MostDerivedType = getDerivedType(Path.size(), M); + MostDerivedType = getDerivedType(Path.size(), M, context); return MostDerivedType; } /// Returns the ith derived type of the path. This is zero indexed with 0 /// being the base type and n consisting of applying the up to n projections /// to the base type. - SILType getDerivedType(unsigned i, SILModule &M) const { + SILType getDerivedType(unsigned i, SILModule &M, + TypeExpansionContext context) const { assert(i <= Path.size()); SILType IterTy = getBaseType(); if (i == 0) return IterTy; for (unsigned j : range(i)) { auto &Proj = Path[j]; - IterTy = Proj.getType(IterTy, M); + IterTy = Proj.getType(IterTy, M, context); } return IterTy; } @@ -671,10 +675,11 @@ class ProjectionPath { const_reverse_iterator rbegin() const { return Path.rbegin(); } const_reverse_iterator rend() const { return Path.rend(); } - void verify(SILModule &M); + void verify(SILModule &M, TypeExpansionContext context); - raw_ostream &print(raw_ostream &OS, SILModule &M) const; - void dump(SILModule &M) const; + raw_ostream &print(raw_ostream &OS, SILModule &M, + TypeExpansionContext context) const; + void dump(SILModule &M, TypeExpansionContext context) const; }; /// Returns the hashcode for the new projection path. @@ -813,9 +818,11 @@ class ProjectionTreeNode { llvm::SmallVectorImpl &Worklist, SILValue Value); - void createNextLevelChildren(ProjectionTree &Tree); + void createNextLevelChildren(ProjectionTree &Tree, TypeExpansionContext context); - void createNextLevelChildrenForStruct(ProjectionTree &Tree, StructDecl *SD); + void createNextLevelChildrenForStruct(ProjectionTree &Tree, + TypeExpansionContext context, + StructDecl *SD); void createNextLevelChildrenForTuple(ProjectionTree &Tree, TupleType *TT); }; diff --git a/include/swift/SIL/SILBasicBlock.h b/include/swift/SIL/SILBasicBlock.h index db7f53cd6a5b9..8e2a37cc088ae 100644 --- a/include/swift/SIL/SILBasicBlock.h +++ b/include/swift/SIL/SILBasicBlock.h @@ -214,7 +214,8 @@ public llvm::ilist_node, public SILAllocated { /// Allocate a new argument of type \p Ty and append it to the argument /// list. Optionally you can pass in a value decl parameter. SILFunctionArgument *createFunctionArgument(SILType Ty, - const ValueDecl *D = nullptr); + const ValueDecl *D = nullptr, + bool disableEntryBlockVerification = false); SILFunctionArgument *insertFunctionArgument(unsigned Index, SILType Ty, ValueOwnershipKind OwnershipKind, diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h index aa3da71165d5c..6d818b060baf0 100644 --- a/include/swift/SIL/SILBuilder.h +++ b/include/swift/SIL/SILBuilder.h @@ -197,16 +197,23 @@ class SILBuilder { assert(F && "cannot create this instruction without a function context"); return *F; } + + TypeExpansionContext getTypeExpansionContext() const { + return TypeExpansionContext(getFunction()); + } + SILBuilderContext &getBuilderContext() const { return C; } SILModule &getModule() const { return C.Module; } ASTContext &getASTContext() const { return getModule().getASTContext(); } const Lowering::TypeLowering &getTypeLowering(SILType T) const { - auto expansion = ResilienceExpansion::Maximal; + + auto expansion = TypeExpansionContext::maximal(getModule().getSwiftModule(), + getModule().isWholeModule()); // If there's no current SILFunction, we're inserting into a global // variable initializer. - if (F) - expansion = F->getResilienceExpansion(); - + if (F) { + expansion = TypeExpansionContext(getFunction()); + } return getModule().Types.getTypeLowering(T, expansion); } @@ -336,12 +343,11 @@ class SILBuilder { // Type remapping //===--------------------------------------------------------------------===// - static SILType - getPartialApplyResultType(SILType Ty, unsigned ArgCount, SILModule &M, - SubstitutionMap subs, - ParameterConvention calleeConvention, - PartialApplyInst::OnStackKind onStack = - PartialApplyInst::OnStackKind::NotOnStack); + static SILType getPartialApplyResultType( + TypeExpansionContext context, SILType Ty, unsigned ArgCount, SILModule &M, + SubstitutionMap subs, ParameterConvention calleeConvention, + PartialApplyInst::OnStackKind onStack = + PartialApplyInst::OnStackKind::NotOnStack); //===--------------------------------------------------------------------===// // CFG Manipulation @@ -574,7 +580,8 @@ class SILBuilder { FunctionRefBaseInst *createFunctionRefFor(SILLocation Loc, SILFunction *f) { if (f->isDynamicallyReplaceable()) return createDynamicFunctionRef(Loc, f); - else return createFunctionRef(Loc, f); + else + return createFunctionRef(Loc, f); } FunctionRefBaseInst *createFunctionRef(SILLocation Loc, SILFunction *f, @@ -590,20 +597,20 @@ class SILBuilder { } FunctionRefInst *createFunctionRef(SILLocation Loc, SILFunction *f) { - return insert(new (getModule()) - FunctionRefInst(getSILDebugLocation(Loc), f)); + return insert(new (getModule()) FunctionRefInst(getSILDebugLocation(Loc), f, + getTypeExpansionContext())); } DynamicFunctionRefInst * createDynamicFunctionRef(SILLocation Loc, SILFunction *f) { return insert(new (getModule()) DynamicFunctionRefInst( - getSILDebugLocation(Loc), f)); + getSILDebugLocation(Loc), f, getTypeExpansionContext())); } PreviousDynamicFunctionRefInst * createPreviousDynamicFunctionRef(SILLocation Loc, SILFunction *f) { return insert(new (getModule()) PreviousDynamicFunctionRefInst( - getSILDebugLocation(Loc), f)); + getSILDebugLocation(Loc), f, getTypeExpansionContext())); } AllocGlobalInst *createAllocGlobal(SILLocation Loc, SILGlobalVariable *g) { @@ -611,16 +618,16 @@ class SILBuilder { AllocGlobalInst(getSILDebugLocation(Loc), g)); } GlobalAddrInst *createGlobalAddr(SILLocation Loc, SILGlobalVariable *g) { - return insert(new (getModule()) - GlobalAddrInst(getSILDebugLocation(Loc), g)); + return insert(new (getModule()) GlobalAddrInst(getSILDebugLocation(Loc), g, + getTypeExpansionContext())); } GlobalAddrInst *createGlobalAddr(SILLocation Loc, SILType Ty) { return insert(new (F->getModule()) GlobalAddrInst(getSILDebugLocation(Loc), Ty)); } GlobalValueInst *createGlobalValue(SILLocation Loc, SILGlobalVariable *g) { - return insert(new (getModule()) - GlobalValueInst(getSILDebugLocation(Loc), g)); + return insert(new (getModule()) GlobalValueInst(getSILDebugLocation(Loc), g, + getTypeExpansionContext())); } IntegerLiteralInst *createIntegerLiteral(IntegerLiteralExpr *E); @@ -1285,8 +1292,8 @@ class SILBuilder { UncheckedEnumDataInst *createUncheckedEnumData(SILLocation Loc, SILValue Operand, EnumElementDecl *Element) { - SILType EltType = - Operand->getType().getEnumElementType(Element, getModule()); + SILType EltType = Operand->getType().getEnumElementType( + Element, getModule(), getTypeExpansionContext()); return createUncheckedEnumData(Loc, Operand, Element, EltType); } @@ -1307,8 +1314,8 @@ class SILBuilder { UncheckedTakeEnumDataAddrInst * createUncheckedTakeEnumDataAddr(SILLocation Loc, SILValue Operand, EnumElementDecl *Element) { - SILType EltType = - Operand->getType().getEnumElementType(Element, getModule()); + SILType EltType = Operand->getType().getEnumElementType( + Element, getModule(), getTypeExpansionContext()); return createUncheckedTakeEnumDataAddr(Loc, Operand, Element, EltType); } @@ -1383,7 +1390,8 @@ class SILBuilder { StructExtractInst *createStructExtract(SILLocation Loc, SILValue Operand, VarDecl *Field) { - auto type = Operand->getType().getFieldType(Field, getModule()); + auto type = Operand->getType().getFieldType(Field, getModule(), + getTypeExpansionContext()); return createStructExtract(Loc, Operand, Field, type); } @@ -1397,7 +1405,8 @@ class SILBuilder { StructElementAddrInst * createStructElementAddr(SILLocation Loc, SILValue Operand, VarDecl *Field) { - auto ResultTy = Operand->getType().getFieldType(Field, getModule()); + auto ResultTy = Operand->getType().getFieldType(Field, getModule(), + getTypeExpansionContext()); return createStructElementAddr(Loc, Operand, Field, ResultTy); } @@ -1408,7 +1417,8 @@ class SILBuilder { } RefElementAddrInst *createRefElementAddr(SILLocation Loc, SILValue Operand, VarDecl *Field) { - auto ResultTy = Operand->getType().getFieldType(Field, getModule()); + auto ResultTy = Operand->getType().getFieldType(Field, getModule(), + getTypeExpansionContext()); return createRefElementAddr(Loc, Operand, Field, ResultTy); } @@ -2131,7 +2141,8 @@ class SILBuilder { SILValue emitStructExtract(SILLocation Loc, SILValue Operand, VarDecl *Field) { - auto type = Operand->getType().getFieldType(Field, getModule()); + auto type = Operand->getType().getFieldType(Field, getModule(), + getTypeExpansionContext()); return emitStructExtract(Loc, Operand, Field, type); } diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h index 91fc6f2dd0e4a..272557603d4cf 100644 --- a/include/swift/SIL/SILCloner.h +++ b/include/swift/SIL/SILCloner.h @@ -128,14 +128,15 @@ class SILCloner : protected SILInstructionVisitor { /// blocks. /// /// This is used to clone an entire function and should not mutate the - /// original function. + /// original function except if \p replaceOriginalFunctionInPlace is true. /// /// entryArgs must have a SILValue from the cloned function corresponding to /// each argument in the original function `F`. /// /// Cloned instructions are inserted starting at the end of clonedEntryBB. void cloneFunctionBody(SILFunction *F, SILBasicBlock *clonedEntryBB, - ArrayRef entryArgs); + ArrayRef entryArgs, + bool replaceOriginalFunctionInPlace = false); /// MARK: Callback utilities used from CRTP extensions during cloning. /// These should only be called from within an instruction cloning visitor. @@ -354,8 +355,14 @@ class SILCloner : protected SILInstructionVisitor { SILLocation remapLocation(SILLocation Loc) { return Loc; } const SILDebugScope *remapScope(const SILDebugScope *DS) { return DS; } - SILType remapType(SILType Ty) { return Ty; } - CanType remapASTType(CanType Ty) { return Ty; } + SILType remapType(SILType Ty) { + return Ty; + } + + CanType remapASTType(CanType Ty) { + return Ty; + } + ProtocolConformanceRef remapConformance(Type Ty, ProtocolConformanceRef C) { return C; } @@ -612,9 +619,11 @@ void SILCloner::cloneReachableBlocks( template void SILCloner::cloneFunctionBody(SILFunction *F, SILBasicBlock *clonedEntryBB, - ArrayRef entryArgs) { + ArrayRef entryArgs, + bool replaceOriginalFunctionInPlace) { - assert(F != clonedEntryBB->getParent() && "Must clone into a new function."); + assert((replaceOriginalFunctionInPlace || F != clonedEntryBB->getParent()) && + "Must clone into a new function."); assert(BBMap.empty() && "This API does not allow clients to map blocks."); assert(ValueMap.empty() && "Stale ValueMap."); @@ -972,9 +981,9 @@ SILCloner::visitFunctionRefInst(FunctionRefInst *Inst) { getOpLocation(Inst->getLoc()), OpFunction)); } -template -void -SILCloner::visitDynamicFunctionRefInst(DynamicFunctionRefInst *Inst) { +template +void SILCloner::visitDynamicFunctionRefInst( + DynamicFunctionRefInst *Inst) { SILFunction *OpFunction = getOpFunction(Inst->getInitiallyReferencedFunction()); getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); @@ -2049,8 +2058,11 @@ SILCloner::visitWitnessMethodInst(WitnessMethodInst *Inst) { CanType Ty = conformance.getConcrete()->getType()->getCanonicalType(); if (Ty != newLookupType) { - assert(Ty->isExactSuperclassOf(newLookupType) && - "Should only create upcasts for sub class."); + assert( + (Ty->isExactSuperclassOf(newLookupType) || + getBuilder().getModule().Types.getLoweredRValueType( + getBuilder().getTypeExpansionContext(), Ty) == newLookupType) && + "Should only create upcasts for sub class."); // We use the super class as the new look up type. newLookupType = Ty; diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h index 3e8f92d571983..58eeff9bb053f 100644 --- a/include/swift/SIL/SILFunction.h +++ b/include/swift/SIL/SILFunction.h @@ -342,6 +342,14 @@ class SILFunction CanSILFunctionType getLoweredFunctionType() const { return LoweredType; } + CanSILFunctionType + getLoweredFunctionTypeInContext(TypeExpansionContext context) const; + + SILType getLoweredTypeInContext(TypeExpansionContext context) const { + return SILType::getPrimitiveObjectType( + getLoweredFunctionTypeInContext(context)); + } + SILFunctionConventions getConventions() const { return SILFunctionConventions(LoweredType, getModule()); } @@ -491,6 +499,11 @@ class SILFunction : ResilienceExpansion::Maximal); } + // Returns the type expansion context to be used inside this function. + TypeExpansionContext getTypeExpansionContext() const { + return TypeExpansionContext(*this); + } + const Lowering::TypeLowering & getTypeLowering(Lowering::AbstractionPattern orig, Type subst); @@ -502,6 +515,8 @@ class SILFunction SILType getLoweredLoadableType(Type t) const; + SILType getLoweredType(SILType t) const; + const Lowering::TypeLowering &getTypeLowering(SILType type) const; bool isTypeABIAccessible(SILType type) const; diff --git a/include/swift/SIL/SILGlobalVariable.h b/include/swift/SIL/SILGlobalVariable.h index eedc850458e3a..c40ba2c5766a1 100644 --- a/include/swift/SIL/SILGlobalVariable.h +++ b/include/swift/SIL/SILGlobalVariable.h @@ -105,7 +105,12 @@ class SILGlobalVariable CanSILFunctionType getLoweredFunctionType() const { return LoweredType.castTo(); } - + SILType getLoweredTypeInContext(TypeExpansionContext context) const; + CanSILFunctionType + getLoweredFunctionTypeInContext(TypeExpansionContext context) const { + return getLoweredTypeInContext(context).castTo(); + } + StringRef getName() const { return Name; } void setDeclaration(bool isD) { IsDeclaration = isD; } diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h index 551eeae5a9928..3e64bce702fb4 100644 --- a/include/swift/SIL/SILInstruction.h +++ b/include/swift/SIL/SILInstruction.h @@ -2357,7 +2357,7 @@ class FunctionRefBaseInst : public LiteralInst { protected: FunctionRefBaseInst(SILInstructionKind Kind, SILDebugLocation DebugLoc, - SILFunction *F); + SILFunction *F, TypeExpansionContext context); public: ~FunctionRefBaseInst(); @@ -2416,7 +2416,9 @@ class FunctionRefInst : public FunctionRefBaseInst { /// /// \param DebugLoc The location of the reference. /// \param F The function being referenced. - FunctionRefInst(SILDebugLocation DebugLoc, SILFunction *F); + /// \param context The type expansion context of the function reference. + FunctionRefInst(SILDebugLocation DebugLoc, SILFunction *F, + TypeExpansionContext context); public: static bool classof(const SILNode *node) { @@ -2434,7 +2436,9 @@ class DynamicFunctionRefInst : public FunctionRefBaseInst { /// /// \param DebugLoc The location of the reference. /// \param F The function being referenced. - DynamicFunctionRefInst(SILDebugLocation DebugLoc, SILFunction *F); + /// \param context The type expansion context of the function reference. + DynamicFunctionRefInst(SILDebugLocation DebugLoc, SILFunction *F, + TypeExpansionContext context); public: static bool classof(const SILNode *node) { @@ -2452,7 +2456,9 @@ class PreviousDynamicFunctionRefInst : public FunctionRefBaseInst { /// /// \param DebugLoc The location of the reference. /// \param F The function being referenced. - PreviousDynamicFunctionRefInst(SILDebugLocation DebugLoc, SILFunction *F); + /// \param context The type expansion context of the function reference. + PreviousDynamicFunctionRefInst(SILDebugLocation DebugLoc, SILFunction *F, + TypeExpansionContext context); public: static bool classof(const SILNode *node) { @@ -3117,14 +3123,16 @@ class GlobalAddrInst GlobalAccessInst> { friend SILBuilder; - GlobalAddrInst(SILDebugLocation DebugLoc, SILGlobalVariable *Global); + GlobalAddrInst(SILDebugLocation DebugLoc, SILGlobalVariable *Global, + TypeExpansionContext context); + public: // FIXME: This constructor should be private but is currently used // in the SILParser. /// Create a placeholder instruction with an unset global reference. GlobalAddrInst(SILDebugLocation DebugLoc, SILType Ty) - : InstructionBase(DebugLoc, Ty, nullptr) { } + : InstructionBase(DebugLoc, Ty, nullptr) {} }; /// Gives the value of a global variable. @@ -3136,7 +3144,8 @@ class GlobalValueInst GlobalAccessInst> { friend SILBuilder; - GlobalValueInst(SILDebugLocation DebugLoc, SILGlobalVariable *Global); + GlobalValueInst(SILDebugLocation DebugLoc, SILGlobalVariable *Global, + TypeExpansionContext context); }; /// IntegerLiteralInst - Encapsulates an integer constant, as defined originally diff --git a/include/swift/SIL/SILModule.h b/include/swift/SIL/SILModule.h index 802bb85041b32..c251bf9f0b3bf 100644 --- a/include/swift/SIL/SILModule.h +++ b/include/swift/SIL/SILModule.h @@ -595,7 +595,7 @@ class SILModule { /// Can value operations (copies and destroys) on the given lowered type /// be performed in this module? bool isTypeABIAccessible(SILType type, - ResilienceExpansion forExpansion); + TypeExpansionContext forExpansion); /// Can type metadata for the given formal type be fetched in /// the given module? diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h index c933c0977e552..f291c86b5628a 100644 --- a/include/swift/SIL/SILType.h +++ b/include/swift/SIL/SILType.h @@ -244,7 +244,7 @@ class SILType { /// tc.getTypeLowering(type).isAddressOnly(). static bool isAddressOnly(CanType type, Lowering::TypeConverter &tc, CanGenericSignature sig, - ResilienceExpansion expansion); + TypeExpansionContext expansion); /// Return true if this type must be returned indirectly. /// @@ -253,7 +253,7 @@ class SILType { static bool isFormallyReturnedIndirectly(CanType type, Lowering::TypeConverter &tc, CanGenericSignature sig) { - return isAddressOnly(type, tc, sig, ResilienceExpansion::Minimal); + return isAddressOnly(type, tc, sig, TypeExpansionContext::minimal()); } /// Return true if this type must be passed indirectly. @@ -263,7 +263,7 @@ class SILType { static bool isFormallyPassedIndirectly(CanType type, Lowering::TypeConverter &tc, CanGenericSignature sig) { - return isAddressOnly(type, tc, sig, ResilienceExpansion::Minimal); + return isAddressOnly(type, tc, sig, TypeExpansionContext::minimal()); } /// True if the type, or the referenced type of an address type, is loadable. @@ -411,16 +411,20 @@ class SILType { /// the given field. Applies substitutions as necessary. The /// result will be an address type if the base type is an address /// type or a class. - SILType getFieldType(VarDecl *field, Lowering::TypeConverter &TC) const; + SILType getFieldType(VarDecl *field, Lowering::TypeConverter &TC, + TypeExpansionContext context) const; - SILType getFieldType(VarDecl *field, SILModule &M) const; + SILType getFieldType(VarDecl *field, SILModule &M, + TypeExpansionContext context) const; /// Given that this is an enum type, return the lowered type of the /// data for the given element. Applies substitutions as necessary. /// The result will have the same value category as the base type. - SILType getEnumElementType(EnumElementDecl *elt, Lowering::TypeConverter &TC) const; + SILType getEnumElementType(EnumElementDecl *elt, Lowering::TypeConverter &TC, + TypeExpansionContext context) const; - SILType getEnumElementType(EnumElementDecl *elt, SILModule &M) const; + SILType getEnumElementType(EnumElementDecl *elt, SILModule &M, + TypeExpansionContext context) const; /// Given that this is a tuple type, return the lowered type of the /// given tuple element. The result will have the same value @@ -458,11 +462,11 @@ class SILType { /// generic args with the appropriate item from the substitution. /// /// Only call this with function types! - SILType substGenericArgs(Lowering::TypeConverter &TC, - SubstitutionMap SubMap) const; + SILType substGenericArgs(Lowering::TypeConverter &TC, SubstitutionMap SubMap, + TypeExpansionContext context) const; - SILType substGenericArgs(SILModule &M, - SubstitutionMap SubMap) const; + SILType substGenericArgs(SILModule &M, SubstitutionMap SubMap, + TypeExpansionContext context) const; /// If the original type is generic, pass the signature as genericSig. /// @@ -487,8 +491,9 @@ class SILType { bool isHeapObjectReferenceType() const; /// Returns true if this SILType is an aggregate that contains \p Ty - bool aggregateContainsRecord(SILType Ty, SILModule &SILMod) const; - + bool aggregateContainsRecord(SILType Ty, SILModule &SILMod, + TypeExpansionContext context) const; + /// Returns true if this SILType is an aggregate with unreferenceable storage, /// meaning it cannot be fully destructured in SIL. bool aggregateHasUnreferenceableStorage() const; @@ -515,7 +520,8 @@ class SILType { /// Returns true if this SILType could be potentially a lowering of the given /// formal type. Meant for verification purposes/assertions. - bool isLoweringOf(SILModule &M, CanType formalType); + bool isLoweringOf(TypeExpansionContext context, SILModule &M, + CanType formalType); /// Returns the hash code for the SILType. llvm::hash_code getHashCode() const { @@ -589,8 +595,9 @@ NON_SIL_TYPE(LValue) #undef NON_SIL_TYPE CanSILFunctionType getNativeSILFunctionType( - Lowering::TypeConverter &TC, Lowering::AbstractionPattern origType, - CanAnyFunctionType substType, Optional origConstant = None, + Lowering::TypeConverter &TC, TypeExpansionContext context, + Lowering::AbstractionPattern origType, CanAnyFunctionType substType, + Optional origConstant = None, Optional constant = None, Optional reqtSubs = None, ProtocolConformanceRef witnessMethodConformance = ProtocolConformanceRef()); @@ -616,15 +623,15 @@ inline SILType SILField::getObjectType() const { return SILType::getPrimitiveObjectType(getLoweredType()); } -CanType getSILBoxFieldLoweredType(SILBoxType *type, - Lowering::TypeConverter &TC, +CanType getSILBoxFieldLoweredType(TypeExpansionContext context, + SILBoxType *type, Lowering::TypeConverter &TC, unsigned index); -inline SILType getSILBoxFieldType(SILBoxType *type, - Lowering::TypeConverter &TC, +inline SILType getSILBoxFieldType(TypeExpansionContext context, + SILBoxType *type, Lowering::TypeConverter &TC, unsigned index) { return SILType::getPrimitiveAddressType( - getSILBoxFieldLoweredType(type, TC, index)); + getSILBoxFieldLoweredType(context, type, TC, index)); } } // end swift namespace diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h index 1a856f8af390d..fa3d4adedf953 100644 --- a/include/swift/SIL/TypeLowering.h +++ b/include/swift/SIL/TypeLowering.h @@ -15,6 +15,7 @@ #include "swift/ABI/MetadataValues.h" #include "swift/AST/CaptureInfo.h" +#include "swift/AST/Module.h" #include "swift/SIL/AbstractionPattern.h" #include "swift/SIL/SILDeclRef.h" #include "swift/SIL/SILInstruction.h" @@ -227,11 +228,12 @@ class TypeLowering { SILType LoweredType; RecursiveProperties Properties; - unsigned ReferenceCounted : 1; /// The resilience expansion for this type lowering. /// If the type is not resilient at all, this is always Minimal. - unsigned ForExpansion : 1; + TypeExpansionContext expansionContext; + + unsigned ReferenceCounted : 1; /// A single linked list of lowerings for different resilience expansions. /// The first lowering is always for ResilientExpansion::Minimal. @@ -240,10 +242,9 @@ class TypeLowering { protected: TypeLowering(SILType type, RecursiveProperties properties, IsReferenceCounted_t isRefCounted, - ResilienceExpansion forExpansion) - : LoweredType(type), Properties(properties), - ReferenceCounted(isRefCounted), - ForExpansion(unsigned(forExpansion)) {} + TypeExpansionContext expansionContext) + : LoweredType(type), Properties(properties), + expansionContext(expansionContext), ReferenceCounted(isRefCounted) {} public: TypeLowering(const TypeLowering &) = delete; @@ -257,27 +258,6 @@ class TypeLowering { /// Dump out the internal state of this type lowering to llvm::dbgs(). SWIFT_DEBUG_DUMP; - /// Are r-values of this type passed as arguments indirectly by formal - /// convention? - /// - /// This is independent of whether the SIL argument is address type. - bool isFormallyPassedIndirectly() const { - assert(!isResilient() || - getResilienceExpansion() == ResilienceExpansion::Minimal && - "calling convention uses minimal resilience expansion"); - return isAddressOnly(); - } - - /// Are r-values of this type returned indirectly by formal convention? - /// - /// This is independent of whether the SIL result is address type. - bool isFormallyReturnedIndirectly() const { - assert(!isResilient() || - getResilienceExpansion() == ResilienceExpansion::Minimal && - "calling convention uses minimal resilience expansion"); - return isAddressOnly(); - } - RecursiveProperties getRecursiveProperties() const { return Properties; } @@ -331,7 +311,11 @@ class TypeLowering { } ResilienceExpansion getResilienceExpansion() const { - return ResilienceExpansion(ForExpansion); + return expansionContext.getResilienceExpansion(); + } + + TypeExpansionContext getExpansionContext() const { + return expansionContext; } /// Produce an exact copy of the value in the given address as a @@ -595,12 +579,13 @@ class TypeConverter { CanGenericSignature Sig; AbstractionPattern::CachingKey OrigType; CanType SubstType; + TypeExpansionContext expansionContext; friend bool operator==(const CachingTypeKey &lhs, const CachingTypeKey &rhs) { - return lhs.Sig == rhs.Sig - && lhs.OrigType == rhs.OrigType - && lhs.SubstType == rhs.SubstType; + return lhs.Sig == rhs.Sig && lhs.OrigType == rhs.OrigType && + lhs.SubstType == rhs.SubstType && + lhs.expansionContext == rhs.expansionContext; } friend bool operator!=(const CachingTypeKey &lhs, const CachingTypeKey &rhs) { @@ -616,13 +601,16 @@ class TypeConverter { /// should be used in the lowered type. CanType SubstType; + TypeExpansionContext expansionContext; + CachingTypeKey getCachingKey() const { assert(isCacheable()); return { (OrigType.hasGenericSignature() ? OrigType.getGenericSignature() : nullptr), OrigType.getCachingKey(), - SubstType }; + SubstType, + expansionContext }; } bool isCacheable() const { @@ -634,14 +622,18 @@ class TypeConverter { return IsDependent; return IsNotDependent; } + TypeKey getKeyForMinimalExpansion() const { + return {OrigType, SubstType, TypeExpansionContext::minimal()}; + } }; friend struct llvm::DenseMapInfo; - - TypeKey getTypeKey(AbstractionPattern origTy, CanType substTy) { - return {origTy, substTy}; + + TypeKey getTypeKey(AbstractionPattern origTy, CanType substTy, + TypeExpansionContext context) { + return {origTy, substTy, context}; } - + struct OverrideKey { SILDeclRef derived; SILDeclRef base; @@ -664,7 +656,11 @@ class TypeConverter { const TypeLowering *find(TypeKey k); /// Insert a mapping into the cache. void insert(TypeKey k, const TypeLowering *tl); - +#ifndef NDEBUG + /// Remove the nullptr entry from the type map. + void removeNullEntry(TypeKey k); +#endif + /// Mapping for types independent on contextual generic parameters. llvm::DenseMap IndependentTypes; @@ -685,12 +681,15 @@ class TypeConverter { llvm::SmallVector DependentTypes; - llvm::DenseMap ConstantTypes; - + llvm::DenseMap, SILConstantInfo *> + ConstantTypes; + llvm::DenseMap ConstantOverrideTypes; llvm::DenseMap LoweredCaptures; + llvm::DenseMap opaqueArchetypeFields; + /// Cache of loadable SILType to number of (estimated) fields /// /// Second element is a ResilienceExpansion. @@ -705,12 +704,14 @@ class TypeConverter { const TypeLowering & getTypeLoweringForLoweredType(TypeKey key, - ResilienceExpansion forExpansion); + TypeExpansionContext forExpansion, + bool origHadOpaqueTypeArchetype); const TypeLowering * getTypeLoweringForExpansion(TypeKey key, - ResilienceExpansion forExpansion, - const TypeLowering *lowering); + TypeExpansionContext forExpansion, + const TypeLowering *lowering, + bool origHadOpaqueTypeArchetype); public: ModuleDecl &M; @@ -723,7 +724,7 @@ class TypeConverter { /// Return the CaptureKind to use when capturing a decl. CaptureKind getDeclCaptureKind(CapturedValue capture, - ResilienceExpansion expansion); + TypeExpansionContext expansion); /// Return a most-general-possible abstraction pattern. AbstractionPattern getMostGeneralAbstraction() { @@ -748,7 +749,7 @@ class TypeConverter { static ProtocolDispatchStrategy getProtocolDispatchStrategy(ProtocolDecl *P); /// Count the total number of fields inside the given SIL Type - unsigned countNumberOfFields(SILType Ty, ResilienceExpansion expansion); + unsigned countNumberOfFields(SILType Ty, TypeExpansionContext expansion); /// True if a protocol uses witness tables for dynamic dispatch. static bool protocolRequiresWitnessTable(ProtocolDecl *P) { @@ -774,7 +775,7 @@ class TypeConverter { /// Lowers a Swift type to a SILType, and returns the SIL TypeLowering /// for that type. const TypeLowering & - getTypeLowering(Type t, ResilienceExpansion forExpansion) { + getTypeLowering(Type t, TypeExpansionContext forExpansion) { AbstractionPattern pattern(getCurGenericContext(), t->getCanonicalType()); return getTypeLowering(pattern, t, forExpansion); } @@ -783,28 +784,28 @@ class TypeConverter { /// patterns of the given original type. const TypeLowering &getTypeLowering(AbstractionPattern origType, Type substType, - ResilienceExpansion forExpansion); + TypeExpansionContext forExpansion); /// 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, ResilienceExpansion forExpansion); + getTypeLowering(SILType t, TypeExpansionContext forExpansion); // Returns the lowered SIL type for a Swift type. - SILType getLoweredType(Type t, ResilienceExpansion forExpansion) { + SILType getLoweredType(Type t, TypeExpansionContext forExpansion) { return getTypeLowering(t, forExpansion).getLoweredType(); } // Returns the lowered SIL type for a Swift type. SILType getLoweredType(AbstractionPattern origType, Type substType, - ResilienceExpansion forExpansion) { + TypeExpansionContext forExpansion) { return getTypeLowering(origType, substType, forExpansion) .getLoweredType(); } SILType getLoweredLoadableType(Type t, - ResilienceExpansion forExpansion, + TypeExpansionContext forExpansion, SILModule &M) { const TypeLowering &ti = getTypeLowering(t, forExpansion); assert( @@ -813,17 +814,13 @@ class TypeConverter { return ti.getLoweredType(); } - CanType getLoweredRValueType(Type t) { - // We're ignoring the category (object vs address), so the resilience - // expansion does not matter. - return getLoweredType(t, ResilienceExpansion::Minimal).getASTType(); + CanType getLoweredRValueType(TypeExpansionContext context, Type t) { + return getLoweredType(t, context).getASTType(); } - CanType getLoweredRValueType(AbstractionPattern origType, Type substType) { - // We're ignoring the category (object vs address), so the resilience - // expansion does not matter. - return getLoweredType(origType, substType, - ResilienceExpansion::Minimal).getASTType(); + CanType getLoweredRValueType(TypeExpansionContext context, + AbstractionPattern origType, Type substType) { + return getLoweredType(origType, substType, context).getASTType(); } AbstractionPattern getAbstractionPattern(AbstractStorageDecl *storage, @@ -836,14 +833,18 @@ class TypeConverter { CanType getLoweredTypeOfGlobal(VarDecl *var); + bool hasOpaqueArchetypeOrPropertiesOrCases(CanType ty); + /// Return the SILFunctionType for a native function value of the /// given type. - CanSILFunctionType getSILFunctionType(AbstractionPattern origType, + CanSILFunctionType getSILFunctionType(TypeExpansionContext context, + AbstractionPattern origType, CanFunctionType substFnType); /// Returns the formal type, lowered AST type, and SILFunctionType /// for a constant reference. - const SILConstantInfo &getConstantInfo(SILDeclRef constant); + const SILConstantInfo &getConstantInfo(TypeExpansionContext context, + SILDeclRef constant); /// Get the generic environment for a constant. GenericSignature getConstantGenericSignature(SILDeclRef constant); @@ -852,26 +853,29 @@ class TypeConverter { GenericEnvironment *getConstantGenericEnvironment(SILDeclRef constant); /// Returns the SIL type of a constant reference. - SILType getConstantType(SILDeclRef constant) { - return getConstantInfo(constant).getSILType(); + SILType getConstantType(TypeExpansionContext context, SILDeclRef constant) { + return getConstantInfo(context, constant).getSILType(); } /// Returns the SILFunctionType for the given declaration. - CanSILFunctionType getConstantFunctionType(SILDeclRef constant) { - return getConstantInfo(constant).SILFnType; + CanSILFunctionType getConstantFunctionType(TypeExpansionContext context, + SILDeclRef constant) { + return getConstantInfo(context, constant).SILFnType; } /// Returns the SILParameterInfo for the given declaration's `self` parameter. /// `constant` must refer to a method. - SILParameterInfo getConstantSelfParameter(SILDeclRef constant); + SILParameterInfo getConstantSelfParameter(TypeExpansionContext context, + SILDeclRef constant); /// Returns the SILFunctionType that must be used to perform a vtable dispatch /// to the given declaration. /// /// Will be the same as getConstantFunctionType() if the declaration does not /// override anything. - CanSILFunctionType getConstantOverrideType(SILDeclRef constant) { - return getConstantOverrideInfo(constant).SILFnType; + CanSILFunctionType getConstantOverrideType(TypeExpansionContext context, + SILDeclRef constant) { + return getConstantOverrideInfo(context, constant).SILFnType; } /// Returns the SILConstantInfo that must be used to perform a vtable dispatch @@ -879,17 +883,19 @@ class TypeConverter { /// /// Will be the same as getConstantInfo() if the declaration does not /// override anything. - const SILConstantInfo &getConstantOverrideInfo(SILDeclRef constant) { + const SILConstantInfo &getConstantOverrideInfo(TypeExpansionContext context, + SILDeclRef constant) { // Fast path if the constant does not override anything. auto next = constant.getNextOverriddenVTableEntry(); if (next.isNull()) - return getConstantInfo(constant); + return getConstantInfo(context, constant); auto base = constant.getOverriddenVTableEntry(); - return getConstantOverrideInfo(constant, base); + return getConstantOverrideInfo(context, constant, base); } - const SILConstantInfo &getConstantOverrideInfo(SILDeclRef constant, + const SILConstantInfo &getConstantOverrideInfo(TypeExpansionContext context, + SILDeclRef constant, SILDeclRef base); /// Get the empty tuple type as a SILType. @@ -939,7 +945,8 @@ class TypeConverter { /// type of the storage of the value. /// /// \return - always an address type - SILType getSubstitutedStorageType(AbstractStorageDecl *value, + SILType getSubstitutedStorageType(TypeExpansionContext context, + AbstractStorageDecl *value, Type lvalueType); /// Push a generic function context. See GenericContextScope for an RAII @@ -1022,9 +1029,10 @@ class TypeConverter { /// \p constant. The result is not cached as part of the constant's normal /// ConstantInfo. CanSILFunctionType - getUncachedSILFunctionTypeForConstant(SILDeclRef constant, - CanAnyFunctionType origInterfaceType); - + getUncachedSILFunctionTypeForConstant(TypeExpansionContext expansion, + SILDeclRef constant, + CanAnyFunctionType origInterfaceType); + /// Get the boxed interface type to use for a capture of the given decl. CanSILBoxType getInterfaceBoxTypeForCapture(ValueDecl *captured, @@ -1038,11 +1046,13 @@ class TypeConverter { GenericEnvironment *env, bool isMutable); - CanSILBoxType getBoxTypeForEnumElement(SILType enumType, + CanSILBoxType getBoxTypeForEnumElement(TypeExpansionContext context, + SILType enumType, EnumElementDecl *elt); private: - CanType computeLoweredRValueType(AbstractionPattern origType, + CanType computeLoweredRValueType(TypeExpansionContext context, + AbstractionPattern origType, CanType substType); Type getLoweredCBridgedType(AbstractionPattern pattern, Type t, @@ -1103,10 +1113,12 @@ namespace llvm { // Use the second field because the first field can validly be null. static CachingTypeKey getEmptyKey() { - return {nullptr, APCachingKey(), CanTypeInfo::getEmptyKey()}; + return {nullptr, APCachingKey(), CanTypeInfo::getEmptyKey(), + swift::TypeExpansionContext::minimal()}; } static CachingTypeKey getTombstoneKey() { - return {nullptr, APCachingKey(), CanTypeInfo::getTombstoneKey()}; + return {nullptr, APCachingKey(), CanTypeInfo::getTombstoneKey(), + swift::TypeExpansionContext::minimal()}; } static unsigned getHashValue(CachingTypeKey val) { auto hashSig = @@ -1115,7 +1127,10 @@ namespace llvm { CachingKeyInfo::getHashValue(val.OrigType); auto hashSubst = DenseMapInfo::getHashValue(val.SubstType); - return hash_combine(hashSig, hashOrig, hashSubst); + auto hashContext = + DenseMapInfo::getHashValue( + val.expansionContext); + return hash_combine(hashSig, hashOrig, hashSubst, hashContext); } static bool isEqual(CachingTypeKey LHS, CachingTypeKey RHS) { return LHS == RHS; diff --git a/include/swift/SIL/TypeSubstCloner.h b/include/swift/SIL/TypeSubstCloner.h index f450827afa47f..22b8dfb679256 100644 --- a/include/swift/SIL/TypeSubstCloner.h +++ b/include/swift/SIL/TypeSubstCloner.h @@ -90,7 +90,8 @@ class TypeSubstCloner : public SILClonerWithScopes { // Use the new set of substitutions to compute the new // substituted callee type. RecursiveSubstCalleeSILType = LoweredFnTy->substGenericArgs( - AI.getModule(), RecursiveSubs); + AI.getModule(), RecursiveSubs, + Builder.getTypeExpansionContext()); } // The specialized recursive function may have different calling @@ -109,7 +110,8 @@ class TypeSubstCloner : public SILClonerWithScopes { assert(Subs.empty() || SubstCalleeSILType == - Callee->getType().substGenericArgs(AI.getModule(), Subs)); + Callee->getType().substGenericArgs( + AI.getModule(), Subs, Builder.getTypeExpansionContext())); } ArrayRef getArguments() const { @@ -168,17 +170,40 @@ class TypeSubstCloner : public SILClonerWithScopes { SILType &Sty = TypeCache[Ty]; if (!Sty) { Sty = Ty.subst(Original.getModule(), SubsMap); + if (!Sty.getASTType()->hasOpaqueArchetype() || + !getBuilder() + .getTypeExpansionContext() + .shouldLookThroughOpaqueTypeArchetypes()) + return Sty; + // Remap types containing opaque result types in the current context. + Sty = getBuilder().getTypeLowering(Sty).getLoweredType().getCategoryType( + Sty.getCategory()); } return Sty; } CanType remapASTType(CanType ty) { - return ty.subst(SubsMap)->getCanonicalType(); + auto substTy = ty.subst(SubsMap)->getCanonicalType(); + if (!substTy->hasOpaqueArchetype() || + !getBuilder().getTypeExpansionContext() + .shouldLookThroughOpaqueTypeArchetypes()) + return substTy; + // Remap types containing opaque result types in the current context. + return getBuilder().getModule().Types.getLoweredRValueType( + TypeExpansionContext(getBuilder().getFunction()), substTy); } - ProtocolConformanceRef remapConformance(Type type, + ProtocolConformanceRef remapConformance(Type ty, ProtocolConformanceRef conf) { - return conf.subst(type, SubsMap); + auto conformance = conf.subst(ty, SubsMap); + auto substTy = ty.subst(SubsMap)->getCanonicalType(); + auto context = getBuilder().getTypeExpansionContext(); + if (substTy->hasOpaqueArchetype() && + context.shouldLookThroughOpaqueTypeArchetypes()) { + conformance = + substOpaqueTypesWithUnderlyingTypes(conformance, substTy, context); + } + return conformance; } SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) { diff --git a/include/swift/SILOptimizer/Analysis/AccessSummaryAnalysis.h b/include/swift/SILOptimizer/Analysis/AccessSummaryAnalysis.h index 1c19552cd5f5f..e71b6c58fea36 100644 --- a/include/swift/SILOptimizer/Analysis/AccessSummaryAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/AccessSummaryAnalysis.h @@ -62,7 +62,8 @@ class AccessSummaryAnalysis : public BottomUpIPAnalysis { /// Returns a description of the summary. For debugging and testing /// purposes. - std::string getDescription(SILType BaseType, SILModule &M) const; + std::string getDescription(SILType BaseType, SILModule &M, + TypeExpansionContext context) const; }; typedef llvm::SmallDenseMap @@ -85,7 +86,8 @@ class AccessSummaryAnalysis : public BottomUpIPAnalysis { /// Returns a description of the summary. For debugging and testing /// purposes. - std::string getDescription(SILType BaseType, SILModule &M) const; + std::string getDescription(SILType BaseType, SILModule &M, + TypeExpansionContext context) const; /// Returns the accesses that the function performs to subpaths of the /// argument. @@ -208,7 +210,8 @@ class AccessSummaryAnalysis : public BottomUpIPAnalysis { /// The base type must be the type of the root of the path. static std::string getSubPathDescription(SILType BaseType, const IndexTrieNode *SubPath, - SILModule &M); + SILModule &M, + TypeExpansionContext context); /// Performs a lexicographic comparison of two subpaths, first by path length /// and then by index of the last path component. Returns true when lhs diff --git a/include/swift/SILOptimizer/Analysis/TypeExpansionAnalysis.h b/include/swift/SILOptimizer/Analysis/TypeExpansionAnalysis.h index bc70dd7a31292..69c0b7718e1cc 100644 --- a/include/swift/SILOptimizer/Analysis/TypeExpansionAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/TypeExpansionAnalysis.h @@ -12,6 +12,7 @@ #ifndef SWIFT_SILOPTIMIZER_ANALYSIS_TYPEEXPANSIONANALYSIS_H #define SWIFT_SILOPTIMIZER_ANALYSIS_TYPEEXPANSIONANALYSIS_H +#include "swift/AST/TypeExpansionContext.h" #include "swift/SIL/Projection.h" #include "swift/SIL/SILType.h" #include "swift/SIL/SILValue.h" @@ -22,7 +23,9 @@ namespace swift { /// This analysis determines memory effects during destruction. class TypeExpansionAnalysis : public SILAnalysis { - llvm::DenseMap ExpansionCache; + llvm::DenseMap, ProjectionPathList> + ExpansionCache; + public: TypeExpansionAnalysis(SILModule *M) : SILAnalysis(SILAnalysisKind::TypeExpansion) {} @@ -32,7 +35,8 @@ class TypeExpansionAnalysis : public SILAnalysis { } /// Return ProjectionPath to every leaf or intermediate node of the given type. - const ProjectionPathList &getTypeExpansion(SILType B, SILModule *Mod); + const ProjectionPathList &getTypeExpansion(SILType B, SILModule *Mod, + TypeExpansionContext context); /// Invalidate all information in this analysis. virtual void invalidate() override { diff --git a/include/swift/SILOptimizer/PassManager/Passes.def b/include/swift/SILOptimizer/PassManager/Passes.def index 96f891f770501..bfcf1254014cb 100644 --- a/include/swift/SILOptimizer/PassManager/Passes.def +++ b/include/swift/SILOptimizer/PassManager/Passes.def @@ -230,8 +230,6 @@ PASS(NoReturnFolding, "noreturn-folding", "Prune Control Flow at No-Return Calls Using SIL unreachable") PASS(ObjectOutliner, "object-outliner", "Outlining of Global Objects") -PASS(OpaqueArchetypeSpecializer, "opaque-archetype-specializer", - "Opaque archetype specializer") PASS(Outliner, "outliner", "Function Outlining Optimization") PASS(OwnershipModelEliminator, "ownership-model-eliminator", diff --git a/include/swift/SILOptimizer/Utils/Generics.h b/include/swift/SILOptimizer/Utils/Generics.h index 50c80b51578d3..d4c3f3d325040 100644 --- a/include/swift/SILOptimizer/Utils/Generics.h +++ b/include/swift/SILOptimizer/Utils/Generics.h @@ -100,6 +100,11 @@ class ReabstractionInfo { // Reference to the original generic non-specialized callee function. SILFunction *Callee; + // The module the specialization is created in. + ModuleDecl *TargetModule = nullptr; + + bool isWholeModule = false; + // The apply site which invokes the generic function. ApplySite Apply; @@ -140,7 +145,9 @@ class ReabstractionInfo { /// substitutions \p ParamSubs. /// If specialization is not possible getSpecializedType() will return an /// invalid type. - ReabstractionInfo(ApplySite Apply, SILFunction *Callee, + ReabstractionInfo(ModuleDecl *targetModule, + bool isModuleWholeModule, + ApplySite Apply, SILFunction *Callee, SubstitutionMap ParamSubs, IsSerialized_t Serialized, bool ConvertIndirectToDirect = true, @@ -148,16 +155,17 @@ class ReabstractionInfo { /// Constructs the ReabstractionInfo for generic function \p Callee with /// a specialization signature. - ReabstractionInfo(SILFunction *Callee, GenericSignature SpecializedSig); + ReabstractionInfo(ModuleDecl *targetModule, bool isModuleWholeModule, + SILFunction *Callee, GenericSignature SpecializedSig); IsSerialized_t isSerialized() const { return Serialized; } - ResilienceExpansion getResilienceExpansion() const { - return (Serialized - ? ResilienceExpansion::Minimal - : ResilienceExpansion::Maximal); + TypeExpansionContext getResilienceExpansion() const { + auto resilience = (Serialized ? ResilienceExpansion::Minimal + : ResilienceExpansion::Maximal); + return TypeExpansionContext(resilience, TargetModule, isWholeModule); } /// Returns true if the \p ParamIdx'th (non-result) formal parameter is diff --git a/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h b/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h index f11fbcd3042af..5a25557693b06 100644 --- a/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h +++ b/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h @@ -169,12 +169,15 @@ class LSBase { } /// Print the LSBase. - virtual void print(llvm::raw_ostream &os, SILModule *Mod) { + virtual void print(llvm::raw_ostream &os, SILModule *Mod, + TypeExpansionContext context) { os << Base; - Path.getValue().print(os, *Mod); + Path.getValue().print(os, *Mod, context); } - virtual void dump(SILModule *Mod) { print(llvm::dbgs(), Mod); } + virtual void dump(SILModule *Mod, TypeExpansionContext context) { + print(llvm::dbgs(), Mod, context); + } }; static inline llvm::hash_code hash_value(const LSBase &S) { @@ -257,16 +260,18 @@ class LSValue : public LSBase { return Path.getValue().createExtract(Base, Inst, true); } - void print(llvm::raw_ostream &os, SILModule *Mod) { + void print(llvm::raw_ostream &os, SILModule *Mod, + TypeExpansionContext context) { if (CoveringValue) { os << "Covering Value"; return; } - LSBase::print(os, Mod); + LSBase::print(os, Mod, context); } /// Expand this SILValue to all individual fields it contains. - static void expand(SILValue Base, SILModule *Mod, LSValueList &Vals, + static void expand(SILValue Base, SILModule *Mod, + TypeExpansionContext context, LSValueList &Vals, TypeExpansionAnalysis *TE); /// Given a memory location and a map between the expansions of the location @@ -329,13 +334,14 @@ class LSLocation : public LSBase { } /// Returns the type of the object the LSLocation represents. - SILType getType(SILModule *M) { - return Path.getValue().getMostDerivedType(*M); + SILType getType(SILModule *M, TypeExpansionContext context) { + return Path.getValue().getMostDerivedType(*M, context); } /// Get the first level locations based on this location's first level /// projection. - void getNextLevelLSLocations(LSLocationList &Locs, SILModule *Mod); + void getNextLevelLSLocations(LSLocationList &Locs, SILModule *Mod, + TypeExpansionContext context); /// Check whether the 2 LSLocations may alias each other or not. bool isMayAliasLSLocation(const LSLocation &RHS, AliasAnalysis *AA); @@ -351,15 +357,18 @@ class LSLocation : public LSBase { /// In SIL, we can have a store to an aggregate and loads from its individual /// fields. Therefore, we expand all the operations on aggregates onto /// individual fields and process them separately. - static void expand(LSLocation Base, SILModule *Mod, LSLocationList &Locs, + static void expand(LSLocation Base, SILModule *Mod, + TypeExpansionContext context, LSLocationList &Locs, TypeExpansionAnalysis *TE); /// Given a set of locations derived from the same base, try to merge/reduce /// them into smallest number of LSLocations possible. - static void reduce(LSLocation Base, SILModule *Mod, LSLocationList &Locs); + static void reduce(LSLocation Base, SILModule *Mod, + TypeExpansionContext context, LSLocationList &Locs); /// Enumerate the given Mem LSLocation. - static void enumerateLSLocation(SILModule *M, SILValue Mem, + static void enumerateLSLocation(TypeExpansionContext context, SILModule *M, + SILValue Mem, std::vector &LSLocationVault, LSLocationIndexMap &LocToBit, LSLocationBaseMap &BaseToLoc, diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp index 3f74f9a42a6ba..38e17b36aed58 100644 --- a/lib/AST/SubstitutionMap.cpp +++ b/lib/AST/SubstitutionMap.cpp @@ -715,3 +715,11 @@ bool SubstitutionMap::isIdentity() const { return !hasNonIdentityReplacement; } + +SubstitutionMap SubstitutionMap::mapIntoTypeExpansionContext( + TypeExpansionContext context) const { + ReplaceOpaqueTypesWithUnderlyingTypes replacer( + context.getContext(), context.getResilienceExpansion(), + context.isWholeModuleContext()); + return this->subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes); +} diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index b29f96dfe9fff..fb2863e97d4fb 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -2670,8 +2670,10 @@ ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution( static Type substOpaqueTypesWithUnderlyingTypes(Type ty, const DeclContext *inContext, - ResilienceExpansion contextExpansion) { - ReplaceOpaqueTypesWithUnderlyingTypes replacer(inContext, contextExpansion); + ResilienceExpansion contextExpansion, + bool isWholeModuleContext) { + ReplaceOpaqueTypesWithUnderlyingTypes replacer(inContext, contextExpansion, + isWholeModuleContext); return ty.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes); } @@ -2682,7 +2684,8 @@ substOpaqueTypesWithUnderlyingTypes(Type ty, const DeclContext *inContext, /// will be accessible. It's not intended to enforce any rules about what /// opaque substitutions are or are not allowed. static bool canSubstituteTypeInto(Type ty, const DeclContext *dc, - OpaqueSubstitutionKind kind) { + OpaqueSubstitutionKind kind, + bool isContextWholeModule) { auto nominal = ty->getAnyNominal(); if (!nominal) return true; @@ -2695,6 +2698,10 @@ static bool canSubstituteTypeInto(Type ty, const DeclContext *dc, return true; case OpaqueSubstitutionKind::SubstituteSameModuleMaximalResilience: + // In whole module compilation private types are okay. + if (isContextWholeModule) + return true; + // In the same file any visibility is okay. if (!dc->isModuleContext() && nominal->getDeclContext()->getParentSourceFile() == @@ -2739,27 +2746,39 @@ operator()(SubstitutableType *maybeOpaqueType) const { // Check that we are allowed to substitute the underlying type into the // context. auto inContext = this->inContext; - if (substTy.findIf([inContext, substitutionKind](Type t) -> bool { - if (!canSubstituteTypeInto(t, inContext, substitutionKind)) - return true; - return false; - })) + auto isContextWholeModule = this->isContextWholeModule; + if (substTy.findIf( + [inContext, substitutionKind, isContextWholeModule](Type t) -> bool { + if (!canSubstituteTypeInto(t, inContext, substitutionKind, + isContextWholeModule)) + return true; + return false; + })) return maybeOpaqueType; // If the type still contains opaque types, recur. if (substTy->hasOpaqueArchetype()) { - return substOpaqueTypesWithUnderlyingTypes(substTy, inContext, - contextExpansion); + return ::substOpaqueTypesWithUnderlyingTypes( + substTy, inContext, contextExpansion, isContextWholeModule); } return substTy; } -static ProtocolConformanceRef -substOpaqueTypesWithUnderlyingTypes(ProtocolConformanceRef ref, Type origType, - const DeclContext *inContext, - ResilienceExpansion contextExpansion) { - ReplaceOpaqueTypesWithUnderlyingTypes replacer(inContext, contextExpansion); +static ProtocolConformanceRef substOpaqueTypesWithUnderlyingTypes( + ProtocolConformanceRef ref, Type origType, const DeclContext *inContext, + ResilienceExpansion contextExpansion, bool isWholeModuleContext) { + ReplaceOpaqueTypesWithUnderlyingTypes replacer(inContext, contextExpansion, + isWholeModuleContext); + return ref.subst(origType, replacer, replacer, + SubstFlags::SubstituteOpaqueArchetypes); +} + +ProtocolConformanceRef swift::substOpaqueTypesWithUnderlyingTypes( + ProtocolConformanceRef ref, Type origType, TypeExpansionContext context) { + ReplaceOpaqueTypesWithUnderlyingTypes replacer( + context.getContext(), context.getResilienceExpansion(), + context.isWholeModuleContext()); return ref.subst(origType, replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes); } @@ -2804,11 +2823,14 @@ operator()(CanType maybeOpaqueType, Type replacementType, // Check that we are allowed to substitute the underlying type into the // context. auto inContext = this->inContext; - if (substTy.findIf([inContext, substitutionKind](Type t) -> bool { - if (!canSubstituteTypeInto(t, inContext, substitutionKind)) - return true; - return false; - })) + auto isContextWholeModule = this->isContextWholeModule; + if (substTy.findIf( + [inContext, substitutionKind, isContextWholeModule](Type t) -> bool { + if (!canSubstituteTypeInto(t, inContext, substitutionKind, + isContextWholeModule)) + return true; + return false; + })) return abstractRef; auto substRef = @@ -2816,8 +2838,8 @@ operator()(CanType maybeOpaqueType, Type replacementType, // If the type still contains opaque types, recur. if (substTy->hasOpaqueArchetype()) { - return substOpaqueTypesWithUnderlyingTypes(substRef, substTy, inContext, - contextExpansion); + return ::substOpaqueTypesWithUnderlyingTypes( + substRef, substTy, inContext, contextExpansion, isContextWholeModule); } return substRef; } @@ -3436,6 +3458,11 @@ static Type substType(Type derivedType, // If we have a substitution for this type, use it. if (auto known = substitutions(substOrig)) { + if (options.contains(SubstFlags::SubstituteOpaqueArchetypes) && + isa(substOrig) && + known->getCanonicalType() == substOrig->getCanonicalType()) + return None; // Recursively process the substitutions of the opaque type + // archetype. return known; } @@ -4612,3 +4639,41 @@ Type TypeBase::openAnyExistentialType(OpenedArchetypeType *&opened) { opened = OpenedArchetypeType::get(this); 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) { + if (!context.shouldLookThroughOpaqueTypeArchetypes() || + !ty->hasOpaqueArchetype()) + return ty; + + ReplaceOpaqueTypesWithUnderlyingTypes replacer( + context.getContext(), context.getResilienceExpansion(), + context.isWholeModuleContext()); + SubstOptions flags = SubstFlags::SubstituteOpaqueArchetypes; + if (allowLoweredTypes) + flags = + SubstFlags::SubstituteOpaqueArchetypes | SubstFlags::AllowLoweredTypes; + return ty.subst(replacer, replacer, flags)->getCanonicalType(); +} diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index bd2b25656cb41..96665c5bd7db4 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -3347,10 +3347,43 @@ Explosion NativeConventionSchema::mapIntoNative(IRGenModule &IGM, return nativeExplosion; } -void IRGenFunction::emitScalarReturn(SILType resultType, Explosion &result, +Explosion IRGenFunction::coerceValueTo(SILType fromTy, Explosion &from, + SILType toTy) { + if (fromTy == toTy) + return std::move(from); + + auto &fromTI = cast(IGM.getTypeInfo(fromTy)); + auto &toTI = cast(IGM.getTypeInfo(toTy)); + + Explosion result; + if (fromTI.getStorageType()->isPointerTy() && + toTI.getStorageType()->isPointerTy()) { + auto ptr = from.claimNext(); + ptr = Builder.CreateBitCast(ptr, toTI.getStorageType()); + result.add(ptr); + return result; + } + + auto temporary = toTI.allocateStack(*this, toTy, "coerce.temp"); + + auto addr = + Address(Builder.CreateBitCast(temporary.getAddressPointer(), + fromTI.getStorageType()->getPointerTo()), + temporary.getAlignment()); + fromTI.initialize(*this, from, addr, false); + + toTI.loadAsTake(*this, temporary.getAddress(), result); + toTI.deallocateStack(*this, temporary, toTy); + return result; +} + +void IRGenFunction::emitScalarReturn(SILType returnResultType, + SILType funcResultType, Explosion &result, bool isSwiftCCReturn, bool isOutlined) { if (result.empty()) { - assert(IGM.getTypeInfo(resultType).nativeReturnValueSchema(IGM).empty() && + assert(IGM.getTypeInfo(returnResultType) + .nativeReturnValueSchema(IGM) + .empty() && "Empty explosion must match the native calling convention"); Builder.CreateRetVoid(); @@ -3359,12 +3392,13 @@ void IRGenFunction::emitScalarReturn(SILType resultType, Explosion &result, // In the native case no coercion is needed. if (isSwiftCCReturn) { + result = coerceValueTo(returnResultType, result, funcResultType); auto &nativeSchema = - IGM.getTypeInfo(resultType).nativeReturnValueSchema(IGM); + IGM.getTypeInfo(funcResultType).nativeReturnValueSchema(IGM); assert(!nativeSchema.requiresIndirect()); - Explosion native = - nativeSchema.mapIntoNative(IGM, *this, result, resultType, isOutlined); + Explosion native = nativeSchema.mapIntoNative(IGM, *this, result, + funcResultType, isOutlined); if (native.size() == 1) { Builder.CreateRet(native.claimNext()); return; @@ -3391,7 +3425,7 @@ void IRGenFunction::emitScalarReturn(SILType resultType, Explosion &result, return; } - auto &resultTI = IGM.getTypeInfo(resultType); + auto &resultTI = IGM.getTypeInfo(returnResultType); auto schema = resultTI.getSchema(); auto *bodyType = schema.getScalarResultType(IGM); diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp index e5a379f927d4a..f120032ca8901 100644 --- a/lib/IRGen/GenClass.cpp +++ b/lib/IRGen/GenClass.cpp @@ -297,7 +297,8 @@ namespace { SILType classType, bool superclass) { for (VarDecl *var : theClass->getStoredProperties()) { - SILType type = classType.getFieldType(var, IGM.getSILModule()); + SILType type = classType.getFieldType(var, IGM.getSILModule(), + TypeExpansionContext::minimal()); // Lower the field type. auto *eltType = &IGM.getTypeInfo(type); @@ -500,23 +501,20 @@ Address IRGenFunction::emitByteOffsetGEP(llvm::Value *base, } /// Emit a field l-value by applying the given offset to the given base. -static OwnedAddress emitAddressAtOffset(IRGenFunction &IGF, - SILType baseType, - llvm::Value *base, - llvm::Value *offset, +static OwnedAddress emitAddressAtOffset(IRGenFunction &IGF, SILType baseType, + llvm::Value *base, llvm::Value *offset, VarDecl *field) { - auto &fieldTI = - IGF.getTypeInfo(baseType.getFieldType(field, IGF.getSILModule())); + auto &fieldTI = IGF.getTypeInfo(baseType.getFieldType( + field, IGF.getSILModule(), IGF.IGM.getMaximalTypeExpansionContext())); auto addr = IGF.emitByteOffsetGEP(base, offset, fieldTI, base->getName() + "." + field->getName().str()); return OwnedAddress(addr, base); } -llvm::Constant * -irgen::tryEmitConstantClassFragilePhysicalMemberOffset(IRGenModule &IGM, - SILType baseType, - VarDecl *field) { - auto fieldType = baseType.getFieldType(field, IGM.getSILModule()); +llvm::Constant *irgen::tryEmitConstantClassFragilePhysicalMemberOffset( + IRGenModule &IGM, SILType baseType, VarDecl *field) { + auto fieldType = baseType.getFieldType(field, IGM.getSILModule(), + IGM.getMaximalTypeExpansionContext()); // If the field is empty, its address doesn't matter. auto &fieldTI = IGM.getTypeInfo(fieldType); if (fieldTI.isKnownEmpty(ResilienceExpansion::Maximal)) { @@ -2423,12 +2421,13 @@ FunctionPointer irgen::emitVirtualMethodValue(IRGenFunction &IGF, return FunctionPointer(fnPtr, signature); } -FunctionPointer irgen::emitVirtualMethodValue(IRGenFunction &IGF, - llvm::Value *base, - SILType baseType, - SILDeclRef method, - CanSILFunctionType methodType, - bool useSuperVTable) { +FunctionPointer +irgen::emitVirtualMethodValue(IRGenFunction &IGF, + llvm::Value *base, + SILType baseType, + SILDeclRef method, + CanSILFunctionType methodType, + bool useSuperVTable) { // Find the metadata. llvm::Value *metadata; if (useSuperVTable) { diff --git a/lib/IRGen/GenClass.h b/lib/IRGen/GenClass.h index b7fdf7f758d87..66018fbfb7b8d 100644 --- a/lib/IRGen/GenClass.h +++ b/lib/IRGen/GenClass.h @@ -50,12 +50,10 @@ namespace irgen { enum class ClassDeallocationKind : unsigned char; enum class FieldAccess : uint8_t; - - OwnedAddress projectPhysicalClassMemberAddress(IRGenFunction &IGF, - llvm::Value *base, - SILType baseType, - SILType fieldType, - VarDecl *field); + + OwnedAddress projectPhysicalClassMemberAddress( + IRGenFunction &IGF, llvm::Value *base, + SILType baseType, SILType fieldType, VarDecl *field); /// Return a strategy for accessing the given stored class property. /// @@ -180,11 +178,9 @@ namespace irgen { /// Emit the constant fragile offset of the given property inside an instance /// of the class. - llvm::Constant * - tryEmitConstantClassFragilePhysicalMemberOffset(IRGenModule &IGM, - SILType baseType, - VarDecl *field); - + llvm::Constant *tryEmitConstantClassFragilePhysicalMemberOffset( + IRGenModule &IGM, SILType baseType, VarDecl *field); + FieldAccess getClassFieldAccess(IRGenModule &IGM, SILType baseType, VarDecl *field); @@ -208,10 +204,8 @@ namespace irgen { /// Given an instance pointer (or, for a static method, a class /// pointer), emit the callee for the given method. - FunctionPointer emitVirtualMethodValue(IRGenFunction &IGF, - llvm::Value *base, - SILType baseType, - SILDeclRef method, + FunctionPointer emitVirtualMethodValue(IRGenFunction &IGF, llvm::Value *base, + SILType baseType, SILDeclRef method, CanSILFunctionType methodType, bool useSuperVTable); diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp index 674a22ab0c052..c6e07d16b6c57 100644 --- a/lib/IRGen/GenEnum.cpp +++ b/lib/IRGen/GenEnum.cpp @@ -315,9 +315,10 @@ namespace { SILType getSingletonType(IRGenModule &IGM, SILType T) const { assert(!ElementsWithPayload.empty()); - + return T.getEnumElementType(ElementsWithPayload[0].decl, - IGM.getSILModule()); + IGM.getSILModule(), + IGM.getMaximalTypeExpansionContext()); } public: @@ -614,8 +615,9 @@ namespace { assert(ElementsWithPayload.size() == 1 && "empty singleton enum should not be dynamic!"); - auto payloadTy = T.getEnumElementType(ElementsWithPayload[0].decl, - IGM.getSILModule()); + auto payloadTy = T.getEnumElementType( + ElementsWithPayload[0].decl, IGM.getSILModule(), + IGM.getMaximalTypeExpansionContext()); auto payloadLayout = emitTypeLayoutRef(IGF, payloadTy, collector); auto flags = emitEnumLayoutFlags(IGF.IGM, isVWTMutable); IGF.Builder.CreateCall( @@ -1567,7 +1569,8 @@ namespace { SILType getPayloadType(IRGenModule &IGM, SILType T) const { return T.getEnumElementType(ElementsWithPayload[0].decl, - IGM.getSILModule()); + IGM.getSILModule(), + IGM.getMaximalTypeExpansionContext()); } const TypeInfo &getPayloadTypeInfo() const { @@ -2957,8 +2960,9 @@ namespace { // Ask the runtime to do our layout using the payload metadata and number // of empty cases. - auto payloadTy = T.getEnumElementType(ElementsWithPayload[0].decl, - IGM.getSILModule()); + auto payloadTy = + T.getEnumElementType(ElementsWithPayload[0].decl, IGM.getSILModule(), + IGM.getMaximalTypeExpansionContext()); auto payloadLayout = emitTypeLayoutRef(IGF, payloadTy, collector); auto emptyCasesVal = llvm::ConstantInt::get(IGM.Int32Ty, ElementsWithNoPayload.size()); @@ -4575,8 +4579,9 @@ namespace { unsigned tagIndex = 0; for (auto &payloadCasePair : ElementsWithPayload) { - SILType PayloadT = T.getEnumElementType(payloadCasePair.decl, - IGF.getSILModule()); + SILType PayloadT = + T.getEnumElementType(payloadCasePair.decl, IGF.getSILModule(), + IGF.IGM.getMaximalTypeExpansionContext()); auto &payloadTI = *payloadCasePair.ti; // Trivial and, in the case of a take, bitwise-takable payloads, // can all share the default path. @@ -4692,9 +4697,9 @@ namespace { } for (auto &payloadCasePair : ElementsWithPayload) { - SILType payloadT = - T.getEnumElementType(payloadCasePair.decl, - collector.IGF.getSILModule()); + SILType payloadT = T.getEnumElementType( + payloadCasePair.decl, collector.IGF.getSILModule(), + collector.IGF.IGM.getMaximalTypeExpansionContext()); auto &payloadTI = *payloadCasePair.ti; payloadTI.collectMetadataForOutlining(collector, payloadT); } @@ -4737,8 +4742,9 @@ namespace { // Destroy the data. Address dataAddr = IGF.Builder.CreateBitCast( addr, elt.ti->getStorageType()->getPointerTo()); - SILType payloadT = - T.getEnumElementType(elt.decl, IGF.getSILModule()); + SILType payloadT = T.getEnumElementType( + elt.decl, IGF.getSILModule(), + IGF.IGM.getMaximalTypeExpansionContext()); elt.ti->destroy(IGF, dataAddr, payloadT, true /*isOutlined*/); }); return; @@ -4977,9 +4983,11 @@ namespace { Address eltAddr = IGF.Builder.CreateStructGEP(metadataBuffer, i, IGM.getPointerSize() * i); if (i == 0) firstAddr = eltAddr.getAddress(); - - auto payloadTy = T.getEnumElementType(elt.decl, IGF.getSILModule()); - + + auto payloadTy = + T.getEnumElementType(elt.decl, IGF.getSILModule(), + IGF.IGM.getMaximalTypeExpansionContext()); + auto metadata = emitTypeLayoutRef(IGF, payloadTy, collector); IGF.Builder.CreateStore(metadata, eltAddr); @@ -5809,7 +5817,8 @@ EnumImplStrategy::get(TypeConverter &TC, SILType type, EnumDecl *theEnum) { // *Now* apply the substitutions and get the type info for the instance's // payload type, since we know this case carries an apparent payload in // the generic case. - SILType fieldTy = type.getEnumElementType(elt, TC.IGM.getSILModule()); + SILType fieldTy = type.getEnumElementType( + elt, TC.IGM.getSILModule(), TC.IGM.getMaximalTypeExpansionContext()); auto *substArgTI = &TC.IGM.getTypeInfo(fieldTy); elementsWithPayload.push_back({elt, substArgTI, origArgTI}); diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index 1a411ef85c5f6..c2b9f730bddf0 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -1138,8 +1138,11 @@ static llvm::Function *emitPartialApplicationForwarder(IRGenModule &IGM, FunctionPointer fnPtr = [&]() -> FunctionPointer { // If we found a function pointer statically, great. if (staticFnPtr) { - assert(staticFnPtr->getPointer()->getType() == fnTy && - "static function type mismatch?!"); + if (staticFnPtr->getPointer()->getType() != fnTy) { + auto fnPtr = staticFnPtr->getPointer(); + fnPtr = subIGF.Builder.CreateBitCast(fnPtr, fnTy); + return FunctionPointer(fnPtr, origSig); + } return *staticFnPtr; } diff --git a/lib/IRGen/GenHeap.cpp b/lib/IRGen/GenHeap.cpp index d3dc107dd68e5..9bb4ecbd0ccbb 100644 --- a/lib/IRGen/GenHeap.cpp +++ b/lib/IRGen/GenHeap.cpp @@ -1528,8 +1528,8 @@ const TypeInfo *TypeConverter::convertBoxType(SILBoxType *T) { // TODO: Multi-field boxes assert(T->getLayout()->getFields().size() == 1 && "multi-field boxes not implemented yet"); - auto &eltTI = IGM.getTypeInfoForLowered( - getSILBoxFieldLoweredType(T, IGM.getSILModule().Types, 0)); + auto &eltTI = IGM.getTypeInfoForLowered(getSILBoxFieldLoweredType( + IGM.getMaximalTypeExpansionContext(), T, IGM.getSILModule().Types, 0)); if (!eltTI.isFixedSize()) { if (!NonFixedBoxTI) NonFixedBoxTI = new NonFixedBoxTypeInfo(IGM); @@ -1577,8 +1577,9 @@ const TypeInfo *TypeConverter::convertBoxType(SILBoxType *T) { // Produce a tailored box metadata for the type. assert(T->getLayout()->getFields().size() == 1 && "multi-field boxes not implemented yet"); - return new FixedBoxTypeInfo(IGM, - getSILBoxFieldType(T, IGM.getSILModule().Types, 0)); + return new FixedBoxTypeInfo( + IGM, getSILBoxFieldType(IGM.getMaximalTypeExpansionContext(), + T, IGM.getSILModule().Types, 0)); } OwnedAddress @@ -1588,9 +1589,12 @@ irgen::emitAllocateBox(IRGenFunction &IGF, CanSILBoxType boxType, auto &boxTI = IGF.getTypeInfoForLowered(boxType).as(); assert(boxType->getLayout()->getFields().size() == 1 && "multi-field boxes not implemented yet"); - return boxTI.allocate(IGF, - getSILBoxFieldType(boxType, IGF.IGM.getSILModule().Types, 0), - env, name); + return boxTI.allocate( + IGF, + getSILBoxFieldType( + IGF.IGM.getMaximalTypeExpansionContext(), + boxType, IGF.IGM.getSILModule().Types, 0), + env, name); } void irgen::emitDeallocateBox(IRGenFunction &IGF, @@ -1599,8 +1603,10 @@ void irgen::emitDeallocateBox(IRGenFunction &IGF, auto &boxTI = IGF.getTypeInfoForLowered(boxType).as(); assert(boxType->getLayout()->getFields().size() == 1 && "multi-field boxes not implemented yet"); - return boxTI.deallocate(IGF, box, - getSILBoxFieldType(boxType, IGF.IGM.getSILModule().Types, 0)); + return boxTI.deallocate( + IGF, box, + getSILBoxFieldType(IGF.IGM.getMaximalTypeExpansionContext(), boxType, + IGF.IGM.getSILModule().Types, 0)); } Address irgen::emitProjectBox(IRGenFunction &IGF, @@ -1609,8 +1615,10 @@ Address irgen::emitProjectBox(IRGenFunction &IGF, auto &boxTI = IGF.getTypeInfoForLowered(boxType).as(); assert(boxType->getLayout()->getFields().size() == 1 && "multi-field boxes not implemented yet"); - return boxTI.project(IGF, box, - getSILBoxFieldType(boxType, IGF.IGM.getSILModule().Types, 0)); + return boxTI.project( + IGF, box, + getSILBoxFieldType(IGF.IGM.getMaximalTypeExpansionContext(), boxType, + IGF.IGM.getSILModule().Types, 0)); } Address irgen::emitAllocateExistentialBoxInBuffer( diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp index 51b30b5c00c11..ca4a41ccb25d5 100644 --- a/lib/IRGen/GenKeyPath.cpp +++ b/lib/IRGen/GenKeyPath.cpp @@ -790,9 +790,8 @@ emitKeyPathComponent(IRGenModule &IGM, switch (getClassFieldAccess(IGM, loweredBaseContextTy, property)) { case FieldAccess::ConstantDirect: { // Known constant fixed offset. - auto offset = tryEmitConstantClassFragilePhysicalMemberOffset(IGM, - loweredClassTy, - property); + auto offset = tryEmitConstantClassFragilePhysicalMemberOffset( + IGM, loweredClassTy, property); assert(offset && "no constant offset for ConstantDirect field?!"); addFixedOffset(/*struct*/ false, property->isLet(), offset); break; diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 2f1e1578f6059..c446dbe77570e 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -1939,7 +1939,8 @@ static void emitInitializeFieldOffsetVector(IRGenFunction &IGF, unsigned index = 0; for (auto prop : storedProperties) { - auto propTy = T.getFieldType(prop, IGF.getSILModule()); + auto propTy = T.getFieldType(prop, IGF.getSILModule(), + TypeExpansionContext::minimal()); llvm::Value *metadata = emitTypeLayoutRef(IGF, propTy, collector); Address field = IGF.Builder.CreateConstArrayGEP(fields, index, IGM.getPointerSize()); @@ -3606,8 +3607,10 @@ namespace { B.add(offset); return; } - assert(IGM.getTypeInfo(Type.getFieldType(field, IGM.getSILModule())) - .isKnownEmpty(ResilienceExpansion::Maximal)); + assert(IGM.getTypeInfo( + Type.getFieldType(field, IGM.getSILModule(), + TypeExpansionContext::minimal())) + .isKnownEmpty(ResilienceExpansion::Maximal)); B.addInt32(0); } diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp index e4b3d5f288241..bb65387cfb82e 100644 --- a/lib/IRGen/GenObjC.cpp +++ b/lib/IRGen/GenObjC.cpp @@ -858,8 +858,8 @@ static llvm::Function *emitObjCPartialApplicationForwarder(IRGenModule &IGM, auto &callee = emission.getCallee(); auto resultType = callee.getOrigFunctionType()->getDirectFormalResultsType(IGM.getSILModule()); - subIGF.emitScalarReturn(resultType, result, true /*isSwiftCCReturn*/, - false); + subIGF.emitScalarReturn(resultType, resultType, result, + true /*isSwiftCCReturn*/, false); } return fwd; @@ -1018,8 +1018,9 @@ static SILDeclRef getObjCMethodRef(AbstractFunctionDecl *method) { } static CanSILFunctionType getObjCMethodType(IRGenModule &IGM, - AbstractFunctionDecl *method) { - return IGM.getSILTypes().getConstantFunctionType(getObjCMethodRef(method)); + AbstractFunctionDecl *method) { + return IGM.getSILTypes().getConstantFunctionType( + TypeExpansionContext::minimal(), getObjCMethodRef(method)); } static clang::CanQualType getObjCPropertyType(IRGenModule &IGM, diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index 278ef516daa69..e61ad1c1674e4 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -3185,10 +3185,9 @@ void irgen::expandTrailingWitnessSignature(IRGenModule &IGM, out.push_back(IGM.WitnessTablePtrTy); } -FunctionPointer -irgen::emitWitnessMethodValue(IRGenFunction &IGF, - llvm::Value *wtable, - SILDeclRef member) { +FunctionPointer irgen::emitWitnessMethodValue(IRGenFunction &IGF, + llvm::Value *wtable, + SILDeclRef member) { auto *fn = cast(member.getDecl()); auto proto = cast(fn->getDeclContext()); @@ -3201,7 +3200,8 @@ irgen::emitWitnessMethodValue(IRGenFunction &IGF, emitInvariantLoadOfOpaqueWitness(IGF, wtable, index.forProtocolWitnessTable()); - auto fnType = IGF.IGM.getSILTypes().getConstantFunctionType(member); + auto fnType = IGF.IGM.getSILTypes().getConstantFunctionType( + IGF.IGM.getMaximalTypeExpansionContext(), member); Signature signature = IGF.IGM.getSignature(fnType); witnessFnPtr = IGF.Builder.CreateBitCast(witnessFnPtr, signature.getType()->getPointerTo()); @@ -3209,12 +3209,9 @@ irgen::emitWitnessMethodValue(IRGenFunction &IGF, return FunctionPointer(witnessFnPtr, signature); } -FunctionPointer -irgen::emitWitnessMethodValue(IRGenFunction &IGF, - CanType baseTy, - llvm::Value **baseMetadataCache, - SILDeclRef member, - ProtocolConformanceRef conformance) { +FunctionPointer irgen::emitWitnessMethodValue( + IRGenFunction &IGF, CanType baseTy, llvm::Value **baseMetadataCache, + SILDeclRef member, ProtocolConformanceRef conformance) { llvm::Value *wtable = emitWitnessTableRef(IGF, baseTy, baseMetadataCache, conformance); diff --git a/lib/IRGen/GenProto.h b/lib/IRGen/GenProto.h index 7d602cc80b291..f91b802841c85 100644 --- a/lib/IRGen/GenProto.h +++ b/lib/IRGen/GenProto.h @@ -64,8 +64,7 @@ namespace irgen { /// Extract the method pointer from an archetype's witness table /// as a function value. - FunctionPointer emitWitnessMethodValue(IRGenFunction &IGF, - CanType baseTy, + FunctionPointer emitWitnessMethodValue(IRGenFunction &IGF, CanType baseTy, llvm::Value **baseMetadataCache, SILDeclRef member, ProtocolConformanceRef conformance); diff --git a/lib/IRGen/GenStruct.cpp b/lib/IRGen/GenStruct.cpp index bd273beda33aa..c6eceff88c938 100644 --- a/lib/IRGen/GenStruct.cpp +++ b/lib/IRGen/GenStruct.cpp @@ -74,7 +74,8 @@ namespace { } SILType getType(IRGenModule &IGM, SILType T) const { - return T.getFieldType(Field, IGM.getSILModule()); + return T.getFieldType(Field, IGM.getSILModule(), + IGM.getMaximalTypeExpansionContext()); } }; @@ -95,7 +96,8 @@ namespace { SILType getType(IRGenModule &IGM, SILType T) const { if (Field) - return T.getFieldType(Field, IGM.getSILModule()); + return T.getFieldType(Field, IGM.getSILModule(), + IGM.getMaximalTypeExpansionContext()); // The Swift-field-less cases use opaque storage, which is // guaranteed to ignore the type passed to it. @@ -592,7 +594,9 @@ namespace { SILType getType(VarDecl *field) { assert(field->getDeclContext() == TheStruct->getAnyNominal()); auto silType = SILType::getPrimitiveAddressType(TheStruct); - return silType.getFieldType(field, IGM.getSILModule()); + return silType.getFieldType( + field, IGM.getSILModule(), + IGM.getMaximalTypeExpansionContext()); } StructLayout performLayout(ArrayRef fieldTypes) { @@ -733,8 +737,9 @@ class ClangRecordLowering { // If we have a Swift import of this type, use our lowered information. if (swiftField) { - auto &fieldTI = cast( - IGM.getTypeInfo(SwiftType.getFieldType(swiftField, IGM.getSILModule()))); + auto &fieldTI = cast(IGM.getTypeInfo( + SwiftType.getFieldType(swiftField, IGM.getSILModule(), + IGM.getMaximalTypeExpansionContext()))); addField(swiftField, offset, fieldTI); return; } diff --git a/lib/IRGen/GenThunk.cpp b/lib/IRGen/GenThunk.cpp index cdc9ffa7c8e84..db4d67356ac81 100644 --- a/lib/IRGen/GenThunk.cpp +++ b/lib/IRGen/GenThunk.cpp @@ -46,7 +46,8 @@ IRGenModule::getAddrOfDispatchThunk(SILDeclRef declRef, return entry; } - auto fnType = getSILModule().Types.getConstantFunctionType(declRef); + auto fnType = getSILModule().Types.getConstantFunctionType( + getMaximalTypeExpansionContext(), declRef); Signature signature = getSignature(fnType); LinkInfo link = LinkInfo::get(*this, entity, forDefinition); @@ -54,8 +55,8 @@ IRGenModule::getAddrOfDispatchThunk(SILDeclRef declRef, return entry; } -static FunctionPointer lookupMethod(IRGenFunction &IGF, - SILDeclRef declRef) { +static FunctionPointer lookupMethod(IRGenFunction &IGF, SILDeclRef declRef) { + auto expansionContext = IGF.IGM.getMaximalTypeExpansionContext(); auto *decl = cast(declRef.getDecl()); // Protocol case. @@ -68,7 +69,8 @@ static FunctionPointer lookupMethod(IRGenFunction &IGF, } // Class case. - auto funcTy = IGF.IGM.getSILModule().Types.getConstantFunctionType(declRef); + auto funcTy = IGF.IGM.getSILModule().Types.getConstantFunctionType( + expansionContext, declRef); // Load the metadata, or use the 'self' value if we have a static method. llvm::Value *self; diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp index 4ba497af06556..6798b24bb23dc 100644 --- a/lib/IRGen/GenType.cpp +++ b/lib/IRGen/GenType.cpp @@ -1466,25 +1466,25 @@ const TypeInfo &IRGenFunction::getTypeInfo(SILType T) { /// Return the SIL-lowering of the given type. SILType IRGenModule::getLoweredType(AbstractionPattern orig, Type subst) const { - return getSILTypes().getLoweredType(orig, subst, - ResilienceExpansion::Maximal); + return getSILTypes().getLoweredType( + orig, subst, TypeExpansionContext::maximalResilienceExpansionOnly()); } /// Return the SIL-lowering of the given type. SILType IRGenModule::getLoweredType(Type subst) const { - return getSILTypes().getLoweredType(subst, - ResilienceExpansion::Maximal); + return getSILTypes().getLoweredType( + subst, TypeExpansionContext::maximalResilienceExpansionOnly()); } /// Return the SIL-lowering of the given type. const Lowering::TypeLowering &IRGenModule::getTypeLowering(SILType type) const { - return getSILTypes().getTypeLowering(type, - ResilienceExpansion::Maximal); + return getSILTypes().getTypeLowering( + type, TypeExpansionContext::maximalResilienceExpansionOnly()); } bool IRGenModule::isTypeABIAccessible(SILType type) const { - return getSILModule().isTypeABIAccessible(type, - ResilienceExpansion::Maximal); + return getSILModule().isTypeABIAccessible( + type, TypeExpansionContext::maximalResilienceExpansionOnly()); } /// Get a pointer to the storage type for the given type. Note that, @@ -2307,7 +2307,10 @@ SILType irgen::getSingletonAggregateFieldType(IRGenModule &IGM, SILType t, auto allFields = structDecl->getStoredProperties(); if (allFields.size() == 1) { - auto fieldTy = t.getFieldType(allFields[0], IGM.getSILModule()); + auto fieldTy = t.getFieldType( + allFields[0], IGM.getSILModule(), + TypeExpansionContext(expansion, IGM.getSwiftModule(), + IGM.getSILModule().isWholeModule())); if (!IGM.isTypeABIAccessible(fieldTy)) return SILType(); return fieldTy; @@ -2327,7 +2330,10 @@ SILType irgen::getSingletonAggregateFieldType(IRGenModule &IGM, SILType t, auto theCase = allCases.begin(); if (!allCases.empty() && std::next(theCase) == allCases.end() && (*theCase)->hasAssociatedValues()) { - auto enumEltTy = t.getEnumElementType(*theCase, IGM.getSILModule()); + auto enumEltTy = t.getEnumElementType( + *theCase, IGM.getSILModule(), + TypeExpansionContext(expansion, IGM.getSwiftModule(), + IGM.getSILModule().isWholeModule())); if (!IGM.isTypeABIAccessible(enumEltTy)) return SILType(); return enumEltTy; diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h index 3ef32d7c19674..0a1affaf92acb 100644 --- a/lib/IRGen/IRGenFunction.h +++ b/lib/IRGen/IRGenFunction.h @@ -92,8 +92,9 @@ class IRGenFunction { //--- Function prologue and epilogue ------------------------------------------- public: Explosion collectParameters(); - void emitScalarReturn(SILType resultTy, Explosion &scalars, - bool isSwiftCCReturn, bool isOutlined); + void emitScalarReturn(SILType returnResultType, SILType funcResultType, + Explosion &scalars, bool isSwiftCCReturn, + bool isOutlined); void emitScalarReturn(llvm::Type *resultTy, Explosion &scalars); void emitBBForReturn(); @@ -280,6 +281,7 @@ class IRGenFunction { const SILDebugScope *getDebugScope() const { return DbgScope; } llvm::Value *coerceValue(llvm::Value *value, llvm::Type *toTy, const llvm::DataLayout &); + Explosion coerceValueTo(SILType fromTy, Explosion &from, SILType toTy); /// Mark a load as invariant. void setInvariantLoad(llvm::LoadInst *load); diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index 80af85aff9456..90037d14bbbfc 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -1376,3 +1376,8 @@ const llvm::DataLayout &IRGenerator::getClangDataLayout() { ->getTargetInfo() .getDataLayout(); } + +TypeExpansionContext IRGenModule::getMaximalTypeExpansionContext() const { + return TypeExpansionContext::maximal(getSwiftModule(), + getSILModule().isWholeModule()); +} diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h index 17fd016ed8798..933b463e93dcb 100644 --- a/lib/IRGen/IRGenModule.h +++ b/lib/IRGen/IRGenModule.h @@ -837,6 +837,8 @@ class IRGenModule { ResilienceExpansion getResilienceExpansionForLayout(NominalTypeDecl *decl); ResilienceExpansion getResilienceExpansionForLayout(SILGlobalVariable *var); + TypeExpansionContext getMaximalTypeExpansionContext() const; + bool isResilientConformance(const NormalProtocolConformance *conformance); bool isResilientConformance(const RootProtocolConformance *root); bool isDependentConformance(const RootProtocolConformance *conformance); diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index 119a0d9202cf0..2fa991e2e02e8 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -622,6 +622,16 @@ class IRGenSILFunction : return foundBB->second; } + TypeExpansionContext getExpansionContext() { + return TypeExpansionContext(*CurSILFn); + } + + SILType getLoweredTypeInContext(SILType ty) { + return CurSILFn->getModule() + .Types.getLoweredType(ty.getASTType(), getExpansionContext()) + .getCategoryType(ty.getCategory()); + } + StringRef getOrCreateAnonymousVarName(VarDecl *Decl) { llvm::SmallString<4> &Name = AnonymousVariables[Decl]; if (Name.empty()) { @@ -1343,41 +1353,72 @@ static ArrayRef emitEntryPointIndirectReturn( SILType directResultType = IGF.CurSILFn->mapTypeIntoContext(fnConv.getSILResultType()); if (requiresIndirectResult(directResultType)) { - auto &retTI = IGF.IGM.getTypeInfo(directResultType); - IGF.IndirectReturn = retTI.getAddressForPointer(params.claimNext()); + auto ¶mTI = IGF.IGM.getTypeInfo(directResultType); + auto &retTI = + IGF.IGM.getTypeInfo(IGF.getLoweredTypeInContext(directResultType)); + auto ptr = params.claimNext(); + if (paramTI.getStorageType() != retTI.getStorageType()) { + assert(directResultType.getASTType()->hasOpaqueArchetype()); + ptr = IGF.Builder.CreateBitCast(ptr, + retTI.getStorageType()->getPointerTo()); + } + IGF.IndirectReturn = retTI.getAddressForPointer(ptr); } auto bbargs = entry->getArguments(); // Map the indirect returns if present. unsigned numIndirectResults = fnConv.getNumIndirectSILResults(); - for (unsigned i = 0; i != numIndirectResults; ++i) { - SILArgument *ret = bbargs[i]; - auto &retTI = IGF.IGM.getTypeInfo(ret->getType()); - IGF.setLoweredAddress(ret, retTI.getAddressForPointer(params.claimNext())); - } + unsigned idx = 0; + for (auto indirectResultType : fnConv.getIndirectSILResultTypes()) { + SILArgument *ret = bbargs[idx]; + auto inContextResultType = + IGF.CurSILFn->mapTypeIntoContext(indirectResultType); + auto &retTI = IGF.IGM.getTypeInfo(ret->getType()); + // The parameter's type might be different due to looking through opaque + // archetypes. + auto ptr = params.claimNext(); + auto ¶mTI = IGF.IGM.getTypeInfo(inContextResultType); + if (paramTI.getStorageType() != retTI.getStorageType()) { + assert(inContextResultType.getASTType()->hasOpaqueArchetype()); + ptr = IGF.Builder.CreateBitCast(ptr, + retTI.getStorageType()->getPointerTo()); + } + auto addr = retTI.getAddressForPointer(ptr); + IGF.setLoweredAddress(ret, addr); + ++idx; + } + assert(numIndirectResults == idx); return bbargs.slice(numIndirectResults); } static void bindParameter(IRGenSILFunction &IGF, SILArgument *param, + SILType paramTy, Explosion &allParamValues) { // Pull out the parameter value and its formal type. - auto ¶mTI = IGF.getTypeInfo(param->getType()); + auto ¶mTI = IGF.getTypeInfo(IGF.CurSILFn->mapTypeIntoContext(paramTy)); + auto &argTI = IGF.getTypeInfo(param->getType()); // If the SIL parameter isn't passed indirectly, we need to map it // to an explosion. if (param->getType().isObject()) { Explosion paramValues; - auto &loadableTI = cast(paramTI); + auto &loadableParamTI = cast(paramTI); + auto &loadableArgTI = cast(paramTI); // If the explosion must be passed indirectly, load the value from the // indirect address. - auto &nativeSchema = paramTI.nativeParameterValueSchema(IGF.IGM); + auto &nativeSchema = argTI.nativeParameterValueSchema(IGF.IGM); if (nativeSchema.requiresIndirect()) { - Address paramAddr - = loadableTI.getAddressForPointer(allParamValues.claimNext()); - loadableTI.loadAsTake(IGF, paramAddr, paramValues); + Address paramAddr = + loadableParamTI.getAddressForPointer(allParamValues.claimNext()); + if (paramTI.getStorageType() != argTI.getStorageType()) + paramAddr = + loadableArgTI.getAddressForPointer(IGF.Builder.CreateBitCast( + paramAddr.getAddress(), + loadableArgTI.getStorageType()->getPointerTo())); + loadableArgTI.loadAsTake(IGF, paramAddr, paramValues); } else { if (!nativeSchema.empty()) { // Otherwise, we map from the native convention to the type's explosion @@ -1399,8 +1440,12 @@ static void bindParameter(IRGenSILFunction &IGF, // FIXME: that doesn't mean we should physically pass it // indirectly at this resilience expansion. An @in or @in_guaranteed parameter // could be passed by value in the right resilience domain. - Address paramAddr - = paramTI.getAddressForPointer(allParamValues.claimNext()); + auto ptr = allParamValues.claimNext(); + if (paramTI.getStorageType() != argTI.getStorageType()) { + ptr = + IGF.Builder.CreateBitCast(ptr, argTI.getStorageType()->getPointerTo()); + } + Address paramAddr = argTI.getAddressForPointer(ptr); IGF.setLoweredAddress(param, paramAddr); } @@ -1430,7 +1475,6 @@ static void emitEntryPointArgumentsNativeCC(IRGenSILFunction &IGF, if (funcTy->hasErrorResult()) { IGF.setErrorResultSlot(allParamValues.takeLast()); } - // The coroutine context should be the first parameter. switch (funcTy->getCoroutineKind()) { case SILCoroutineKind::None: @@ -1443,6 +1487,8 @@ static void emitEntryPointArgumentsNativeCC(IRGenSILFunction &IGF, break; } + SILFunctionConventions conv(funcTy, IGF.getSILModule()); + // The 'self' argument might be in the context position, which is // now the end of the parameter list. Bind it now. if (hasSelfContextParameter(funcTy)) { @@ -1451,10 +1497,12 @@ static void emitEntryPointArgumentsNativeCC(IRGenSILFunction &IGF, Explosion selfTemp; selfTemp.add(allParamValues.takeLast()); - bindParameter(IGF, selfParam, selfTemp); + bindParameter(IGF, selfParam, + conv.getSILArgumentType(conv.getNumSILArguments() - 1), + selfTemp); - // Even if we don't have a 'self', if we have an error result, we - // should have a placeholder argument here. + // Even if we don't have a 'self', if we have an error result, we + // should have a placeholder argument here. } else if (funcTy->hasErrorResult() || funcTy->getRepresentation() == SILFunctionTypeRepresentation::Thick) { @@ -1463,8 +1511,11 @@ static void emitEntryPointArgumentsNativeCC(IRGenSILFunction &IGF, } // Map the remaining SIL parameters to LLVM parameters. + unsigned i = 0; for (SILArgument *param : params) { - bindParameter(IGF, param, allParamValues); + auto argIdx = conv.getSILArgIndexOfFirstParam() + i; + bindParameter(IGF, param, conv.getSILArgumentType(argIdx), allParamValues); + ++i; } // Bind polymorphic arguments. This can only be done after binding @@ -1917,7 +1968,7 @@ void IRGenSILFunction::visitAllocGlobalInst(AllocGlobalInst *i) { void IRGenSILFunction::visitGlobalAddrInst(GlobalAddrInst *i) { SILGlobalVariable *var = i->getReferencedGlobal(); - SILType loweredTy = var->getLoweredType(); + SILType loweredTy = var->getLoweredTypeInContext(getExpansionContext()); assert(loweredTy == i->getType().getObjectType()); auto &ti = getTypeInfo(loweredTy); @@ -2643,7 +2694,12 @@ static void emitReturnInst(IRGenSILFunction &IGF, auto swiftCCReturn = funcLang == SILFunctionLanguage::Swift; assert(swiftCCReturn || funcLang == SILFunctionLanguage::C && "Need to handle all cases"); - IGF.emitScalarReturn(resultTy, result, swiftCCReturn, false); + SILFunctionConventions conv(IGF.CurSILFn->getLoweredFunctionType(), + IGF.getSILModule()); + auto funcResultType = + IGF.CurSILFn->mapTypeIntoContext(conv.getSILResultType()); + IGF.emitScalarReturn(resultTy, funcResultType, result, swiftCCReturn, + false); } } @@ -3567,12 +3623,9 @@ void IRGenSILFunction::visitRefElementAddrInst(swift::RefElementAddrInst *i) { llvm::Value *value = base.claimNext(); SILType baseTy = i->getOperand()->getType(); - Address field = projectPhysicalClassMemberAddress(*this, - value, - baseTy, - i->getType(), - i->getField()) - .getAddress(); + Address field = projectPhysicalClassMemberAddress(*this, value, baseTy, + i->getType(), i->getField()) + .getAddress(); setLoweredAddress(i, field); } @@ -4194,7 +4247,8 @@ void IRGenSILFunction::visitAllocBoxInst(swift::AllocBoxInst *i) { assert(i->getBoxType()->getLayout()->getFields().size() == 1 && "multi field boxes not implemented yet"); const TypeInfo &type = getTypeInfo( - getSILBoxFieldType(i->getBoxType(), IGM.getSILModule().Types, 0)); + getSILBoxFieldType(IGM.getMaximalTypeExpansionContext(), i->getBoxType(), + IGM.getSILModule().Types, 0)); // Derive name from SIL location. bool IsAnonymous = false; @@ -4232,7 +4286,9 @@ void IRGenSILFunction::visitAllocBoxInst(swift::AllocBoxInst *i) { assert(i->getBoxType()->getLayout()->getFields().size() == 1 && "box for a local variable should only have one field"); - auto SILTy = getSILBoxFieldType(i->getBoxType(), IGM.getSILModule().Types, 0); + auto SILTy = getSILBoxFieldType( + IGM.getMaximalTypeExpansionContext(), + i->getBoxType(), IGM.getSILModule().Types, 0); auto RealType = SILTy.getASTType(); auto DbgTy = DebugTypeInfo::getLocalVariable(Decl, RealType, type); @@ -5412,7 +5468,8 @@ void IRGenSILFunction::visitWitnessMethodInst(swift::WitnessMethodInst *i) { if (IGM.isResilient(conformance.getRequirement(), ResilienceExpansion::Maximal)) { auto *fnPtr = IGM.getAddrOfDispatchThunk(member, NotForDefinition); - auto fnType = IGM.getSILTypes().getConstantFunctionType(member); + auto fnType = IGM.getSILTypes().getConstantFunctionType( + IGM.getMaximalTypeExpansionContext(), member); auto sig = IGM.getSignature(fnType); auto fn = FunctionPointer::forDirect(fnPtr, sig); @@ -5423,9 +5480,9 @@ void IRGenSILFunction::visitWitnessMethodInst(swift::WitnessMethodInst *i) { // It would be nice if this weren't discarded. llvm::Value *baseMetadataCache = nullptr; - auto fn = emitWitnessMethodValue(*this, baseTy, &baseMetadataCache, - member, conformance); - + auto fn = emitWitnessMethodValue(*this, baseTy, &baseMetadataCache, member, + conformance); + setLoweredFunctionPointer(i, fn); } @@ -5582,9 +5639,9 @@ void IRGenSILFunction::visitSuperMethodInst(swift::SuperMethodInst *i) { // Non-resilient case. - auto fn = emitVirtualMethodValue(*this, baseValue, baseType, - method, methodType, - /*useSuperVTable*/ true); + auto fn = + emitVirtualMethodValue(*this, baseValue, baseType, method, methodType, + /*useSuperVTable*/ true); setLoweredFunctionPointer(i, fn); } @@ -5618,10 +5675,9 @@ void IRGenSILFunction::visitClassMethodInst(swift::ClassMethodInst *i) { // For Swift classes, get the method implementation from the vtable. // FIXME: better explosion kind, map as static. - FunctionPointer fn = emitVirtualMethodValue(*this, baseValue, - i->getOperand()->getType(), - method, methodType, - /*useSuperVTable*/ false); + FunctionPointer fn = emitVirtualMethodValue( + *this, baseValue, i->getOperand()->getType(), method, methodType, + /*useSuperVTable*/ false); setLoweredFunctionPointer(i, fn); } diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp index 73c451dc940fa..85698e126a4dd 100644 --- a/lib/IRGen/LoadableByAddress.cpp +++ b/lib/IRGen/LoadableByAddress.cpp @@ -2592,7 +2592,7 @@ bool LoadableByAddress::recreateUncheckedEnumDataInstr( GenericEnvironment *genEnv = F->getGenericEnvironment(); SILType newType = MapperCache.getNewSILType(genEnv, origType, *currIRMod); auto caseTy = enumInstr->getOperand()->getType().getEnumElementType( - enumInstr->getElement(), F->getModule()); + enumInstr->getElement(), F->getModule(), TypeExpansionContext(*F)); SingleValueInstruction *newInstr = nullptr; if (newType.isAddress()) { newType = newType.getObjectType(); @@ -2625,7 +2625,7 @@ bool LoadableByAddress::recreateUncheckedTakeEnumDataAddrInst( GenericEnvironment *genEnv = F->getGenericEnvironment(); SILType newType = MapperCache.getNewSILType(genEnv, origType, *currIRMod); auto caseTy = enumInstr->getOperand()->getType().getEnumElementType( - enumInstr->getElement(), F->getModule()); + enumInstr->getElement(), F->getModule(), TypeExpansionContext(*F)); SingleValueInstruction *newInstr = nullptr; if (caseTy != origType.getObjectType()) { auto *takeEnum = enumBuilder.createUncheckedTakeEnumDataAddr( diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index ed9c5bdfff275..e2adea5d371d0 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -516,8 +516,9 @@ CanType IRGenModule::substOpaqueTypesWithUnderlyingTypes(CanType type) { // Substitute away opaque types whose underlying types we're allowed to // assume are constant. if (type->hasOpaqueArchetype()) { - ReplaceOpaqueTypesWithUnderlyingTypes replacer(getSwiftModule(), - ResilienceExpansion::Maximal); + ReplaceOpaqueTypesWithUnderlyingTypes replacer( + getSwiftModule(), ResilienceExpansion::Maximal, + getSILModule().isWholeModule()); auto underlyingTy = type.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes) ->getCanonicalType(); @@ -532,8 +533,9 @@ SILType IRGenModule::substOpaqueTypesWithUnderlyingTypes( // Substitute away opaque types whose underlying types we're allowed to // assume are constant. if (type.getASTType()->hasOpaqueArchetype()) { - ReplaceOpaqueTypesWithUnderlyingTypes replacer(getSwiftModule(), - ResilienceExpansion::Maximal); + ReplaceOpaqueTypesWithUnderlyingTypes replacer( + getSwiftModule(), ResilienceExpansion::Maximal, + getSILModule().isWholeModule()); auto underlyingTy = type.subst(getSILModule(), replacer, replacer, genericSig, /*substitute opaque*/ true); @@ -549,8 +551,9 @@ IRGenModule::substOpaqueTypesWithUnderlyingTypes(CanType type, // Substitute away opaque types whose underlying types we're allowed to // assume are constant. if (type->hasOpaqueArchetype()) { - ReplaceOpaqueTypesWithUnderlyingTypes replacer(getSwiftModule(), - ResilienceExpansion::Maximal); + ReplaceOpaqueTypesWithUnderlyingTypes replacer( + getSwiftModule(), ResilienceExpansion::Maximal, + getSILModule().isWholeModule()); auto substConformance = conformance.subst( type, replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes); auto underlyingTy = diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp index de34626cd11e3..706aa218fcd52 100644 --- a/lib/ParseSIL/ParseSIL.cpp +++ b/lib/ParseSIL/ParseSIL.cpp @@ -4082,8 +4082,9 @@ bool SILParser::parseSILInstruction(SILBuilder &B) { return true; EnumElementDecl *Elt = cast(EltRef.getDecl()); - auto ResultTy = Operand->getType().getEnumElementType(Elt, SILMod); - + auto ResultTy = Operand->getType().getEnumElementType( + Elt, SILMod, B.getTypeExpansionContext()); + switch (Opcode) { case swift::SILInstructionKind::InitEnumDataAddrInst: ResultVal = B.createInitEnumDataAddr(InstLoc, Operand, Elt, ResultTy); @@ -4431,7 +4432,8 @@ bool SILParser::parseSILInstruction(SILBuilder &B) { // FIXME: substitution means this type should be explicit to improve // performance. - auto ResultTy = Val->getType().getFieldType(Field, SILMod); + auto ResultTy = + Val->getType().getFieldType(Field, SILMod, B.getTypeExpansionContext()); if (Opcode == SILInstructionKind::StructElementAddrInst) ResultVal = B.createStructElementAddr(InstLoc, Val, Field, ResultTy.getAddressType()); @@ -4453,7 +4455,8 @@ bool SILParser::parseSILInstruction(SILBuilder &B) { return true; } VarDecl *Field = cast(FieldV); - auto ResultTy = Val->getType().getFieldType(Field, SILMod); + auto ResultTy = + Val->getType().getFieldType(Field, SILMod, B.getTypeExpansionContext()); ResultVal = B.createRefElementAddr(InstLoc, Val, Field, ResultTy); break; } @@ -5136,8 +5139,8 @@ bool SILParser::parseCallInstruction(SILLocation InstLoc, CanSILFunctionType substFTI = FTI; if (!subs.empty()) { auto silFnTy = FnTy.castTo(); - substFTI - = silFnTy->substGenericArgs(SILMod, subs); + substFTI = + silFnTy->substGenericArgs(SILMod, subs, B.getTypeExpansionContext()); FnTy = SILType::getPrimitiveObjectType(substFTI); } SILFunctionConventions substConv(substFTI, B.getModule()); diff --git a/lib/SIL/AbstractionPattern.cpp b/lib/SIL/AbstractionPattern.cpp index ff1b499c68120..ed058b3a899e8 100644 --- a/lib/SIL/AbstractionPattern.cpp +++ b/lib/SIL/AbstractionPattern.cpp @@ -596,6 +596,8 @@ AbstractionPattern AbstractionPattern::getOptionalObjectType() const { case Kind::Type: if (isTypeParameter()) return AbstractionPattern::getOpaque(); + if (isa(getType())) + return AbstractionPattern::getOpaque(); return AbstractionPattern(getGenericSignature(), ::getOptionalObjectType(getType())); diff --git a/lib/SIL/Bridging.cpp b/lib/SIL/Bridging.cpp index ab2fc6bab7aef..c5760f1805eda 100644 --- a/lib/SIL/Bridging.cpp +++ b/lib/SIL/Bridging.cpp @@ -33,7 +33,8 @@ using namespace swift::Lowering; CanType TypeConverter::getLoweredTypeOfGlobal(VarDecl *var) { AbstractionPattern origType = getAbstractionPattern(var); assert(!origType.isTypeParameter()); - return getLoweredRValueType(origType, origType.getType()); + return getLoweredRValueType(TypeExpansionContext::minimal(), origType, + origType.getType()); } AnyFunctionType::Param diff --git a/lib/SIL/DynamicCasts.cpp b/lib/SIL/DynamicCasts.cpp index 3f83785d1bbbb..f294dddecb59b 100644 --- a/lib/SIL/DynamicCasts.cpp +++ b/lib/SIL/DynamicCasts.cpp @@ -918,7 +918,8 @@ namespace { auto sourceSomeDecl = Ctx.getOptionalSomeDecl(); SILType loweredSourceObjectType = - source.Value->getType().getEnumElementType(sourceSomeDecl, M); + source.Value->getType().getEnumElementType( + sourceSomeDecl, M, B.getTypeExpansionContext()); // Form the target for the optional object. EmitSomeState state; @@ -991,8 +992,8 @@ namespace { auto someDecl = Ctx.getOptionalSomeDecl(); state.SomeDecl = someDecl; - SILType loweredObjectType = - target.LoweredType.getEnumElementType(someDecl, M); + SILType loweredObjectType = target.LoweredType.getEnumElementType( + someDecl, M, B.getTypeExpansionContext()); if (target.isAddress()) { SILValue objectAddr = diff --git a/lib/SIL/MemoryLifetime.cpp b/lib/SIL/MemoryLifetime.cpp index 8c8688086b0ca..39af8027f878f 100644 --- a/lib/SIL/MemoryLifetime.cpp +++ b/lib/SIL/MemoryLifetime.cpp @@ -374,7 +374,8 @@ void MemoryLocations::initFieldsCounter(Location &loc) { } SILModule &module = function->getModule(); for (VarDecl *field : decl->getStoredProperties()) { - loc.updateFieldCounters(ty.getFieldType(field, module), +1); + loc.updateFieldCounters( + ty.getFieldType(field, module, TypeExpansionContext(*function)), +1); } return; } diff --git a/lib/SIL/Projection.cpp b/lib/SIL/Projection.cpp index 3e090189a21bf..2881469102ea1 100644 --- a/lib/SIL/Projection.cpp +++ b/lib/SIL/Projection.cpp @@ -177,17 +177,18 @@ Projection::Projection(SingleValueInstruction *I) : Value() { /// /// WARNING: This is not a constant time operation because it is implemented /// in terms of getVarDecl, which requests all BaseType's stored properties. -SILType Projection::getType(SILType BaseType, SILModule &M) const { +SILType Projection::getType(SILType BaseType, SILModule &M, + TypeExpansionContext context) const { assert(isValid()); switch (getKind()) { case ProjectionKind::Struct: case ProjectionKind::Class: - return BaseType.getFieldType(getVarDecl(BaseType), M); + return BaseType.getFieldType(getVarDecl(BaseType), M, context); case ProjectionKind::Enum: - return BaseType.getEnumElementType(getEnumElementDecl(BaseType), M); + return BaseType.getEnumElementType(getEnumElementDecl(BaseType), M, context); case ProjectionKind::Box: - return getSILBoxFieldType(BaseType.castTo(), - M.Types, getIndex()); + return getSILBoxFieldType(context, BaseType.castTo(), M.Types, + getIndex()); case ProjectionKind::Tuple: return BaseType.getTupleElementType(getIndex()); case ProjectionKind::Upcast: @@ -285,18 +286,20 @@ Projection::createAddressProjection(SILBuilder &B, SILLocation Loc, llvm_unreachable("Unhandled ProjectionKind in switch."); } -void Projection::getFirstLevelProjections(SILType Ty, SILModule &Mod, - llvm::SmallVectorImpl &Out) { +void Projection::getFirstLevelProjections( + SILType Ty, SILModule &Mod, TypeExpansionContext context, + llvm::SmallVectorImpl &Out) { if (auto *S = Ty.getStructOrBoundGenericStruct()) { unsigned Count = 0; for (auto *VDecl : S->getStoredProperties()) { (void) VDecl; Projection P(ProjectionKind::Struct, Count++); LLVM_DEBUG(ProjectionPath X(Ty); - assert(X.getMostDerivedType(Mod) == Ty); + assert(X.getMostDerivedType(Mod, context) == Ty); X.append(P); - assert(X.getMostDerivedType(Mod)==Ty.getFieldType(VDecl, Mod)); - X.verify(Mod);); + assert(X.getMostDerivedType(Mod, context) == + Ty.getFieldType(VDecl, Mod, context)); + X.verify(Mod, context);); Out.push_back(P); } return; @@ -306,10 +309,11 @@ void Projection::getFirstLevelProjections(SILType Ty, SILModule &Mod, for (unsigned i = 0, e = TT->getNumElements(); i != e; ++i) { Projection P(ProjectionKind::Tuple, i); LLVM_DEBUG(ProjectionPath X(Ty); - assert(X.getMostDerivedType(Mod) == Ty); + assert(X.getMostDerivedType(Mod, context) == Ty); X.append(P); - assert(X.getMostDerivedType(Mod) == Ty.getTupleElementType(i)); - X.verify(Mod);); + assert(X.getMostDerivedType(Mod, context) == + Ty.getTupleElementType(i)); + X.verify(Mod, context);); Out.push_back(P); } return; @@ -321,10 +325,11 @@ void Projection::getFirstLevelProjections(SILType Ty, SILModule &Mod, (void) VDecl; Projection P(ProjectionKind::Class, Count++); LLVM_DEBUG(ProjectionPath X(Ty); - assert(X.getMostDerivedType(Mod) == Ty); + assert(X.getMostDerivedType(Mod, context) == Ty); X.append(P); - assert(X.getMostDerivedType(Mod)==Ty.getFieldType(VDecl, Mod)); - X.verify(Mod);); + assert(X.getMostDerivedType(Mod, context) == + Ty.getFieldType(VDecl, Mod, context)); + X.verify(Mod, context);); Out.push_back(P); } return; @@ -334,11 +339,10 @@ void Projection::getFirstLevelProjections(SILType Ty, SILModule &Mod, for (unsigned field : indices(Box->getLayout()->getFields())) { Projection P(ProjectionKind::Box, field); LLVM_DEBUG(ProjectionPath X(Ty); - assert(X.getMostDerivedType(Mod) == Ty); - X.append(P); - assert(X.getMostDerivedType(Mod) - == getSILBoxFieldType(Box, Mod.Types, field)); - X.verify(Mod);); + assert(X.getMostDerivedType(Mod, context) == Ty); X.append(P); + assert(X.getMostDerivedType(Mod, context) == + getSILBoxFieldType(context, Box, Mod.Types, field)); + X.verify(Mod, context);); (void)Box; Out.push_back(P); } @@ -580,12 +584,13 @@ void Projection::print(raw_ostream &os, SILType baseType) const { os << ""; } -raw_ostream &ProjectionPath::print(raw_ostream &os, SILModule &M) const { +raw_ostream &ProjectionPath::print(raw_ostream &os, SILModule &M, + TypeExpansionContext context) const { os << "Projection Path ["; SILType IterType = getBaseType(); for (const Projection &IterProj : Path) { SILType BaseType = IterType; - IterType = IterProj.getType(IterType, M); + IterType = IterProj.getType(IterType, M, context); os << BaseType.getAddressType() << "\n "; @@ -596,16 +601,16 @@ raw_ostream &ProjectionPath::print(raw_ostream &os, SILModule &M) const { return os; } -void ProjectionPath::dump(SILModule &M) const { - print(llvm::dbgs(), M); +void ProjectionPath::dump(SILModule &M, TypeExpansionContext context) const { + print(llvm::dbgs(), M, context); } -void ProjectionPath::verify(SILModule &M) { +void ProjectionPath::verify(SILModule &M, TypeExpansionContext context) { #ifndef NDEBUG SILType IterTy = getBaseType(); assert(IterTy); for (auto &Proj : Path) { - IterTy = Proj.getType(IterTy, M); + IterTy = Proj.getType(IterTy, M, context); assert(IterTy); } #endif @@ -613,6 +618,7 @@ void ProjectionPath::verify(SILModule &M) { void ProjectionPath::expandTypeIntoLeafProjectionPaths(SILType B, SILModule *Mod, + TypeExpansionContext context, ProjectionPathList &Paths) { // Perform a BFS to expand the given type into projectionpath each of // which contains 1 field from the type. @@ -626,7 +632,7 @@ ProjectionPath::expandTypeIntoLeafProjectionPaths(SILType B, SILModule *Mod, // Get the next level projections based on current projection's type. ProjectionPath PP = Worklist.pop_back_val(); // Get the current type to process. - SILType Ty = PP.getMostDerivedType(*Mod); + SILType Ty = PP.getMostDerivedType(*Mod, context); LLVM_DEBUG(llvm::dbgs() << "Visiting type: " << Ty << "\n"); @@ -655,7 +661,7 @@ ProjectionPath::expandTypeIntoLeafProjectionPaths(SILType B, SILModule *Mod, // Get the first level projection of the current type. Projections.clear(); - Projection::getFirstLevelProjections(Ty, *Mod, Projections); + Projection::getFirstLevelProjections(Ty, *Mod, context, Projections); // Reached the end of the projection tree, this field can not be expanded // anymore. @@ -695,11 +701,12 @@ bool ProjectionPath::hasUncoveredNonTrivials(SILType B, const SILFunction &F, continue; // Get the current type to process. - SILType Ty = PP.getMostDerivedType(Mod); + SILType Ty = PP.getMostDerivedType(Mod, F.getTypeExpansionContext()); // Get the first level projection of the current type. llvm::SmallVector Projections; - Projection::getFirstLevelProjections(Ty, Mod, Projections); + Projection::getFirstLevelProjections(Ty, Mod, F.getTypeExpansionContext(), + Projections); // Reached the end of the projection tree, this field can not be expanded // anymore. @@ -719,7 +726,8 @@ bool ProjectionPath::hasUncoveredNonTrivials(SILType B, const SILFunction &F, for (auto &P : Projections) { ProjectionPath X(B); X.append(PP); - assert(PP.getMostDerivedType(Mod) == X.getMostDerivedType(Mod)); + assert(PP.getMostDerivedType(Mod, F.getTypeExpansionContext()) == + X.getMostDerivedType(Mod, F.getTypeExpansionContext())); X.append(P); Worklist.push_back(X); } @@ -728,8 +736,8 @@ bool ProjectionPath::hasUncoveredNonTrivials(SILType B, const SILFunction &F, // Check whether any path leads to a non-trivial type. for (auto &X : Paths) { - if (!X.getMostDerivedType(Mod).isTrivial(F)) - return true; + if (!X.getMostDerivedType(Mod, F.getTypeExpansionContext()).isTrivial(F)) + return true; } return false; } @@ -937,7 +945,8 @@ processUsersOfValue(ProjectionTree &Tree, // we have a projection to the next level children, create the next // level children nodes lazily. if (!Initialized) - createNextLevelChildren(Tree); + createNextLevelChildren( + Tree, TypeExpansionContext(*projectionInst->getFunction())); // Look up the Node for this projection add {User, ChildNode} to the // worklist. @@ -962,15 +971,14 @@ processUsersOfValue(ProjectionTree &Tree, } } -void -ProjectionTreeNode:: -createNextLevelChildrenForStruct(ProjectionTree &Tree, StructDecl *SD) { +void ProjectionTreeNode::createNextLevelChildrenForStruct( + ProjectionTree &Tree, TypeExpansionContext context, StructDecl *SD) { SILModule &Mod = Tree.getModule(); unsigned ChildIndex = 0; SILType Ty = getType(); for (VarDecl *VD : SD->getStoredProperties()) { assert(Tree.getNode(Index) == this && "Node is not mapped to itself?"); - SILType NodeTy = Ty.getFieldType(VD, Mod); + SILType NodeTy = Ty.getFieldType(VD, Mod, context); auto *Node = Tree.createChildForStruct(this, NodeTy, VD, ChildIndex++); LLVM_DEBUG(llvm::dbgs() << " Creating child for: " < elts) { return createTuple(loc, tupleType, elts); } -SILType SILBuilder::getPartialApplyResultType(SILType origTy, unsigned argCount, - SILModule &M, - SubstitutionMap subs, - ParameterConvention calleeConvention, - PartialApplyInst::OnStackKind onStack) { +SILType SILBuilder::getPartialApplyResultType( + TypeExpansionContext context, SILType origTy, unsigned argCount, + SILModule &M, SubstitutionMap subs, ParameterConvention calleeConvention, + PartialApplyInst::OnStackKind onStack) { CanSILFunctionType FTI = origTy.castTo(); if (!subs.empty()) - FTI = FTI->substGenericArgs(M, subs); - + FTI = FTI->substGenericArgs(M, subs, context); + assert(!FTI->isPolymorphic() && "must provide substitutions for generic partial_apply"); auto params = FTI->getParameters(); @@ -104,7 +103,8 @@ ProjectBoxInst *SILBuilder::createProjectBox(SILLocation Loc, SILValue boxOperand, unsigned index) { auto boxTy = boxOperand->getType().castTo(); - auto fieldTy = getSILBoxFieldType(boxTy, getModule().Types, index); + auto fieldTy = getSILBoxFieldType(getTypeExpansionContext(), boxTy, + getModule().Types, index); return insert(new (getModule()) ProjectBoxInst( getSILDebugLocation(Loc), boxOperand, index, fieldTy)); @@ -511,11 +511,11 @@ void SILBuilder::addOpenedArchetypeOperands(SILInstruction *I) { ValueMetatypeInst *SILBuilder::createValueMetatype(SILLocation Loc, SILType MetatypeTy, SILValue Base) { - assert( - Base->getType().isLoweringOf( - getModule(), MetatypeTy.castTo().getInstanceType()) && - "value_metatype result must be formal metatype of the lowered operand " - "type"); + assert(Base->getType().isLoweringOf( + getTypeExpansionContext(), getModule(), + MetatypeTy.castTo().getInstanceType()) && + "value_metatype result must be formal metatype of the lowered operand " + "type"); return insert(new (getModule()) ValueMetatypeInst(getSILDebugLocation(Loc), MetatypeTy, Base)); } @@ -541,7 +541,8 @@ void SILBuilder::emitDestructureValueOperation( // In non qualified ownership SIL, drop back to using projection code. SmallVector projections; - Projection::getFirstLevelProjections(v->getType(), getModule(), projections); + Projection::getFirstLevelProjections(v->getType(), getModule(), + getTypeExpansionContext(), projections); llvm::transform(projections, std::back_inserter(results), [&](const Projection &p) -> SILValue { return p.createObjectProjection(*this, loc, v).get(); @@ -562,7 +563,8 @@ void SILBuilder::emitDestructureAddressOperation( } SmallVector projections; - Projection::getFirstLevelProjections(v->getType(), getModule(), projections); + Projection::getFirstLevelProjections(v->getType(), getModule(), + getTypeExpansionContext(), projections); llvm::transform(projections, std::back_inserter(results), [&](const Projection &p) -> SILValue { return p.createAddressProjection(*this, loc, v).get(); diff --git a/lib/SIL/SILFunction.cpp b/lib/SIL/SILFunction.cpp index 8fdf99b6878dc..44905ea1b1504 100644 --- a/lib/SIL/SILFunction.cpp +++ b/lib/SIL/SILFunction.cpp @@ -235,34 +235,37 @@ bool SILFunction::isNoReturnFunction() const { const TypeLowering & SILFunction::getTypeLowering(AbstractionPattern orig, Type subst) { return getModule().Types.getTypeLowering(orig, subst, - getResilienceExpansion()); + TypeExpansionContext(*this)); } const TypeLowering &SILFunction::getTypeLowering(Type t) const { - return getModule().Types.getTypeLowering(t, getResilienceExpansion()); + return getModule().Types.getTypeLowering(t, TypeExpansionContext(*this)); } SILType SILFunction::getLoweredType(AbstractionPattern orig, Type subst) const { return getModule().Types.getLoweredType(orig, subst, - getResilienceExpansion()); + TypeExpansionContext(*this)); } SILType SILFunction::getLoweredType(Type t) const { - return getModule().Types.getLoweredType(t, getResilienceExpansion()); + return getModule().Types.getLoweredType(t, TypeExpansionContext(*this)); } SILType SILFunction::getLoweredLoadableType(Type t) const { auto &M = getModule(); - return M.Types.getLoweredLoadableType(t, getResilienceExpansion(), M); + return M.Types.getLoweredLoadableType(t, TypeExpansionContext(*this), M); } const TypeLowering &SILFunction::getTypeLowering(SILType type) const { - return getModule().Types.getTypeLowering(type, getResilienceExpansion()); + return getModule().Types.getTypeLowering(type, TypeExpansionContext(*this)); } +SILType SILFunction::getLoweredType(SILType t) const { + return getTypeLowering(t).getLoweredType().getCategoryType(t.getCategory()); +} bool SILFunction::isTypeABIAccessible(SILType type) const { - return getModule().isTypeABIAccessible(type, getResilienceExpansion()); + return getModule().isTypeABIAccessible(type, TypeExpansionContext(*this)); } bool SILFunction::isWeakImported() const { diff --git a/lib/SIL/SILFunctionBuilder.cpp b/lib/SIL/SILFunctionBuilder.cpp index e2abe75068a65..85c962470be37 100644 --- a/lib/SIL/SILFunctionBuilder.cpp +++ b/lib/SIL/SILFunctionBuilder.cpp @@ -107,7 +107,8 @@ SILFunctionBuilder::getOrCreateFunction(SILLocation loc, SILDeclRef constant, ForDefinition_t forDefinition, ProfileCounter entryCount) { auto nameTmp = constant.mangle(); - auto constantType = mod.Types.getConstantFunctionType(constant); + auto constantType = mod.Types.getConstantFunctionType( + TypeExpansionContext::minimal(), constant); SILLinkage linkage = constant.getLinkage(forDefinition); if (auto fn = mod.lookUpFunction(nameTmp)) { diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp index b6399ec306434..67ea7f9ec0428 100644 --- a/lib/SIL/SILFunctionType.cpp +++ b/lib/SIL/SILFunctionType.cpp @@ -338,10 +338,13 @@ class DestructureResults { TypeConverter &TC; const Conventions &Convs; SmallVectorImpl &Results; + TypeExpansionContext context; + public: - DestructureResults(TypeConverter &TC, const Conventions &conventions, + DestructureResults(TypeExpansionContext context, TypeConverter &TC, + const Conventions &conventions, SmallVectorImpl &results) - : TC(TC), Convs(conventions), Results(results) {} + : TC(TC), Convs(conventions), Results(results), context(context) {} void destructure(AbstractionPattern origType, CanType substType) { // Recurse into tuples. @@ -356,15 +359,19 @@ class DestructureResults { return; } + auto &substResultTLForConvention = TC.getTypeLowering( + origType, substType, TypeExpansionContext::minimal()); auto &substResultTL = TC.getTypeLowering(origType, substType, - ResilienceExpansion::Minimal); + context); + // Determine the result convention. ResultConvention convention; - if (isFormallyReturnedIndirectly(origType, substType, substResultTL)) { + if (isFormallyReturnedIndirectly(origType, substType, + substResultTLForConvention)) { convention = ResultConvention::Indirect; } else { - convention = Convs.getResult(substResultTL); + convention = Convs.getResult(substResultTLForConvention); // Reduce conventions for trivial types to an unowned convention. if (substResultTL.isTrivial()) { @@ -507,6 +514,7 @@ static bool isFormallyPassedIndirectly(TypeConverter &TC, /// /// See the comment in AbstractionPattern.h for details. class DestructureInputs { + TypeExpansionContext expansion; TypeConverter &TC; const Conventions &Convs; const ForeignInfo &Foreign; @@ -514,10 +522,11 @@ class DestructureInputs { SmallVectorImpl &Inputs; unsigned NextOrigParamIndex = 0; public: - DestructureInputs(TypeConverter &TC, const Conventions &conventions, - const ForeignInfo &foreign, + DestructureInputs(TypeExpansionContext expansion, TypeConverter &TC, + const Conventions &conventions, const ForeignInfo &foreign, SmallVectorImpl &inputs) - : TC(TC), Convs(conventions), Foreign(foreign), Inputs(inputs) {} + : expansion(expansion), TC(TC), Convs(conventions), Foreign(foreign), + Inputs(inputs) {} void destructure(AbstractionPattern origType, CanAnyFunctionType::CanParamArrayRef params, @@ -628,20 +637,21 @@ class DestructureInputs { unsigned origParamIndex = NextOrigParamIndex++; - auto &substTL = TC.getTypeLowering(origType, substType, - ResilienceExpansion::Minimal); + auto &substTLConv = TC.getTypeLowering(origType, substType, + TypeExpansionContext::minimal()); + auto &substTL = TC.getTypeLowering(origType, substType, expansion); ParameterConvention convention; if (ownership == ValueOwnership::InOut) { convention = ParameterConvention::Indirect_Inout; - } else if (isFormallyPassedIndirectly(origType, substType, substTL)) { + } else if (isFormallyPassedIndirectly(origType, substType, substTLConv)) { convention = Convs.getIndirect(ownership, forSelf, origParamIndex, - origType, substTL); + origType, substTLConv); assert(isIndirectFormalParameter(convention)); } else if (substTL.isTrivial()) { convention = ParameterConvention::Direct_Unowned; } else { convention = Convs.getDirect(ownership, forSelf, origParamIndex, origType, - substTL); + substTLConv); assert(!isIndirectFormalParameter(convention)); } auto loweredType = substTL.getLoweredType().getASTType(); @@ -665,8 +675,8 @@ class DestructureInputs { NextOrigParamIndex != Foreign.Error->getErrorParameterIndex()) return false; - auto foreignErrorTy = - TC.getLoweredRValueType(Foreign.Error->getErrorParameterType()); + auto foreignErrorTy = TC.getLoweredRValueType( + expansion, Foreign.Error->getErrorParameterType()); // Assume the error parameter doesn't have interesting lowering. Inputs.push_back(SILParameterInfo(foreignErrorTy, @@ -755,7 +765,7 @@ static std::pair updateResultTypeForForeignError( static void lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function, CanGenericSignature genericSig, - ResilienceExpansion expansion, + TypeExpansionContext expansion, SmallVectorImpl &inputs) { // NB: The generic signature may be elided from the lowered function type @@ -827,9 +837,14 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function, break; } case CaptureKind::Box: { + // The type in the box is lowered in the minimal context. + auto minimalLoweredTy = + TC.getTypeLowering(AbstractionPattern(genericSig, canType), canType, + TypeExpansionContext::minimal()) + .getLoweredType(); // Lvalues are captured as a box that owns the captured value. auto boxTy = TC.getInterfaceBoxTypeForCapture( - VD, loweredTy.getASTType(), + VD, minimalLoweredTy.getASTType(), /*mutable*/ true); auto convention = ParameterConvention::Direct_Guaranteed; auto param = SILParameterInfo(boxTy, convention); @@ -850,6 +865,7 @@ lowerCaptureContextParameters(TypeConverter &TC, SILDeclRef function, } static void destructureYieldsForReadAccessor(TypeConverter &TC, + TypeExpansionContext expansion, AbstractionPattern origType, CanType valueType, SmallVectorImpl &yields) { @@ -859,17 +875,20 @@ static void destructureYieldsForReadAccessor(TypeConverter &TC, for (auto i : indices(valueTupleType.getElementTypes())) { auto origEltType = origType.getTupleElementType(i); auto valueEltType = valueTupleType.getElementType(i); - destructureYieldsForReadAccessor(TC, origEltType, valueEltType, yields); + destructureYieldsForReadAccessor(TC, expansion, origEltType, valueEltType, + yields); } return; } - auto &tl = TC.getTypeLowering(origType, valueType, - ResilienceExpansion::Minimal); + auto &tlConv = + TC.getTypeLowering(origType, valueType, TypeExpansionContext::minimal()); + auto &tl = + TC.getTypeLowering(origType, valueType, expansion); auto convention = [&] { - if (isFormallyPassedIndirectly(TC, origType, valueType, tl)) + if (isFormallyPassedIndirectly(TC, origType, valueType, tlConv)) return ParameterConvention::Indirect_In_Guaranteed; - if (tl.isTrivial()) + if (tlConv.isTrivial()) return ParameterConvention::Direct_Unowned; return ParameterConvention::Direct_Guaranteed; }(); @@ -878,6 +897,7 @@ static void destructureYieldsForReadAccessor(TypeConverter &TC, } static void destructureYieldsForCoroutine(TypeConverter &TC, + TypeExpansionContext expansion, Optional origConstant, Optional constant, Optional reqtSubs, @@ -916,7 +936,8 @@ static void destructureYieldsForCoroutine(TypeConverter &TC, // 'modify' yields an inout of the target type. if (accessor->getAccessorKind() == AccessorKind::Modify) { - auto loweredValueTy = TC.getLoweredRValueType(origType, canValueType); + auto loweredValueTy = + TC.getLoweredRValueType(expansion, origType, canValueType); yields.push_back(SILYieldInfo(loweredValueTy, ParameterConvention::Indirect_Inout)); return; @@ -925,7 +946,8 @@ static void destructureYieldsForCoroutine(TypeConverter &TC, // 'read' yields a borrowed value of the target type, destructuring // tuples as necessary. assert(accessor->getAccessorKind() == AccessorKind::Read); - destructureYieldsForReadAccessor(TC, origType, canValueType, yields); + destructureYieldsForReadAccessor(TC, expansion, origType, canValueType, + yields); } /// Create the appropriate SIL function type for the given formal type @@ -964,7 +986,7 @@ static void destructureYieldsForCoroutine(TypeConverter &TC, /// /// \param conventions - conventions as expressed for the original type static CanSILFunctionType getSILFunctionType( - TypeConverter &TC, AbstractionPattern origType, + TypeConverter &TC, TypeExpansionContext expansionContext, AbstractionPattern origType, CanAnyFunctionType substFnInterfaceType, AnyFunctionType::ExtInfo extInfo, const Conventions &conventions, const ForeignInfo &foreignInfo, Optional origConstant, Optional constant, @@ -1016,14 +1038,15 @@ static CanSILFunctionType getSILFunctionType( // Destructure the result tuple type. SmallVector results; { - DestructureResults destructurer(TC, conventions, results); + DestructureResults destructurer(expansionContext, TC, conventions, results); destructurer.destructure(origResultType, substFormalResultType); } // Destructure the input tuple type. SmallVector inputs; { - DestructureInputs destructurer(TC, conventions, foreignInfo, inputs); + DestructureInputs destructurer(expansionContext, TC, conventions, + foreignInfo, inputs); destructurer.destructure(origType, substFnInterfaceType.getParams(), extInfo); @@ -1032,16 +1055,16 @@ static CanSILFunctionType getSILFunctionType( // Destructure the coroutine yields. SILCoroutineKind coroutineKind = SILCoroutineKind::None; SmallVector yields; - destructureYieldsForCoroutine(TC, origConstant, constant, reqtSubs, - yields, coroutineKind); - + destructureYieldsForCoroutine(TC, expansionContext, origConstant, constant, + reqtSubs, yields, coroutineKind); + // Lower the capture context parameters, if any. if (constant && constant->getAnyFunctionRef()) { - auto expansion = ResilienceExpansion::Maximal; + auto expansion = TypeExpansionContext::maximal( + expansionContext.getContext(), expansionContext.isWholeModuleContext()); if (constant->isSerialized()) - expansion = ResilienceExpansion::Minimal; - lowerCaptureContextParameters(TC, *constant, genericSig, expansion, - inputs); + expansion = TypeExpansionContext::minimal(); + lowerCaptureContextParameters(TC, *constant, genericSig, expansion, inputs); } auto calleeConvention = ParameterConvention::Direct_Unowned; @@ -1434,7 +1457,7 @@ getSILFunctionTypeForAbstractCFunction(TypeConverter &TC, Optional constant); static CanSILFunctionType getNativeSILFunctionType( - TypeConverter &TC, AbstractionPattern origType, + TypeConverter &TC, TypeExpansionContext context, AbstractionPattern origType, CanAnyFunctionType substInterfaceType, AnyFunctionType::ExtInfo extInfo, Optional origConstant, Optional constant, Optional reqtSubs, @@ -1456,23 +1479,23 @@ static CanSILFunctionType getNativeSILFunctionType( switch (constant ? constant->kind : SILDeclRef::Kind::Func) { case SILDeclRef::Kind::Initializer: case SILDeclRef::Kind::EnumElement: - return getSILFunctionType(TC, origType, substInterfaceType, extInfo, - DefaultInitializerConventions(), ForeignInfo(), - origConstant, constant, reqtSubs, + return getSILFunctionType(TC, context, origType, substInterfaceType, + extInfo, DefaultInitializerConventions(), + ForeignInfo(), origConstant, constant, reqtSubs, witnessMethodConformance); case SILDeclRef::Kind::Allocator: - return getSILFunctionType(TC, origType, substInterfaceType, extInfo, - DefaultAllocatorConventions(), ForeignInfo(), - origConstant, constant, reqtSubs, + return getSILFunctionType(TC, context, origType, substInterfaceType, + extInfo, DefaultAllocatorConventions(), + ForeignInfo(), origConstant, constant, reqtSubs, witnessMethodConformance); case SILDeclRef::Kind::Func: // If we have a setter, use the special setter convention. This ensures // that we take normal parameters at +1. if (constant && constant->isSetter()) { - return getSILFunctionType(TC, origType, substInterfaceType, extInfo, - DefaultSetterConventions(), ForeignInfo(), - origConstant, constant, reqtSubs, - witnessMethodConformance); + return getSILFunctionType(TC, context, origType, substInterfaceType, + extInfo, DefaultSetterConventions(), + ForeignInfo(), origConstant, constant, + reqtSubs, witnessMethodConformance); } LLVM_FALLTHROUGH; case SILDeclRef::Kind::Destroyer: @@ -1483,14 +1506,14 @@ static CanSILFunctionType getNativeSILFunctionType( case SILDeclRef::Kind::IVarInitializer: case SILDeclRef::Kind::IVarDestroyer: { auto conv = DefaultConventions(NormalParameterConvention::Guaranteed); - return getSILFunctionType(TC, origType, substInterfaceType, extInfo, conv, - ForeignInfo(), origConstant, constant, reqtSubs, - witnessMethodConformance); + return getSILFunctionType(TC, context, origType, substInterfaceType, + extInfo, conv, ForeignInfo(), origConstant, + constant, reqtSubs, witnessMethodConformance); } case SILDeclRef::Kind::Deallocator: - return getSILFunctionType(TC, origType, substInterfaceType, extInfo, - DeallocatorConventions(), ForeignInfo(), - origConstant, constant, reqtSubs, + return getSILFunctionType(TC, context, origType, substInterfaceType, + extInfo, DeallocatorConventions(), + ForeignInfo(), origConstant, constant, reqtSubs, witnessMethodConformance); } } @@ -1500,9 +1523,10 @@ static CanSILFunctionType getNativeSILFunctionType( } CanSILFunctionType swift::getNativeSILFunctionType( - TypeConverter &TC, AbstractionPattern origType, - CanAnyFunctionType substType, Optional origConstant, - Optional substConstant, Optional reqtSubs, + TypeConverter &TC, TypeExpansionContext context, + AbstractionPattern origType, CanAnyFunctionType substType, + Optional origConstant, Optional substConstant, + Optional reqtSubs, ProtocolConformanceRef witnessMethodConformance) { AnyFunctionType::ExtInfo extInfo; @@ -1515,7 +1539,7 @@ CanSILFunctionType swift::getNativeSILFunctionType( extInfo = substType->getExtInfo(); } - return ::getNativeSILFunctionType(TC, origType, substType, extInfo, + return ::getNativeSILFunctionType(TC, context, origType, substType, extInfo, origConstant, substConstant, reqtSubs, witnessMethodConformance); } @@ -1862,7 +1886,8 @@ getSILFunctionTypeForClangDecl(TypeConverter &TC, const clang::Decl *clangDecl, if (auto method = dyn_cast(clangDecl)) { auto origPattern = AbstractionPattern::getObjCMethod(origType, method, foreignInfo.Error); - return getSILFunctionType(TC, origPattern, substInterfaceType, extInfo, + return getSILFunctionType(TC, TypeExpansionContext::minimal(), origPattern, + substInterfaceType, extInfo, ObjCMethodConventions(method), foreignInfo, constant, constant, None, ProtocolConformanceRef()); @@ -1872,9 +1897,10 @@ getSILFunctionTypeForClangDecl(TypeConverter &TC, const clang::Decl *clangDecl, AbstractionPattern origPattern = AbstractionPattern::getCXXMethod(origType, method); auto conventions = CXXMethodConventions(method); - return getSILFunctionType(TC, origPattern, substInterfaceType, extInfo, - conventions, foreignInfo, constant, constant, - None, ProtocolConformanceRef()); + return getSILFunctionType(TC, TypeExpansionContext::minimal(), origPattern, + substInterfaceType, extInfo, conventions, + foreignInfo, constant, constant, None, + ProtocolConformanceRef()); } if (auto func = dyn_cast(clangDecl)) { @@ -1884,7 +1910,8 @@ getSILFunctionTypeForClangDecl(TypeConverter &TC, const clang::Decl *clangDecl, ? AbstractionPattern::getCFunctionAsMethod(origType, clangType, foreignInfo.Self) : AbstractionPattern(origType, clangType); - return getSILFunctionType(TC, origPattern, substInterfaceType, extInfo, + return getSILFunctionType(TC, TypeExpansionContext::minimal(), origPattern, + substInterfaceType, extInfo, CFunctionConventions(func), foreignInfo, constant, constant, None, ProtocolConformanceRef()); } @@ -1914,15 +1941,17 @@ getSILFunctionTypeForAbstractCFunction(TypeConverter &TC, } if (fnType) { return getSILFunctionType( - TC, origType, substType, extInfo, CFunctionTypeConventions(fnType), - ForeignInfo(), constant, constant, None, ProtocolConformanceRef()); + TC, TypeExpansionContext::minimal(), origType, substType, extInfo, + CFunctionTypeConventions(fnType), ForeignInfo(), constant, constant, + None, ProtocolConformanceRef()); } } // TODO: Ought to support captures in block funcs. - return getSILFunctionType(TC, origType, substType, extInfo, - DefaultBlockConventions(), ForeignInfo(), constant, - constant, None, ProtocolConformanceRef()); + return getSILFunctionType(TC, TypeExpansionContext::minimal(), origType, + substType, extInfo, DefaultBlockConventions(), + ForeignInfo(), constant, constant, None, + ProtocolConformanceRef()); } /// Try to find a clang method declaration for the given function. @@ -2087,8 +2116,9 @@ getSILFunctionTypeForObjCSelectorFamily(TypeConverter &TC, ObjCSelectorFamily fa const ForeignInfo &foreignInfo, Optional constant) { return getSILFunctionType( - TC, AbstractionPattern(origType), substInterfaceType, extInfo, - ObjCSelectorFamilyConventions(family), foreignInfo, constant, constant, + TC, TypeExpansionContext::minimal(), AbstractionPattern(origType), + substInterfaceType, extInfo, ObjCSelectorFamilyConventions(family), + foreignInfo, constant, constant, /*requirement subs*/ None, ProtocolConformanceRef()); } @@ -2110,10 +2140,9 @@ static bool isImporterGeneratedAccessor(const clang::Decl *clangDecl, return true; } -static CanSILFunctionType -getUncachedSILFunctionTypeForConstant(TypeConverter &TC, - SILDeclRef constant, - CanAnyFunctionType origLoweredInterfaceType) { +static CanSILFunctionType getUncachedSILFunctionTypeForConstant( + TypeConverter &TC, TypeExpansionContext context, SILDeclRef constant, + CanAnyFunctionType origLoweredInterfaceType) { assert(origLoweredInterfaceType->getExtInfo().getSILRepresentation() != SILFunctionTypeRepresentation::Thick && origLoweredInterfaceType->getExtInfo().getSILRepresentation() @@ -2131,9 +2160,9 @@ getUncachedSILFunctionTypeForConstant(TypeConverter &TC, } return ::getNativeSILFunctionType( - TC, AbstractionPattern(origLoweredInterfaceType), - origLoweredInterfaceType, extInfo, - constant, constant, None, witnessMethodConformance); + TC, context, AbstractionPattern(origLoweredInterfaceType), + origLoweredInterfaceType, extInfo, constant, constant, None, + witnessMethodConformance); } ForeignInfo foreignInfo; @@ -2173,12 +2202,12 @@ getUncachedSILFunctionTypeForConstant(TypeConverter &TC, extInfo, foreignInfo, constant); } -CanSILFunctionType TypeConverter:: -getUncachedSILFunctionTypeForConstant(SILDeclRef constant, - CanAnyFunctionType origInterfaceType) { +CanSILFunctionType TypeConverter::getUncachedSILFunctionTypeForConstant( + TypeExpansionContext context, SILDeclRef constant, + CanAnyFunctionType origInterfaceType) { auto origLoweredInterfaceType = getLoweredFormalTypes(constant, origInterfaceType).Uncurried; - return ::getUncachedSILFunctionTypeForConstant(*this, constant, + return ::getUncachedSILFunctionTypeForConstant(*this, context, constant, origLoweredInterfaceType); } @@ -2258,9 +2287,11 @@ static llvm::cl::opt DisableConstantInfoCache("sil-disable-typelowering-constantinfo-cache", llvm::cl::init(false)); -const SILConstantInfo &TypeConverter::getConstantInfo(SILDeclRef constant) { +const SILConstantInfo & +TypeConverter::getConstantInfo(TypeExpansionContext expansion, + SILDeclRef constant) { if (!DisableConstantInfoCache) { - auto found = ConstantTypes.find(constant); + auto found = ConstantTypes.find(std::make_pair(expansion, constant)); if (found != ConstantTypes.end()) return *found->second; } @@ -2281,7 +2312,7 @@ const SILConstantInfo &TypeConverter::getConstantInfo(SILDeclRef constant) { // The SIL type encodes conventions according to the original type. CanSILFunctionType silFnType = - ::getUncachedSILFunctionTypeForConstant(*this, constant, + ::getUncachedSILFunctionTypeForConstant(*this, expansion, constant, loweredInterfaceType); LLVM_DEBUG(llvm::dbgs() << "lowering type for constant "; @@ -2304,7 +2335,8 @@ const SILConstantInfo &TypeConverter::getConstantInfo(SILDeclRef constant) { if (DisableConstantInfoCache) return *result; - auto inserted = ConstantTypes.insert({constant, result}); + auto inserted = + ConstantTypes.insert({std::make_pair(expansion, constant), result}); assert(inserted.second); (void)inserted; return *result; @@ -2312,8 +2344,10 @@ const SILConstantInfo &TypeConverter::getConstantInfo(SILDeclRef constant) { /// Returns the SILParameterInfo for the given declaration's `self` parameter. /// `constant` must refer to a method. -SILParameterInfo TypeConverter::getConstantSelfParameter(SILDeclRef constant) { - auto ty = getConstantFunctionType(constant); +SILParameterInfo +TypeConverter::getConstantSelfParameter(TypeExpansionContext context, + SILDeclRef constant) { + auto ty = getConstantFunctionType(context, constant); // In most cases the "self" parameter is lowered as the back parameter. // The exception is C functions imported as methods. @@ -2417,10 +2451,11 @@ static CanType copyOptionalityFromDerivedToBase(TypeConverter &tc, /// Returns the ConstantInfo corresponding to the VTable thunk for overriding. /// Will be the same as getConstantInfo if the declaration does not override. const SILConstantInfo & -TypeConverter::getConstantOverrideInfo(SILDeclRef derived, SILDeclRef base) { +TypeConverter::getConstantOverrideInfo(TypeExpansionContext context, + SILDeclRef derived, SILDeclRef base) { // Foreign overrides currently don't need reabstraction. if (derived.isForeign) - return getConstantInfo(derived); + return getConstantInfo(context, derived); auto found = ConstantOverrideTypes.find({derived, base}); if (found != ConstantOverrideTypes.end()) @@ -2428,8 +2463,8 @@ TypeConverter::getConstantOverrideInfo(SILDeclRef derived, SILDeclRef base) { assert(base.requiresNewVTableEntry() && "base must not be an override"); - auto baseInfo = getConstantInfo(base); - auto derivedInfo = getConstantInfo(derived); + auto baseInfo = getConstantInfo(context, base); + auto derivedInfo = getConstantInfo(context, derived); // If the derived method is ABI-compatible with the base method, give the // vtable thunk the same signature as the derived method. @@ -2476,7 +2511,7 @@ TypeConverter::getConstantOverrideInfo(SILDeclRef derived, SILDeclRef base) { // Build the SILFunctionType for the vtable thunk. CanSILFunctionType fnTy = getNativeSILFunctionType( - *this, basePattern, overrideLoweredInterfaceTy, base, derived, + *this, context, basePattern, overrideLoweredInterfaceTy, base, derived, /*reqt subs*/ None, ProtocolConformanceRef()); // Build the SILConstantInfo and cache it. @@ -2509,10 +2544,13 @@ class SILTypeSubstituter : // context signature. CanGenericSignature Sig; + TypeExpansionContext typeExpansionContext; + bool shouldSubstituteOpaqueArchetypes; public: SILTypeSubstituter(TypeConverter &TC, + TypeExpansionContext context, TypeSubstitutionFn Subst, LookupConformanceFn Conformances, CanGenericSignature Sig, @@ -2521,6 +2559,7 @@ class SILTypeSubstituter : Subst(Subst), Conformances(Conformances), Sig(Sig), + typeExpansionContext(context), shouldSubstituteOpaqueArchetypes(shouldSubstituteOpaqueArchetypes) {} @@ -2584,13 +2623,31 @@ class SILTypeSubstituter : } witnessMethodConformance = conformance.subst(selfType, Subst, Conformances); + + // Substitute the underlying conformance of opaque type archetypes if we + // should look through opaque archetypes. + if (typeExpansionContext.shouldLookThroughOpaqueTypeArchetypes()) { + SubstOptions substOptions(None); + auto substType = selfType.subst(Subst, Conformances, substOptions) + ->getCanonicalType(); + if (substType->hasOpaqueArchetype()) { + witnessMethodConformance = substOpaqueTypesWithUnderlyingTypes( + witnessMethodConformance, substType, typeExpansionContext); + } + } } // The substituted type is no longer generic, so it'd never be // pseudogeneric. - auto extInfo = origType->getExtInfo().withIsPseudogeneric(false); + auto extInfo = origType->getExtInfo(); + if (!shouldSubstituteOpaqueArchetypes) + extInfo = extInfo.withIsPseudogeneric(false); - return SILFunctionType::get(nullptr, extInfo, + auto genericSig = shouldSubstituteOpaqueArchetypes + ? origType->getSubstGenericSignature() + : nullptr; + + return SILFunctionType::get(genericSig, extInfo, origType->getCoroutineKind(), origType->getCalleeConvention(), substParams, substYields, substResults, substErrorResult, @@ -2670,7 +2727,14 @@ class SILTypeSubstituter : } AbstractionPattern abstraction(Sig, origType); - return TC.getLoweredRValueType(abstraction, substType); + // If we looked through an opaque archetype to a function type we need to + // use the function type's abstraction. + if (isa(origType) && + isa(substType)) + abstraction = AbstractionPattern(Sig, substType); + + return TC.getLoweredRValueType(typeExpansionContext, abstraction, + substType); } }; @@ -2687,8 +2751,9 @@ SILType SILType::subst(TypeConverter &tc, TypeSubstitutionFn subs, if (!genericSig) genericSig = tc.getCurGenericContext(); - SILTypeSubstituter STST(tc, subs, conformances, - genericSig, shouldSubstituteOpaqueArchetypes); + SILTypeSubstituter STST(tc, TypeExpansionContext::minimal(), subs, + conformances, genericSig, + shouldSubstituteOpaqueArchetypes); return STST.subst(*this); } @@ -2712,8 +2777,8 @@ SILType SILType::subst(SILModule &M, SubstitutionMap subs) const{ /// it has the form of the normal SILFunctionType for the substituted /// type, except using the original conventions. CanSILFunctionType -SILFunctionType::substGenericArgs(SILModule &silModule, - SubstitutionMap subs) { +SILFunctionType::substGenericArgs(SILModule &silModule, SubstitutionMap subs, + TypeExpansionContext context) { if (!isPolymorphic()) { return CanSILFunctionType(this); } @@ -2724,20 +2789,49 @@ SILFunctionType::substGenericArgs(SILModule &silModule, return substGenericArgs(silModule, QuerySubstitutionMap{subs}, - LookUpConformanceInSubstitutionMap(subs)); + LookUpConformanceInSubstitutionMap(subs), + context); } CanSILFunctionType SILFunctionType::substGenericArgs(SILModule &silModule, TypeSubstitutionFn subs, - LookupConformanceFn conformances) { + LookupConformanceFn conformances, + TypeExpansionContext context) { if (!isPolymorphic()) return CanSILFunctionType(this); - SILTypeSubstituter substituter(silModule.Types, subs, conformances, + SILTypeSubstituter substituter(silModule.Types, context, subs, conformances, getSubstGenericSignature(), /*shouldSubstituteOpaqueTypes*/ false); return substituter.substSILFunctionType(CanSILFunctionType(this)); } +CanSILFunctionType +SILFunctionType::substituteOpaqueArchetypes(TypeConverter &TC, + TypeExpansionContext context) { + if (!hasOpaqueArchetype() || + !context.shouldLookThroughOpaqueTypeArchetypes()) + return CanSILFunctionType(this); + + ReplaceOpaqueTypesWithUnderlyingTypes replacer( + context.getContext(), context.getResilienceExpansion(), + context.isWholeModuleContext()); + + assert(!(getSubstGenericSignature() && TC.getCurGenericContext())); + + auto genericSig = getSubstGenericSignature(); + GenericContextScope genericContext(TC, genericSig); + if (!genericSig) { + genericSig = TC.getCurGenericContext(); + } + + SILTypeSubstituter substituter(TC, context, replacer, replacer, genericSig, + /*shouldSubstituteOpaqueTypes*/ true); + auto resTy = + substituter.substSILFunctionType(CanSILFunctionType(this)); + + return resTy; +} + /// Fast path for bridging types in a function type without uncurrying. CanAnyFunctionType TypeConverter::getBridgedFunctionType(AbstractionPattern pattern, @@ -3009,7 +3103,8 @@ static bool areABICompatibleParamsOrReturns(SILType a, SILType b, if (!dc || !dc->isChildContextOf(currentModule)) dc = currentModule; ReplaceOpaqueTypesWithUnderlyingTypes replacer( - dc, inFunction->getResilienceExpansion()); + dc, inFunction->getResilienceExpansion(), + inFunction->getModule().isWholeModule()); if (aa.getASTType()->hasOpaqueArchetype()) opaqueTypesSubsituted = aa.subst(inFunction->getModule(), replacer, replacer, CanGenericSignature(), true); @@ -3205,3 +3300,26 @@ SILFunctionType::withSubstitutions(SubstitutionMap subs) const { subs, isGenericSignatureImplied(), const_cast(this)->getASTContext()); } + +static DeclContext *getDeclContextForExpansion(const SILFunction &f) { + auto *dc = f.getDeclContext(); + if (!dc) + dc = f.getModule().getSwiftModule(); + auto *currentModule = f.getModule().getSwiftModule(); + if (!dc || !dc->isChildContextOf(currentModule)) + dc = currentModule; + return dc; +} + +TypeExpansionContext::TypeExpansionContext(const SILFunction &f) + : expansion(f.getResilienceExpansion()), + inContext(getDeclContextForExpansion(f)), + isContextWholeModule(f.getModule().isWholeModule()) {} + +CanSILFunctionType SILFunction::getLoweredFunctionTypeInContext( + TypeExpansionContext context) const { + auto origFunTy = getLoweredFunctionType(); + auto &M = getModule(); + auto funTy = M.Types.getLoweredType(origFunTy , context); + return cast(funTy.getASTType()); +} diff --git a/lib/SIL/SILGlobalVariable.cpp b/lib/SIL/SILGlobalVariable.cpp index 48d66dd76e3de..733ad528dcd52 100644 --- a/lib/SIL/SILGlobalVariable.cpp +++ b/lib/SIL/SILGlobalVariable.cpp @@ -310,3 +310,14 @@ swift::getVariableOfStaticInitializer(SILFunction *InitFunc, return nullptr; return GVar; } + +SILType +SILGlobalVariable::getLoweredTypeInContext(TypeExpansionContext context) const { + auto ty = getLoweredType(); + if (!ty.getASTType()->hasOpaqueArchetype() || + !context.shouldLookThroughOpaqueTypeArchetypes()) + return ty; + auto resultTy = + getModule().Types.getTypeLowering(ty, context).getLoweredType(); + return resultTy.getCategoryType(ty.getCategory()); +} diff --git a/lib/SIL/SILInstructions.cpp b/lib/SIL/SILInstructions.cpp index 49e627dd18fd2..31e17ef61c79c 100644 --- a/lib/SIL/SILInstructions.cpp +++ b/lib/SIL/SILInstructions.cpp @@ -285,7 +285,9 @@ AllocBoxInst *AllocBoxInst::create(SILDebugLocation Loc, } SILType AllocBoxInst::getAddressType() const { - return getSILBoxFieldType(getBoxType(), getModule().Types, 0).getAddressType(); + return getSILBoxFieldType(TypeExpansionContext(*this->getFunction()), + getBoxType(), getModule().Types, 0) + .getAddressType(); } VarDecl *AllocBoxInst::getDecl() const { @@ -416,8 +418,8 @@ ApplyInst::create(SILDebugLocation Loc, SILValue Callee, SubstitutionMap Subs, Optional ModuleConventions, SILFunction &F, SILOpenedArchetypesState &OpenedArchetypes, const GenericSpecializationInformation *SpecializationInfo) { - SILType SubstCalleeSILTy = - Callee->getType().substGenericArgs(F.getModule(), Subs); + SILType SubstCalleeSILTy = Callee->getType().substGenericArgs( + F.getModule(), Subs, F.getTypeExpansionContext()); auto SubstCalleeTy = SubstCalleeSILTy.getAs(); SILFunctionConventions Conv(SubstCalleeTy, ModuleConventions.hasValue() @@ -462,8 +464,8 @@ BeginApplyInst::create(SILDebugLocation loc, SILValue callee, SILFunction &F, SILOpenedArchetypesState &openedArchetypes, const GenericSpecializationInformation *specializationInfo) { - SILType substCalleeSILType = - callee->getType().substGenericArgs(F.getModule(), subs); + SILType substCalleeSILType = callee->getType().substGenericArgs( + F.getModule(), subs, F.getTypeExpansionContext()); auto substCalleeType = substCalleeSILType.castTo(); SILFunctionConventions conv(substCalleeType, @@ -553,10 +555,11 @@ PartialApplyInst *PartialApplyInst::create( SILOpenedArchetypesState &OpenedArchetypes, const GenericSpecializationInformation *SpecializationInfo, OnStackKind onStack) { - SILType SubstCalleeTy = - Callee->getType().substGenericArgs(F.getModule(), Subs); + SILType SubstCalleeTy = Callee->getType().substGenericArgs( + F.getModule(), Subs, F.getTypeExpansionContext()); SILType ClosureType = SILBuilder::getPartialApplyResultType( - SubstCalleeTy, Args.size(), F.getModule(), {}, CalleeConvention, onStack); + F.getTypeExpansionContext(), SubstCalleeTy, Args.size(), F.getModule(), {}, + CalleeConvention, onStack); SmallVector TypeDependentOperands; collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F, @@ -591,8 +594,8 @@ TryApplyInst *TryApplyInst::create( ArrayRef args, SILBasicBlock *normalBB, SILBasicBlock *errorBB, SILFunction &F, SILOpenedArchetypesState &openedArchetypes, const GenericSpecializationInformation *specializationInfo) { - SILType substCalleeTy = - callee->getType().substGenericArgs(F.getModule(), subs); + SILType substCalleeTy = callee->getType().substGenericArgs( + F.getModule(), subs, F.getTypeExpansionContext()); SmallVector typeDependentOperands; collectTypeDependentOperands(typeDependentOperands, openedArchetypes, F, @@ -608,8 +611,9 @@ TryApplyInst *TryApplyInst::create( FunctionRefBaseInst::FunctionRefBaseInst(SILInstructionKind Kind, SILDebugLocation DebugLoc, - SILFunction *F) - : LiteralInst(Kind, DebugLoc, F->getLoweredType()), f(F) { + SILFunction *F, + TypeExpansionContext context) + : LiteralInst(Kind, DebugLoc, F->getLoweredTypeInContext(context)), f(F) { F->incrementRefCount(); } @@ -624,21 +628,25 @@ FunctionRefBaseInst::~FunctionRefBaseInst() { getInitiallyReferencedFunction()->decrementRefCount(); } -FunctionRefInst::FunctionRefInst(SILDebugLocation Loc, SILFunction *F) - : FunctionRefBaseInst(SILInstructionKind::FunctionRefInst, Loc, F) { +FunctionRefInst::FunctionRefInst(SILDebugLocation Loc, SILFunction *F, + TypeExpansionContext context) + : FunctionRefBaseInst(SILInstructionKind::FunctionRefInst, Loc, F, + context) { assert(!F->isDynamicallyReplaceable()); } DynamicFunctionRefInst::DynamicFunctionRefInst(SILDebugLocation Loc, - SILFunction *F) - : FunctionRefBaseInst(SILInstructionKind::DynamicFunctionRefInst, Loc, F) { + SILFunction *F, + TypeExpansionContext context) + : FunctionRefBaseInst(SILInstructionKind::DynamicFunctionRefInst, Loc, F, + context) { assert(F->isDynamicallyReplaceable()); } PreviousDynamicFunctionRefInst::PreviousDynamicFunctionRefInst( - SILDebugLocation Loc, SILFunction *F) + SILDebugLocation Loc, SILFunction *F, TypeExpansionContext context) : FunctionRefBaseInst(SILInstructionKind::PreviousDynamicFunctionRefInst, - Loc, F) { + Loc, F, context) { assert(!F->isDynamicallyReplaceable()); } @@ -648,16 +656,19 @@ AllocGlobalInst::AllocGlobalInst(SILDebugLocation Loc, Global(Global) {} GlobalAddrInst::GlobalAddrInst(SILDebugLocation DebugLoc, - SILGlobalVariable *Global) - : InstructionBase(DebugLoc, Global->getLoweredType().getAddressType(), + SILGlobalVariable *Global, + TypeExpansionContext context) + : InstructionBase(DebugLoc, + Global->getLoweredTypeInContext(context).getAddressType(), Global) {} GlobalValueInst::GlobalValueInst(SILDebugLocation DebugLoc, - SILGlobalVariable *Global) - : InstructionBase(DebugLoc, Global->getLoweredType().getObjectType(), + SILGlobalVariable *Global, + TypeExpansionContext context) + : InstructionBase(DebugLoc, + Global->getLoweredTypeInContext(context).getObjectType(), Global) {} - const IntrinsicInfo &BuiltinInst::getIntrinsicInfo() const { return getModule().getIntrinsicInfo(getName()); } @@ -1087,7 +1098,8 @@ bool StructExtractInst::isTrivialFieldOfOneRCIDStruct() const { // Otherwise check if we have a non-trivial type. If we don't have one, // continue. - if (StructTy.getFieldType(D, F->getModule()).isTrivial(*F)) + if (StructTy.getFieldType(D, F->getModule(), TypeExpansionContext(*F)) + .isTrivial(*F)) continue; // Ok, this type is non-trivial. If we have not seen a non-trivial field @@ -1132,7 +1144,8 @@ bool StructExtractInst::isFieldOnlyNonTrivialField() const { // Ok, we have a field that is not equal to the field we are // extracting. If that field is trivial, we do not care about // it... continue. - if (StructTy.getFieldType(D, F->getModule()).isTrivial(*F)) + if (StructTy.getFieldType(D, F->getModule(), TypeExpansionContext(*F)) + .isTrivial(*F)) continue; // We have found a non trivial member that is not the member we are @@ -2450,11 +2463,12 @@ static void computeAggregateFirstLevelSubtypeInfo( // TODO: Create an iterator for accessing first level projections to eliminate // this SmallVector. llvm::SmallVector Projections; - Projection::getFirstLevelProjections(OpType, M, Projections); + Projection::getFirstLevelProjections(OpType, M, F.getTypeExpansionContext(), + Projections); auto OpOwnershipKind = Operand.getOwnershipKind(); for (auto &P : Projections) { - SILType ProjType = P.getType(OpType, M); + SILType ProjType = P.getType(OpType, M, F.getTypeExpansionContext()); Types.emplace_back(ProjType); OwnershipKinds.emplace_back( OpOwnershipKind.getProjectedOwnershipKind(F, ProjType)); diff --git a/lib/SIL/SILType.cpp b/lib/SIL/SILType.cpp index 3b89dbc7852e9..60eceb46c333b 100644 --- a/lib/SIL/SILType.cpp +++ b/lib/SIL/SILType.cpp @@ -86,7 +86,7 @@ bool SILType::isTrivial(const SILFunction &F) const { bool SILType::isReferenceCounted(SILModule &M) const { return M.Types.getTypeLowering(*this, - ResilienceExpansion::Minimal) + TypeExpansionContext::minimal()) .isReferenceCounted(); } @@ -133,8 +133,8 @@ bool SILType::canRefCast(SILType operTy, SILType resultTy, SILModule &M) { && toTy.isHeapObjectReferenceType(); } -SILType SILType::getFieldType(VarDecl *field, - TypeConverter &TC) const { +SILType SILType::getFieldType(VarDecl *field, TypeConverter &TC, + TypeExpansionContext context) const { AbstractionPattern origFieldTy = TC.getAbstractionPattern(field); CanType substFieldTy; if (field->hasClangNode()) { @@ -144,7 +144,8 @@ SILType SILType::getFieldType(VarDecl *field, getASTType()->getTypeOfMember(&TC.M, field, nullptr)->getCanonicalType(); } - auto loweredTy = TC.getLoweredRValueType(origFieldTy, substFieldTy); + auto loweredTy = + TC.getLoweredRValueType(context, origFieldTy, substFieldTy); if (isAddress() || getClassOrBoundGenericClass() != nullptr) { return SILType::getPrimitiveAddressType(loweredTy); } else { @@ -152,12 +153,13 @@ SILType SILType::getFieldType(VarDecl *field, } } -SILType SILType::getFieldType(VarDecl *field, SILModule &M) const { - return getFieldType(field, M.Types); +SILType SILType::getFieldType(VarDecl *field, SILModule &M, + TypeExpansionContext context) const { + return getFieldType(field, M.Types, context); } -SILType SILType::getEnumElementType(EnumElementDecl *elt, - TypeConverter &TC) const { +SILType SILType::getEnumElementType(EnumElementDecl *elt, TypeConverter &TC, + TypeExpansionContext context) const { assert(elt->getDeclContext() == getEnumOrBoundGenericEnum()); assert(elt->hasAssociatedValues()); @@ -168,7 +170,7 @@ SILType SILType::getEnumElementType(EnumElementDecl *elt, // If the case is indirect, then the payload is boxed. if (elt->isIndirect() || elt->getParentEnum()->isIndirect()) { - auto box = TC.getBoxTypeForEnumElement(*this, elt); + auto box = TC.getBoxTypeForEnumElement(context, *this, elt); return SILType(SILType::getPrimitiveObjectType(box).getASTType(), getCategory()); } @@ -176,15 +178,15 @@ SILType SILType::getEnumElementType(EnumElementDecl *elt, auto substEltTy = getASTType()->getTypeOfMember(&TC.M, elt, elt->getArgumentInterfaceType()); - auto loweredTy = - TC.getLoweredRValueType(TC.getAbstractionPattern(elt), - substEltTy); + auto loweredTy = TC.getLoweredRValueType( + context, TC.getAbstractionPattern(elt), substEltTy); return SILType(loweredTy, getCategory()); } -SILType SILType::getEnumElementType(EnumElementDecl *elt, SILModule &M) const { - return getEnumElementType(elt, M.Types); +SILType SILType::getEnumElementType(EnumElementDecl *elt, SILModule &M, + TypeExpansionContext context) const { + return getEnumElementType(elt, M.Types, context); } bool SILType::isLoadableOrOpaque(const SILFunction &F) const { @@ -196,10 +198,10 @@ bool SILType::isAddressOnly(const SILFunction &F) const { return F.getTypeLowering(*this).isAddressOnly(); } -SILType SILType::substGenericArgs(SILModule &M, - SubstitutionMap SubMap) const { +SILType SILType::substGenericArgs(SILModule &M, SubstitutionMap SubMap, + TypeExpansionContext context) const { auto fnTy = castTo(); - auto canFnTy = CanSILFunctionType(fnTy->substGenericArgs(M, SubMap)); + auto canFnTy = CanSILFunctionType(fnTy->substGenericArgs(M, SubMap, context)); return SILType::getPrimitiveObjectType(canFnTy); } @@ -217,7 +219,8 @@ bool SILType::isHeapObjectReferenceType() const { return false; } -bool SILType::aggregateContainsRecord(SILType Record, SILModule &Mod) const { +bool SILType::aggregateContainsRecord(SILType Record, SILModule &Mod, + TypeExpansionContext context) const { assert(!hasArchetype() && "Agg should be proven to not be generic " "before passed to this function."); assert(!Record.hasArchetype() && "Record should be proven to not be generic " @@ -246,14 +249,14 @@ bool SILType::aggregateContainsRecord(SILType Record, SILModule &Mod) const { if (EnumDecl *E = Ty.getEnumOrBoundGenericEnum()) { for (auto Elt : E->getAllElements()) if (Elt->hasAssociatedValues()) - Worklist.push_back(Ty.getEnumElementType(Elt, Mod)); + Worklist.push_back(Ty.getEnumElementType(Elt, Mod, context)); continue; } // Then if we have a struct address... if (StructDecl *S = Ty.getStructOrBoundGenericStruct()) for (VarDecl *Var : S->getStoredProperties()) - Worklist.push_back(Ty.getFieldType(Var, Mod)); + Worklist.push_back(Ty.getFieldType(Var, Mod, context)); // If we have a class address, it is a pointer so it cannot contain other // types. @@ -387,21 +390,22 @@ SILType SILType::mapTypeOutOfContext() const { getCategory()); } -CanType -swift::getSILBoxFieldLoweredType(SILBoxType *type, TypeConverter &TC, - unsigned index) { +CanType swift::getSILBoxFieldLoweredType(TypeExpansionContext context, + SILBoxType *type, TypeConverter &TC, + unsigned index) { auto fieldTy = type->getLayout()->getFields()[index].getLoweredType(); // Apply generic arguments if the layout is generic. if (auto subMap = type->getSubstitutions()) { auto sig = type->getLayout()->getGenericSignature(); - return SILType::getPrimitiveObjectType(fieldTy) + fieldTy = SILType::getPrimitiveObjectType(fieldTy) .subst(TC, QuerySubstitutionMap{subMap}, LookUpConformanceInSubstitutionMap(subMap), sig) .getASTType(); } + fieldTy = TC.getLoweredType(fieldTy, context).getASTType(); return fieldTy; } @@ -440,9 +444,8 @@ SILModuleConventions::SILModuleConventions(SILModule &M) bool SILModuleConventions::isReturnedIndirectlyInSIL(SILType type, SILModule &M) { if (SILModuleConventions(M).loweredAddresses) { - return M.Types.getTypeLowering(type, - ResilienceExpansion::Minimal) - .isAddressOnly(); + return M.Types.getTypeLowering(type, TypeExpansionContext::minimal()) + .isAddressOnly(); } return false; @@ -450,9 +453,8 @@ bool SILModuleConventions::isReturnedIndirectlyInSIL(SILType type, bool SILModuleConventions::isPassedIndirectlyInSIL(SILType type, SILModule &M) { if (SILModuleConventions(M).loweredAddresses) { - return M.Types.getTypeLowering(type, - ResilienceExpansion::Minimal) - .isAddressOnly(); + return M.Types.getTypeLowering(type, TypeExpansionContext::minimal()) + .isAddressOnly(); } return false; @@ -546,8 +548,14 @@ bool SILType::hasAbstractionDifference(SILFunctionTypeRepresentation rep, return (*this != type2); } -bool SILType::isLoweringOf(SILModule &Mod, CanType formalType) { +bool SILType::isLoweringOf(TypeExpansionContext context, SILModule &Mod, + CanType formalType) { SILType loweredType = *this; + if (formalType->hasOpaqueArchetype() && + context.shouldLookThroughOpaqueTypeArchetypes() && + loweredType.getASTType() == + Mod.Types.getLoweredRValueType(context, formalType)) + return true; // Optional lowers its contained type. SILType loweredObjectType = loweredType.getOptionalObjectType(); @@ -555,7 +563,7 @@ bool SILType::isLoweringOf(SILModule &Mod, CanType formalType) { if (loweredObjectType) { return formalObjectType && - loweredObjectType.isLoweringOf(Mod, formalObjectType); + loweredObjectType.isLoweringOf(context, Mod, formalObjectType); } // Metatypes preserve their instance type through lowering. @@ -586,7 +594,8 @@ bool SILType::isLoweringOf(SILModule &Mod, CanType formalType) { for (unsigned i = 0, e = loweredTT->getNumElements(); i < e; ++i) { auto loweredTTEltType = SILType::getPrimitiveAddressType(loweredTT.getElementType(i)); - if (!loweredTTEltType.isLoweringOf(Mod, formalTT.getElementType(i))) + if (!loweredTTEltType.isLoweringOf(context, Mod, + formalTT.getElementType(i))) return false; } return true; diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp index 610649ac1c1b3..7aafd4d378133 100644 --- a/lib/SIL/SILVerifier.cpp +++ b/lib/SIL/SILVerifier.cpp @@ -134,14 +134,15 @@ void verifyKeyPathComponent(SILModule &M, bool forPropertyDescriptor, bool hasIndices) { auto &C = M.getASTContext(); - + auto typeExpansionContext = + TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(expansion); auto opaque = AbstractionPattern::getOpaque(); auto loweredBaseTy = - M.Types.getLoweredType(opaque, baseTy, expansion); + M.Types.getLoweredType(opaque, baseTy, typeExpansionContext); auto componentTy = component.getComponentType().subst(patternSubs) ->getCanonicalType(); auto loweredComponentTy = - M.Types.getLoweredType(opaque, componentTy, expansion); + M.Types.getLoweredType(opaque, componentTy, typeExpansionContext); auto checkIndexEqualsAndHash = [&]{ if (!component.getSubscriptIndices().empty()) { @@ -153,7 +154,7 @@ void verifyKeyPathComponent(SILModule &M, "operator"); auto substEqualsType = equals->getLoweredFunctionType() - ->substGenericArgs(M, patternSubs); + ->substGenericArgs(M, patternSubs, TypeExpansionContext::minimal()); require(substEqualsType->getParameters().size() == 2, "must have two arguments"); @@ -186,7 +187,7 @@ void verifyKeyPathComponent(SILModule &M, "operator"); auto substHashType = hash->getLoweredFunctionType() - ->substGenericArgs(M, patternSubs); + ->substGenericArgs(M, patternSubs, TypeExpansionContext::minimal()); require(substHashType->getParameters().size() == 1, "must have two arguments"); @@ -234,7 +235,8 @@ void verifyKeyPathComponent(SILModule &M, require(property->hasStorage(), "property must be stored"); require(!property->isResilient(M.getSwiftModule(), expansion), "cannot access storage of resilient property"); - auto propertyTy = loweredBaseTy.getFieldType(property, M); + auto propertyTy = + loweredBaseTy.getFieldType(property, M, typeExpansionContext); require(propertyTy.getObjectType() == loweredComponentTy.getObjectType(), "component type should match the maximal abstraction of the " @@ -269,8 +271,8 @@ void verifyKeyPathComponent(SILModule &M, "less visible getters"); } - auto substGetterType = getter->getLoweredFunctionType() - ->substGenericArgs(M, patternSubs); + auto substGetterType = getter->getLoweredFunctionType()->substGenericArgs( + M, patternSubs, TypeExpansionContext::minimal()); require(substGetterType->getRepresentation() == SILFunctionTypeRepresentation::Thin, "getter should be a thin function"); @@ -317,7 +319,7 @@ void verifyKeyPathComponent(SILModule &M, } auto substSetterType = setter->getLoweredFunctionType() - ->substGenericArgs(M, patternSubs); + ->substGenericArgs(M, patternSubs, TypeExpansionContext::minimal()); require(substSetterType->getRepresentation() == SILFunctionTypeRepresentation::Thin, @@ -366,8 +368,9 @@ void verifyKeyPathComponent(SILModule &M, require(contextType == operands[opIndex].get()->getType(), "operand must match type required by pattern"); SILType loweredType = index.LoweredType; - require(loweredType.isLoweringOf(M, index.FormalType), - "pattern index formal type doesn't match lowered type"); + require( + loweredType.isLoweringOf(typeExpansionContext, M, index.FormalType), + "pattern index formal type doesn't match lowered type"); } checkIndexEqualsAndHash(); @@ -1301,7 +1304,7 @@ class SILVerifier : public SILVerifierBase { } // Apply the substitutions. - return fnTy->substGenericArgs(F.getModule(), subs); + return fnTy->substGenericArgs(F.getModule(), subs, F.getTypeExpansionContext()); } /// Check that for each opened archetype or dynamic self type in substitutions @@ -1743,7 +1746,8 @@ class SILVerifier : public SILVerifierBase { void checkGlobalAccessInst(GlobalAccessInst *GAI) { SILGlobalVariable *RefG = GAI->getReferencedGlobal(); - require(GAI->getType().getObjectType() == RefG->getLoweredType(), + require(GAI->getType().getObjectType() == + RefG->getLoweredTypeInContext(F.getTypeExpansionContext()), "global_addr/value must be the type of the variable it references"); if (auto *VD = RefG->getDecl()) { require(!VD->isResilient(F.getModule().getSwiftModule(), @@ -2324,7 +2328,8 @@ class SILVerifier : public SILVerifierBase { "project_box operand should be a value"); auto boxTy = I->getOperand()->getType().getAs(); require(boxTy, "project_box operand should be a @box type"); - require(I->getType() == getSILBoxFieldType(boxTy, F.getModule().Types, + require(I->getType() == getSILBoxFieldType(F.getTypeExpansionContext(), boxTy, + F.getModule().Types, I->getFieldIndex()), "project_box result should be address of boxed type"); @@ -2393,7 +2398,8 @@ class SILVerifier : public SILVerifierBase { "number of struct operands does not match number of stored " "member variables of struct"); - SILType loweredType = structTy.getFieldType(field, F.getModule()); + SILType loweredType = + structTy.getFieldType(field, F.getModule(), F.getTypeExpansionContext()); if (SI->getModule().getStage() != SILStage::Lowered) { require((*opi)->getType() == loweredType, "struct operand type does not match field type"); @@ -2415,8 +2421,8 @@ class SILVerifier : public SILVerifierBase { if (UI->getElement()->hasAssociatedValues()) { require(UI->getOperand()->getType().isObject(), "EnumInst operand must be an object"); - SILType caseTy = UI->getType().getEnumElementType(UI->getElement(), - F.getModule()); + SILType caseTy = UI->getType().getEnumElementType( + UI->getElement(), F.getModule(), F.getTypeExpansionContext()); if (UI->getModule().getStage() != SILStage::Lowered) { require(caseTy == UI->getOperand()->getType(), "EnumInst operand type does not match type of case"); @@ -2436,9 +2442,8 @@ class SILVerifier : public SILVerifierBase { require(UI->getType().isAddress(), "InitEnumDataAddrInst must produce an address"); - SILType caseTy = - UI->getOperand()->getType().getEnumElementType(UI->getElement(), - F.getModule()); + SILType caseTy = UI->getOperand()->getType().getEnumElementType( + UI->getElement(), F.getModule(), F.getTypeExpansionContext()); if (UI->getModule().getStage() != SILStage::Lowered) { requireSameType( @@ -2459,9 +2464,8 @@ class SILVerifier : public SILVerifierBase { require(UI->getType().isObject(), "UncheckedEnumData must produce an address"); - SILType caseTy = - UI->getOperand()->getType().getEnumElementType(UI->getElement(), - F.getModule()); + SILType caseTy = UI->getOperand()->getType().getEnumElementType( + UI->getElement(), F.getModule(), F.getTypeExpansionContext()); if (UI->getModule().getStage() != SILStage::Lowered) { require(caseTy == UI->getType(), @@ -2481,9 +2485,8 @@ class SILVerifier : public SILVerifierBase { require(UI->getType().isAddress(), "UncheckedTakeEnumDataAddrInst must produce an address"); - SILType caseTy = - UI->getOperand()->getType().getEnumElementType(UI->getElement(), - F.getModule()); + SILType caseTy = UI->getOperand()->getType().getEnumElementType( + UI->getElement(), F.getModule(), F.getTypeExpansionContext()); if (UI->getModule().getStage() != SILStage::Lowered) { require(caseTy == UI->getType(), "UncheckedTakeEnumDataAddrInst result " @@ -2519,7 +2522,8 @@ class SILVerifier : public SILVerifierBase { // Is a SIL type a potential lowering of a formal type? bool isLoweringOf(SILType loweredType, CanType formalType) { - return loweredType.isLoweringOf(F.getModule(), formalType); + return loweredType.isLoweringOf(F.getTypeExpansionContext(), F.getModule(), + formalType); } void checkMetatypeInst(MetatypeInst *MI) { @@ -2609,9 +2613,9 @@ class SILVerifier : public SILVerifierBase { require(AI->getType().isObject(), "result of alloc_box must be an object"); for (unsigned field : indices(AI->getBoxType()->getLayout()->getFields())) { - verifyOpenedArchetype(AI, - getSILBoxFieldLoweredType(AI->getBoxType(), F.getModule().Types, - field)); + verifyOpenedArchetype(AI, getSILBoxFieldLoweredType( + F.getTypeExpansionContext(), AI->getBoxType(), + F.getModule().Types, field)); } // An alloc_box with a mark_uninitialized user can not have any other users. @@ -2705,8 +2709,8 @@ class SILVerifier : public SILVerifierBase { "struct_extract field is not a member of the struct"); if (EI->getModule().getStage() != SILStage::Lowered) { - SILType loweredFieldTy = - operandTy.getFieldType(EI->getField(), F.getModule()); + SILType loweredFieldTy = operandTy.getFieldType( + EI->getField(), F.getModule(), F.getTypeExpansionContext()); require(loweredFieldTy == EI->getType(), "result of struct_extract does not match type of field"); } @@ -2751,8 +2755,8 @@ class SILVerifier : public SILVerifierBase { "struct_element_addr field is not a member of the struct"); if (EI->getModule().getStage() != SILStage::Lowered) { - SILType loweredFieldTy = - operandTy.getFieldType(EI->getField(), F.getModule()); + SILType loweredFieldTy = operandTy.getFieldType( + EI->getField(), F.getModule(), F.getTypeExpansionContext()); require(loweredFieldTy == EI->getType(), "result of struct_element_addr does not match type of field"); } @@ -2777,8 +2781,8 @@ class SILVerifier : public SILVerifierBase { "ref_element_addr field must be a member of the class"); if (EI->getModule().getStage() != SILStage::Lowered) { - SILType loweredFieldTy = - operandTy.getFieldType(EI->getField(), F.getModule()); + SILType loweredFieldTy = operandTy.getFieldType( + EI->getField(), F.getModule(), F.getTypeExpansionContext()); require(loweredFieldTy == EI->getType(), "result of ref_element_addr does not match type of field"); } @@ -2876,7 +2880,8 @@ class SILVerifier : public SILVerifierBase { // The type of the dynamic method must match the usual type of the method, // but with the more opaque Self type. - auto constantInfo = F.getModule().Types.getConstantInfo(method); + auto constantInfo = + F.getModule().Types.getConstantInfo(F.getTypeExpansionContext(), method); auto methodTy = constantInfo.SILFnType; assert(!methodTy->isCoroutine()); @@ -2884,7 +2889,8 @@ class SILVerifier : public SILVerifierBase { // Map interface types to archetypes. if (auto *env = F.getModule().Types.getConstantGenericEnvironment(method)) { auto subs = env->getForwardingSubstitutionMap(); - methodTy = methodTy->substGenericArgs(F.getModule(), subs); + methodTy = methodTy->substGenericArgs(F.getModule(), subs, + F.getTypeExpansionContext()); } assert(!methodTy->isPolymorphic()); @@ -2954,7 +2960,8 @@ class SILVerifier : public SILVerifierBase { void checkClassMethodInst(ClassMethodInst *CMI) { auto member = CMI->getMember(); - auto overrideTy = TC.getConstantOverrideType(member); + auto overrideTy = + TC.getConstantOverrideType(F.getTypeExpansionContext(), member); if (CMI->getModule().getStage() != SILStage::Lowered) { requireSameType( CMI->getType(), SILType::getPrimitiveObjectType(overrideTy), @@ -2982,7 +2989,8 @@ class SILVerifier : public SILVerifierBase { void checkSuperMethodInst(SuperMethodInst *CMI) { auto member = CMI->getMember(); - auto overrideTy = TC.getConstantOverrideType(member); + auto overrideTy = + TC.getConstantOverrideType(F.getTypeExpansionContext(), member); if (CMI->getModule().getStage() != SILStage::Lowered) { requireSameType( CMI->getType(), SILType::getPrimitiveObjectType(overrideTy), @@ -3033,7 +3041,8 @@ class SILVerifier : public SILVerifierBase { operandInstanceType = metatypeType.getInstanceType(); if (operandInstanceType.getClassOrBoundGenericClass()) { - auto overrideTy = TC.getConstantOverrideType(member); + auto overrideTy = + TC.getConstantOverrideType(F.getTypeExpansionContext(), member); requireSameType( OMI->getType(), SILType::getPrimitiveObjectType(overrideTy), "result type of objc_method must match abstracted type of method"); @@ -3058,7 +3067,8 @@ class SILVerifier : public SILVerifierBase { void checkObjCSuperMethodInst(ObjCSuperMethodInst *OMI) { auto member = OMI->getMember(); - auto overrideTy = TC.getConstantOverrideType(member); + auto overrideTy = + TC.getConstantOverrideType(F.getTypeExpansionContext(), member); if (OMI->getModule().getStage() != SILStage::Lowered) { requireSameType( OMI->getType(), SILType::getPrimitiveObjectType(overrideTy), @@ -3901,7 +3911,9 @@ class SILVerifier : public SILVerifierBase { LLVM_DEBUG(RI->print(llvm::dbgs())); SILType functionResultType = - F.mapTypeIntoContext(fnConv.getSILResultType()); + F.getLoweredType( + F.mapTypeIntoContext(fnConv.getSILResultType()).getASTType()) + .getCategoryType(fnConv.getSILResultType().getCategory()); SILType instResultType = RI->getOperand()->getType(); LLVM_DEBUG(llvm::dbgs() << "function return type: "; functionResultType.dump(); @@ -3914,11 +3926,15 @@ class SILVerifier : public SILVerifierBase { void checkThrowInst(ThrowInst *TI) { LLVM_DEBUG(TI->print(llvm::dbgs())); - CanSILFunctionType fnType = F.getLoweredFunctionType(); + CanSILFunctionType fnType = + F.getLoweredFunctionTypeInContext(F.getTypeExpansionContext()); require(fnType->hasErrorResult(), "throw in function that doesn't have an error result"); - SILType functionResultType = F.mapTypeIntoContext(fnConv.getSILErrorType()); + SILType functionResultType = + F.getLoweredType( + F.mapTypeIntoContext(fnConv.getSILErrorType()).getASTType()) + .getCategoryType(fnConv.getSILErrorType().getCategory()); SILType instResultType = TI->getOperand()->getType(); LLVM_DEBUG(llvm::dbgs() << "function error result type: "; functionResultType.dump(); @@ -3934,7 +3950,8 @@ class SILVerifier : public SILVerifierBase { } void checkYieldInst(YieldInst *YI) { - CanSILFunctionType fnType = F.getLoweredFunctionType(); + CanSILFunctionType fnType = + F.getLoweredFunctionTypeInContext(F.getTypeExpansionContext()); require(fnType->isCoroutine(), "yield in non-coroutine function"); @@ -4134,7 +4151,8 @@ class SILVerifier : public SILVerifierBase { } if (dest->getArguments().size() == 1) { - SILType eltArgTy = uTy.getEnumElementType(elt, F.getModule()); + SILType eltArgTy = uTy.getEnumElementType(elt, F.getModule(), + F.getTypeExpansionContext()); SILType bbArgTy = dest->getArguments()[0]->getType(); if (F.getModule().getStage() != SILStage::Lowered) { // During the lowered stage, a function type might have different @@ -4540,7 +4558,9 @@ class SILVerifier : public SILVerifierBase { auto mappedTy = F.mapTypeIntoContext(ty); SILArgument *bbarg = *argI; ++argI; - if (bbarg->getType() != mappedTy) { + if (bbarg->getType() != mappedTy && + bbarg->getType() != F.getLoweredType(mappedTy.getASTType()) + .getCategoryType(mappedTy.getCategory())) { llvm::errs() << what << " type mismatch!\n"; llvm::errs() << " argument: "; bbarg->dump(); llvm::errs() << " expected: "; mappedTy.dump(); @@ -5145,7 +5165,8 @@ void SILVTable::verify(const SILModule &M) const { for (auto &entry : getEntries()) { // All vtable entries must be decls in a class context. assert(entry.Method.hasDecl() && "vtable entry is not a decl"); - auto baseInfo = M.Types.getConstantInfo(entry.Method); + auto baseInfo = + M.Types.getConstantInfo(TypeExpansionContext::minimal(), entry.Method); ValueDecl *decl = entry.Method.getDecl(); assert((!isa(decl) diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp index 16b373c9e6447..f124d37c7c4bc 100644 --- a/lib/SIL/TypeLowering.cpp +++ b/lib/SIL/TypeLowering.cpp @@ -92,7 +92,7 @@ static bool hasSingletonMetatype(CanType instanceType) { } CaptureKind TypeConverter::getDeclCaptureKind(CapturedValue capture, - ResilienceExpansion expansion) { + TypeExpansionContext expansion) { auto decl = capture.getDecl(); auto *var = cast(decl); assert(var->hasStorage() && @@ -103,7 +103,11 @@ CaptureKind TypeConverter::getDeclCaptureKind(CapturedValue capture, // by its address (like a var) instead. if (!var->supportsMutation() && (Context.LangOpts.EnableSILOpaqueValues || - !getTypeLowering(var->getType(), expansion).isAddressOnly())) + !getTypeLowering( + var->getType(), + TypeExpansionContext::noOpaqueTypeArchetypesSubstitution( + expansion.getResilienceExpansion())) + .isAddressOnly())) return CaptureKind::Constant; // In-out parameters are captured by address. @@ -132,7 +136,7 @@ using RecursiveProperties = TypeLowering::RecursiveProperties; static RecursiveProperties classifyType(CanType type, TypeConverter &TC, CanGenericSignature sig, - ResilienceExpansion expansion); + TypeExpansionContext expansion); namespace { /// A CRTP helper class for doing things that depends on type @@ -143,9 +147,9 @@ namespace { protected: TypeConverter &TC; CanGenericSignature Sig; - ResilienceExpansion Expansion; + TypeExpansionContext Expansion; TypeClassifierBase(TypeConverter &TC, CanGenericSignature Sig, - ResilienceExpansion Expansion) + TypeExpansionContext Expansion) : TC(TC), Sig(Sig), Expansion(Expansion) {} public: @@ -326,7 +330,7 @@ namespace { auto referentType = type->getReferentType(); \ auto concreteType = getConcreteReferenceStorageReferent(referentType); \ if (Name##StorageType::get(concreteType, TC.Context) \ - ->isLoadable(Expansion)) { \ + ->isLoadable(Expansion.getResilienceExpansion())) { \ return asImpl().visitLoadable##Name##StorageType(type); \ } else { \ return asImpl().visitAddressOnly##Name##StorageType(type); \ @@ -338,6 +342,13 @@ namespace { } #include "swift/AST/ReferenceStorage.def" + RetTy visitOpaqueTypeArchetypeType(CanOpaqueTypeArchetypeType ty) { + auto replacedTy = substOpaqueTypesWithUnderlyingTypes(ty, Expansion); + if (replacedTy == ty) + return visitArchetypeType(ty); + return this->visit(replacedTy); + } + RetTy visitArchetypeType(CanArchetypeType type) { if (type->requiresClass()) { return asImpl().handleReference(type); @@ -448,7 +459,7 @@ namespace { public TypeClassifierBase { public: TypeClassifier(TypeConverter &TC, CanGenericSignature Sig, - ResilienceExpansion Expansion) + TypeExpansionContext Expansion) : TypeClassifierBase(TC, Sig, Expansion) {} RecursiveProperties handle(CanType type, RecursiveProperties properties) { @@ -502,7 +513,7 @@ namespace { static RecursiveProperties classifyType(CanType type, TypeConverter &tc, CanGenericSignature sig, - ResilienceExpansion expansion) { + TypeExpansionContext expansion) { return TypeClassifier(tc, sig, expansion).visit(type); } @@ -511,7 +522,7 @@ static RecursiveProperties classifyType(CanType type, TypeConverter &tc, /// something of unknown size. bool SILType::isAddressOnly(CanType type, TypeConverter &tc, CanGenericSignature sig, - ResilienceExpansion expansion) { + TypeExpansionContext expansion) { return classifyType(type, tc, sig, expansion).isAddressOnly(); } @@ -523,7 +534,7 @@ namespace { protected: LoadableTypeLowering(SILType type, RecursiveProperties properties, IsReferenceCounted_t isRefCounted, - ResilienceExpansion forExpansion) + TypeExpansionContext forExpansion) : TypeLowering(type, properties, isRefCounted, forExpansion) {} public: @@ -550,7 +561,7 @@ namespace { class TrivialTypeLowering final : public LoadableTypeLowering { public: TrivialTypeLowering(SILType type, RecursiveProperties properties, - ResilienceExpansion forExpansion) + TypeExpansionContext forExpansion) : LoadableTypeLowering(type, properties, IsNotReferenceCounted, forExpansion) { assert(properties.isFixedABI()); @@ -620,7 +631,7 @@ namespace { NonTrivialLoadableTypeLowering(SILType type, RecursiveProperties properties, IsReferenceCounted_t isRefCounted, - ResilienceExpansion forExpansion) + TypeExpansionContext forExpansion) : LoadableTypeLowering(type, properties, isRefCounted, forExpansion) { assert(!properties.isTrivial()); } @@ -713,7 +724,7 @@ namespace { public: LoadableAggTypeLowering(CanType type, RecursiveProperties properties, - ResilienceExpansion forExpansion) + TypeExpansionContext forExpansion) : NonTrivialLoadableTypeLowering(SILType::getPrimitiveObjectType(type), properties, IsNotReferenceCounted, forExpansion) { @@ -832,7 +843,7 @@ namespace { : public LoadableAggTypeLowering { public: LoadableTupleTypeLowering(CanType type, RecursiveProperties properties, - ResilienceExpansion forExpansion) + TypeExpansionContext forExpansion) : LoadableAggTypeLowering(type, properties, forExpansion) {} SILValue emitRValueProject(SILBuilder &B, SILLocation loc, @@ -857,7 +868,7 @@ namespace { unsigned index = 0; for (auto elt : tupleTy.getElementTypes()) { auto silElt = SILType::getPrimitiveType(elt, silTy.getCategory()); - auto &eltTL = TC.getTypeLowering(silElt, getResilienceExpansion()); + auto &eltTL = TC.getTypeLowering(silElt, getExpansionContext()); children.push_back(Child{index, eltTL}); ++index; } @@ -869,7 +880,7 @@ namespace { : public LoadableAggTypeLowering { public: LoadableStructTypeLowering(CanType type, RecursiveProperties properties, - ResilienceExpansion forExpansion) + TypeExpansionContext forExpansion) : LoadableAggTypeLowering(type, properties, forExpansion) {} SILValue emitRValueProject(SILBuilder &B, SILLocation loc, @@ -892,8 +903,8 @@ namespace { assert(structDecl); for (auto prop : structDecl->getStoredProperties()) { - SILType propTy = silTy.getFieldType(prop, TC); - auto &propTL = TC.getTypeLowering(propTy, getResilienceExpansion()); + SILType propTy = silTy.getFieldType(prop, TC, getExpansionContext()); + auto &propTL = TC.getTypeLowering(propTy, getExpansionContext()); children.push_back(Child{prop, propTL}); } } @@ -903,7 +914,7 @@ namespace { class LoadableEnumTypeLowering final : public NonTrivialLoadableTypeLowering { public: LoadableEnumTypeLowering(CanType type, RecursiveProperties properties, - ResilienceExpansion forExpansion) + TypeExpansionContext forExpansion) : NonTrivialLoadableTypeLowering(SILType::getPrimitiveObjectType(type), properties, IsNotReferenceCounted, @@ -946,7 +957,7 @@ namespace { public: LeafLoadableTypeLowering(SILType type, RecursiveProperties properties, IsReferenceCounted_t isRefCounted, - ResilienceExpansion forExpansion) + TypeExpansionContext forExpansion) : NonTrivialLoadableTypeLowering(type, properties, isRefCounted, forExpansion) {} @@ -966,7 +977,7 @@ namespace { /// loadable. class ReferenceTypeLowering : public LeafLoadableTypeLowering { public: - ReferenceTypeLowering(SILType type, ResilienceExpansion forExpansion) + ReferenceTypeLowering(SILType type, TypeExpansionContext forExpansion) : LeafLoadableTypeLowering(type, RecursiveProperties::forReference(), IsReferenceCounted, forExpansion) {} @@ -998,7 +1009,7 @@ namespace { class Loadable##Name##TypeLowering final : public LeafLoadableTypeLowering { \ public: \ Loadable##Name##TypeLowering(SILType type, \ - ResilienceExpansion forExpansion) \ + TypeExpansionContext forExpansion) \ : LeafLoadableTypeLowering(type, RecursiveProperties::forReference(), \ IsReferenceCounted, \ forExpansion) {} \ @@ -1024,7 +1035,7 @@ namespace { class AddressOnlyTypeLowering : public TypeLowering { public: AddressOnlyTypeLowering(SILType type, RecursiveProperties properties, - ResilienceExpansion forExpansion) + TypeExpansionContext forExpansion) : TypeLowering(type, properties, IsNotReferenceCounted, forExpansion) { assert(properties.isAddressOnly()); @@ -1096,7 +1107,7 @@ namespace { class UnsafeValueBufferTypeLowering : public AddressOnlyTypeLowering { public: UnsafeValueBufferTypeLowering(SILType type, - ResilienceExpansion forExpansion) + TypeExpansionContext forExpansion) : AddressOnlyTypeLowering(type, {IsNotTrivial, IsFixedABI, IsAddressOnly, IsNotResilient}, @@ -1127,7 +1138,7 @@ namespace { class OpaqueValueTypeLowering : public LeafLoadableTypeLowering { public: OpaqueValueTypeLowering(SILType type, RecursiveProperties properties, - ResilienceExpansion forExpansion) + TypeExpansionContext forExpansion) : LeafLoadableTypeLowering(type, properties, IsNotReferenceCounted, forExpansion) {} @@ -1169,7 +1180,7 @@ namespace { IsDependent_t Dependent; public: LowerType(TypeConverter &TC, CanGenericSignature Sig, - ResilienceExpansion Expansion, IsDependent_t Dependent) + TypeExpansionContext Expansion, IsDependent_t Dependent) : TypeClassifierBase(TC, Sig, Expansion), Dependent(Dependent) {} TypeLowering *handleTrivial(CanType type) { @@ -1249,7 +1260,8 @@ namespace { // Note: if the type is in a different module, the lowering does // not depend on the resilience expansion, so we do not need to set // the isResilent() flag above. - if (!sameModule || Expansion == ResilienceExpansion::Minimal) { + if (!sameModule || Expansion.getResilienceExpansion() == + ResilienceExpansion::Minimal) { properties.addSubobject(RecursiveProperties::forOpaque()); return true; } @@ -1379,10 +1391,34 @@ const TypeLowering *TypeConverter::find(TypeKey k) { if (found == types->end()) return nullptr; - assert(found->second && "type recursion not caught in Sema"); + assert((found->second || k.expansionContext.isMinimal()) && + "type recursion not caught in Sema"); return found->second; } +#ifndef NDEBUG +void TypeConverter::removeNullEntry(TypeKey k) { + if (!k.isCacheable()) + return; + + auto ck = k.getCachingKey(); + + llvm::DenseMap *types; + if (k.isDependent()) { + auto &state = DependentTypes.back(); + types = &state.Map; + } else { + types = &IndependentTypes; + } + + auto found = types->find(ck); + if (found == types->end() || found->second != nullptr) + return; + + types->erase(ck); +} +#endif + void TypeConverter::insert(TypeKey k, const TypeLowering *tl) { if (!k.isCacheable()) return; @@ -1393,13 +1429,13 @@ void TypeConverter::insert(TypeKey k, const TypeLowering *tl) { } else { types = &IndependentTypes; } - (*types)[k.getCachingKey()] = tl; } /// Lower each of the elements of the substituted type according to /// the abstraction pattern of the given original type. static CanTupleType computeLoweredTupleType(TypeConverter &tc, + TypeExpansionContext context, AbstractionPattern origType, CanTupleType substType) { assert(origType.matchesTuple(substType)); @@ -1422,7 +1458,7 @@ static CanTupleType computeLoweredTupleType(TypeConverter &tc, assert(!Flags.isVariadic()); CanType loweredSubstEltType = - tc.getLoweredRValueType(origEltType, substEltType); + tc.getLoweredRValueType(context, origEltType, substEltType); changed = (changed || substEltType != loweredSubstEltType || !Flags.isNone()); @@ -1444,14 +1480,14 @@ static CanTupleType computeLoweredTupleType(TypeConverter &tc, } static CanType computeLoweredOptionalType(TypeConverter &tc, + TypeExpansionContext context, AbstractionPattern origType, CanType substType, CanType substObjectType) { assert(substType.getOptionalObjectType() == substObjectType); - CanType loweredObjectType = - tc.getLoweredRValueType(origType.getOptionalObjectType(), - substObjectType); + CanType loweredObjectType = tc.getLoweredRValueType( + context, origType.getOptionalObjectType(), substObjectType); // If the object type didn't change, we don't have to rebuild anything. if (loweredObjectType == substObjectType) { @@ -1464,11 +1500,12 @@ static CanType computeLoweredOptionalType(TypeConverter &tc, static CanType computeLoweredReferenceStorageType(TypeConverter &tc, + TypeExpansionContext context, AbstractionPattern origType, CanReferenceStorageType substType) { - CanType loweredReferentType = - tc.getLoweredRValueType(origType.getReferenceStorageReferentType(), - substType.getReferentType()); + CanType loweredReferentType = tc.getLoweredRValueType( + context, origType.getReferenceStorageReferentType(), + substType.getReferentType()); if (loweredReferentType == substType.getReferentType()) return substType; @@ -1478,36 +1515,53 @@ computeLoweredReferenceStorageType(TypeConverter &tc, } CanSILFunctionType -TypeConverter::getSILFunctionType(AbstractionPattern origType, +TypeConverter::getSILFunctionType(TypeExpansionContext context, + AbstractionPattern origType, CanFunctionType substType) { return cast( - getLoweredRValueType(origType, substType)); + getLoweredRValueType(context, origType, substType)); +} + +bool TypeConverter::hasOpaqueArchetypeOrPropertiesOrCases(CanType ty) { + if (ty->hasOpaqueArchetype()) + return true; + + auto it = opaqueArchetypeFields.find(ty); + if (it == opaqueArchetypeFields.end()) { + bool res = ty->hasOpaqueArchetypePropertiesOrCases(); + opaqueArchetypeFields[ty] = res; + return res; + } + return it->second; } const TypeLowering & TypeConverter::getTypeLowering(AbstractionPattern origType, Type origSubstType, - ResilienceExpansion forExpansion) { + TypeExpansionContext forExpansion) { CanType substType = origSubstType->getCanonicalType(); - auto key = getTypeKey(origType, substType); - + auto origHadOpaqueTypeArchetype = + hasOpaqueArchetypeOrPropertiesOrCases(origSubstType->getCanonicalType()); + auto key = getTypeKey(origType, substType, forExpansion); assert((!key.isDependent() || getCurGenericContext()) && "dependent type outside of generic context?!"); assert(!substType->is()); - auto *prev = find(key); - auto *lowering = getTypeLoweringForExpansion(key, forExpansion, prev); + auto *candidateLowering = find(key.getKeyForMinimalExpansion()); + auto *lowering = getTypeLoweringForExpansion( + key, forExpansion, candidateLowering, origHadOpaqueTypeArchetype); if (lowering != nullptr) return *lowering; #ifndef NDEBUG // Catch reentrancy bugs. - if (prev == nullptr) - insert(key, nullptr); + if (candidateLowering == nullptr) + insert(key.getKeyForMinimalExpansion(), nullptr); #endif // Lower the type. - auto loweredSubstType = computeLoweredRValueType(origType, substType); + auto loweredSubstType = + computeLoweredRValueType(forExpansion, origType, substType); // If that didn't change the type and the key is cachable, there's no // point in re-checking the table, so just construct a type lowering @@ -1524,24 +1578,29 @@ TypeConverter::getTypeLowering(AbstractionPattern origType, } else { AbstractionPattern origTypeForCaching = AbstractionPattern(getCurGenericContext(), loweredSubstType); - auto loweredKey = getTypeKey(origTypeForCaching, loweredSubstType); + auto loweredKey = + getTypeKey(origTypeForCaching, loweredSubstType, forExpansion); lowering = &getTypeLoweringForLoweredType(loweredKey, - forExpansion); + forExpansion, + origHadOpaqueTypeArchetype); } - if (prev == nullptr) - insert(key, lowering); + if (!lowering->isResilient() && !origHadOpaqueTypeArchetype) + insert(key.getKeyForMinimalExpansion(), lowering); else { - prev->NextExpansion = lowering; - assert(prev->isResilient() == lowering->isResilient()); + insert(key, lowering); +#ifndef NDEBUG + removeNullEntry(key.getKeyForMinimalExpansion()); +#endif } - return *lowering; } -CanType TypeConverter::computeLoweredRValueType(AbstractionPattern origType, - CanType substType) { +CanType +TypeConverter::computeLoweredRValueType(TypeExpansionContext forExpansion, + AbstractionPattern origType, + CanType substType) { // AST function types are turned into SIL function types: // - the type is uncurried as desired // - types are turned into their unbridged equivalents, depending @@ -1576,12 +1635,12 @@ CanType TypeConverter::computeLoweredRValueType(AbstractionPattern origType, } } - return getNativeSILFunctionType(*this, origType, substFnType); + return getNativeSILFunctionType(*this, forExpansion, origType, substFnType); } // Ignore dynamic self types. if (auto selfType = dyn_cast(substType)) { - return selfType.getSelfType(); + return getLoweredRValueType(forExpansion, selfType.getSelfType()); } // Static metatypes are unitary and can optimized to a "thin" empty @@ -1592,7 +1651,7 @@ CanType TypeConverter::computeLoweredRValueType(AbstractionPattern origType, // representation. if (substMeta->hasRepresentation()) { assert(substMeta->isLegalSILType()); - return substMeta; + return substOpaqueTypesWithUnderlyingTypes(substMeta, forExpansion); } MetatypeRepresentation repr; @@ -1611,8 +1670,9 @@ CanType TypeConverter::computeLoweredRValueType(AbstractionPattern origType, else repr = MetatypeRepresentation::Thick; } - - CanType instanceType = substMeta.getInstanceType(); + + CanType instanceType = substOpaqueTypesWithUnderlyingTypes( + substMeta.getInstanceType(), forExpansion); // Regardless of thinness, metatypes are always trivial. return CanMetatypeType::get(instanceType, repr); @@ -1631,61 +1691,100 @@ CanType TypeConverter::computeLoweredRValueType(AbstractionPattern origType, // Lower tuple element types. if (auto substTupleType = dyn_cast(substType)) { - return computeLoweredTupleType(*this, origType, substTupleType); + return computeLoweredTupleType(*this, forExpansion, origType, + substTupleType); } // Lower the referent type of reference storage types. if (auto substRefType = dyn_cast(substType)) { - return computeLoweredReferenceStorageType(*this, origType, substRefType); + return computeLoweredReferenceStorageType(*this, forExpansion, origType, + substRefType); } // Lower the object type of optional types. if (auto substObjectType = substType.getOptionalObjectType()) { - return computeLoweredOptionalType(*this, origType, + return computeLoweredOptionalType(*this, forExpansion, origType, substType, substObjectType); } + if (auto silFnTy = dyn_cast(substType)) { + if (!substType->hasOpaqueArchetype() || + !forExpansion.shouldLookThroughOpaqueTypeArchetypes()) + return substType; + return silFnTy->substituteOpaqueArchetypes(*this, forExpansion); + } + // The Swift type directly corresponds to the lowered type. - return substType; + auto underlyingTy = + substOpaqueTypesWithUnderlyingTypes(substType, forExpansion, + /*allowLoweredTypes*/ true); + if (underlyingTy != substType) { + if (auto underlyingFnTy = dyn_cast(underlyingTy)) { + underlyingTy = computeLoweredRValueType( + forExpansion, AbstractionPattern::getOpaque(), underlyingTy); + } else + underlyingTy = computeLoweredRValueType( + forExpansion, + AbstractionPattern(getCurGenericContext(), underlyingTy), + underlyingTy); + } + + return underlyingTy; } const TypeLowering & -TypeConverter::getTypeLowering(SILType type, ResilienceExpansion forExpansion) { +TypeConverter::getTypeLowering(SILType type, + TypeExpansionContext forExpansion) { auto loweredType = type.getASTType(); auto key = getTypeKey(AbstractionPattern(getCurGenericContext(), loweredType), - loweredType); + loweredType, forExpansion); + + auto origHadOpaqueTypeArchetype = + hasOpaqueArchetypeOrPropertiesOrCases(loweredType); - return getTypeLoweringForLoweredType(key, forExpansion); + return getTypeLoweringForLoweredType(key, forExpansion, + origHadOpaqueTypeArchetype); } const TypeLowering & TypeConverter::getTypeLoweringForLoweredType(TypeKey key, - ResilienceExpansion forExpansion) { + TypeExpansionContext forExpansion, + bool origHadOpaqueTypeArchetype) { auto type = key.SubstType; assert(type->isLegalSILType() && "type is not lowered!"); (void)type; - auto *prev = find(key); - auto *lowering = getTypeLoweringForExpansion(key, forExpansion, prev); + auto *candidateLowering = find(key.getKeyForMinimalExpansion()); + auto *lowering = getTypeLoweringForExpansion( + key, forExpansion, candidateLowering, origHadOpaqueTypeArchetype); if (lowering != nullptr) return *lowering; #ifndef NDEBUG // Catch reentrancy bugs. - if (prev == nullptr) - insert(key, nullptr); + if (candidateLowering == nullptr) + insert(key.getKeyForMinimalExpansion(), nullptr); #endif - lowering = LowerType(*this, - CanGenericSignature(), - forExpansion, - key.isDependent()).visit(key.SubstType); + if (forExpansion.shouldLookThroughOpaqueTypeArchetypes() && + type->hasOpaqueArchetype()) { + type = computeLoweredRValueType( + forExpansion, AbstractionPattern(getCurGenericContext(), type), type); + } + + lowering = + LowerType(*this, CanGenericSignature(), forExpansion, key.isDependent()) + .visit(type); - if (prev) { - prev->NextExpansion = lowering; - assert(prev->isResilient() == lowering->isResilient()); - } else + if (!lowering->isResilient() && !origHadOpaqueTypeArchetype) + insert(key.getKeyForMinimalExpansion(), lowering); + else { insert(key, lowering); +#ifndef NDEBUG + removeNullEntry(key.getKeyForMinimalExpansion()); +#endif + } + return *lowering; } @@ -1695,28 +1794,25 @@ TypeConverter::getTypeLoweringForLoweredType(TypeKey key, /// go ahead and lower the type with the correct expansion. const TypeLowering *TypeConverter:: getTypeLoweringForExpansion(TypeKey key, - ResilienceExpansion forExpansion, - const TypeLowering *lowering) { + TypeExpansionContext forExpansion, + const TypeLowering *lowering, + bool origHadOpaqueTypeArchetype) { if (lowering == nullptr) return nullptr; - if (!lowering->isResilient()) { + if (!lowering->isResilient() && !origHadOpaqueTypeArchetype) { // Don't try to refine the lowering for other resilience expansions if - // we don't expect to get a different lowering anyway. + // we don't expect to get a different lowering anyway. Similar if the + // original type did not have opaque type archetypes. // // See LowerType::handleResilience() for the gory details; we only // set this flag if the type is resilient *and* inside our module. return lowering; } - // Search for a matching lowering in the linked list of lowerings. - while (lowering) { - if (lowering->getResilienceExpansion() == forExpansion) - return lowering; - - // Continue searching. - lowering = lowering->NextExpansion; - } + auto *exactLowering = find(key); + if (exactLowering) + return exactLowering; // We have to create a new one. return nullptr; @@ -2020,7 +2116,8 @@ TypeConverter::getConstantGenericEnvironment(SILDeclRef c) { return nullptr; } -SILType TypeConverter::getSubstitutedStorageType(AbstractStorageDecl *value, +SILType TypeConverter::getSubstitutedStorageType(TypeExpansionContext context, + AbstractStorageDecl *value, Type lvalueType) { // The l-value type is the result of applying substitutions to // the type-of-reference. Essentially, we want to apply those @@ -2039,7 +2136,7 @@ SILType TypeConverter::getSubstitutedStorageType(AbstractStorageDecl *value, substType = substType.getReferenceStorageReferent(); } - CanType substLoweredType = getLoweredRValueType(origType, substType); + CanType substLoweredType = getLoweredRValueType(context, origType, substType); // Type substitution preserves structural type structure, and the // type-of-reference is only different in the outermost structural @@ -2605,10 +2702,11 @@ TypeConverter::getInterfaceBoxTypeForCapture(ValueDecl *captured, env->mapTypeIntoContext(contextBoxTy) ->getCanonicalType()); } - assert(contextBoxTy->getLayout()->getFields().size() == 1 - && getSILBoxFieldType(contextBoxTy, *this, 0).getASTType() - == loweredContextType - && "box field type doesn't match capture!"); + assert(contextBoxTy->getLayout()->getFields().size() == 1 && + getSILBoxFieldType(TypeExpansionContext::minimal(), contextBoxTy, + *this, 0) + .getASTType() == loweredContextType && + "box field type doesn't match capture!"); #endif return boxTy; } @@ -2638,8 +2736,8 @@ TypeConverter::getContextBoxTypeForCapture(ValueDecl *captured, return boxType; } -CanSILBoxType TypeConverter::getBoxTypeForEnumElement(SILType enumType, - EnumElementDecl *elt) { +CanSILBoxType TypeConverter::getBoxTypeForEnumElement( + TypeExpansionContext context, SILType enumType, EnumElementDecl *elt) { auto *enumDecl = enumType.getEnumOrBoundGenericEnum(); @@ -2652,8 +2750,7 @@ CanSILBoxType TypeConverter::getBoxTypeForEnumElement(SILType enumType, if (boxSignature == CanGenericSignature()) { auto eltIntfTy = elt->getArgumentInterfaceType(); - - auto boxVarTy = getLoweredRValueType(eltIntfTy); + auto boxVarTy = getLoweredRValueType(context, eltIntfTy); auto layout = SILLayout::get(C, nullptr, SILField(boxVarTy, true)); return SILBoxType::get(C, layout, {}); } @@ -2665,8 +2762,8 @@ CanSILBoxType TypeConverter::getBoxTypeForEnumElement(SILType enumType, auto eltIntfTy = elt->getArgumentInterfaceType(); GenericContextScope scope(*this, boxSignature); - auto boxVarTy = getLoweredRValueType(getAbstractionPattern(elt), - eltIntfTy); + auto boxVarTy = getLoweredRValueType(context, + getAbstractionPattern(elt), eltIntfTy); auto layout = SILLayout::get(C, boxSignature, SILField(boxVarTy, true)); // Instantiate the layout with enum's substitution list. @@ -2678,13 +2775,15 @@ CanSILBoxType TypeConverter::getBoxTypeForEnumElement(SILType enumType, } static void countNumberOfInnerFields(unsigned &fieldsCount, TypeConverter &TC, - SILType Ty, ResilienceExpansion expansion) { + SILType Ty, + TypeExpansionContext expansion) { if (auto *structDecl = Ty.getStructOrBoundGenericStruct()) { - assert(!structDecl->isResilient(&TC.M, expansion) && - " FSO should not be trying to explode resilient (ie address-only) " - "types at all"); + assert( + !structDecl->isResilient(&TC.M, expansion.getResilienceExpansion()) && + " FSO should not be trying to explode resilient (ie address-only) " + "types at all"); for (auto *prop : structDecl->getStoredProperties()) { - SILType propTy = Ty.getFieldType(prop, TC); + SILType propTy = Ty.getFieldType(prop, TC, expansion); unsigned fieldsCountBefore = fieldsCount; countNumberOfInnerFields(fieldsCount, TC, propTy, expansion); if (fieldsCount == fieldsCountBefore) { @@ -2706,7 +2805,7 @@ static void countNumberOfInnerFields(unsigned &fieldsCount, TypeConverter &TC, if (enumDecl->isIndirect()) { return; } - assert(!enumDecl->isResilient(&TC.M, expansion) && + assert(!enumDecl->isResilient(&TC.M, expansion.getResilienceExpansion()) && " FSO should not be trying to explode resilient (ie address-only) " "types at all"); unsigned fieldsCountBefore = fieldsCount; @@ -2723,7 +2822,7 @@ static void countNumberOfInnerFields(unsigned &fieldsCount, TypeConverter &TC, // (we shouldn't expand enums) // Number of fields > 1 as "future proof" for this heuristic: // In case it is used by a pass that tries to explode enums. - auto payloadTy = Ty.getEnumElementType(elt, TC); + auto payloadTy = Ty.getEnumElementType(elt, TC, expansion); fieldsCount = 0; countNumberOfInnerFields(fieldsCount, TC, payloadTy, expansion); if (fieldsCount > maxEnumCount) { @@ -2736,8 +2835,8 @@ static void countNumberOfInnerFields(unsigned &fieldsCount, TypeConverter &TC, } unsigned TypeConverter::countNumberOfFields(SILType Ty, - ResilienceExpansion expansion) { - auto key = std::make_pair(Ty, unsigned(expansion)); + TypeExpansionContext expansion) { + auto key = std::make_pair(Ty, unsigned(expansion.getResilienceExpansion())); auto Iter = TypeFields.find(key); if (Iter != TypeFields.end()) { return std::max(Iter->second, 1U); @@ -2755,7 +2854,7 @@ void TypeLowering::print(llvm::raw_ostream &os) const { return "false"; }; os << "Type Lowering for lowered type: " << LoweredType << ".\n" - << "Expansion: " << ResilienceExpansion(ForExpansion) << "\n" + << "Expansion: " << getResilienceExpansion() << "\n" << "isTrivial: " << BOOL(Properties.isTrivial()) << ".\n" << "isFixedABI: " << BOOL(Properties.isFixedABI()) << ".\n" << "isAddressOnly: " << BOOL(Properties.isAddressOnly()) << ".\n" diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index b1e5e9c22937f..248e10c4613bd 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -110,11 +110,12 @@ getBridgingFn(Optional &cacheSlot, // Check that the function takes the expected arguments and returns the // expected result type. SILDeclRef c(fd); - auto funcTy = SGM.Types.getConstantFunctionType(c); + auto funcTy = + SGM.Types.getConstantFunctionType(TypeExpansionContext::minimal(), c); SILFunctionConventions fnConv(funcTy, SGM.M); auto toSILType = [&SGM](Type ty) { - return SGM.Types.getLoweredType(ty, ResilienceExpansion::Minimal); + return SGM.Types.getLoweredType(ty, TypeExpansionContext::minimal()); }; if (inputTypes) { @@ -916,7 +917,6 @@ SILFunction *SILGenModule::emitClosure(AbstractClosureExpr *ce) { // initializer of the containing type. if (!f->isExternalDeclaration()) return f; - preEmitFunction(constant, ce, f, ce); PrettyStackTraceSILFunction X("silgen closureexpr", f); SILGenFunction(*this, *f, ce).emitClosure(ce); @@ -947,8 +947,8 @@ bool SILGenModule::hasNonTrivialIVars(ClassDecl *cd) { auto *vd = dyn_cast(member); if (!vd || !vd->hasStorage()) continue; - auto &ti = Types.getTypeLowering(vd->getType(), - ResilienceExpansion::Maximal); + auto &ti = Types.getTypeLowering( + vd->getType(), TypeExpansionContext::maximalResilienceExpansionOnly()); if (!ti.isTrivial()) return true; } @@ -1170,7 +1170,7 @@ SILFunction *SILGenModule::emitLazyGlobalInitializer(StringRef funcName, Type initType = FunctionType::get({}, TupleType::getEmpty(C), type->getExtInfo()); auto initSILType = cast( - Types.getLoweredRValueType(initType)); + Types.getLoweredRValueType(TypeExpansionContext::minimal(), initType)); SILGenFunctionBuilder builder(*this); auto *f = builder.createFunction( @@ -1354,11 +1354,12 @@ SILGenModule::canStorageUseStoredKeyPathComponent(AbstractStorageDecl *decl, if (auto genericEnv = decl->getInnermostDeclContext()->getGenericEnvironmentOfContext()) componentObjTy = genericEnv->mapTypeIntoContext(componentObjTy); - auto storageTy = M.Types.getSubstitutedStorageType(decl, componentObjTy); - auto opaqueTy = - M.Types.getLoweredRValueType(AbstractionPattern::getOpaque(), - componentObjTy); - + auto storageTy = M.Types.getSubstitutedStorageType( + TypeExpansionContext::minimal(), decl, componentObjTy); + auto opaqueTy = M.Types.getLoweredRValueType( + TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(expansion), + AbstractionPattern::getOpaque(), componentObjTy); + return storageTy.getASTType() == opaqueTy; } case AccessStrategy::DirectToAccessor: diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index 00be4b4e930fa..c0f7ce664ff24 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -90,7 +90,8 @@ getIndirectApplyAbstractionPattern(SILGenFunction &SGF, static CanFunctionType getPartialApplyOfDynamicMethodFormalType(SILGenModule &SGM, SILDeclRef member, ConcreteDeclRef memberRef) { - auto memberCI = SGM.Types.getConstantInfo(member); + auto memberCI = + SGM.Types.getConstantInfo(TypeExpansionContext::minimal(), member); // Construct a non-generic version of the formal type. // This works because we're only using foreign members, where presumably @@ -133,7 +134,8 @@ getDynamicMethodLoweredType(SILModule &M, auto objcFormalTy = substMemberTy.withExtInfo(substMemberTy->getExtInfo() .withSILRepresentation(SILFunctionTypeRepresentation::ObjCMethod)); return SILType::getPrimitiveObjectType( - M.Types.getUncachedSILFunctionTypeForConstant(constant, objcFormalTy)); + M.Types.getUncachedSILFunctionTypeForConstant( + TypeExpansionContext::minimal(), constant, objcFormalTy)); } /// Check if we can perform a dynamic dispatch on a super method call. @@ -382,34 +384,39 @@ class Callee { SubstitutionMap subs, SILLocation l, bool callPreviousDynamicReplaceableImpl = false) { - auto &ci = SGF.getConstantInfo(c); - return Callee(SGF, c, ci.FormalPattern, ci.FormalType, subs, l, - callPreviousDynamicReplaceableImpl); + auto &ci = SGF.getConstantInfo(SGF.getTypeExpansionContext(), c); + return Callee( + SGF, c, ci.FormalPattern, ci.FormalType, + subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext()), l, + callPreviousDynamicReplaceableImpl); } static Callee forEnumElement(SILGenFunction &SGF, SILDeclRef c, SubstitutionMap subs, SILLocation l) { assert(isa(c.getDecl())); - auto &ci = SGF.getConstantInfo(c); - return Callee(Kind::EnumElement, SGF, c, ci.FormalPattern, - ci.FormalType, subs, l); + auto &ci = SGF.getConstantInfo(SGF.getTypeExpansionContext(), c); + return Callee( + Kind::EnumElement, SGF, c, ci.FormalPattern, ci.FormalType, + subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext()), l); } static Callee forClassMethod(SILGenFunction &SGF, SILDeclRef c, SubstitutionMap subs, SILLocation l) { auto base = c.getOverriddenVTableEntry(); - auto &baseCI = SGF.getConstantInfo(base); - auto &derivedCI = SGF.getConstantInfo(c); - return Callee(Kind::ClassMethod, SGF, c, - baseCI.FormalPattern, derivedCI.FormalType, subs, l); + auto &baseCI = SGF.getConstantInfo(SGF.getTypeExpansionContext(), base); + auto &derivedCI = SGF.getConstantInfo(SGF.getTypeExpansionContext(), c); + return Callee( + Kind::ClassMethod, SGF, c, baseCI.FormalPattern, derivedCI.FormalType, + subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext()), l); } static Callee forSuperMethod(SILGenFunction &SGF, SILDeclRef c, SubstitutionMap subs, SILLocation l) { - auto &ci = SGF.getConstantInfo(c); - return Callee(Kind::SuperMethod, SGF, c, - ci.FormalPattern, ci.FormalType, subs, l); + auto &ci = SGF.getConstantInfo(SGF.getTypeExpansionContext(), c); + return Callee( + Kind::SuperMethod, SGF, c, ci.FormalPattern, ci.FormalType, + subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext()), l); } static Callee forWitnessMethod(SILGenFunction &SGF, CanType protocolSelfType, @@ -430,15 +437,16 @@ class Callee { subs); } - auto &ci = SGF.getConstantInfo(c); - return Callee(Kind::WitnessMethod, SGF, c, ci.FormalPattern, - ci.FormalType, subs, l); + auto &ci = SGF.getConstantInfo(SGF.getTypeExpansionContext(), c); + return Callee( + Kind::WitnessMethod, SGF, c, ci.FormalPattern, ci.FormalType, + subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext()), l); } static Callee forDynamic(SILGenFunction &SGF, SILDeclRef c, SubstitutionMap constantSubs, CanAnyFunctionType substFormalType, SubstitutionMap subs, SILLocation l) { - auto &ci = SGF.getConstantInfo(c); + auto &ci = SGF.getConstantInfo(SGF.getTypeExpansionContext(), c); AbstractionPattern origFormalType = ci.FormalPattern; // Replace the original self type with the partially-applied subst type. @@ -456,8 +464,9 @@ class Callee { } origFormalType.rewriteType(CanGenericSignature(), origFormalFnType); - return Callee(Kind::DynamicMethod, SGF, c, origFormalType, - substFormalType, subs, l); + return Callee( + Kind::DynamicMethod, SGF, c, origFormalType, substFormalType, + subs.mapIntoTypeExpansionContext(SGF.getTypeExpansionContext()), l); } Callee(Callee &&) = default; @@ -534,8 +543,8 @@ class Callee { CalleeTypeInfo result; result.substFnType = - formalFnType.castTo()->substGenericArgs(SGF.SGM.M, - Substitutions); + formalFnType.castTo()->substGenericArgs( + SGF.SGM.M, Substitutions, SGF.getTypeExpansionContext()); if (!constant || !constant->isForeign) return result; @@ -578,7 +587,8 @@ class Callee { // If the call is curried, emit a direct call to the curry thunk. if (constant->isCurried) { - auto constantInfo = SGF.getConstantInfo(*constant); + auto constantInfo = + SGF.getConstantInfo(SGF.getTypeExpansionContext(), *constant); SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo); return ManagedValue::forUnmanaged(ref); } @@ -590,18 +600,21 @@ class Callee { return IndirectValue; case Kind::EnumElement: case Kind::StandaloneFunction: { - auto constantInfo = SGF.getConstantInfo(*constant); + auto constantInfo = + SGF.getConstantInfo(SGF.getTypeExpansionContext(), *constant); SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo); return ManagedValue::forUnmanaged(ref); } case Kind::StandaloneFunctionDynamicallyReplaceableImpl: { - auto constantInfo = SGF.getConstantInfo(*constant); + auto constantInfo = + SGF.getConstantInfo(SGF.getTypeExpansionContext(), *constant); SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo, true); return ManagedValue::forUnmanaged(ref); } case Kind::ClassMethod: { - auto methodTy = SGF.SGM.Types.getConstantOverrideType(*constant); + auto methodTy = SGF.SGM.Types.getConstantOverrideType( + SGF.getTypeExpansionContext(), *constant); // Otherwise, do the dynamic dispatch inline. ArgumentScope S(SGF, Loc); @@ -626,8 +639,8 @@ class Callee { SGF, Loc, *borrowedSelf); auto base = constant->getOverriddenVTableEntry(); - auto constantInfo = - SGF.SGM.Types.getConstantOverrideInfo(*constant, base); + auto constantInfo = SGF.SGM.Types.getConstantOverrideInfo( + SGF.getTypeExpansionContext(), *constant, base); ManagedValue fn; if (!constant->isForeign) { @@ -641,8 +654,10 @@ class Callee { return fn; } case Kind::WitnessMethod: { - auto constantInfo = SGF.getConstantInfo(*constant); + auto constantInfo = + SGF.getConstantInfo(SGF.getTypeExpansionContext(), *constant); + // TODO: substOpaqueTypesWithUnderlyingTypes ... auto proto = cast(Constant.getDecl()->getDeclContext()); auto selfType = proto->getSelfInterfaceType()->getCanonicalType(); auto lookupType = selfType.subst(Substitutions)->getCanonicalType(); @@ -687,7 +702,8 @@ class Callee { // If the call is curried, emit a direct call to the curry thunk. if (constant->isCurried) { - auto constantInfo = SGF.getConstantInfo(*constant); + auto constantInfo = + SGF.getConstantInfo(SGF.getTypeExpansionContext(), *constant); return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType()); } } @@ -699,26 +715,30 @@ class Callee { case Kind::StandaloneFunctionDynamicallyReplaceableImpl: case Kind::StandaloneFunction: { - auto constantInfo = SGF.getConstantInfo(*constant); + auto constantInfo = + SGF.getConstantInfo(SGF.getTypeExpansionContext(), *constant); return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType()); } case Kind::EnumElement: { // Emit a direct call to the element constructor thunk. - auto constantInfo = SGF.getConstantInfo(*constant); + auto constantInfo = + SGF.getConstantInfo(SGF.getTypeExpansionContext(), *constant); return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType()); } case Kind::ClassMethod: { - auto constantInfo = SGF.SGM.Types.getConstantOverrideInfo(*constant); + auto constantInfo = SGF.SGM.Types.getConstantOverrideInfo( + SGF.getTypeExpansionContext(), *constant); return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType()); } case Kind::SuperMethod: { auto base = constant->getOverriddenVTableEntry(); - auto constantInfo = - SGF.SGM.Types.getConstantOverrideInfo(*constant, base); + auto constantInfo = SGF.SGM.Types.getConstantOverrideInfo( + SGF.getTypeExpansionContext(), *constant, base); return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType()); } case Kind::WitnessMethod: { - auto constantInfo = SGF.getConstantInfo(*constant); + auto constantInfo = + SGF.getConstantInfo(SGF.getTypeExpansionContext(), *constant); return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType()); } case Kind::DynamicMethod: { @@ -3951,8 +3971,8 @@ CallEmission::applyPartiallyAppliedSuperMethod(SGFContext C) { // because that's what the partially applied super method expects; firstLevelResult.formalType = callee.getSubstFormalType(); auto origFormalType = AbstractionPattern(firstLevelResult.formalType); - auto substFnType = - SGF.getSILFunctionType(origFormalType, firstLevelResult.formalType); + auto substFnType = SGF.getSILFunctionType( + SGF.getTypeExpansionContext(), origFormalType, firstLevelResult.formalType); // Emit the arguments. SmallVector uncurriedArgs; @@ -3978,7 +3998,8 @@ CallEmission::applyPartiallyAppliedSuperMethod(SGFContext C) { // partial_apply. upcastedSelf = upcastedSelf.ensurePlusOne(SGF, loc); - auto constantInfo = SGF.getConstantInfo(callee.getMethodName()); + auto constantInfo = + SGF.getConstantInfo(SGF.getTypeExpansionContext(), callee.getMethodName()); auto functionTy = constantInfo.getSILType(); ManagedValue superMethod; { @@ -4019,8 +4040,8 @@ CallEmission::applySpecializedEmitter(SpecializedEmitter &specializedEmitter, // expect. firstLevelResult.formalType = callee.getSubstFormalType(); auto origFormalType = AbstractionPattern(firstLevelResult.formalType); - auto substFnType = - SGF.getSILFunctionType(origFormalType, firstLevelResult.formalType); + auto substFnType = SGF.getSILFunctionType( + SGF.getTypeExpansionContext(), origFormalType, firstLevelResult.formalType); // If we have an early emitter, just let it take over for the // uncurried call site. @@ -4352,7 +4373,8 @@ bool SILGenModule::isNonMutatingSelfIndirect(SILDeclRef methodRef) { if (method->isStatic()) return false; - auto fnType = M.Types.getConstantFunctionType(methodRef); + auto fnType = M.Types.getConstantFunctionType(TypeExpansionContext::minimal(), + methodRef); auto importAsMember = method->getImportAsMemberStatus(); SILParameterInfo self; @@ -4640,7 +4662,7 @@ void SILGenFunction::emitYield(SILLocation loc, SmallVector yieldArgs; SmallVector delayedArgs; - auto fnType = F.getLoweredFunctionType(); + auto fnType = F.getLoweredFunctionTypeInContext(getTypeExpansionContext()); SmallVector substYieldTys; for (auto origYield : fnType->getYields()) { substYieldTys.push_back({ @@ -4740,7 +4762,8 @@ ManagedValue SILGenFunction::emitInjectEnum(SILLocation loc, // careful to stage the cleanups so that if the expression // throws, we know to deallocate the uninitialized box. if (element->isIndirect() || element->getParentEnum()->isIndirect()) { - auto boxTy = SGM.M.Types.getBoxTypeForEnumElement(enumTy, element); + auto boxTy = SGM.M.Types.getBoxTypeForEnumElement(getTypeExpansionContext(), + enumTy, element); auto *box = B.createAllocBox(loc, boxTy); auto *addr = B.createProjectBox(loc, box, 0); @@ -4868,7 +4891,7 @@ RValue SILGenFunction::emitApplyAllocatingInitializer(SILLocation loc, // Form the reference to the allocating initializer. auto initRef = SILDeclRef(ctor, SILDeclRef::Kind::Allocator) .asForeign(requiresForeignEntryPoint(ctor)); - auto initConstant = getConstantInfo(initRef); + auto initConstant = getConstantInfo(getTypeExpansionContext(), initRef); auto subs = init.getSubstitutions(); // Scope any further writeback just within this operation. @@ -4879,8 +4902,8 @@ RValue SILGenFunction::emitApplyAllocatingInitializer(SILLocation loc, SILType selfMetaTy; { // Determine the self metatype type. - CanSILFunctionType substFnType = - initConstant.SILFnType->substGenericArgs(SGM.M, subs); + CanSILFunctionType substFnType = initConstant.SILFnType->substGenericArgs( + SGM.M, subs, getTypeExpansionContext()); SILType selfParamMetaTy = getSILType(substFnType->getSelfParameter(), substFnType); @@ -4972,7 +4995,7 @@ RValue SILGenFunction::emitApplyMethod(SILLocation loc, ConcreteDeclRef declRef, // Form the reference to the method. auto callRef = SILDeclRef(call, SILDeclRef::Kind::Func) .asForeign(requiresForeignEntryPoint(declRef.getDecl())); - auto declRefConstant = getConstantInfo(callRef); + auto declRefConstant = getConstantInfo(getTypeExpansionContext(), callRef); auto subs = declRef.getSubstitutions(); // Scope any further writeback just within this operation. @@ -4984,7 +5007,8 @@ RValue SILGenFunction::emitApplyMethod(SILLocation loc, ConcreteDeclRef declRef, { // Determine the self metatype type. CanSILFunctionType substFnType = - declRefConstant.SILFnType->substGenericArgs(SGM.M, subs); + declRefConstant.SILFnType->substGenericArgs(SGM.M, subs, + getTypeExpansionContext()); SILType selfParamMetaTy = getSILType(substFnType->getSelfParameter(), substFnType); selfMetaTy = selfParamMetaTy; @@ -5490,8 +5514,8 @@ AccessorBaseArgPreparer::AccessorBaseArgPreparer(SILGenFunction &SGF, CanType baseFormalType, SILDeclRef accessor) : SGF(SGF), loc(loc), base(base), baseFormalType(baseFormalType), - accessor(accessor), - selfParam(SGF.SGM.Types.getConstantSelfParameter(accessor)), + accessor(accessor), selfParam(SGF.SGM.Types.getConstantSelfParameter( + SGF.getTypeExpansionContext(), accessor)), baseLoweredType(base.getType()) { assert(!base.isInContext()); assert(!base.isLValue() || !base.hasCleanup()); diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index 5520e6f15536f..bd88f7a2ad42b 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -123,7 +123,8 @@ emitBridgeNativeToObjectiveC(SILGenFunction &SGF, SGF.SGM.SwiftModule, dc); // Substitute into the witness function type. - witnessFnTy = witnessFnTy.substGenericArgs(SGF.SGM.M, typeSubMap); + witnessFnTy = witnessFnTy.substGenericArgs(SGF.SGM.M, typeSubMap, + SGF.getTypeExpansionContext()); // We might have to re-abstract the 'self' value if it is an // Optional. @@ -204,7 +205,8 @@ emitBridgeObjectiveCToNative(SILGenFunction &SGF, SubstitutionMap typeSubMap = witness.getSubstitutions(); // Substitute into the witness function type. - witnessFnTy = witnessFnTy->substGenericArgs(SGF.SGM.M, typeSubMap); + witnessFnTy = witnessFnTy->substGenericArgs(SGF.SGM.M, typeSubMap, + SGF.getTypeExpansionContext()); // The witness takes an _ObjectiveCType?, so convert to that type. CanType desiredValueType = OptionalType::get(objcType)->getCanonicalType(); @@ -220,7 +222,8 @@ emitBridgeObjectiveCToNative(SILGenFunction &SGF, SGF.B.createMetatype(loc, metatypeParam.getSILStorageType(SGF.SGM.M, witnessFnTy)); - auto witnessCI = SGF.getConstantInfo(witnessConstant); + auto witnessCI = + SGF.getConstantInfo(SGF.getTypeExpansionContext(), witnessConstant); CanType formalResultTy = witnessCI.LoweredType.getResult(); auto subs = witness.getSubstitutions(); @@ -954,7 +957,8 @@ SILGenFunction::emitBlockToFunc(SILLocation loc, if (thunkTy->getInvocationGenericSignature()) { substFnTy = thunkTy->substGenericArgs(F.getModule(), - interfaceSubs); + interfaceSubs, + getTypeExpansionContext()); } // Create it in the current function. @@ -1263,12 +1267,16 @@ static SILFunctionType *emitObjCThunkArguments(SILGenFunction &SGF, auto subs = SGF.F.getForwardingSubstitutionMap(); - auto objcInfo = SGF.SGM.Types.getConstantInfo(thunk); - auto objcFnTy = objcInfo.SILFnType->substGenericArgs(SGF.SGM.M, subs); + auto objcInfo = + SGF.SGM.Types.getConstantInfo(SGF.getTypeExpansionContext(), thunk); + auto objcFnTy = objcInfo.SILFnType->substGenericArgs( + SGF.SGM.M, subs, SGF.getTypeExpansionContext()); auto objcFormalFnTy = substGenericArgs(objcInfo.LoweredType, subs); - auto swiftInfo = SGF.SGM.Types.getConstantInfo(native); - auto swiftFnTy = swiftInfo.SILFnType->substGenericArgs(SGF.SGM.M, subs); + auto swiftInfo = + SGF.SGM.Types.getConstantInfo(SGF.getTypeExpansionContext(), native); + auto swiftFnTy = swiftInfo.SILFnType->substGenericArgs( + SGF.SGM.M, subs, SGF.getTypeExpansionContext()); auto swiftFormalFnTy = substGenericArgs(swiftInfo.LoweredType, subs); SILFunctionConventions swiftConv(swiftFnTy, SGF.SGM.M); @@ -1402,9 +1410,10 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) { } } - auto nativeInfo = getConstantInfo(native); + auto nativeInfo = getConstantInfo(getTypeExpansionContext(), native); auto subs = F.getForwardingSubstitutionMap(); - auto substTy = nativeInfo.SILFnType->substGenericArgs(SGM.M, subs); + auto substTy = nativeInfo.SILFnType->substGenericArgs( + SGM.M, subs, getTypeExpansionContext()); SILFunctionConventions substConv(substTy, SGM.M); // Use the same generic environment as the native entry point. @@ -1605,7 +1614,7 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) { // Wrap the function in its original form. auto fd = cast(thunk.getDecl()); - auto nativeCI = getConstantInfo(thunk); + auto nativeCI = getConstantInfo(getTypeExpansionContext(), thunk); auto nativeFnTy = F.getLoweredFunctionType(); assert(nativeFnTy == nativeCI.SILFnType); @@ -1613,7 +1622,8 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) { F.setGenericEnvironment(SGM.Types.getConstantGenericEnvironment(thunk)); SILDeclRef foreignDeclRef = thunk.asForeign(true); - SILConstantInfo foreignCI = getConstantInfo(foreignDeclRef); + SILConstantInfo foreignCI = + getConstantInfo(getTypeExpansionContext(), foreignDeclRef); auto foreignFnTy = foreignCI.SILFnType; // Find the foreign error convention and 'self' parameter index. @@ -1780,7 +1790,7 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) { foreignCI); auto fnType = fn->getType().castTo(); - fnType = fnType->substGenericArgs(SGM.M, subs); + fnType = fnType->substGenericArgs(SGM.M, subs, getTypeExpansionContext()); CanType nativeFormalResultType = fd->mapTypeIntoContext(nativeCI.LoweredType.getResult()) diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp index f43baef1ba102..c46970ecf36e4 100644 --- a/lib/SILGen/SILGenConstructor.cpp +++ b/lib/SILGen/SILGenConstructor.cpp @@ -49,7 +49,8 @@ static SILValue emitConstructorMetatypeArg(SILGenFunction &SGF, VD->setInterfaceType(metatype); SGF.AllocatorMetatype = SGF.F.begin()->createFunctionArgument( - SGF.getLoweredType(DC->mapTypeIntoContext(metatype)), VD); + SGF.getLoweredTypeForFunctionArgument(DC->mapTypeIntoContext(metatype)), + VD); return SGF.AllocatorMetatype; } @@ -78,8 +79,7 @@ static RValue emitImplicitValueConstructorArg(SILGenFunction &SGF, VD->setSpecifier(ParamSpecifier::Default); VD->setInterfaceType(interfaceType); - auto argType = SGF.SGM.Types.getLoweredType(type, - ResilienceExpansion::Minimal); + auto argType = SGF.getLoweredTypeForFunctionArgument(type); auto *arg = SGF.F.begin()->createFunctionArgument(argType, VD); ManagedValue mvArg; if (arg->getArgumentConvention().isOwnedConvention()) { @@ -129,7 +129,7 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF, auto *paramList = ctor->getParameters(); auto *selfDecl = ctor->getImplicitSelfDecl(); auto selfIfaceTy = selfDecl->getInterfaceType(); - SILType selfTy = SGF.getLoweredType(selfDecl->getType()); + SILType selfTy = SGF.getLoweredTypeForFunctionArgument(selfDecl->getType()); // Emit the indirect return argument, if any. SILValue resultSlot; @@ -142,7 +142,8 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF, ctor); VD->setSpecifier(ParamSpecifier::InOut); VD->setInterfaceType(selfIfaceTy); - resultSlot = SGF.F.begin()->createFunctionArgument(selfTy.getAddressType(), VD); + resultSlot = + SGF.F.begin()->createFunctionArgument(selfTy.getAddressType(), VD); } // Emit the elementwise arguments. @@ -164,7 +165,8 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF, if (resultSlot) { auto elti = elements.begin(), eltEnd = elements.end(); for (VarDecl *field : decl->getStoredProperties()) { - auto fieldTy = selfTy.getFieldType(field, SGF.SGM.M); + auto fieldTy = + selfTy.getFieldType(field, SGF.SGM.M, SGF.getTypeExpansionContext()); SILValue slot = SGF.B.createStructElementAddr(Loc, resultSlot, field, fieldTy.getAddressType()); @@ -201,7 +203,8 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF, auto elti = elements.begin(), eltEnd = elements.end(); for (VarDecl *field : decl->getStoredProperties()) { - auto fieldTy = selfTy.getFieldType(field, SGF.SGM.M); + auto fieldTy = + selfTy.getFieldType(field, SGF.SGM.M, SGF.getTypeExpansionContext()); SILValue v; // If it's memberwise initialized, do so now. @@ -416,8 +419,8 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) { void SILGenFunction::emitEnumConstructor(EnumElementDecl *element) { Type enumIfaceTy = element->getParentEnum()->getDeclaredInterfaceType(); Type enumTy = F.mapTypeIntoContext(enumIfaceTy); - auto &enumTI = SGM.Types.getTypeLowering(enumTy, - ResilienceExpansion::Minimal); + auto &enumTI = + SGM.Types.getTypeLowering(enumTy, TypeExpansionContext::minimal()); RegularLocation Loc(element); CleanupLocation CleanupLoc(element); diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp index 8ef1cf2c6af67..ace1e9e71c359 100644 --- a/lib/SILGen/SILGenDecl.cpp +++ b/lib/SILGen/SILGenDecl.cpp @@ -371,12 +371,13 @@ class LocalVariableInitialization : public SingleBufferInitialization { "can't emit a local var for a non-local var decl"); assert(decl->hasStorage() && "can't emit storage for a computed variable"); assert(!SGF.VarLocs.count(decl) && "Already have an entry for this decl?"); - - auto boxType = SGF.SGM.Types - .getContextBoxTypeForCapture(decl, - SGF.SGM.Types.getLoweredRValueType(decl->getType()), - SGF.F.getGenericEnvironment(), - /*mutable*/ true); + // The box type's context is lowered in the minimal resilience domain. + auto boxType = SGF.SGM.Types.getContextBoxTypeForCapture( + decl, + SGF.SGM.Types.getLoweredRValueType(TypeExpansionContext::minimal(), + decl->getType()), + SGF.F.getGenericEnvironment(), + /*mutable*/ true); // The variable may have its lifetime extended by a closure, heap-allocate // it using a box. @@ -850,7 +851,8 @@ void EnumElementPatternInitialization::emitEnumMatch( } // Otherwise, the bound value for the enum case is available. - SILType eltTy = value.getType().getEnumElementType(eltDecl, SGF.SGM.M); + SILType eltTy = value.getType().getEnumElementType( + eltDecl, SGF.SGM.M, SGF.getTypeExpansionContext()); auto &eltTL = SGF.getTypeLowering(eltTy); if (mv.getType().isAddress()) { @@ -1237,7 +1239,7 @@ SILValue SILGenFunction::emitOSVersionRangeCheck(SILLocation loc, auto silDeclRef = SILDeclRef(versionQueryDecl); SILValue availabilityGTEFn = emitGlobalFunctionRef( - loc, silDeclRef, getConstantInfo(silDeclRef)); + loc, silDeclRef, getConstantInfo(getTypeExpansionContext(), silDeclRef)); SILValue args[] = {majorValue, minorValue, subminorValue}; return B.createApply(loc, availabilityGTEFn, SubstitutionMap(), args); diff --git a/lib/SILGen/SILGenDestructor.cpp b/lib/SILGen/SILGenDestructor.cpp index 1c816b3314ce5..3041fb58404ee 100644 --- a/lib/SILGen/SILGenDestructor.cpp +++ b/lib/SILGen/SILGenDestructor.cpp @@ -232,7 +232,8 @@ void SILGenFunction::emitObjCDestructor(SILDeclRef dtor) { auto superclassDtor = SILDeclRef(superclassDtorDecl, SILDeclRef::Kind::Deallocator) .asForeign(); - auto superclassDtorType = SGM.Types.getConstantType(superclassDtor); + auto superclassDtorType = + SGM.Types.getConstantType(getTypeExpansionContext(), superclassDtor); SILValue superclassDtorValue = B.createObjCSuperMethod( cleanupLoc, selfValue, superclassDtor, superclassDtorType); diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 65f4e81ffc9a7..05cedbb18d0df 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -1442,10 +1442,13 @@ RValueEmitter::visitBridgeToObjCExpr(BridgeToObjCExpr *E, SGFContext C) { RValue RValueEmitter::visitArchetypeToSuperExpr(ArchetypeToSuperExpr *E, SGFContext C) { ManagedValue archetype = SGF.emitRValueAsSingleValue(E->getSubExpr()); + auto loweredTy = SGF.getLoweredLoadableType(E->getType()); + if (loweredTy == archetype.getType()) + return RValue(SGF, E, archetype); + // Replace the cleanup with a new one on the superclass value so we always use // concrete retain/release operations. - auto base = SGF.B.createUpcast(E, archetype, - SGF.getLoweredLoadableType(E->getType())); + auto base = SGF.B.createUpcast(E, archetype, loweredTy); return RValue(SGF, E, base); } @@ -1539,7 +1542,8 @@ ManagedValue emitCFunctionPointer(SILGenFunction &SGF, // Produce a reference to the C-compatible entry point for the function. SILDeclRef constant(loc, /*curried*/ false, /*foreign*/ true); - SILConstantInfo constantInfo = SGF.getConstantInfo(constant); + SILConstantInfo constantInfo = + SGF.getConstantInfo(SGF.getTypeExpansionContext(), constant); // C function pointers cannot capture anything from their context. auto captures = SGF.SGM.Types.getLoweredLocalCaptures(constant); @@ -1968,7 +1972,11 @@ RValue RValueEmitter::visitUnderlyingToOpaqueExpr(UnderlyingToOpaqueExpr *E, E->getSubExpr()->getType()); auto &underlyingSubstTL = SGF.getTypeLowering(E->getSubExpr()->getType()); - + + if (underlyingSubstTL.getLoweredType() == opaqueTL.getLoweredType()) { + return SGF.emitRValue(E->getSubExpr(), C); + } + // If the opaque type is address only, initialize in place. if (opaqueTL.getLoweredType().isAddress()) { auto opaqueAddr = SGF.getBufferForExprResult( @@ -2007,15 +2015,18 @@ RValue RValueEmitter::visitUnderlyingToOpaqueExpr(UnderlyingToOpaqueExpr *E, // If the opaque type is loadable, emit the subexpression and bitcast it. auto value = SGF.emitRValueAsSingleValue(E->getSubExpr()); - if (underlyingSubstTL.getLoweredType() == underlyingTL.getLoweredType()) { + if (underlyingSubstTL.getLoweredType() != underlyingTL.getLoweredType()) { value = SGF.emitSubstToOrigValue(E, value, AbstractionPattern::getOpaque(), E->getSubExpr()->getType()->getCanonicalType()); } - + + if (value.getType() == opaqueTL.getLoweredType()) + return RValue(SGF, E, value); + auto cast = SGF.B.createUncheckedBitCast(E, value.forward(SGF), - opaqueTL.getLoweredType()); + opaqueTL.getLoweredType()); value = SGF.emitManagedRValueWithCleanup(cast); - + return RValue(SGF, E, value); } @@ -2198,7 +2209,8 @@ SILGenFunction::emitApplyOfDefaultArgGenerator(SILLocation loc, if (fnType->isPolymorphic()) subs = defaultArgsOwner.getSubstitutions(); - auto substFnType = fnType->substGenericArgs(SGM.M, subs); + auto substFnType = + fnType->substGenericArgs(SGM.M, subs, getTypeExpansionContext()); CalleeTypeInfo calleeTypeInfo(substFnType, origResultType, resultType); ResultPlanPtr resultPtr = @@ -2225,7 +2237,8 @@ RValue SILGenFunction::emitApplyOfStoredPropertyInitializer( auto fnRef = ManagedValue::forUnmanaged(emitGlobalFunctionRef(loc, constant)); auto fnType = fnRef.getType().castTo(); - auto substFnType = fnType->substGenericArgs(SGM.M, subs); + auto substFnType = + fnType->substGenericArgs(SGM.M, subs, getTypeExpansionContext()); CalleeTypeInfo calleeTypeInfo(substFnType, origResultType, resultType); ResultPlanPtr resultPlan = @@ -2650,8 +2663,10 @@ static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM, GenericContextScope scope(SGM.Types, genericSig); AbstractionPattern opaque = AbstractionPattern::getOpaque(); - loweredBaseTy = SGM.Types.getLoweredRValueType(opaque, baseType); - loweredPropTy = SGM.Types.getLoweredRValueType(opaque, propertyType); + loweredBaseTy = SGM.Types.getLoweredRValueType( + TypeExpansionContext::minimal(), opaque, baseType); + loweredPropTy = SGM.Types.getLoweredRValueType( + TypeExpansionContext::minimal(), opaque, propertyType); } auto paramConvention = ParameterConvention::Indirect_In_Guaranteed; @@ -2786,8 +2801,10 @@ static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM, GenericContextScope scope(SGM.Types, genericSig); AbstractionPattern opaque = AbstractionPattern::getOpaque(); - loweredBaseTy = SGM.Types.getLoweredRValueType(opaque, baseType); - loweredPropTy = SGM.Types.getLoweredRValueType(opaque, propertyType); + loweredBaseTy = SGM.Types.getLoweredRValueType( + TypeExpansionContext::minimal(), opaque, baseType); + loweredPropTy = SGM.Types.getLoweredRValueType( + TypeExpansionContext::minimal(), opaque, propertyType); } auto &C = SGM.getASTContext(); @@ -2968,8 +2985,8 @@ getOrCreateKeyPathEqualsAndHash(SILGenModule &SGM, RValue indexValue(indexTupleTy); auto indexLoweredTy = - SILType::getPrimitiveAddressType( - SGM.Types.getLoweredRValueType(indexTupleTy)); + SILType::getPrimitiveAddressType(SGM.Types.getLoweredRValueType( + TypeExpansionContext::minimal(), indexTupleTy)); // Get or create the equals witness [unsafeRawPointerTy, boolTy, genericSig, &C, &indexTypes, &equals, loc, @@ -3031,8 +3048,9 @@ getOrCreateKeyPathEqualsAndHash(SILGenModule &SGM, auto equalsMethod = equatableProtocol->getSingleRequirement( C.Id_EqualsOperator); auto equalsRef = SILDeclRef(equalsMethod); - auto equalsTy = subSGF.SGM.Types.getConstantType(equalsRef); - + auto equalsTy = subSGF.SGM.Types.getConstantType( + TypeExpansionContext(subSGF.F), equalsRef); + auto isFalseBB = subSGF.createBasicBlock(); auto i1Ty = SILType::getBuiltinIntegerType(1, C); for (unsigned i : indices(indexes)) { @@ -3064,8 +3082,8 @@ getOrCreateKeyPathEqualsAndHash(SILGenModule &SGM, = SubstitutionMap::getProtocolSubstitutions(equatableProtocol, formalCanTy, equatable); - auto equalsSubstTy = equalsTy.castTo() - ->substGenericArgs(SGM.M, equatableSub); + auto equalsSubstTy = equalsTy.castTo()->substGenericArgs( + SGM.M, equatableSub, TypeExpansionContext(subSGF.F)); auto equalsInfo = CalleeTypeInfo(equalsSubstTy, AbstractionPattern(boolTy), boolTy, None, @@ -3310,8 +3328,8 @@ lowerKeyPathSubscriptIndexTypes( } auto indexLoweredTy = SGM.Types.getLoweredType( - AbstractionPattern::getOpaque(), - indexTy, expansion); + AbstractionPattern::getOpaque(), indexTy, + TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(expansion)); indexLoweredTy = indexLoweredTy.mapTypeOutOfContext(); indexPatterns.push_back({indexTy->mapTypeOutOfContext() ->getCanonicalType(), diff --git a/lib/SILGen/SILGenForeignError.cpp b/lib/SILGen/SILGenForeignError.cpp index 41acb7b8646da..ad33042cd1cf5 100644 --- a/lib/SILGen/SILGenForeignError.cpp +++ b/lib/SILGen/SILGenForeignError.cpp @@ -113,7 +113,8 @@ static SILValue emitIntValue(SILGenFunction &SGF, SILLocation loc, if (auto structDecl = type.getStructOrBoundGenericStruct()) { auto properties = structDecl->getStoredProperties(); assert(properties.size() == 1); - SILType fieldType = type.getFieldType(properties[0], SGF.SGM.M); + SILType fieldType = type.getFieldType(properties[0], SGF.SGM.M, + SGF.getTypeExpansionContext()); SILValue fieldValue = emitIntValue(SGF, loc, fieldType, value); return SGF.B.createStruct(loc, type, fieldValue); } diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index 9fca470e3feb4..307ef69050cf2 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -153,10 +153,12 @@ SILGenFunction::emitSiblingMethodRef(SILLocation loc, // dispatch (viz. objc_msgSend for now). if (methodConstant.hasDecl() && methodConstant.getDecl()->isObjCDynamic()) { - methodValue = emitDynamicMethodRef( - loc, methodConstant, - SGM.Types.getConstantInfo(methodConstant).SILFnType) - .getValue(); + methodValue = + emitDynamicMethodRef( + loc, methodConstant, + SGM.Types.getConstantInfo(getTypeExpansionContext(), methodConstant) + .SILFnType) + .getValue(); } else { methodValue = emitGlobalFunctionRef(loc, methodConstant); } @@ -164,7 +166,8 @@ SILGenFunction::emitSiblingMethodRef(SILLocation loc, SILType methodTy = methodValue->getType(); // Specialize the generic method. - methodTy = methodTy.substGenericArgs(SGM.M, subMap); + methodTy = + methodTy.substGenericArgs(SGM.M, subMap, getTypeExpansionContext()); return std::make_tuple(ManagedValue::forUnmanaged(methodValue), methodTy); @@ -190,8 +193,8 @@ void SILGenFunction::emitCaptures(SILLocation loc, canGuarantee = true; break; } - - auto expansion = F.getResilienceExpansion(); + + auto expansion = getTypeExpansionContext(); for (auto capture : captureInfo.getCaptures()) { if (capture.isDynamicSelfMetadata()) { @@ -262,10 +265,12 @@ void SILGenFunction::emitCaptures(SILLocation loc, capturedArgs.push_back(emitUndef(getLoweredType(type).getAddressType())); break; case CaptureKind::Box: { - auto boxTy = SGM.Types.getContextBoxTypeForCapture(vd, - getLoweredType(type).getASTType(), - FunctionDC->getGenericEnvironmentOfContext(), - /*mutable*/ true); + auto boxTy = SGM.Types.getContextBoxTypeForCapture( + vd, + SGM.Types.getLoweredRValueType(TypeExpansionContext::minimal(), + type), + FunctionDC->getGenericEnvironmentOfContext(), + /*mutable*/ true); capturedArgs.push_back(emitUndef(boxTy)); break; } @@ -273,8 +278,28 @@ void SILGenFunction::emitCaptures(SILLocation loc, continue; } - auto Entry = found->second; + // Get an address value for a SILValue if it is address only in an type + // expansion context without opaque archetype substitution. + auto getAddressValue = [&](SILValue entryValue) -> SILValue { + if (SGM.Types + .getTypeLowering( + valueType, + TypeExpansionContext::noOpaqueTypeArchetypesSubstitution( + expansion.getResilienceExpansion())) + .isAddressOnly() && + !entryValue->getType().isAddress()) { + + auto addr = emitTemporaryAllocation(vd, entryValue->getType()); + auto val = B.emitCopyValueOperation(vd, entryValue); + auto &lowering = getTypeLowering(entryValue->getType()); + lowering.emitStore(B, vd, val, addr, StoreOwnershipQualifier::Init); + entryValue = addr; + enterDestroyCleanup(addr); + } + return entryValue; + }; + auto Entry = found->second; switch (SGM.Types.getDeclCaptureKind(capture, expansion)) { case CaptureKind::Constant: { // let declarations. @@ -309,20 +334,25 @@ void SILGenFunction::emitCaptures(SILLocation loc, } case CaptureKind::StorageAddress: { + auto entryValue = getAddressValue(Entry.value); // No-escaping stored declarations are captured as the // address of the value. - assert(Entry.value->getType().isAddress() && "no address for captured var!"); - capturedArgs.push_back(ManagedValue::forLValue(Entry.value)); + assert(entryValue->getType().isAddress() && "no address for captured var!"); + capturedArgs.push_back(ManagedValue::forLValue(entryValue)); break; } case CaptureKind::Box: { + auto entryValue = getAddressValue(Entry.value); // LValues are captured as both the box owning the value and the // address of the value. - assert(Entry.value->getType().isAddress() && "no address for captured var!"); - + assert(entryValue->getType().isAddress() && "no address for captured var!"); + // Boxes of opaque return values stay opaque. + auto minimalLoweredType = SGM.Types.getLoweredRValueType( + TypeExpansionContext::minimal(), type->getCanonicalType()); // If this is a boxed variable, we can use it directly. - if (Entry.box) { + if (Entry.box && + entryValue->getType().getASTType() == minimalLoweredType) { // We can guarantee our own box to the callee. if (canGuarantee) { capturedArgs.push_back( @@ -330,7 +360,7 @@ void SILGenFunction::emitCaptures(SILLocation loc, } else { capturedArgs.push_back(emitManagedRetain(loc, Entry.box)); } - escapesToMark.push_back(Entry.value); + escapesToMark.push_back(entryValue); } else { // Address only 'let' values are passed by box. This isn't great, in // that a variable captured by multiple closures will be boxed for each @@ -343,14 +373,13 @@ void SILGenFunction::emitCaptures(SILLocation loc, // closure context and pass it down to the partially applied function // in-place. // TODO: Use immutable box for immutable captures. - auto boxTy = SGM.Types.getContextBoxTypeForCapture(vd, - Entry.value->getType().getASTType(), - FunctionDC->getGenericEnvironmentOfContext(), - /*mutable*/ true); - + auto boxTy = SGM.Types.getContextBoxTypeForCapture( + vd, minimalLoweredType, FunctionDC->getGenericEnvironmentOfContext(), + /*mutable*/ true); + AllocBoxInst *allocBox = B.createAllocBox(loc, boxTy); ProjectBoxInst *boxAddress = B.createProjectBox(loc, allocBox, 0); - B.createCopyAddr(loc, Entry.value, boxAddress, IsNotTake, + B.createCopyAddr(loc, entryValue, boxAddress, IsNotTake, IsInitialization); if (canGuarantee) capturedArgs.push_back( @@ -377,7 +406,7 @@ SILGenFunction::emitClosureValue(SILLocation loc, SILDeclRef constant, SubstitutionMap subs) { auto loweredCaptureInfo = SGM.Types.getLoweredLocalCaptures(constant); - auto constantInfo = getConstantInfo(constant); + auto constantInfo = getConstantInfo(getTypeExpansionContext(), constant); SILValue functionRef = emitGlobalFunctionRef(loc, constant, constantInfo); SILType functionTy = functionRef->getType(); @@ -400,7 +429,8 @@ SILGenFunction::emitClosureValue(SILLocation loc, SILDeclRef constant, bool wasSpecialized = false; if (!subs.empty()) { - auto specialized = pft->substGenericArgs(F.getModule(), subs); + auto specialized = + pft->substGenericArgs(F.getModule(), subs, getTypeExpansionContext()); functionTy = SILType::getPrimitiveObjectType(specialized); wasSpecialized = true; } diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h index 0887461ea7992..165a09e91442a 100644 --- a/lib/SILGen/SILGenFunction.h +++ b/lib/SILGen/SILGenFunction.h @@ -494,22 +494,35 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction SILGenBuilder &getBuilder() { return B; } SILOptions &getOptions() { return getModule().getOptions(); } + // Returns the type expansion context for types in this function. + TypeExpansionContext getTypeExpansionContext() { + return TypeExpansionContext(getFunction()); + } + const TypeLowering &getTypeLowering(AbstractionPattern orig, Type subst) { return F.getTypeLowering(orig, subst); } const TypeLowering &getTypeLowering(Type t) { return F.getTypeLowering(t); } - CanSILFunctionType getSILFunctionType(AbstractionPattern orig, + CanSILFunctionType getSILFunctionType(TypeExpansionContext context, + AbstractionPattern orig, CanFunctionType substFnType) { - return SGM.Types.getSILFunctionType(orig, substFnType); + return SGM.Types.getSILFunctionType(context, orig, substFnType); } - SILType getLoweredType(AbstractionPattern orig, Type subst) { + SILType getLoweredType(AbstractionPattern orig, + Type subst) { return F.getLoweredType(orig, subst); } SILType getLoweredType(Type t) { return F.getLoweredType(t); } + SILType getLoweredTypeForFunctionArgument(Type t) { + auto typeForConv = + SGM.Types.getLoweredType(t, TypeExpansionContext::minimal()); + return getLoweredType(t).getCategoryType(typeForConv.getCategory()); + } + SILType getLoweredLoadableType(Type t) { return F.getLoweredLoadableType(t); } @@ -524,8 +537,19 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction return silConv.getSILType(result, fnTy); } - const SILConstantInfo &getConstantInfo(SILDeclRef constant) { - return SGM.Types.getConstantInfo(constant); + SILType getSILTypeInContext(SILResultInfo result, CanSILFunctionType fnTy) { + auto t = F.mapTypeIntoContext(getSILType(result, fnTy)); + return getTypeLowering(t).getLoweredType().getCategoryType(t.getCategory()); + } + + SILType getSILTypeInContext(SILParameterInfo param, CanSILFunctionType fnTy) { + auto t = F.mapTypeIntoContext(getSILType(param, fnTy)); + return getTypeLowering(t).getLoweredType().getCategoryType(t.getCategory()); + } + + const SILConstantInfo &getConstantInfo(TypeExpansionContext context, + SILDeclRef constant) { + return SGM.Types.getConstantInfo(context, constant); } Optional getStaticEnforcement(VarDecl *var = nullptr); @@ -1162,7 +1186,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction /// Returns a reference to a constant in global context. For local func decls /// this returns the function constant with unapplied closure context. SILValue emitGlobalFunctionRef(SILLocation loc, SILDeclRef constant) { - return emitGlobalFunctionRef(loc, constant, getConstantInfo(constant)); + return emitGlobalFunctionRef( + loc, constant, getConstantInfo(getTypeExpansionContext(), constant)); } SILValue emitGlobalFunctionRef(SILLocation loc, SILDeclRef constant, diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp index caf7acfc56ffa..747c6a97d1922 100644 --- a/lib/SILGen/SILGenLValue.cpp +++ b/lib/SILGen/SILGenLValue.cpp @@ -201,35 +201,37 @@ static CanType getSubstFormalRValueType(Expr *expr) { return expr->getType()->getRValueType()->getCanonicalType(); } -static LValueTypeData getAbstractedTypeData(SILGenModule &SGM, +static LValueTypeData getAbstractedTypeData(TypeExpansionContext context, + SILGenModule &SGM, SGFAccessKind accessKind, AbstractionPattern origFormalType, CanType substFormalType) { return { - accessKind, - origFormalType, - substFormalType, - SGM.Types.getLoweredRValueType(origFormalType, substFormalType) - }; + accessKind, origFormalType, substFormalType, + SGM.Types.getLoweredRValueType(context, origFormalType, substFormalType)}; } -static LValueTypeData getLogicalStorageTypeData(SILGenModule &SGM, +static LValueTypeData getLogicalStorageTypeData(TypeExpansionContext context, + SILGenModule &SGM, SGFAccessKind accessKind, CanType substFormalType) { assert(!isa(substFormalType)); AbstractionPattern origFormalType( substFormalType.getReferenceStorageReferent()); - return getAbstractedTypeData(SGM, accessKind, origFormalType, substFormalType); + return getAbstractedTypeData(context, SGM, accessKind, origFormalType, + substFormalType); } -static LValueTypeData getPhysicalStorageTypeData(SILGenModule &SGM, +static LValueTypeData getPhysicalStorageTypeData(TypeExpansionContext context, + SILGenModule &SGM, SGFAccessKind accessKind, AbstractStorageDecl *storage, CanType substFormalType) { assert(!isa(substFormalType)); auto origFormalType = SGM.Types.getAbstractionPattern(storage) .getReferenceStorageReferentType(); - return getAbstractedTypeData(SGM, accessKind, origFormalType, substFormalType); + return getAbstractedTypeData(context, SGM, accessKind, origFormalType, + substFormalType); } static bool shouldUseUnsafeEnforcement(VarDecl *var) { @@ -1208,7 +1210,8 @@ namespace { bool doesAccessorMutateSelf(SILGenFunction &SGF, SILDeclRef accessor) const { - auto accessorSelf = SGF.SGM.Types.getConstantSelfParameter(accessor); + auto accessorSelf = SGF.SGM.Types.getConstantSelfParameter( + SGF.getTypeExpansionContext(), accessor); return accessorSelf.getInterfaceType() && accessorSelf.isIndirectMutating(); } @@ -1396,10 +1399,12 @@ namespace { CanType ValType = SGF.F.mapTypeIntoContext(backingVar->getInterfaceType()) ->getCanonicalType(); - SILType varStorageType = - SGF.SGM.Types.getSubstitutedStorageType(backingVar, ValType); + // TODO: revist minimal + SILType varStorageType = SGF.SGM.Types.getSubstitutedStorageType( + TypeExpansionContext::minimal(), backingVar, ValType); auto typeData = - getLogicalStorageTypeData(SGF.SGM, getTypeData().AccessKind, ValType); + getLogicalStorageTypeData(SGF.getTypeExpansionContext(), SGF.SGM, + getTypeData().AccessKind, ValType); // Get the address of the storage property. ManagedValue proj; @@ -1441,11 +1446,13 @@ namespace { ManagedValue initFn = SGF.emitManagedRValueWithCleanup(initPAI); // Create the allocating setter function. It captures the base address. - auto setterInfo = SGF.getConstantInfo(setter); + auto setterInfo = + SGF.getConstantInfo(SGF.getTypeExpansionContext(), setter); SILValue setterFRef; if (setter.hasDecl() && setter.getDecl()->isObjCDynamic()) { auto methodTy = SILType::getPrimitiveObjectType( - SGF.SGM.Types.getConstantFunctionType(setter)); + SGF.SGM.Types.getConstantFunctionType(SGF.getTypeExpansionContext(), + setter)); setterFRef = SGF.B.createObjCMethod( loc, base.getValue(), setter, methodTy); } else @@ -2016,7 +2023,8 @@ namespace { projectFnType->getInvocationGenericSignature(), keyPathTy->getGenericArgs(), {}); - auto substFnType = projectFnType->substGenericArgs(SGF.SGM.M, subs); + auto substFnType = projectFnType->substGenericArgs( + SGF.SGM.M, subs, SGF.getTypeExpansionContext()); // Perform the begin_apply. SmallVector yields; @@ -2484,8 +2492,9 @@ namespace { void emitUsingStrategy(AccessStrategy strategy) { switch (strategy.getKind()) { case AccessStrategy::Storage: { - auto typeData = getPhysicalStorageTypeData(SGF.SGM, AccessKind, Storage, - FormalRValueType); + auto typeData = + getPhysicalStorageTypeData(SGF.getTypeExpansionContext(), SGF.SGM, + AccessKind, Storage, FormalRValueType); return asImpl().emitUsingStorage(typeData); } @@ -2496,8 +2505,8 @@ namespace { return asImpl().emitUsingAccessor(strategy.getAccessor(), false); case AccessStrategy::MaterializeToTemporary: { - auto typeData = - getLogicalStorageTypeData(SGF.SGM, AccessKind, FormalRValueType); + auto typeData = getLogicalStorageTypeData( + SGF.getTypeExpansionContext(), SGF.SGM, AccessKind, FormalRValueType); return asImpl().emitUsingMaterialization(strategy.getReadStrategy(), strategy.getWriteStrategy(), typeData); @@ -2513,22 +2522,24 @@ namespace { switch (accessorKind) { case AccessorKind::Get: case AccessorKind::Set: { - auto typeData = - getLogicalStorageTypeData(SGF.SGM, AccessKind, FormalRValueType); + auto typeData = getLogicalStorageTypeData( + SGF.getTypeExpansionContext(), SGF.SGM, AccessKind, FormalRValueType); return asImpl().emitUsingGetterSetter(accessor, isDirect, typeData); } case AccessorKind::Address: case AccessorKind::MutableAddress: { - auto typeData = getPhysicalStorageTypeData(SGF.SGM, AccessKind, Storage, - FormalRValueType); + auto typeData = + getPhysicalStorageTypeData(SGF.getTypeExpansionContext(), SGF.SGM, + AccessKind, Storage, FormalRValueType); return asImpl().emitUsingAddressor(accessor, isDirect, typeData); } case AccessorKind::Read: case AccessorKind::Modify: { - auto typeData = getPhysicalStorageTypeData(SGF.SGM, AccessKind, Storage, - FormalRValueType); + auto typeData = + getPhysicalStorageTypeData(SGF.getTypeExpansionContext(), SGF.SGM, + AccessKind, Storage, FormalRValueType); return asImpl().emitUsingCoroutineAccessor(accessor, isDirect, typeData); } @@ -3052,8 +3063,8 @@ struct MemberStorageAccessEmitter : AccessEmitter { void emitUsingAddressor(SILDeclRef addressor, bool isDirect, LValueTypeData typeData) { - SILType varStorageType = - SGF.SGM.Types.getSubstitutedStorageType(Storage, FormalRValueType); + SILType varStorageType = SGF.SGM.Types.getSubstitutedStorageType( + SGF.getTypeExpansionContext(), Storage, FormalRValueType); LV.add(Storage, addressor, IsSuper, isDirect, Subs, BaseFormalType, typeData, varStorageType, @@ -3117,8 +3128,8 @@ void LValue::addMemberVarComponent(SILGenFunction &SGF, SILLocation loc, } // Otherwise, it's a physical member. - SILType varStorageType = - SGF.SGM.Types.getSubstitutedStorageType(Storage, FormalRValueType); + SILType varStorageType = SGF.SGM.Types.getSubstitutedStorageType( + SGF.getTypeExpansionContext(), Storage, FormalRValueType); if (BaseFormalType->mayHaveSuperclass()) { LV.add(Storage, Options, varStorageType, typeData); @@ -3254,8 +3265,8 @@ LValue SILGenLValue::visitKeyPathApplicationExpr(KeyPathApplicationExpr *e, }(); if (useLogical) { - auto typeData = getLogicalStorageTypeData(SGF.SGM, accessKind, - substFormalType); + auto typeData = getLogicalStorageTypeData( + SGF.getTypeExpansionContext(), SGF.SGM, accessKind, substFormalType); Type baseFormalType = e->getBase()->getType()->getRValueType(); lv.add(typeData, keyPathKind, keyPath, @@ -3265,9 +3276,9 @@ LValue SILGenLValue::visitKeyPathApplicationExpr(KeyPathApplicationExpr *e, // in the opaque AbstractionPattern and push an OrigToSubstComponent here // so it can be peepholed. } else { - auto typeData = getAbstractedTypeData(SGF.SGM, accessKind, - AbstractionPattern::getOpaque(), - substFormalType); + auto typeData = getAbstractedTypeData( + TypeExpansionContext::minimal(), SGF.SGM, accessKind, + AbstractionPattern::getOpaque(), substFormalType); lv.add(typeData, keyPathKind, keyPath); diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp index f54c4f90a4128..3b95cc66d571e 100644 --- a/lib/SILGen/SILGenPattern.cpp +++ b/lib/SILGen/SILGenPattern.cpp @@ -1878,7 +1878,8 @@ void PatternMatchEmission::emitEnumElementObjectDispatch( bool hasNonVoidAssocValue = false; bool hasAssocValue = elt->hasAssociatedValues(); if (hasAssocValue) { - eltTy = src.getType().getEnumElementType(elt, SGF.SGM.M); + eltTy = src.getType().getEnumElementType(elt, SGF.SGM.M, + SGF.getTypeExpansionContext()); hasNonVoidAssocValue = !eltTy.getASTType()->isVoid(); } @@ -2060,7 +2061,8 @@ void PatternMatchEmission::emitEnumElementDispatch( SILType eltTy; bool hasElt = false; if (elt->hasAssociatedValues()) { - eltTy = src.getType().getEnumElementType(elt, SGF.SGM.M); + eltTy = src.getType().getEnumElementType(elt, SGF.SGM.M, + SGF.getTypeExpansionContext()); hasElt = !eltTy.getASTType()->isVoid(); } diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp index a62315dc41e03..9fea54ed37d55 100644 --- a/lib/SILGen/SILGenPoly.cpp +++ b/lib/SILGen/SILGenPoly.cpp @@ -787,7 +787,11 @@ void SILGenFunction::collectThunkParams( // Add the indirect results. for (auto resultTy : F.getConventions().getIndirectSILResultTypes()) { auto paramTy = F.mapTypeIntoContext(resultTy); - SILArgument *arg = F.begin()->createFunctionArgument(paramTy); + // Lower result parameters in the context of the function: opaque result + // types will be lowered to their underlying type if allowed by resilience. + auto inContextParamTy = F.getLoweredType(paramTy.getASTType()) + .getCategoryType(paramTy.getCategory()); + SILArgument *arg = F.begin()->createFunctionArgument(inContextParamTy); if (indirectResults) indirectResults->push_back(arg); } @@ -796,7 +800,11 @@ void SILGenFunction::collectThunkParams( auto paramTypes = F.getLoweredFunctionType()->getParameters(); for (auto param : paramTypes) { auto paramTy = F.mapTypeIntoContext(F.getConventions().getSILType(param)); - params.push_back(B.createInputFunctionArgument(paramTy, loc)); + // Lower parameters in the context of the function: opaque result types will + // be lowered to their underlying type if allowed by resilience. + auto inContextParamTy = F.getLoweredType(paramTy.getASTType()) + .getCategoryType(paramTy.getCategory()); + params.push_back(B.createInputFunctionArgument(inContextParamTy, loc)); } } @@ -2689,8 +2697,8 @@ void ResultPlanner::execute(ArrayRef innerDirectResults, // A helper function to add an outer direct result. auto addOuterDirectResult = [&](ManagedValue resultValue, SILResultInfo result) { - assert(resultValue.getType() - == SGF.F.mapTypeIntoContext(SGF.getSILType(result, CanSILFunctionType()))); + assert(resultValue.getType() == + SGF.getSILTypeInContext(result, CanSILFunctionType())); outerDirectResults.push_back(resultValue.forward(SGF)); }; @@ -3563,16 +3571,19 @@ SILGenFunction::emitVTableThunk(SILDeclRef base, CanSILFunctionType derivedFTy; if (baseLessVisibleThanDerived) { - derivedFTy = SGM.Types.getConstantOverrideType(derived); + derivedFTy = + SGM.Types.getConstantOverrideType(getTypeExpansionContext(), derived); } else { - derivedFTy = SGM.Types.getConstantInfo(derived).SILFnType; + derivedFTy = + SGM.Types.getConstantInfo(getTypeExpansionContext(), derived).SILFnType; } SubstitutionMap subs; if (auto *genericEnv = fd->getGenericEnvironment()) { F.setGenericEnvironment(genericEnv); subs = getForwardingSubstitutionMap(); - derivedFTy = derivedFTy->substGenericArgs(SGM.M, subs); + derivedFTy = + derivedFTy->substGenericArgs(SGM.M, subs, getTypeExpansionContext()); inputSubstType = cast( cast(inputSubstType) @@ -3622,7 +3633,8 @@ SILGenFunction::emitVTableThunk(SILDeclRef base, if (baseLessVisibleThanDerived) { // See the comment in SILVTableVisitor.h under maybeAddMethod(). auto selfValue = thunkArgs.back().getValue(); - auto derivedTy = SGM.Types.getConstantOverrideType(derived); + auto derivedTy = + SGM.Types.getConstantOverrideType(getTypeExpansionContext(), derived); derivedRef = emitClassMethodRef(loc, selfValue, derived, derivedTy); } else { derivedRef = B.createFunctionRefFor(loc, implFn); @@ -3744,16 +3756,15 @@ static WitnessDispatchKind getWitnessDispatchKind(SILDeclRef witness, } static CanSILFunctionType -getWitnessFunctionType(SILGenModule &SGM, - SILDeclRef witness, - WitnessDispatchKind witnessKind) { +getWitnessFunctionType(TypeExpansionContext context, SILGenModule &SGM, + SILDeclRef witness, WitnessDispatchKind witnessKind) { switch (witnessKind) { case WitnessDispatchKind::Static: case WitnessDispatchKind::Dynamic: case WitnessDispatchKind::Witness: - return SGM.Types.getConstantInfo(witness).SILFnType; + return SGM.Types.getConstantInfo(context, witness).SILFnType; case WitnessDispatchKind::Class: - return SGM.Types.getConstantOverrideType(witness); + return SGM.Types.getConstantOverrideType(context, witness); } llvm_unreachable("Unhandled WitnessDispatchKind in switch."); @@ -3838,7 +3849,7 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy, collectThunkParams(loc, origParams); // Get the type of the witness. - auto witnessInfo = getConstantInfo(witness); + auto witnessInfo = getConstantInfo(getTypeExpansionContext(), witness); CanAnyFunctionType witnessSubstTy = witnessInfo.LoweredType; if (auto genericFnType = dyn_cast(witnessSubstTy)) { witnessSubstTy = cast(genericFnType @@ -3857,10 +3868,12 @@ void SILGenFunction::emitProtocolWitness(AbstractionPattern reqtOrigTy, } // Get the lowered type of the witness. - auto origWitnessFTy = getWitnessFunctionType(SGM, witness, witnessKind); + auto origWitnessFTy = getWitnessFunctionType(getTypeExpansionContext(), SGM, + witness, witnessKind); auto witnessFTy = origWitnessFTy; if (!witnessSubs.empty()) - witnessFTy = origWitnessFTy->substGenericArgs(SGM.M, witnessSubs); + witnessFTy = origWitnessFTy->substGenericArgs(SGM.M, witnessSubs, + getTypeExpansionContext()); auto reqtSubstParams = reqtSubstTy.getParams(); auto witnessSubstParams = witnessSubstTy.getParams(); diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp index d3b9edb10248b..4c57bf2e96ee1 100644 --- a/lib/SILGen/SILGenProlog.cpp +++ b/lib/SILGen/SILGenProlog.cpp @@ -98,9 +98,14 @@ class EmitBBArguments : public CanTypeVisitor elements; - auto &tl = SGF.SGM.Types.getTypeLowering(t, ResilienceExpansion::Minimal); + auto &tl = SGF.SGM.Types.getTypeLowering(t, SGF.getTypeExpansionContext()); bool canBeGuaranteed = tl.isLoadable(); // Collect the exploded elements. @@ -226,9 +231,10 @@ struct ArgumentInitHelper { uint16_t ArgNo = 0; ArgumentInitHelper(SILGenFunction &SGF, SILFunction &f) - : SGF(SGF), f(f), initB(SGF.B), - parameters(f.getLoweredFunctionType()->getParameters()) { - } + : SGF(SGF), f(f), initB(SGF.B), + parameters( + f.getLoweredFunctionTypeInContext(SGF.B.getTypeExpansionContext()) + ->getParameters()) {} unsigned getNumArgs() const { return ArgNo; } @@ -320,8 +326,7 @@ static void makeArgument(Type ty, ParamDecl *decl, for (auto fieldType : tupleTy->getElementTypes()) makeArgument(fieldType, decl, args, SGF); } else { - auto loweredTy = SGF.SGM.Types.getLoweredType(ty, - ResilienceExpansion::Minimal); + auto loweredTy = SGF.getLoweredTypeForFunctionArgument(ty); if (decl->isInOut()) loweredTy = SILType::getPrimitiveAddressType(loweredTy.getASTType()); auto arg = SGF.F.begin()->createFunctionArgument(loweredTy, decl); @@ -358,7 +363,7 @@ static void emitCaptureArguments(SILGenFunction &SGF, return SGF.F.mapTypeIntoContext(interfaceType); }; - auto expansion = SGF.F.getResilienceExpansion(); + auto expansion = SGF.getTypeExpansionContext(); switch (SGF.SGM.Types.getDeclCaptureKind(capture, expansion)) { case CaptureKind::Constant: { auto type = getVarTypeInCaptureContext(); @@ -400,9 +405,13 @@ static void emitCaptureArguments(SILGenFunction &SGF, // LValues are captured as a retained @box that owns // the captured value. auto type = getVarTypeInCaptureContext(); - auto boxTy = SGF.SGM.Types.getContextBoxTypeForCapture(VD, - SGF.SGM.Types.getLoweredRValueType(type), - SGF.F.getGenericEnvironment(), /*mutable*/ true); + // Get the content for the box in the minimal resilience domain because we + // are declaring a type. + auto boxTy = SGF.SGM.Types.getContextBoxTypeForCapture( + VD, + SGF.SGM.Types.getLoweredRValueType(TypeExpansionContext::minimal(), + type), + SGF.F.getGenericEnvironment(), /*mutable*/ true); SILValue box = SGF.F.begin()->createFunctionArgument( SILType::getPrimitiveObjectType(boxTy), VD); SILValue addr = SGF.B.createProjectBox(VD, box, 0); @@ -499,9 +508,12 @@ static void emitIndirectResultParameters(SILGenFunction &SGF, Type resultType, // The calling convention always uses minimal resilience expansion. auto &resultTI = SGF.SGM.Types.getTypeLowering(DC->mapTypeIntoContext(resultType), - ResilienceExpansion::Minimal); + SGF.getTypeExpansionContext()); + auto &resultTIConv = SGF.SGM.Types.getTypeLowering( + DC->mapTypeIntoContext(resultType), TypeExpansionContext::minimal()); + if (!SILModuleConventions::isReturnedIndirectlyInSIL( - resultTI.getLoweredType(), SGF.SGM.M)) { + resultTIConv.getLoweredType(), SGF.SGM.M)) { return; } auto &ctx = SGF.getASTContext(); @@ -511,9 +523,8 @@ static void emitIndirectResultParameters(SILGenFunction &SGF, Type resultType, DC); var->setSpecifier(ParamSpecifier::InOut); var->setInterfaceType(resultType); - - auto *arg = - SGF.F.begin()->createFunctionArgument(resultTI.getLoweredType(), var); + auto *arg = SGF.F.begin()->createFunctionArgument( + resultTI.getLoweredType().getAddressType(), var); (void)arg; } diff --git a/lib/SILGen/SILGenThunk.cpp b/lib/SILGen/SILGenThunk.cpp index 37f9557a8ce53..ca420cb1a55aa 100644 --- a/lib/SILGen/SILGenThunk.cpp +++ b/lib/SILGen/SILGenThunk.cpp @@ -97,7 +97,8 @@ getNextUncurryLevelRef(SILGenFunction &SGF, SILLocation loc, SILDeclRef thunk, SILDeclRef next = SILDeclRef(vd, thunk.kind); assert(!next.isCurried); - auto constantInfo = SGF.SGM.Types.getConstantInfo(next); + auto constantInfo = + SGF.SGM.Types.getConstantInfo(SGF.getTypeExpansionContext(), next); // If the function is natively foreign, reference its foreign entry point. if (requiresForeignToNativeThunk(vd)) @@ -118,7 +119,8 @@ getNextUncurryLevelRef(SILGenFunction &SGF, SILLocation loc, SILDeclRef thunk, next}; } - auto methodTy = SGF.SGM.Types.getConstantOverrideType(next); + auto methodTy = SGF.SGM.Types.getConstantOverrideType( + SGF.getTypeExpansionContext(), next); SILValue result = SGF.emitClassMethodRef(loc, selfArg.getValue(), next, methodTy); return {ManagedValue::forUnmanaged(result), @@ -158,7 +160,7 @@ void SILGenFunction::emitCurryThunk(SILDeclRef thunk) { SILLocation loc(vd); Scope S(*this, vd); - auto thunkInfo = SGM.Types.getConstantInfo(thunk); + auto thunkInfo = SGM.Types.getConstantInfo(getTypeExpansionContext(), thunk); auto thunkFnTy = thunkInfo.SILFnType; SILFunctionConventions fromConv(thunkFnTy, SGM.M); @@ -192,8 +194,9 @@ void SILGenFunction::emitCurryThunk(SILDeclRef thunk) { // just grab the pattern for the curried fn ref and "call" it. assert(!calleeRef.isCurried); calleeRef.isCurried = true; - auto appliedFnPattern = SGM.Types.getConstantInfo(calleeRef).FormalPattern - .getFunctionResultType(); + auto appliedFnPattern = + SGM.Types.getConstantInfo(getTypeExpansionContext(), calleeRef) + .FormalPattern.getFunctionResultType(); auto appliedThunkPattern = thunkInfo.FormalPattern.getFunctionResultType(); @@ -265,7 +268,7 @@ SILValue SILGenFunction::emitGlobalFunctionRef(SILLocation loc, SILDeclRef constant, SILConstantInfo constantInfo, bool callPreviousDynamicReplaceableImpl) { - assert(constantInfo == getConstantInfo(constant)); + assert(constantInfo == getConstantInfo(getTypeExpansionContext(), constant)); // Builtins must be fully applied at the point of reference. if (constant.hasDecl() && @@ -289,7 +292,8 @@ SILGenFunction::emitGlobalFunctionRef(SILLocation loc, SILDeclRef constant, } auto f = SGM.getFunction(constant, NotForDefinition); - assert(f->getLoweredFunctionType() == constantInfo.SILFnType); + assert(f->getLoweredFunctionTypeInContext(B.getTypeExpansionContext()) == + constantInfo.SILFnType); if (callPreviousDynamicReplaceableImpl) return B.createPreviousDynamicFunctionRef(loc, f); else diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp index 9e634105d3594..d226f30b7d109 100644 --- a/lib/SILGen/SILGenType.cpp +++ b/lib/SILGen/SILGenType.cpp @@ -87,7 +87,9 @@ SILGenModule::emitVTableMethod(ClassDecl *theClass, derived.kind != SILDeclRef::Kind::Allocator); if (usesObjCDynamicDispatch) { - implFn = getDynamicThunk(derived, Types.getConstantInfo(derived).SILFnType); + implFn = getDynamicThunk( + derived, Types.getConstantInfo(TypeExpansionContext::minimal(), derived) + .SILFnType); } else { implFn = getFunction(derived, NotForDefinition); } @@ -105,11 +107,13 @@ SILGenModule::emitVTableMethod(ClassDecl *theClass, // Determine the derived thunk type by lowering the derived type against the // abstraction pattern of the base. - auto baseInfo = Types.getConstantInfo(base); - auto derivedInfo = Types.getConstantInfo(derived); + auto baseInfo = Types.getConstantInfo(TypeExpansionContext::minimal(), base); + auto derivedInfo = + Types.getConstantInfo(TypeExpansionContext::minimal(), derived); auto basePattern = AbstractionPattern(baseInfo.LoweredType); - - auto overrideInfo = M.Types.getConstantOverrideInfo(derived, base); + + auto overrideInfo = M.Types.getConstantOverrideInfo( + TypeExpansionContext::minimal(), derived, base); // If base method's generic requirements are not satisfied by the derived // method then we need a thunk. @@ -588,7 +592,8 @@ SILFunction *SILGenModule::emitProtocolWitness( ProtocolConformanceRef conformance, SILLinkage linkage, IsSerialized_t isSerialized, SILDeclRef requirement, SILDeclRef witnessRef, IsFreeFunctionWitness_t isFree, Witness witness) { - auto requirementInfo = Types.getConstantInfo(requirement); + auto requirementInfo = + Types.getConstantInfo(TypeExpansionContext::minimal(), requirement); // Work out the lowered function type of the SIL witness thunk. auto reqtOrigTy = cast(requirementInfo.LoweredType); @@ -652,8 +657,9 @@ SILFunction *SILGenModule::emitProtocolWitness( // Lower the witness thunk type with the requirement's abstraction level. auto witnessSILFnType = getNativeSILFunctionType( - M.Types, AbstractionPattern(reqtOrigTy), reqtSubstTy, - requirement, witnessRef, witnessSubsForTypeLowering, conformance); + M.Types, TypeExpansionContext::minimal(), AbstractionPattern(reqtOrigTy), + reqtSubstTy, requirement, witnessRef, witnessSubsForTypeLowering, + conformance); // Mangle the name of the witness thunk. Mangle::ASTMangler NewMangler; @@ -705,7 +711,8 @@ static SILFunction *emitSelfConformanceWitness(SILGenModule &SGM, SelfProtocolConformance *conformance, SILLinkage linkage, SILDeclRef requirement) { - auto requirementInfo = SGM.Types.getConstantInfo(requirement); + auto requirementInfo = + SGM.Types.getConstantInfo(TypeExpansionContext::minimal(), requirement); // Work out the lowered function type of the SIL witness thunk. auto reqtOrigTy = cast(requirementInfo.LoweredType); @@ -734,8 +741,8 @@ static SILFunction *emitSelfConformanceWitness(SILGenModule &SGM, cast(reqtOrigTy.subst(reqtSubs)->getCanonicalType()); // Substitute into the requirement type to get the type of the thunk. - auto witnessSILFnType = - requirementInfo.SILFnType->substGenericArgs(SGM.M, reqtSubs); + auto witnessSILFnType = requirementInfo.SILFnType->substGenericArgs( + SGM.M, reqtSubs, TypeExpansionContext::minimal()); // Mangle the name of the witness thunk. std::string name = [&] { diff --git a/lib/SILGen/SwitchEnumBuilder.cpp b/lib/SILGen/SwitchEnumBuilder.cpp index c230ec981a713..4704d95fae200 100644 --- a/lib/SILGen/SwitchEnumBuilder.cpp +++ b/lib/SILGen/SwitchEnumBuilder.cpp @@ -144,8 +144,8 @@ void SwitchEnumBuilder::emit() && { ManagedValue input; if (decl->hasAssociatedValues()) { // Pull the payload out if we have one. - SILType inputType = - optional.getType().getEnumElementType(decl, builder.getModule()); + SILType inputType = optional.getType().getEnumElementType( + decl, builder.getModule(), builder.getFunction()); input = optional; if (!isAddressOnly) { input = builder.createOwnedPhiArgument(inputType); diff --git a/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp b/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp index 928106140beb0..fbd23936c2238 100644 --- a/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp @@ -380,13 +380,13 @@ void AccessSummaryAnalysis::recompute(FunctionInfo *initial) { } while (needAnotherIteration); } -std::string -AccessSummaryAnalysis::SubAccessSummary::getDescription(SILType BaseType, - SILModule &M) const { +std::string AccessSummaryAnalysis::SubAccessSummary::getDescription( + SILType BaseType, SILModule &M, TypeExpansionContext context) const { std::string sbuf; llvm::raw_string_ostream os(sbuf); - os << AccessSummaryAnalysis::getSubPathDescription(BaseType, SubPath, M); + os << AccessSummaryAnalysis::getSubPathDescription(BaseType, SubPath, M, + context); if (!SubPath->isRoot()) os << " "; @@ -409,9 +409,8 @@ void AccessSummaryAnalysis::ArgumentSummary::getSortedSubAccesses( assert(storage.size() == SubAccesses.size()); } -std::string -AccessSummaryAnalysis::ArgumentSummary::getDescription(SILType BaseType, - SILModule &M) const { +std::string AccessSummaryAnalysis::ArgumentSummary::getDescription( + SILType BaseType, SILModule &M, TypeExpansionContext context) const { std::string sbuf; llvm::raw_string_ostream os(sbuf); os << "["; @@ -425,7 +424,7 @@ AccessSummaryAnalysis::ArgumentSummary::getDescription(SILType BaseType, if (index > 0) { os << ", "; } - os << subAccess.getDescription(BaseType, M); + os << subAccess.getDescription(BaseType, M, context); ++index; } os << "]"; @@ -551,7 +550,8 @@ AccessSummaryAnalysis::findSubPathAccessed(BeginAccessInst *BAI) { /// that stored-property relaxation supports: struct stored properties /// and tuple elements. std::string AccessSummaryAnalysis::getSubPathDescription( - SILType baseType, const IndexTrieNode *subPath, SILModule &M) { + SILType baseType, const IndexTrieNode *subPath, SILModule &M, + TypeExpansionContext context) { // Walk the trie to the root to collect the sequence (in reverse order). llvm::SmallVector reversedIndices; const IndexTrieNode *I = subPath; @@ -570,7 +570,7 @@ std::string AccessSummaryAnalysis::getSubPathDescription( if (StructDecl *D = containingType.getStructOrBoundGenericStruct()) { VarDecl *var = D->getStoredProperties()[index]; os << var->getBaseName(); - containingType = containingType.getFieldType(var, M); + containingType = containingType.getFieldType(var, M, context); continue; } @@ -635,7 +635,8 @@ void AccessSummaryAnalysis::FunctionSummary::print(raw_ostream &os, } SILArgument *arg = fn->getArgument(i); SILModule &m = fn->getModule(); - os << getAccessForArgument(i).getDescription(arg->getType(), m); + os << getAccessForArgument(i).getDescription(arg->getType(), m, + TypeExpansionContext(*fn)); } os << ")"; diff --git a/lib/SILOptimizer/Analysis/AliasAnalysis.cpp b/lib/SILOptimizer/Analysis/AliasAnalysis.cpp index e2db274668799..90e304d0a5084 100644 --- a/lib/SILOptimizer/Analysis/AliasAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/AliasAnalysis.cpp @@ -475,8 +475,8 @@ static bool typedAccessTBAAMayAlias(SILType LTy, SILType RTy, // If one type is an aggregate and it contains the other type then the record // reference may alias the aggregate reference. - if (LTy.aggregateContainsRecord(RTy, Mod) || - RTy.aggregateContainsRecord(LTy, Mod)) + if (LTy.aggregateContainsRecord(RTy, Mod, F.getTypeExpansionContext()) || + RTy.aggregateContainsRecord(LTy, Mod, F.getTypeExpansionContext())) return true; // FIXME: All the code following could be made significantly more aggressive diff --git a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp index ce6af396ff29d..fbe37439c5eb7 100644 --- a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp @@ -70,7 +70,9 @@ static bool findRecursiveRefType(SILType Ty, const SILFunction &F, if (auto *Str = Ty.getStructOrBoundGenericStruct()) { for (auto *Field : Str->getStoredProperties()) { - if (findRecursiveRefType(Ty.getFieldType(Field, Mod), F, mustBeRef)) + if (findRecursiveRefType( + Ty.getFieldType(Field, Mod, F.getTypeExpansionContext()), F, + mustBeRef)) return true; } return false; @@ -84,9 +86,10 @@ static bool findRecursiveRefType(SILType Ty, const SILFunction &F, } if (auto En = Ty.getEnumOrBoundGenericEnum()) { for (auto *ElemDecl : En->getAllElements()) { - if (ElemDecl->hasAssociatedValues() - && findRecursiveRefType(Ty.getEnumElementType(ElemDecl, Mod), F, - mustBeRef)) + if (ElemDecl->hasAssociatedValues() && + findRecursiveRefType( + Ty.getEnumElementType(ElemDecl, Mod, F.getTypeExpansionContext()), + F, mustBeRef)) return true; } return false; diff --git a/lib/SILOptimizer/Analysis/TypeExpansionAnalysis.cpp b/lib/SILOptimizer/Analysis/TypeExpansionAnalysis.cpp index 203e7cca65921..43fa3d930e048 100644 --- a/lib/SILOptimizer/Analysis/TypeExpansionAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/TypeExpansionAnalysis.cpp @@ -24,10 +24,13 @@ using namespace swift; // memory usage of this cache. static const int TypeExpansionAnalysisMaxCacheSize = 4096; -const ProjectionPathList& -TypeExpansionAnalysis::getTypeExpansion(SILType B, SILModule *Mod) { +const ProjectionPathList & +TypeExpansionAnalysis::getTypeExpansion(SILType B, SILModule *Mod, + TypeExpansionContext context) { // Check whether we have the type expansion. - auto Iter = ExpansionCache.find(B); + auto key = std::make_pair(B, context); + auto Iter = ExpansionCache.find(key); + // if (Iter != ExpansionCache.end()) { return Iter->second; } @@ -36,8 +39,8 @@ TypeExpansionAnalysis::getTypeExpansion(SILType B, SILModule *Mod) { if (!shouldExpand(*Mod, B)) { // Push the empty projection path. ProjectionPath P(B); - ExpansionCache[B].push_back(P); - return ExpansionCache[B]; + ExpansionCache[key].push_back(P); + return ExpansionCache[key]; } // Flush the cache if the size of the cache is too large. @@ -46,8 +49,9 @@ TypeExpansionAnalysis::getTypeExpansion(SILType B, SILModule *Mod) { } // Build the type expansion for the leaf nodes. - ProjectionPath::expandTypeIntoLeafProjectionPaths(B, Mod, ExpansionCache[B]); - return ExpansionCache[B]; + ProjectionPath::expandTypeIntoLeafProjectionPaths(B, Mod, context, + ExpansionCache[key]); + return ExpansionCache[key]; } SILAnalysis *swift::createTypeExpansionAnalysis(SILModule *M) { diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp index b4d3be9dbda36..41671b27609de 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp +++ b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp @@ -517,7 +517,8 @@ void ExistentialTransform::populateThunkBody() { MakeAbstractConformanceForGenericType()); /// Perform the substitutions. - auto SubstCalleeType = GenCalleeType->substGenericArgs(M, SubMap); + auto SubstCalleeType = GenCalleeType->substGenericArgs( + M, SubMap, Builder.getTypeExpansionContext()); /// Obtain the Result Type. SILValue ReturnValue; diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp index 620d02b9c3be1..69089e5f54770 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp +++ b/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp @@ -581,8 +581,8 @@ void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() { // Produce a substitutions list and a set of substituted SIL types // required for creating a new SIL function. Subs = F->getForwardingSubstitutionMap(); - auto SubstCalleeType = - GenCalleeType->substGenericArgs(M, Subs); + auto SubstCalleeType = GenCalleeType->substGenericArgs( + M, Subs, Builder.getTypeExpansionContext()); SubstCalleeSILType = SILType::getPrimitiveObjectType(SubstCalleeType); SILFunctionConventions Conv(SubstCalleeType, M); ResultType = Conv.getSILResultType(); diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp index dff5e4489c9e0..db161542862f7 100644 --- a/lib/SILOptimizer/IPO/CapturePromotion.cpp +++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp @@ -368,8 +368,11 @@ computeNewArgInterfaceTypes(SILFunction *F, IndicesSet &PromotableIndices, auto paramBoxTy = paramTy.castTo(); assert(paramBoxTy->getLayout()->getFields().size() == 1 && "promoting compound box not implemented yet"); - auto paramBoxedTy = getSILBoxFieldType(paramBoxTy, Types, 0); - auto ¶mTL = Types.getTypeLowering(paramBoxedTy, expansion); + auto paramBoxedTy = + getSILBoxFieldType(TypeExpansionContext(*F), paramBoxTy, Types, 0); + assert(expansion == F->getResilienceExpansion()); + auto ¶mTL = + Types.getTypeLowering(paramBoxedTy, TypeExpansionContext(*F)); ParameterConvention convention; if (paramTL.isAddressOnly()) { convention = ParameterConvention::Indirect_In; @@ -480,8 +483,9 @@ ClosureCloner::populateCloned() { auto BoxTy = (*I)->getType().castTo(); assert(BoxTy->getLayout()->getFields().size() == 1 && "promoting compound box not implemented"); - auto BoxedTy = getSILBoxFieldType(BoxTy, Cloned->getModule().Types, 0) - .getObjectType(); + auto BoxedTy = getSILBoxFieldType(TypeExpansionContext(*Cloned), BoxTy, + Cloned->getModule().Types, 0) + .getObjectType(); SILValue MappedValue = ClonedEntryBB->createFunctionArgument(BoxedTy, (*I)->getDecl()); @@ -999,7 +1003,8 @@ bool isPartialApplyNonEscapingUser(Operand *CurrentOp, PartialApplyInst *PAI, auto BoxTy = BoxArg->getType().castTo(); assert(BoxTy->getLayout()->getFields().size() == 1 && "promoting compound box not implemented yet"); - if (getSILBoxFieldType(BoxTy, M.Types, 0).isAddressOnly(*F)) { + if (getSILBoxFieldType(TypeExpansionContext(*Fn), BoxTy, M.Types, 0) + .isAddressOnly(*F)) { LLVM_DEBUG(llvm::dbgs() << " FAIL! Box is an address only " "argument!\n"); return false; @@ -1273,8 +1278,8 @@ processPartialApplyInst(SILOptFunctionBuilder &FuncBuilder, auto CalleeFunctionTy = PAI->getCallee()->getType().castTo(); auto SubstCalleeFunctionTy = CalleeFunctionTy; if (PAI->hasSubstitutions()) - SubstCalleeFunctionTy = - CalleeFunctionTy->substGenericArgs(M, PAI->getSubstitutionMap()); + SubstCalleeFunctionTy = CalleeFunctionTy->substGenericArgs( + M, PAI->getSubstitutionMap(), TypeExpansionContext(*F)); SILFunctionConventions calleeConv(SubstCalleeFunctionTy, M); auto CalleePInfo = SubstCalleeFunctionTy->getParameters(); SILFunctionConventions paConv(PAI->getType().castTo(), M); diff --git a/lib/SILOptimizer/IPO/CapturePropagation.cpp b/lib/SILOptimizer/IPO/CapturePropagation.cpp index 0b2ff3827e4d5..d482e8b01ecac 100644 --- a/lib/SILOptimizer/IPO/CapturePropagation.cpp +++ b/lib/SILOptimizer/IPO/CapturePropagation.cpp @@ -421,10 +421,11 @@ static SILFunction *getSpecializedWithDeadParams( return nullptr; // Perform a generic specialization of the Specialized function. - ReabstractionInfo ReInfo(ApplySite(), Specialized, - PAI->getSubstitutionMap(), - Specialized->isSerialized(), - /* ConvertIndirectToDirect */ false); + ReabstractionInfo ReInfo( + FuncBuilder.getModule().getSwiftModule(), + FuncBuilder.getModule().isWholeModule(), ApplySite(), Specialized, + PAI->getSubstitutionMap(), Specialized->isSerialized(), + /* ConvertIndirectToDirect */ false); GenericFuncSpecializer FuncSpecializer(FuncBuilder, Specialized, ReInfo.getClonerParamSubstitutionMap(), diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp index 6395f744aa76b..d9395b29b8f92 100644 --- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp +++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp @@ -800,8 +800,9 @@ void ClosureSpecCloner::populateCloned() { } // Otherwise, create a new argument which copies the original argument + auto typeInContext = Cloned->getLoweredType(Arg->getType()); SILValue MappedValue = - ClonedEntryBB->createFunctionArgument(Arg->getType(), Arg->getDecl()); + ClonedEntryBB->createFunctionArgument(typeInContext, Arg->getDecl()); entryArgs.push_back(MappedValue); } @@ -821,6 +822,8 @@ void ClosureSpecCloner::populateCloned() { unsigned idx = 0; for (auto &PInfo : ClosedOverFunConv.getParameters().slice(NumNotCaptured)) { auto paramTy = ClosedOverFunConv.getSILType(PInfo); + // Get the type in context of the new function. + paramTy = Cloned->getLoweredType(paramTy); SILValue MappedValue = ClonedEntryBB->createFunctionArgument(paramTy); NewPAIArgs.push_back(MappedValue); auto CapturedVal = diff --git a/lib/SILOptimizer/IPO/EagerSpecializer.cpp b/lib/SILOptimizer/IPO/EagerSpecializer.cpp index ca0df01328595..a56bd3c8bdacd 100644 --- a/lib/SILOptimizer/IPO/EagerSpecializer.cpp +++ b/lib/SILOptimizer/IPO/EagerSpecializer.cpp @@ -231,7 +231,8 @@ emitInvocation(SILBuilder &Builder, if (ReInfo.getSpecializedType()->isPolymorphic()) { Subs = ReInfo.getCallerParamSubstitutionMap(); CalleeSubstFnTy = CanSILFuncTy->substGenericArgs( - Builder.getModule(), ReInfo.getCallerParamSubstitutionMap()); + Builder.getModule(), ReInfo.getCallerParamSubstitutionMap(), + Builder.getTypeExpansionContext()); assert(!CalleeSubstFnTy->isPolymorphic() && "Substituted callee type should not be polymorphic"); assert(!CalleeSubstFnTy->hasTypeParameter() && @@ -628,7 +629,8 @@ emitArgumentConversion(SmallVectorImpl &CallArgs) { auto CalleeSubstFnTy = CanSILFuncTy; if (CanSILFuncTy->isPolymorphic()) { CalleeSubstFnTy = CanSILFuncTy->substGenericArgs( - Builder.getModule(), ReInfo.getCallerParamSubstitutionMap()); + Builder.getModule(), ReInfo.getCallerParamSubstitutionMap(), + Builder.getTypeExpansionContext()); assert(!CalleeSubstFnTy->isPolymorphic() && "Substituted callee type should not be polymorphic"); assert(!CalleeSubstFnTy->hasTypeParameter() && @@ -763,7 +765,9 @@ void EagerSpecializerTransform::run() { // TODO: Use a decision-tree to reduce the amount of dynamic checks being // performed. for (auto *SA : F.getSpecializeAttrs()) { - ReInfoVec.emplace_back(&F, SA->getSpecializedSignature()); + ReInfoVec.emplace_back(FuncBuilder.getModule().getSwiftModule(), + FuncBuilder.getModule().isWholeModule(), &F, + SA->getSpecializedSignature()); auto *NewFunc = eagerSpecialize(FuncBuilder, &F, *SA, ReInfoVec.back()); SpecializedFuncs.push_back(NewFunc); diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp index 4581f7faa0cf8..e0cc724ab1a1b 100644 --- a/lib/SILOptimizer/IPO/GlobalOpt.cpp +++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp @@ -264,7 +264,8 @@ static SILFunction *getGlobalGetterFunction(SILOptFunctionBuilder &FunctionBuild Serialized = IsSerialized; } - auto refType = M.Types.getLoweredRValueType(varDecl->getInterfaceType()); + auto refType = M.Types.getLoweredRValueType(TypeExpansionContext::minimal(), + varDecl->getInterfaceType()); // Function takes no arguments and returns refType SILResultInfo Results[] = { SILResultInfo(refType, @@ -747,7 +748,9 @@ void SILGlobalOpt::optimizeInitializer(SILFunction *AddrF, if (hasPublicVisibility(SILG->getLinkage())) expansion = ResilienceExpansion::Minimal; - auto &tl = Module->Types.getTypeLowering(SILG->getLoweredType(), expansion); + auto &tl = Module->Types.getTypeLowering( + SILG->getLoweredType(), + TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(expansion)); if (!tl.isLoadable()) return; diff --git a/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp b/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp index 6fc43adc5fe52..5b1dab1e9ed3c 100644 --- a/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp +++ b/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp @@ -376,7 +376,7 @@ bool LetPropertiesOpt::isConstantLetProperty(VarDecl *Property) { // FIXME: Expansion auto &TL = Module->Types.getTypeLowering(Property->getType(), - ResilienceExpansion::Minimal); + TypeExpansionContext::minimal()); if (!TL.isTrivial()) { LLVM_DEBUG(llvm::dbgs() << "Property '" << *Property << "' is not of trivial type\n"); diff --git a/lib/SILOptimizer/IPO/UsePrespecialized.cpp b/lib/SILOptimizer/IPO/UsePrespecialized.cpp index 2b1e8f58aa42b..b2f7bfde4e40f 100644 --- a/lib/SILOptimizer/IPO/UsePrespecialized.cpp +++ b/lib/SILOptimizer/IPO/UsePrespecialized.cpp @@ -90,7 +90,8 @@ bool UsePrespecialized::replaceByPrespecialized(SILFunction &F) { if (Subs.hasArchetypes()) continue; - ReabstractionInfo ReInfo(AI, ReferencedF, Subs, IsNotSerialized); + ReabstractionInfo ReInfo(M.getSwiftModule(), M.isWholeModule(), AI, + ReferencedF, Subs, IsNotSerialized); if (!ReInfo.canBeSpecialized()) continue; diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp index a8138c942ddc3..5188411efe102 100644 --- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp +++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp @@ -63,7 +63,8 @@ static void gatherDestroysOfContainer(const MarkUninitializedInst *MUI, // DIMemoryObjectInfo Implementation //===----------------------------------------------------------------------===// -static unsigned getElementCountRec(SILModule &Module, SILType T, +static unsigned getElementCountRec(TypeExpansionContext context, + SILModule &Module, SILType T, bool IsSelfOfNonDelegatingInitializer) { // If this is a tuple, it is always recursively flattened. if (CanTupleType TT = T.getAs()) { @@ -71,7 +72,7 @@ static unsigned getElementCountRec(SILModule &Module, SILType T, unsigned NumElements = 0; for (unsigned i = 0, e = TT->getNumElements(); i < e; i++) NumElements += - getElementCountRec(Module, T.getTupleElementType(i), false); + getElementCountRec(context, Module, T.getTupleElementType(i), false); return NumElements; } @@ -83,8 +84,8 @@ static unsigned getElementCountRec(SILModule &Module, SILType T, if (auto *NTD = T.getNominalOrBoundGenericNominal()) { unsigned NumElements = 0; for (auto *VD : NTD->getStoredProperties()) - NumElements += - getElementCountRec(Module, T.getFieldType(VD, Module), false); + NumElements += getElementCountRec( + context, Module, T.getFieldType(VD, Module, context), false); return NumElements; } } @@ -134,7 +135,8 @@ DIMemoryObjectInfo::DIMemoryObjectInfo(MarkUninitializedInst *MI) // Otherwise, we break down the initializer. NumElements = - getElementCountRec(Module, MemorySILType, isNonDelegatingInit()); + getElementCountRec(TypeExpansionContext(*MI->getFunction()), Module, + MemorySILType, isNonDelegatingInit()); // If this is a derived class init method, track an extra element to determine // whether super.init has been called at each program point. @@ -152,16 +154,18 @@ SILInstruction *DIMemoryObjectInfo::getFunctionEntryPoint() const { } /// Given a symbolic element number, return the type of the element. -static SILType getElementTypeRec(SILModule &Module, SILType T, unsigned EltNo, +static SILType getElementTypeRec(TypeExpansionContext context, + SILModule &Module, SILType T, unsigned EltNo, bool IsSelfOfNonDelegatingInitializer) { // If this is a tuple type, walk into it. if (CanTupleType TT = T.getAs()) { assert(!IsSelfOfNonDelegatingInitializer && "self never has tuple type"); for (unsigned i = 0, e = TT->getNumElements(); i < e; i++) { auto FieldType = T.getTupleElementType(i); - unsigned NumFieldElements = getElementCountRec(Module, FieldType, false); + unsigned NumFieldElements = + getElementCountRec(context, Module, FieldType, false); if (EltNo < NumFieldElements) - return getElementTypeRec(Module, FieldType, EltNo, false); + return getElementTypeRec(context, Module, FieldType, EltNo, false); EltNo -= NumFieldElements; } // This can only happen if we look at a symbolic element number of an empty @@ -177,11 +181,11 @@ static SILType getElementTypeRec(SILModule &Module, SILType T, unsigned EltNo, bool HasStoredProperties = false; for (auto *VD : NTD->getStoredProperties()) { HasStoredProperties = true; - auto FieldType = T.getFieldType(VD, Module); + auto FieldType = T.getFieldType(VD, Module, context); unsigned NumFieldElements = - getElementCountRec(Module, FieldType, false); + getElementCountRec(context, Module, FieldType, false); if (EltNo < NumFieldElements) - return getElementTypeRec(Module, FieldType, EltNo, false); + return getElementTypeRec(context, Module, FieldType, EltNo, false); EltNo -= NumFieldElements; } @@ -202,7 +206,8 @@ static SILType getElementTypeRec(SILModule &Module, SILType T, unsigned EltNo, /// getElementTypeRec - Return the swift type of the specified element. SILType DIMemoryObjectInfo::getElementType(unsigned EltNo) const { auto &Module = MemoryInst->getModule(); - return getElementTypeRec(Module, MemorySILType, EltNo, isNonDelegatingInit()); + return getElementTypeRec(TypeExpansionContext(*MemoryInst->getFunction()), + Module, MemorySILType, EltNo, isNonDelegatingInit()); } /// computeTupleElementAddress - Given a tuple element number (in the flattened @@ -225,7 +230,8 @@ SILValue DIMemoryObjectInfo::emitElementAddress( unsigned FieldNo = 0; for (unsigned i = 0, e = TT->getNumElements(); i < e; i++) { auto EltTy = PointeeType.getTupleElementType(i); - unsigned NumSubElt = getElementCountRec(Module, EltTy, false); + unsigned NumSubElt = getElementCountRec( + TypeExpansionContext(B.getFunction()), Module, EltTy, false); if (EltNo < NumSubElt) { Ptr = B.createTupleElementAddr(Loc, Ptr, FieldNo); PointeeType = EltTy; @@ -255,10 +261,11 @@ SILValue DIMemoryObjectInfo::emitElementAddress( EndBorrowList.emplace_back(Borrowed, Original); } } - - auto FieldType = PointeeType.getFieldType(VD, Module); + auto expansionContext = TypeExpansionContext(B.getFunction()); + auto FieldType = + PointeeType.getFieldType(VD, Module, expansionContext); unsigned NumFieldElements = - getElementCountRec(Module, FieldType, false); + getElementCountRec(expansionContext, Module, FieldType, false); if (EltNo < NumFieldElements) { if (isa(NTD)) { Ptr = B.createStructElementAddr(Loc, Ptr, VD); @@ -300,7 +307,8 @@ SILValue DIMemoryObjectInfo::emitElementAddress( /// Push the symbolic path name to the specified element number onto the /// specified std::string. -static void getPathStringToElementRec(SILModule &Module, SILType T, +static void getPathStringToElementRec(TypeExpansionContext context, + SILModule &Module, SILType T, unsigned EltNo, std::string &Result) { CanTupleType TT = T.getAs(); if (!TT) { @@ -313,7 +321,7 @@ static void getPathStringToElementRec(SILModule &Module, SILType T, for (unsigned i = 0, e = TT->getNumElements(); i < e; i++) { auto Field = TT->getElement(i); SILType FieldTy = T.getTupleElementType(i); - unsigned NumFieldElements = getElementCountRec(Module, FieldTy, false); + unsigned NumFieldElements = getElementCountRec(context, Module, FieldTy, false); if (EltNo < NumFieldElements) { Result += '.'; @@ -321,7 +329,7 @@ static void getPathStringToElementRec(SILModule &Module, SILType T, Result += Field.getName().str(); else Result += llvm::utostr(FieldNo); - return getPathStringToElementRec(Module, FieldTy, EltNo, Result); + return getPathStringToElementRec(context, Module, FieldTy, EltNo, Result); } EltNo -= NumFieldElements; @@ -346,14 +354,16 @@ DIMemoryObjectInfo::getPathStringToElement(unsigned Element, Result = ""; // If this is indexing into a field of 'self', look it up. + auto expansionContext = TypeExpansionContext(*MemoryInst->getFunction()); if (isNonDelegatingInit() && !isDerivedClassSelfOnly()) { if (auto *NTD = MemorySILType.getNominalOrBoundGenericNominal()) { bool HasStoredProperty = false; for (auto *VD : NTD->getStoredProperties()) { HasStoredProperty = true; - auto FieldType = MemorySILType.getFieldType(VD, Module); + auto FieldType = + MemorySILType.getFieldType(VD, Module, expansionContext); unsigned NumFieldElements = - getElementCountRec(Module, FieldType, false); + getElementCountRec(expansionContext, Module, FieldType, false); if (Element < NumFieldElements) { Result += '.'; auto originalProperty = VD->getOriginalWrappedProperty(); @@ -362,7 +372,8 @@ DIMemoryObjectInfo::getPathStringToElement(unsigned Element, } else { Result += VD->getName().str(); } - getPathStringToElementRec(Module, FieldType, Element, Result); + getPathStringToElementRec(expansionContext, Module, FieldType, + Element, Result); return VD; } Element -= NumFieldElements; @@ -375,7 +386,8 @@ DIMemoryObjectInfo::getPathStringToElement(unsigned Element, } // Get the path through a tuple, if relevant. - getPathStringToElementRec(Module, MemorySILType, Element, Result); + getPathStringToElementRec(expansionContext, Module, MemorySILType, Element, + Result); // If we are analyzing a variable, we can generally get the decl associated // with it. @@ -402,9 +414,11 @@ bool DIMemoryObjectInfo::isElementLetProperty(unsigned Element) const { return false; } + auto expansionContext = TypeExpansionContext(*MemoryInst->getFunction()); for (auto *VD : NTD->getStoredProperties()) { - auto FieldType = MemorySILType.getFieldType(VD, Module); - unsigned NumFieldElements = getElementCountRec(Module, FieldType, false); + auto FieldType = MemorySILType.getFieldType(VD, Module, expansionContext); + unsigned NumFieldElements = + getElementCountRec(expansionContext, Module, FieldType, false); if (Element < NumFieldElements) return VD->isLet(); Element -= NumFieldElements; @@ -591,7 +605,8 @@ void ElementUseCollector::addElementUses(unsigned BaseEltNo, SILType UseTy, unsigned NumElements = 1; if (TheMemory.NumElements != 1 && !InStructSubElement && !InEnumSubElement) NumElements = - getElementCountRec(Module, UseTy, IsSelfOfNonDelegatingInitializer); + getElementCountRec(TypeExpansionContext(*User->getFunction()), Module, + UseTy, IsSelfOfNonDelegatingInitializer); trackUse(DIMemoryUse(User, Kind, BaseEltNo, NumElements)); } @@ -617,7 +632,8 @@ void ElementUseCollector::collectTupleElementUses(TupleElementAddrInst *TEAI, if (T.is()) { for (unsigned i = 0; i != FieldNo; ++i) { SILType EltTy = T.getTupleElementType(i); - BaseEltNo += getElementCountRec(Module, EltTy, false); + BaseEltNo += getElementCountRec(TypeExpansionContext(*TEAI->getFunction()), + Module, EltTy, false); } } @@ -644,7 +660,8 @@ void ElementUseCollector::collectDestructureTupleResultUses( if (T.is()) { for (unsigned i = 0; i != FieldNo; ++i) { SILType EltTy = T.getTupleElementType(i); - BaseEltNo += getElementCountRec(Module, EltTy, false); + BaseEltNo += getElementCountRec(TypeExpansionContext(*DTR->getFunction()), + Module, EltTy, false); } } @@ -670,8 +687,9 @@ void ElementUseCollector::collectStructElementUses(StructElementAddrInst *SEAI, if (SEAI->getField() == VD) break; - auto FieldType = SEAI->getOperand()->getType().getFieldType(VD, Module); - BaseEltNo += getElementCountRec(Module, FieldType, false); + auto expansionContext = TypeExpansionContext(*SEAI->getFunction()); + auto FieldType = SEAI->getOperand()->getType().getFieldType(VD, Module, expansionContext); + BaseEltNo += getElementCountRec(expansionContext, Module, FieldType, false); } collectUses(SEAI, BaseEltNo); @@ -1119,8 +1137,11 @@ void ElementUseCollector::collectClassSelfUses() { unsigned NumElements = 0; for (auto *VD : NTD->getStoredProperties()) { EltNumbering[VD] = NumElements; - NumElements += - getElementCountRec(Module, T.getFieldType(VD, Module), false); + auto expansionContext = + TypeExpansionContext(*TheMemory.MemoryInst->getFunction()); + NumElements += getElementCountRec( + expansionContext, Module, + T.getFieldType(VD, Module, expansionContext), false); } } diff --git a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp index f4f6247e4aad5..0dec95dd11056 100644 --- a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp +++ b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp @@ -499,12 +499,14 @@ static void addSwapAtFixit(InFlightDiagnostic &Diag, CallExpr *&FoundCall, /// and tuple elements. static std::string getPathDescription(DeclName BaseName, SILType BaseType, const IndexTrieNode *SubPath, - SILModule &M) { + SILModule &M, + TypeExpansionContext context) { std::string sbuf; llvm::raw_string_ostream os(sbuf); os << "'" << BaseName; - os << AccessSummaryAnalysis::getSubPathDescription(BaseType, SubPath, M); + os << AccessSummaryAnalysis::getSubPathDescription(BaseType, SubPath, M, + context); os << "'"; return os.str(); @@ -547,7 +549,8 @@ static void diagnoseExclusivityViolation(const ConflictingAccess &Violation, SILType BaseType = FirstAccess.getInstruction()->getType().getAddressType(); SILModule &M = FirstAccess.getInstruction()->getModule(); std::string PathDescription = getPathDescription( - VD->getBaseName(), BaseType, MainAccess.getSubPath(), M); + VD->getBaseName(), BaseType, MainAccess.getSubPath(), M, + TypeExpansionContext(*FirstAccess.getInstruction()->getFunction())); // Determine whether we can safely suggest replacing the violation with // a call to MutableCollection.swapAt(). diff --git a/lib/SILOptimizer/Mandatory/OSLogOptimization.cpp b/lib/SILOptimizer/Mandatory/OSLogOptimization.cpp index 091ab93943547..4d2c1233b3a08 100644 --- a/lib/SILOptimizer/Mandatory/OSLogOptimization.cpp +++ b/lib/SILOptimizer/Mandatory/OSLogOptimization.cpp @@ -753,9 +753,11 @@ static bool checkOSLogMessageIsConstant(SingleValueInstruction *osLogMessage, StructDecl *structDecl = osLogMessageType.getStructOrBoundGenericStruct(); assert(structDecl); + auto typeExpansionContext = + TypeExpansionContext(*osLogMessage->getFunction()); VarDecl *interpolationPropDecl = structDecl->getStoredProperties().front(); - SILType osLogInterpolationType = - osLogMessageType.getFieldType(interpolationPropDecl, module); + SILType osLogInterpolationType = osLogMessageType.getFieldType( + interpolationPropDecl, module, typeExpansionContext); StructDecl *interpolationStruct = osLogInterpolationType.getStructOrBoundGenericStruct(); assert(interpolationStruct); diff --git a/lib/SILOptimizer/Mandatory/OwnershipModelEliminator.cpp b/lib/SILOptimizer/Mandatory/OwnershipModelEliminator.cpp index 402d40edf5c77..40c47fd45f47d 100644 --- a/lib/SILOptimizer/Mandatory/OwnershipModelEliminator.cpp +++ b/lib/SILOptimizer/Mandatory/OwnershipModelEliminator.cpp @@ -258,7 +258,8 @@ static void splitDestructure(SILBuilder &B, SILInstruction *I, SILValue Op) { SILType OpType = Op->getType(); llvm::SmallVector Projections; - Projection::getFirstLevelProjections(OpType, M, Projections); + Projection::getFirstLevelProjections(OpType, M, B.getTypeExpansionContext(), + Projections); assert(Projections.size() == I->getNumResults()); auto Results = I->getResults(); diff --git a/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp b/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp index a333d41114343..5aa0d49fa6034 100644 --- a/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp +++ b/lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp @@ -34,7 +34,9 @@ PMOMemoryObjectInfo::PMOMemoryObjectInfo(AllocationInst *allocation) if (auto *abi = dyn_cast(MemoryInst)) { assert(abi->getBoxType()->getLayout()->getFields().size() == 1 && "analyzing multi-field boxes not implemented"); - MemorySILType = getSILBoxFieldType(abi->getBoxType(), module.Types, 0); + MemorySILType = + getSILBoxFieldType(TypeExpansionContext(*abi->getFunction()), + abi->getBoxType(), module.Types, 0); } else { MemorySILType = cast(MemoryInst)->getElementType(); } diff --git a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp index 2a1934ed35193..4586e03bb8da1 100644 --- a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp +++ b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp @@ -47,19 +47,22 @@ getFullyReferenceableStruct(SILType Ty) { return SD; } -static unsigned getNumSubElements(SILType T, SILModule &M) { +static unsigned getNumSubElements(SILType T, SILModule &M, + TypeExpansionContext context) { if (auto TT = T.getAs()) { unsigned NumElements = 0; for (auto index : indices(TT.getElementTypes())) - NumElements += getNumSubElements(T.getTupleElementType(index), M); + NumElements += + getNumSubElements(T.getTupleElementType(index), M, context); return NumElements; } if (auto *SD = getFullyReferenceableStruct(T)) { unsigned NumElements = 0; for (auto *D : SD->getStoredProperties()) - NumElements += getNumSubElements(T.getFieldType(D, M), M); + NumElements += + getNumSubElements(T.getFieldType(D, M, context), M, context); return NumElements; } @@ -127,7 +130,9 @@ static unsigned computeSubelement(SILValue Pointer, // Keep track of what subelement is being referenced. for (unsigned i = 0, e = TEAI->getFieldNo(); i != e; ++i) { - SubElementNumber += getNumSubElements(TT.getTupleElementType(i), M); + SubElementNumber += + getNumSubElements(TT.getTupleElementType(i), M, + TypeExpansionContext(*RootInst->getFunction())); } Pointer = TEAI->getOperand(); continue; @@ -140,7 +145,9 @@ static unsigned computeSubelement(SILValue Pointer, StructDecl *SD = SEAI->getStructDecl(); for (auto *D : SD->getStoredProperties()) { if (D == SEAI->getField()) break; - SubElementNumber += getNumSubElements(ST.getFieldType(D, M), M); + auto context = TypeExpansionContext(*RootInst->getFunction()); + SubElementNumber += + getNumSubElements(ST.getFieldType(D, M, context), M, context); } Pointer = SEAI->getOperand(); @@ -316,7 +323,8 @@ static SILValue nonDestructivelyExtractSubElement(const AvailableValue &Val, for (unsigned EltNo : indices(TT.getElementTypes())) { // Keep track of what subelement is being referenced. SILType EltTy = ValTy.getTupleElementType(EltNo); - unsigned NumSubElt = getNumSubElements(EltTy, B.getModule()); + unsigned NumSubElt = getNumSubElements( + EltTy, B.getModule(), TypeExpansionContext(B.getFunction())); if (SubElementNumber < NumSubElt) { auto BorrowedVal = Val.emitBeginBorrow(B, Loc); auto NewVal = @@ -338,9 +346,11 @@ static SILValue nonDestructivelyExtractSubElement(const AvailableValue &Val, // Extract struct elements. if (auto *SD = getFullyReferenceableStruct(ValTy)) { for (auto *D : SD->getStoredProperties()) { - auto fieldType = ValTy.getFieldType(D, B.getModule()); - unsigned NumSubElt = getNumSubElements(fieldType, B.getModule()); - + auto fieldType = ValTy.getFieldType( + D, B.getModule(), TypeExpansionContext(B.getFunction())); + unsigned NumSubElt = getNumSubElements( + fieldType, B.getModule(), TypeExpansionContext(B.getFunction())); + if (SubElementNumber < NumSubElt) { auto BorrowedVal = Val.emitBeginBorrow(B, Loc); auto NewVal = @@ -490,7 +500,8 @@ bool AvailableValueAggregator::isFullyAvailable(SILType loadTy, if (!firstVal || firstVal.getType() != loadTy) return false; - return llvm::all_of(range(getNumSubElements(loadTy, M)), + return llvm::all_of(range(getNumSubElements( + loadTy, M, TypeExpansionContext(B.getFunction()))), [&](unsigned index) -> bool { auto &val = AvailableValueList[firstElt + index]; return val.getValue() == firstVal.getValue() && @@ -516,7 +527,8 @@ bool AvailableValueAggregator::canTake(SILType loadTy, if (TupleType *tt = loadTy.getAs()) { return llvm::all_of(indices(tt->getElements()), [&](unsigned eltNo) { SILType eltTy = loadTy.getTupleElementType(eltNo); - unsigned numSubElt = getNumSubElements(eltTy, M); + unsigned numSubElt = + getNumSubElements(eltTy, M, TypeExpansionContext(B.getFunction())); bool success = canTake(eltTy, firstElt); firstElt += numSubElt; return success; @@ -525,8 +537,9 @@ bool AvailableValueAggregator::canTake(SILType loadTy, if (auto *sd = getFullyReferenceableStruct(loadTy)) { return llvm::all_of(sd->getStoredProperties(), [&](VarDecl *decl) -> bool { - SILType eltTy = loadTy.getFieldType(decl, M); - unsigned numSubElt = getNumSubElements(eltTy, M); + auto context = TypeExpansionContext(B.getFunction()); + SILType eltTy = loadTy.getFieldType(decl, M, context); + unsigned numSubElt = getNumSubElements(eltTy, M, context); bool success = canTake(eltTy, firstElt); firstElt += numSubElt; return success; @@ -650,7 +663,8 @@ SILValue AvailableValueAggregator::aggregateTupleSubElts(TupleType *TT, for (unsigned EltNo : indices(TT->getElements())) { SILType EltTy = LoadTy.getTupleElementType(EltNo); - unsigned NumSubElt = getNumSubElements(EltTy, M); + unsigned NumSubElt = + getNumSubElements(EltTy, M, TypeExpansionContext(B.getFunction())); // If we are missing any of the available values in this struct element, // compute an address to load from. @@ -676,8 +690,9 @@ SILValue AvailableValueAggregator::aggregateStructSubElts(StructDecl *sd, SmallVector resultElts; for (auto *decl : sd->getStoredProperties()) { - SILType eltTy = loadTy.getFieldType(decl, M); - unsigned numSubElt = getNumSubElements(eltTy, M); + auto context = TypeExpansionContext(B.getFunction()); + SILType eltTy = loadTy.getFieldType(decl, M, context); + unsigned numSubElt = getNumSubElements(eltTy, M, context); // If we are missing any of the available values in this struct element, // compute an address to load from. @@ -1094,8 +1109,9 @@ static inline void updateAvailableValuesHelper( // TODO: Is this needed now? assert(startSubElt != ~0U && "Store within enum projection not handled"); - for (unsigned i : - range(getNumSubElements(address->getType().getObjectType(), mod))) { + for (unsigned i : range(getNumSubElements( + address->getType().getObjectType(), mod, + TypeExpansionContext(*theMemory->getFunction())))) { // If this element is not required, don't fill it in. if (!requiredElts[startSubElt + i]) continue; @@ -1221,12 +1237,13 @@ void AvailableValueDataflowContext::updateAvailableValues( SILType ValTy = CAI->getDest()->getType(); bool AnyRequired = false; - for (unsigned i : range(getNumSubElements(ValTy, getModule()))) { + for (unsigned i : range(getNumSubElements( + ValTy, getModule(), TypeExpansionContext(*CAI->getFunction())))) { // If this element is not required, don't fill it in. AnyRequired = RequiredElts[StartSubElt+i]; if (AnyRequired) break; } - + // If this is a copy addr that doesn't intersect the loaded subelements, // just continue with an unmodified load mask. if (!AnyRequired) @@ -1513,7 +1530,8 @@ static SILType getMemoryType(AllocationInst *memory) { if (auto *abi = dyn_cast(memory)) { assert(abi->getBoxType()->getLayout()->getFields().size() == 1 && "optimizing multi-field boxes not implemented"); - return getSILBoxFieldType(abi->getBoxType(), abi->getModule().Types, 0); + return getSILBoxFieldType(TypeExpansionContext(*abi->getFunction()), + abi->getBoxType(), abi->getModule().Types, 0); } assert(isa(memory)); @@ -1552,8 +1570,9 @@ class AllocOptimize { DeadEndBlocks &deadEndBlocks) : Module(memory->getModule()), TheMemory(memory), MemoryType(getMemoryType(memory)), - NumMemorySubElements(getNumSubElements(MemoryType, Module)), Uses(uses), - Releases(releases), deadEndBlocks(deadEndBlocks), + NumMemorySubElements(getNumSubElements( + MemoryType, Module, TypeExpansionContext(*memory->getFunction()))), + Uses(uses), Releases(releases), deadEndBlocks(deadEndBlocks), DataflowContext(TheMemory, NumMemorySubElements, uses) {} bool optimizeMemoryAccesses(); @@ -1598,7 +1617,8 @@ Optional> AllocOptimize::computeAvailableValues( if (FirstElt == ~0U) return None; - unsigned NumLoadSubElements = getNumSubElements(LoadTy, Module); + unsigned NumLoadSubElements = getNumSubElements( + LoadTy, Module, TypeExpansionContext(*TheMemory->getFunction())); // Set up the bitvector of elements being demanded by the load. SmallBitVector RequiredElts(NumMemorySubElements); @@ -1825,7 +1845,9 @@ bool AllocOptimize::canPromoteTake( // def/use behavior. unsigned firstElt = computeSubelement(address, TheMemory); assert(firstElt != ~0U && "destroy within enum projection is not valid"); - unsigned numLoadSubElements = getNumSubElements(loadTy, Module); + auto expansionContext = TypeExpansionContext(*inst->getFunction()); + unsigned numLoadSubElements = + getNumSubElements(loadTy, Module, expansionContext); // Find out if we have any available values. If no bits are demanded, we // trivially succeed. This can happen when there is a load of an empty struct. diff --git a/lib/SILOptimizer/PassManager/PassPipeline.cpp b/lib/SILOptimizer/PassManager/PassPipeline.cpp index cf118006bd076..d666cee5a14da 100644 --- a/lib/SILOptimizer/PassManager/PassPipeline.cpp +++ b/lib/SILOptimizer/PassManager/PassPipeline.cpp @@ -292,10 +292,6 @@ void addSSAPasses(SILPassPipelinePlan &P, OptimizationLevelKind OpLevel) { // Mainly for Array.append(contentsOf) optimization. P.addArrayElementPropagation(); - // Specialize opaque archetypes. - // This can expose oportunities for the generic specializer. - P.addOpaqueArchetypeSpecializer(); - // Run the devirtualizer, specializer, and inliner. If any of these // makes a change we'll end up restarting the function passes on the // current function (after optimizing any new callees). diff --git a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp index 42752a6acda1e..71bf97da9f221 100644 --- a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp +++ b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp @@ -436,7 +436,8 @@ static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) { && "rewriting multi-field box not implemented"); auto *ASI = Builder.createAllocStack( ABI->getLoc(), - getSILBoxFieldType(ABI->getBoxType(), ABI->getModule().Types, 0), + getSILBoxFieldType(TypeExpansionContext(*ABI->getFunction()), + ABI->getBoxType(), ABI->getModule().Types, 0), ABI->getVarInfo(), ABI->hasDynamicLifetime()); // Transfer a mark_uninitialized if we have one. @@ -452,9 +453,9 @@ static bool rewriteAllocBoxAsAllocStack(AllocBoxInst *ABI) { assert(ABI->getBoxType()->getLayout()->getFields().size() == 1 && "promoting multi-field box not implemented"); - auto &Lowering = ABI->getFunction() - ->getTypeLowering( - getSILBoxFieldType(ABI->getBoxType(), ABI->getModule().Types, 0)); + auto &Lowering = ABI->getFunction()->getTypeLowering( + getSILBoxFieldType(TypeExpansionContext(*ABI->getFunction()), + ABI->getBoxType(), ABI->getModule().Types, 0)); auto Loc = CleanupLocation::get(ABI->getLoc()); for (auto LastRelease : FinalReleases) { @@ -585,7 +586,7 @@ SILFunction *PromotedParamCloner::initCloned(SILOptFunctionBuilder &FuncBuilder, auto &TC = Orig->getModule().Types; Lowering::GenericContextScope scope(TC, OrigFTI->getSubstGenericSignature()); - paramTy = getSILBoxFieldType(boxTy, TC, 0); + paramTy = getSILBoxFieldType(TypeExpansionContext(*Orig), boxTy, TC, 0); } auto promotedParam = SILParameterInfo(paramTy.getASTType(), ParameterConvention::Indirect_InoutAliasable); @@ -650,7 +651,8 @@ PromotedParamCloner::populateCloned() { auto boxTy = (*I)->getType().castTo(); assert(boxTy->getLayout()->getFields().size() == 1 && "promoting multi-field boxes not implemented yet"); - auto promotedTy = getSILBoxFieldType(boxTy, Cloned->getModule().Types, 0); + auto promotedTy = getSILBoxFieldType(TypeExpansionContext(*Cloned), boxTy, + Cloned->getModule().Types, 0); auto *promotedArg = ClonedEntryBB->createFunctionArgument(promotedTy, (*I)->getDecl()); OrigPromotedParameters.insert(*I); diff --git a/lib/SILOptimizer/Transforms/CMakeLists.txt b/lib/SILOptimizer/Transforms/CMakeLists.txt index fbba6b0fcac59..b0146133a9a32 100644 --- a/lib/SILOptimizer/Transforms/CMakeLists.txt +++ b/lib/SILOptimizer/Transforms/CMakeLists.txt @@ -31,7 +31,6 @@ silopt_register_sources( SILSROA.cpp SimplifyCFG.cpp Sink.cpp - SpecializeOpaqueArchetypes.cpp SpeculativeDevirtualizer.cpp StackPromotion.cpp UnsafeGuaranteedPeephole.cpp diff --git a/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp b/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp index 182d6d642e094..266859152516a 100644 --- a/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp +++ b/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp @@ -855,7 +855,8 @@ void DSEContext::processRead(SILInstruction *I, SILValue Mem, DSEKind Kind) { // Expand the given Mem into individual fields and process them as separate // reads. LSLocationList Locs; - LSLocation::expand(L, &I->getModule(), Locs, TE); + LSLocation::expand(L, &I->getModule(), + TypeExpansionContext(*I->getFunction()), Locs, TE); // Are we building the genset and killset. if (isBuildingGenKillSet(Kind)) { @@ -940,7 +941,7 @@ void DSEContext::processWrite(SILInstruction *I, SILValue Val, SILValue Mem, // writes. bool Dead = true; LSLocationList Locs; - LSLocation::expand(L, Mod, Locs, TE); + LSLocation::expand(L, Mod, TypeExpansionContext(*I->getFunction()), Locs, TE); SmallBitVector V(Locs.size()); // Are we computing max store set. @@ -997,7 +998,7 @@ void DSEContext::processWrite(SILInstruction *I, SILValue Val, SILValue Mem, } // Try to create as few aggregated stores as possible out of the locations. - LSLocation::reduce(L, Mod, Alives); + LSLocation::reduce(L, Mod, TypeExpansionContext(*I->getFunction()), Alives); // Oops, we have too many smaller stores generated, bail out. if (Alives.size() > MaxPartialStoreCount) diff --git a/lib/SILOptimizer/Transforms/ObjectOutliner.cpp b/lib/SILOptimizer/Transforms/ObjectOutliner.cpp index 08f3bc0c54483..dd35ec91fbe74 100644 --- a/lib/SILOptimizer/Transforms/ObjectOutliner.cpp +++ b/lib/SILOptimizer/Transforms/ObjectOutliner.cpp @@ -488,7 +488,8 @@ bool ObjectOutliner::optimizeObjectAllocation(AllocRefInst *ARI) { void ObjectOutliner::replaceFindStringCall(ApplyInst *FindStringCall) { // Find the replacement function in the swift stdlib. SmallVector results; - SILModule *Module = &FindStringCall->getFunction()->getModule(); + auto &F = *FindStringCall->getFunction(); + SILModule *Module = &F.getModule(); Module->getASTContext().lookupInSwiftModule("_findStringSwitchCaseWithCache", results); if (results.size() != 1) @@ -517,8 +518,9 @@ void ObjectOutliner::replaceFindStringCall(ApplyInst *FindStringCall) { assert(!cacheDecl->isResilient(Module->getSwiftModule(), ResilienceExpansion::Minimal)); - SILType wordTy = cacheType.getFieldType( - cacheDecl->getStoredProperties().front(), *Module); + SILType wordTy = + cacheType.getFieldType(cacheDecl->getStoredProperties().front(), *Module, + F.getTypeExpansionContext()); GlobalVariableMangler Mangler; std::string GlobName = diff --git a/lib/SILOptimizer/Transforms/RedundantLoadElimination.cpp b/lib/SILOptimizer/Transforms/RedundantLoadElimination.cpp index 0f610308babfa..d34370660a95b 100644 --- a/lib/SILOptimizer/Transforms/RedundantLoadElimination.cpp +++ b/lib/SILOptimizer/Transforms/RedundantLoadElimination.cpp @@ -677,7 +677,8 @@ SILValue BlockState::reduceValuesAtEndOfBlock(RLEContext &Ctx, LSLocation &L) { LSLocationValueMap Values; LSLocationList Locs; - LSLocation::expand(L, &BB->getModule(), Locs, Ctx.getTE()); + LSLocation::expand(L, &BB->getModule(), + TypeExpansionContext(*BB->getParent()), Locs, Ctx.getTE()); // Find the values that this basic block defines and the locations which // we do not have a concrete value in the current basic block. @@ -689,8 +690,8 @@ SILValue BlockState::reduceValuesAtEndOfBlock(RLEContext &Ctx, LSLocation &L) { // Second, reduce the available values into a single SILValue we can use to // forward. SILValue TheForwardingValue; - TheForwardingValue = LSValue::reduce(L, &BB->getModule(), Values, - BB->getTerminator()); + TheForwardingValue = + LSValue::reduce(L, &BB->getModule(), Values, BB->getTerminator()); /// Return the forwarding value. return TheForwardingValue; } @@ -856,7 +857,9 @@ void BlockState::processWrite(RLEContext &Ctx, SILInstruction *I, SILValue Mem, // Expand the given location and val into individual fields and process // them as separate writes. LSLocationList Locs; - LSLocation::expand(L, &I->getModule(), Locs, Ctx.getTE()); + LSLocation::expand(L, &I->getModule(), + TypeExpansionContext(*I->getFunction()), Locs, + Ctx.getTE()); if (isComputeAvailSetMax(Kind)) { for (unsigned i = 0; i < Locs.size(); ++i) { @@ -875,7 +878,8 @@ void BlockState::processWrite(RLEContext &Ctx, SILInstruction *I, SILValue Mem, // Are we computing available value or performing RLE? LSValueList Vals; - LSValue::expand(Val, &I->getModule(), Vals, Ctx.getTE()); + LSValue::expand(Val, &I->getModule(), TypeExpansionContext(*I->getFunction()), + Vals, Ctx.getTE()); if (isComputeAvailValue(Kind) || isPerformingRLE(Kind)) { for (unsigned i = 0; i < Locs.size(); ++i) { updateForwardSetAndValForWrite(Ctx, Ctx.getLocationBit(Locs[i]), @@ -907,7 +911,9 @@ void BlockState::processRead(RLEContext &Ctx, SILInstruction *I, SILValue Mem, // Expand the given LSLocation and Val into individual fields and process // them as separate reads. LSLocationList Locs; - LSLocation::expand(L, &I->getModule(), Locs, Ctx.getTE()); + LSLocation::expand(L, &I->getModule(), + TypeExpansionContext(*I->getFunction()), Locs, + Ctx.getTE()); if (isComputeAvailSetMax(Kind)) { for (unsigned i = 0; i < Locs.size(); ++i) { @@ -927,7 +933,8 @@ void BlockState::processRead(RLEContext &Ctx, SILInstruction *I, SILValue Mem, // Are we computing available values ?. bool CanForward = true; LSValueList Vals; - LSValue::expand(Val, &I->getModule(), Vals, Ctx.getTE()); + LSValue::expand(Val, &I->getModule(), TypeExpansionContext(*I->getFunction()), + Vals, Ctx.getTE()); if (isComputeAvailValue(Kind) || isPerformingRLE(Kind)) { for (unsigned i = 0; i < Locs.size(); ++i) { if (isTrackingLocation(ForwardSetIn, Ctx.getLocationBit(Locs[i]))) @@ -1245,7 +1252,8 @@ BlockState::ValueState BlockState::getValueStateAtEndOfBlock(RLEContext &Ctx, // expanded from the given location. unsigned CSCount = 0, CTCount = 0; LSLocationList Locs; - LSLocation::expand(L, &BB->getModule(), Locs, Ctx.getTE()); + LSLocation::expand(L, &BB->getModule(), + TypeExpansionContext(*BB->getParent()), Locs, Ctx.getTE()); ValueTableMap &OTM = getForwardValOut(); for (auto &X : Locs) { @@ -1319,12 +1327,15 @@ SILValue RLEContext::computePredecessorLocationValue(SILBasicBlock *BB, // Reduce the available values into a single SILValue we can use to forward SILInstruction *IPt = CurBB->getTerminator(); - Values.push_back({CurBB, LSValue::reduce(L, &BB->getModule(), LSValues, IPt)}); + Values.push_back( + {CurBB, LSValue::reduce(L, &BB->getModule(), LSValues, IPt)}); } // Finally, collect all the values for the SILArgument, materialize it using // the SSAUpdater. - Updater.Initialize(L.getType(&BB->getModule()).getObjectType()); + Updater.Initialize( + L.getType(&BB->getModule(), TypeExpansionContext(*BB->getParent())) + .getObjectType()); for (auto V : Values) { Updater.AddAvailableValue(V.first, V.second); } @@ -1337,7 +1348,8 @@ bool RLEContext::collectLocationValues(SILBasicBlock *BB, LSLocation &L, ValueTableMap &VM) { LSLocationList CSLocs; LSLocationList Locs; - LSLocation::expand(L, &BB->getModule(), Locs, TE); + LSLocation::expand(L, &BB->getModule(), + TypeExpansionContext(*BB->getParent()), Locs, TE); auto *Mod = &BB->getModule(); // Find the locations that this basic block defines and the locations which @@ -1352,7 +1364,7 @@ bool RLEContext::collectLocationValues(SILBasicBlock *BB, LSLocation &L, // For locations which we do not have concrete values for in this basic // block, try to reduce it to the minimum # of locations possible, this // will help us to generate as few SILArguments as possible. - LSLocation::reduce(L, Mod, CSLocs); + LSLocation::reduce(L, Mod, TypeExpansionContext(*BB->getParent()), CSLocs); // To handle covering value, we need to go to the predecessors and // materialize them there. @@ -1365,8 +1377,9 @@ bool RLEContext::collectLocationValues(SILBasicBlock *BB, LSLocation &L, // collect the newly created forwardable values. LSLocationList Locs; LSValueList Vals; - LSLocation::expand(X, Mod, Locs, TE); - LSValue::expand(V, Mod, Vals, TE); + auto expansionContext = TypeExpansionContext(*BB->getParent()); + LSLocation::expand(X, Mod, expansionContext, Locs, TE); + LSValue::expand(V, Mod, expansionContext, Vals, TE); for (unsigned i = 0; i < Locs.size(); ++i) { Values[Locs[i]] = Vals[i]; @@ -1570,7 +1583,8 @@ bool RLEContext::run() { LLVM_DEBUG(for (unsigned i = 0; i < LocationVault.size(); ++i) { llvm::dbgs() << "LSLocation #" << i; - getLocation(i).print(llvm::dbgs(), &Fn->getModule()); + getLocation(i).print(llvm::dbgs(), &Fn->getModule(), + TypeExpansionContext(*Fn)); }); if (Optimistic) diff --git a/lib/SILOptimizer/Transforms/ReleaseDevirtualizer.cpp b/lib/SILOptimizer/Transforms/ReleaseDevirtualizer.cpp index e52ce639db7d0..3642e337053fc 100644 --- a/lib/SILOptimizer/Transforms/ReleaseDevirtualizer.cpp +++ b/lib/SILOptimizer/Transforms/ReleaseDevirtualizer.cpp @@ -142,13 +142,14 @@ bool ReleaseDevirtualizer::createDeallocCall(SILType AllocType, SILFunction *Dealloc = M.lookUpFunction(DeallocRef); if (!Dealloc) return false; - - CanSILFunctionType DeallocType = Dealloc->getLoweredFunctionType(); + TypeExpansionContext context(*ReleaseInst->getFunction()); + CanSILFunctionType DeallocType = + Dealloc->getLoweredFunctionTypeInContext(context); auto *NTD = AllocType.getASTType()->getAnyNominal(); auto AllocSubMap = AllocType.getASTType() ->getContextSubstitutionMap(M.getSwiftModule(), NTD); - DeallocType = DeallocType->substGenericArgs(M, AllocSubMap); + DeallocType = DeallocType->substGenericArgs(M, AllocSubMap, context); SILBuilder B(ReleaseInst); if (object->getType() != AllocType) diff --git a/lib/SILOptimizer/Transforms/SILCodeMotion.cpp b/lib/SILOptimizer/Transforms/SILCodeMotion.cpp index 61d1efa68b7c6..d7bae9dd2a835 100644 --- a/lib/SILOptimizer/Transforms/SILCodeMotion.cpp +++ b/lib/SILOptimizer/Transforms/SILCodeMotion.cpp @@ -60,7 +60,8 @@ static void createRefCountOpForPayload(SILBuilder &Builder, SILInstruction *I, // argument to the refcount instruction. SILValue EnumVal = DefOfEnum ? DefOfEnum : I->getOperand(0); - SILType ArgType = EnumVal->getType().getEnumElementType(EnumDecl, Mod); + SILType ArgType = EnumVal->getType().getEnumElementType( + EnumDecl, Mod, TypeExpansionContext(Builder.getFunction())); auto *UEDI = Builder.createUncheckedEnumData(I->getLoc(), EnumVal, EnumDecl, ArgType); diff --git a/lib/SILOptimizer/Transforms/SILSROA.cpp b/lib/SILOptimizer/Transforms/SILSROA.cpp index eafc9d41b120f..dcfb8d6803e78 100644 --- a/lib/SILOptimizer/Transforms/SILSROA.cpp +++ b/lib/SILOptimizer/Transforms/SILSROA.cpp @@ -228,8 +228,9 @@ createAllocas(llvm::SmallVector &NewAllocations) { "this point."); SILModule &M = AI->getModule(); for (auto *D : SD->getStoredProperties()) - NewAllocations.push_back( - B.createAllocStack(Loc, Type.getFieldType(D, M), {})); + NewAllocations.push_back(B.createAllocStack( + Loc, Type.getFieldType(D, M, TypeExpansionContext(B.getFunction())), + {})); } } diff --git a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp index 4a4530142072a..617456bf340a9 100644 --- a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp +++ b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp @@ -313,7 +313,8 @@ class ThreadInfo { auto EnumVal = SEI->getOperand(); auto EnumTy = EnumVal->getType(); auto Loc = SEI->getLoc(); - auto Ty = EnumTy.getEnumElementType(EnumCase, SEI->getModule()); + auto Ty = EnumTy.getEnumElementType(EnumCase, SEI->getModule(), + Builder.getTypeExpansionContext()); SILValue UED( Builder.createUncheckedEnumData(Loc, EnumVal, EnumCase, Ty)); assert(UED->getType() == @@ -358,7 +359,8 @@ static SILValue createEnumElement(SILBuilder &Builder, // Do we have a payload. auto EnumTy = EnumVal->getType(); if (EnumElement->hasAssociatedValues()) { - auto Ty = EnumTy.getEnumElementType(EnumElement, SEI->getModule()); + auto Ty = EnumTy.getEnumElementType(EnumElement, SEI->getModule(), + Builder.getTypeExpansionContext()); SILValue UED(Builder.createUncheckedEnumData(SEI->getLoc(), EnumVal, EnumElement, Ty)); return Builder.createEnum(SEI->getLoc(), UED, EnumElement, EnumTy); @@ -1702,7 +1704,8 @@ bool SimplifyCFG::simplifySwitchEnumUnreachableBlocks(SwitchEnumInst *SEI) { auto &Mod = SEI->getModule(); auto OpndTy = SEI->getOperand()->getType(); - auto Ty = OpndTy.getEnumElementType(Element, Mod); + auto Ty = OpndTy.getEnumElementType( + Element, Mod, TypeExpansionContext(*SEI->getFunction())); auto *UED = SILBuilderWithScope(SEI) .createUncheckedEnumData(SEI->getLoc(), SEI->getOperand(), Element, Ty); @@ -2388,15 +2391,17 @@ bool SimplifyCFG::simplifyTryApplyBlock(TryApplyInst *TAI) { auto TargetFnTy = CalleeFnTy; if (TargetFnTy->isPolymorphic()) { - TargetFnTy = TargetFnTy->substGenericArgs(TAI->getModule(), - TAI->getSubstitutionMap()); + TargetFnTy = TargetFnTy->substGenericArgs( + TAI->getModule(), TAI->getSubstitutionMap(), + Builder.getTypeExpansionContext()); } SILFunctionConventions targetConv(TargetFnTy, TAI->getModule()); auto OrigFnTy = TAI->getCallee()->getType().getAs(); if (OrigFnTy->isPolymorphic()) { OrigFnTy = OrigFnTy->substGenericArgs(TAI->getModule(), - TAI->getSubstitutionMap()); + TAI->getSubstitutionMap(), + Builder.getTypeExpansionContext()); } SILFunctionConventions origConv(OrigFnTy, TAI->getModule()); @@ -2857,7 +2862,8 @@ bool ArgumentSplitter::createNewArguments() { return false; // Get the first level projection for the struct or tuple type. - Projection::getFirstLevelProjections(Arg->getType(), Mod, Projections); + Projection::getFirstLevelProjections(Arg->getType(), Mod, + TypeExpansionContext(*F), Projections); // We do not want to split arguments with less than 2 projections. if (Projections.size() < 2) @@ -2866,7 +2872,7 @@ bool ArgumentSplitter::createNewArguments() { // We do not want to split arguments that have less than 2 non-trivial // projections. if (count_if(Projections, [&](const Projection &P) { - return !P.getType(Ty, Mod).isTrivial(*F); + return !P.getType(Ty, Mod, TypeExpansionContext(*F)).isTrivial(*F); }) < 2) return false; @@ -2878,8 +2884,9 @@ bool ArgumentSplitter::createNewArguments() { // old one. llvm::SmallVector NewArgumentValues; for (auto &P : Projections) { - auto *NewArg = ParentBB->createPhiArgument(P.getType(Ty, Mod), - ValueOwnershipKind::Owned); + auto *NewArg = ParentBB->createPhiArgument( + P.getType(Ty, Mod, TypeExpansionContext(*F)), + ValueOwnershipKind::Owned); // This is unfortunate, but it feels wrong to put in an API into SILBuilder // that only takes in arguments. // diff --git a/lib/SILOptimizer/Transforms/SpecializeOpaqueArchetypes.cpp b/lib/SILOptimizer/Transforms/SpecializeOpaqueArchetypes.cpp deleted file mode 100644 index 11f66eb2666bf..0000000000000 --- a/lib/SILOptimizer/Transforms/SpecializeOpaqueArchetypes.cpp +++ /dev/null @@ -1,558 +0,0 @@ -//===--- SpecializeOpaqueArchetypes.cpp - Specialize opaque archetypes ---===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// -// -// A pass to specialize opaque archetypes -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "opaque-archetype-specializer" - -#include "swift/AST/Types.h" -#include "swift/SIL/SILFunction.h" -#include "swift/SIL/SILInstruction.h" -#include "swift/SIL/TypeSubstCloner.h" -#include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" - -#include "llvm/Support/CommandLine.h" - -llvm::cl::opt - EnableOpaqueArchetypeSpecializer("enable-opaque-archetype-specializer", - llvm::cl::init(true)); - -using namespace swift; - -static const DeclContext * -getDeclContextIfInCurrentModule(const SILFunction &fn) { - auto *dc = fn.getDeclContext(); - auto *currentModule = fn.getModule().getSwiftModule(); - if (dc && dc->isChildContextOf(currentModule)) - return dc; - return currentModule; -} - -static Type substOpaqueTypesWithUnderlyingTypes( - Type ty, SILFunction *context) { - auto *dc = getDeclContextIfInCurrentModule(*context); - ReplaceOpaqueTypesWithUnderlyingTypes replacer( - dc, context->getResilienceExpansion()); - return ty.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes); -} - -static SubstitutionMap -substOpaqueTypesWithUnderlyingTypes(SubstitutionMap map, SILFunction *context) { - auto *dc = getDeclContextIfInCurrentModule(*context); - ReplaceOpaqueTypesWithUnderlyingTypes replacer( - dc, context->getResilienceExpansion()); - return map.subst(replacer, replacer, SubstFlags::SubstituteOpaqueArchetypes); -} - -namespace { -class OpaqueSpecializerCloner - : public SILCloner { - - using SuperTy = SILCloner; - - SILBasicBlock *entryBlock; - SILBasicBlock *cloneFromBlock; - - /// Cache for substituted types. - llvm::DenseMap TypeCache; - - SILFunction &Original; - -public: - friend class SILCloner; - friend class SILCloner; - friend class SILInstructionVisitor; - - OpaqueSpecializerCloner(SILFunction &fun) : SuperTy(fun), Original(fun) { - entryBlock = fun.getEntryBlock(); - cloneFromBlock = entryBlock->split(entryBlock->begin()); - } - - void clone(); - -protected: - void insertOpaqueToConcreteAddressCasts(SILInstruction *orig, - SILInstruction *cloned); - - void postProcess(SILInstruction *orig, SILInstruction *cloned) { - SILCloner::postProcess(orig, cloned); - insertOpaqueToConcreteAddressCasts(orig, cloned); - } - - void visitTerminator(SILBasicBlock *BB) { - visit(BB->getTerminator()); - } - - void visitReturnInst(ReturnInst *Inst) { - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - auto origResult = Inst->getOperand(); - auto clonedResult = getOpValue(Inst->getOperand()); - if (clonedResult->getType().getASTType() != - origResult->getType().getASTType()) { - clonedResult = createCast(RegularLocation::getAutoGeneratedLocation(), - clonedResult, origResult->getType()); - } - recordClonedInstruction( - Inst, - getBuilder().createReturn(getOpLocation(Inst->getLoc()), clonedResult)); - } - - void visitStructInst(StructInst *Inst) { - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - auto elements = getOpValueArray<8>(Inst->getElements()); - auto structTy = getOpType(Inst->getType()); - auto *structDecl = structTy.getStructOrBoundGenericStruct(); - unsigned idx = 0; - // Adjust field types if neccessary. - for (VarDecl *field : structDecl->getStoredProperties()) { - SILType loweredType = structTy.getFieldType( - field, getBuilder().getFunction().getModule()); - if (elements[idx]->getType() != loweredType) { - elements[idx] = createCast(getOpLocation(Inst->getLoc()), elements[idx], - loweredType); - } - idx++; - } - recordClonedInstruction( - Inst, getBuilder().createStruct(getOpLocation(Inst->getLoc()), - getOpType(Inst->getType()), elements)); - } - - void visitTupleInst(TupleInst *Inst) { - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - auto elements = getOpValueArray<8>(Inst->getElements()); - auto tupleTy = getOpType(Inst->getType()); - for (size_t i = 0, size = Inst->getElements().size(); i < size; ++i) { - auto elementTy = tupleTy.getTupleElementType(i); - if (Inst->getElement(i)->getType() != elementTy) { - elements[i] = - createCast(getOpLocation(Inst->getLoc()), elements[i], elementTy); - } - } - recordClonedInstruction( - Inst, getBuilder().createTuple(getOpLocation(Inst->getLoc()), - getOpType(Inst->getType()), elements)); - } - - void visitEnumInst(EnumInst *Inst) { - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - SILValue opd = SILValue(); - auto newTy = getOpType(Inst->getType()); - if (Inst->hasOperand()) { - opd = getOpValue(Inst->getOperand()); - SILType newCaseTy = newTy.getEnumElementType( - Inst->getElement(), getBuilder().getFunction().getModule()); - if (opd->getType() != newCaseTy) - opd = createCast(getOpLocation(Inst->getLoc()), opd, newCaseTy); - } - recordClonedInstruction( - Inst, getBuilder().createEnum(getOpLocation(Inst->getLoc()), opd, - Inst->getElement(), newTy)); - } - - void visitInitEnumDataAddrInst(InitEnumDataAddrInst *Inst) { - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - auto opd = getOpValue(Inst->getOperand()); - auto caseTy = opd->getType().getEnumElementType( - Inst->getElement(), getBuilder().getFunction().getModule()); - auto expectedTy = getOpType(Inst->getType()); - if (expectedTy != caseTy) - expectedTy = caseTy; - recordClonedInstruction(Inst, getBuilder().createInitEnumDataAddr( - getOpLocation(Inst->getLoc()), opd, - Inst->getElement(), expectedTy)); - } - - /// Projections should not change the type if the type is not specialized. - void visitStructElementAddrInst(StructElementAddrInst *Inst) { - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - auto opd = getOpValue(Inst->getOperand()); - recordClonedInstruction( - Inst, getBuilder().createStructElementAddr( - getOpLocation(Inst->getLoc()), opd, Inst->getField())); - } - - /// Projections should not change the type if the type is not specialized. - void visitStructExtractInst(StructExtractInst *Inst) { - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - auto opd = getOpValue(Inst->getOperand()); - recordClonedInstruction( - Inst, getBuilder().createStructExtract(getOpLocation(Inst->getLoc()), - opd, Inst->getField())); - } - /// Projections should not change the type if the type is not specialized. - void visitTupleElementAddrInst(TupleElementAddrInst *Inst) { - auto opd = getOpValue(Inst->getOperand()); - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - recordClonedInstruction(Inst, getBuilder().createTupleElementAddr( - getOpLocation(Inst->getLoc()), opd, - Inst->getFieldNo())); - } - /// Projections should not change the type if the type is not specialized. - void visitTupleExtractInst(TupleExtractInst *Inst) { - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - recordClonedInstruction( - Inst, getBuilder().createTupleExtract(getOpLocation(Inst->getLoc()), - getOpValue(Inst->getOperand()), - Inst->getFieldNo())); - } - /// Projections should not change the type if the type is not specialized. - void visitRefElementAddrInst(RefElementAddrInst *Inst) { - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - recordClonedInstruction( - Inst, getBuilder().createRefElementAddr( - getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()), - Inst->getField())); - } - - /// Projections should not change the type if the type is not specialized. - void visitRefTailAddrInst(RefTailAddrInst *Inst) { - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - recordClonedInstruction( - Inst, getBuilder().createRefTailAddr(getOpLocation(Inst->getLoc()), - getOpValue(Inst->getOperand()), - Inst->getType())); - } - - void visitYieldInst(YieldInst *Inst) { - auto OrigValues = Inst->getYieldedValues(); - auto Values = getOpValueArray<8>(Inst->getYieldedValues()); - auto ResumeBB = getOpBasicBlock(Inst->getResumeBB()); - auto UnwindBB = getOpBasicBlock(Inst->getUnwindBB()); - for (auto idx : indices(Values)) { - if (OrigValues[idx]->getType().getASTType() != - Values[idx]->getType().getASTType()) { - Values[idx] = createCast(RegularLocation::getAutoGeneratedLocation(), - Values[idx], OrigValues[idx]->getType()); - } - } - - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - recordClonedInstruction( - Inst, getBuilder().createYield(getOpLocation(Inst->getLoc()), Values, - ResumeBB, UnwindBB)); - } - - void visitCopyAddrInst(CopyAddrInst *Inst) { - auto src = getOpValue(Inst->getSrc()); - auto dst = getOpValue(Inst->getDest()); - auto srcType = src->getType(); - auto destType = dst->getType(); - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - // If the types mismatch cast the operands to the non opaque archetype. - if (destType.getASTType() != srcType.getASTType()) { - if (srcType.getASTType()->hasOpaqueArchetype()) { - src = getBuilder().createUncheckedAddrCast( - getOpLocation(Inst->getLoc()), src, destType); - } else if (destType.getASTType()->hasOpaqueArchetype()) { - dst = getBuilder().createUncheckedAddrCast( - getOpLocation(Inst->getLoc()), dst, srcType); - } - } - recordClonedInstruction( - Inst, getBuilder().createCopyAddr(getOpLocation(Inst->getLoc()), src, - dst, Inst->isTakeOfSrc(), - Inst->isInitializationOfDest())); - } - - SILValue remapResultType(SILLocation loc, SILValue val) { - auto specializedTy = remapType(val->getType()); - if (val->getType() == specializedTy) - return val; - return createCast(loc, val, specializedTy); - } - - void visitThinToThickFunctionInst(ThinToThickFunctionInst *Inst) { - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - auto loc = getOpLocation(Inst->getLoc()); - auto opd = remapResultType(loc, getOpValue(Inst->getOperand())); - recordClonedInstruction(Inst, getBuilder().createThinToThickFunction( - loc, opd, getOpType(Inst->getType()))); - } - - void visitStoreInst(StoreInst *Inst) { - auto src = getOpValue(Inst->getSrc()); - auto dst = getOpValue(Inst->getDest()); - auto srcType = src->getType(); - auto destType = dst->getType(); - getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope())); - // If the types mismatch cast the operands to the non opaque archetype. - if (destType.getASTType() != srcType.getASTType()) { - if (srcType.getASTType()->hasOpaqueArchetype()) { - assert(!srcType.isAddress()); - src = createCast(getOpLocation(Inst->getLoc()), src, - destType.getObjectType()); - } else if (destType.getASTType()->hasOpaqueArchetype()) { - dst = getBuilder().createUncheckedAddrCast( - getOpLocation(Inst->getLoc()), dst, srcType.getAddressType()); - } - } - - if (!getBuilder().hasOwnership()) { - switch (Inst->getOwnershipQualifier()) { - case StoreOwnershipQualifier::Assign: { - auto *li = getBuilder().createLoad(getOpLocation(Inst->getLoc()), dst, - LoadOwnershipQualifier::Unqualified); - auto *si = getBuilder().createStore( - getOpLocation(Inst->getLoc()), src, getOpValue(Inst->getDest()), - StoreOwnershipQualifier::Unqualified); - getBuilder().emitDestroyValueOperation(getOpLocation(Inst->getLoc()), - li); - return recordClonedInstruction(Inst, si); - } - case StoreOwnershipQualifier::Init: - case StoreOwnershipQualifier::Trivial: - case StoreOwnershipQualifier::Unqualified: - break; - } - - return recordClonedInstruction( - Inst, - getBuilder().createStore(getOpLocation(Inst->getLoc()), src, dst, - StoreOwnershipQualifier::Unqualified)); - } - - recordClonedInstruction( - Inst, getBuilder().createStore(getOpLocation(Inst->getLoc()), src, dst, - Inst->getOwnershipQualifier())); - } - -protected: - - SILType remapType(SILType Ty) { - SILType &Sty = TypeCache[Ty]; - if (Sty) - return Sty; - auto *dc = getDeclContextIfInCurrentModule(Original); - - // Apply the opaque types substitution. - ReplaceOpaqueTypesWithUnderlyingTypes replacer( - dc, Original.getResilienceExpansion()); - Sty = Ty.subst(Original.getModule(), replacer, replacer, - CanGenericSignature(), true); - return Sty; - } - - CanType remapASTType(CanType ty) { - // Apply the opaque types substitution. - return substOpaqueTypesWithUnderlyingTypes(ty, &Original) - ->getCanonicalType(); - } - - ProtocolConformanceRef remapConformance(Type type, - ProtocolConformanceRef conf) { - auto *dc = getDeclContextIfInCurrentModule(Original); - // Apply the opaque types substitution. - ReplaceOpaqueTypesWithUnderlyingTypes replacer( - dc, Original.getResilienceExpansion()); - return conf.subst(type, replacer, replacer, - SubstFlags::SubstituteOpaqueArchetypes); - } - - SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) { - // Apply the opaque types substitution. - return substOpaqueTypesWithUnderlyingTypes(Subs, &Original); - } - - SILValue createCast(SILLocation loc, SILValue opd, SILType type) { - auto &CurFn = getBuilder().getFunction(); - if (opd->getType().isAddress()) { - return getBuilder().createUncheckedAddrCast(loc, opd, type); - } else if (opd->getType().is()) { - return getBuilder().createConvertFunction( - loc, opd, type, /*withoutActuallyEscaping*/ false); - } else if (opd->getType().isTrivial(CurFn)) { - return getBuilder().createUncheckedTrivialBitCast(loc, opd, type); - } else if (opd->getType().canRefCast(opd->getType(), type, - CurFn.getModule())) { - return getBuilder().createUncheckedRefCast(loc, opd, type); - } else { - // This could be improved upon by recursively recomposing the type. - auto *stackLoc = getBuilder().createAllocStack(loc, type); - auto *addr = getBuilder().createUncheckedAddrCast( - loc, stackLoc, opd->getType().getAddressType()); - getBuilder().createTrivialStoreOr(loc, opd, addr, - StoreOwnershipQualifier::Init, true); - SILValue res = getBuilder().createTrivialLoadOr( - loc, stackLoc, LoadOwnershipQualifier::Take, true); - getBuilder().createDeallocStack(loc, stackLoc); - return res; - } - } - - void replaceBlockArgumentType(SILLocation loc, SILBasicBlock *destBlock, - SILType withType) { - assert(destBlock->getArguments().size() == 1); - - auto origType = (*destBlock->args_begin())->getType(); - auto origPhi = destBlock->getPhiArguments()[0]; - SILValue undef = SILUndef::get(origType, getBuilder().getFunction()); - SmallVector useList(origPhi->use_begin(), origPhi->use_end()); - for (auto *use : useList) { - use->set(undef); - } - - auto *newPhi = - destBlock->replacePhiArgument(0, withType, origPhi->getOwnershipKind()); - - getBuilder().setInsertionPoint(destBlock->begin()); - auto cast = createCast(loc, newPhi, origType); - for (auto *use : useList) { - use->set(cast); - } - } - - void fixUp(SILFunction *) { - auto &clonedFunction = getBuilder().getFunction(); - for (auto &BB : clonedFunction) { - for (auto &cloned : BB) { - // Fix up the type of try_apply successor block arguments. - if (auto *tryApply = dyn_cast(&cloned)) { - auto normalBB = tryApply->getNormalBB(); - SILFunctionConventions calleeConv( - tryApply->getSubstCalleeType(), - tryApply->getFunction()->getModule()); - auto normalBBType = (*normalBB->args_begin())->getType(); - auto applyResultType = calleeConv.getSILResultType(); - if (normalBBType != calleeConv.getSILResultType()) { - replaceBlockArgumentType(tryApply->getLoc(), normalBB, applyResultType); - } - } - // Fix up the type of switch_enum successor block arguments. - if (auto *switchEnum = dyn_cast(&cloned)) { - SILType enumTy = switchEnum->getOperand()->getType(); - for (unsigned i = 0, e = switchEnum->getNumCases(); i < e; ++i) { - EnumElementDecl *elt; - SILBasicBlock *dest; - std::tie(elt, dest) = switchEnum->getCase(i); - - if (elt->hasAssociatedValues() && - dest->getArguments().size() == 1) { - SILType eltArgTy = - enumTy.getEnumElementType(elt, clonedFunction.getModule()); - SILType bbArgTy = dest->getArguments()[0]->getType(); - if (eltArgTy != bbArgTy) - replaceBlockArgumentType(switchEnum->getLoc(), dest, eltArgTy); - - } - } - } - } - } - } -}; -} // namespace - -void OpaqueSpecializerCloner::clone() { - for (auto arg: entryBlock->getArguments()) - recordFoldedValue(arg, arg); - cloneReachableBlocks(cloneFromBlock, {}, entryBlock, - true /*havePrepopulatedFunctionArgs*/); - getBuilder().setInsertionPoint(entryBlock); - getBuilder().createBranch(RegularLocation::getAutoGeneratedLocation(), - getOpBasicBlock(cloneFromBlock)); -} - -/// Update address uses of the opaque type archetype with the concrete type. -/// This is neccessary for apply instructions. -void OpaqueSpecializerCloner::insertOpaqueToConcreteAddressCasts( - SILInstruction *orig, SILInstruction *cloned) { - - // Replace apply operands. - if (auto apply = ApplySite::isa(cloned)) { - SavedInsertionPointRAII restore(getBuilder()); - getBuilder().setInsertionPoint(apply.getInstruction()); - auto substConv = apply.getSubstCalleeConv(); - unsigned idx = 0; - for (auto &opd : apply.getArgumentOperands()) { - auto argIdx = apply.getCalleeArgIndex(opd); - auto argType = substConv.getSILArgumentType(argIdx); - if (argType.getASTType() != opd.get()->getType().getASTType()) { - opd.set(createCast(apply.getLoc(), opd.get(), argType)); - } - ++idx; - } - } -} - -namespace { -class OpaqueArchetypeSpecializer : public SILFunctionTransform { - void run() override { - if (!EnableOpaqueArchetypeSpecializer) - return; - - auto *context = getFunction(); - - if (!context->shouldOptimize()) - return; - - auto opaqueArchetypeWouldChange = [=](CanType ty) -> bool { - if (!ty->hasOpaqueArchetype()) - return false; - - return ty.findIf([=](Type type) -> bool { - if (auto opaqueTy = type->getAs()) { - auto opaque = opaqueTy->getDecl(); - OpaqueSubstitutionKind subKind = - ReplaceOpaqueTypesWithUnderlyingTypes:: - shouldPerformSubstitution(opaque, - context->getModule().getSwiftModule(), - context->getResilienceExpansion()); - return subKind != OpaqueSubstitutionKind::DontSubstitute; - } - return false; - }); - }; - - // Look for opaque type archetypes. - bool foundOpaqueArchetype = false; - for (auto &BB : *getFunction()) { - for (auto &inst : BB) { - auto hasOpaqueOperand = [&] (SILInstruction &inst) -> bool { - // Check the operands for opaque types. - for (auto &opd : inst.getAllOperands()) - if (opaqueArchetypeWouldChange(opd.get()->getType().getASTType())) - return true; - return false; - }; - if ((foundOpaqueArchetype = hasOpaqueOperand(inst))) - break; - auto hasOpaqueResult = [&](SILInstruction &inst) -> bool { - // Check the results for opaque types. - for (const auto &res : inst.getResults()) - if (opaqueArchetypeWouldChange(res->getType().getASTType())) - return true; - return false; - }; - if ((foundOpaqueArchetype = hasOpaqueResult(inst))) - break; - } - if (foundOpaqueArchetype) - break; - } - - if (foundOpaqueArchetype) { - OpaqueSpecializerCloner s(*getFunction()); - s.clone(); - removeUnreachableBlocks(*getFunction()); - invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody); - } - } -}; -} // end anonymous namespace - -SILTransform *swift::createOpaqueArchetypeSpecializer() { - return new OpaqueArchetypeSpecializer(); -} diff --git a/lib/SILOptimizer/UtilityPasses/LSLocationPrinter.cpp b/lib/SILOptimizer/UtilityPasses/LSLocationPrinter.cpp index 9c5ac3a6e8e42..e30cbc9cce79f 100644 --- a/lib/SILOptimizer/UtilityPasses/LSLocationPrinter.cpp +++ b/lib/SILOptimizer/UtilityPasses/LSLocationPrinter.cpp @@ -78,12 +78,14 @@ class LSLocationPrinter : public SILModuleTransform { SILValue V = LI->getOperand(); // This is an address type, take it object type. SILType Ty = V->getType().getObjectType(); - ProjectionPath::expandTypeIntoLeafProjectionPaths(Ty, M, PPList); + ProjectionPath::expandTypeIntoLeafProjectionPaths( + Ty, M, TypeExpansionContext(Fn), PPList); } else if (auto *SI = dyn_cast(&II)) { SILValue V = SI->getDest(); // This is an address type, take it object type. SILType Ty = V->getType().getObjectType(); - ProjectionPath::expandTypeIntoLeafProjectionPaths(Ty, M, PPList); + ProjectionPath::expandTypeIntoLeafProjectionPaths( + Ty, M, TypeExpansionContext(Fn), PPList); } else { // Not interested in these instructions yet. continue; @@ -91,7 +93,7 @@ class LSLocationPrinter : public SILModuleTransform { llvm::outs() << "#" << Counter++ << II; for (auto &T : PPList) { - T.getValue().print(llvm::outs(), *M); + T.getValue().print(llvm::outs(), *M, TypeExpansionContext(Fn)); } PPList.clear(); } @@ -111,12 +113,14 @@ class LSLocationPrinter : public SILModuleTransform { V = LI->getOperand(); // This is an address type, take it object type. Ty = V->getType().getObjectType(); - ProjectionPath::expandTypeIntoLeafProjectionPaths(Ty, M, PPList); + ProjectionPath::expandTypeIntoLeafProjectionPaths( + Ty, M, TypeExpansionContext(Fn), PPList); } else if (auto *SI = dyn_cast(&II)) { V = SI->getDest(); // This is an address type, take it object type. Ty = V->getType().getObjectType(); - ProjectionPath::expandTypeIntoLeafProjectionPaths(Ty, M, PPList); + ProjectionPath::expandTypeIntoLeafProjectionPaths( + Ty, M, TypeExpansionContext(Fn), PPList); } else { // Not interested in these instructions yet. continue; @@ -124,7 +128,7 @@ class LSLocationPrinter : public SILModuleTransform { llvm::outs() << "#" << Counter++ << II; for (auto &T : PPList) { - T.getValue().print(llvm::outs(), *M); + T.getValue().print(llvm::outs(), *M, TypeExpansionContext(Fn)); } PPList.clear(); } @@ -150,14 +154,16 @@ class LSLocationPrinter : public SILModuleTransform { L.init(UO, ProjectionPath::getProjectionPath(UO, Mem)); if (!L.isValid()) continue; - LSLocation::expand(L, &Fn.getModule(), Locs, TE); + LSLocation::expand(L, &Fn.getModule(), TypeExpansionContext(Fn), Locs, + TE); } else if (auto *SI = dyn_cast(&II)) { SILValue Mem = SI->getDest(); SILValue UO = getUnderlyingObject(Mem); L.init(UO, ProjectionPath::getProjectionPath(UO, Mem)); if (!L.isValid()) continue; - LSLocation::expand(L, &Fn.getModule(), Locs, TE); + LSLocation::expand(L, &Fn.getModule(), TypeExpansionContext(Fn), Locs, + TE); } else { // Not interested in these instructions yet. continue; @@ -165,7 +171,7 @@ class LSLocationPrinter : public SILModuleTransform { llvm::outs() << "#" << Counter++ << II; for (auto &Loc : Locs) { - Loc.print(llvm::outs(), &Fn.getModule()); + Loc.print(llvm::outs(), &Fn.getModule(), TypeExpansionContext(Fn)); } Locs.clear(); } @@ -194,14 +200,16 @@ class LSLocationPrinter : public SILModuleTransform { L.init(UO, ProjectionPath::getProjectionPath(UO, Mem)); if (!L.isValid()) continue; - LSLocation::expand(L, &Fn.getModule(), Locs, TE); + LSLocation::expand(L, &Fn.getModule(), TypeExpansionContext(Fn), Locs, + TE); } else if (auto *SI = dyn_cast(&II)) { SILValue Mem = SI->getDest(); SILValue UO = getUnderlyingObject(Mem); L.init(UO, ProjectionPath::getProjectionPath(UO, Mem)); if (!L.isValid()) continue; - LSLocation::expand(L, &Fn.getModule(), Locs, TE); + LSLocation::expand(L, &Fn.getModule(), TypeExpansionContext(Fn), Locs, + TE); } else { // Not interested in these instructions yet. continue; @@ -216,10 +224,10 @@ class LSLocationPrinter : public SILModuleTransform { } // This should get the original (unexpanded) location back. - LSLocation::reduce(L, &Fn.getModule(), SLocs); + LSLocation::reduce(L, &Fn.getModule(), TypeExpansionContext(Fn), SLocs); llvm::outs() << "#" << Counter++ << II; for (auto &Loc : SLocs) { - Loc.print(llvm::outs(), &Fn.getModule()); + Loc.print(llvm::outs(), &Fn.getModule(), TypeExpansionContext(Fn)); } L.reset(); Locs.clear(); diff --git a/lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp b/lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp index 31703885545fa..75645fa97a748 100644 --- a/lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp +++ b/lib/SILOptimizer/UtilityPasses/SerializeSILPass.cpp @@ -12,11 +12,382 @@ #define DEBUG_TYPE "serialize-sil" #include "swift/Strings.h" +#include "swift/SIL/ApplySite.h" +#include "swift/SIL/SILCloner.h" +#include "swift/SIL/SILFunction.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" using namespace swift; +namespace { +/// In place map opaque archetypes to their underlying type in a function. +/// This needs to happen when a function changes from serializable to not +/// serializable. +class MapOpaqueArchetypes : public SILCloner { + using SuperTy = SILCloner; + + SILBasicBlock *origEntryBlock; + SILBasicBlock *clonedEntryBlock; +public: + friend class SILCloner; + friend class SILCloner; + friend class SILInstructionVisitor; + + MapOpaqueArchetypes(SILFunction &fun) : SuperTy(fun) { + origEntryBlock = fun.getEntryBlock(); + clonedEntryBlock = fun.createBasicBlock(); + } + + SILType remapType(SILType Ty) { + if (!Ty.getASTType()->hasOpaqueArchetype() || + !getBuilder() + .getTypeExpansionContext() + .shouldLookThroughOpaqueTypeArchetypes()) + return Ty; + + return getBuilder().getTypeLowering(Ty).getLoweredType().getCategoryType( + Ty.getCategory()); + } + + CanType remapASTType(CanType ty) { + if (!ty->hasOpaqueArchetype() || + !getBuilder() + .getTypeExpansionContext() + .shouldLookThroughOpaqueTypeArchetypes()) + return ty; + // Remap types containing opaque result types in the current context. + return getBuilder() + .getTypeLowering(SILType::getPrimitiveObjectType(ty)) + .getLoweredType() + .getASTType(); + } + + ProtocolConformanceRef remapConformance(Type ty, + ProtocolConformanceRef conf) { + auto context = getBuilder().getTypeExpansionContext(); + auto conformance = conf; + if (ty->hasOpaqueArchetype() && + context.shouldLookThroughOpaqueTypeArchetypes()) { + conformance = + substOpaqueTypesWithUnderlyingTypes(conformance, ty, context); + } + return conformance; + } + + void replace(); +}; +} // namespace + +void MapOpaqueArchetypes::replace() { + // Map the function arguments. + SmallVector entryArgs; + entryArgs.reserve(origEntryBlock->getArguments().size()); + for (auto &origArg : origEntryBlock->getArguments()) { + SILType mappedType = remapType(origArg->getType()); + auto *NewArg = clonedEntryBlock->createFunctionArgument( + mappedType, origArg->getDecl(), true); + entryArgs.push_back(NewArg); + } + + getBuilder().setInsertionPoint(clonedEntryBlock); + auto &fn = getBuilder().getFunction(); + cloneFunctionBody(&fn, clonedEntryBlock, entryArgs, + true /*replaceOriginalFunctionInPlace*/); + // Insert the new entry block at the beginning. + fn.getBlocks().splice(fn.getBlocks().begin(), fn.getBlocks(), + clonedEntryBlock); + removeUnreachableBlocks(fn); +} + +static bool opaqueArchetypeWouldChange(TypeExpansionContext context, + CanType ty) { + if (!ty->hasOpaqueArchetype()) + return false; + + return ty.findIf([=](Type type) -> bool { + if (auto opaqueTy = type->getAs()) { + auto opaque = opaqueTy->getDecl(); + auto module = context.getContext()->getParentModule(); + OpaqueSubstitutionKind subKind = + ReplaceOpaqueTypesWithUnderlyingTypes::shouldPerformSubstitution( + opaque, module, context.getResilienceExpansion()); + return subKind != OpaqueSubstitutionKind::DontSubstitute; + } + return false; + }); +} + +static bool hasOpaqueArchetypeOperand(TypeExpansionContext context, + SILInstruction &inst) { + // Check the operands for opaque types. + for (auto &opd : inst.getAllOperands()) + if (opaqueArchetypeWouldChange(context, opd.get()->getType().getASTType())) + return true; + return false; +} + +static bool hasOpaqueArchetypeResult(TypeExpansionContext context, + SILInstruction &inst) { + // Check the results for opaque types. + for (const auto &res : inst.getResults()) + if (opaqueArchetypeWouldChange(context, res->getType().getASTType())) + return true; + return false; +} + +static bool hasOpaqueArchetype(TypeExpansionContext context, + SILInstruction &inst) { + // Check operands and results. + if (hasOpaqueArchetypeOperand(context, inst)) + return true; + if (hasOpaqueArchetypeResult(context, inst)) + return true; + + // Check substitution maps. + switch (inst.getKind()) { + case SILInstructionKind::AllocStackInst: + case SILInstructionKind::AllocRefInst: + case SILInstructionKind::AllocRefDynamicInst: + case SILInstructionKind::AllocValueBufferInst: + case SILInstructionKind::AllocBoxInst: + case SILInstructionKind::AllocExistentialBoxInst: + case SILInstructionKind::IndexAddrInst: + case SILInstructionKind::TailAddrInst: + case SILInstructionKind::IndexRawPointerInst: + case SILInstructionKind::FunctionRefInst: + case SILInstructionKind::DynamicFunctionRefInst: + case SILInstructionKind::PreviousDynamicFunctionRefInst: + case SILInstructionKind::GlobalAddrInst: + case SILInstructionKind::GlobalValueInst: + case SILInstructionKind::IntegerLiteralInst: + case SILInstructionKind::FloatLiteralInst: + case SILInstructionKind::StringLiteralInst: + case SILInstructionKind::ClassMethodInst: + case SILInstructionKind::SuperMethodInst: + case SILInstructionKind::ObjCMethodInst: + case SILInstructionKind::ObjCSuperMethodInst: + case SILInstructionKind::WitnessMethodInst: + case SILInstructionKind::UpcastInst: + case SILInstructionKind::AddressToPointerInst: + case SILInstructionKind::PointerToAddressInst: + case SILInstructionKind::UncheckedRefCastInst: + case SILInstructionKind::UncheckedAddrCastInst: + case SILInstructionKind::UncheckedTrivialBitCastInst: + case SILInstructionKind::UncheckedBitwiseCastInst: + case SILInstructionKind::RefToRawPointerInst: + case SILInstructionKind::RawPointerToRefInst: +#define LOADABLE_REF_STORAGE(Name, ...) \ + case SILInstructionKind::RefTo##Name##Inst: \ + case SILInstructionKind::Name##ToRefInst: +#include "swift/AST/ReferenceStorage.def" +#undef LOADABLE_REF_STORAGE_HELPER + case SILInstructionKind::ConvertFunctionInst: + case SILInstructionKind::ConvertEscapeToNoEscapeInst: + case SILInstructionKind::ThinFunctionToPointerInst: + case SILInstructionKind::PointerToThinFunctionInst: + case SILInstructionKind::RefToBridgeObjectInst: + case SILInstructionKind::BridgeObjectToRefInst: + case SILInstructionKind::BridgeObjectToWordInst: + case SILInstructionKind::ThinToThickFunctionInst: + case SILInstructionKind::ThickToObjCMetatypeInst: + case SILInstructionKind::ObjCToThickMetatypeInst: + case SILInstructionKind::ObjCMetatypeToObjectInst: + case SILInstructionKind::ObjCExistentialMetatypeToObjectInst: + case SILInstructionKind::UnconditionalCheckedCastValueInst: + case SILInstructionKind::UnconditionalCheckedCastInst: + case SILInstructionKind::ClassifyBridgeObjectInst: + case SILInstructionKind::ValueToBridgeObjectInst: + case SILInstructionKind::MarkDependenceInst: + case SILInstructionKind::CopyBlockInst: + case SILInstructionKind::CopyBlockWithoutEscapingInst: + case SILInstructionKind::CopyValueInst: +#define UNCHECKED_REF_STORAGE(Name, ...) \ + case SILInstructionKind::StrongCopy##Name##ValueInst: +#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + case SILInstructionKind::StrongCopy##Name##ValueInst: +#include "swift/AST/ReferenceStorage.def" +#undef UNCHECKED_REF_STORAGE +#undef ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE + case SILInstructionKind::UncheckedOwnershipConversionInst: + case SILInstructionKind::IsUniqueInst: + case SILInstructionKind::IsEscapingClosureInst: + case SILInstructionKind::LoadInst: + case SILInstructionKind::LoadBorrowInst: + case SILInstructionKind::BeginBorrowInst: + case SILInstructionKind::StoreBorrowInst: + case SILInstructionKind::BeginAccessInst: +#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ + case SILInstructionKind::Load##Name##Inst: +#include "swift/AST/ReferenceStorage.def" +#undef NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE + case SILInstructionKind::MarkUninitializedInst: + case SILInstructionKind::ProjectValueBufferInst: + case SILInstructionKind::ProjectBoxInst: + case SILInstructionKind::ProjectExistentialBoxInst: + case SILInstructionKind::BuiltinInst: + case SILInstructionKind::MetatypeInst: + case SILInstructionKind::ValueMetatypeInst: + case SILInstructionKind::ExistentialMetatypeInst: + case SILInstructionKind::ObjCProtocolInst: + case SILInstructionKind::ObjectInst: + case SILInstructionKind::TupleInst: + case SILInstructionKind::TupleExtractInst: + case SILInstructionKind::TupleElementAddrInst: + case SILInstructionKind::StructInst: + case SILInstructionKind::StructExtractInst: + case SILInstructionKind::StructElementAddrInst: + case SILInstructionKind::RefElementAddrInst: + case SILInstructionKind::RefTailAddrInst: + case SILInstructionKind::EnumInst: + case SILInstructionKind::UncheckedEnumDataInst: + case SILInstructionKind::InitEnumDataAddrInst: + case SILInstructionKind::UncheckedTakeEnumDataAddrInst: + case SILInstructionKind::SelectEnumInst: + case SILInstructionKind::SelectEnumAddrInst: + case SILInstructionKind::SelectValueInst: + case SILInstructionKind::InitExistentialAddrInst: + case SILInstructionKind::InitExistentialValueInst: + case SILInstructionKind::OpenExistentialAddrInst: + case SILInstructionKind::InitExistentialRefInst: + case SILInstructionKind::OpenExistentialRefInst: + case SILInstructionKind::InitExistentialMetatypeInst: + case SILInstructionKind::OpenExistentialMetatypeInst: + case SILInstructionKind::OpenExistentialBoxInst: + case SILInstructionKind::OpenExistentialValueInst: + case SILInstructionKind::OpenExistentialBoxValueInst: + case SILInstructionKind::ProjectBlockStorageInst: + case SILInstructionKind::InitBlockStorageHeaderInst: + case SILInstructionKind::KeyPathInst: + case SILInstructionKind::UnreachableInst: + case SILInstructionKind::ReturnInst: + case SILInstructionKind::ThrowInst: + case SILInstructionKind::YieldInst: + case SILInstructionKind::UnwindInst: + case SILInstructionKind::BranchInst: + case SILInstructionKind::CondBranchInst: + case SILInstructionKind::SwitchValueInst: + case SILInstructionKind::SwitchEnumInst: + case SILInstructionKind::SwitchEnumAddrInst: + case SILInstructionKind::DynamicMethodBranchInst: + case SILInstructionKind::CheckedCastBranchInst: + case SILInstructionKind::CheckedCastAddrBranchInst: + case SILInstructionKind::CheckedCastValueBranchInst: + case SILInstructionKind::DeallocStackInst: + case SILInstructionKind::DeallocRefInst: + case SILInstructionKind::DeallocPartialRefInst: + case SILInstructionKind::DeallocValueBufferInst: + case SILInstructionKind::DeallocBoxInst: + case SILInstructionKind::DeallocExistentialBoxInst: + case SILInstructionKind::StrongRetainInst: + case SILInstructionKind::StrongReleaseInst: + case SILInstructionKind::UnmanagedRetainValueInst: + case SILInstructionKind::UnmanagedReleaseValueInst: + case SILInstructionKind::UnmanagedAutoreleaseValueInst: +#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + case SILInstructionKind::StrongRetain##Name##Inst: \ + case SILInstructionKind::Name##RetainInst: \ + case SILInstructionKind::Name##ReleaseInst: +#include "swift/AST/ReferenceStorage.def" +#undef ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE + case SILInstructionKind::RetainValueInst: + case SILInstructionKind::RetainValueAddrInst: + case SILInstructionKind::ReleaseValueInst: + case SILInstructionKind::ReleaseValueAddrInst: + case SILInstructionKind::SetDeallocatingInst: + case SILInstructionKind::AutoreleaseValueInst: + case SILInstructionKind::BindMemoryInst: + case SILInstructionKind::FixLifetimeInst: + case SILInstructionKind::DestroyValueInst: + case SILInstructionKind::EndBorrowInst: + case SILInstructionKind::EndAccessInst: + case SILInstructionKind::BeginUnpairedAccessInst: + case SILInstructionKind::EndUnpairedAccessInst: + case SILInstructionKind::StoreInst: + case SILInstructionKind::AssignInst: + case SILInstructionKind::AssignByWrapperInst: + case SILInstructionKind::MarkFunctionEscapeInst: + case SILInstructionKind::DebugValueInst: + case SILInstructionKind::DebugValueAddrInst: +#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + case SILInstructionKind::Store##Name##Inst: +#include "swift/AST/ReferenceStorage.def" + case SILInstructionKind::CopyAddrInst: + case SILInstructionKind::DestroyAddrInst: + case SILInstructionKind::EndLifetimeInst: + case SILInstructionKind::InjectEnumAddrInst: + case SILInstructionKind::DeinitExistentialAddrInst: + case SILInstructionKind::DeinitExistentialValueInst: + case SILInstructionKind::UnconditionalCheckedCastAddrInst: + case SILInstructionKind::UncheckedRefCastAddrInst: + case SILInstructionKind::AllocGlobalInst: + case SILInstructionKind::EndApplyInst: + case SILInstructionKind::AbortApplyInst: + case SILInstructionKind::CondFailInst: + case SILInstructionKind::DestructureStructInst: + case SILInstructionKind::DestructureTupleInst: + // Handle by operand and result check. + break; + + case SILInstructionKind::ApplyInst: + case SILInstructionKind::PartialApplyInst: + case SILInstructionKind::TryApplyInst: + case SILInstructionKind::BeginApplyInst: + // Check substitution map. + auto apply = ApplySite(&inst); + auto subs = apply.getSubstitutionMap(); + for (auto ty: subs.getReplacementTypes()) { + if (opaqueArchetypeWouldChange(context, ty->getCanonicalType())) + return true; + } + break; + } + + return false; +} + +static bool hasOpaqueArchetypeArgument(TypeExpansionContext context, SILBasicBlock &BB) { + for (auto *arg : BB.getArguments()) { + if (opaqueArchetypeWouldChange(context, arg->getType().getASTType())) + return true; + } + return false; +} + +static bool hasAnyOpaqueArchetype(SILFunction &F) { + bool foundOpaqueArchetype = false; + auto context = F.getTypeExpansionContext(); + for (auto &BB : F) { + // Check basic block argument types. + if (hasOpaqueArchetypeArgument(context, BB)) { + foundOpaqueArchetype = true; + break; + } + + // Check instruction results and operands. + for (auto &inst : BB) { + if (hasOpaqueArchetype(context, inst)) { + foundOpaqueArchetype = true; + break; + } + } + + if (foundOpaqueArchetype) + break; + } + + return foundOpaqueArchetype; +} + +void updateOpaqueArchetypes(SILFunction &F) { + // Only map if there are opaque archetypes that could change. + if (!hasAnyOpaqueArchetype(F)) + return; + + MapOpaqueArchetypes(F).replace(); +} + /// A utility pass to serialize a SILModule at any place inside the optimization /// pipeline. class SerializeSILPass : public SILModuleTransform { @@ -24,7 +395,16 @@ class SerializeSILPass : public SILModuleTransform { /// optimizations and for a better dead function elimination. void removeSerializedFlagFromAllFunctions(SILModule &M) { for (auto &F : M) { + bool wasSerialized = F.isSerialized() != IsNotSerialized; F.setSerialized(IsNotSerialized); + + // We are removing [serialized] from the function. This will change how + // opaque archetypes are lowered in SIL - they might lower to their + // underlying type. Update the function's opaque archetypes. + if (wasSerialized && F.isDefinition()) { + updateOpaqueArchetypes(F); + invalidateAnalysis(&F, SILAnalysis::InvalidationKind::Everything); + } } for (auto &WT : M.getWitnessTables()) { diff --git a/lib/SILOptimizer/Utils/CastOptimizer.cpp b/lib/SILOptimizer/Utils/CastOptimizer.cpp index 1ff70ac1ea143..f5e3a5fe77ad8 100644 --- a/lib/SILOptimizer/Utils/CastOptimizer.cpp +++ b/lib/SILOptimizer/Utils/CastOptimizer.cpp @@ -628,7 +628,8 @@ CastOptimizer::optimizeBridgedSwiftToObjCCast(SILDynamicCastInst dynamicCast) { std::tie(bridgedFunc, subMap) = result.getValue(); } - SILType SubstFnTy = bridgedFunc->getLoweredType().substGenericArgs(M, subMap); + SILType SubstFnTy = bridgedFunc->getLoweredType().substGenericArgs( + M, subMap, TypeExpansionContext(*F)); SILFunctionConventions substConv(SubstFnTy.castTo(), M); // Check that this is a case that the authors of this code thought it could diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp index ff881c8fb690c..e7d6e9e0f2714 100644 --- a/lib/SILOptimizer/Utils/Devirtualize.cpp +++ b/lib/SILOptimizer/Utils/Devirtualize.cpp @@ -743,14 +743,16 @@ FullApplySite swift::devirtualizeClassMethod(FullApplySite applySite, auto *f = getTargetClassMethod(module, cd, mi); - CanSILFunctionType genCalleeType = f->getLoweredFunctionType(); + CanSILFunctionType genCalleeType = f->getLoweredFunctionTypeInContext( + TypeExpansionContext(*applySite.getFunction())); SubstitutionMap subs = getSubstitutionsForCallee( module, genCalleeType, classOrMetatype->getType().getASTType(), applySite); CanSILFunctionType substCalleeType = genCalleeType; if (genCalleeType->isPolymorphic()) - substCalleeType = genCalleeType->substGenericArgs(module, subs); + substCalleeType = genCalleeType->substGenericArgs( + module, subs, TypeExpansionContext(*applySite.getFunction())); SILFunctionConventions substConv(substCalleeType, module); SILBuilderWithScope builder(applySite.getInstruction()); @@ -937,7 +939,8 @@ SubstitutionMap swift::getWitnessMethodSubstitutions(SILModule &module, ApplySite applySite, SILFunction *f, ProtocolConformanceRef cRef) { - auto witnessFnTy = f->getLoweredFunctionType(); + auto witnessFnTy = f->getLoweredFunctionTypeInContext( + TypeExpansionContext(*applySite.getFunction())); assert(witnessFnTy->getRepresentation() == SILFunctionTypeRepresentation::WitnessMethod); @@ -975,8 +978,10 @@ static ApplySite devirtualizeWitnessMethod(ApplySite applySite, SILFunction *f, // Figure out the exact bound type of the function to be called by // applying all substitutions. - auto calleeCanType = f->getLoweredFunctionType(); - auto substCalleeCanType = calleeCanType->substGenericArgs(module, subMap); + auto calleeCanType = f->getLoweredFunctionTypeInContext( + TypeExpansionContext(*applySite.getFunction())); + auto substCalleeCanType = calleeCanType->substGenericArgs( + module, subMap, TypeExpansionContext(*applySite.getFunction())); // Collect arguments from the apply instruction. SmallVector arguments; diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp index d9ddecae47bb1..51375e857424e 100644 --- a/lib/SILOptimizer/Utils/Generics.cpp +++ b/lib/SILOptimizer/Utils/Generics.cpp @@ -537,12 +537,12 @@ bool ReabstractionInfo::canBeSpecialized(ApplySite Apply, SILFunction *Callee, return ReInfo.prepareAndCheck(Apply, Callee, ParamSubs); } -ReabstractionInfo::ReabstractionInfo(ApplySite Apply, SILFunction *Callee, - SubstitutionMap ParamSubs, - IsSerialized_t Serialized, - bool ConvertIndirectToDirect, - OptRemark::Emitter *ORE) +ReabstractionInfo::ReabstractionInfo( + ModuleDecl *targetModule, bool isWholeModule, ApplySite Apply, + SILFunction *Callee, SubstitutionMap ParamSubs, IsSerialized_t Serialized, + bool ConvertIndirectToDirect, OptRemark::Emitter *ORE) : ConvertIndirectToDirect(ConvertIndirectToDirect), + TargetModule(targetModule), isWholeModule(isWholeModule), Serialized(Serialized) { if (!prepareAndCheck(Apply, Callee, ParamSubs, ORE)) return; @@ -576,14 +576,16 @@ ReabstractionInfo::ReabstractionInfo(ApplySite Apply, SILFunction *Callee, auto CalleeFnTy = Callee->getLoweredFunctionType(); assert(CalleeFnTy->isPolymorphic()); auto CalleeSubstFnTy = CalleeFnTy->substGenericArgs( - Callee->getModule(), getCalleeParamSubstitutionMap()); + Callee->getModule(), getCalleeParamSubstitutionMap(), + getResilienceExpansion()); assert(!CalleeSubstFnTy->isPolymorphic() && "Substituted callee type should not be polymorphic"); assert(!CalleeSubstFnTy->hasTypeParameter() && "Substituted callee type should not have type parameters"); SpecializedSubstFnTy = SpecializedFnTy->substGenericArgs( - Callee->getModule(), getCallerParamSubstitutionMap()); + Callee->getModule(), getCallerParamSubstitutionMap(), + getResilienceExpansion()); assert(!SpecializedSubstFnTy->isPolymorphic() && "Substituted callee type should not be polymorphic"); @@ -756,7 +758,8 @@ ReabstractionInfo::createSubstitutedType(SILFunction *OrigF, { Lowering::GenericContextScope GenericScope(M.Types, CanSpecializedGenericSig); - FnTy = OrigF->getLoweredFunctionType()->substGenericArgs(M, SubstMap); + FnTy = OrigF->getLoweredFunctionType()->substGenericArgs( + M, SubstMap, getResilienceExpansion()); // FIXME: Some of the added new requirements may not have been taken into // account by the substGenericArgs. So, canonicalize in the context of the // specialized signature. @@ -886,7 +889,7 @@ void ReabstractionInfo::performFullSpecializationPreparation( ClonerParamSubMap = ParamSubs; SubstitutedType = Callee->getLoweredFunctionType()->substGenericArgs( - M, ClonerParamSubMap); + M, ClonerParamSubMap, getResilienceExpansion()); CallerParamSubMap = {}; createSubstitutedAndSpecializedTypes(); } @@ -1755,8 +1758,10 @@ void ReabstractionInfo::finishPartialSpecializationPreparation( } /// This constructor is used when processing @_specialize. -ReabstractionInfo::ReabstractionInfo(SILFunction *Callee, - GenericSignature SpecializedSig) { +ReabstractionInfo::ReabstractionInfo(ModuleDecl *targetModule, + bool isWholeModule, SILFunction *Callee, + GenericSignature SpecializedSig) + : TargetModule(targetModule), isWholeModule(isWholeModule) { Serialized = Callee->isSerialized(); if (shouldNotSpecialize(Callee, nullptr)) @@ -1932,10 +1937,11 @@ static void prepareCallArguments(ApplySite AI, SILBuilder &Builder, /// Return a substituted callee function type. static CanSILFunctionType -getCalleeSubstFunctionType(SILValue Callee, SubstitutionMap Subs) { +getCalleeSubstFunctionType(SILValue Callee, SubstitutionMap Subs, + TypeExpansionContext context) { // Create a substituted callee type. auto CanFnTy = Callee->getType().castTo(); - return CanFnTy->substGenericArgs(*Callee->getModule(), Subs); + return CanFnTy->substGenericArgs(*Callee->getModule(), Subs, context); } /// Create a new apply based on an old one, but with a different @@ -1956,7 +1962,8 @@ static ApplySite replaceWithSpecializedCallee(ApplySite AI, Subs = ReInfo.getCallerParamSubstitutionMap(); } - auto CalleeSubstFnTy = getCalleeSubstFunctionType(Callee, Subs); + auto CalleeSubstFnTy = + getCalleeSubstFunctionType(Callee, Subs, ReInfo.getResilienceExpansion()); auto CalleeSILSubstFnTy = SILType::getPrimitiveObjectType(CalleeSubstFnTy); SILFunctionConventions substConv(CalleeSubstFnTy, Builder.getModule()); @@ -2261,9 +2268,10 @@ static bool createPrespecialized(StringRef UnspecializedName, if (!UnspecFunc || !UnspecFunc->isDefinition()) return false; - ReabstractionInfo ReInfo(ApplySite(), UnspecFunc, Apply.getSubstitutionMap(), - IsNotSerialized, /*ConvertIndirectToDirect=*/true, - nullptr); + ReabstractionInfo ReInfo(M.getSwiftModule(), M.isWholeModule(), ApplySite(), + UnspecFunc, Apply.getSubstitutionMap(), + IsNotSerialized, + /*ConvertIndirectToDirect=*/true, nullptr); if (!ReInfo.canBeSpecialized()) return false; @@ -2362,9 +2370,10 @@ void swift::trySpecializeApplyOfGeneric( Serialized = IsNotSerialized; } - ReabstractionInfo ReInfo(Apply, RefF, Apply.getSubstitutionMap(), - Serialized, /*ConvertIndirectToDirect=*/true, - &ORE); + ReabstractionInfo ReInfo(FuncBuilder.getModule().getSwiftModule(), + FuncBuilder.getModule().isWholeModule(), Apply, RefF, + Apply.getSubstitutionMap(), Serialized, + /*ConvertIndirectToDirect=*/true, &ORE); if (!ReInfo.canBeSpecialized()) return; diff --git a/lib/SILOptimizer/Utils/InstOptUtils.cpp b/lib/SILOptimizer/Utils/InstOptUtils.cpp index e952b85f57dbc..fa87ac8eb62cd 100644 --- a/lib/SILOptimizer/Utils/InstOptUtils.cpp +++ b/lib/SILOptimizer/Utils/InstOptUtils.cpp @@ -1224,7 +1224,7 @@ bool swift::simplifyUsers(SingleValueInstruction *inst) { /// True if a type can be expanded without a significant increase to code size. bool swift::shouldExpand(SILModule &module, SILType ty) { // FIXME: Expansion - auto expansion = ResilienceExpansion::Minimal; + auto expansion = TypeExpansionContext::minimal(); if (module.Types.getTypeLowering(ty, expansion).isAddressOnly()) { return false; diff --git a/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp b/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp index 93dcad0c477b6..80992cb15ad58 100644 --- a/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp +++ b/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp @@ -31,10 +31,9 @@ removeLSLocations(LSLocationValueMap &Values, LSLocationList &NextLevel) { //===----------------------------------------------------------------------===// // LSValue //===----------------------------------------------------------------------===// -void -LSValue::expand(SILValue Base, SILModule *M, LSValueList &Vals, - TypeExpansionAnalysis *TE) { - for (const auto &P : TE->getTypeExpansion((*Base).getType(), M)) { +void LSValue::expand(SILValue Base, SILModule *M, TypeExpansionContext context, + LSValueList &Vals, TypeExpansionAnalysis *TE) { + for (const auto &P : TE->getTypeExpansion((*Base).getType(), M, context)) { Vals.push_back(LSValue(Base, P.getValue())); } } @@ -42,18 +41,20 @@ LSValue::expand(SILValue Base, SILModule *M, LSValueList &Vals, void LSValue::reduceInner(LSLocation &Base, SILModule *M, LSLocationValueMap &Values, SILInstruction *InsertPt) { + TypeExpansionContext context(*InsertPt->getFunction()); + // If this is a class reference type, we have reached end of the type tree. - if (Base.getType(M).getClassOrBoundGenericClass()) + if (Base.getType(M, context).getClassOrBoundGenericClass()) return; // This a don't expand node. - if (!shouldExpand(*M, Base.getType(M))) { + if (!shouldExpand(*M, Base.getType(M, context))) { return; } // This is a leaf node, we must have a value for it. LSLocationList NextLevel; - Base.getNextLevelLSLocations(NextLevel, M); + Base.getNextLevelLSLocations(NextLevel, M, context); if (NextLevel.empty()) return; @@ -117,11 +118,10 @@ LSValue::reduceInner(LSLocation &Base, SILModule *M, LSLocationValueMap &Values, NullablePtr AI = Projection::createAggFromFirstLevelProjections( Builder, RegularLocation::getAutoGeneratedLocation(), - Base.getType(M).getObjectType(), - Vals); + Base.getType(M, context).getObjectType(), Vals); // This is the Value for the current base. - ProjectionPath P(Base.getType(M)); + ProjectionPath P(Base.getType(M, context)); Values[Base] = LSValue(SILValue(AI.get()), P); removeLSLocations(Values, NextLevel); } @@ -163,11 +163,11 @@ LSLocation::isMayAliasLSLocation(const LSLocation &RHS, AliasAnalysis *AA) { return true; } -void -LSLocation::getNextLevelLSLocations(LSLocationList &Locs, SILModule *Mod) { - SILType Ty = getType(Mod); +void LSLocation::getNextLevelLSLocations(LSLocationList &Locs, SILModule *Mod, + TypeExpansionContext context) { + SILType Ty = getType(Mod, context); llvm::SmallVector Out; - Projection::getFirstLevelProjections(Ty, *Mod, Out); + Projection::getFirstLevelProjections(Ty, *Mod, context, Out); for (auto &X : Out) { ProjectionPath P((*Base).getType()); P.append(Path.getValue()); @@ -176,22 +176,23 @@ LSLocation::getNextLevelLSLocations(LSLocationList &Locs, SILModule *Mod) { } } -void -LSLocation::expand(LSLocation Base, SILModule *M, LSLocationList &Locs, - TypeExpansionAnalysis *TE) { +void LSLocation::expand(LSLocation Base, SILModule *M, + TypeExpansionContext context, LSLocationList &Locs, + TypeExpansionAnalysis *TE) { const ProjectionPath &BasePath = Base.getPath().getValue(); - for (const auto &P : TE->getTypeExpansion(Base.getType(M), M)) { + for (const auto &P : + TE->getTypeExpansion(Base.getType(M, context), M, context)) { Locs.push_back(LSLocation(Base.getBase(), BasePath, P.getValue())); } } /// Gets the sub-locations of \p Base in \p SubLocations. /// Returns false if this is not possible or too complex. -static bool -getSubLocations(LSLocationList &SubLocations, LSLocation Base, SILModule *M, - const LSLocationList &Locs) { +static bool getSubLocations(LSLocationList &SubLocations, LSLocation Base, + SILModule *M, TypeExpansionContext context, + const LSLocationList &Locs) { // If this is a class reference type, we have reached end of the type tree. - if (Base.getType(M).getClassOrBoundGenericClass()) + if (Base.getType(M, context).getClassOrBoundGenericClass()) return false; // Don't expand if it would be too complex. As Locs is a list (and not a set) @@ -199,27 +200,28 @@ getSubLocations(LSLocationList &SubLocations, LSLocation Base, SILModule *M, // Usually Locs is small anyway, because we limit expansion to 6 members. // But with deeply nested types we could run in a corner case where Locs is // large. - if (!shouldExpand(*M, Base.getType(M)) || Locs.size() >= 8) { + if (!shouldExpand(*M, Base.getType(M, context)) || Locs.size() >= 8) { return false; } // This is a leaf node. - Base.getNextLevelLSLocations(SubLocations, M); + Base.getNextLevelLSLocations(SubLocations, M, context); return !SubLocations.empty(); } /// Replaces \p SubLocations with \p Base in \p Locs if all sub-locations are /// alive, i.e. present in \p Locs. -static bool -replaceSubLocations(LSLocation Base, SILModule *M, LSLocationList &Locs, - const LSLocationList &SubLocations) { +static bool replaceSubLocations(LSLocation Base, SILModule *M, + TypeExpansionContext context, + LSLocationList &Locs, + const LSLocationList &SubLocations) { // Find whether all its children of Base are alive. bool Alive = true; for (auto &X : SubLocations) { // Recurse into the next level. LSLocationList NextInnerLevel; - if (getSubLocations(NextInnerLevel, X, M, Locs)) { - Alive &= replaceSubLocations(X, M, Locs, NextInnerLevel); + if (getSubLocations(NextInnerLevel, X, M, context, Locs)) { + Alive &= replaceSubLocations(X, M, context, Locs, NextInnerLevel); } else { Alive &= is_contained(Locs, X); } @@ -237,18 +239,19 @@ replaceSubLocations(LSLocation Base, SILModule *M, LSLocationList &Locs, return true; } -void LSLocation::reduce(LSLocation Base, SILModule *M, LSLocationList &Locs) { +void LSLocation::reduce(LSLocation Base, SILModule *M, + TypeExpansionContext context, LSLocationList &Locs) { LSLocationList SubLocations; - if (getSubLocations(SubLocations, Base, M, Locs)) - replaceSubLocations(Base, M, Locs, SubLocations); + if (getSubLocations(SubLocations, Base, M, context, Locs)) + replaceSubLocations(Base, M, context, Locs, SubLocations); } -void -LSLocation::enumerateLSLocation(SILModule *M, SILValue Mem, - std::vector &Locations, - LSLocationIndexMap &IndexMap, - LSLocationBaseMap &BaseMap, - TypeExpansionAnalysis *TypeCache) { +void LSLocation::enumerateLSLocation(TypeExpansionContext context, SILModule *M, + SILValue Mem, + std::vector &Locations, + LSLocationIndexMap &IndexMap, + LSLocationBaseMap &BaseMap, + TypeExpansionAnalysis *TypeCache) { // We have processed this SILValue before. if (BaseMap.find(Mem) != BaseMap.end()) return; @@ -272,7 +275,7 @@ LSLocation::enumerateLSLocation(SILModule *M, SILValue Mem, // Expand the given Mem into individual fields and add them to the // locationvault. LSLocationList Locs; - LSLocation::expand(L, M, Locs, TypeCache); + LSLocation::expand(L, M, context, Locs, TypeCache); for (auto &Loc : Locs) { if (IndexMap.find(Loc) != IndexMap.end()) continue; @@ -292,14 +295,16 @@ LSLocation::enumerateLSLocations(SILFunction &F, for (auto &B : F) { for (auto &I : B) { if (auto *LI = dyn_cast(&I)) { - enumerateLSLocation(&I.getModule(), LI->getOperand(), Locations, - IndexMap, BaseMap, TypeCache); + enumerateLSLocation(F.getTypeExpansionContext(), &I.getModule(), + LI->getOperand(), Locations, IndexMap, BaseMap, + TypeCache); ++LSCount.first; continue; } if (auto *SI = dyn_cast(&I)) { - enumerateLSLocation(&I.getModule(), SI->getDest(), Locations, - IndexMap, BaseMap, TypeCache); + enumerateLSLocation(F.getTypeExpansionContext(), &I.getModule(), + SI->getDest(), Locations, IndexMap, BaseMap, + TypeCache); ++LSCount.second; continue; } diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 3eeae17f1c77b..751a2ca9c169c 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -326,10 +326,15 @@ SILBasicBlock *SILDeserializer::getBBForReference(SILFunction *Fn, } /// Helper function to convert from Type to SILType. -static SILType getSILType(Type Ty, SILValueCategory Category) { +SILType SILDeserializer::getSILType(Type Ty, SILValueCategory Category, + SILFunction *inContext) { auto TyLoc = TypeLoc::withoutLoc(Ty); - return SILType::getPrimitiveType(TyLoc.getType()->getCanonicalType(), - Category); + if (!inContext) { + return SILType::getPrimitiveType(TyLoc.getType()->getCanonicalType(), + Category); + } + return inContext->getLoweredType(TyLoc.getType()->getCanonicalType()) + .getCategoryType(Category); } /// Helper function to find a SILFunction, given its name and type. @@ -494,7 +499,7 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn, llvm::consumeError(astType.takeError()); return existingFn; } - auto ty = getSILType(astType.get(), SILValueCategory::Object); + auto ty = getSILType(astType.get(), SILValueCategory::Object, nullptr); if (!ty.is()) { LLVM_DEBUG(llvm::dbgs() << "not a function type for SILFunction\n"); MF->fatal(); @@ -806,7 +811,7 @@ SILBasicBlock *SILDeserializer::readSILBasicBlock(SILFunction *Fn, auto ArgTy = MF->getType(TyID); SILArgument *Arg; auto ValueCategory = SILValueCategory(Args[I + 1] & 0xF); - SILType SILArgTy = getSILType(ArgTy, ValueCategory); + SILType SILArgTy = getSILType(ArgTy, ValueCategory, Fn); if (IsEntry) { Arg = CurrentBB->createFunctionArgument(SILArgTy); } else { @@ -1101,68 +1106,68 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, break; case SILInstructionKind::AllocStackInst: assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType."); - ResultVal = Builder.createAllocStack(Loc, - getSILType(MF->getType(TyID), (SILValueCategory)TyCategory), - None, /*bool hasDynamicLifetime*/ Attr != 0); + ResultVal = Builder.createAllocStack( + Loc, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn), + None, /*bool hasDynamicLifetime*/ Attr != 0); break; case SILInstructionKind::MetatypeInst: assert(RecordKind == SIL_ONE_TYPE && "Layout should be OneType."); - ResultVal = Builder.createMetatype(Loc, - getSILType(MF->getType(TyID), (SILValueCategory)TyCategory)); - break; - -#define ONETYPE_ONEOPERAND_INST(ID) \ - case SILInstructionKind::ID##Inst: \ - assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && \ - "Layout should be OneTypeOneOperand."); \ - ResultVal = Builder.create##ID(Loc, \ - getSILType(MF->getType(TyID), (SILValueCategory)TyCategory), \ - getLocalValue(ValID, \ - getSILType(MF->getType(TyID2), \ - (SILValueCategory)TyCategory2))); \ - break; - ONETYPE_ONEOPERAND_INST(ValueMetatype) - ONETYPE_ONEOPERAND_INST(ExistentialMetatype) - ONETYPE_ONEOPERAND_INST(AllocValueBuffer) - ONETYPE_ONEOPERAND_INST(ProjectValueBuffer) - ONETYPE_ONEOPERAND_INST(ProjectExistentialBox) - ONETYPE_ONEOPERAND_INST(DeallocValueBuffer) + ResultVal = Builder.createMetatype( + Loc, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); + break; + +#define ONETYPE_ONEOPERAND_INST(ID) \ + case SILInstructionKind::ID##Inst: \ + assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && \ + "Layout should be OneTypeOneOperand."); \ + ResultVal = Builder.create##ID( \ + Loc, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn), \ + getLocalValue(ValID, getSILType(MF->getType(TyID2), \ + (SILValueCategory)TyCategory2, Fn))); \ + break; + ONETYPE_ONEOPERAND_INST(ValueMetatype) + ONETYPE_ONEOPERAND_INST(ExistentialMetatype) + ONETYPE_ONEOPERAND_INST(AllocValueBuffer) + ONETYPE_ONEOPERAND_INST(ProjectValueBuffer) + ONETYPE_ONEOPERAND_INST(ProjectExistentialBox) + ONETYPE_ONEOPERAND_INST(DeallocValueBuffer) #undef ONETYPE_ONEOPERAND_INST case SILInstructionKind::DeallocBoxInst: assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && "Layout should be OneTypeOneOperand."); - ResultVal = Builder.createDeallocBox(Loc, - getLocalValue(ValID, - getSILType(MF->getType(TyID2), - (SILValueCategory)TyCategory2))); + ResultVal = Builder.createDeallocBox( + Loc, + getLocalValue(ValID, getSILType(MF->getType(TyID2), + (SILValueCategory)TyCategory2, Fn))); break; case SILInstructionKind::OpenExistentialAddrInst: assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && "Layout should be OneTypeOneOperand."); ResultVal = Builder.createOpenExistentialAddr( - Loc, getLocalValue(ValID, getSILType(MF->getType(TyID2), - (SILValueCategory)TyCategory2)), - getSILType(MF->getType(TyID), (SILValueCategory)TyCategory), + Loc, + getLocalValue(ValID, getSILType(MF->getType(TyID2), + (SILValueCategory)TyCategory2, Fn)), + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn), Attr == 0 ? OpenedExistentialAccess::Immutable : OpenedExistentialAccess::Mutable); break; -#define ONEOPERAND_ONETYPE_INST(ID) \ - case SILInstructionKind::ID##Inst: \ - assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && \ - "Layout should be OneTypeOneOperand."); \ - ResultVal = Builder.create##ID(Loc, \ - getLocalValue(ValID, \ - getSILType(MF->getType(TyID2), \ - (SILValueCategory)TyCategory2)), \ - getSILType(MF->getType(TyID), (SILValueCategory)TyCategory));\ - break; - ONEOPERAND_ONETYPE_INST(OpenExistentialRef) - ONEOPERAND_ONETYPE_INST(OpenExistentialMetatype) - ONEOPERAND_ONETYPE_INST(OpenExistentialBox) - ONEOPERAND_ONETYPE_INST(OpenExistentialValue) - ONEOPERAND_ONETYPE_INST(OpenExistentialBoxValue) - // Conversion instructions. +#define ONEOPERAND_ONETYPE_INST(ID) \ + case SILInstructionKind::ID##Inst: \ + assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && \ + "Layout should be OneTypeOneOperand."); \ + ResultVal = Builder.create##ID( \ + Loc, \ + getLocalValue(ValID, getSILType(MF->getType(TyID2), \ + (SILValueCategory)TyCategory2, Fn)), \ + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); \ + break; + ONEOPERAND_ONETYPE_INST(OpenExistentialRef) + ONEOPERAND_ONETYPE_INST(OpenExistentialMetatype) + ONEOPERAND_ONETYPE_INST(OpenExistentialBox) + ONEOPERAND_ONETYPE_INST(OpenExistentialValue) + ONEOPERAND_ONETYPE_INST(OpenExistentialBoxValue) + // Conversion instructions. #define LOADABLE_REF_STORAGE(Name, ...) \ ONEOPERAND_ONETYPE_INST(RefTo##Name) \ ONEOPERAND_ONETYPE_INST(Name##ToRef) @@ -1190,11 +1195,11 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, case SILInstructionKind::ProjectBoxInst: { assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && "Layout should be OneTypeOneOperand."); - ResultVal = Builder.createProjectBox(Loc, - getLocalValue(ValID, - getSILType(MF->getType(TyID2), - (SILValueCategory)TyCategory2)), - TyID); + ResultVal = Builder.createProjectBox( + Loc, + getLocalValue(ValID, getSILType(MF->getType(TyID2), + (SILValueCategory)TyCategory2, Fn)), + TyID); break; } case SILInstructionKind::ConvertEscapeToNoEscapeInst: { @@ -1204,8 +1209,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, ResultVal = Builder.createConvertEscapeToNoEscape( Loc, getLocalValue(ValID, getSILType(MF->getType(TyID2), - (SILValueCategory)TyCategory2)), - getSILType(MF->getType(TyID), (SILValueCategory)TyCategory), + (SILValueCategory)TyCategory2, Fn)), + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn), isLifetimeGuaranteed); break; } @@ -1216,8 +1221,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, ResultVal = Builder.createConvertFunction( Loc, getLocalValue(ValID, getSILType(MF->getType(TyID2), - (SILValueCategory)TyCategory2)), - getSILType(MF->getType(TyID), (SILValueCategory)TyCategory), + (SILValueCategory)TyCategory2, Fn)), + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn), withoutActuallyEscaping); break; } @@ -1227,29 +1232,30 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, bool isStrict = Attr & 0x01; bool isInvariant = Attr & 0x02; ResultVal = Builder.createPointerToAddress( - Loc, - getLocalValue(ValID, getSILType(MF->getType(TyID2), - (SILValueCategory)TyCategory2)), - getSILType(MF->getType(TyID), (SILValueCategory)TyCategory), - isStrict, isInvariant); + Loc, + getLocalValue(ValID, getSILType(MF->getType(TyID2), + (SILValueCategory)TyCategory2, Fn)), + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn), isStrict, + isInvariant); break; } case SILInstructionKind::DeallocExistentialBoxInst: { assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND && "Layout should be OneTypeOneOperand."); - ResultVal = Builder.createDeallocExistentialBox(Loc, - MF->getType(TyID)->getCanonicalType(), - getLocalValue(ValID, - getSILType(MF->getType(TyID2), - (SILValueCategory)TyCategory2))); + ResultVal = Builder.createDeallocExistentialBox( + Loc, MF->getType(TyID)->getCanonicalType(), + getLocalValue(ValID, getSILType(MF->getType(TyID2), + (SILValueCategory)TyCategory2, Fn))); break; } case SILInstructionKind::RefToBridgeObjectInst: { - auto RefTy = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); + auto RefTy = + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); auto Ref = getLocalValue(ValID, RefTy); - auto BitsTy = getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2); + auto BitsTy = + getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2, Fn); auto Bits = getLocalValue(ValID2, BitsTy); ResultVal = Builder.createRefToBridgeObject(Loc, Ref, Bits); @@ -1257,7 +1263,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, } case SILInstructionKind::ObjCProtocolInst: { - auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); + auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); auto Proto = MF->getDecl(ValID); ResultVal = Builder.createObjCProtocol(Loc, cast(Proto), Ty); break; @@ -1269,15 +1275,15 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, case SILInstructionKind::InitExistentialRefInst: case SILInstructionKind::AllocExistentialBoxInst: { - auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); + auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); auto Ty2 = MF->getType(TyID2); CanType ConcreteTy; if (OpCode != SILInstructionKind::InitExistentialMetatypeInst) ConcreteTy = MF->getType(ConcreteTyID)->getCanonicalType(); SILValue operand; if (OpCode != SILInstructionKind::AllocExistentialBoxInst) - operand = getLocalValue(ValID, - getSILType(Ty2, (SILValueCategory)TyCategory2)); + operand = getLocalValue( + ValID, getSILType(Ty2, (SILValueCategory)TyCategory2, Fn)); SmallVector conformances; while (NumConformances--) { @@ -1325,16 +1331,17 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, unsigned Flags = ListOfValues[0]; bool isObjC = (bool)(Flags & 1); bool canAllocOnStack = (bool)((Flags >> 1) & 1); - SILType ClassTy = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); + SILType ClassTy = + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); SmallVector Counts; SmallVector TailTypes; unsigned i = 1; for (; i + 2 < NumVals; i += 3) { SILType TailType = getSILType(MF->getType(ListOfValues[i]), - SILValueCategory::Object); + SILValueCategory::Object, Fn); TailTypes.push_back(TailType); - SILType CountType = getSILType(MF->getType(ListOfValues[i+2]), - SILValueCategory::Object); + SILType CountType = getSILType(MF->getType(ListOfValues[i + 2]), + SILValueCategory::Object, Fn); SILValue CountVal = getLocalValue(ListOfValues[i+1], CountType); Counts.push_back(CountVal); } @@ -1342,7 +1349,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, assert(i + 2 == NumVals); assert(!canAllocOnStack); SILType MetadataType = getSILType(MF->getType(ListOfValues[i+1]), - SILValueCategory::Object); + SILValueCategory::Object, Fn); SILValue MetadataOp = getLocalValue(ListOfValues[i], MetadataType); ResultVal = Builder.createAllocRefDynamic(Loc, MetadataOp, ClassTy, isObjC, TailTypes, Counts); @@ -1360,8 +1367,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, // is represented with 2 IDs: ValueID and ValueResultNumber. auto Ty = MF->getType(TyID); auto Ty2 = MF->getType(TyID2); - SILType FnTy = getSILType(Ty, SILValueCategory::Object); - SILType SubstFnTy = getSILType(Ty2, SILValueCategory::Object); + SILType FnTy = getSILType(Ty, SILValueCategory::Object, Fn); + SILType SubstFnTy = getSILType(Ty2, SILValueCategory::Object, Fn); SILFunctionConventions substConventions(SubstFnTy.castTo(), Builder.getModule()); assert(substConventions.getNumSILArguments() == ListOfValues.size() @@ -1390,8 +1397,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, // two values in the list are the basic block identifiers. auto Ty = MF->getType(TyID); auto Ty2 = MF->getType(TyID2); - SILType FnTy = getSILType(Ty, SILValueCategory::Object); - SILType SubstFnTy = getSILType(Ty2, SILValueCategory::Object); + SILType FnTy = getSILType(Ty, SILValueCategory::Object, nullptr); + SILType SubstFnTy = getSILType(Ty2, SILValueCategory::Object, Fn); SILBasicBlock *errorBB = getBBForReference(Fn, ListOfValues.back()); ListOfValues = ListOfValues.drop_back(); @@ -1416,14 +1423,15 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, case SILInstructionKind::PartialApplyInst: { auto Ty = MF->getType(TyID); auto Ty2 = MF->getType(TyID2); - SILType FnTy = getSILType(Ty, SILValueCategory::Object); - SILType closureTy = getSILType(Ty2, SILValueCategory::Object); + SILType FnTy = getSILType(Ty, SILValueCategory::Object, nullptr); + SILType closureTy = getSILType(Ty2, SILValueCategory::Object, Fn); SubstitutionMap Substitutions = MF->getSubstitutionMap(NumSubs); auto SubstFnTy = SILType::getPrimitiveObjectType( - FnTy.castTo() - ->substGenericArgs(Builder.getModule(), Substitutions)); + FnTy.castTo()->substGenericArgs( + Builder.getModule(), Substitutions, + Builder.getTypeExpansionContext())); SILFunctionConventions fnConv(SubstFnTy.castTo(), Builder.getModule()); @@ -1448,12 +1456,12 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, } case SILInstructionKind::BuiltinInst: { auto ASTTy = MF->getType(TyID); - auto ResultTy = getSILType(ASTTy, (SILValueCategory)(unsigned)TyID2); + auto ResultTy = getSILType(ASTTy, (SILValueCategory)(unsigned)TyID2, Fn); SmallVector Args; for (unsigned i = 0, e = ListOfValues.size(); i < e; i += 3) { auto ArgASTTy = MF->getType(ListOfValues[i+1]); - auto ArgTy = getSILType(ArgASTTy, - (SILValueCategory)(unsigned)ListOfValues[i+2]); + auto ArgTy = getSILType( + ArgASTTy, (SILValueCategory)(unsigned)ListOfValues[i + 2], Fn); Args.push_back(getLocalValue(ListOfValues[i], ArgTy)); } SubstitutionMap Substitutions = MF->getSubstitutionMap(NumSubs); @@ -1483,10 +1491,12 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, // Find the global variable. SILGlobalVariable *g = getGlobalForReference(Name); assert(g && "Can't deserialize global variable"); - SILType expectedType = (OpCode == SILInstructionKind::GlobalAddrInst ? - g->getLoweredType().getAddressType() : - g->getLoweredType()); - assert(expectedType == getSILType(Ty, (SILValueCategory)TyCategory) && + SILType expectedType = + (OpCode == SILInstructionKind::GlobalAddrInst + ? g->getLoweredTypeInContext(TypeExpansionContext(*Fn)) + .getAddressType() + : g->getLoweredTypeInContext(TypeExpansionContext(*Fn))); + assert(expectedType == getSILType(Ty, (SILValueCategory)TyCategory, Fn) && "Type of a global variable does not match GlobalAddr."); (void)Ty; (void)expectedType; @@ -1499,17 +1509,18 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, } case SILInstructionKind::DeallocStackInst: { auto Ty = MF->getType(TyID); - ResultVal = Builder.createDeallocStack(Loc, - getLocalValue(ValID, - getSILType(Ty, (SILValueCategory)TyCategory))); + ResultVal = Builder.createDeallocStack( + Loc, + getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn))); break; } case SILInstructionKind::DeallocRefInst: { auto Ty = MF->getType(TyID); bool OnStack = (bool)Attr; - ResultVal = Builder.createDeallocRef(Loc, - getLocalValue(ValID, - getSILType(Ty, (SILValueCategory)TyCategory)), OnStack); + ResultVal = Builder.createDeallocRef( + Loc, + getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), + OnStack); break; } case SILInstructionKind::DeallocPartialRefInst: { @@ -1517,81 +1528,87 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, auto Ty2 = MF->getType(TyID2); ResultVal = Builder.createDeallocPartialRef(Loc, getLocalValue(ValID, - getSILType(Ty, (SILValueCategory)TyCategory)), + getSILType(Ty, (SILValueCategory)TyCategory, Fn)), getLocalValue(ValID2, - getSILType(Ty2, (SILValueCategory)TyCategory2))); + getSILType(Ty2, (SILValueCategory)TyCategory2, Fn))); break; } case SILInstructionKind::FunctionRefInst: { auto Ty = MF->getType(TyID); StringRef FuncName = MF->getIdentifierText(ValID); ResultVal = Builder.createFunctionRef( - Loc, getFuncForReference(FuncName, - getSILType(Ty, (SILValueCategory)TyCategory))); + Loc, + getFuncForReference( + FuncName, getSILType(Ty, (SILValueCategory)TyCategory, nullptr))); break; } case SILInstructionKind::DynamicFunctionRefInst: { auto Ty = MF->getType(TyID); StringRef FuncName = MF->getIdentifierText(ValID); ResultVal = Builder.createDynamicFunctionRef( - Loc, getFuncForReference(FuncName, - getSILType(Ty, (SILValueCategory)TyCategory))); + Loc, + getFuncForReference( + FuncName, getSILType(Ty, (SILValueCategory)TyCategory, nullptr))); break; } case SILInstructionKind::PreviousDynamicFunctionRefInst: { auto Ty = MF->getType(TyID); StringRef FuncName = MF->getIdentifierText(ValID); ResultVal = Builder.createPreviousDynamicFunctionRef( - Loc, getFuncForReference(FuncName, - getSILType(Ty, (SILValueCategory)TyCategory))); + Loc, + getFuncForReference( + FuncName, getSILType(Ty, (SILValueCategory)TyCategory, nullptr))); break; } case SILInstructionKind::MarkDependenceInst: { auto Ty = MF->getType(TyID); auto Ty2 = MF->getType(TyID2); - ResultVal = Builder.createMarkDependence(Loc, - getLocalValue(ValID, - getSILType(Ty, (SILValueCategory)TyCategory)), + ResultVal = Builder.createMarkDependence( + Loc, + getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), getLocalValue(ValID2, - getSILType(Ty2, (SILValueCategory)TyCategory2))); + getSILType(Ty2, (SILValueCategory)TyCategory2, Fn))); break; } case SILInstructionKind::CopyBlockWithoutEscapingInst: { auto Ty = MF->getType(TyID); auto Ty2 = MF->getType(TyID2); ResultVal = Builder.createCopyBlockWithoutEscaping( - Loc, getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory)), - getLocalValue(ValID2, getSILType(Ty2, (SILValueCategory)TyCategory2))); + Loc, + getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), + getLocalValue(ValID2, + getSILType(Ty2, (SILValueCategory)TyCategory2, Fn))); break; } case SILInstructionKind::IndexAddrInst: { auto Ty = MF->getType(TyID); auto Ty2 = MF->getType(TyID2); - ResultVal = Builder.createIndexAddr(Loc, - getLocalValue(ValID, - getSILType(Ty, (SILValueCategory)TyCategory)), + ResultVal = Builder.createIndexAddr( + Loc, + getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), getLocalValue(ValID2, - getSILType(Ty2, (SILValueCategory)TyCategory2))); + getSILType(Ty2, (SILValueCategory)TyCategory2, Fn))); break; } case SILInstructionKind::TailAddrInst: { auto Ty = MF->getType(TyID); auto Ty2 = MF->getType(TyID2); auto ResultTy = MF->getType(TyID3); - ResultVal = Builder.createTailAddr(Loc, - getLocalValue(ValID, getSILType(Ty, SILValueCategory::Address)), - getLocalValue(ValID2, getSILType(Ty2, SILValueCategory::Object)), - getSILType(ResultTy, SILValueCategory::Address)); + ResultVal = Builder.createTailAddr( + Loc, + getLocalValue(ValID, getSILType(Ty, SILValueCategory::Address, Fn)), + getLocalValue(ValID2, getSILType(Ty2, SILValueCategory::Object, Fn)), + getSILType(ResultTy, SILValueCategory::Address, Fn)); break; } case SILInstructionKind::IndexRawPointerInst: { auto Ty = MF->getType(TyID); auto Ty2 = MF->getType(TyID2); - ResultVal = Builder.createIndexRawPointer(Loc, - getLocalValue(ValID, - getSILType(Ty, (SILValueCategory)TyCategory)), + ResultVal = Builder.createIndexRawPointer( + Loc, + getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), getLocalValue(ValID2, - getSILType(Ty2, (SILValueCategory)TyCategory2))); + getSILType(Ty2, (SILValueCategory)TyCategory2, Fn))); break; } case SILInstructionKind::IntegerLiteralInst: { @@ -1601,9 +1618,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, bool negate = text[0] == '-'; if (negate) text = text.drop_front(); APInt value = intTy->getWidth().parse(text, 10, negate); - ResultVal = Builder.createIntegerLiteral(Loc, - getSILType(Ty, (SILValueCategory)TyCategory), - value); + ResultVal = Builder.createIntegerLiteral( + Loc, getSILType(Ty, (SILValueCategory)TyCategory, Fn), value); break; } case SILInstructionKind::FloatLiteralInst: { @@ -1617,9 +1633,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, APFloat value(floatTy->getAPFloatSemantics(), bits); - ResultVal = Builder.createFloatLiteral(Loc, - getSILType(Ty, (SILValueCategory)TyCategory), - value); + ResultVal = Builder.createFloatLiteral( + Loc, getSILType(Ty, (SILValueCategory)TyCategory, Fn), value); break; } case SILInstructionKind::StringLiteralInst: { @@ -1631,8 +1646,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, break; } case SILInstructionKind::CondFailInst: { - SILValue Op = getLocalValue(ValID, getSILType(MF->getType(TyID), \ - (SILValueCategory)TyCategory)); + SILValue Op = getLocalValue( + ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); StringRef StringVal = MF->getIdentifierText(ValID2); ResultVal = Builder.createCondFail(Loc, Op, StringVal); break; @@ -1643,39 +1658,41 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, SmallVector OpList; for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3) { auto EltTy = MF->getType(ListOfValues[I]); - OpList.push_back( - getLocalValue(ListOfValues[I+2], - getSILType(EltTy, (SILValueCategory)ListOfValues[I+1]))); + OpList.push_back(getLocalValue( + ListOfValues[I + 2], + getSILType(EltTy, (SILValueCategory)ListOfValues[I + 1], Fn))); } ResultVal = Builder.createMarkFunctionEscape(Loc, OpList); break; } // Checked Conversion instructions. case SILInstructionKind::UnconditionalCheckedCastInst: { - SILValue Val = getLocalValue(ValID, - getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2)); - SILType Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); + SILValue Val = + getLocalValue(ValID, getSILType(MF->getType(TyID2), + (SILValueCategory)TyCategory2, Fn)); + SILType Ty = + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); ResultVal = Builder.createUnconditionalCheckedCast(Loc, Val, Ty); break; } -#define UNARY_INSTRUCTION(ID) \ - case SILInstructionKind::ID##Inst: \ - assert(RecordKind == SIL_ONE_OPERAND && \ - "Layout should be OneOperand."); \ - ResultVal = Builder.create##ID(Loc, getLocalValue(ValID, \ - getSILType(MF->getType(TyID), \ - (SILValueCategory)TyCategory))); \ - break; +#define UNARY_INSTRUCTION(ID) \ + case SILInstructionKind::ID##Inst: \ + assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand."); \ + ResultVal = Builder.create##ID( \ + Loc, \ + getLocalValue(ValID, getSILType(MF->getType(TyID), \ + (SILValueCategory)TyCategory, Fn))); \ + break; -#define REFCOUNTING_INSTRUCTION(ID) \ - case SILInstructionKind::ID##Inst: \ - assert(RecordKind == SIL_ONE_OPERAND && \ - "Layout should be OneOperand."); \ - ResultVal = Builder.create##ID(Loc, getLocalValue(ValID, \ - getSILType(MF->getType(TyID), \ - (SILValueCategory)TyCategory)), \ - (Atomicity)Attr); \ +#define REFCOUNTING_INSTRUCTION(ID) \ + case SILInstructionKind::ID##Inst: \ + assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand."); \ + ResultVal = Builder.create##ID( \ + Loc, \ + getLocalValue(ValID, getSILType(MF->getType(TyID), \ + (SILValueCategory)TyCategory, Fn)), \ + (Atomicity)Attr); \ break; #define UNCHECKED_REF_STORAGE(Name, ...) \ @@ -1723,8 +1740,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, unsigned verificationType = Attr; ResultVal = Builder.createIsEscapingClosure( Loc, - getLocalValue( - ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory)), + getLocalValue(ValID, getSILType(MF->getType(TyID), + (SILValueCategory)TyCategory, Fn)), verificationType); break; } @@ -1732,14 +1749,14 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, case SILInstructionKind::DestructureTupleInst: { assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand."); SILValue Operand = getLocalValue( - ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory)); + ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); ResultVal = Builder.createDestructureTuple(Loc, Operand); break; } case SILInstructionKind::DestructureStructInst: { assert(RecordKind == SIL_ONE_OPERAND && "Layout should be OneOperand."); SILValue Operand = getLocalValue( - ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory)); + ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); ResultVal = Builder.createDestructureStruct(Loc, Operand); break; } @@ -1747,7 +1764,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, auto Ty = MF->getType(TyID); auto ResultKind = ValueOwnershipKind(Attr); ResultVal = Builder.createUncheckedOwnershipConversion( - Loc, getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory)), + Loc, + getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), ResultKind); break; } @@ -1756,35 +1774,35 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, auto Ty = MF->getType(TyID); auto Qualifier = LoadOwnershipQualifier(Attr); ResultVal = Builder.createLoad( - Loc, getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory)), + Loc, + getLocalValue(ValID, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), Qualifier); break; } -#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ - case SILInstructionKind::Load##Name##Inst: { \ - auto Ty = MF->getType(TyID); \ - bool isTake = (Attr > 0); \ - auto Val = getLocalValue(ValID, getSILType(Ty, \ - SILValueCategory(TyCategory)));\ - ResultVal = Builder.createLoad##Name(Loc, Val, IsTake_t(isTake)); \ - break; \ - } \ - case SILInstructionKind::Store##Name##Inst: { \ - auto Ty = MF->getType(TyID); \ - SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory); \ - auto refType = addrType.castTo(); \ +#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ + case SILInstructionKind::Load##Name##Inst: { \ + auto Ty = MF->getType(TyID); \ + bool isTake = (Attr > 0); \ + auto Val = getLocalValue( \ + ValID, getSILType(Ty, SILValueCategory(TyCategory), Fn)); \ + ResultVal = Builder.createLoad##Name(Loc, Val, IsTake_t(isTake)); \ + break; \ + } \ + case SILInstructionKind::Store##Name##Inst: { \ + auto Ty = MF->getType(TyID); \ + SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn); \ + auto refType = addrType.castTo(); \ auto ValType = SILType::getPrimitiveObjectType(refType.getReferentType()); \ - bool isInit = (Attr > 0); \ - ResultVal = Builder.createStore##Name(Loc, \ - getLocalValue(ValID, ValType), \ - getLocalValue(ValID2, addrType), \ - IsInitialization_t(isInit)); \ - break; \ + bool isInit = (Attr > 0); \ + ResultVal = Builder.createStore##Name(Loc, getLocalValue(ValID, ValType), \ + getLocalValue(ValID2, addrType), \ + IsInitialization_t(isInit)); \ + break; \ } #include "swift/AST/ReferenceStorage.def" case SILInstructionKind::MarkUninitializedInst: { - auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); + auto Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); auto Kind = (MarkUninitializedInst::Kind)Attr; auto Val = getLocalValue(ValID, Ty); ResultVal = Builder.createMarkUninitialized(Loc, Val, Kind); @@ -1792,7 +1810,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, } case SILInstructionKind::StoreInst: { auto Ty = MF->getType(TyID); - SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory); + SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn); SILType ValType = addrType.getObjectType(); auto Qualifier = StoreOwnershipQualifier(Attr); ResultVal = Builder.createStore(Loc, getLocalValue(ValID, ValType), @@ -1801,7 +1819,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, } case SILInstructionKind::StoreBorrowInst: { auto Ty = MF->getType(TyID); - SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory); + SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn); SILType ValType = addrType.getObjectType(); ResultVal = Builder.createStoreBorrow(Loc, getLocalValue(ValID, ValType), getLocalValue(ValID2, addrType)); @@ -1809,7 +1827,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, } case SILInstructionKind::BeginAccessInst: { SILValue op = getLocalValue( - ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory)); + ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); auto accessKind = SILAccessKind(Attr & 0x3); auto enforcement = SILAccessEnforcement((Attr >> 2) & 0x3); bool noNestedConflict = (Attr >> 4) & 0x01; @@ -1821,16 +1839,17 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, } case SILInstructionKind::EndAccessInst: { SILValue op = getLocalValue( - ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory)); + ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); bool aborted = Attr & 0x1; ResultVal = Builder.createEndAccess(Loc, op, aborted); break; } case SILInstructionKind::BeginUnpairedAccessInst: { SILValue source = getLocalValue( - ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory)); - SILValue buffer = getLocalValue( - ValID2, getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2)); + ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); + SILValue buffer = + getLocalValue(ValID2, getSILType(MF->getType(TyID2), + (SILValueCategory)TyCategory2, Fn)); auto accessKind = SILAccessKind(Attr & 0x3); auto enforcement = SILAccessEnforcement((Attr >> 2) & 0x03); bool noNestedConflict = (Attr >> 4) & 0x01; @@ -1842,7 +1861,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, } case SILInstructionKind::EndUnpairedAccessInst: { SILValue op = getLocalValue( - ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory)); + ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); bool aborted = Attr & 0x1; auto enforcement = SILAccessEnforcement((Attr >> 1) & 0x03); bool fromBuiltin = (Attr >> 3) & 0x01; @@ -1852,7 +1871,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, } case SILInstructionKind::CopyAddrInst: { auto Ty = MF->getType(TyID); - SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory); + SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn); bool isInit = (Attr & 0x2) > 0; bool isTake = (Attr & 0x1) > 0; ResultVal = Builder.createCopyAddr(Loc, @@ -1864,7 +1883,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, } case SILInstructionKind::AssignInst: { auto Ty = MF->getType(TyID); - SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory); + SILType addrType = getSILType(Ty, (SILValueCategory)TyCategory, Fn); SILType valType = addrType.getObjectType(); auto qualifier = AssignOwnershipQualifier(Attr); ResultVal = Builder.createAssign(Loc, @@ -1880,14 +1899,14 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, "Layout should be OneTypeValues."); auto Ty = MF->getType(TyID); // BoundTy ResultVal = Builder.createBindMemory( - Loc, - getLocalValue(ListOfValues[2], - getSILType(MF->getType(ListOfValues[0]), - (SILValueCategory)ListOfValues[1])), - getLocalValue(ListOfValues[5], - getSILType(MF->getType(ListOfValues[3]), - (SILValueCategory)ListOfValues[4])), - getSILType(Ty, (SILValueCategory)TyCategory)); + Loc, + getLocalValue(ListOfValues[2], + getSILType(MF->getType(ListOfValues[0]), + (SILValueCategory)ListOfValues[1], Fn)), + getLocalValue(ListOfValues[5], + getSILType(MF->getType(ListOfValues[3]), + (SILValueCategory)ListOfValues[4], Fn)), + getSILType(Ty, (SILValueCategory)TyCategory, Fn)); break; } case SILInstructionKind::StructElementAddrInst: @@ -1895,9 +1914,10 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, // Use SILOneValueOneOperandLayout. VarDecl *Field = cast(MF->getDecl(ValID)); auto Ty = MF->getType(TyID); - auto Val = getLocalValue(ValID2, - getSILType(Ty, (SILValueCategory)TyCategory)); - auto ResultTy = Val->getType().getFieldType(Field, SILMod); + auto Val = + getLocalValue(ValID2, getSILType(Ty, (SILValueCategory)TyCategory, Fn)); + auto ResultTy = Val->getType().getFieldType( + Field, SILMod, Builder.getTypeExpansionContext()); if (OpCode == SILInstructionKind::StructElementAddrInst) ResultVal = Builder.createStructElementAddr(Loc, Val, Field, ResultTy.getAddressType()); @@ -1913,35 +1933,33 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, SmallVector OpList; for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3) { auto EltTy = MF->getType(ListOfValues[I]); - OpList.push_back( - getLocalValue(ListOfValues[I+2], - getSILType(EltTy, (SILValueCategory)ListOfValues[I+1]))); + OpList.push_back(getLocalValue( + ListOfValues[I + 2], + getSILType(EltTy, (SILValueCategory)ListOfValues[I + 1], Fn))); } - ResultVal = Builder.createStruct(Loc, - getSILType(Ty, (SILValueCategory)TyCategory), - OpList); + ResultVal = Builder.createStruct( + Loc, getSILType(Ty, (SILValueCategory)TyCategory, Fn), OpList); break; } case SILInstructionKind::TupleElementAddrInst: case SILInstructionKind::TupleExtractInst: { // Use OneTypeOneOperand layout where the field number is stored in TypeID. auto Ty2 = MF->getType(TyID2); - SILType ST = getSILType(Ty2, (SILValueCategory)TyCategory2); + SILType ST = getSILType(Ty2, (SILValueCategory)TyCategory2, Fn); TupleType *TT = ST.castTo(); auto ResultTy = TT->getElement(TyID).getType(); switch (OpCode) { default: llvm_unreachable("Out of sync with parent switch"); case SILInstructionKind::TupleElementAddrInst: - ResultVal = Builder.createTupleElementAddr(Loc, - getLocalValue(ValID, ST), - TyID, getSILType(ResultTy, SILValueCategory::Address)); + ResultVal = Builder.createTupleElementAddr( + Loc, getLocalValue(ValID, ST), TyID, + getSILType(ResultTy, SILValueCategory::Address, Fn)); break; case SILInstructionKind::TupleExtractInst: - ResultVal = Builder.createTupleExtract(Loc, - getLocalValue(ValID,ST), - TyID, - getSILType(ResultTy, SILValueCategory::Object)); + ResultVal = Builder.createTupleExtract( + Loc, getLocalValue(ValID, ST), TyID, + getSILType(ResultTy, SILValueCategory::Object, Fn)); break; } break; @@ -1957,11 +1975,10 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, Type EltTy = TT->getElement(I).getType(); OpList.push_back( getLocalValue(ListOfValues[I], - getSILType(EltTy, SILValueCategory::Object))); + getSILType(EltTy, SILValueCategory::Object, Fn))); } - ResultVal = Builder.createTuple(Loc, - getSILType(Ty, (SILValueCategory)TyCategory), - OpList); + ResultVal = Builder.createTuple( + Loc, getSILType(Ty, (SILValueCategory)TyCategory, Fn), OpList); break; } case SILInstructionKind::ObjectInst: { @@ -1971,9 +1988,9 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, SmallVector Args; for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3) Args.push_back( - getLocalValue(ListOfValues[I+2], - getSILType(MF->getType(ListOfValues[I]), - (SILValueCategory)ListOfValues[I+1]))); + getLocalValue(ListOfValues[I + 2], + getSILType(MF->getType(ListOfValues[I]), + (SILValueCategory)ListOfValues[I + 1], Fn))); ResultVal = Builder.createBranch(Loc, getBBForReference(Fn, TyID), Args); @@ -1985,9 +2002,9 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, // for condition, the list has value for condition, true basic block ID, // false basic block ID, number of true arguments, and a list of true|false // arguments. - SILValue Cond = getLocalValue(ListOfValues[0], - getSILType(MF->getType(TyID), - (SILValueCategory)TyCategory)); + SILValue Cond = getLocalValue( + ListOfValues[0], + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); unsigned NumTrueArgs = ListOfValues[3]; unsigned StartOfTrueArg = 4; @@ -1995,16 +2012,16 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, SmallVector TrueArgs; for (unsigned I = StartOfTrueArg, E = StartOfFalseArg; I < E; I += 3) TrueArgs.push_back( - getLocalValue(ListOfValues[I+2], - getSILType(MF->getType(ListOfValues[I]), - (SILValueCategory)ListOfValues[I+1]))); + getLocalValue(ListOfValues[I + 2], + getSILType(MF->getType(ListOfValues[I]), + (SILValueCategory)ListOfValues[I + 1], Fn))); SmallVector FalseArgs; for (unsigned I = StartOfFalseArg, E = ListOfValues.size(); I < E; I += 3) FalseArgs.push_back( - getLocalValue(ListOfValues[I+2], - getSILType(MF->getType(ListOfValues[I]), - (SILValueCategory)ListOfValues[I+1]))); + getLocalValue(ListOfValues[I + 2], + getSILType(MF->getType(ListOfValues[I]), + (SILValueCategory)ListOfValues[I + 1], Fn))); ResultVal = Builder.createCondBranch(Loc, Cond, getBBForReference(Fn, ListOfValues[1]), TrueArgs, @@ -2017,9 +2034,9 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, // default basic block ID. Use SILOneTypeValuesLayout: the type is // for condition, the list has value for condition, hasDefault, default // basic block ID, a list of (DeclID, BasicBlock ID). - SILValue Cond = getLocalValue(ListOfValues[0], - getSILType(MF->getType(TyID), - (SILValueCategory)TyCategory)); + SILValue Cond = getLocalValue( + ListOfValues[0], + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); SILBasicBlock *DefaultBB = nullptr; if (ListOfValues[1]) @@ -2046,12 +2063,12 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, // basic block ID, a list of (DeclID, BasicBlock ID). SILValue Cond = getLocalValue(ListOfValues[0], getSILType(MF->getType(TyID), - (SILValueCategory)TyCategory)); + (SILValueCategory)TyCategory, Fn)); Type ResultLoweredTy = MF->getType(ListOfValues[1]); SILValueCategory ResultCategory = (SILValueCategory)ListOfValues[2]; - SILType ResultTy = getSILType(ResultLoweredTy, ResultCategory); - + SILType ResultTy = getSILType(ResultLoweredTy, ResultCategory, Fn); + SILValue DefaultVal = nullptr; if (ListOfValues[3]) DefaultVal = getLocalValue(ListOfValues[4], ResultTy); @@ -2076,9 +2093,10 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, // for condition, the list contains value for condition, hasDefault, default // basic block ID, a list of (Value ID, BasicBlock ID). SILType ResultTy = getSILType(MF->getType(TyID), - (SILValueCategory)TyCategory); - SILValue Cond = getLocalValue(ListOfValues[0], getSILType(MF->getType(TyID), - (SILValueCategory)TyCategory)); + (SILValueCategory)TyCategory, Fn); + SILValue Cond = getLocalValue( + ListOfValues[0], + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); SILBasicBlock *DefaultBB = nullptr; if (ListOfValues[1]) @@ -2098,12 +2116,13 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, // for condition, the list has value for condition, result type, // hasDefault, default, // basic block ID, a list of (Value ID, Value ID). - SILValue Cond = getLocalValue(ListOfValues[0], getSILType(MF->getType(TyID), - (SILValueCategory)TyCategory)); + SILValue Cond = getLocalValue( + ListOfValues[0], + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); Type ResultLoweredTy = MF->getType(ListOfValues[1]); SILValueCategory ResultCategory = (SILValueCategory)ListOfValues[2]; - SILType ResultTy = getSILType(ResultLoweredTy, ResultCategory); + SILType ResultTy = getSILType(ResultLoweredTy, ResultCategory, Fn); SILValue DefaultVal = nullptr; if (ListOfValues[3]) @@ -2125,21 +2144,21 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, // (DeclID + hasOperand), and an operand. SILValue Operand; if (Attr) - Operand = getLocalValue(ValID2, - getSILType(MF->getType(TyID2), - (SILValueCategory)TyCategory2)); - ResultVal = Builder.createEnum(Loc, Operand, - cast(MF->getDecl(ValID)), - getSILType(MF->getType(TyID), - (SILValueCategory)TyCategory)); + Operand = + getLocalValue(ValID2, getSILType(MF->getType(TyID2), + (SILValueCategory)TyCategory2, Fn)); + ResultVal = Builder.createEnum( + Loc, Operand, cast(MF->getDecl(ValID)), + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)); break; } case SILInstructionKind::InitEnumDataAddrInst: { // Use SILOneValueOneOperandLayout. EnumElementDecl *Elt = cast(MF->getDecl(ValID)); SILType OperandTy = getSILType(MF->getType(TyID), - (SILValueCategory) TyCategory); - SILType ResultTy = OperandTy.getEnumElementType(Elt, SILMod); + (SILValueCategory) TyCategory, Fn); + SILType ResultTy = OperandTy.getEnumElementType( + Elt, SILMod, Builder.getTypeExpansionContext()); ResultVal = Builder.createInitEnumDataAddr(Loc, getLocalValue(ValID2, OperandTy), Elt, ResultTy); @@ -2148,9 +2167,10 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, case SILInstructionKind::UncheckedEnumDataInst: { // Use SILOneValueOneOperandLayout. EnumElementDecl *Elt = cast(MF->getDecl(ValID)); - SILType OperandTy = getSILType(MF->getType(TyID), - (SILValueCategory) TyCategory); - SILType ResultTy = OperandTy.getEnumElementType(Elt, SILMod); + SILType OperandTy = + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); + SILType ResultTy = OperandTy.getEnumElementType( + Elt, SILMod, Builder.getTypeExpansionContext()); ResultVal = Builder.createUncheckedEnumData(Loc, getLocalValue(ValID2, OperandTy), Elt, ResultTy); @@ -2159,9 +2179,10 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, case SILInstructionKind::UncheckedTakeEnumDataAddrInst: { // Use SILOneValueOneOperandLayout. EnumElementDecl *Elt = cast(MF->getDecl(ValID)); - SILType OperandTy = getSILType(MF->getType(TyID), - (SILValueCategory) TyCategory); - SILType ResultTy = OperandTy.getEnumElementType(Elt, SILMod); + SILType OperandTy = + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); + SILType ResultTy = OperandTy.getEnumElementType( + Elt, SILMod, Builder.getTypeExpansionContext()); ResultVal = Builder.createUncheckedTakeEnumDataAddr(Loc, getLocalValue(ValID2, OperandTy), Elt, ResultTy); @@ -2171,10 +2192,10 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, // Use SILOneValueOneOperandLayout. EnumElementDecl *Elt = cast(MF->getDecl(ValID)); auto Ty = MF->getType(TyID); - ResultVal = Builder.createInjectEnumAddr(Loc, - getLocalValue(ValID2, - getSILType(Ty, (SILValueCategory)TyCategory)), - Elt); + ResultVal = Builder.createInjectEnumAddr( + Loc, + getLocalValue(ValID2, getSILType(Ty, (SILValueCategory)TyCategory, Fn)), + Elt); break; } case SILInstructionKind::RefElementAddrInst: { @@ -2182,8 +2203,9 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, VarDecl *Field = cast(MF->getDecl(ValID)); auto Ty = MF->getType(TyID); auto Val = getLocalValue(ValID2, - getSILType(Ty, (SILValueCategory)TyCategory)); - auto ResultTy = Val->getType().getFieldType(Field, SILMod); + getSILType(Ty, (SILValueCategory)TyCategory, Fn)); + auto ResultTy = Val->getType().getFieldType( + Field, SILMod, Builder.getTypeExpansionContext()); ResultVal = Builder.createRefElementAddr(Loc, Val, Field, ResultTy); break; @@ -2194,10 +2216,10 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, assert(Attr == 0); assert((SILValueCategory)TyCategory == SILValueCategory::Address); ResultVal = Builder.createRefTailAddr( - Loc, - getLocalValue(ValID, getSILType(MF->getType(TyID2), - (SILValueCategory)TyCategory2)), - getSILType(MF->getType(TyID), SILValueCategory::Address)); + Loc, + getLocalValue(ValID, getSILType(MF->getType(TyID2), + (SILValueCategory)TyCategory2, Fn)), + getSILType(MF->getType(TyID), SILValueCategory::Address, Fn)); break; } case SILInstructionKind::ClassMethodInst: @@ -2208,11 +2230,13 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, // type, Attr, SILDeclRef (DeclID, Kind, uncurryLevel), and an operand. unsigned NextValueIndex = 0; SILDeclRef DRef = getSILDeclRef(MF, ListOfValues, NextValueIndex); - SILType Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); + SILType Ty = + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); assert(ListOfValues.size() >= NextValueIndex + 2 && "Out of entries for MethodInst"); - SILType operandTy = getSILType(MF->getType(ListOfValues[NextValueIndex]), - (SILValueCategory)ListOfValues[NextValueIndex+1]); + SILType operandTy = + getSILType(MF->getType(ListOfValues[NextValueIndex]), + (SILValueCategory)ListOfValues[NextValueIndex + 1], Fn); NextValueIndex += 2; switch (OpCode) { @@ -2247,15 +2271,15 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, "Out of entries for MethodInst"); CanType Ty = MF->getType(TyID)->getCanonicalType(); - SILType OperandTy = getSILType(MF->getType(TyID2), - (SILValueCategory)TyCategory2); + SILType OperandTy = + getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2, Fn); auto Conformance = MF->readConformance(SILCursor); // Read the optional opened existential. SILValue ExistentialOperand; if (TyID3) { SILType ExistentialOperandTy = - getSILType(MF->getType(TyID3), (SILValueCategory)TyCategory3); + getSILType(MF->getType(TyID3), (SILValueCategory)TyCategory3, Fn); if (ValID3) ExistentialOperand = getLocalValue(ValID3, ExistentialOperandTy); } @@ -2270,11 +2294,13 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, SILDeclRef DRef = getSILDeclRef(MF, ListOfValues, NextValueIndex); assert(ListOfValues.size() == NextValueIndex + 2 && "Wrong number of entries for DynamicMethodBranchInst"); - ResultVal = Builder.createDynamicMethodBranch(Loc, - getLocalValue(ListOfValues[0], getSILType(MF->getType(TyID), - (SILValueCategory)TyCategory)), - DRef, getBBForReference(Fn, ListOfValues[NextValueIndex]), - getBBForReference(Fn, ListOfValues[NextValueIndex+1])); + ResultVal = Builder.createDynamicMethodBranch( + Loc, + getLocalValue( + ListOfValues[0], + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn)), + DRef, getBBForReference(Fn, ListOfValues[NextValueIndex]), + getBBForReference(Fn, ListOfValues[NextValueIndex + 1])); break; } case SILInstructionKind::CheckedCastBranchInst: { @@ -2284,10 +2310,10 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, "expect 7 numbers for CheckedCastBranchInst"); bool isExact = ListOfValues[0] != 0; SILType opTy = getSILType(MF->getType(ListOfValues[2]), - (SILValueCategory)ListOfValues[3]); + (SILValueCategory)ListOfValues[3], Fn); SILValue op = getLocalValue(ListOfValues[1], opTy); - SILType castTy = getSILType(MF->getType(TyID), - (SILValueCategory)TyCategory); + SILType castTy = + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); auto *successBB = getBBForReference(Fn, ListOfValues[4]); auto *failureBB = getBBForReference(Fn, ListOfValues[5]); @@ -2301,10 +2327,10 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, assert(ListOfValues.size() == 5 && "expect 6 numbers for CheckedCastValueBranchInst"); SILType opTy = getSILType(MF->getType(ListOfValues[1]), - (SILValueCategory)ListOfValues[2]); + (SILValueCategory)ListOfValues[2], Fn); SILValue op = getLocalValue(ListOfValues[0], opTy); SILType castTy = - getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); auto *successBB = getBBForReference(Fn, ListOfValues[3]); auto *failureBB = getBBForReference(Fn, ListOfValues[4]); @@ -2314,8 +2340,9 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, } case SILInstructionKind::UnconditionalCheckedCastValueInst: { SILValue Val = getLocalValue( - ValID, getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2)); - SILType Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); + ValID, getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2, Fn)); + SILType Ty = + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); ResultVal = Builder.createUnconditionalCheckedCastValue(Loc, Val, Ty); break; } @@ -2323,12 +2350,12 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, // ignore attr. CanType sourceType = MF->getType(ListOfValues[0])->getCanonicalType(); SILType srcAddrTy = getSILType(MF->getType(ListOfValues[2]), - (SILValueCategory)ListOfValues[3]); + (SILValueCategory)ListOfValues[3], Fn); SILValue src = getLocalValue(ListOfValues[1], srcAddrTy); CanType targetType = MF->getType(ListOfValues[4])->getCanonicalType(); SILType destAddrTy = - getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); SILValue dest = getLocalValue(ListOfValues[5], destAddrTy); ResultVal = Builder.createUnconditionalCheckedCastAddr(Loc, src, sourceType, @@ -2340,12 +2367,12 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, CanType sourceType = MF->getType(ListOfValues[1])->getCanonicalType(); SILType srcAddrTy = getSILType(MF->getType(ListOfValues[3]), - (SILValueCategory)ListOfValues[4]); + (SILValueCategory)ListOfValues[4], Fn); SILValue src = getLocalValue(ListOfValues[2], srcAddrTy); CanType targetType = MF->getType(ListOfValues[5])->getCanonicalType(); SILType destAddrTy = - getSILType(MF->getType(TyID), (SILValueCategory) TyCategory); + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); SILValue dest = getLocalValue(ListOfValues[6], destAddrTy); auto *successBB = getBBForReference(Fn, ListOfValues[7]); @@ -2360,12 +2387,12 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, CanType sourceType = MF->getType(ListOfValues[0])->getCanonicalType(); // ignore attr. SILType srcAddrTy = getSILType(MF->getType(ListOfValues[2]), - (SILValueCategory)ListOfValues[3]); + (SILValueCategory)ListOfValues[3], Fn); SILValue src = getLocalValue(ListOfValues[1], srcAddrTy); CanType targetType = MF->getType(ListOfValues[4])->getCanonicalType(); SILType destAddrTy = - getSILType(MF->getType(TyID), (SILValueCategory) TyCategory); + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); SILValue dest = getLocalValue(ListOfValues[5], destAddrTy); ResultVal = Builder.createUncheckedRefCastAddr(Loc, src, sourceType, @@ -2375,16 +2402,16 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, case SILInstructionKind::InitBlockStorageHeaderInst: { assert(ListOfValues.size() == 5 && "expected 5 values for InitBlockStorageHeader"); - SILType blockTy - = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); + SILType blockTy = + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); SILType storageTy = getSILType(MF->getType(ListOfValues[1]), - SILValueCategory::Address); + SILValueCategory::Address, Fn); SILValue storage = getLocalValue(ListOfValues[0], storageTy); - SILType invokeTy = getSILType(MF->getType(ListOfValues[3]), - SILValueCategory::Object); + SILType invokeTy = + getSILType(MF->getType(ListOfValues[3]), SILValueCategory::Object, Fn); SILValue invoke = getLocalValue(ListOfValues[2], invokeTy); @@ -2412,8 +2439,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3) { auto valueTy = MF->getType(ListOfValues[I]); auto valueCategory = (SILValueCategory) ListOfValues[I+1]; - yieldedValues.push_back( - getLocalValue(ListOfValues[I+2], getSILType(valueTy, valueCategory))); + yieldedValues.push_back(getLocalValue( + ListOfValues[I + 2], getSILType(valueTy, valueCategory, Fn))); } ResultVal = Builder.createYield(Loc, yieldedValues, resumeBB, unwindBB); @@ -2421,8 +2448,8 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, } case SILInstructionKind::KeyPathInst: { unsigned nextValue = 0; - SILType kpTy - = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory); + SILType kpTy = + getSILType(MF->getType(TyID), (SILValueCategory)TyCategory, Fn); auto rootTy = MF->getType(ListOfValues[nextValue++]); auto valueTy = MF->getType(ListOfValues[nextValue++]); @@ -2465,7 +2492,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB, auto opValue = ListOfValues[nextValue++]; auto opTy = MF->getType(ListOfValues[nextValue++]); auto opCat = (SILValueCategory)ListOfValues[nextValue++]; - operands.push_back(getLocalValue(opValue, getSILType(opTy, opCat))); + operands.push_back(getLocalValue(opValue, getSILType(opTy, opCat, Fn))); } ResultVal = Builder.createKeyPath(Loc, pattern, subMap, operands, kpTy); @@ -2659,7 +2686,7 @@ SILGlobalVariable *SILDeserializer::readGlobalVar(StringRef Name) { SILGlobalVariable *v = SILGlobalVariable::create( SILMod, linkage.getValue(), isSerialized ? IsSerialized : IsNotSerialized, - Name.str(), getSILType(Ty, SILValueCategory::Object), + Name.str(), getSILType(Ty, SILValueCategory::Object, nullptr), None, dID ? cast(MF->getDecl(dID)): nullptr); v->setLet(IsLet); diff --git a/lib/Serialization/DeserializeSIL.h b/lib/Serialization/DeserializeSIL.h index c2790c01e48c2..d94de0c3e178d 100644 --- a/lib/Serialization/DeserializeSIL.h +++ b/lib/Serialization/DeserializeSIL.h @@ -110,6 +110,9 @@ namespace swift { SILValue getLocalValue(serialization::ValueID Id, SILType Type); + SILType getSILType(Type ty, SILValueCategory category, + SILFunction *inContext); + SILFunction *getFuncForReference(StringRef Name, SILType Ty); SILFunction *getFuncForReference(StringRef Name); SILVTable *readVTable(serialization::DeclID); diff --git a/test/IRGen/lazy_opaque_result_type.swift b/test/IRGen/lazy_opaque_result_type.swift index 382ad927ec039..d526623ebff0b 100644 --- a/test/IRGen/lazy_opaque_result_type.swift +++ b/test/IRGen/lazy_opaque_result_type.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -enable-implicit-dynamic -disable-availability-checking -Xllvm -sil-disable-pass=OpaqueArchetypeSpecializer -parse-as-library -module-name=test -O -primary-file %s -emit-ir > %t.ll +// RUN: %target-swift-frontend -enable-implicit-dynamic -disable-availability-checking -parse-as-library -module-name=test -O -primary-file %s -emit-ir > %t.ll // RUN: %FileCheck %s < %t.ll protocol P { } diff --git a/test/IRGen/opaque_result_type_debug.swift b/test/IRGen/opaque_result_type_debug.swift index c4e26d4d201db..a5b0de69c28f4 100644 --- a/test/IRGen/opaque_result_type_debug.swift +++ b/test/IRGen/opaque_result_type_debug.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-frontend -disable-availability-checking -g -emit-ir -enable-anonymous-context-mangled-names %s | %FileCheck %s +// RUN: %target-swift-frontend -enable-library-evolution -disable-availability-checking -g -emit-ir -enable-anonymous-context-mangled-names %s | %FileCheck %s public protocol P {} extension Int: P {} @@ -24,6 +24,7 @@ public var prop: some P { // CHECK: @"$s24opaque_result_type_debug3FooVQrycipQOMQ" = {{.*}}constant{{.*}} @"$s24opaque_result_type_debug3FooVQrycipMXX" public struct Foo { + public init() {} public subscript() -> some P { return 0 } @@ -33,6 +34,7 @@ public struct Foo { @_silgen_name("use") public func use(_: T) +@inlinable public func bar(genericValue: T) { use(genericValue) diff --git a/test/IRGen/opaque_result_type_substitution.swift b/test/IRGen/opaque_result_type_substitution.swift index e5d80c020f113..5fbe15e35217e 100644 --- a/test/IRGen/opaque_result_type_substitution.swift +++ b/test/IRGen/opaque_result_type_substitution.swift @@ -1,21 +1,22 @@ -// RUN: %target-swift-frontend -disable-availability-checking -emit-ir -primary-file %s | %FileCheck %s +// RUN: %target-swift-frontend -enable-library-evolution -disable-availability-checking -emit-ir -primary-file %s | %FileCheck %s -protocol E {} +public protocol E {} -struct Pair : E { +public struct Pair : E { var fst : T var snd : V - init(_ f: T, _ s: V) { + public init(_ f: T, _ s: V) { self.fst = f self.snd = s } - func foobar() -> some E { + public func foobar() -> some E { return self } } +@inlinable public func usePair(_ t: T, _ v: V) { var x = Pair(t, v) let q = x.foobar() diff --git a/test/IRGen/partial_apply.sil b/test/IRGen/partial_apply.sil index 87974e3d3c67c..79c5d9d10e354 100644 --- a/test/IRGen/partial_apply.sil +++ b/test/IRGen/partial_apply.sil @@ -527,7 +527,14 @@ enum GenericEnum2 { sil public_external @generic_indirect_return2 : $@convention(thin) (Int) -> @owned GenericEnum2 // CHECK-LABEL: define{{.*}} @partial_apply_generic_indirect_return2 -// CHECK: insertvalue {{.*}}$s24generic_indirect_return2TA +// CHECK: [[CTX:%.]] = call noalias %swift.refcounted* @swift_allocObject +// CHECK: store {{.*}}$s24generic_indirect_return2TA +// CHECK: store %swift.refcounted* [[CTX]] +// CHECK: [[FN:%.*]] = load i8* +// CHECK: [[CTX2:%.*]] = load %swift.refcounted* +// CHECK: [[R1:%.]] = insertvalue { i8*, %swift.refcounted* } undef, i8* [[FN]], 0 +// CHECK: [[R2:%.*]] = insertvalue { i8*, %swift.refcounted* } [[R1]], %swift.refcounted* [[CTX2]], 1 +// CHECK: ret { i8*, %swift.refcounted* } [[R2]] // CHECK-LABEL: define internal swiftcc void @"$s24generic_indirect_return2TA"(%T13partial_apply12GenericEnum2OySiG* noalias nocapture sret, %swift.refcounted* swiftself) // CHECK: [[CASTED_ADDR:%.*]] = bitcast %T13partial_apply12GenericEnum2OySiG* %0 to %T13partial_apply12GenericEnum2O* diff --git a/test/SIL/Serialization/opaque_return_type_serialize.sil b/test/SIL/Serialization/opaque_return_type_serialize.sil index 2a42e8740a058..37c589eebe77e 100644 --- a/test/SIL/Serialization/opaque_return_type_serialize.sil +++ b/test/SIL/Serialization/opaque_return_type_serialize.sil @@ -1,5 +1,5 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -disable-availability-checking -emit-module -emit-module-path %t/OpaqueReturnTypeExporter.swiftmodule -module-name OpaqueReturnTypeExporter %S/Inputs/OpaqueReturnTypeExporter.swift +// RUN: %target-swift-frontend -disable-availability-checking -enable-library-evolution -emit-module -emit-module-path %t/OpaqueReturnTypeExporter.swiftmodule -module-name OpaqueReturnTypeExporter %S/Inputs/OpaqueReturnTypeExporter.swift // RUN: %target-sil-opt -I %t %s -emit-sib -module-name test -o %t/test.sib // RUN: %target-swift-frontend -disable-availability-checking -I %t -emit-ir %t/test.sib @@ -12,7 +12,7 @@ typealias SomeButt2 = @_opaqueReturnTypeOf("$sSi24OpaqueReturnTypeExporterE8some sil @$s24OpaqueReturnTypeExporter07exportsaB0QryF : $@convention(thin) () -> @out SomeButt sil @$sSi24OpaqueReturnTypeExporterE8someButtQryF : $@convention(thin) (Int) -> @out SomeButt2 -sil @use_opaque_type : $@convention(thin) (Int) -> () { +sil [serialized] @use_opaque_type : $@convention(thin) (Int) -> () { entry(%a : $Int): %f = function_ref @$s24OpaqueReturnTypeExporter07exportsaB0QryF : $@convention(thin) () -> @out SomeButt %x = alloc_stack $SomeButt diff --git a/test/SILGen/opaque_result_type.swift b/test/SILGen/opaque_result_type.swift index 50ae18fc37105..eacbd6204ab5f 100644 --- a/test/SILGen/opaque_result_type.swift +++ b/test/SILGen/opaque_result_type.swift @@ -1,4 +1,8 @@ -// RUN: %target-swift-frontend -disable-availability-checking -emit-silgen %s | %FileCheck %s +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift +// RUN: %target-swift-frontend -I %t -disable-availability-checking -emit-silgen %s | %FileCheck %s + +import resilient_struct protocol P {} protocol Q: AnyObject {} @@ -10,39 +14,138 @@ class C: Q {} // CHECK-LABEL: sil hidden {{.*}}11valueToAddr1xQr func valueToAddr(x: String) -> some P { - // CHECK: [[UNDERLYING:%.*]] = unchecked_addr_cast %0 - // CHECK: [[VALUE_COPY:%.*]] = copy_value %1 - // CHECK: store [[VALUE_COPY]] to [init] [[UNDERLYING]] + // CHECK: bb0([[ARG0:%.*]] : $*String, [[ARG1:%.*]] : @guaranteed $String): + // CHECK: [[VALUE_COPY:%.*]] = copy_value [[ARG1]] + // CHECK: store [[VALUE_COPY]] to [init] [[ARG0]] return x } // CHECK-LABEL: sil hidden {{.*}}10addrToAddr1xQr func addrToAddr(x: AddrOnly) -> some P { - // CHECK: [[UNDERLYING:%.*]] = unchecked_addr_cast %0 - // CHECK: copy_addr %1 to [initialization] [[UNDERLYING]] + // CHECK: bb0([[ARG0:%.*]] : $*AddrOnly, [[ARG1:%.*]] : $*AddrOnly): + // CHECK: copy_addr [[ARG1]] to [initialization] [[ARG0]] return x } // CHECK-LABEL: sil hidden {{.*}}13genericAddrToE01xQr func genericAddrToAddr(x: T) -> some P { - // CHECK: [[UNDERLYING:%.*]] = unchecked_addr_cast %0 - // CHECK: copy_addr %1 to [initialization] [[UNDERLYING]] + // CHECK: bb0([[ARG0:%.*]] : $*T, [[ARG1:%.*]] : $*T): + // CHECK: copy_addr [[ARG1]] to [initialization] [[ARG0]] return x } // CHECK-LABEL: sil hidden {{.*}}12valueToValue1xQr func valueToValue(x: C) -> some Q { - // CHECK: [[VALUE_COPY:%.*]] = copy_value %0 - // CHECK: [[CAST_TO_OPAQUE:%.*]] = unchecked_ref_cast [[VALUE_COPY]] - // CHECK: return [[CAST_TO_OPAQUE]] + // CHECK: bb0([[ARG:%.*]] : @guaranteed $C): + // CHECK: [[VALUE_COPY:%.*]] = copy_value [[ARG]] + // CHECK: return [[VALUE_COPY]] return x } // CHECK-LABEL: sil hidden {{.*}}13reabstraction1xQr func reabstraction(x: @escaping () -> ()) -> some Any { - // CHECK: [[UNDERLYING:%.*]] = unchecked_addr_cast %0 : ${{.*}} to $*@callee_guaranteed () -> @out () - // CHECK: [[VALUE_COPY:%.*]] = copy_value %1 - // CHECK: [[VALUE_REABSTRACT:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[VALUE_COPY]]) - // CHECK: store [[VALUE_REABSTRACT]] to [init] [[UNDERLYING]] + // CHECK: bb0([[ARG0:%.*]] : $*@callee_guaranteed () -> @out (), [[ARG1:%.*]] : @guaranteed $@callee_guaranteed () -> ()): + // CHECK: [[VALUE_COPY:%.*]] = copy_value [[ARG1]] + // CHECK: [[REABSTRACT:%.*]] = function_ref @$sIeg_ytIegr_TR + // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT]]([[VALUE_COPY]]) + // CHECK: store [[THUNK]] to [init] [[ARG0]] return x } + +protocol X { + associatedtype A + func foo() -> A +} + +extension Int : P {} + +extension ResilientInt : P {} + +class K : P {} + +func useClosure2(_ cl: () -> ()) {} + +func useClosure(_ cl: @escaping () -> ()) { + cl() +} + +struct S : X { + + func foo() -> some P { + return returnTrivial() + } + + func returnTrivial() -> some P { + return 1 + } + + func returnClass() -> some P { + return K() + } + + func returnResilient() -> some P { + return ResilientInt(i: 1) + } + + func testCapture() { + var someP = returnTrivial() + var someK = returnClass() + var someR = returnResilient() + useClosure { + someP = self.returnTrivial() + someK = self.returnClass() + someR = self.returnResilient() + } + print(someP) + print(someK) + print(someR) + } + + func testCapture2() { + var someP = returnTrivial() + var someK = returnClass() + var someR = returnResilient() + useClosure2 { + someP = self.returnTrivial() + someK = self.returnClass() + someR = self.returnResilient() + } + print(someP) + print(someK) + print(someR) + } + + func testCapture3() { + let someP = returnTrivial() + let someK = returnClass() + let someR = returnResilient() + useClosure { + print(someP) + print(someK) + print(someR) + } + } + + func testCapture4() { + let someP = returnTrivial() + let someK = returnClass() + let someR = returnResilient() + useClosure { + print(someP) + print(someK) + print(someR) + } + } +} + +extension Optional : P { } + +struct S2 : X { + func foo() -> some P { + let x : Optional = 1 + return x + } + func returnFunctionType() -> () -> A { + return foo + } +} diff --git a/test/SILOptimizer/cast_folding.swift b/test/SILOptimizer/cast_folding.swift index 156b6a2d54780..1394bbc7b10d0 100644 --- a/test/SILOptimizer/cast_folding.swift +++ b/test/SILOptimizer/cast_folding.swift @@ -1072,7 +1072,7 @@ public func testCastToPForOptionalFailure() -> Bool { struct Underlying : P { } -func returnOpaque() -> some P { +public func returnOpaque() -> some P { return Underlying() } @@ -1083,6 +1083,7 @@ func returnOpaque() -> some P { // MANDATORY: [[U:%.*]] = alloc_stack $Underlying // MANDATORY: unconditional_checked_cast_addr @_opaqueReturnTypeOf{{.*}}in [[O]] : $*@_opaqueReturnTypeOf{{.*}}to Underlying in [[U]] : $*Underlying // MANDATORY: load [[U]] : $*Underlying +@inlinable public func testCastOpaqueArchetype() { let o = returnOpaque() as! Underlying } diff --git a/test/SILOptimizer/specialize_opaque_type_archetypes.swift b/test/SILOptimizer/specialize_opaque_type_archetypes.swift index 50dee3429f0c3..48cf8c8799248 100644 --- a/test/SILOptimizer/specialize_opaque_type_archetypes.swift +++ b/test/SILOptimizer/specialize_opaque_type_archetypes.swift @@ -49,12 +49,12 @@ func identity(_ t: T) -> T { // CHECK-LABEL: sil @$s1A10testFooBaryyxAA1PRzlF : $@convention(thin) (@in_guaranteed T) -> () { // CHECK: bb3([[FOOS_INT:%.*]] : $Builtin.Int64): -// CHECK: [[ID:%.*]] = function_ref @$s1A8identityyxxlFs5Int64V_Tg5 : $@convention(thin) (Int64) -> Int64 // CHECK: [[FOO_RES:%.*]] = struct $Int64 ([[FOOS_INT]] : $Builtin.Int64) +// CHECK: [[ID:%.*]] = function_ref @$s1A8identityyxxlFs5Int64V_Tg5 : $@convention(thin) (Int64) -> Int64 // CHECK: [[ID_RES:%.*]] = apply [[ID]]([[FOO_RES]]) : $@convention(thin) (Int64) -> Int64 // CHECK: [[USEP:%.*]] = function_ref @$s1A4usePyyxAA1PRzlFs5Int64V_Tg5 : $@convention(thin) (Int64) -> () -// CHECK: %27 = apply [[USEP]]([[ID_RES]]) : $@convention(thin) (Int64) -> () -// CHECK: %29 = apply [[USEP]]([[FOO_RES]]) : $@convention(thin) (Int64) -> () +// CHECK: apply [[USEP]]([[ID_RES]]) : $@convention(thin) (Int64) -> () +// CHECK: apply [[USEP]]([[FOO_RES]]) : $@convention(thin) (Int64) -> () public func testFooBar(_ t : T) { let x = foo(getInt()) @@ -99,9 +99,8 @@ public func returnC() -> some CP { } // CHECK-LABEL: sil @$s1A4useCyyF -// CHECK: [[INT:%.*]] = struct $Int64 ( -// CHECK: // function_ref specialized useP(_:) // CHECK: [[FUN:%.*]] = function_ref @$s1A4usePyyxAA1PRzlFs5Int64V_Tg5 +// CHECK: [[INT:%.*]] = struct $Int64 ( // CHECK: = apply [[FUN]]([[INT]]) public func useC() { let c = returnC() @@ -166,6 +165,7 @@ struct Container2 { } class Container3 { + @inline(__always) init(member : S.T) { self.member = member } @@ -229,8 +229,8 @@ func nonResilient() -> some ExternalP2 { // CHECK-LABEL: sil @$s1A019usePairResilientNonC0yyF : $@convention(thin) () -> () // CHECK: alloc_stack $Pair: P3 { // Don't assert. // CHECK-LABEL: sil {{.*}} @$s1A7AdapterVyxGAA2P3A2aEP3foo2ATQzyFTW // CHECK: [[F:%.*]] = function_ref @$s1A7AdapterV3fooQryF -// CHECK: apply [[F]]<τ_0_0>(%0, %1) : $@convention(method) <τ_0_0 where τ_0_0 : P3> (@in_guaranteed Adapter<τ_0_0>) -> @out @_opaqueReturnTypeOf("$s1A7AdapterV3fooQryF", 0) +// CHECK: apply [[F]]<τ_0_0>(%0, %1) : $@convention(method) <τ_0_0 where τ_0_0 : P3> (@in_guaranteed Adapter<τ_0_0>) -> extension P3 { public func foo() -> some P3 { return Adapter(inner: self) @@ -270,9 +270,8 @@ extension P3 { // CHECK-LABEL: sil @$s1A21useExternalResilient2yyF : $@convention(thin) () -> () // CHECK: [[RES:%.*]] = alloc_stack $Int64 -// CHECK: [[FUN:%.*]] = function_ref @$s9External226inlinableExternalResilientQryF : $@convention(thin) () -> @out @_opaqueReturnTypeOf("$s9External226inlinableExternalResilientQryF", 0) -// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*Int64 to $*@_opaqueReturnTypeOf("$s9External226inlinableExternalResilientQryF", 0) -// CHECK: apply [[FUN]]([[RES2]]) +// CHECK: [[FUN:%.*]] = function_ref @$s9External226inlinableExternalResilientQryF : $@convention(thin) () -> @out Int64 +// CHECK: apply [[FUN]]([[RES]]) // CHECK: return public func useExternalResilient2() { let e = inlinableExternalResilient() @@ -282,9 +281,8 @@ public func useExternalResilient2() { // In this case we should only 'peel' one layer of opaque archetypes. // CHECK-LABEL: sil @$s1A21useExternalResilient3yyF // CHECK: [[RES:%.*]] = alloc_stack $@_opaqueReturnTypeOf("$s9External217externalResilientQryF", 0) -// CHECK: [[FUN:%.*]] = function_ref @$s9External3031inlinableExternalResilientCallsD0QryF : $@convention(thin) () -> @out @_opaqueReturnTypeOf("$s9External3031inlinableExternalResilientCallsD0QryF", 0) -// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*@_opaqueReturnTypeOf("$s9External217externalResilientQryF", 0){{.*}}to $*@_opaqueReturnTypeOf("$s9External3031inlinableExternalResilientCallsD0QryF", 0) -// CHECK: apply [[FUN]]([[RES2]]) +// CHECK: [[FUN:%.*]] = function_ref @$s9External3031inlinableExternalResilientCallsD0QryF : $@convention(thin) () -> @out @_opaqueReturnTypeOf("$s9External217externalResilientQryF", 0) +// CHECK: apply [[FUN]]([[RES]]) public func useExternalResilient3() { let e = inlinableExternalResilientCallsResilient() useP(e.myValue3()) @@ -293,9 +291,8 @@ public func useExternalResilient3() { // Check that we can look throught two layers of inlinable resilient functions. // CHECK-LABEL: sil @$s1A21useExternalResilient4yyF // CHECK: [[RES:%.*]] = alloc_stack $Int64 -// CHECK: [[FUN:%.*]] = function_ref @$s9External3040inlinableExternalResilientCallsInlinablecD0QryF : $@convention(thin) () -> @out @_opaqueReturnTypeOf("$s9External3040inlinableExternalResilientCallsInlinablecD0QryF", 0) -// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*Int64 to $*@_opaqueReturnTypeOf("$s9External3040inlinableExternalResilientCallsInlinablecD0QryF", 0) -// CHECK: apply [[FUN]]([[RES2]]) +// CHECK: [[FUN:%.*]] = function_ref @$s9External3040inlinableExternalResilientCallsInlinablecD0QryF : $@convention(thin) () -> @out Int64 +// CHECK: apply [[FUN]]([[RES]]) public func useExternalResilient4() { let e = inlinableExternalResilientCallsInlinableExternalResilient() useP(e.myValue3()) @@ -306,8 +303,7 @@ public func useExternalResilient4() { // CHECK: [[CONTAINER:%.*]] = apply [[CONTAINER_INIT_FUN]] // CHECK: [[RES:%.*]] = alloc_stack $Int64 // CHECK: [[COMPUTED_PROP:%.*]] = function_ref @$s8External0A9ContainerV16computedPropertyQrvg -// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*Int64 to $*@_opaqueReturnTypeOf("$s8External0A9ContainerV16computedPropertyQrvp", 0) -// CHECK: apply [[COMPUTED_PROP]]([[RES2]], [[CONTAINER]]) +// CHECK: apply [[COMPUTED_PROP]]([[RES]], [[CONTAINER]]) // CHECK: [[MYVALUE:%.*]] = function_ref @$ss5Int64V8ExternalE8myValue2AByF : $@convention(method) (Int64) -> Int64 // CHECK: apply [[MYVALUE]] public func testStoredProperty() { @@ -329,8 +325,7 @@ public func testResilientProperty() { // CHECK: [[CONTAINER:%.*]] = alloc_stack $ResilientContainer // CHECK: [[RES:%.*]] = alloc_stack $Int64 // CHECK: [[FUN:%.*]] = function_ref @$s9External218ResilientContainerV18inlineablePropertyQrvg -// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*Int64 to $*@_opaqueReturnTypeOf("$s9External218ResilientContainerV18inlineablePropertyQrvp", 0) -// CHECK: apply [[FUN]]([[RES2]], [[CONTAINER]]) +// CHECK: apply [[FUN]]([[RES]], [[CONTAINER]]) public func testResilientInlinableProperty() { let r = ResilientContainer() useP(r.inlineableProperty.myValue3()) @@ -340,8 +335,7 @@ public func testResilientInlinableProperty() { // CHECK: [[CONTAINER:%.*]] = alloc_stack $ResilientContainer // CHECK: [[RES:%.*]] = alloc_stack $Int64 // CHECK: [[FUN:%.*]] = function_ref @$s9External218ResilientContainerV19inlineableProperty2Qrvg -// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*Int64 to $*@_opaqueReturnTypeOf("$s9External218ResilientContainerV19inlineableProperty2Qrvp", 0) -// CHECK: apply [[FUN]]([[RES2]], [[CONTAINER]]) +// CHECK: apply [[FUN]]([[RES]], [[CONTAINER]]) public func testResilientInlinableProperty3() { let r = ResilientContainer() useP(r.inlineableProperty2.myValue3()) @@ -362,8 +356,7 @@ public func testResilientProperty2() { // CHECK: [[CONTAINER:%.*]] = alloc_stack $ResilientContainer2 // CHECK: [[RES:%.*]] = alloc_stack $@_opaqueReturnTypeOf("$s9External218ResilientContainerV16computedPropertyQrvp", 0) // CHECK: [[FUN:%.*]] = function_ref @$s9External319ResilientContainer2V18inlineablePropertyQrvg -// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*@_opaqueReturnTypeOf("$s9External218ResilientContainerV16computedPropertyQrvp", 0){{.*}}to $*@_opaqueReturnTypeOf("$s9External319ResilientContainer2V18inlineablePropertyQrvp", 0) -// CHECK: apply [[FUN]]([[RES2]], [[CONTAINER]]) +// CHECK: apply [[FUN]]([[RES]], [[CONTAINER]]) public func testResilientInlinableProperty2() { let r = ResilientContainer2() useP(r.inlineableProperty.myValue3()) @@ -373,8 +366,7 @@ public func testResilientInlinableProperty2() { // CHECK: [[CONTAINTER:%.*]] = alloc_stack $ResilientContainer2 // CHECK: [[RES:%.*]] = alloc_stack $Int64 // CHECK: [[FUN:%.*]] = function_ref @$s9External319ResilientContainer2V023inlineablePropertyCallsB10InlineableQrvg -// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*Int64 to $*@_opaqueReturnTypeOf("$s9External319ResilientContainer2V023inlineablePropertyCallsB10InlineableQrvp", 0) -// CHECK: apply [[FUN]]([[RES2]], [[CONTAINTER]]) +// CHECK: apply [[FUN]]([[RES]], [[CONTAINTER]]) public func testResilientInlinablePropertyCallsResilientInlinable() { let r = ResilientContainer2() useP(r.inlineablePropertyCallsResilientInlineable.myValue3()) @@ -420,9 +412,9 @@ func testIt(cl: (Int64) throws -> T) { // CHECK-LABEL: sil shared [noinline] @$s1A16testPartialApplyyyxAA2P4RzlFAA2PAV_Tg5 // CHECK: [[PA:%.*]] = alloc_stack $PA // CHECK: store %0 to [[PA]] : $*PA -// CHECK: [[F:%.*]] = function_ref @$s1A2PAVAA2P4A2aDP3fooy2ATQzs5Int64VFTW : $@convention(witness_method: P4) (Int64, @in_guaranteed PA) -> @out @_opaqueReturnTypeOf("$s1A2PAV3fooyQrs5Int64VF", 0) -// CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]]([[PA]]) : $@convention(witness_method: P4) (Int64, @in_guaranteed PA) -> @out @_opaqueReturnTypeOf("$s1A2PAV3fooyQrs5Int64VF", 0) -// CHECK: convert_function [[C]] : $@callee_guaranteed (Int64) -> @out @_opaqueReturnTypeOf("$s1A2PAV3fooyQrs5Int64VF", {{.*}} to $@callee_guaranteed (Int64) -> (@out Int64, @error Error) +// CHECK: [[F:%.*]] = function_ref @$s1A2PAVAA2P4A2aDP3fooy2ATQzs5Int64VFTW : $@convention(witness_method: P4) (Int64, @in_guaranteed PA) -> @out Int64 +// CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]]([[PA]]) : $@convention(witness_method: P4) (Int64, @in_guaranteed PA) -> @out Int64 +// CHECK: convert_function [[C]] : $@callee_guaranteed (Int64) -> @out Int64 to $@callee_guaranteed (Int64) -> (@out Int64, @error Error) @inline(never) func testPartialApply(_ t: T) { let fun = t.foo @@ -563,7 +555,7 @@ public func rdar56410009_inlinedInner() { // CHECK-LABEL: sil @$s1A25rdar56410009_inlinedOuteryyF public func rdar56410009_inlinedOuter() { // CHECK: [[INLINABLE_EXTERNAL_RESILIENT_WRAPPER:%.+]] = function_ref @$s9External233inlinableExternalResilientWrapperyQrxAA0C2P2RzlFAA08externalD0QryFQOyQo__Tg5 - // CHECK: = apply [[INLINABLE_EXTERNAL_RESILIENT_WRAPPER]]({{%.+}}, {{%.+}}) : $@convention(thin) (@in_guaranteed @_opaqueReturnTypeOf("$s9External217externalResilientQryF", 0) 🦸) -> @out @_opaqueReturnTypeOf("$s9External233inlinableExternalResilientWrapperyQrxAA0C2P2RzlF", 0) 🦸<@_opaqueReturnTypeOf("$s9External217externalResilientQryF", 0) 🦸> + // CHECK: = apply [[INLINABLE_EXTERNAL_RESILIENT_WRAPPER]]({{%.+}}, {{%.+}}) : $@convention(thin) (@in_guaranteed @_opaqueReturnTypeOf("$s9External217externalResilientQryF", 0) 🦸) -> @out WrapperP2<@_opaqueReturnTypeOf("$s9External217externalResilientQryF" _ = inlinableExternalResilientWrapper(externalResilient()) } // CHECK: end sil function '$s1A25rdar56410009_inlinedOuteryyF' @@ -582,6 +574,6 @@ public func rdar56410009_inlinedOuter() { // CHECK-LABEL: sil @$s1A24rdar56410009_inlinedBothyyF public func rdar56410009_inlinedBoth() { // CHECK: [[INLINABLE_EXTERNAL_RESILIENT_WRAPPER:%.+]] = function_ref @$s9External233inlinableExternalResilientWrapperyQrxAA0C2P2RzlFs5Int64V_Tg5 - // CHECK: = apply [[INLINABLE_EXTERNAL_RESILIENT_WRAPPER]]({{%.+}}, {{%.+}}) : $@convention(thin) (Int64) -> @out @_opaqueReturnTypeOf("$s9External233inlinableExternalResilientWrapperyQrxAA0C2P2RzlF", 0) 🦸 + // CHECK: = apply [[INLINABLE_EXTERNAL_RESILIENT_WRAPPER]]({{%.+}}, {{%.+}}) : $@convention(thin) (Int64) -> @out WrapperP2 _ = inlinableExternalResilientWrapper(inlinableExternalResilient()) } // CHECK: end sil function '$s1A24rdar56410009_inlinedBothyyF' diff --git a/test/SILOptimizer/specialize_opaque_type_archetypes_multifile.swift b/test/SILOptimizer/specialize_opaque_type_archetypes_multifile.swift index 9e70b35bb6466..f858632090311 100644 --- a/test/SILOptimizer/specialize_opaque_type_archetypes_multifile.swift +++ b/test/SILOptimizer/specialize_opaque_type_archetypes_multifile.swift @@ -1,5 +1,5 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -O -Xllvm -enable-opaque-archetype-specializer -disable-availability-checking -primary-file %s %S/Inputs/specialize_opaque_type_archetypes_multifile_A.swift -emit-sil | %FileCheck %s +// RUN: %target-swift-frontend -O -disable-availability-checking -primary-file %s %S/Inputs/specialize_opaque_type_archetypes_multifile_A.swift -emit-sil | %FileCheck %s protocol P {}