Files
swift-mirror/lib/IRGen/Linking.cpp
T
Kavon Farvardin 006a0a494a Reparenting: require an extension
This change forces you to write ``@reparented` relationships
on an extension of a protocol, rather than on the protocol
itself.

The ProtocolConformance needs to be associated with some
GenericContext and IRGen expects it to be an ExtensionDecl.
That environment defines under what conditions the conformance
exists. We also need to define witnesses for the new parent's
requirements in an extension anyway, so it's a natural fit.

The previous workaround for this was kind of awful, as it'd
require searching all the protocol's extensions and "guess"
which extension they want to represent the conformance. While
we could try to synthesize an extension, there's two
challenges there:

1. Due to SuppressedAssociatedTypes, it's not so simple to
synthesize an unconstrained ExtensionDecl.
2. We currently rely on same-type requirements to pin the
associated types to particular witnesses of those requirements
in the extension. So it's not purely unconstrained! For example,

```
extension Seq: @reparented BorrowSeq where Iter == MyIter {}
```

The constraints that are disallowed (but not yet diagnosed)
are conditional conformance requirements, as the default
conformance for a reparenting cannot depend on those.

Thus, it's better that programmers to specify the extension.
2026-02-03 16:40:21 -08:00

1821 lines
67 KiB
C++

//===--- Linking.cpp - Name mangling for IRGen entities -------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements name mangling for IRGen entities with linkage.
//
//===----------------------------------------------------------------------===//
#include "swift/IRGen/Linking.h"
#include "IRGenMangler.h"
#include "IRGenModule.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/Basic/Assertions.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/SIL/SILGlobalVariable.h"
#include "swift/SIL/FormalLinkage.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include "MetadataRequest.h"
using namespace swift;
using namespace irgen;
using namespace Mangle;
const IRLinkage IRLinkage::InternalLinkOnceODR = {
llvm::GlobalValue::LinkOnceODRLinkage,
llvm::GlobalValue::HiddenVisibility,
llvm::GlobalValue::DefaultStorageClass,
};
const IRLinkage IRLinkage::InternalWeakODR = {
llvm::GlobalValue::WeakODRLinkage,
llvm::GlobalValue::HiddenVisibility,
llvm::GlobalValue::DefaultStorageClass,
};
const IRLinkage IRLinkage::Internal = {
llvm::GlobalValue::InternalLinkage,
llvm::GlobalValue::DefaultVisibility,
llvm::GlobalValue::DefaultStorageClass,
};
const IRLinkage IRLinkage::ExternalCommon = {
llvm::GlobalValue::CommonLinkage,
llvm::GlobalValue::DefaultVisibility,
llvm::GlobalValue::DLLExportStorageClass,
};
const IRLinkage IRLinkage::ExternalImport = {
llvm::GlobalValue::ExternalLinkage,
llvm::GlobalValue::DefaultVisibility,
llvm::GlobalValue::DLLImportStorageClass,
};
const IRLinkage IRLinkage::ExternalWeakImport = {
llvm::GlobalValue::ExternalWeakLinkage,
llvm::GlobalValue::DefaultVisibility,
llvm::GlobalValue::DLLImportStorageClass,
};
const IRLinkage IRLinkage::ExternalExport = {
llvm::GlobalValue::ExternalLinkage,
llvm::GlobalValue::DefaultVisibility,
llvm::GlobalValue::DLLExportStorageClass,
};
bool swift::irgen::useDllStorage(const llvm::Triple &triple) {
return triple.isOSBinFormatCOFF() && !triple.isOSCygMing();
}
UniversalLinkageInfo::UniversalLinkageInfo(IRGenModule &IGM)
: UniversalLinkageInfo(IGM.Triple, IGM.IRGen.hasMultipleIGMs(),
IGM.IRGen.Opts.ForcePublicLinkage,
IGM.IRGen.Opts.InternalizeSymbols) {}
UniversalLinkageInfo::UniversalLinkageInfo(const llvm::Triple &triple,
bool hasMultipleIGMs,
bool forcePublicDecls,
bool isStaticLibrary)
: IsELFObject(triple.isOSBinFormatELF()),
IsMSVCEnvironment(triple.isWindowsMSVCEnvironment()),
UseDLLStorage(useDllStorage(triple)), Internalize(isStaticLibrary),
HasMultipleIGMs(hasMultipleIGMs), ForcePublicDecls(forcePublicDecls) {}
LinkEntity LinkEntity::forSILGlobalVariable(SILGlobalVariable *G,
IRGenModule &IGM) {
LinkEntity entity;
entity.Pointer = G;
entity.SecondaryPointer = nullptr;
auto kind = (G->isInitializedObject() && IGM.canMakeStaticObjectReadOnly(G->getLoweredType()) ?
Kind::ReadOnlyGlobalObject : Kind::SILGlobalVariable);
entity.Data = unsigned(kind) << KindShift;
return entity;
}
/// Mangle this entity into the given buffer.
void LinkEntity::mangle(ASTContext &Ctx, SmallVectorImpl<char> &buffer) const {
llvm::raw_svector_ostream stream(buffer);
mangle(Ctx, stream);
}
/// Mangle this entity into the given stream.
void LinkEntity::mangle(ASTContext &Ctx, raw_ostream &buffer) const {
std::string Result = mangleAsString(Ctx);
buffer.write(Result.data(), Result.size());
}
/// Mangle this entity as a std::string.
std::string LinkEntity::mangleAsString(ASTContext &Ctx) const {
IRGenMangler mangler(Ctx);
switch (getKind()) {
case Kind::DispatchThunk: {
auto *func = cast<FuncDecl>(getDecl());
return mangler.mangleDispatchThunk(func);
}
case Kind::DispatchThunkDerivative: {
auto *func = cast<AbstractFunctionDecl>(getDecl());
auto *derivativeId = getAutoDiffDerivativeFunctionIdentifier();
return mangler.mangleDerivativeDispatchThunk(func, derivativeId);
}
case Kind::DispatchThunkInitializer: {
auto *ctor = cast<ConstructorDecl>(getDecl());
return mangler.mangleConstructorDispatchThunk(ctor,
/*isAllocating=*/false);
}
case Kind::DispatchThunkAllocator: {
auto *ctor = cast<ConstructorDecl>(getDecl());
return mangler.mangleConstructorDispatchThunk(ctor,
/*isAllocating=*/true);
}
case Kind::MethodDescriptor: {
auto *func = cast<FuncDecl>(getDecl());
return mangler.mangleMethodDescriptor(func);
}
case Kind::MethodDescriptorDerivative: {
auto *func = cast<AbstractFunctionDecl>(getDecl());
auto *derivativeId = getAutoDiffDerivativeFunctionIdentifier();
return mangler.mangleDerivativeMethodDescriptor(func, derivativeId);
}
case Kind::MethodDescriptorInitializer: {
auto *ctor = cast<ConstructorDecl>(getDecl());
return mangler.mangleConstructorMethodDescriptor(ctor,
/*isAllocating=*/false);
}
case Kind::MethodDescriptorAllocator: {
auto *ctor = cast<ConstructorDecl>(getDecl());
return mangler.mangleConstructorMethodDescriptor(ctor,
/*isAllocating=*/true);
}
case Kind::MethodLookupFunction: {
auto *classDecl = cast<ClassDecl>(getDecl());
return mangler.mangleMethodLookupFunction(classDecl);
}
case Kind::ValueWitness:
return mangler.mangleValueWitness(getType(), getValueWitness());
case Kind::ValueWitnessTable:
return mangler.mangleValueWitnessTable(getType());
case Kind::TypeMetadataAccessFunction:
return mangler.mangleTypeMetadataAccessFunction(getType());
case Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
return mangler.mangleCanonicalSpecializedGenericTypeMetadataAccessFunction(
getType());
case Kind::TypeMetadataLazyCacheVariable:
return mangler.mangleTypeMetadataLazyCacheVariable(getType());
case Kind::TypeMetadataDemanglingCacheVariable:
return mangler.mangleTypeMetadataDemanglingCacheVariable(getType());
case Kind::TypeMetadataInstantiationCache:
return mangler.mangleTypeMetadataInstantiationCache(
cast<NominalTypeDecl>(getDecl()));
case Kind::TypeMetadataInstantiationFunction:
return mangler.mangleTypeMetadataInstantiationFunction(
cast<NominalTypeDecl>(getDecl()));
case Kind::TypeMetadataSingletonInitializationCache:
return mangler.mangleTypeMetadataSingletonInitializationCache(
cast<NominalTypeDecl>(getDecl()));
case Kind::TypeMetadataCompletionFunction:
return mangler.mangleTypeMetadataCompletionFunction(
cast<NominalTypeDecl>(getDecl()));
case Kind::TypeMetadata:
switch (getMetadataAddress()) {
case TypeMetadataAddress::FullMetadata:
return mangler.mangleTypeFullMetadataFull(getType());
case TypeMetadataAddress::AddressPoint:
return mangler.mangleTypeMetadataFull(getType());
}
llvm_unreachable("invalid metadata address");
case Kind::NoncanonicalSpecializedGenericTypeMetadata:
return mangler.mangleNoncanonicalTypeMetadata(getType());
case Kind::CanonicalPrespecializedGenericTypeCachingOnceToken:
return mangler.mangleCanonicalPrespecializedGenericTypeCachingOnceToken(
cast<NominalTypeDecl>(getDecl()));
case Kind::NoncanonicalSpecializedGenericTypeMetadataCacheVariable:
return mangler.mangleNoncanonicalSpecializedGenericTypeMetadataCache(getType());
case Kind::TypeMetadataPattern:
return mangler.mangleTypeMetadataPattern(
cast<NominalTypeDecl>(getDecl()));
case Kind::SwiftMetaclassStub:
return mangler.mangleClassMetaClass(cast<ClassDecl>(getDecl()));
case Kind::CanonicalSpecializedGenericSwiftMetaclassStub:
return mangler.mangleSpecializedGenericClassMetaClass(getType());
case Kind::ObjCMetadataUpdateFunction:
return mangler.mangleObjCMetadataUpdateFunction(cast<ClassDecl>(getDecl()));
case Kind::ObjCResilientClassStub:
switch (getMetadataAddress()) {
case TypeMetadataAddress::FullMetadata:
return mangler.mangleFullObjCResilientClassStub(cast<ClassDecl>(getDecl()));
case TypeMetadataAddress::AddressPoint:
return mangler.mangleObjCResilientClassStub(cast<ClassDecl>(getDecl()));
}
llvm_unreachable("invalid metadata address");
case Kind::ClassMetadataBaseOffset: // class metadata base offset
return mangler.mangleClassMetadataBaseOffset(cast<ClassDecl>(getDecl()));
case Kind::NominalTypeDescriptor:
return mangler.mangleNominalTypeDescriptor(
cast<NominalTypeDecl>(getDecl()));
case Kind::NominalTypeDescriptorRecord:
return mangler.mangleNominalTypeDescriptorRecord(
cast<NominalTypeDecl>(getDecl()));
case Kind::OpaqueTypeDescriptor:
return mangler.mangleOpaqueTypeDescriptor(cast<OpaqueTypeDecl>(getDecl()));
case Kind::OpaqueTypeDescriptorRecord:
return mangler.mangleOpaqueTypeDescriptorRecord(
cast<OpaqueTypeDecl>(getDecl()));
case Kind::OpaqueTypeDescriptorAccessor:
return mangler.mangleOpaqueTypeDescriptorAccessor(
cast<OpaqueTypeDecl>(getDecl()));
case Kind::OpaqueTypeDescriptorAccessorImpl:
return mangler.mangleOpaqueTypeDescriptorAccessorImpl(
cast<OpaqueTypeDecl>(getDecl()));
case Kind::OpaqueTypeDescriptorAccessorKey:
return mangler.mangleOpaqueTypeDescriptorAccessorKey(
cast<OpaqueTypeDecl>(getDecl()));
case Kind::OpaqueTypeDescriptorAccessorVar:
return mangler.mangleOpaqueTypeDescriptorAccessorVar(
cast<OpaqueTypeDecl>(getDecl()));
case Kind::PropertyDescriptor:
return mangler.manglePropertyDescriptor(
cast<AbstractStorageDecl>(getDecl()));
case Kind::ModuleDescriptor:
return mangler.mangleModuleDescriptor(cast<ModuleDecl>(getDecl()));
case Kind::ExtensionDescriptor:
return mangler.mangleExtensionDescriptor(getExtension());
case Kind::AnonymousDescriptor:
return mangler.mangleAnonymousDescriptor(getAnonymousDeclContext());
case Kind::ProtocolDescriptor:
return mangler.mangleProtocolDescriptor(cast<ProtocolDecl>(getDecl()));
case Kind::ProtocolDescriptorRecord:
return mangler.mangleProtocolDescriptorRecord(cast<ProtocolDecl>(getDecl()));
case Kind::ProtocolRequirementsBaseDescriptor:
return mangler.mangleProtocolRequirementsBaseDescriptor(
cast<ProtocolDecl>(getDecl()));
case Kind::AssociatedTypeDescriptor:
return mangler.mangleAssociatedTypeDescriptor(
cast<AssociatedTypeDecl>(getDecl()));
case Kind::AssociatedConformanceDescriptor: {
auto assocConformance = getAssociatedConformance();
return mangler.mangleAssociatedConformanceDescriptor(
cast<ProtocolDecl>(getDecl()),
assocConformance.first,
assocConformance.second);
}
case Kind::BaseConformanceDescriptor: {
auto assocConformance = getAssociatedConformance();
return mangler.mangleBaseConformanceDescriptor(
cast<ProtocolDecl>(getDecl()),
assocConformance.second);
}
case Kind::DefaultAssociatedConformanceAccessor: {
auto assocConformance = getAssociatedConformance();
return mangler.mangleDefaultAssociatedConformanceAccessor(
cast<ProtocolDecl>(getDecl()),
assocConformance.first,
assocConformance.second);
}
case Kind::ProtocolConformanceDescriptor:
return mangler.mangleProtocolConformanceDescriptor(
getRootProtocolConformance());
case Kind::ProtocolConformanceDescriptorRecord:
return mangler.mangleProtocolConformanceDescriptorRecord(
getRootProtocolConformance());
case Kind::EnumCase:
return mangler.mangleEnumCase(getDecl());
case Kind::FieldOffset:
return mangler.mangleFieldOffset(getDecl());
case Kind::ProtocolWitnessTable:
return mangler.mangleWitnessTable(getProtocolConformance());
case Kind::GenericProtocolWitnessTableInstantiationFunction:
return mangler.mangleGenericProtocolWitnessTableInstantiationFunction(
getProtocolConformance());
case Kind::ProtocolWitnessTablePattern:
return mangler.mangleProtocolWitnessTablePattern(getProtocolConformance());
case Kind::ProtocolWitnessTableLazyAccessFunction:
return mangler.mangleProtocolWitnessTableLazyAccessFunction(getType(),
getProtocolConformance());
case Kind::ProtocolWitnessTableLazyCacheVariable:
return mangler.mangleProtocolWitnessTableLazyCacheVariable(getType(),
getProtocolConformance());
case Kind::AssociatedTypeWitnessTableAccessFunction: {
auto assocConf = getAssociatedConformance();
if (isa<GenericTypeParamType>(assocConf.first)) {
return mangler.mangleBaseWitnessTableAccessFunction(
getProtocolConformance(), assocConf.second);
}
return mangler.mangleAssociatedTypeWitnessTableAccessFunction(
getProtocolConformance(), assocConf.first, assocConf.second);
}
case Kind::CoroutineContinuationPrototype:
return mangler.mangleCoroutineContinuationPrototype(
cast<SILFunctionType>(getType()));
// An Objective-C class reference reference. The symbol is private, so
// the mangling is unimportant; it should just be readable in LLVM IR.
case Kind::ObjCClassRef: {
llvm::SmallString<64> tempBuffer;
StringRef name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(tempBuffer);
std::string Result("OBJC_CLASS_REF_$_");
Result.append(name.data(), name.size());
return Result;
}
// An Objective-C class reference; not a swift mangling.
case Kind::ObjCClass: {
llvm::SmallString<64> TempBuffer;
StringRef Name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(TempBuffer);
std::string Result("OBJC_CLASS_$_");
Result.append(Name.data(), Name.size());
return Result;
}
// An Objective-C metaclass reference; not a swift mangling.
case Kind::ObjCMetaclass: {
llvm::SmallString<64> TempBuffer;
StringRef Name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(TempBuffer);
std::string Result("OBJC_METACLASS_$_");
Result.append(Name.data(), Name.size());
return Result;
}
case Kind::SILFunction: {
auto asmName = getSILFunction()->asmName();
if (!asmName.empty())
return asmName.str();
std::string Result(getSILFunction()->getName());
if (isDynamicallyReplaceable()) {
Result.append("TI");
}
return Result;
}
case Kind::DynamicallyReplaceableFunctionImpl: {
assert(isa<AbstractFunctionDecl>(getDecl()));
std::string Result;
if (auto *Constructor = dyn_cast<ConstructorDecl>(getDecl())) {
Result = mangler.mangleConstructorEntity(Constructor, isAllocator());
} else {
Result = mangler.mangleEntity(getDecl());
}
Result.append("TI");
return Result;
}
case Kind::DynamicallyReplaceableFunctionVariable: {
std::string Result(getSILFunction()->getName());
Result.append("TX");
return Result;
}
case Kind::DynamicallyReplaceableFunctionKey: {
std::string Result(getSILFunction()->getName());
Result.append("Tx");
return Result;
}
case Kind::DynamicallyReplaceableFunctionVariableAST: {
assert(isa<AbstractFunctionDecl>(getDecl()));
std::string Result;
if (auto *Constructor = dyn_cast<ConstructorDecl>(getDecl())) {
Result =
mangler.mangleConstructorEntity(Constructor, isAllocator());
} else {
Result = mangler.mangleEntity(getDecl());
}
Result.append("TX");
return Result;
}
case Kind::DynamicallyReplaceableFunctionKeyAST: {
assert(isa<AbstractFunctionDecl>(getDecl()));
std::string Result;
if (auto *Constructor = dyn_cast<ConstructorDecl>(getDecl())) {
Result =
mangler.mangleConstructorEntity(Constructor, isAllocator());
} else {
Result = mangler.mangleEntity(getDecl());
}
Result.append("Tx");
return Result;
}
case Kind::SILGlobalVariable: {
auto asmName = getSILGlobalVariable()->asmName();
if (!asmName.empty())
return asmName.str();
return getSILGlobalVariable()->getName().str();
}
case Kind::ReadOnlyGlobalObject:
return getSILGlobalVariable()->getName().str() + "r";
case Kind::ReflectionBuiltinDescriptor:
return mangler.mangleReflectionBuiltinDescriptor(getType());
case Kind::ReflectionFieldDescriptor:
return mangler.mangleReflectionFieldDescriptor(getType());
case Kind::ReflectionAssociatedTypeDescriptor:
return mangler.mangleReflectionAssociatedTypeDescriptor(
getProtocolConformance());
case Kind::DifferentiabilityWitness:
return mangler.mangleSILDifferentiabilityWitness(
getSILDifferentiabilityWitness()->getOriginalFunction()->getName(),
getSILDifferentiabilityWitness()->getKind(),
getSILDifferentiabilityWitness()->getConfig());
case Kind::AsyncFunctionPointer:
case Kind::DispatchThunkAsyncFunctionPointer:
case Kind::DispatchThunkInitializerAsyncFunctionPointer:
case Kind::DispatchThunkAllocatorAsyncFunctionPointer:
case Kind::PartialApplyForwarderAsyncFunctionPointer:
case Kind::DistributedAccessorAsyncPointer: {
std::string Result(getUnderlyingEntityForAsyncFunctionPointer()
.mangleAsString(Ctx));
Result.append("Tu");
return Result;
}
case Kind::DistributedThunkAsyncFunctionPointer: {
std::string Result = getSILDeclRef().mangle();
Result.append("TE");
Result.append("Tu");
return Result;
}
case Kind::KnownAsyncFunctionPointer: {
std::string Result(static_cast<char *>(Pointer));
Result.append("Tu");
return Result;
}
case Kind::AsyncFunctionPointerAST: {
std::string Result = getSILDeclRef().mangle();
Result.append("Tu");
return Result;
}
case Kind::PartialApplyForwarder: {
std::string Result;
Result = std::string(static_cast<llvm::Function *>(Pointer)->getName());
return Result;
}
case Kind::DistributedAccessor: {
std::string Result = getSILDeclRef().mangle();
Result.append("TF");
return Result;
}
case Kind::AccessibleFunctionRecord: {
auto DC = getSILFunction()->getDeclContext();
auto thunk = dyn_cast<AbstractFunctionDecl>(DC);
if (thunk && thunk->isDistributedThunk()) {
IRGenMangler mangler(Ctx);
return mangler.mangleDistributedThunkRecord(thunk);
}
// Otherwise use the default mangling: just the function name
std::string Result(getSILFunction()->getName());
Result.append("HF");
return Result;
}
case Kind::ExtendedExistentialTypeShape: {
auto genSig = getExtendedExistentialTypeShapeGenSig();
auto existentialType = getExtendedExistentialTypeShapeType();
auto isUnique = isExtendedExistentialTypeShapeUnique();
return mangler.mangleExtendedExistentialTypeShapeSymbol(
genSig, existentialType, isUnique);
}
case Kind::CoroFunctionPointer:
case Kind::DispatchThunkCoroFunctionPointer:
case Kind::DispatchThunkInitializerCoroFunctionPointer:
case Kind::DispatchThunkAllocatorCoroFunctionPointer:
case Kind::PartialApplyForwarderCoroFunctionPointer:
case Kind::DistributedAccessorCoroFunctionPointer: {
std::string Result(
getUnderlyingEntityForCoroFunctionPointer().mangleAsString(Ctx));
Result.append("Twc");
return Result;
}
case Kind::DistributedThunkCoroFunctionPointer: {
std::string Result = getSILDeclRef().mangle();
Result.append("TE");
Result.append("Twc");
return Result;
}
case Kind::CoroFunctionPointerAST: {
std::string Result = getSILDeclRef().mangle();
Result.append("Twc");
return Result;
}
case Kind::KnownCoroFunctionPointer: {
std::string Result(static_cast<char *>(Pointer));
Result.append("Twc");
return Result;
}
case Kind::CoroAllocator: {
switch (getCoroAllocatorKind()) {
case CoroAllocatorKind::Stack:
llvm::report_fatal_error("attempting to mangle the coro stack allocator");
case CoroAllocatorKind::Async:
return "_swift_coro_async_allocator";
case CoroAllocatorKind::Malloc:
return "_swift_coro_malloc_allocator";
case CoroAllocatorKind::TypedMalloc:
return "_swift_coro_typed_malloc_allocator";
}
}
}
llvm_unreachable("bad entity kind!");
}
SILDeclRef::Kind LinkEntity::getSILDeclRefKind() const {
switch (getKind()) {
case Kind::DispatchThunk:
case Kind::MethodDescriptor:
case Kind::DistributedAccessor:
return SILDeclRef::Kind::Func;
case Kind::DispatchThunkInitializer:
case Kind::MethodDescriptorInitializer:
return SILDeclRef::Kind::Initializer;
case Kind::MethodDescriptorAllocator:
case Kind::DispatchThunkAllocator:
return SILDeclRef::Kind::Allocator;
case Kind::DistributedThunkAsyncFunctionPointer:
case Kind::AsyncFunctionPointerAST:
case Kind::CoroFunctionPointerAST:
case Kind::DistributedThunkCoroFunctionPointer:
return static_cast<SILDeclRef::Kind>(
reinterpret_cast<uintptr_t>(SecondaryPointer));
default:
llvm_unreachable("unhandled kind");
}
}
SILDeclRef LinkEntity::getSILDeclRef() const {
auto ref = SILDeclRef(const_cast<ValueDecl *>(getDecl()), getSILDeclRefKind());
if (getKind() == Kind::DistributedAccessor)
return ref.asDistributed();
return ref;
}
static bool isLazyEmissionOfPublicSymbolInMultipleModulesPossible(CanType ty) {
// In embedded existenitals mode we generate lazy public metadata on demand
// which makes it non unique.
auto &langOpts = ty->getASTContext().LangOpts;
auto isEmbeddedWithExistentials = langOpts.hasFeature(Feature::Embedded) &&
langOpts.hasFeature(Feature::EmbeddedExistentials);
if (isEmbeddedWithExistentials) {
if (auto nominal = ty->getAnyNominal()) {
if (SILDeclRef::declHasNonUniqueDefinition(nominal)) {
return true;
}
} else {
return true;
}
}
return false;
}
SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
// For when `this` is a protocol conformance of some kind.
auto getLinkageAsConformance = [&] {
return getLinkageForProtocolConformance(
getProtocolConformance()->getRootConformance(), forDefinition);
};
switch (getKind()) {
case Kind::DispatchThunk:
case Kind::DispatchThunkDerivative:
case Kind::DispatchThunkInitializer:
case Kind::DispatchThunkAllocator:
case Kind::MethodDescriptor:
case Kind::MethodDescriptorDerivative:
case Kind::MethodDescriptorInitializer:
case Kind::MethodDescriptorAllocator: {
auto *decl = getDecl();
// Protocol requirements don't have their own access control
if (auto *proto = dyn_cast<ProtocolDecl>(decl->getDeclContext()))
decl = proto;
return getSILLinkage(getDeclLinkage(decl), forDefinition);
}
// Most type metadata depend on the formal linkage of their type.
case Kind::ValueWitnessTable: {
auto type = getType();
// In embedded existenitals mode we generate lazy public metadata on demand
// which makes it non unique.
if (isLazyEmissionOfPublicSymbolInMultipleModulesPossible(type))
return SILLinkage::Shared;
// Builtin types, (), () -> () and so on are in the runtime.
if (!type.getAnyNominal())
return getSILLinkage(FormalLinkage::PublicUnique, forDefinition);
// Imported types.
if (isAccessorLazilyGenerated(getTypeMetadataAccessStrategy(type)))
return SILLinkage::Shared;
// Everything else is only referenced inside its module.
return SILLinkage::Private;
}
case Kind::ObjCMetadataUpdateFunction:
case Kind::TypeMetadataInstantiationCache:
case Kind::TypeMetadataInstantiationFunction:
case Kind::TypeMetadataSingletonInitializationCache:
case Kind::TypeMetadataCompletionFunction:
case Kind::TypeMetadataPattern:
return SILLinkage::Private;
case Kind::TypeMetadataLazyCacheVariable: {
auto type = getType();
// Imported types, non-primitive structural types.
if (isAccessorLazilyGenerated(getTypeMetadataAccessStrategy(type)))
return SILLinkage::Shared;
// Everything else is only referenced inside its module.
return SILLinkage::Private;
}
case Kind::TypeMetadataDemanglingCacheVariable:
return SILLinkage::Shared;
case Kind::TypeMetadata: {
if (isForcedShared())
return SILLinkage::Shared;
// In embedded existenitals mode we generate lazy public metadata on demand
// which makes it non unique.
if (isLazyEmissionOfPublicSymbolInMultipleModulesPossible(getType()))
return SILLinkage::Shared;
auto *nominal = getType().getAnyNominal();
switch (getMetadataAddress()) {
case TypeMetadataAddress::FullMetadata:
// For imported types, the full metadata object is a candidate
// for uniquing.
if (getDeclLinkage(nominal) == FormalLinkage::PublicNonUnique)
return SILLinkage::Shared;
// Prespecialization of the same generic metadata may be requested
// multiple times within the same module, so it needs to be uniqued.
if (nominal->isGenericContext())
return SILLinkage::Shared;
// The full metadata object is private to the containing module.
return SILLinkage::Private;
case TypeMetadataAddress::AddressPoint: {
return getSILLinkage(nominal
? getDeclLinkage(nominal)
: FormalLinkage::PublicUnique,
forDefinition);
}
}
llvm_unreachable("bad kind");
}
case Kind::NoncanonicalSpecializedGenericTypeMetadata:
case Kind::NoncanonicalSpecializedGenericTypeMetadataCacheVariable:
// Prespecialization of the same non-canonical generic metadata may be
// requested multiple times, so it needs to be uniqued.
return SILLinkage::Shared;
// ...but we don't actually expose individual value witnesses (right now).
case Kind::ValueWitness: {
auto *nominal = getType().getAnyNominal();
if (nominal && getDeclLinkage(nominal) == FormalLinkage::PublicNonUnique)
return SILLinkage::Shared;
assert(forDefinition);
return SILLinkage::Private;
}
case Kind::TypeMetadataAccessFunction:
switch (getTypeMetadataAccessStrategy(getType())) {
case MetadataAccessStrategy::PublicUniqueAccessor:
return getSILLinkage(FormalLinkage::PublicUnique, forDefinition);
case MetadataAccessStrategy::PackageUniqueAccessor:
return getSILLinkage(FormalLinkage::PackageUnique, forDefinition);
case MetadataAccessStrategy::HiddenUniqueAccessor:
return getSILLinkage(FormalLinkage::HiddenUnique, forDefinition);
case MetadataAccessStrategy::PrivateAccessor:
return getSILLinkage(FormalLinkage::Private, forDefinition);
case MetadataAccessStrategy::ForeignAccessor:
case MetadataAccessStrategy::NonUniqueAccessor:
return SILLinkage::Shared;
}
llvm_unreachable("bad metadata access kind");
case Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
return SILLinkage::Shared;
case Kind::ObjCClassRef:
return SILLinkage::Private;
// Continuation prototypes need to be external or else LLVM will fret.
case Kind::CoroutineContinuationPrototype:
return SILLinkage::PublicExternal;
case Kind::ObjCResilientClassStub: {
switch (getMetadataAddress()) {
case TypeMetadataAddress::FullMetadata:
// The full class stub object is private to the containing module,
// except for foreign types.
return SILLinkage::Private;
case TypeMetadataAddress::AddressPoint: {
auto *classDecl = cast<ClassDecl>(getDecl());
return getSILLinkage(getDeclLinkage(classDecl),
forDefinition);
}
}
llvm_unreachable("invalid metadata address");
}
case Kind::EnumCase: {
auto *elementDecl = cast<EnumElementDecl>(getDecl());
return getSILLinkage(getDeclLinkage(elementDecl), forDefinition);
}
case Kind::FieldOffset: {
auto *varDecl = cast<VarDecl>(getDecl());
auto linkage = getDeclLinkage(varDecl);
// Classes with resilient storage don't expose field offset symbols.
auto implContext = varDecl->getDeclContext()->getImplementedObjCContext();
if (cast<ClassDecl>(implContext)->isResilient()) {
assert(linkage != FormalLinkage::PublicNonUnique &&
"Cannot have a resilient class with non-unique linkage");
if (linkage == FormalLinkage::PublicUnique ||
linkage == FormalLinkage::PackageUnique)
linkage = FormalLinkage::HiddenUnique;
}
return getSILLinkage(linkage, forDefinition);
}
case Kind::PropertyDescriptor: {
// Return the linkage of the getter, which may be more permissive than the
// property itself (for instance, with a private/internal property whose
// accessor is @inlinable or @usableFromInline)
auto getterDecl = cast<AbstractStorageDecl>(getDecl())
->getOpaqueAccessor(AccessorKind::Get);
return getSILLinkage(getDeclLinkage(getterDecl), forDefinition);
}
case Kind::OpaqueTypeDescriptor: {
auto *opaqueType = cast<OpaqueTypeDecl>(getDecl());
// With conditionally available substitutions, the opaque result type
// descriptor has to be emitted into a client module when associated with
// always-emitted-into-client declaration which means it's linkage
// has to be "shared".
//
// If we don't have conditionally available substitutions, we won't emit
// the descriptor at all, but still make sure we report "shared" linkage
// so that TBD files don't include a bogus symbol.
auto *srcDecl = opaqueType->getNamingDecl();
if (srcDecl->isAlwaysEmittedIntoClient())
return SILLinkage::Shared;
return getSILLinkage(getDeclLinkage(opaqueType), forDefinition);
}
case Kind::AssociatedConformanceDescriptor:
case Kind::BaseConformanceDescriptor:
case Kind::ObjCClass:
case Kind::ObjCMetaclass:
case Kind::SwiftMetaclassStub:
case Kind::NominalTypeDescriptor:
case Kind::NominalTypeDescriptorRecord:
case Kind::ClassMetadataBaseOffset:
case Kind::ProtocolDescriptor:
case Kind::ProtocolDescriptorRecord:
case Kind::ProtocolRequirementsBaseDescriptor:
case Kind::MethodLookupFunction:
case Kind::OpaqueTypeDescriptorRecord:
case Kind::OpaqueTypeDescriptorAccessor:
case Kind::OpaqueTypeDescriptorAccessorImpl:
case Kind::OpaqueTypeDescriptorAccessorKey:
case Kind::OpaqueTypeDescriptorAccessorVar:
return getSILLinkage(getDeclLinkage(getDecl()), forDefinition);
case Kind::CanonicalSpecializedGenericSwiftMetaclassStub:
// Prespecialization of the same generic class' metaclass may be requested
// multiple times within the same module, so it needs to be uniqued.
return SILLinkage::Shared;
case Kind::AssociatedTypeDescriptor:
return getSILLinkage(getDeclLinkage(getAssociatedType()->getProtocol()),
forDefinition);
case Kind::ProtocolWitnessTable:
case Kind::ProtocolConformanceDescriptor:
case Kind::ProtocolConformanceDescriptorRecord:
return getLinkageForProtocolConformance(getRootProtocolConformance(),
forDefinition);
case Kind::ProtocolWitnessTablePattern:
if (getLinkageAsConformance() == SILLinkage::Shared)
return SILLinkage::Shared;
return SILLinkage::Private;
case Kind::ProtocolWitnessTableLazyAccessFunction:
case Kind::ProtocolWitnessTableLazyCacheVariable: {
TypeDecl *typeDecl = nullptr;
if (auto *otat = getType()->getAs<OpaqueTypeArchetypeType>()) {
typeDecl = otat->getDecl();
} else {
typeDecl = getProtocolConformance()->getDeclContext()
->getSelfNominalTypeDecl();
}
assert(typeDecl);
if (getDeclLinkage(typeDecl) == FormalLinkage::Private ||
getLinkageAsConformance() == SILLinkage::Private) {
return SILLinkage::Private;
} else {
return SILLinkage::Shared;
}
}
case Kind::AssociatedTypeWitnessTableAccessFunction:
case Kind::DefaultAssociatedConformanceAccessor:
case Kind::GenericProtocolWitnessTableInstantiationFunction:
case Kind::CanonicalPrespecializedGenericTypeCachingOnceToken:
return SILLinkage::Private;
case Kind::DynamicallyReplaceableFunctionKey:
return getSILFunction()->getLinkage();
case Kind::SILFunction:
return getSILFunction()->getEffectiveSymbolLinkage();
case Kind::AsyncFunctionPointerAST:
case Kind::DistributedThunkAsyncFunctionPointer:
case Kind::CoroFunctionPointerAST:
case Kind::DistributedThunkCoroFunctionPointer:
return getSILLinkage(getDeclLinkage(getDecl()), forDefinition);
case Kind::DynamicallyReplaceableFunctionImpl:
case Kind::DynamicallyReplaceableFunctionKeyAST:
return getSILLinkage(getDeclLinkage(getDecl()), forDefinition);
case Kind::DynamicallyReplaceableFunctionVariable:
return getSILFunction()->getEffectiveSymbolLinkage();
case Kind::DynamicallyReplaceableFunctionVariableAST:
return getSILLinkage(getDeclLinkage(getDecl()), forDefinition);
case Kind::SILGlobalVariable:
case Kind::ReadOnlyGlobalObject:
return getSILGlobalVariable()->getLinkage();
case Kind::ReflectionBuiltinDescriptor:
case Kind::ReflectionFieldDescriptor: {
// Reflection descriptors for imported types have shared linkage,
// since we may emit them in other TUs in the same module.
if (auto *nominal = getType().getAnyNominal())
if (getDeclLinkage(nominal) == FormalLinkage::PublicNonUnique)
return SILLinkage::Shared;
return SILLinkage::Private;
}
case Kind::ReflectionAssociatedTypeDescriptor:
if (getLinkageAsConformance() == SILLinkage::Shared)
return SILLinkage::Shared;
return SILLinkage::Private;
case Kind::ModuleDescriptor:
case Kind::ExtensionDescriptor:
case Kind::AnonymousDescriptor:
return SILLinkage::Shared;
case Kind::DifferentiabilityWitness:
return getSILDifferentiabilityWitness()->getLinkage();
case Kind::AsyncFunctionPointer:
case Kind::DispatchThunkAsyncFunctionPointer:
case Kind::DispatchThunkInitializerAsyncFunctionPointer:
case Kind::DispatchThunkAllocatorAsyncFunctionPointer:
case Kind::PartialApplyForwarderAsyncFunctionPointer:
case Kind::DistributedAccessorAsyncPointer:
return getUnderlyingEntityForAsyncFunctionPointer()
.getLinkage(forDefinition);
case Kind::KnownAsyncFunctionPointer:
case Kind::KnownCoroFunctionPointer:
return SILLinkage::PublicExternal;
case Kind::PartialApplyForwarder:
return SILLinkage::Private;
case Kind::DistributedAccessor:
case Kind::AccessibleFunctionRecord:
return SILLinkage::Shared;
case Kind::ExtendedExistentialTypeShape:
return (isExtendedExistentialTypeShapeShared()
? SILLinkage::Shared : SILLinkage::Private);
case Kind::CoroFunctionPointer:
case Kind::DispatchThunkCoroFunctionPointer:
case Kind::DispatchThunkInitializerCoroFunctionPointer:
case Kind::DispatchThunkAllocatorCoroFunctionPointer:
case Kind::PartialApplyForwarderCoroFunctionPointer:
case Kind::DistributedAccessorCoroFunctionPointer:
return getUnderlyingEntityForCoroFunctionPointer().getLinkage(
forDefinition);
return getSILLinkage(getDeclLinkage(getDecl()), forDefinition);
case Kind::CoroAllocator:
return SILLinkage::Shared;
}
llvm_unreachable("bad link entity kind");
}
bool LinkEntity::isContextDescriptor() const {
switch (getKind()) {
case Kind::ModuleDescriptor:
case Kind::ExtensionDescriptor:
case Kind::AnonymousDescriptor:
case Kind::NominalTypeDescriptor:
case Kind::ProtocolDescriptor:
case Kind::OpaqueTypeDescriptor:
return true;
case Kind::AsyncFunctionPointer:
case Kind::AsyncFunctionPointerAST:
case Kind::DistributedThunkAsyncFunctionPointer:
case Kind::PropertyDescriptor:
case Kind::DispatchThunk:
case Kind::DispatchThunkDerivative:
case Kind::DispatchThunkInitializer:
case Kind::DispatchThunkAllocator:
case Kind::DispatchThunkAsyncFunctionPointer:
case Kind::DispatchThunkInitializerAsyncFunctionPointer:
case Kind::DispatchThunkAllocatorAsyncFunctionPointer:
case Kind::PartialApplyForwarderAsyncFunctionPointer:
case Kind::DistributedAccessorAsyncPointer:
case Kind::MethodDescriptor:
case Kind::MethodDescriptorDerivative:
case Kind::MethodDescriptorInitializer:
case Kind::MethodDescriptorAllocator:
case Kind::MethodLookupFunction:
case Kind::EnumCase:
case Kind::FieldOffset:
case Kind::ObjCClass:
case Kind::ObjCClassRef:
case Kind::ObjCMetaclass:
case Kind::ObjCMetadataUpdateFunction:
case Kind::ObjCResilientClassStub:
case Kind::SwiftMetaclassStub:
case Kind::ClassMetadataBaseOffset:
case Kind::TypeMetadataPattern:
case Kind::TypeMetadataInstantiationCache:
case Kind::TypeMetadataInstantiationFunction:
case Kind::TypeMetadataSingletonInitializationCache:
case Kind::TypeMetadataCompletionFunction:
case Kind::NominalTypeDescriptorRecord:
case Kind::OpaqueTypeDescriptorRecord:
case Kind::ProtocolDescriptorRecord:
case Kind::ProtocolRequirementsBaseDescriptor:
case Kind::AssociatedTypeDescriptor:
case Kind::AssociatedConformanceDescriptor:
case Kind::BaseConformanceDescriptor:
case Kind::DefaultAssociatedConformanceAccessor:
case Kind::SILFunction:
case Kind::SILGlobalVariable:
case Kind::ReadOnlyGlobalObject:
case Kind::ProtocolWitnessTable:
case Kind::ProtocolWitnessTablePattern:
case Kind::GenericProtocolWitnessTableInstantiationFunction:
case Kind::AssociatedTypeWitnessTableAccessFunction:
case Kind::ReflectionAssociatedTypeDescriptor:
case Kind::ProtocolConformanceDescriptor:
case Kind::ProtocolConformanceDescriptorRecord:
case Kind::ProtocolWitnessTableLazyAccessFunction:
case Kind::ProtocolWitnessTableLazyCacheVariable:
case Kind::ValueWitness:
case Kind::ValueWitnessTable:
case Kind::TypeMetadata:
case Kind::TypeMetadataAccessFunction:
case Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
case Kind::TypeMetadataLazyCacheVariable:
case Kind::TypeMetadataDemanglingCacheVariable:
case Kind::ReflectionBuiltinDescriptor:
case Kind::ReflectionFieldDescriptor:
case Kind::CoroutineContinuationPrototype:
case Kind::DynamicallyReplaceableFunctionVariableAST:
case Kind::DynamicallyReplaceableFunctionKeyAST:
case Kind::DynamicallyReplaceableFunctionImpl:
case Kind::DynamicallyReplaceableFunctionKey:
case Kind::DynamicallyReplaceableFunctionVariable:
case Kind::OpaqueTypeDescriptorAccessor:
case Kind::OpaqueTypeDescriptorAccessorImpl:
case Kind::OpaqueTypeDescriptorAccessorKey:
case Kind::OpaqueTypeDescriptorAccessorVar:
case Kind::DifferentiabilityWitness:
case Kind::CanonicalSpecializedGenericSwiftMetaclassStub:
case Kind::NoncanonicalSpecializedGenericTypeMetadata:
case Kind::NoncanonicalSpecializedGenericTypeMetadataCacheVariable:
case Kind::CanonicalPrespecializedGenericTypeCachingOnceToken:
case Kind::PartialApplyForwarder:
case Kind::KnownAsyncFunctionPointer:
case Kind::DistributedAccessor:
case Kind::AccessibleFunctionRecord:
case Kind::ExtendedExistentialTypeShape:
case Kind::CoroFunctionPointer:
case Kind::DispatchThunkCoroFunctionPointer:
case Kind::DispatchThunkInitializerCoroFunctionPointer:
case Kind::DispatchThunkAllocatorCoroFunctionPointer:
case Kind::PartialApplyForwarderCoroFunctionPointer:
case Kind::DistributedAccessorCoroFunctionPointer:
case Kind::CoroFunctionPointerAST:
case Kind::DistributedThunkCoroFunctionPointer:
case Kind::KnownCoroFunctionPointer:
case Kind::CoroAllocator:
return false;
}
llvm_unreachable("invalid descriptor");
}
llvm::Type *LinkEntity::getDefaultDeclarationType(IRGenModule &IGM) const {
switch (getKind()) {
case Kind::ModuleDescriptor:
case Kind::ExtensionDescriptor:
case Kind::AnonymousDescriptor:
case Kind::NominalTypeDescriptor:
case Kind::NominalTypeDescriptorRecord:
case Kind::PropertyDescriptor:
return IGM.TypeContextDescriptorTy;
case Kind::OpaqueTypeDescriptor:
case Kind::OpaqueTypeDescriptorRecord:
return IGM.OpaqueTypeDescriptorTy;
case Kind::ProtocolDescriptor:
return IGM.ProtocolDescriptorStructTy;
case Kind::AssociatedTypeDescriptor:
case Kind::AssociatedConformanceDescriptor:
case Kind::BaseConformanceDescriptor:
case Kind::ProtocolDescriptorRecord:
case Kind::ProtocolRequirementsBaseDescriptor:
return IGM.ProtocolRequirementStructTy;
case Kind::ProtocolConformanceDescriptor:
case Kind::ProtocolConformanceDescriptorRecord:
return IGM.ProtocolConformanceDescriptorTy;
case Kind::ObjCClassRef:
return IGM.ObjCClassPtrTy;
case Kind::ObjCClass:
case Kind::ObjCMetaclass:
case Kind::SwiftMetaclassStub:
case Kind::CanonicalSpecializedGenericSwiftMetaclassStub:
return IGM.ObjCClassStructTy;
case Kind::TypeMetadataLazyCacheVariable:
case Kind::NoncanonicalSpecializedGenericTypeMetadataCacheVariable:
return IGM.TypeMetadataPtrTy;
case Kind::TypeMetadataDemanglingCacheVariable:
return llvm::StructType::get(IGM.Int32Ty, IGM.Int32Ty);
case Kind::TypeMetadataSingletonInitializationCache:
// TODO: put a cache variable on IGM
return llvm::StructType::get(IGM.getLLVMContext(),
{IGM.TypeMetadataPtrTy, IGM.Int8PtrTy});
case Kind::TypeMetadata:
case Kind::NoncanonicalSpecializedGenericTypeMetadata:
switch (getMetadataAddress()) {
case TypeMetadataAddress::FullMetadata: {
auto &langOpts = IGM.Context.LangOpts;
auto isEmbeddedWithExistentials = langOpts.hasFeature(Feature::Embedded) &&
langOpts.hasFeature(Feature::EmbeddedExistentials);
if (isEmbeddedWithExistentials) {
return IGM.EmbeddedExistentialsMetadataStructTy;
}
if (getType().getClassOrBoundGenericClass())
return IGM.FullHeapMetadataStructTy;
else
return IGM.FullTypeMetadataStructTy;
}
case TypeMetadataAddress::AddressPoint:
return IGM.TypeMetadataStructTy;
}
llvm_unreachable("invalid metadata address");
case Kind::TypeMetadataPattern:
// TODO: Use a real type?
return IGM.Int8Ty;
case Kind::ClassMetadataBaseOffset:
return IGM.ClassMetadataBaseOffsetTy;
case Kind::TypeMetadataInstantiationCache:
// TODO: put a cache variable on IGM
return llvm::ArrayType::get(IGM.Int8PtrTy,
NumGenericMetadataPrivateDataWords);
case Kind::ReflectionBuiltinDescriptor:
case Kind::ReflectionFieldDescriptor:
case Kind::ReflectionAssociatedTypeDescriptor:
return IGM.FieldDescriptorTy;
case Kind::ValueWitnessTable: // TODO: use ValueWitnessTableTy
case Kind::ProtocolWitnessTable:
case Kind::ProtocolWitnessTablePattern:
return IGM.WitnessTableTy;
case Kind::FieldOffset:
return IGM.SizeTy;
case Kind::EnumCase:
return IGM.Int32Ty;
case Kind::ProtocolWitnessTableLazyCacheVariable:
return IGM.WitnessTablePtrTy;
case Kind::SILFunction:
return IGM.PtrTy;
case Kind::MethodDescriptor:
case Kind::MethodDescriptorInitializer:
case Kind::MethodDescriptorAllocator:
case Kind::MethodDescriptorDerivative:
return IGM.MethodDescriptorStructTy;
case Kind::DynamicallyReplaceableFunctionKey:
case Kind::DynamicallyReplaceableFunctionKeyAST:
case Kind::OpaqueTypeDescriptorAccessorKey:
return IGM.DynamicReplacementKeyTy;
case Kind::DynamicallyReplaceableFunctionVariable:
case Kind::DynamicallyReplaceableFunctionVariableAST:
case Kind::OpaqueTypeDescriptorAccessorVar:
return IGM.DynamicReplacementLinkEntryTy;
case Kind::ObjCMetadataUpdateFunction:
return IGM.ObjCUpdateCallbackTy;
case Kind::ObjCResilientClassStub:
switch (getMetadataAddress()) {
case TypeMetadataAddress::FullMetadata:
return IGM.ObjCFullResilientClassStubTy;
case TypeMetadataAddress::AddressPoint:
return IGM.ObjCResilientClassStubTy;
}
llvm_unreachable("invalid metadata address");
case Kind::DifferentiabilityWitness:
return IGM.DifferentiabilityWitnessTy;
case Kind::CanonicalPrespecializedGenericTypeCachingOnceToken:
return IGM.OnceTy;
case Kind::AsyncFunctionPointer:
case Kind::DispatchThunkAsyncFunctionPointer:
case Kind::DispatchThunkInitializerAsyncFunctionPointer:
case Kind::DispatchThunkAllocatorAsyncFunctionPointer:
case Kind::DistributedThunkAsyncFunctionPointer:
case Kind::PartialApplyForwarderAsyncFunctionPointer:
case Kind::DistributedAccessorAsyncPointer:
case Kind::AsyncFunctionPointerAST:
case Kind::KnownAsyncFunctionPointer:
return IGM.AsyncFunctionPointerTy;
case Kind::PartialApplyForwarder:
return IGM.FunctionPtrTy;
case Kind::AccessibleFunctionRecord:
return IGM.AccessibleFunctionRecordTy;
case Kind::ExtendedExistentialTypeShape:
return IGM.RelativeAddressTy;
case Kind::CoroFunctionPointer:
case Kind::DispatchThunkCoroFunctionPointer:
case Kind::DispatchThunkInitializerCoroFunctionPointer:
case Kind::DispatchThunkAllocatorCoroFunctionPointer:
case Kind::PartialApplyForwarderCoroFunctionPointer:
case Kind::DistributedAccessorCoroFunctionPointer:
case Kind::CoroFunctionPointerAST:
case Kind::DistributedThunkCoroFunctionPointer:
case Kind::KnownCoroFunctionPointer:
return IGM.CoroFunctionPointerPtrTy;
case Kind::CoroAllocator:
return IGM.CoroAllocatorTy;
default:
llvm_unreachable("declaration LLVM type not specified");
}
}
Alignment LinkEntity::getAlignment(IRGenModule &IGM) const {
switch (getKind()) {
case Kind::ModuleDescriptor:
case Kind::ExtensionDescriptor:
case Kind::AnonymousDescriptor:
case Kind::NominalTypeDescriptor:
case Kind::NominalTypeDescriptorRecord:
case Kind::ProtocolDescriptor:
case Kind::ProtocolDescriptorRecord:
case Kind::AssociatedTypeDescriptor:
case Kind::AssociatedConformanceDescriptor:
case Kind::BaseConformanceDescriptor:
case Kind::ProtocolConformanceDescriptor:
case Kind::ProtocolConformanceDescriptorRecord:
case Kind::ProtocolRequirementsBaseDescriptor:
case Kind::ReflectionBuiltinDescriptor:
case Kind::ReflectionFieldDescriptor:
case Kind::ReflectionAssociatedTypeDescriptor:
case Kind::PropertyDescriptor:
case Kind::EnumCase:
case Kind::MethodDescriptor:
case Kind::MethodDescriptorInitializer:
case Kind::MethodDescriptorAllocator:
case Kind::OpaqueTypeDescriptor:
case Kind::OpaqueTypeDescriptorRecord:
case Kind::AccessibleFunctionRecord:
case Kind::ExtendedExistentialTypeShape:
case Kind::CoroAllocator:
return Alignment(4);
case Kind::AsyncFunctionPointer:
case Kind::DispatchThunkAsyncFunctionPointer:
case Kind::DispatchThunkInitializerAsyncFunctionPointer:
case Kind::DispatchThunkAllocatorAsyncFunctionPointer:
case Kind::PartialApplyForwarderAsyncFunctionPointer:
case Kind::DistributedAccessorAsyncPointer:
case Kind::KnownAsyncFunctionPointer:
case Kind::AsyncFunctionPointerAST:
case Kind::ObjCClassRef:
case Kind::ObjCClass:
case Kind::TypeMetadataLazyCacheVariable:
case Kind::TypeMetadataSingletonInitializationCache:
case Kind::TypeMetadata:
case Kind::TypeMetadataPattern:
case Kind::ClassMetadataBaseOffset:
case Kind::TypeMetadataInstantiationCache:
case Kind::ValueWitnessTable:
case Kind::FieldOffset:
case Kind::ProtocolWitnessTableLazyCacheVariable:
case Kind::ProtocolWitnessTable:
case Kind::ProtocolWitnessTablePattern:
case Kind::ObjCMetaclass:
case Kind::SwiftMetaclassStub:
case Kind::CanonicalSpecializedGenericSwiftMetaclassStub:
case Kind::DynamicallyReplaceableFunctionVariable:
case Kind::DynamicallyReplaceableFunctionVariableAST:
case Kind::DynamicallyReplaceableFunctionKey:
case Kind::DynamicallyReplaceableFunctionKeyAST:
case Kind::OpaqueTypeDescriptorAccessorKey:
case Kind::OpaqueTypeDescriptorAccessorVar:
case Kind::ObjCResilientClassStub:
case Kind::DifferentiabilityWitness:
case Kind::NoncanonicalSpecializedGenericTypeMetadata:
case Kind::NoncanonicalSpecializedGenericTypeMetadataCacheVariable:
case Kind::PartialApplyForwarder:
case Kind::CoroFunctionPointer:
case Kind::DispatchThunkCoroFunctionPointer:
case Kind::DispatchThunkInitializerCoroFunctionPointer:
case Kind::DispatchThunkAllocatorCoroFunctionPointer:
case Kind::PartialApplyForwarderCoroFunctionPointer:
case Kind::DistributedAccessorCoroFunctionPointer:
case Kind::CoroFunctionPointerAST:
case Kind::DistributedThunkCoroFunctionPointer:
case Kind::KnownCoroFunctionPointer:
return IGM.getPointerAlignment();
case Kind::CanonicalPrespecializedGenericTypeCachingOnceToken:
case Kind::TypeMetadataDemanglingCacheVariable:
return Alignment(8);
case Kind::SILFunction:
return Alignment(1);
default:
llvm_unreachable("alignment not specified");
}
}
bool LinkEntity::isText() const {
switch (getKind()) {
case Kind::DispatchThunkAllocator:
case Kind::MethodDescriptor:
case Kind::MethodDescriptorDerivative:
case Kind::MethodDescriptorAllocator:
case Kind::MethodLookupFunction:
case Kind::EnumCase:
case Kind::FieldOffset:
case Kind::ClassMetadataBaseOffset:
case Kind::PropertyDescriptor:
case Kind::NominalTypeDescriptor:
case Kind::OpaqueTypeDescriptor:
case Kind::OpaqueTypeDescriptorAccessor:
case Kind::OpaqueTypeDescriptorAccessorImpl:
case Kind::OpaqueTypeDescriptorAccessorKey:
case Kind::AssociatedConformanceDescriptor:
case Kind::AssociatedTypeDescriptor:
case Kind::BaseConformanceDescriptor:
case Kind::DynamicallyReplaceableFunctionKeyAST:
case Kind::DynamicallyReplaceableFunctionImpl:
case Kind::DispatchThunk:
case Kind::ProtocolDescriptor:
case Kind::ProtocolRequirementsBaseDescriptor:
case Kind::ProtocolConformanceDescriptor:
case Kind::ProtocolConformanceDescriptorRecord:
case Kind::TypeMetadataAccessFunction:
return true;
case Kind::DispatchThunkAsyncFunctionPointer:
case Kind::DistributedThunkAsyncFunctionPointer:
case Kind::SwiftMetaclassStub:
case Kind::ObjCResilientClassStub:
case Kind::OpaqueTypeDescriptorAccessorVar:
case Kind::DynamicallyReplaceableFunctionVariableAST:
case Kind::AsyncFunctionPointerAST:
case Kind::ProtocolWitnessTable:
case Kind::TypeMetadata:
case Kind::DispatchThunkCoroFunctionPointer:
case Kind::DistributedThunkCoroFunctionPointer:
case Kind::CoroFunctionPointerAST:
return false;
// The following cases do not currently generate linkable symbols
// through TBDGen. The full enumeration is captured to ensure
// that as more LinkEntity kind's are created their segement assignment
// will be known.
case Kind::ObjCMetadataUpdateFunction:
case Kind::NominalTypeDescriptorRecord:
case Kind::OpaqueTypeDescriptorRecord:
case Kind::SILFunction:
case Kind::PartialApplyForwarder:
case Kind::DistributedAccessor:
case Kind::DispatchThunkDerivative:
case Kind::DispatchThunkInitializer:
case Kind::MethodDescriptorInitializer:
case Kind::TypeMetadataPattern:
case Kind::TypeMetadataInstantiationCache:
case Kind::TypeMetadataInstantiationFunction:
case Kind::TypeMetadataSingletonInitializationCache:
case Kind::TypeMetadataCompletionFunction:
case Kind::ModuleDescriptor:
case Kind::DefaultAssociatedConformanceAccessor:
case Kind::CanonicalPrespecializedGenericTypeCachingOnceToken:
case Kind::DynamicallyReplaceableFunctionKey:
case Kind::ExtensionDescriptor:
case Kind::AnonymousDescriptor:
case Kind::SILGlobalVariable:
case Kind::ReadOnlyGlobalObject:
case Kind::ProtocolWitnessTablePattern:
case Kind::GenericProtocolWitnessTableInstantiationFunction:
case Kind::AssociatedTypeWitnessTableAccessFunction:
case Kind::ReflectionAssociatedTypeDescriptor:
case Kind::ProtocolWitnessTableLazyAccessFunction:
case Kind::DifferentiabilityWitness:
case Kind::ValueWitness:
case Kind::ValueWitnessTable:
case Kind::TypeMetadataLazyCacheVariable:
case Kind::TypeMetadataDemanglingCacheVariable:
case Kind::ReflectionBuiltinDescriptor:
case Kind::ReflectionFieldDescriptor:
case Kind::CoroutineContinuationPrototype:
case Kind::DynamicallyReplaceableFunctionVariable:
case Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
case Kind::ExtendedExistentialTypeShape:
case Kind::CoroAllocator:
return true;
case Kind::ObjCClass:
case Kind::ObjCClassRef:
case Kind::ObjCMetaclass:
case Kind::AsyncFunctionPointer:
case Kind::PartialApplyForwarderAsyncFunctionPointer:
case Kind::KnownAsyncFunctionPointer:
case Kind::DispatchThunkInitializerAsyncFunctionPointer:
case Kind::DispatchThunkAllocatorAsyncFunctionPointer:
case Kind::NoncanonicalSpecializedGenericTypeMetadataCacheVariable:
case Kind::DistributedAccessorAsyncPointer:
case Kind::ProtocolWitnessTableLazyCacheVariable:
case Kind::ProtocolDescriptorRecord:
case Kind::CanonicalSpecializedGenericSwiftMetaclassStub:
case Kind::NoncanonicalSpecializedGenericTypeMetadata:
case Kind::AccessibleFunctionRecord:
case Kind::CoroFunctionPointer:
case Kind::DispatchThunkInitializerCoroFunctionPointer:
case Kind::DispatchThunkAllocatorCoroFunctionPointer:
case Kind::PartialApplyForwarderCoroFunctionPointer:
case Kind::DistributedAccessorCoroFunctionPointer:
case Kind::KnownCoroFunctionPointer:
return false;
}
}
bool LinkEntity::isDistributedThunk() const {
if (!hasDecl())
return false;
auto value = getDecl();
if (auto afd = dyn_cast<AbstractFunctionDecl>(value)) {
return afd->isDistributedThunk();
}
return false;
}
bool LinkEntity::isWeakImported(ModuleDecl *module) const {
switch (getKind()) {
case Kind::SILGlobalVariable:
case Kind::ReadOnlyGlobalObject:
if (getSILGlobalVariable()->getDecl()) {
return getSILGlobalVariable()->getDecl()->isWeakImported(module);
}
return false;
case Kind::DynamicallyReplaceableFunctionKey:
case Kind::DynamicallyReplaceableFunctionVariable:
case Kind::SILFunction: {
return getSILFunction()->isWeakImported(module);
}
case Kind::AssociatedConformanceDescriptor:
case Kind::DefaultAssociatedConformanceAccessor: {
// Associated conformance descriptors use the protocol as their declaration
// and are weak linked if either the protocol or the associated type stored
// in extra storage area is weak linked.
if (cast<ProtocolDecl>(getDecl())->isWeakImported(module))
return true;
auto assocConformance = getAssociatedConformance();
auto &ctx = getDecl()->getASTContext();
if (assocConformance.first->isEqual(ctx.TheSelfType))
return cast<ProtocolDecl>(getDecl())->isWeakImported(module);
auto *depMemTy = assocConformance.first->castTo<DependentMemberType>();
return depMemTy->getAssocType()->isWeakImported(module);
}
case Kind::BaseConformanceDescriptor:
return cast<ProtocolDecl>(getDecl())->isWeakImported(module);
case Kind::TypeMetadata:
case Kind::TypeMetadataAccessFunction: {
if (auto *nominalDecl = getType()->getAnyNominal())
return nominalDecl->isWeakImported(module);
return false;
}
case Kind::AsyncFunctionPointerAST:
case Kind::DistributedThunkAsyncFunctionPointer:
case Kind::CoroFunctionPointerAST:
case Kind::DistributedThunkCoroFunctionPointer:
case Kind::DispatchThunk:
case Kind::DispatchThunkDerivative:
case Kind::DispatchThunkInitializer:
case Kind::DispatchThunkAllocator:
case Kind::MethodDescriptor:
case Kind::MethodDescriptorDerivative:
case Kind::MethodDescriptorInitializer:
case Kind::MethodDescriptorAllocator:
case Kind::MethodLookupFunction:
case Kind::EnumCase:
case Kind::FieldOffset:
case Kind::ObjCClass:
case Kind::ObjCClassRef:
case Kind::ObjCMetaclass:
case Kind::SwiftMetaclassStub:
case Kind::ClassMetadataBaseOffset:
case Kind::NominalTypeDescriptor:
case Kind::NominalTypeDescriptorRecord:
case Kind::ModuleDescriptor:
case Kind::ProtocolDescriptor:
case Kind::ProtocolDescriptorRecord:
case Kind::ProtocolRequirementsBaseDescriptor:
case Kind::AssociatedTypeDescriptor:
case Kind::DynamicallyReplaceableFunctionKeyAST:
case Kind::DynamicallyReplaceableFunctionVariableAST:
case Kind::DynamicallyReplaceableFunctionImpl:
case Kind::OpaqueTypeDescriptor:
case Kind::OpaqueTypeDescriptorRecord:
case Kind::OpaqueTypeDescriptorAccessor:
case Kind::OpaqueTypeDescriptorAccessorImpl:
case Kind::OpaqueTypeDescriptorAccessorKey:
case Kind::OpaqueTypeDescriptorAccessorVar:
case Kind::DistributedAccessor:
return getDecl()->isWeakImported(module);
case Kind::PropertyDescriptor:
// Static properties may have nil property descriptors if declared in
// modules compiled with older compilers and should be weak linked.
return (getDecl()->isWeakImported(module) || getDecl()->isStatic());
case Kind::CanonicalSpecializedGenericSwiftMetaclassStub:
return getType()->getClassOrBoundGenericClass()->isWeakImported(module);
case Kind::ProtocolWitnessTable:
case Kind::ProtocolConformanceDescriptor:
case Kind::ProtocolConformanceDescriptorRecord:
return getProtocolConformance()->getRootConformance()
->isWeakImported(module);
case Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
case Kind::NoncanonicalSpecializedGenericTypeMetadata:
case Kind::NoncanonicalSpecializedGenericTypeMetadataCacheVariable:
case Kind::CanonicalPrespecializedGenericTypeCachingOnceToken:
return false;
// TODO: Revisit some of the below, for weak conformances.
case Kind::ObjCMetadataUpdateFunction:
case Kind::ObjCResilientClassStub:
case Kind::PartialApplyForwarder:
case Kind::TypeMetadataPattern:
case Kind::TypeMetadataInstantiationCache:
case Kind::TypeMetadataInstantiationFunction:
case Kind::TypeMetadataSingletonInitializationCache:
case Kind::TypeMetadataCompletionFunction:
case Kind::ExtensionDescriptor:
case Kind::AnonymousDescriptor:
case Kind::ProtocolWitnessTablePattern:
case Kind::GenericProtocolWitnessTableInstantiationFunction:
case Kind::AssociatedTypeWitnessTableAccessFunction:
case Kind::ReflectionAssociatedTypeDescriptor:
case Kind::ProtocolWitnessTableLazyAccessFunction:
case Kind::ProtocolWitnessTableLazyCacheVariable:
case Kind::ValueWitness:
case Kind::ValueWitnessTable:
case Kind::TypeMetadataLazyCacheVariable:
case Kind::TypeMetadataDemanglingCacheVariable:
case Kind::ReflectionBuiltinDescriptor:
case Kind::ReflectionFieldDescriptor:
case Kind::CoroutineContinuationPrototype:
case Kind::DifferentiabilityWitness:
case Kind::AccessibleFunctionRecord:
case Kind::ExtendedExistentialTypeShape:
case Kind::CoroAllocator:
return false;
case Kind::AsyncFunctionPointer:
case Kind::DispatchThunkAsyncFunctionPointer:
case Kind::DispatchThunkInitializerAsyncFunctionPointer:
case Kind::DispatchThunkAllocatorAsyncFunctionPointer:
case Kind::PartialApplyForwarderAsyncFunctionPointer:
case Kind::DistributedAccessorAsyncPointer:
return getUnderlyingEntityForAsyncFunctionPointer()
.isWeakImported(module);
case Kind::KnownAsyncFunctionPointer: {
auto &context = module->getASTContext();
auto deploymentAvailability =
AvailabilityRange::forDeploymentTarget(context);
return !deploymentAvailability.isContainedIn(
context.getConcurrencyAvailability());
}
case Kind::CoroFunctionPointer:
case Kind::DispatchThunkCoroFunctionPointer:
case Kind::DispatchThunkInitializerCoroFunctionPointer:
case Kind::DispatchThunkAllocatorCoroFunctionPointer:
case Kind::PartialApplyForwarderCoroFunctionPointer:
case Kind::DistributedAccessorCoroFunctionPointer:
return getUnderlyingEntityForCoroFunctionPointer().isWeakImported(module);
case Kind::KnownCoroFunctionPointer: {
auto &context = module->getASTContext();
auto deploymentAvailability =
AvailabilityRange::forDeploymentTarget(context);
return !deploymentAvailability.isContainedIn(
context.getCoroutineAccessorsAvailability());
}
}
llvm_unreachable("Bad link entity kind");
}
DeclContext *LinkEntity::getDeclContextForEmission() const {
switch (getKind()) {
case Kind::AsyncFunctionPointerAST:
case Kind::DistributedThunkAsyncFunctionPointer:
case Kind::CoroFunctionPointerAST:
case Kind::DistributedThunkCoroFunctionPointer:
case Kind::DispatchThunk:
case Kind::DispatchThunkDerivative:
case Kind::DispatchThunkInitializer:
case Kind::DispatchThunkAllocator:
case Kind::MethodDescriptor:
case Kind::MethodDescriptorDerivative:
case Kind::MethodDescriptorInitializer:
case Kind::MethodDescriptorAllocator:
case Kind::MethodLookupFunction:
case Kind::EnumCase:
case Kind::FieldOffset:
case Kind::ObjCClass:
case Kind::ObjCMetaclass:
case Kind::SwiftMetaclassStub:
case Kind::ObjCMetadataUpdateFunction:
case Kind::ObjCResilientClassStub:
case Kind::ClassMetadataBaseOffset:
case Kind::PropertyDescriptor:
case Kind::NominalTypeDescriptor:
case Kind::NominalTypeDescriptorRecord:
case Kind::TypeMetadataPattern:
case Kind::TypeMetadataInstantiationCache:
case Kind::TypeMetadataInstantiationFunction:
case Kind::TypeMetadataSingletonInitializationCache:
case Kind::TypeMetadataCompletionFunction:
case Kind::ProtocolDescriptor:
case Kind::ProtocolDescriptorRecord:
case Kind::ProtocolRequirementsBaseDescriptor:
case Kind::AssociatedTypeDescriptor:
case Kind::AssociatedConformanceDescriptor:
case Kind::DefaultAssociatedConformanceAccessor:
case Kind::BaseConformanceDescriptor:
case Kind::DynamicallyReplaceableFunctionVariableAST:
case Kind::DynamicallyReplaceableFunctionKeyAST:
case Kind::DynamicallyReplaceableFunctionImpl:
case Kind::OpaqueTypeDescriptor:
case Kind::OpaqueTypeDescriptorRecord:
case Kind::OpaqueTypeDescriptorAccessor:
case Kind::OpaqueTypeDescriptorAccessorImpl:
case Kind::OpaqueTypeDescriptorAccessorKey:
case Kind::OpaqueTypeDescriptorAccessorVar:
case Kind::CanonicalPrespecializedGenericTypeCachingOnceToken:
case Kind::DistributedAccessor:
return getDecl()->getDeclContext();
case Kind::CanonicalSpecializedGenericSwiftMetaclassStub:
return getType()->getClassOrBoundGenericClass()->getDeclContext();
case Kind::SILFunction:
case Kind::DynamicallyReplaceableFunctionVariable:
case Kind::DynamicallyReplaceableFunctionKey:
return getSILFunction()->getDeclContext();
case Kind::SILGlobalVariable:
case Kind::ReadOnlyGlobalObject:
if (auto decl = getSILGlobalVariable()->getDecl())
return decl->getDeclContext();
return nullptr;
case Kind::ProtocolWitnessTable:
case Kind::ProtocolConformanceDescriptor:
case Kind::ProtocolConformanceDescriptorRecord:
return getRootProtocolConformance()->getDeclContext();
case Kind::ProtocolWitnessTablePattern:
case Kind::GenericProtocolWitnessTableInstantiationFunction:
case Kind::AssociatedTypeWitnessTableAccessFunction:
case Kind::ReflectionAssociatedTypeDescriptor:
case Kind::ProtocolWitnessTableLazyCacheVariable:
case Kind::ProtocolWitnessTableLazyAccessFunction:
return getProtocolConformance()->getDeclContext();
case Kind::TypeMetadata: {
auto ty = getType();
// Only fully concrete nominal type metadata gets emitted eagerly.
auto nom = ty->getAnyNominal();
if (nom)
return nom->getDeclContext();
return nullptr;
}
// Always shared linkage
case Kind::ModuleDescriptor:
case Kind::ExtensionDescriptor:
case Kind::AnonymousDescriptor:
case Kind::ObjCClassRef:
case Kind::TypeMetadataAccessFunction:
case Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
case Kind::TypeMetadataLazyCacheVariable:
case Kind::TypeMetadataDemanglingCacheVariable:
case Kind::NoncanonicalSpecializedGenericTypeMetadata:
case Kind::NoncanonicalSpecializedGenericTypeMetadataCacheVariable:
case Kind::CoroAllocator:
assert(isAlwaysSharedLinkage() && "kind should always be shared linkage");
return nullptr;
// TODO
case Kind::CoroutineContinuationPrototype:
case Kind::ReflectionFieldDescriptor:
case Kind::ReflectionBuiltinDescriptor:
case Kind::ValueWitness:
case Kind::ValueWitnessTable:
case Kind::DifferentiabilityWitness:
case Kind::PartialApplyForwarder:
case Kind::KnownAsyncFunctionPointer:
case Kind::KnownCoroFunctionPointer:
case Kind::ExtendedExistentialTypeShape:
return nullptr;
case Kind::AsyncFunctionPointer:
case Kind::DispatchThunkAsyncFunctionPointer:
case Kind::DispatchThunkInitializerAsyncFunctionPointer:
case Kind::DispatchThunkAllocatorAsyncFunctionPointer:
case Kind::PartialApplyForwarderAsyncFunctionPointer:
case Kind::DistributedAccessorAsyncPointer:
return getUnderlyingEntityForAsyncFunctionPointer()
.getDeclContextForEmission();
case Kind::AccessibleFunctionRecord: {
return getSILFunction()->getParentModule();
case Kind::CoroFunctionPointer:
case Kind::DispatchThunkCoroFunctionPointer:
case Kind::DispatchThunkInitializerCoroFunctionPointer:
case Kind::DispatchThunkAllocatorCoroFunctionPointer:
case Kind::PartialApplyForwarderCoroFunctionPointer:
case Kind::DistributedAccessorCoroFunctionPointer:
return getUnderlyingEntityForCoroFunctionPointer()
.getDeclContextForEmission();
}
}
llvm_unreachable("invalid decl kind");
}
bool LinkEntity::isAlwaysSharedLinkage() const {
switch (getKind()) {
case Kind::ModuleDescriptor:
case Kind::ExtensionDescriptor:
case Kind::AnonymousDescriptor:
case Kind::ObjCClassRef:
case Kind::TypeMetadataAccessFunction:
case Kind::CanonicalSpecializedGenericTypeMetadataAccessFunction:
case Kind::TypeMetadataLazyCacheVariable:
case Kind::TypeMetadataDemanglingCacheVariable:
case Kind::NoncanonicalSpecializedGenericTypeMetadata:
case Kind::NoncanonicalSpecializedGenericTypeMetadataCacheVariable:
case Kind::CoroAllocator:
return true;
default:
return false;
}
}
bool LinkEntity::hasNonUniqueDefinition() const {
if (isDeclKind(getKind())) {
auto decl = getDecl();
return SILDeclRef::declHasNonUniqueDefinition(decl);
}
if (hasSILFunction()) {
return getSILFunction()->hasNonUniqueDefinition();
}
if (getKind() == Kind::SILGlobalVariable ||
getKind() == Kind::ReadOnlyGlobalObject)
return getSILGlobalVariable()->hasNonUniqueDefinition();
if (getKind() == Kind::TypeMetadata ||
getKind() == Kind::ValueWitnessTable) {
// For a nominal type, check its declaration.
CanType type = getType();
if (auto nominal = type->getAnyNominal()) {
return SILDeclRef::declHasNonUniqueDefinition(nominal);
}
// All other type metadata is nonuniqued.
return true;
}
// Always treat witness tables as having non-unique definitions.
if (getKind() == Kind::ProtocolWitnessTable) {
if (auto context = getDeclContextForEmission())
if (context->getParentModule()->getASTContext().LangOpts.hasFeature(Feature::Embedded))
return true;
}
return false;
}