| //===--- GenType.h - Auxiliary Interface for Type IR Generation -*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 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 private interface used for turning AST types |
| // into LLVM IR types. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_IRGEN_GENTYPE_H |
| #define SWIFT_IRGEN_GENTYPE_H |
| |
| #include "llvm/ADT/DenseMap.h" |
| #include "llvm/ADT/FoldingSet.h" |
| #include "llvm/ADT/ilist.h" |
| #include "llvm/ADT/ilist_node.h" |
| #include "llvm/ADT/StringMap.h" |
| #include "IRGenModule.h" |
| #include "IRGenFunction.h" |
| #include "LegacyLayoutFormat.h" |
| |
| namespace swift { |
| class GenericSignatureBuilder; |
| class ArchetypeType; |
| class CanType; |
| class ClassDecl; |
| class AnyFunctionType; |
| class InOutType; |
| class MetatypeType; |
| class ModuleType; |
| class NominalTypeDecl; |
| class EnumDecl; |
| class ProtocolCompositionType; |
| class ProtocolDecl; |
| class ProtocolType; |
| class SILFunctionType; |
| class StructDecl; |
| class TupleType; |
| class TypeBase; |
| class Type; |
| class EnumDecl; |
| class UnownedStorageType; |
| class WeakStorageType; |
| enum IsTake_t : bool; |
| |
| namespace irgen { |
| class Alignment; |
| class ProtocolInfo; |
| class Size; |
| class FixedTypeInfo; |
| class LoadableTypeInfo; |
| class TypeInfo; |
| |
| /// The helper class for generating types. |
| class TypeConverter { |
| public: |
| enum class Mode : unsigned { |
| /// Normal type lowering mode where resilient types are opaque. |
| Normal, |
| |
| /// Used for computing backward deployment class layouts, where we emit a |
| /// static class metadata layout using known sizes and alignments of any |
| /// resiliently-typed fields from a previous Swift version. On newer Swift |
| /// versions we use a runtime mechanism to re-initialize the class metadata |
| /// in-place with the current known layout. |
| Legacy, |
| |
| /// A temporary hack for lldb where all resilient types are transparent and |
| /// treated like fixed-size (but still lowered in a way that matches the |
| /// runtime layout produced for resilient types, which is important for some |
| /// types like enums where enabling resilience changes the layout). |
| CompletelyFragile |
| |
| /// When adding or removing fields, remember to update NumLoweringModes below. |
| }; |
| |
| static unsigned const NumLoweringModes = 3; |
| |
| IRGenModule &IGM; |
| private: |
| Mode LoweringMode = Mode::Normal; |
| |
| llvm::DenseMap<ProtocolDecl*, std::unique_ptr<const ProtocolInfo>> Protocols; |
| const TypeInfo *FirstType; |
| |
| const LoadableTypeInfo *NativeObjectTI = nullptr; |
| const LoadableTypeInfo *UnknownObjectTI = nullptr; |
| const LoadableTypeInfo *BridgeObjectTI = nullptr; |
| const LoadableTypeInfo *RawPointerTI = nullptr; |
| const LoadableTypeInfo *WitnessTablePtrTI = nullptr; |
| const TypeInfo *TypeMetadataPtrTI = nullptr; |
| const TypeInfo *ObjCClassPtrTI = nullptr; |
| const LoadableTypeInfo *EmptyTI = nullptr; |
| const LoadableTypeInfo *IntegerLiteralTI = nullptr; |
| |
| const TypeInfo *AccessibleResilientStructTI = nullptr; |
| const TypeInfo *InaccessibleResilientStructTI = nullptr; |
| |
| llvm::DenseMap<std::pair<unsigned, unsigned>, const LoadableTypeInfo *> |
| OpaqueStorageTypes; |
| |
| const LoadableTypeInfo *NonFixedBoxTI = nullptr; |
| const LoadableTypeInfo *EmptyBoxTI = nullptr; |
| llvm::DenseMap<std::pair<unsigned, unsigned>, const LoadableTypeInfo *> |
| PODBoxTI; |
| const LoadableTypeInfo *SwiftRetainablePointerBoxTI = nullptr, |
| *UnknownObjectRetainablePointerBoxTI = nullptr; |
| |
| llvm::StringMap<YAMLTypeInfoNode> LegacyTypeInfos; |
| llvm::DenseMap<NominalTypeDecl *, std::string> DeclMangledNames; |
| |
| const LoadableTypeInfo *createPrimitive(llvm::Type *T, |
| Size size, Alignment align); |
| const LoadableTypeInfo *createPrimitiveForAlignedPointer(llvm::PointerType *T, |
| Size size, Alignment align, |
| Alignment pointerAlignment); |
| const FixedTypeInfo *createImmovable(llvm::Type *T, |
| Size size, Alignment align); |
| |
| void addForwardDecl(TypeBase *key); |
| |
| const TypeInfo *convertType(CanType T); |
| const TypeInfo *convertAnyNominalType(CanType T, NominalTypeDecl *D); |
| const TypeInfo *convertTupleType(TupleType *T); |
| const TypeInfo *convertClassType(CanType type, ClassDecl *D); |
| const TypeInfo *convertEnumType(TypeBase *key, CanType type, EnumDecl *D); |
| const TypeInfo *convertStructType(TypeBase *key, CanType type, StructDecl *D); |
| const TypeInfo *convertFunctionType(SILFunctionType *T); |
| const TypeInfo *convertBlockStorageType(SILBlockStorageType *T); |
| const TypeInfo *convertBoxType(SILBoxType *T); |
| const TypeInfo *convertArchetypeType(ArchetypeType *T); |
| const TypeInfo *convertInOutType(InOutType *T); |
| const TypeInfo *convertExistentialMetatypeType(ExistentialMetatypeType *T); |
| const TypeInfo *convertMetatypeType(MetatypeType *T); |
| const TypeInfo *convertModuleType(ModuleType *T); |
| const TypeInfo *convertProtocolType(ProtocolType *T); |
| const TypeInfo *convertProtocolCompositionType(ProtocolCompositionType *T); |
| const LoadableTypeInfo *convertBuiltinNativeObject(); |
| const LoadableTypeInfo *convertBuiltinUnknownObject(); |
| const LoadableTypeInfo *convertBuiltinBridgeObject(); |
| const TypeInfo *convertResilientStruct(IsABIAccessible_t abiAccessible); |
| #define REF_STORAGE(Name, ...) \ |
| const TypeInfo *convert##Name##StorageType(Name##StorageType *T); |
| #include "swift/AST/ReferenceStorage.def" |
| |
| public: |
| TypeConverter(IRGenModule &IGM); |
| ~TypeConverter(); |
| |
| Mode getLoweringMode() const { |
| return LoweringMode; |
| } |
| |
| const TypeInfo *getTypeEntry(CanType type); |
| const TypeInfo &getCompleteTypeInfo(CanType type); |
| const LoadableTypeInfo &getNativeObjectTypeInfo(); |
| const LoadableTypeInfo &getUnknownObjectTypeInfo(); |
| const LoadableTypeInfo &getBridgeObjectTypeInfo(); |
| const LoadableTypeInfo &getRawPointerTypeInfo(); |
| const TypeInfo &getTypeMetadataPtrTypeInfo(); |
| const TypeInfo &getObjCClassPtrTypeInfo(); |
| const LoadableTypeInfo &getWitnessTablePtrTypeInfo(); |
| const LoadableTypeInfo &getEmptyTypeInfo(); |
| const LoadableTypeInfo &getIntegerLiteralTypeInfo(); |
| const TypeInfo &getResilientStructTypeInfo(IsABIAccessible_t abiAccessible); |
| const ProtocolInfo &getProtocolInfo(ProtocolDecl *P, ProtocolInfoKind kind); |
| const LoadableTypeInfo &getOpaqueStorageTypeInfo(Size storageSize, |
| Alignment storageAlign); |
| const TypeInfo &getMetatypeTypeInfo(MetatypeRepresentation representation); |
| |
| #define REF_STORAGE(Name, ...) \ |
| const TypeInfo *create##Name##StorageType(llvm::Type *valueType, \ |
| ReferenceCounting style, \ |
| bool isOptional); |
| #include "swift/AST/ReferenceStorage.def" |
| |
| /// Enter a generic context for lowering the parameters of a generic function |
| /// type. |
| void pushGenericContext(CanGenericSignature signature); |
| |
| /// Exit a generic context. |
| void popGenericContext(CanGenericSignature signature); |
| |
| /// Retrieve the generic environment for the current generic context. |
| /// |
| /// Fails if there is no generic context. |
| GenericEnvironment *getGenericEnvironment(); |
| |
| private: |
| friend class LoweringModeScope; |
| |
| void setLoweringMode(Mode mode) { |
| LoweringMode = mode; |
| } |
| |
| /// Read a YAML legacy type layout dump. Returns false on success, true on |
| /// error. |
| bool readLegacyTypeInfo(StringRef path); |
| |
| Optional<YAMLTypeInfoNode> getLegacyTypeInfo(NominalTypeDecl *decl) const; |
| |
| // Debugging aids. |
| #ifndef NDEBUG |
| bool isExemplarArchetype(ArchetypeType *arch) const; |
| #endif |
| |
| ArchetypeType *getExemplarArchetype(ArchetypeType *t); |
| CanType getExemplarType(CanType t); |
| |
| class Types_t { |
| llvm::DenseMap<TypeBase *, const TypeInfo *> IndependentCache[NumLoweringModes]; |
| llvm::DenseMap<TypeBase *, const TypeInfo *> DependentCache[NumLoweringModes]; |
| |
| public: |
| llvm::DenseMap<TypeBase *, const TypeInfo *> &getCacheFor(bool isDependent, |
| Mode mode); |
| }; |
| Types_t Types; |
| }; |
| |
| /// An RAII interface for entering a generic context for type conversion in |
| /// a scope. |
| class GenericContextScope { |
| TypeConverter &TC; |
| CanGenericSignature sig; |
| public: |
| GenericContextScope(TypeConverter &TC, CanGenericSignature sig) |
| : TC(TC), sig(sig) |
| { |
| TC.pushGenericContext(sig); |
| } |
| |
| GenericContextScope(IRGenModule &IGM, CanGenericSignature sig) |
| : GenericContextScope(IGM.Types, sig) |
| {} |
| |
| ~GenericContextScope() { |
| TC.popGenericContext(sig); |
| } |
| }; |
| |
| /// An RAII interface for forcing types to be lowered bypassing resilience. |
| class LoweringModeScope { |
| TypeConverter::Mode OldLoweringMode; |
| TypeConverter &TC; |
| public: |
| LoweringModeScope(TypeConverter &TC, TypeConverter::Mode LoweringMode) |
| : TC(TC) { |
| OldLoweringMode = TC.getLoweringMode(); |
| TC.setLoweringMode(LoweringMode); |
| } |
| |
| LoweringModeScope(IRGenModule &IGM, TypeConverter::Mode LoweringMode) |
| : LoweringModeScope(IGM.Types, LoweringMode) {} |
| |
| ~LoweringModeScope() { |
| TC.setLoweringMode(OldLoweringMode); |
| } |
| }; |
| |
| /// If a type is visibly a singleton aggregate (a tuple with one element, a |
| /// struct with one field, or an enum with a single payload case), return the |
| /// type of its field, which it is guaranteed to have identical layout to. |
| SILType getSingletonAggregateFieldType(IRGenModule &IGM, |
| SILType t, |
| ResilienceExpansion expansion); |
| |
| /// An IRGenFunction interface for generating type layout verifiers. |
| class IRGenTypeVerifierFunction : public IRGenFunction { |
| private: |
| llvm::Constant *VerifierFn; |
| |
| struct VerifierArgumentBuffers { |
| Address runtimeBuf, staticBuf; |
| }; |
| llvm::DenseMap<llvm::Type *, VerifierArgumentBuffers> VerifierArgBufs; |
| |
| public: |
| IRGenTypeVerifierFunction(IRGenModule &IGM, llvm::Function *f); |
| |
| void emit(ArrayRef<CanType> typesToVerify); |
| |
| /// Call a runtime function that verifies that the two LLVM values are |
| /// equivalent, logging a detailed error if they differ. |
| void verifyValues(llvm::Value *typeMetadata, |
| llvm::Value *runtimeValue, |
| llvm::Value *compilerValue, |
| const llvm::Twine &description); |
| |
| /// Call a runtime function that verifies that the contents of the two |
| /// memory buffers are equivalent, logging a detailed error if they differ. |
| void verifyBuffers(llvm::Value *typeMetadata, |
| Address runtimeValue, |
| Address compilerValue, |
| Size size, |
| const llvm::Twine &description); |
| }; |
| |
| } // end namespace irgen |
| } // end namespace swift |
| |
| #endif |