| //===--- GenMeta.h - Swift IR generation for metadata -----------*- 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 provides the private interface to the metadata emission code. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_IRGEN_GENMETA_H |
| #define SWIFT_IRGEN_GENMETA_H |
| |
| #include "swift/AST/Types.h" |
| #include <utility> |
| |
| namespace llvm { |
| template <class T> class ArrayRef; |
| class Constant; |
| class Function; |
| class GlobalVariable; |
| class Value; |
| } |
| |
| namespace swift { |
| class AbstractFunctionDecl; |
| class FuncDecl; |
| enum class ResilienceExpansion : unsigned; |
| struct SILDeclRef; |
| class SILType; |
| class VarDecl; |
| enum class SpecialProtocol : uint8_t; |
| |
| namespace irgen { |
| class Callee; |
| class ConstantReference; |
| class Explosion; |
| class FieldTypeInfo; |
| class FunctionPointer; |
| class GenericTypeRequirements; |
| class IRGenFunction; |
| class IRGenModule; |
| class Size; |
| class StructLayout; |
| enum class SymbolReferenceKind : unsigned char; |
| struct ClassLayout; |
| |
| /// Is the given class known to have Swift-compatible metadata? |
| bool hasKnownSwiftMetadata(IRGenModule &IGM, ClassDecl *theClass); |
| |
| inline bool isKnownNotTaggedPointer(IRGenModule &IGM, ClassDecl *theClass) { |
| // For now, assume any class type defined in Clang might be tagged. |
| return hasKnownSwiftMetadata(IGM, theClass); |
| } |
| |
| /// Is the given class-like type known to have Swift-compatible |
| /// metadata? |
| bool hasKnownSwiftMetadata(IRGenModule &IGM, CanType theType); |
| |
| /// Emit the body of a lazy cache access function. |
| void emitLazyCacheAccessFunction(IRGenModule &IGM, |
| llvm::Function *accessor, |
| llvm::GlobalVariable *cacheVariable, |
| const llvm::function_ref<llvm::Value *(IRGenFunction &IGF)> &getValue); |
| |
| /// Emit a declaration reference to a metatype object. |
| void emitMetatypeRef(IRGenFunction &IGF, CanMetatypeType type, |
| Explosion &explosion); |
| |
| /// Emit a reference to a compile-time constant piece of type metadata, or |
| /// return a null pointer if the type's metadata cannot be represented by a |
| /// constant. |
| ConstantReference tryEmitConstantTypeMetadataRef(IRGenModule &IGM, |
| CanType type, |
| SymbolReferenceKind refKind); |
| |
| /// Get the type as it exists in Swift's runtime type system, removing any |
| /// erased generic parameters. |
| CanType getRuntimeReifiedType(IRGenModule &IGM, CanType type); |
| |
| /// Emit a reference to a compile-time constant piece of heap metadata, or |
| /// return a null pointer if the type's heap metadata cannot be represented |
| /// by a constant. |
| llvm::Constant *tryEmitConstantHeapMetadataRef(IRGenModule &IGM, |
| CanType type, |
| bool allowUninitialized); |
| |
| enum class MetadataValueType { ObjCClass, TypeMetadata }; |
| |
| /// Emit a reference to the heap metadata for a class. |
| /// |
| /// \returns a value of type ObjCClassPtrTy or TypeMetadataPtrTy, |
| /// depending on desiredType |
| llvm::Value *emitClassHeapMetadataRef(IRGenFunction &IGF, CanType type, |
| MetadataValueType desiredType, |
| bool allowUninitialized = false); |
| |
| /// Emit a reference to the (initialized) ObjC heap metadata for a class. |
| /// |
| /// \returns a value of type ObjCClassPtrTy |
| llvm::Value *emitObjCHeapMetadataRef(IRGenFunction &IGF, ClassDecl *theClass, |
| bool allowUninitialized = false); |
| |
| /// Given a class metadata reference, produce the appropriate heap |
| /// metadata reference for it. |
| llvm::Value *emitClassHeapMetadataRefForMetatype(IRGenFunction &IGF, |
| llvm::Value *metatype, |
| CanType type); |
| |
| /// Emit the metadata associated with the given class declaration. |
| void emitClassMetadata(IRGenModule &IGM, ClassDecl *theClass, |
| const StructLayout &layout, |
| const ClassLayout &fieldLayout); |
| |
| /// Emit the constant initializer of the type metadata candidate for |
| /// the given foreign class declaration. |
| llvm::Constant *emitForeignTypeMetadataInitializer(IRGenModule &IGM, |
| CanType type, |
| Size &addressPointOffset); |
| |
| /// Emit the metadata associated with the given struct declaration. |
| void emitStructMetadata(IRGenModule &IGM, StructDecl *theStruct); |
| |
| /// Emit the metadata associated with the given enum declaration. |
| void emitEnumMetadata(IRGenModule &IGM, EnumDecl *theEnum); |
| |
| /// Get what will be the index into the generic type argument array at the end |
| /// of a nominal type's metadata. |
| int32_t getIndexOfGenericArgument(IRGenModule &IGM, |
| NominalTypeDecl *decl, |
| ArchetypeType *archetype); |
| |
| /// Given a reference to nominal type metadata of the given type, |
| /// derive a reference to the parent type metadata. There must be a |
| /// parent type. |
| llvm::Value *emitParentMetadataRef(IRGenFunction &IGF, |
| NominalTypeDecl *theDecl, |
| llvm::Value *metadata); |
| |
| /// Given a reference to nominal type metadata of the given type, |
| /// derive a reference to the type metadata stored in the nth |
| /// requirement slot. The type must have generic arguments. |
| llvm::Value *emitArgumentMetadataRef(IRGenFunction &IGF, |
| NominalTypeDecl *theDecl, |
| const GenericTypeRequirements &reqts, |
| unsigned reqtIndex, |
| llvm::Value *metadata); |
| |
| /// Given a reference to nominal type metadata of the given type, |
| /// derive a reference to a protocol witness table stored in the nth |
| /// requirement slot. The type must have generic arguments. |
| llvm::Value *emitArgumentWitnessTableRef(IRGenFunction &IGF, |
| NominalTypeDecl *theDecl, |
| const GenericTypeRequirements &reqts, |
| unsigned reqtIndex, |
| llvm::Value *metadata); |
| |
| /// Get the offset of a field in the class type metadata. |
| Size getClassFieldOffset(IRGenModule &IGM, |
| ClassDecl *theClass, |
| VarDecl *field); |
| |
| /// Given a reference to class type metadata of the given type, |
| /// decide the offset to the given field. This assumes that the |
| /// offset is stored in the metadata, i.e. its offset is potentially |
| /// dependent on generic arguments. The result is a ptrdiff_t. |
| llvm::Value *emitClassFieldOffset(IRGenFunction &IGF, |
| ClassDecl *theClass, |
| VarDecl *field, |
| llvm::Value *metadata); |
| |
| /// Given a metatype value, read its instance type. |
| llvm::Value *emitMetatypeInstanceType(IRGenFunction &IGF, |
| llvm::Value *metatypeMetadata); |
| |
| /// Load the fragile instance size and alignment mask from a reference to |
| /// class type metadata of the given type. |
| std::pair<llvm::Value *, llvm::Value *> |
| emitClassFragileInstanceSizeAndAlignMask(IRGenFunction &IGF, |
| ClassDecl *theClass, |
| llvm::Value *metadata); |
| |
| /// Load the instance size and alignment mask from a reference to |
| /// class type metadata of the given type. |
| std::pair<llvm::Value *, llvm::Value *> |
| emitClassResilientInstanceSizeAndAlignMask(IRGenFunction &IGF, |
| ClassDecl *theClass, |
| llvm::Value *metadata); |
| |
| /// Given an opaque class instance pointer, produce the type |
| /// metadata reference as a %type*. |
| llvm::Value *emitDynamicTypeOfOpaqueHeapObject(IRGenFunction &IGF, |
| llvm::Value *object); |
| |
| /// Given a heap-object instance, with some heap-object type, |
| /// produce a reference to its type metadata. |
| llvm::Value *emitDynamicTypeOfHeapObject(IRGenFunction &IGF, |
| llvm::Value *object, |
| SILType objectType, |
| bool suppressCast = false); |
| |
| /// Given a non-tagged object pointer, load a pointer to its class object. |
| llvm::Value *emitLoadOfObjCHeapMetadataRef(IRGenFunction &IGF, |
| llvm::Value *object); |
| |
| /// Given a heap-object instance, with some heap-object type, produce a |
| /// reference to its heap metadata by dynamically asking the runtime for it. |
| llvm::Value *emitHeapMetadataRefForUnknownHeapObject(IRGenFunction &IGF, |
| llvm::Value *object); |
| |
| /// Given a heap-object instance, with some heap-object type, |
| /// produce a reference to its heap metadata. |
| llvm::Value *emitHeapMetadataRefForHeapObject(IRGenFunction &IGF, |
| llvm::Value *object, |
| CanType objectType, |
| bool suppressCast = false); |
| |
| /// Given a heap-object instance, with some heap-object type, |
| /// produce a reference to its heap metadata. |
| llvm::Value *emitHeapMetadataRefForHeapObject(IRGenFunction &IGF, |
| llvm::Value *object, |
| SILType objectType, |
| bool suppressCast = false); |
| |
| /// 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, |
| CanSILFunctionType methodType, |
| bool useSuperVTable); |
| |
| /// Get the offset of the given class method within the class's vtables. |
| unsigned getVirtualMethodIndex(IRGenModule &IGM, SILDeclRef method); |
| |
| /// \brief Load a reference to the protocol descriptor for the given protocol. |
| /// |
| /// For Swift protocols, this is a constant reference to the protocol |
| /// descriptor symbol. |
| /// For ObjC protocols, descriptors are uniqued at runtime by the ObjC |
| /// runtime. We need to load the unique reference from a global variable fixed up at |
| /// startup. |
| llvm::Value *emitProtocolDescriptorRef(IRGenFunction &IGF, |
| ProtocolDecl *protocol); |
| |
| llvm::Value *emitObjCMetadataRefForMetadata(IRGenFunction &IGF, |
| llvm::Value *classPtr); |
| |
| /// Emit the field type accessor for a nominal type's metadata. This function |
| /// lazily generates the metadata for the types of all of the nominal type's |
| /// fields for reflection purposes. |
| void emitFieldTypeAccessor(IRGenModule &IGM, |
| NominalTypeDecl *type, |
| llvm::Function *fn, |
| ArrayRef<FieldTypeInfo> fieldTypes); |
| |
| /// Adjustment indices for the address points of various metadata. |
| /// Size is in words. |
| namespace MetadataAdjustmentIndex { |
| enum : unsigned { |
| // Class metadata has two words of head-allocated data: the destructor |
| // and the value witness table. |
| Class = 2, |
| |
| // Struct and enum metadata have one word of head-allocated data: |
| // the value witness table. |
| ValueType = 1, |
| |
| // Other metadata objects have no head allocation. |
| None = 0, |
| }; |
| } |
| |
| enum class MetadataAccessStrategy { |
| /// There is a unique public accessor function for the given type metadata. |
| PublicUniqueAccessor, |
| |
| /// There is a unique hidden accessor function for the given type metadata. |
| HiddenUniqueAccessor, |
| |
| /// There is a unique private accessor function for the given type metadata. |
| PrivateAccessor, |
| |
| /// There is no unique accessor function for the given type metadata, but |
| /// one should be made automatically. |
| NonUniqueAccessor |
| }; |
| |
| /// Is it basically trivial to access the given metadata? If so, we don't |
| /// need a cache variable in its accessor. |
| bool isTypeMetadataAccessTrivial(IRGenModule &IGM, CanType type); |
| |
| /// Determine how the given type metadata should be accessed. |
| MetadataAccessStrategy getTypeMetadataAccessStrategy(CanType type); |
| |
| /// Return the address of a function that will return type metadata |
| /// for the given non-dependent type. |
| llvm::Function *getOrCreateTypeMetadataAccessFunction(IRGenModule &IGM, |
| CanType type); |
| |
| /// Get the runtime identifier for a special protocol, if any. |
| SpecialProtocol getSpecialProtocolID(ProtocolDecl *P); |
| |
| } // end namespace irgen |
| } // end namespace swift |
| |
| #endif |