mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
1789 lines
66 KiB
C++
1789 lines
66 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;
|
|
}
|
|
|
|
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();
|
|
|
|
// 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 metadata for tuple types.
|
|
if (getType()->getASTContext().LangOpts.hasFeature(Feature::EmbeddedExistentials) &&
|
|
isa<TupleType>(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:
|
|
if (IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
|
|
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 *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) {
|
|
// 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;
|
|
}
|