//===--- 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/ClangImporter/ClangModule.h" #include "swift/SIL/SILGlobalVariable.h" #include "swift/SIL/FormalLinkage.h" #include "llvm/ADT/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::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) {} UniversalLinkageInfo::UniversalLinkageInfo(const llvm::Triple &triple, bool hasMultipleIGMs, bool forcePublicDecls) : IsELFObject(triple.isOSBinFormatELF()), UseDLLStorage(useDllStorage(triple)), HasMultipleIGMs(hasMultipleIGMs), ForcePublicDecls(forcePublicDecls) {} /// Mangle this entity into the given buffer. void LinkEntity::mangle(SmallVectorImpl &buffer) const { llvm::raw_svector_ostream stream(buffer); mangle(stream); } /// Mangle this entity into the given stream. void LinkEntity::mangle(raw_ostream &buffer) const { std::string Result = mangleAsString(); buffer.write(Result.data(), Result.size()); } /// Mangle this entity as a std::string. std::string LinkEntity::mangleAsString() const { IRGenMangler mangler; switch (getKind()) { case Kind::DispatchThunk: { auto *func = cast(getDecl()); return mangler.mangleDispatchThunk(func); } case Kind::DispatchThunkInitializer: { auto *ctor = cast(getDecl()); return mangler.mangleConstructorDispatchThunk(ctor, /*isAllocating=*/false); } case Kind::DispatchThunkAllocator: { auto *ctor = cast(getDecl()); return mangler.mangleConstructorDispatchThunk(ctor, /*isAllocating=*/true); } case Kind::MethodDescriptor: { auto *func = cast(getDecl()); return mangler.mangleMethodDescriptor(func); } case Kind::MethodDescriptorInitializer: { auto *ctor = cast(getDecl()); return mangler.mangleConstructorMethodDescriptor(ctor, /*isAllocating=*/false); } case Kind::MethodDescriptorAllocator: { auto *ctor = cast(getDecl()); return mangler.mangleConstructorMethodDescriptor(ctor, /*isAllocating=*/true); } case Kind::MethodLookupFunction: { auto *classDecl = cast(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::TypeMetadataLazyCacheVariable: return mangler.mangleTypeMetadataLazyCacheVariable(getType()); case Kind::TypeMetadataDemanglingCacheVariable: return mangler.mangleTypeMetadataDemanglingCacheVariable(getType()); case Kind::TypeMetadataInstantiationCache: return mangler.mangleTypeMetadataInstantiationCache( cast(getDecl())); case Kind::TypeMetadataInstantiationFunction: return mangler.mangleTypeMetadataInstantiationFunction( cast(getDecl())); case Kind::TypeMetadataSingletonInitializationCache: return mangler.mangleTypeMetadataSingletonInitializationCache( cast(getDecl())); case Kind::TypeMetadataCompletionFunction: return mangler.mangleTypeMetadataCompletionFunction( cast(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::TypeMetadataPattern: return mangler.mangleTypeMetadataPattern( cast(getDecl())); case Kind::SwiftMetaclassStub: return mangler.mangleClassMetaClass(cast(getDecl())); case Kind::ObjCMetadataUpdateFunction: return mangler.mangleObjCMetadataUpdateFunction(cast(getDecl())); case Kind::ObjCResilientClassStub: switch (getMetadataAddress()) { case TypeMetadataAddress::FullMetadata: return mangler.mangleFullObjCResilientClassStub(cast(getDecl())); case TypeMetadataAddress::AddressPoint: return mangler.mangleObjCResilientClassStub(cast(getDecl())); } llvm_unreachable("invalid metadata address"); case Kind::ClassMetadataBaseOffset: // class metadata base offset return mangler.mangleClassMetadataBaseOffset(cast(getDecl())); case Kind::NominalTypeDescriptor: return mangler.mangleNominalTypeDescriptor( cast(getDecl())); case Kind::OpaqueTypeDescriptor: return mangler.mangleOpaqueTypeDescriptor(cast(getDecl())); case Kind::OpaqueTypeDescriptorAccessor: return mangler.mangleOpaqueTypeDescriptorAccessor( cast(getDecl())); case Kind::OpaqueTypeDescriptorAccessorImpl: return mangler.mangleOpaqueTypeDescriptorAccessorImpl( cast(getDecl())); case Kind::OpaqueTypeDescriptorAccessorKey: return mangler.mangleOpaqueTypeDescriptorAccessorKey( cast(getDecl())); case Kind::OpaqueTypeDescriptorAccessorVar: return mangler.mangleOpaqueTypeDescriptorAccessorVar( cast(getDecl())); case Kind::PropertyDescriptor: return mangler.manglePropertyDescriptor( cast(getDecl())); case Kind::ModuleDescriptor: return mangler.mangleModuleDescriptor(cast(getDecl())); case Kind::ExtensionDescriptor: return mangler.mangleExtensionDescriptor(getExtension()); case Kind::AnonymousDescriptor: return mangler.mangleAnonymousDescriptor(getAnonymousDeclContext()); case Kind::ProtocolDescriptor: return mangler.mangleProtocolDescriptor(cast(getDecl())); case Kind::ProtocolRequirementsBaseDescriptor: return mangler.mangleProtocolRequirementsBaseDescriptor( cast(getDecl())); case Kind::AssociatedTypeDescriptor: return mangler.mangleAssociatedTypeDescriptor( cast(getDecl())); case Kind::AssociatedConformanceDescriptor: { auto assocConformance = getAssociatedConformance(); return mangler.mangleAssociatedConformanceDescriptor( cast(getDecl()), assocConformance.first, assocConformance.second); } case Kind::BaseConformanceDescriptor: { auto assocConformance = getAssociatedConformance(); return mangler.mangleBaseConformanceDescriptor( cast(getDecl()), assocConformance.second); } case Kind::DefaultAssociatedConformanceAccessor: { auto assocConformance = getAssociatedConformance(); return mangler.mangleDefaultAssociatedConformanceAccessor( cast(getDecl()), assocConformance.first, assocConformance.second); } case Kind::ProtocolConformanceDescriptor: return mangler.mangleProtocolConformanceDescriptor( getRootProtocolConformance()); case Kind::EnumCase: return mangler.mangleEnumCase(getDecl()); case Kind::FieldOffset: return mangler.mangleFieldOffset(getDecl()); case Kind::ProtocolWitnessTable: return mangler.mangleWitnessTable(getRootProtocolConformance()); 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(assocConf.first)) { return mangler.mangleBaseWitnessTableAccessFunction( getProtocolConformance(), assocConf.second); } return mangler.mangleAssociatedTypeWitnessTableAccessFunction( getProtocolConformance(), assocConf.first, assocConf.second); } case Kind::CoroutineContinuationPrototype: return mangler.mangleCoroutineContinuationPrototype( cast(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(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(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(getDecl())->getObjCRuntimeName(TempBuffer); std::string Result("OBJC_METACLASS_$_"); Result.append(Name.data(), Name.size()); return Result; } case Kind::SILFunction: { std::string Result(getSILFunction()->getName()); if (isDynamicallyReplaceable()) { Result.append("TI"); } return Result; } case Kind::DynamicallyReplaceableFunctionImpl: { assert(isa(getDecl())); std::string Result; if (auto *Constructor = dyn_cast(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(getDecl())); std::string Result; if (auto *Constructor = dyn_cast(getDecl())) { Result = mangler.mangleConstructorEntity(Constructor, isAllocator()); } else { Result = mangler.mangleEntity(getDecl()); } Result.append("TX"); return Result; } case Kind::DynamicallyReplaceableFunctionKeyAST: { assert(isa(getDecl())); std::string Result; if (auto *Constructor = dyn_cast(getDecl())) { Result = mangler.mangleConstructorEntity(Constructor, isAllocator()); } else { Result = mangler.mangleEntity(getDecl()); } Result.append("Tx"); return Result; } case Kind::SILGlobalVariable: return getSILGlobalVariable()->getName().str(); 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.mangleSILDifferentiabilityWitnessKey( {getSILDifferentiabilityWitness()->getOriginalFunction()->getName(), getSILDifferentiabilityWitness()->getConfig()}); } llvm_unreachable("bad entity kind!"); } 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::DispatchThunkInitializer: case Kind::DispatchThunkAllocator: case Kind::MethodDescriptor: case Kind::MethodDescriptorInitializer: case Kind::MethodDescriptorAllocator: { auto *decl = getDecl(); // Protocol requirements don't have their own access control if (auto *proto = dyn_cast(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: { 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"); } // ...but we don't actually expose individual value witnesses (right now). case Kind::ValueWitness: { auto *nominal = getType().getAnyNominal(); if (getDeclLinkage(nominal) == FormalLinkage::PublicNonUnique) return SILLinkage::Shared; return forDefinition ? SILLinkage::Private : SILLinkage::PrivateExternal; } case Kind::TypeMetadataAccessFunction: switch (getTypeMetadataAccessStrategy(getType())) { case MetadataAccessStrategy::PublicUniqueAccessor: return getSILLinkage(FormalLinkage::PublicUnique, 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::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, // excpet for foreign types. return SILLinkage::Private; case TypeMetadataAddress::AddressPoint: { auto *classDecl = cast(getDecl()); return getSILLinkage(getDeclLinkage(classDecl), forDefinition); } } llvm_unreachable("invalid metadata address"); } case Kind::EnumCase: { auto *elementDecl = cast(getDecl()); return getSILLinkage(getDeclLinkage(elementDecl), forDefinition); } case Kind::FieldOffset: { auto *varDecl = cast(getDecl()); auto linkage = getDeclLinkage(varDecl); // Classes with resilient storage don't expose field offset symbols. if (cast(varDecl->getDeclContext())->isResilient()) { assert(linkage != FormalLinkage::PublicNonUnique && "Cannot have a resilient class with non-unique linkage"); if (linkage == FormalLinkage::PublicUnique) 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(getDecl()) ->getOpaqueAccessor(AccessorKind::Get); return getSILLinkage(getDeclLinkage(getterDecl), forDefinition); } case Kind::AssociatedConformanceDescriptor: case Kind::BaseConformanceDescriptor: case Kind::ObjCClass: case Kind::ObjCMetaclass: case Kind::SwiftMetaclassStub: case Kind::NominalTypeDescriptor: case Kind::ClassMetadataBaseOffset: case Kind::ProtocolDescriptor: case Kind::ProtocolRequirementsBaseDescriptor: case Kind::MethodLookupFunction: case Kind::OpaqueTypeDescriptor: case Kind::OpaqueTypeDescriptorAccessor: case Kind::OpaqueTypeDescriptorAccessorImpl: case Kind::OpaqueTypeDescriptorAccessorKey: case Kind::OpaqueTypeDescriptorAccessorVar: return getSILLinkage(getDeclLinkage(getDecl()), forDefinition); case Kind::AssociatedTypeDescriptor: return getSILLinkage(getDeclLinkage(getAssociatedType()->getProtocol()), forDefinition); case Kind::ProtocolWitnessTable: case Kind::ProtocolConformanceDescriptor: return getLinkageForProtocolConformance(getRootProtocolConformance(), forDefinition); case Kind::ProtocolWitnessTablePattern: if (getLinkageAsConformance() == SILLinkage::Shared) return SILLinkage::Shared; return SILLinkage::Private; case Kind::ProtocolWitnessTableLazyAccessFunction: case Kind::ProtocolWitnessTableLazyCacheVariable: { auto *nominal = getType().getAnyNominal(); assert(nominal); if (getDeclLinkage(nominal) == FormalLinkage::Private || getLinkageAsConformance() == SILLinkage::Private) { return SILLinkage::Private; } else { return SILLinkage::Shared; } } case Kind::AssociatedTypeWitnessTableAccessFunction: case Kind::DefaultAssociatedConformanceAccessor: case Kind::GenericProtocolWitnessTableInstantiationFunction: return SILLinkage::Private; case Kind::DynamicallyReplaceableFunctionKey: return getSILFunction()->getLinkage(); case Kind::SILFunction: return getSILFunction()->getEffectiveSymbolLinkage(); 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: 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(); } 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::PropertyDescriptor: case Kind::DispatchThunk: case Kind::DispatchThunkInitializer: case Kind::DispatchThunkAllocator: case Kind::MethodDescriptor: 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::ProtocolRequirementsBaseDescriptor: case Kind::AssociatedTypeDescriptor: case Kind::AssociatedConformanceDescriptor: case Kind::BaseConformanceDescriptor: case Kind::DefaultAssociatedConformanceAccessor: case Kind::SILFunction: case Kind::SILGlobalVariable: case Kind::ProtocolWitnessTable: case Kind::ProtocolWitnessTablePattern: case Kind::GenericProtocolWitnessTableInstantiationFunction: case Kind::AssociatedTypeWitnessTableAccessFunction: case Kind::ReflectionAssociatedTypeDescriptor: case Kind::ProtocolConformanceDescriptor: case Kind::ProtocolWitnessTableLazyAccessFunction: case Kind::ProtocolWitnessTableLazyCacheVariable: case Kind::ValueWitness: case Kind::ValueWitnessTable: case Kind::TypeMetadata: case Kind::TypeMetadataAccessFunction: 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: return false; } } llvm::Type *LinkEntity::getDefaultDeclarationType(IRGenModule &IGM) const { switch (getKind()) { case Kind::ModuleDescriptor: case Kind::ExtensionDescriptor: case Kind::AnonymousDescriptor: case Kind::NominalTypeDescriptor: case Kind::PropertyDescriptor: return IGM.TypeContextDescriptorTy; case Kind::OpaqueTypeDescriptor: return IGM.OpaqueTypeDescriptorTy; case Kind::ProtocolDescriptor: return IGM.ProtocolDescriptorStructTy; case Kind::AssociatedTypeDescriptor: case Kind::AssociatedConformanceDescriptor: case Kind::BaseConformanceDescriptor: case Kind::ProtocolRequirementsBaseDescriptor: return IGM.ProtocolRequirementStructTy; case Kind::ProtocolConformanceDescriptor: return IGM.ProtocolConformanceDescriptorTy; case Kind::ObjCClassRef: return IGM.ObjCClassPtrTy; case Kind::ObjCClass: case Kind::ObjCMetaclass: case Kind::SwiftMetaclassStub: return IGM.ObjCClassStructTy; case Kind::TypeMetadataLazyCacheVariable: 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: switch (getMetadataAddress()) { case TypeMetadataAddress::FullMetadata: 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: // TODO: put a cache variable on IGM return llvm::StructType::get(IGM.getLLVMContext(), { IGM.SizeTy, // Immediate members offset IGM.Int32Ty, // Negative size in words IGM.Int32Ty // Positive size in words }); 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.FunctionPtrTy->getPointerTo(); case Kind::MethodDescriptor: case Kind::MethodDescriptorInitializer: case Kind::MethodDescriptorAllocator: return IGM.MethodDescriptorStructTy; case Kind::DynamicallyReplaceableFunctionKey: case Kind::OpaqueTypeDescriptorAccessorKey: return IGM.DynamicReplacementKeyTy; case Kind::DynamicallyReplaceableFunctionVariable: 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; 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::ProtocolDescriptor: case Kind::AssociatedTypeDescriptor: case Kind::AssociatedConformanceDescriptor: case Kind::BaseConformanceDescriptor: case Kind::ProtocolConformanceDescriptor: 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: return Alignment(4); 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::DynamicallyReplaceableFunctionVariable: case Kind::DynamicallyReplaceableFunctionKey: case Kind::OpaqueTypeDescriptorAccessorKey: case Kind::OpaqueTypeDescriptorAccessorVar: case Kind::ObjCResilientClassStub: case Kind::DifferentiabilityWitness: return IGM.getPointerAlignment(); case Kind::TypeMetadataDemanglingCacheVariable: return Alignment(8); case Kind::SILFunction: return Alignment(1); default: llvm_unreachable("alignment not specified"); } } bool LinkEntity::isWeakImported(ModuleDecl *module) const { switch (getKind()) { case Kind::SILGlobalVariable: if (getSILGlobalVariable()->getDecl()) { return getSILGlobalVariable()->getDecl()->isWeakImported(module); } return false; case Kind::DynamicallyReplaceableFunctionKey: case Kind::DynamicallyReplaceableFunctionVariable: case Kind::SILFunction: { return getSILFunction()->isWeakImported(); } case Kind::AssociatedConformanceDescriptor: case Kind::DefaultAssociatedConformanceAccessor: { // Associated conformance descriptors use the protocol as // their declaration, but are weak linked if the associated // type stored in extra storage area is weak linked. auto assocConformance = getAssociatedConformance(); auto *depMemTy = assocConformance.first->castTo(); return depMemTy->getAssocType()->isWeakImported(module); } case Kind::BaseConformanceDescriptor: return cast(getDecl())->isWeakImported(module); case Kind::TypeMetadata: case Kind::TypeMetadataAccessFunction: { if (auto *nominalDecl = getType()->getAnyNominal()) return nominalDecl->isWeakImported(module); return false; } case Kind::DispatchThunk: case Kind::DispatchThunkInitializer: case Kind::DispatchThunkAllocator: case Kind::MethodDescriptor: 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::PropertyDescriptor: case Kind::NominalTypeDescriptor: case Kind::ModuleDescriptor: case Kind::ProtocolDescriptor: case Kind::ProtocolRequirementsBaseDescriptor: case Kind::AssociatedTypeDescriptor: case Kind::DynamicallyReplaceableFunctionKeyAST: case Kind::DynamicallyReplaceableFunctionVariableAST: case Kind::DynamicallyReplaceableFunctionImpl: case Kind::OpaqueTypeDescriptor: case Kind::OpaqueTypeDescriptorAccessor: case Kind::OpaqueTypeDescriptorAccessorImpl: case Kind::OpaqueTypeDescriptorAccessorKey: case Kind::OpaqueTypeDescriptorAccessorVar: return getDecl()->isWeakImported(module); case Kind::ProtocolWitnessTable: case Kind::ProtocolConformanceDescriptor: return getProtocolConformance()->getRootConformance() ->isWeakImported(module); // TODO: Revisit some of the below, for weak conformances. case Kind::ObjCMetadataUpdateFunction: case Kind::ObjCResilientClassStub: 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: return false; } llvm_unreachable("Bad link entity kind"); } DeclContext *LinkEntity::getDeclContextForEmission() const { switch (getKind()) { case Kind::DispatchThunk: case Kind::DispatchThunkInitializer: case Kind::DispatchThunkAllocator: case Kind::MethodDescriptor: 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::TypeMetadataPattern: case Kind::TypeMetadataInstantiationCache: case Kind::TypeMetadataInstantiationFunction: case Kind::TypeMetadataSingletonInitializationCache: case Kind::TypeMetadataCompletionFunction: case Kind::ProtocolDescriptor: 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::OpaqueTypeDescriptorAccessor: case Kind::OpaqueTypeDescriptorAccessorImpl: case Kind::OpaqueTypeDescriptorAccessorKey: case Kind::OpaqueTypeDescriptorAccessorVar: return getDecl()->getDeclContext(); case Kind::SILFunction: case Kind::DynamicallyReplaceableFunctionVariable: case Kind::DynamicallyReplaceableFunctionKey: return getSILFunction()->getDeclContext(); case Kind::SILGlobalVariable: if (auto decl = getSILGlobalVariable()->getDecl()) return decl->getDeclContext(); return nullptr; case Kind::ProtocolWitnessTable: case Kind::ProtocolConformanceDescriptor: 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::TypeMetadataLazyCacheVariable: case Kind::TypeMetadataDemanglingCacheVariable: 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: return nullptr; } } bool LinkEntity::isAlwaysSharedLinkage() const { switch (getKind()) { case Kind::ModuleDescriptor: case Kind::ExtensionDescriptor: case Kind::AnonymousDescriptor: case Kind::ObjCClassRef: case Kind::TypeMetadataAccessFunction: case Kind::TypeMetadataLazyCacheVariable: case Kind::TypeMetadataDemanglingCacheVariable: return true; default: return false; } }