mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
2011 lines
70 KiB
C++
2011 lines
70 KiB
C++
//===--- 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);
|
||
}
|
||
inline bool isEmbeddedWithoutEmbeddedExitentials(CanType t) {
|
||
auto &langOpts = t->getASTContext().LangOpts;
|
||
return langOpts.hasFeature(Feature::Embedded) &&
|
||
!langOpts.hasFeature(Feature::EmbeddedExistentials);
|
||
}
|
||
// 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) {
|
||
bool embeddedExistentials =
|
||
t->getASTContext().LangOpts.hasFeature(Feature::EmbeddedExistentials);
|
||
|
||
if (isa<ClassType>(t) || isa<BoundGenericClassType>(t) ||
|
||
isa<DynamicSelfType>(t)) {
|
||
return true;
|
||
}
|
||
if (auto existentialTy = dyn_cast<ExistentialType>(t)) {
|
||
if (existentialTy->requiresClass())
|
||
return true;
|
||
}
|
||
if (auto archeTy = dyn_cast<ArchetypeType>(t)) {
|
||
if (archeTy->requiresClass())
|
||
return true;
|
||
}
|
||
|
||
if (embeddedExistentials)
|
||
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);
|
||
}
|
||
|
||
inline bool isEmbeddedWithoutEmbeddedExitentials(const ProtocolConformance *c) {
|
||
return isEmbedded(c) && !c->getType()->getASTContext().
|
||
LangOpts.hasFeature(Feature::EmbeddedExistentials);
|
||
}
|
||
|
||
/// 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<LinkEntity>;
|
||
|
||
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<void*>(static_cast<const void*>(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<ValueDecl *>(const_cast<ProtocolDecl *>(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<void*>(static_cast<const void*>(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<void*>(static_cast<const void*>(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<void*>(static_cast<const void*>(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<void*>(static_cast<const void*>(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<CanType, ProtocolDecl*>
|
||
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<CanType, ProtocolDecl*>
|
||
getAssociatedConformanceByIndex(const ProtocolConformance *conformance,
|
||
unsigned index) {
|
||
return getAssociatedConformanceByIndex(conformance->getProtocol(), index);
|
||
}
|
||
|
||
void
|
||
setForDifferentiabilityWitness(Kind kind,
|
||
const SILDifferentiabilityWitness *witness) {
|
||
Pointer = nullptr;
|
||
SecondaryPointer = const_cast<void *>(static_cast<const void *>(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<ClassDecl>(decl->getDeclContext()) ||
|
||
isa<ProtocolDecl>(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<void*>(static_cast<const void*>(decl));
|
||
entity.SecondaryPointer = nullptr;
|
||
entity.Data =
|
||
LINKENTITY_SET_FIELD(Kind, unsigned(Kind::ExtensionDescriptor));
|
||
return entity;
|
||
}
|
||
|
||
static LinkEntity forAnonymousDescriptor(
|
||
PointerUnion<DeclContext *, VarDecl *> 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(!isEmbeddedWithoutEmbeddedExitentials(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 (isEmbeddedWithoutEmbeddedExitentials(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<void *>(static_cast<uintptr_t>(declRef.kind));
|
||
return entity;
|
||
}
|
||
|
||
static LinkEntity forKnownAsyncFunctionPointer(const char *name) {
|
||
LinkEntity entity;
|
||
entity.Pointer = const_cast<char *>(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<GenericSignatureImpl*>(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<void *>(static_cast<uintptr_t>(declRef.kind));
|
||
return entity;
|
||
}
|
||
|
||
static LinkEntity forKnownCoroFunctionPointer(const char *name) {
|
||
LinkEntity entity;
|
||
entity.Pointer = const_cast<char *>(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<char> &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<ValueDecl*>(Pointer);
|
||
}
|
||
|
||
const ExtensionDecl *getExtension() const {
|
||
assert(getKind() == Kind::ExtensionDescriptor);
|
||
return reinterpret_cast<ExtensionDecl*>(Pointer);
|
||
}
|
||
|
||
const AbstractStorageDecl *getAbstractStorageDecl() const {
|
||
assert(getKind() == Kind::PropertyDescriptor);
|
||
return reinterpret_cast<AbstractStorageDecl *>(Pointer);
|
||
}
|
||
|
||
const PointerUnion<DeclContext *, VarDecl *> getAnonymousDeclContext() const {
|
||
assert(getKind() == Kind::AnonymousDescriptor);
|
||
return PointerUnion<DeclContext *, VarDecl *>
|
||
::getFromOpaqueValue(reinterpret_cast<void*>(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<SILFunction *>(Pointer);
|
||
}
|
||
|
||
SILGlobalVariable *getSILGlobalVariable() const {
|
||
assert(getKind() == Kind::SILGlobalVariable ||
|
||
getKind() == Kind::ReadOnlyGlobalObject);
|
||
return reinterpret_cast<SILGlobalVariable*>(Pointer);
|
||
}
|
||
|
||
SILDifferentiabilityWitness *getSILDifferentiabilityWitness() const {
|
||
assert(getKind() == Kind::DifferentiabilityWitness);
|
||
return reinterpret_cast<SILDifferentiabilityWitness *>(SecondaryPointer);
|
||
}
|
||
|
||
const RootProtocolConformance *getRootProtocolConformance() const {
|
||
assert(isProtocolConformanceKind(getKind()));
|
||
return getProtocolConformance()->getRootConformance();
|
||
}
|
||
|
||
const ProtocolConformance *getProtocolConformance() const {
|
||
assert(isProtocolConformanceKind(getKind()));
|
||
return reinterpret_cast<ProtocolConformance*>(SecondaryPointer);
|
||
}
|
||
|
||
AssociatedTypeDecl *getAssociatedType() const {
|
||
assert(getKind() == Kind::AssociatedTypeDescriptor);
|
||
return reinterpret_cast<AssociatedTypeDecl *>(Pointer);
|
||
}
|
||
|
||
std::pair<CanType, ProtocolDecl *> 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<ProtocolDecl>(getDecl()),
|
||
LINKENTITY_GET_FIELD(Data, AssociatedConformanceIndex));
|
||
}
|
||
|
||
ProtocolDecl *getAssociatedProtocol() const {
|
||
assert(getKind() == Kind::AssociatedTypeWitnessTableAccessFunction);
|
||
return reinterpret_cast<ProtocolDecl*>(Pointer);
|
||
}
|
||
|
||
AutoDiffDerivativeFunctionIdentifier *
|
||
getAutoDiffDerivativeFunctionIdentifier() const {
|
||
assert(getKind() == Kind::DispatchThunkDerivative ||
|
||
getKind() == Kind::MethodDescriptorDerivative);
|
||
return reinterpret_cast<AutoDiffDerivativeFunctionIdentifier*>(
|
||
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<const GenericSignatureImpl*>(SecondaryPointer));
|
||
}
|
||
|
||
CanType getExtendedExistentialTypeShapeType() const {
|
||
assert(getKind() == Kind::ExtendedExistentialTypeShape);
|
||
return CanType(reinterpret_cast<TypeBase*>(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<TypeBase*>(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 nonAliasedDefinition = 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. Also, definitions that are
|
||
// exported through aliases should not have COMDATs, because the alias
|
||
// itself might represent an externally visible symbol but such symbols
|
||
// are discarded from the symtab when other object files have a COMDAT
|
||
// group with the same signature.
|
||
//
|
||
// If we have a non-aliased definition with ODR-based linkage, attach it
|
||
// to a COMDAT group so that duplicate definitions across object files
|
||
// can be merged by the linker.
|
||
if (nonAliasedDefinition)
|
||
if (IRL.Linkage == llvm::GlobalValue::LinkOnceODRLinkage ||
|
||
IRL.Linkage == llvm::GlobalValue::WeakODRLinkage)
|
||
if (Triple.supportsCOMDAT())
|
||
if (llvm::GlobalObject *GO = dyn_cast<llvm::GlobalObject>(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<char> &buf,
|
||
StringRef name);
|
||
}
|
||
}
|
||
|
||
/// Allow LinkEntity to be used as a key for a DenseMap.
|
||
namespace llvm {
|
||
template <> struct DenseMapInfo<swift::irgen::LinkEntity> {
|
||
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<void *>::getHashValue(entity.Pointer) ^
|
||
DenseMapInfo<void *>::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
|