mirror of
https://github.com/apple/swift.git
synced 2026-06-20 15:42:51 +02:00
14bc0baecf
The code generation model for a particular declaration or conformance can be defined explicitly with `@export(interface)`, `@export(implementation)`, or `@inlinable` (for declarations), indicating where the definition will occur. Embedded Swift also has some limitations on what can be emitted into IR. For example, a generic function cannot be `@export(interface)` because Embedded Swift does not support unspecialized generics. Compute the effective code generation model based on what was explicitly specified, the limitations of the model, and the default code generation model for the given module, which defaults to "inlinable" but can be made "implementation" by the DeferredCodeGen feature. Use the effective code generation model for IR- and SIL-level determinations of linkage and where to emit symbols. [WIP] Start computing and using the "effective" code generation model FIXUP linkage of the alias symbol
1863 lines
68 KiB
C++
1863 lines
68 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/Basic/CodeGenerationModel.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;
|
|
if (langOpts.hasFeature(Feature::Embedded)) {
|
|
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;
|
|
|
|
auto *nominal = getType().getAnyNominal();
|
|
switch (getMetadataAddress()) {
|
|
case TypeMetadataAddress::FullMetadata: {
|
|
// In embedded existentials mode we generate lazy public metadata on
|
|
// demand which makes the full metadata non-unique. (The address-point
|
|
// alias still uses the formal declaration linkage so that it survives
|
|
// GlobalDCE under -internalize-at-link.)
|
|
if (isLazyEmissionOfPublicSymbolInMultipleModulesPossible(getType()))
|
|
return SILLinkage::Shared;
|
|
|
|
// 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;
|
|
|
|
// @export(interface) types have a unique definition in their defining
|
|
// module, so the FullMetadata must be externally linkable.
|
|
bool isEmbedded =
|
|
nominal->getASTContext().LangOpts.hasFeature(Feature::Embedded);
|
|
if (isEmbedded) {
|
|
if (nominal->getEffectiveCodeGenerationModel()
|
|
== CodeGenerationModel::Interface) {
|
|
return getSILLinkage(FormalLinkage::PublicUnique, forDefinition);
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
if (langOpts.hasFeature(Feature::Embedded)) {
|
|
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>(assocConformance.second)->isWeakImported(module);
|
|
|
|
auto *depMemTy = assocConformance.first->castTo<DependentMemberType>();
|
|
return depMemTy->getAssocType()->isWeakImported(module);
|
|
}
|
|
|
|
case Kind::BaseConformanceDescriptor: {
|
|
auto baseProto = getAssociatedConformance().second;
|
|
|
|
// The base protocol might be reparented and less available.
|
|
if (baseProto->isWeakImported(module))
|
|
return true;
|
|
|
|
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) {
|
|
// The address-point alias of type metadata is uniquely defined per
|
|
// binary even when the full metadata it references is shared, so it
|
|
// gets the formal declaration linkage rather than linkonce_odr.
|
|
if (getKind() == Kind::TypeMetadata &&
|
|
getMetadataAddress() == TypeMetadataAddress::AddressPoint)
|
|
return false;
|
|
|
|
// 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;
|
|
}
|
|
|
|
// In embedded Swift, witness tables are treated as having non-unique
|
|
// definitions (so they get linkonce_odr linkage) unless the underlying
|
|
// conformance was explicitly marked @export(interface).
|
|
if (getKind() == Kind::ProtocolWitnessTable) {
|
|
if (auto context = getDeclContextForEmission()) {
|
|
if (context->getParentModule()->getASTContext().LangOpts.hasFeature(
|
|
Feature::Embedded)) {
|
|
if (auto *normal = dyn_cast<NormalProtocolConformance>(
|
|
getProtocolConformance()->getRootConformance())) {
|
|
switch (normal->getEffectiveCodeGenerationModel()) {
|
|
case CodeGenerationModel::Interface:
|
|
return false;
|
|
|
|
case CodeGenerationModel::Implementation:
|
|
case CodeGenerationModel::Inlinable:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|