//===--- Linking.h - Named declarations and how to link to them -*- 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 // //===----------------------------------------------------------------------===// #ifndef SWIFT_IRGEN_LINKING_H #define SWIFT_IRGEN_LINKING_H #include "swift/ABI/Coro.h" #include "swift/AST/Decl.h" #include "swift/AST/Module.h" #include "swift/AST/ProtocolAssociations.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/RequirementSignature.h" #include "swift/AST/Types.h" #include "swift/IRGen/ValueWitness.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILGlobalVariable.h" #include "swift/SIL/SILModule.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/IR/GlobalObject.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Module.h" namespace llvm { class Triple; } namespace swift { class AvailabilityRange; namespace irgen { class IRGenModule; class Alignment; /// Determine if the triple uses the DLL storage. bool useDllStorage(const llvm::Triple &triple); class UniversalLinkageInfo { public: bool IsELFObject; bool IsMSVCEnvironment; bool UseDLLStorage; bool Internalize; /// True iff are multiple llvm modules. bool HasMultipleIGMs; /// When this is true, the linkage for forward-declared private symbols will /// be promoted to public external. Used by the LLDB expression evaluator. bool ForcePublicDecls; explicit UniversalLinkageInfo(IRGenModule &IGM); UniversalLinkageInfo(const llvm::Triple &triple, bool hasMultipleIGMs, bool forcePublicDecls, bool isStaticLibrary); /// In case of multiple llvm modules (in multi-threaded compilation) all /// private decls must be visible from other files. bool shouldAllPrivateDeclsBeVisibleFromOtherFiles() const { return HasMultipleIGMs; } /// In case of multiple llvm modules, private lazy protocol /// witness table accessors could be emitted by two different IGMs during /// IRGen into different object files and the linker would complain about /// duplicate symbols. bool needLinkerToMergeDuplicateSymbols() const { return HasMultipleIGMs; } /// This is used by the LLDB expression evaluator since an expression's /// llvm::Module may need to access private symbols defined in the /// expression's context. This flag ensures that private accessors are /// forward-declared as public external in the expression's module. bool forcePublicDecls() const { return ForcePublicDecls; } }; /// Selector for type metadata symbol kinds. enum class TypeMetadataAddress { AddressPoint, FullMetadata, }; inline bool isEmbedded(CanType t) { return t->getASTContext().LangOpts.hasFeature(Feature::Embedded); } // Metadata is not generated and not allowed to be referenced in Embedded Swift, // expect for classes (both generic and non-generic), dynamic self, and // class-bound existentials. inline bool isMetadataAllowedInEmbedded(CanType t) { if (isa(t) || isa(t) || isa(t)) { return true; } if (auto existentialTy = dyn_cast(t)) { if (existentialTy->requiresClass()) return true; } if (auto archeTy = dyn_cast(t)) { if (archeTy->requiresClass()) return true; } return false; } inline bool isEmbedded(Decl *d) { return d->getASTContext().LangOpts.hasFeature(Feature::Embedded); } inline bool isEmbedded(const ProtocolConformance *c) { return c->getType()->getASTContext().LangOpts.hasFeature(Feature::Embedded); } /// A link entity is some sort of named declaration, combined with all /// the information necessary to distinguish specific implementations /// of the declaration from each other. /// /// For example, functions may be uncurried at different levels, each of /// which potentially creates a different top-level function. class LinkEntity { /// ValueDecl*, SILFunction*, or TypeBase*, depending on Kind. void *Pointer; /// ProtocolConformance* or SILDifferentiabilityWitness*, depending on Kind. void *SecondaryPointer; /// A hand-rolled bitfield with the following layout: unsigned Data; enum : unsigned { KindShift = 0, KindMask = 0xFF, // This field appears in the ValueWitness kind. ValueWitnessShift = 8, ValueWitnessMask = 0xFF00, // This field appears in the TypeMetadata and ObjCResilientClassStub kinds. MetadataAddressShift = 8, MetadataAddressMask = 0x0300, // This field appears in the TypeMetadata kind. ForceSharedShift = 12, ForceSharedMask = 0x1000, // This field appears in associated type access functions. AssociatedTypeIndexShift = 8, AssociatedTypeIndexMask = ~KindMask, // This field appears in associated conformance access functions. AssociatedConformanceIndexShift = 8, AssociatedConformanceIndexMask = ~KindMask, // This field appears in SILFunction. IsDynamicallyReplaceableImplShift = 8, IsDynamicallyReplaceableImplMask = ~KindMask, // These fields appear in ExtendedExistentialTypeShape. ExtendedExistentialIsUniqueShift = 8, ExtendedExistentialIsUniqueMask = 0x100, ExtendedExistentialIsSharedShift = 9, ExtendedExistentialIsSharedMask = 0x200, // Used by CoroAllocator. 2 bits. CoroAllocatorKindShift = 8, CoroAllocatorKindMask = 0x300, }; #define LINKENTITY_SET_FIELD(field, value) (value << field##Shift) #define LINKENTITY_GET_FIELD(value, field) ((value & field##Mask) >> field##Shift) enum class Kind { /// A method dispatch thunk. The pointer is a FuncDecl* inside a protocol /// or a class. DispatchThunk, /// A derivative method dispatch thunk. The pointer is a /// AbstractFunctionDecl* inside a protocol or a class, and the secondary /// pointer is an AutoDiffDerivativeFunctionIdentifier*. DispatchThunkDerivative, /// A method dispatch thunk for an initializing constructor. The pointer /// is a ConstructorDecl* inside a class. DispatchThunkInitializer, /// A method dispatch thunk for an allocating constructor. The pointer is /// a ConstructorDecl* inside a protocol or a class. DispatchThunkAllocator, /// An async function pointer for a method dispatch thunk. The pointer is /// a FuncDecl* inside a protocol or a class. DispatchThunkAsyncFunctionPointer, /// An async function pointer for a method dispatch thunk for an /// initializing constructor. The pointer is a ConstructorDecl* inside a /// class. DispatchThunkInitializerAsyncFunctionPointer, /// An async function pointer for a method dispatch thunk for an allocating /// constructor. The pointer is a ConstructorDecl* inside a protocol or /// a class. DispatchThunkAllocatorAsyncFunctionPointer, /// An async function pointer for a distributed thunk. /// The pointer is a FuncDecl* inside an actor (class). DistributedThunkAsyncFunctionPointer, /// A method descriptor. The pointer is a FuncDecl* inside a protocol /// or a class. MethodDescriptor, /// A derivative method descriptor. The pointer is a AbstractFunctionDecl* /// inside a protocol or a class, and the secondary pointer is an /// AutoDiffDerivativeFunctionIdentifier*. MethodDescriptorDerivative, /// A method descriptor for an initializing constructor. The pointer /// is a ConstructorDecl* inside a class. MethodDescriptorInitializer, /// A method descriptor for an allocating constructor. The pointer is a /// ConstructorDecl* inside a protocol or a class. MethodDescriptorAllocator, /// A method lookup function for a class. The pointer is a ClassDecl*. MethodLookupFunction, /// A resilient enum tag index. The pointer is a EnumElementDecl*. EnumCase, /// A field offset. The pointer is a VarDecl*. FieldOffset, /// An Objective-C class reference. The pointer is a ClassDecl*. ObjCClass, /// An Objective-C class reference reference. The pointer is a ClassDecl*. ObjCClassRef, /// An Objective-C metaclass reference. The pointer is a ClassDecl*. ObjCMetaclass, /// A swift metaclass-stub reference. The pointer is a ClassDecl*. SwiftMetaclassStub, /// A callback used by newer Objective-C runtimes to initialize class /// metadata for classes where getClassMetadataStrategy() is equal to /// ClassMetadataStrategy::Update or ::FixedOrUpdate. ObjCMetadataUpdateFunction, /// A stub that we emit to allow Clang-generated code to statically refer /// to Swift classes with resiliently-sized metadata, since the metadata /// is not statically-emitted. Used when getClassMetadataStrategy() is /// equal to ClassMetadataStrategy::Resilient. ObjCResilientClassStub, /// A class metadata base offset global variable. This stores the offset /// of the immediate members of a class (generic parameters, field offsets, /// vtable offsets) in the class's metadata. The immediate members begin /// immediately after the superclass members end. /// /// The pointer is a ClassDecl*. ClassMetadataBaseOffset, /// The property descriptor for a public property or subscript. /// The pointer is an AbstractStorageDecl*. PropertyDescriptor, /// The nominal type descriptor for a nominal type. /// The pointer is a NominalTypeDecl*. NominalTypeDescriptor, /// The nominal type descriptor runtime record for a nominal type. /// The pointer is a NominalTypeDecl*. NominalTypeDescriptorRecord, /// The descriptor for an opaque type. /// The pointer is an OpaqueTypeDecl*. OpaqueTypeDescriptor, /// The runtime record for a descriptor for an opaque type. /// The pointer is an OpaqueTypeDecl*. OpaqueTypeDescriptorRecord, /// The descriptor accessor for an opaque type used for dynamic functions. /// The pointer is an OpaqueTypeDecl*. OpaqueTypeDescriptorAccessor, /// The descriptor accessor implementation for an opaque type used for /// dynamic functions. /// The pointer is an OpaqueTypeDecl*. OpaqueTypeDescriptorAccessorImpl, /// The descriptor accessor key of dynamic replacements for an opaque type. /// The pointer is an OpaqueTypeDecl*. OpaqueTypeDescriptorAccessorKey, /// The descriptor accessor variable of dynamic replacements for an opaque /// type. /// The pointer is an OpaqueTypeDecl*. OpaqueTypeDescriptorAccessorVar, /// The metadata pattern for a generic nominal type. /// The pointer is a NominalTypeDecl*. TypeMetadataPattern, /// The instantiation cache for a generic nominal type. /// The pointer is a NominalTypeDecl*. TypeMetadataInstantiationCache, /// The instantiation function for a generic nominal type. /// The pointer is a NominalTypeDecl*. TypeMetadataInstantiationFunction, /// The in-place initialization cache for a generic nominal type. /// The pointer is a NominalTypeDecl*. TypeMetadataSingletonInitializationCache, /// The completion function for a generic or resilient nominal type. /// The pointer is a NominalTypeDecl*. TypeMetadataCompletionFunction, /// The module descriptor for a module. /// The pointer is a ModuleDecl*. ModuleDescriptor, /// The protocol descriptor for a protocol type. /// The pointer is a ProtocolDecl*. ProtocolDescriptor, /// The protocol descriptor runtime record for a protocol type. /// The pointer is a ProtocolDecl*. ProtocolDescriptorRecord, /// The alias referring to the base of the requirements within the /// protocol descriptor, which is used to determine the offset of a /// particular requirement in the witness table. /// The pointer is a ProtocolDecl*. ProtocolRequirementsBaseDescriptor, /// An descriptor for an associated type within a protocol, which /// will alias the TargetProtocolRequirement descripting this /// particular associated type. /// The pointer is an AssociatedTypeDecl*. AssociatedTypeDescriptor, /// An descriptor for an associated conformance within a protocol, which /// will alias the TargetProtocolRequirement descripting this /// particular associated conformance. /// The pointer is a ProtocolDecl*; the index of the associated conformance /// is stored in the data. AssociatedConformanceDescriptor, /// A default accessor for an associated conformance of a protocol. /// The pointer is a ProtocolDecl*; the index of the associated conformance /// is stored in the data. DefaultAssociatedConformanceAccessor, /// An descriptor for an base conformance within a protocol, which /// will alias the TargetProtocolRequirement descripting this /// particular base conformance. /// The pointer is a ProtocolDecl*; the index of the base conformance /// is stored in the data. BaseConformanceDescriptor, /// A global function pointer for dynamically replaceable functions. /// The pointer is a AbstractFunctionDecl*. DynamicallyReplaceableFunctionVariableAST, /// The pointer is a AbstractFunctionDecl*. DynamicallyReplaceableFunctionKeyAST, /// The original implementation of a dynamically replaceable function. /// The pointer is a AbstractFunctionDecl*. DynamicallyReplaceableFunctionImpl, /// The once token used by cacheCanonicalSpecializedMetadata, by way of /// swift_getCanonicalSpecializedMetadata and /// swift_getCanonicalPrespecializedGenericMetadata, to /// ensure that canonical prespecialized generic records are only added to /// the metadata cache once. CanonicalPrespecializedGenericTypeCachingOnceToken, /// The function used to access distributed methods and accessors. DistributedAccessor, /// The same as AsyncFunctionPointer but with a different stored value, for /// use by TBDGen. /// The pointer is an AbstractFunctionDecl*. AsyncFunctionPointerAST, /// The same as CoroFunctionPointer but with a different stored value, for /// use by TBDGen. /// The pointer is an AbstractFunctionDecl*. CoroFunctionPointerAST, /// The pointer is a SILFunction*. DynamicallyReplaceableFunctionKey, /// A SIL function. The pointer is a SILFunction*. SILFunction, /// The descriptor for an extension. /// The pointer is an ExtensionDecl*. ExtensionDescriptor, /// The descriptor for a runtime-anonymous context. /// The pointer is the DeclContext* of a child of the context that should /// be considered private. AnonymousDescriptor, /// A SIL global variable. The pointer is a SILGlobalVariable*. SILGlobalVariable, /// An outlined read-only global object. The pointer is a /// SILGlobalVariable*. ReadOnlyGlobalObject, // These next few are protocol-conformance kinds. /// A direct protocol witness table. The secondary pointer is a /// RootProtocolConformance*. ProtocolWitnessTable, /// A protocol witness table pattern. The secondary pointer is a /// ProtocolConformance*. ProtocolWitnessTablePattern, /// The instantiation function for a generic protocol witness table. /// The secondary pointer is a ProtocolConformance*. GenericProtocolWitnessTableInstantiationFunction, /// A function which returns the witness table for a protocol-constrained /// associated type of a protocol. The secondary pointer is a /// ProtocolConformance*. The index of the associated conformance /// requirement is stored in the data. AssociatedTypeWitnessTableAccessFunction, /// A reflection metadata descriptor for the associated type witnesses of a /// nominal type in a protocol conformance. ReflectionAssociatedTypeDescriptor, /// The protocol conformance descriptor for a conformance. /// The pointer is a RootProtocolConformance*. ProtocolConformanceDescriptor, /// The protocol conformance descriptor runtime record for a conformance. /// The pointer is a RootProtocolConformance*. ProtocolConformanceDescriptorRecord, // These are both type kinds and protocol-conformance kinds. // TYPE KINDS: BEGIN {{ /// A lazy protocol witness accessor function. The pointer is a /// canonical TypeBase*, and the secondary pointer is a /// ProtocolConformance*. ProtocolWitnessTableLazyAccessFunction, /// A lazy protocol witness cache variable. The pointer is a /// canonical TypeBase*, and the secondary pointer is a /// ProtocolConformance*. ProtocolWitnessTableLazyCacheVariable, /// A SIL differentiability witness. The pointer is a /// SILDifferentiabilityWitness*. DifferentiabilityWitness, // Everything following this is a type kind. /// A value witness for a type. /// The pointer is a canonical TypeBase*. ValueWitness, /// The value witness table for a type. /// The pointer is a canonical TypeBase*. ValueWitnessTable, /// The metadata or metadata template for a type. /// The pointer is a canonical TypeBase*. TypeMetadata, /// An access function for type metadata. /// The pointer is a canonical TypeBase*. TypeMetadataAccessFunction, /// A lazy cache variable for type metadata. /// The pointer is a canonical TypeBase*. TypeMetadataLazyCacheVariable, /// A lazy cache variable for fetching type metadata from a mangled name. /// The pointer is a canonical TypeBase*. TypeMetadataDemanglingCacheVariable, /// A reflection metadata descriptor for a builtin or imported type. ReflectionBuiltinDescriptor, /// A reflection metadata descriptor for a struct, enum, class or protocol. ReflectionFieldDescriptor, /// A coroutine continuation prototype function. CoroutineContinuationPrototype, /// A reference to a metaclass-stub for a statically specialized generic /// class. /// The pointer is a canonical TypeBase*. CanonicalSpecializedGenericSwiftMetaclassStub, /// An access function for prespecialized type metadata. /// The pointer is a canonical TypeBase*. CanonicalSpecializedGenericTypeMetadataAccessFunction, /// Metadata for a specialized generic type which cannot be statically /// guaranteed to be canonical and so must be canonicalized. /// The pointer is a canonical TypeBase*. NoncanonicalSpecializedGenericTypeMetadata, /// A cache variable for noncanonical specialized type metadata, to be /// passed to swift_getCanonicalSpecializedMetadata. /// The pointer is a canonical TypeBase*. NoncanonicalSpecializedGenericTypeMetadataCacheVariable, /// Extended existential type shape. /// Pointer is the (generalized) existential type. /// SecondaryPointer is the GenericSignatureImpl*. ExtendedExistentialTypeShape, // TYPE KINDS: END }} /// A global function pointer for dynamically replaceable functions. DynamicallyReplaceableFunctionVariable, /// Provides the data required to invoke an async function using the async /// calling convention in the form of the size of the context to allocate /// and the relative address of the function to call with that allocated /// context. /// The pointer is a SILFunction*. AsyncFunctionPointer, /// The thunk provided for partially applying a function at some values /// which are captured. /// The pointer is an llvm::Function*. PartialApplyForwarder, /// An async function pointer to a partial apply forwarder. /// The pointer is the llvm::Function* for a partial apply forwarder. PartialApplyForwarderAsyncFunctionPointer, /// An async function pointer to a function which is known to exist whose /// name is known. /// The pointer is a const char* of the name. KnownAsyncFunctionPointer, /// An async function pointer for a distributed accessor (method or /// property). /// The pointer is a SILFunction*. DistributedAccessorAsyncPointer, /// Accessible function record, which describes a function that can be /// looked up by name by the runtime. /// The pointer is a SILFunction*. AccessibleFunctionRecord, /// A global struct containing a relative pointer to the single-yield /// coroutine ramp function and the fixed-size to be allocated in the /// caller. /// The pointer is a SILFunction*. CoroFunctionPointer, /// An coro function pointer for a method dispatch thunk. The pointer is /// a FuncDecl* inside a protocol or a class. DispatchThunkCoroFunctionPointer, /// An coro function pointer for a method dispatch thunk for an /// initializing constructor. The pointer is a ConstructorDecl* inside a /// class. DispatchThunkInitializerCoroFunctionPointer, /// An coro function pointer for a method dispatch thunk for an allocating /// constructor. The pointer is a ConstructorDecl* inside a protocol or /// a class. DispatchThunkAllocatorCoroFunctionPointer, /// An coro function pointer for a distributed thunk. /// The pointer is a FuncDecl* inside an actor (class). DistributedThunkCoroFunctionPointer, /// An coro function pointer to a partial apply forwarder. /// The pointer is the llvm::Function* for a partial apply forwarder. PartialApplyForwarderCoroFunctionPointer, /// An coro function pointer to a function which is known to exist whose /// name is known. /// The pointer is a const char* of the name. KnownCoroFunctionPointer, /// A coro function pointer for a distributed accessor (method or /// property). /// The pointer is a SILFunction*. DistributedAccessorCoroFunctionPointer, /// An allocator to be passed to swift_coro_alloc and swift_coro_dealloc. CoroAllocator, }; friend struct llvm::DenseMapInfo; Kind getKind() const { return Kind(LINKENTITY_GET_FIELD(Data, Kind)); } friend llvm::hash_code hash_value(const LinkEntity &Entity) { return llvm::hash_combine(Entity.Pointer, Entity.SecondaryPointer, Entity.Data); } friend bool operator==(const LinkEntity &LHS, const LinkEntity &RHS) { return LHS.Pointer == RHS.Pointer && LHS.SecondaryPointer == RHS.SecondaryPointer && LHS.Data == RHS.Data; } friend bool operator!=(const LinkEntity &LHS, const LinkEntity &RHS) { return !(LHS == RHS); } static bool isDeclKind(Kind k) { return k <= Kind::CoroFunctionPointerAST; } static bool isTypeKind(Kind k) { return k >= Kind::ProtocolWitnessTableLazyAccessFunction && k < Kind::DynamicallyReplaceableFunctionVariable; } static bool isRootProtocolConformanceKind(Kind k) { return (k == Kind::ProtocolConformanceDescriptor || k == Kind::ProtocolConformanceDescriptorRecord || k == Kind::ProtocolWitnessTable); } static bool isProtocolConformanceKind(Kind k) { return (k >= Kind::ProtocolWitnessTable && k <= Kind::ProtocolWitnessTableLazyCacheVariable); } void setForDecl(Kind kind, const ValueDecl *decl) { assert(isDeclKind(kind)); Pointer = const_cast(static_cast(decl)); SecondaryPointer = nullptr; Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind)); } void setForProtocolAndAssociatedConformance(Kind kind, const ProtocolDecl *proto, CanType associatedType, ProtocolDecl *associatedProtocol){ assert(isDeclKind(kind)); Pointer = static_cast(const_cast(proto)); SecondaryPointer = nullptr; Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind)) | LINKENTITY_SET_FIELD(AssociatedConformanceIndex, getAssociatedConformanceIndex( proto, associatedType, associatedProtocol)); } void setForProtocolConformance(Kind kind, const ProtocolConformance *c) { assert(isProtocolConformanceKind(kind) && !isTypeKind(kind)); Pointer = nullptr; SecondaryPointer = const_cast(static_cast(c)); Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind)); } void setForProtocolConformanceAndType(Kind kind, const ProtocolConformance *c, CanType type) { assert(isProtocolConformanceKind(kind) && isTypeKind(kind)); Pointer = type.getPointer(); SecondaryPointer = const_cast(static_cast(c)); Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind)); } void setForProtocolConformanceAndAssociatedType(Kind kind, const ProtocolConformance *c, AssociatedTypeDecl *associate) { assert(isProtocolConformanceKind(kind)); Pointer = nullptr; SecondaryPointer = const_cast(static_cast(c)); Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind)) | LINKENTITY_SET_FIELD(AssociatedTypeIndex, getAssociatedTypeIndex(c, associate)); } void setForProtocolConformanceAndAssociatedConformance(Kind kind, const ProtocolConformance *c, CanType associatedType, ProtocolDecl *associatedProtocol) { assert(isProtocolConformanceKind(kind)); Pointer = associatedProtocol; SecondaryPointer = const_cast(static_cast(c)); Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind)) | LINKENTITY_SET_FIELD(AssociatedConformanceIndex, getAssociatedConformanceIndex(c, associatedType, associatedProtocol)); } // We store associated types using their index in their parent protocol // in order to avoid bloating LinkEntity out to three key pointers. static unsigned getAssociatedTypeIndex(const ProtocolConformance *conformance, AssociatedTypeDecl *associate) { auto *proto = associate->getProtocol(); assert(conformance->getProtocol() == proto); unsigned result = 0; for (auto requirement : proto->getAssociatedTypeMembers()) { if (requirement == associate) return result; result++; } llvm_unreachable("didn't find associated type in protocol?"); } static AssociatedTypeDecl * getAssociatedTypeByIndex(const ProtocolConformance *conformance, unsigned index) { for (auto associate : conformance->getProtocol()->getAssociatedTypeMembers()) { if (index == 0) return associate; index--; } llvm_unreachable("didn't find associated type in protocol?"); } // We store associated conformances using their index in the requirement // list of the requirement signature of the protocol. static unsigned getAssociatedConformanceIndex(const ProtocolDecl *proto, CanType associatedType, ProtocolDecl *requirement) { unsigned index = 0; for (const auto &reqt : proto->getRequirementSignature().getRequirements()) { if (reqt.getKind() == RequirementKind::Conformance && reqt.getFirstType()->getCanonicalType() == associatedType && reqt.getProtocolDecl() == requirement) { return index; } ++index; } llvm_unreachable("requirement not found in protocol"); } // We store associated conformances using their index in the requirement // list of the requirement signature of the conformance's protocol. static unsigned getAssociatedConformanceIndex( const ProtocolConformance *conformance, CanType associatedType, ProtocolDecl *requirement) { return getAssociatedConformanceIndex(conformance->getProtocol(), associatedType, requirement); } static std::pair getAssociatedConformanceByIndex(const ProtocolDecl *proto, unsigned index) { auto &reqt = proto->getRequirementSignature().getRequirements()[index]; assert(reqt.getKind() == RequirementKind::Conformance); return { reqt.getFirstType()->getCanonicalType(), reqt.getProtocolDecl() }; } static std::pair getAssociatedConformanceByIndex(const ProtocolConformance *conformance, unsigned index) { return getAssociatedConformanceByIndex(conformance->getProtocol(), index); } void setForDifferentiabilityWitness(Kind kind, const SILDifferentiabilityWitness *witness) { Pointer = nullptr; SecondaryPointer = const_cast(static_cast(witness)); Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind)); } void setForType(Kind kind, CanType type) { assert(isTypeKind(kind)); Pointer = type.getPointer(); SecondaryPointer = nullptr; Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind)); } LinkEntity() : Pointer(nullptr), SecondaryPointer(nullptr), Data(0) {} static bool isValidResilientMethodRef(SILDeclRef declRef) { if (declRef.isForeign) return false; auto *decl = declRef.getDecl(); return (isa(decl->getDeclContext()) || isa(decl->getDeclContext())); } SILDeclRef::Kind getSILDeclRefKind() const; public: static LinkEntity forDispatchThunk(SILDeclRef declRef) { assert(isValidResilientMethodRef(declRef)); if (declRef.isAutoDiffDerivativeFunction()) { LinkEntity entity; // The derivative function for any decl is always a method (not an // initializer). entity.setForDecl(Kind::DispatchThunkDerivative, declRef.getDecl()); entity.SecondaryPointer = declRef.getAutoDiffDerivativeFunctionIdentifier(); return entity; } LinkEntity::Kind kind; switch (declRef.kind) { case SILDeclRef::Kind::Func: kind = Kind::DispatchThunk; break; case SILDeclRef::Kind::Initializer: kind = Kind::DispatchThunkInitializer; break; case SILDeclRef::Kind::Allocator: kind = Kind::DispatchThunkAllocator; break; default: llvm_unreachable("Bad SILDeclRef for dispatch thunk"); } LinkEntity entity; entity.setForDecl(kind, declRef.getDecl()); return entity; } static LinkEntity forMethodDescriptor(SILDeclRef declRef) { assert(isValidResilientMethodRef(declRef)); if (declRef.isAutoDiffDerivativeFunction()) { LinkEntity entity; // The derivative function for any decl is always a method (not an // initializer). entity.setForDecl(Kind::MethodDescriptorDerivative, declRef.getDecl()); entity.SecondaryPointer = declRef.getAutoDiffDerivativeFunctionIdentifier(); return entity; } LinkEntity::Kind kind; switch (declRef.kind) { case SILDeclRef::Kind::Func: kind = Kind::MethodDescriptor; break; case SILDeclRef::Kind::Initializer: kind = Kind::MethodDescriptorInitializer; break; case SILDeclRef::Kind::Allocator: kind = Kind::MethodDescriptorAllocator; break; default: llvm_unreachable("Bad SILDeclRef for method descriptor"); } LinkEntity entity; entity.setForDecl(kind, declRef.getDecl()); return entity; } static LinkEntity forMethodLookupFunction(ClassDecl *classDecl) { LinkEntity entity; entity.setForDecl(Kind::MethodLookupFunction, classDecl); return entity; } static LinkEntity forFieldOffset(VarDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::FieldOffset, decl); return entity; } static LinkEntity forEnumCase(EnumElementDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::EnumCase, decl); return entity; } static LinkEntity forObjCClassRef(ClassDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::ObjCClassRef, decl); return entity; } static LinkEntity forObjCClass(ClassDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::ObjCClass, decl); return entity; } static LinkEntity forObjCMetaclass(ClassDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::ObjCMetaclass, decl); return entity; } static LinkEntity forSwiftMetaclassStub(ClassDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::SwiftMetaclassStub, decl); return entity; } static LinkEntity forObjCMetadataUpdateFunction(ClassDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::ObjCMetadataUpdateFunction, decl); return entity; } static LinkEntity forObjCResilientClassStub(ClassDecl *decl, TypeMetadataAddress addr) { LinkEntity entity; entity.setForDecl(Kind::ObjCResilientClassStub, decl); entity.Data |= LINKENTITY_SET_FIELD(MetadataAddress, unsigned(addr)); return entity; } static LinkEntity forTypeMetadata(CanType concreteType, TypeMetadataAddress addr, bool forceShared = false) { assert(!isObjCImplementation(concreteType)); assert(!isEmbedded(concreteType) || isMetadataAllowedInEmbedded(concreteType)); LinkEntity entity; entity.setForType(Kind::TypeMetadata, concreteType); entity.Data |= LINKENTITY_SET_FIELD(MetadataAddress, unsigned(addr)); entity.Data |= LINKENTITY_SET_FIELD(ForceShared, unsigned(forceShared)); return entity; } static LinkEntity forTypeMetadataPattern(NominalTypeDecl *decl) { assert(!isEmbedded(decl)); LinkEntity entity; entity.setForDecl(Kind::TypeMetadataPattern, decl); return entity; } static LinkEntity forTypeMetadataAccessFunction(CanType type) { LinkEntity entity; entity.setForType(Kind::TypeMetadataAccessFunction, type); return entity; } static LinkEntity forTypeMetadataInstantiationCache(NominalTypeDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::TypeMetadataInstantiationCache, decl); return entity; } static LinkEntity forTypeMetadataInstantiationFunction(NominalTypeDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::TypeMetadataInstantiationFunction, decl); return entity; } static LinkEntity forTypeMetadataSingletonInitializationCache( NominalTypeDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::TypeMetadataSingletonInitializationCache, decl); return entity; } static LinkEntity forTypeMetadataCompletionFunction(NominalTypeDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::TypeMetadataCompletionFunction, decl); return entity; } static LinkEntity forTypeMetadataLazyCacheVariable(CanType type) { LinkEntity entity; entity.setForType(Kind::TypeMetadataLazyCacheVariable, type); return entity; } static LinkEntity forTypeMetadataDemanglingCacheVariable(CanType type) { LinkEntity entity; entity.setForType(Kind::TypeMetadataDemanglingCacheVariable, type); return entity; } static LinkEntity forClassMetadataBaseOffset(ClassDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::ClassMetadataBaseOffset, decl); return entity; } static LinkEntity forNominalTypeDescriptor(NominalTypeDecl *decl) { assert(!isObjCImplementation(decl)); assert(!isEmbedded(decl)); LinkEntity entity; entity.setForDecl(Kind::NominalTypeDescriptor, decl); return entity; } static LinkEntity forNominalTypeDescriptorRecord(NominalTypeDecl *decl) { assert(!isObjCImplementation(decl)); assert(!isEmbedded(decl)); LinkEntity entity; entity.setForDecl(Kind::NominalTypeDescriptorRecord, decl); return entity; } static LinkEntity forOpaqueTypeDescriptor(OpaqueTypeDecl *decl) { assert(!isEmbedded(decl)); LinkEntity entity; entity.setForDecl(Kind::OpaqueTypeDescriptor, decl); return entity; } static LinkEntity forOpaqueTypeDescriptorRecord(OpaqueTypeDecl *decl) { assert(!isEmbedded(decl)); LinkEntity entity; entity.setForDecl(Kind::OpaqueTypeDescriptorRecord, decl); return entity; } static LinkEntity forOpaqueTypeDescriptorAccessor(OpaqueTypeDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::OpaqueTypeDescriptorAccessor, decl); return entity; } static LinkEntity forOpaqueTypeDescriptorAccessorImpl(OpaqueTypeDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::OpaqueTypeDescriptorAccessorImpl, decl); return entity; } static LinkEntity forOpaqueTypeDescriptorAccessorKey(OpaqueTypeDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::OpaqueTypeDescriptorAccessorKey, decl); return entity; } static LinkEntity forOpaqueTypeDescriptorAccessorVar(OpaqueTypeDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::OpaqueTypeDescriptorAccessorVar, decl); return entity; } static LinkEntity forPropertyDescriptor(AbstractStorageDecl *decl) { assert((bool)decl->getPropertyDescriptorGenericSignature()); LinkEntity entity; entity.setForDecl(Kind::PropertyDescriptor, decl); return entity; } static LinkEntity forModuleDescriptor(ModuleDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::ModuleDescriptor, decl); return entity; } static LinkEntity forExtensionDescriptor(ExtensionDecl *decl) { LinkEntity entity; entity.Pointer = const_cast(static_cast(decl)); entity.SecondaryPointer = nullptr; entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::ExtensionDescriptor)); return entity; } static LinkEntity forAnonymousDescriptor( PointerUnion dc) { LinkEntity entity; entity.Pointer = dc.getOpaqueValue(); entity.SecondaryPointer = nullptr; entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::AnonymousDescriptor)); return entity; } static LinkEntity forProtocolDescriptor(ProtocolDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::ProtocolDescriptor, decl); return entity; } static LinkEntity forProtocolDescriptorRecord(ProtocolDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::ProtocolDescriptorRecord, decl); return entity; } static LinkEntity forProtocolRequirementsBaseDescriptor(ProtocolDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::ProtocolRequirementsBaseDescriptor, decl); return entity; } static LinkEntity forValueWitness(CanType concreteType, ValueWitness witness) { // Explicitly allowed in embedded Swift because we generate value witnesses // (but not witness tables) for Swift Concurrency usage. LinkEntity entity; entity.Pointer = concreteType.getPointer(); entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::ValueWitness)) | LINKENTITY_SET_FIELD(ValueWitness, unsigned(witness)); return entity; } static LinkEntity forValueWitnessTable(CanType type) { assert(!isEmbedded(type)); LinkEntity entity; entity.setForType(Kind::ValueWitnessTable, type); return entity; } static LinkEntity forSILFunction(SILFunction *F, bool IsDynamicallyReplaceableImplementation=false) { LinkEntity entity; entity.Pointer = F; entity.SecondaryPointer = nullptr; entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::SILFunction)) | LINKENTITY_SET_FIELD(IsDynamicallyReplaceableImpl, (unsigned)IsDynamicallyReplaceableImplementation); return entity; } static LinkEntity forSILGlobalVariable(SILGlobalVariable *G, IRGenModule &IGM); static LinkEntity forDifferentiabilityWitness(const SILDifferentiabilityWitness *witness) { LinkEntity entity; entity.setForDifferentiabilityWitness(Kind::DifferentiabilityWitness, witness); return entity; } static LinkEntity forProtocolWitnessTable(const ProtocolConformance *C) { if (isEmbedded(C)) { assert(C->getProtocol()->requiresClass()); } LinkEntity entity; entity.setForProtocolConformance(Kind::ProtocolWitnessTable, C); return entity; } static LinkEntity forProtocolWitnessTablePattern(const ProtocolConformance *C) { assert(!isEmbedded(C)); LinkEntity entity; entity.setForProtocolConformance(Kind::ProtocolWitnessTablePattern, C); return entity; } static LinkEntity forGenericProtocolWitnessTableInstantiationFunction( const ProtocolConformance *C) { LinkEntity entity; entity.setForProtocolConformance( Kind::GenericProtocolWitnessTableInstantiationFunction, C); return entity; } static LinkEntity forProtocolWitnessTableLazyAccessFunction(const ProtocolConformance *C, CanType type) { LinkEntity entity; entity.setForProtocolConformanceAndType( Kind::ProtocolWitnessTableLazyAccessFunction, C, type); return entity; } static LinkEntity forProtocolWitnessTableLazyCacheVariable(const ProtocolConformance *C, CanType type) { LinkEntity entity; entity.setForProtocolConformanceAndType( Kind::ProtocolWitnessTableLazyCacheVariable, C, type); return entity; } static LinkEntity forAssociatedTypeDescriptor(AssociatedTypeDecl *assocType) { LinkEntity entity; entity.setForDecl(Kind::AssociatedTypeDescriptor, assocType); return entity; } static LinkEntity forAssociatedConformanceDescriptor(AssociatedConformance conformance) { LinkEntity entity; entity.setForProtocolAndAssociatedConformance( Kind::AssociatedConformanceDescriptor, conformance.getSourceProtocol(), conformance.getAssociation(), conformance.getAssociatedRequirement()); return entity; } static LinkEntity forBaseConformanceDescriptor(BaseConformance conformance) { LinkEntity entity; entity.setForProtocolAndAssociatedConformance( Kind::BaseConformanceDescriptor, conformance.getSourceProtocol(), conformance.getSourceProtocol()->getSelfInterfaceType() ->getCanonicalType(), conformance.getBaseRequirement()); return entity; } static LinkEntity forAssociatedTypeWitnessTableAccessFunction(const ProtocolConformance *C, const AssociatedConformance &association) { LinkEntity entity; entity.setForProtocolConformanceAndAssociatedConformance( Kind::AssociatedTypeWitnessTableAccessFunction, C, association.getAssociation(), association.getAssociatedRequirement()); return entity; } static LinkEntity forDefaultAssociatedConformanceAccessor(AssociatedConformance conformance) { LinkEntity entity; entity.setForProtocolAndAssociatedConformance( Kind::DefaultAssociatedConformanceAccessor, conformance.getSourceProtocol(), conformance.getAssociation(), conformance.getAssociatedRequirement()); return entity; } static LinkEntity forReflectionBuiltinDescriptor(CanType type) { LinkEntity entity; entity.setForType(Kind::ReflectionBuiltinDescriptor, type); return entity; } static LinkEntity forReflectionFieldDescriptor(CanType type) { LinkEntity entity; entity.setForType(Kind::ReflectionFieldDescriptor, type); return entity; } static LinkEntity forReflectionAssociatedTypeDescriptor(const ProtocolConformance *C) { LinkEntity entity; entity.setForProtocolConformance( Kind::ReflectionAssociatedTypeDescriptor, C); return entity; } static LinkEntity forProtocolConformanceDescriptor(const RootProtocolConformance *C) { LinkEntity entity; entity.setForProtocolConformance(Kind::ProtocolConformanceDescriptor, C); return entity; } static LinkEntity forProtocolConformanceDescriptorRecord(const RootProtocolConformance *C) { LinkEntity entity; entity.setForProtocolConformance(Kind::ProtocolConformanceDescriptorRecord, C); return entity; } static LinkEntity forCoroutineContinuationPrototype(CanSILFunctionType type) { LinkEntity entity; entity.setForType(Kind::CoroutineContinuationPrototype, type); return entity; } static LinkEntity forDynamicallyReplaceableFunctionVariable(SILFunction *F) { LinkEntity entity; entity.Pointer = F; entity.SecondaryPointer = nullptr; entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(Kind::DynamicallyReplaceableFunctionVariable)); return entity; } static LinkEntity forDynamicallyReplaceableFunctionVariable(AbstractFunctionDecl *decl, bool isAllocator) { LinkEntity entity; entity.setForDecl(Kind::DynamicallyReplaceableFunctionVariableAST, decl); entity.SecondaryPointer = isAllocator ? decl : nullptr; return entity; } static LinkEntity forDynamicallyReplaceableFunctionKey(SILFunction *F) { LinkEntity entity; entity.Pointer = F; entity.SecondaryPointer = nullptr; entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(Kind::DynamicallyReplaceableFunctionKey)); return entity; } static LinkEntity forDynamicallyReplaceableFunctionKey(AbstractFunctionDecl *decl, bool isAllocator) { LinkEntity entity; entity.setForDecl(Kind::DynamicallyReplaceableFunctionKeyAST, decl); entity.SecondaryPointer = isAllocator ? decl : nullptr; return entity; } static LinkEntity forDynamicallyReplaceableFunctionImpl(AbstractFunctionDecl *decl, bool isAllocator) { LinkEntity entity; entity.setForDecl(Kind::DynamicallyReplaceableFunctionImpl, decl); entity.SecondaryPointer = isAllocator ? decl : nullptr; return entity; } static LinkEntity forCanonicalPrespecializedGenericTypeCachingOnceToken(NominalTypeDecl *decl) { LinkEntity entity; entity.setForDecl(Kind::CanonicalPrespecializedGenericTypeCachingOnceToken, decl); return entity; } static LinkEntity forSpecializedGenericSwiftMetaclassStub(CanType concreteType) { LinkEntity entity; entity.setForType(Kind::CanonicalSpecializedGenericSwiftMetaclassStub, concreteType); return entity; } static LinkEntity forPrespecializedTypeMetadataAccessFunction(CanType theType) { LinkEntity entity; entity.setForType( Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction, theType); return entity; } static LinkEntity forNoncanonicalSpecializedGenericTypeMetadata(CanType theType) { LinkEntity entity; entity.setForType(Kind::NoncanonicalSpecializedGenericTypeMetadata, theType); entity.Data |= LINKENTITY_SET_FIELD( MetadataAddress, unsigned(TypeMetadataAddress::FullMetadata)); return entity; } static LinkEntity forNoncanonicalSpecializedGenericTypeMetadataCacheVariable(CanType theType) { LinkEntity entity; entity.setForType(Kind::NoncanonicalSpecializedGenericTypeMetadataCacheVariable, theType); return entity; } static LinkEntity forAsyncFunctionPointer(LinkEntity other) { LinkEntity entity; entity.Pointer = other.Pointer; entity.SecondaryPointer = nullptr; switch (other.getKind()) { case LinkEntity::Kind::SILFunction: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::AsyncFunctionPointer)); break; case LinkEntity::Kind::DispatchThunk: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::DispatchThunkAsyncFunctionPointer)); break; case LinkEntity::Kind::DispatchThunkInitializer: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::DispatchThunkInitializerAsyncFunctionPointer)); break; case LinkEntity::Kind::DispatchThunkAllocator: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::DispatchThunkAllocatorAsyncFunctionPointer)); break; case LinkEntity::Kind::PartialApplyForwarder: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::PartialApplyForwarderAsyncFunctionPointer)); break; case LinkEntity::Kind::DistributedAccessor: { entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::DistributedAccessorAsyncPointer)); break; } default: llvm_unreachable("Link entity kind cannot have an async function pointer"); } return entity; } static LinkEntity forAsyncFunctionPointer(SILDeclRef declRef) { LinkEntity entity; entity.setForDecl(declRef.isDistributedThunk() ? Kind::DistributedThunkAsyncFunctionPointer : Kind::AsyncFunctionPointerAST, declRef.getAbstractFunctionDecl()); entity.SecondaryPointer = reinterpret_cast(static_cast(declRef.kind)); return entity; } static LinkEntity forKnownAsyncFunctionPointer(const char *name) { LinkEntity entity; entity.Pointer = const_cast(name); entity.SecondaryPointer = nullptr; entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::KnownAsyncFunctionPointer)); return entity; } static LinkEntity forDistributedTargetAccessor(SILFunction *target) { return forDistributedTargetAccessor(target->getDeclContext()->getAsDecl()); } static LinkEntity forDistributedTargetAccessor(Decl *target) { LinkEntity entity; entity.Pointer = target; entity.SecondaryPointer = nullptr; entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::DistributedAccessor)); return entity; } static LinkEntity forAccessibleFunctionRecord(SILFunction *func) { LinkEntity entity; entity.Pointer = func; entity.SecondaryPointer = nullptr; entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::AccessibleFunctionRecord)); return entity; } LinkEntity getUnderlyingEntityForAsyncFunctionPointer() const { LinkEntity entity; entity.Pointer = Pointer; entity.SecondaryPointer = nullptr; switch (getKind()) { case LinkEntity::Kind::AsyncFunctionPointer: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::SILFunction)); break; case LinkEntity::Kind::DispatchThunkAsyncFunctionPointer: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::DispatchThunk)); break; case LinkEntity::Kind::DispatchThunkInitializerAsyncFunctionPointer: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::DispatchThunkInitializer)); break; case LinkEntity::Kind::DispatchThunkAllocatorAsyncFunctionPointer: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::DispatchThunkAllocator)); break; case LinkEntity::Kind::PartialApplyForwarderAsyncFunctionPointer: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::PartialApplyForwarder)); break; case LinkEntity::Kind::DistributedAccessorAsyncPointer: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::DistributedAccessor)); break; default: llvm_unreachable("Link entity is not an async function pointer"); } return entity; } static LinkEntity forPartialApplyForwarder(llvm::Function *function) { LinkEntity entity; entity.Pointer = function; entity.SecondaryPointer = nullptr; entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::PartialApplyForwarder)); return entity; } static LinkEntity forExtendedExistentialTypeShape(CanGenericSignature genSig, CanType existentialType, bool isUnique, bool isShared) { LinkEntity entity; entity.Pointer = existentialType.getPointer(); entity.SecondaryPointer = const_cast(genSig.getPointer()); entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::ExtendedExistentialTypeShape)) | LINKENTITY_SET_FIELD(ExtendedExistentialIsUnique, unsigned(isUnique)) | LINKENTITY_SET_FIELD(ExtendedExistentialIsShared, unsigned(isShared)); return entity; } static LinkEntity forCoroAllocator(CoroAllocatorKind kind) { LinkEntity entity; entity.Pointer = nullptr; entity.SecondaryPointer = nullptr; entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::CoroAllocator)) | LINKENTITY_SET_FIELD(CoroAllocatorKind, unsigned(kind)); return entity; } static LinkEntity forCoroFunctionPointer(LinkEntity other) { LinkEntity entity; entity.Pointer = other.Pointer; entity.SecondaryPointer = nullptr; switch (other.getKind()) { case LinkEntity::Kind::SILFunction: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::CoroFunctionPointer)); break; case LinkEntity::Kind::DispatchThunk: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::DispatchThunkCoroFunctionPointer)); break; case LinkEntity::Kind::DispatchThunkInitializer: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned( LinkEntity::Kind::DispatchThunkInitializerCoroFunctionPointer)); break; case LinkEntity::Kind::DispatchThunkAllocator: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned( LinkEntity::Kind::DispatchThunkAllocatorCoroFunctionPointer)); break; case LinkEntity::Kind::PartialApplyForwarder: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::PartialApplyForwarderCoroFunctionPointer)); break; case LinkEntity::Kind::DistributedAccessor: { entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::DistributedAccessorCoroFunctionPointer)); break; } default: llvm_unreachable("Link entity kind cannot have an coro function pointer"); } return entity; } static LinkEntity forCoroFunctionPointer(SILDeclRef declRef) { LinkEntity entity; entity.setForDecl(declRef.isDistributedThunk() ? Kind::DistributedThunkCoroFunctionPointer : Kind::CoroFunctionPointerAST, declRef.getAbstractFunctionDecl()); entity.SecondaryPointer = reinterpret_cast(static_cast(declRef.kind)); return entity; } static LinkEntity forKnownCoroFunctionPointer(const char *name) { LinkEntity entity; entity.Pointer = const_cast(name); entity.SecondaryPointer = nullptr; entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::KnownCoroFunctionPointer)); return entity; } LinkEntity getUnderlyingEntityForCoroFunctionPointer() const { LinkEntity entity; entity.Pointer = Pointer; entity.SecondaryPointer = nullptr; switch (getKind()) { case LinkEntity::Kind::CoroFunctionPointer: entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(LinkEntity::Kind::SILFunction)); break; case LinkEntity::Kind::DispatchThunkCoroFunctionPointer: entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(LinkEntity::Kind::DispatchThunk)); break; case LinkEntity::Kind::DispatchThunkInitializerCoroFunctionPointer: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::DispatchThunkInitializer)); break; case LinkEntity::Kind::DispatchThunkAllocatorCoroFunctionPointer: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::DispatchThunkAllocator)); break; case LinkEntity::Kind::PartialApplyForwarderCoroFunctionPointer: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::PartialApplyForwarder)); break; case LinkEntity::Kind::DistributedAccessorCoroFunctionPointer: entity.Data = LINKENTITY_SET_FIELD( Kind, unsigned(LinkEntity::Kind::DistributedAccessor)); break; default: llvm_unreachable("Link entity is not an coro function pointer"); } return entity; } void mangle(ASTContext &Ctx, llvm::raw_ostream &out) const; void mangle(ASTContext &Ctx, SmallVectorImpl &buffer) const; std::string mangleAsString(ASTContext &Ctx) const; SILDeclRef getSILDeclRef() const; SILLinkage getLinkage(ForDefinition_t isDefinition) const; bool hasDecl() const { return isDeclKind(getKind()); } const ValueDecl *getDecl() const { assert(isDeclKind(getKind())); return reinterpret_cast(Pointer); } const ExtensionDecl *getExtension() const { assert(getKind() == Kind::ExtensionDescriptor); return reinterpret_cast(Pointer); } const AbstractStorageDecl *getAbstractStorageDecl() const { assert(getKind() == Kind::PropertyDescriptor); return reinterpret_cast(Pointer); } const PointerUnion getAnonymousDeclContext() const { assert(getKind() == Kind::AnonymousDescriptor); return PointerUnion ::getFromOpaqueValue(reinterpret_cast(Pointer)); } bool hasSILFunction() const { return getKind() == Kind::AsyncFunctionPointer || getKind() == Kind::DynamicallyReplaceableFunctionVariable || getKind() == Kind::DynamicallyReplaceableFunctionKey || getKind() == Kind::SILFunction || getKind() == Kind::DistributedAccessor || getKind() == Kind::AccessibleFunctionRecord; } SILFunction *getSILFunction() const { assert(hasSILFunction()); return reinterpret_cast(Pointer); } SILGlobalVariable *getSILGlobalVariable() const { assert(getKind() == Kind::SILGlobalVariable || getKind() == Kind::ReadOnlyGlobalObject); return reinterpret_cast(Pointer); } SILDifferentiabilityWitness *getSILDifferentiabilityWitness() const { assert(getKind() == Kind::DifferentiabilityWitness); return reinterpret_cast(SecondaryPointer); } const RootProtocolConformance *getRootProtocolConformance() const { assert(isProtocolConformanceKind(getKind())); return getProtocolConformance()->getRootConformance(); } const ProtocolConformance *getProtocolConformance() const { assert(isProtocolConformanceKind(getKind())); return reinterpret_cast(SecondaryPointer); } AssociatedTypeDecl *getAssociatedType() const { assert(getKind() == Kind::AssociatedTypeDescriptor); return reinterpret_cast(Pointer); } std::pair getAssociatedConformance() const { if (getKind() == Kind::AssociatedTypeWitnessTableAccessFunction) { return getAssociatedConformanceByIndex(getProtocolConformance(), LINKENTITY_GET_FIELD(Data, AssociatedConformanceIndex)); } assert(getKind() == Kind::AssociatedConformanceDescriptor || getKind() == Kind::DefaultAssociatedConformanceAccessor || getKind() == Kind::BaseConformanceDescriptor); return getAssociatedConformanceByIndex( cast(getDecl()), LINKENTITY_GET_FIELD(Data, AssociatedConformanceIndex)); } ProtocolDecl *getAssociatedProtocol() const { assert(getKind() == Kind::AssociatedTypeWitnessTableAccessFunction); return reinterpret_cast(Pointer); } AutoDiffDerivativeFunctionIdentifier * getAutoDiffDerivativeFunctionIdentifier() const { assert(getKind() == Kind::DispatchThunkDerivative || getKind() == Kind::MethodDescriptorDerivative); return reinterpret_cast( SecondaryPointer); } CoroAllocatorKind getCoroAllocatorKind() const { assert(getKind() == Kind::CoroAllocator); return CoroAllocatorKind(LINKENTITY_GET_FIELD(Data, CoroAllocatorKind)); } CanGenericSignature getExtendedExistentialTypeShapeGenSig() const { assert(getKind() == Kind::ExtendedExistentialTypeShape); return CanGenericSignature( reinterpret_cast(SecondaryPointer)); } CanType getExtendedExistentialTypeShapeType() const { assert(getKind() == Kind::ExtendedExistentialTypeShape); return CanType(reinterpret_cast(Pointer)); } bool isExtendedExistentialTypeShapeUnique() const { assert(getKind() == Kind::ExtendedExistentialTypeShape); return LINKENTITY_GET_FIELD(Data, ExtendedExistentialIsUnique); } bool isExtendedExistentialTypeShapeShared() const { assert(getKind() == Kind::ExtendedExistentialTypeShape); return LINKENTITY_GET_FIELD(Data, ExtendedExistentialIsShared); } bool isDynamicallyReplaceable() const { assert(getKind() == Kind::SILFunction); return LINKENTITY_GET_FIELD(Data, IsDynamicallyReplaceableImpl); } bool isDynamicallyReplaceableKey() const { return getKind() == Kind::DynamicallyReplaceableFunctionKey || getKind() == Kind::OpaqueTypeDescriptorAccessorKey; } bool isOpaqueTypeDescriptorAccessor() const { return getKind() == Kind::OpaqueTypeDescriptorAccessor || getKind() == Kind::OpaqueTypeDescriptorAccessorImpl || getKind() == Kind::OpaqueTypeDescriptorAccessorKey || getKind() == Kind::OpaqueTypeDescriptorAccessorVar; } bool isOpaqueTypeDescriptorAccessorImpl() const { return getKind() == Kind::OpaqueTypeDescriptorAccessorImpl; } bool isAllocator() const { assert(getKind() == Kind::DynamicallyReplaceableFunctionImpl || getKind() == Kind::DynamicallyReplaceableFunctionKeyAST || getKind() == Kind::DynamicallyReplaceableFunctionVariableAST); return SecondaryPointer != nullptr; } bool isValueWitness() const { return getKind() == Kind::ValueWitness; } bool isContextDescriptor() const; CanType getType() const { assert(isTypeKind(getKind())); return CanType(reinterpret_cast(Pointer)); } ValueWitness getValueWitness() const { assert(getKind() == Kind::ValueWitness); return ValueWitness(LINKENTITY_GET_FIELD(Data, ValueWitness)); } TypeMetadataAddress getMetadataAddress() const { assert(getKind() == Kind::TypeMetadata || getKind() == Kind::NoncanonicalSpecializedGenericTypeMetadata || getKind() == Kind::ObjCResilientClassStub); return (TypeMetadataAddress)LINKENTITY_GET_FIELD(Data, MetadataAddress); } bool isForcedShared() const { assert(getKind() == Kind::TypeMetadata); return (bool)LINKENTITY_GET_FIELD(Data, ForceShared); } bool isObjCClassRef() const { return getKind() == Kind::ObjCClassRef; } bool isSILFunction() const { return getKind() == Kind::SILFunction; } bool isDynamicallyReplaceableFunctionKey() const { return getKind() == Kind::DynamicallyReplaceableFunctionKey; } bool isDynamicallyReplaceableFunctionImpl() const { return getKind() == Kind::DynamicallyReplaceableFunctionImpl; } bool isTypeMetadataAccessFunction() const { return getKind() == Kind::TypeMetadataAccessFunction; } bool isDistributedThunk() const; bool isDispatchThunk() const { return getKind() == Kind::DispatchThunk || getKind() == Kind::DispatchThunkInitializer || getKind() == Kind::DispatchThunkAllocator || getKind() == Kind::DispatchThunkDerivative; } bool isPropertyDescriptor() const { return getKind() == Kind::PropertyDescriptor; } bool isNominalTypeDescriptor() const { return getKind() == Kind::NominalTypeDescriptor; } /// Determine whether this entity will be weak-imported. bool isWeakImported(ModuleDecl *module) const; /// Return the module scope context whose codegen should trigger emission /// of this link entity, if one can be identified. DeclContext *getDeclContextForEmission() const; /// Get the preferred alignment for the definition of this entity. Alignment getAlignment(IRGenModule &IGM) const; /// Get the default LLVM type to use for forward declarations of this /// entity. llvm::Type *getDefaultDeclarationType(IRGenModule &IGM) const; /// Determine whether entity that represents a symbol is in TEXT segment. bool isText() const; /// Determine whether entity that represents a symbol is in DATA segment. bool isData() const { return !isText(); } bool isTypeKind() const { return isTypeKind(getKind()); } bool isAlwaysSharedLinkage() const; /// Whether the link entity's definitions must be considered non-unique. /// /// This applies only in the Embedded Swift linkage model, and is used for /// any symbols that have not been explicitly requested to have unique /// definitions (e.g., with @_used). bool hasNonUniqueDefinition() const; #undef LINKENTITY_GET_FIELD #undef LINKENTITY_SET_FIELD private: static bool isObjCImplementation(NominalTypeDecl *NTD) { if (NTD) return NTD->getObjCImplementationDecl(); return false; } static bool isObjCImplementation(CanType ty) { return isObjCImplementation(ty->getClassOrBoundGenericClass()); } }; struct IRLinkage { llvm::GlobalValue::LinkageTypes Linkage; llvm::GlobalValue::VisibilityTypes Visibility; llvm::GlobalValue::DLLStorageClassTypes DLLStorage; static const IRLinkage InternalLinkOnceODR; static const IRLinkage InternalWeakODR; static const IRLinkage Internal; static const IRLinkage ExternalCommon; static const IRLinkage ExternalImport; static const IRLinkage ExternalWeakImport; static const IRLinkage ExternalExport; }; class ApplyIRLinkage { IRLinkage IRL; public: ApplyIRLinkage(IRLinkage IRL) : IRL(IRL) {} void to(llvm::GlobalValue *GV, bool definition = true) const { llvm::Module *M = GV->getParent(); const llvm::Triple Triple(M->getTargetTriple()); GV->setLinkage(IRL.Linkage); GV->setVisibility(IRL.Visibility); if (Triple.isOSBinFormatCOFF() && !Triple.isOSCygMing()) GV->setDLLStorageClass(IRL.DLLStorage); // TODO: BFD and gold do not handle COMDATs properly if (Triple.isOSBinFormatELF()) return; // COMDATs cannot be applied to declarations. If we have a definition, // apply the COMDAT. if (definition) if (IRL.Linkage == llvm::GlobalValue::LinkOnceODRLinkage || IRL.Linkage == llvm::GlobalValue::WeakODRLinkage) if (Triple.supportsCOMDAT()) if (llvm::GlobalObject *GO = dyn_cast(GV)) GO->setComdat(M->getOrInsertComdat(GV->getName())); } }; /// Encapsulated information about the linkage of an entity. class LinkInfo { LinkInfo() = default; llvm::SmallString<32> Name; IRLinkage IRL; ForDefinition_t ForDefinition; public: /// Compute linkage information for the given static LinkInfo get(IRGenModule &IGM, const LinkEntity &entity, ForDefinition_t forDefinition); static LinkInfo get(const UniversalLinkageInfo &linkInfo, ModuleDecl *swiftModule, const LinkEntity &entity, ForDefinition_t forDefinition); static LinkInfo get(const UniversalLinkageInfo &linkInfo, StringRef name, SILLinkage linkage, ForDefinition_t isDefinition, bool isWeakImported); StringRef getName() const { return Name.str(); } llvm::GlobalValue::LinkageTypes getLinkage() const { return IRL.Linkage; } llvm::GlobalValue::VisibilityTypes getVisibility() const { return IRL.Visibility; } llvm::GlobalValue::DLLStorageClassTypes getDLLStorage() const { return IRL.DLLStorage; } bool isForDefinition() const { return ForDefinition; } bool isUsed() const { return ForDefinition && isUsed(IRL); } static bool isUsed(IRLinkage IRL); }; StringRef encodeForceLoadSymbolName(llvm::SmallVectorImpl &buf, StringRef name); } } /// Allow LinkEntity to be used as a key for a DenseMap. namespace llvm { template <> struct DenseMapInfo { using LinkEntity = swift::irgen::LinkEntity; static LinkEntity getEmptyKey() { LinkEntity entity; entity.Pointer = nullptr; entity.SecondaryPointer = nullptr; entity.Data = 0; return entity; } static LinkEntity getTombstoneKey() { LinkEntity entity; entity.Pointer = nullptr; entity.SecondaryPointer = nullptr; entity.Data = 1; return entity; } static unsigned getHashValue(const LinkEntity &entity) { return DenseMapInfo::getHashValue(entity.Pointer) ^ DenseMapInfo::getHashValue(entity.SecondaryPointer) ^ entity.Data; } static bool isEqual(const LinkEntity &LHS, const LinkEntity &RHS) { return LHS.Pointer == RHS.Pointer && LHS.SecondaryPointer == RHS.SecondaryPointer && LHS.Data == RHS.Data; } }; } #endif