//===--- IRGenModule.h - Swift Global IR Generation Module ------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file defines the interface used // the AST into LLVM IR. // //===----------------------------------------------------------------------===// #ifndef SWIFT_IRGEN_IRGENMODULE_H #define SWIFT_IRGEN_IRGENMODULE_H #include "Callee.h" #include "IRGen.h" #include "SwiftTargetInfo.h" #include "TypeLayout.h" #include "swift/AST/Decl.h" #include "swift/AST/IRGenOptions.h" #include "swift/AST/LinkLibrary.h" #include "swift/AST/Module.h" #include "swift/AST/ReferenceCounting.h" #include "swift/AST/SourceFile.h" #include "swift/AST/SynthesizedFileUnit.h" #include "swift/Basic/ClusteredBitVector.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/OptimizationMode.h" #include "swift/Basic/SuccessorMap.h" #include "swift/IRGen/ValueWitness.h" #include "swift/SIL/RuntimeEffect.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILModule.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Constant.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Target/TargetMachine.h" #include namespace llvm { class Constant; class ConstantInt; class DataLayout; class Function; class FunctionType; class GlobalVariable; class InlineAsm; class IntegerType; class LLVMContext; class MDNode; class Metadata; class Module; class PointerType; class StructType; class StringRef; class Type; class AttributeList; } namespace clang { class ASTContext; template class CanQual; class CodeGenerator; class CXXDestructorDecl; class Decl; class GlobalDecl; class Type; class ObjCProtocolDecl; class PointerAuthSchema; namespace CodeGen { class CGFunctionInfo; class CodeGenModule; } } namespace swift { class GenericSignature; class AssociatedConformance; class ASTContext; class BaseConformance; class BraceStmt; class CanType; class GeneratedModule; class GenericRequirement; class LinkLibrary; class SILFunction; class IRGenOptions; class NormalProtocolConformance; class ProtocolConformance; class ProtocolCompositionType; class RootProtocolConformance; class SILCoverageMap; struct SILDeclRef; class SILDefaultWitnessTable; class SILDifferentiabilityWitness; class SILGlobalVariable; class SILModule; class SILDefaultOverrideTable; class SILProperty; class SILType; class SILVTable; class SILWitnessTable; class SourceLoc; class SourceFile; class Type; enum class TypeReferenceKind : unsigned; namespace Lowering { class TypeConverter; } namespace irgen { class Address; class ClangTypeConverter; class ClassMetadataLayout; class ConformanceDescription; class ConformanceInfo; class ConstantInitBuilder; struct ConstantIntegerLiteral; class ConstantIntegerLiteralMap; class DebugTypeInfo; class EnumImplStrategy; class EnumMetadataLayout; class ExplosionSchema; class FixedTypeInfo; class ForeignClassMetadataLayout; class ForeignFunctionInfo; class FormalType; class FunctionPointerKind; class HeapLayout; class StructLayout; class IRGenDebugInfo; class IRGenFunction; struct IRLinkage; class LinkEntity; class LoadableTypeInfo; class MetadataLayout; class NecessaryBindings; class NominalMetadataLayout; class OutliningMetadataCollector; class PointerAuthEntity; class ProtocolInfo; enum class ProtocolInfoKind : uint8_t; class Signature; class StructMetadataLayout; struct SymbolicMangling; class TypeConverter; class TypeInfo; enum class TypeMetadataAddress; enum class ValueWitness : unsigned; enum class ClassMetadataStrategy; class IRGenModule; /// A type descriptor for a field type accessor. class FieldTypeInfo { llvm::PointerIntPair Info; /// Bits in the "int" part of the Info pair. enum : unsigned { /// Flag indicates that the case is indirectly stored in a box. Indirect = 1, /// Indicates a weak optional reference Weak = 2, }; static unsigned getFlags(bool indirect, bool weak) { return (indirect ? Indirect : 0) | (weak ? Weak : 0); // | (blah ? Blah : 0) ... } public: FieldTypeInfo(CanType type, bool indirect, bool weak) : Info(type, getFlags(indirect, weak)) {} CanType getType() const { return Info.getPointer(); } bool isIndirect() const { return Info.getInt() & Indirect; } bool isWeak() const { return Info.getInt() & Weak; } bool hasFlags() const { return Info.getInt() != 0; } }; enum RequireMetadata_t : bool { DontRequireMetadata = false, RequireMetadata = true }; enum class TypeMetadataCanonicality : bool { Noncanonical, Canonical, }; /// The principal singleton which manages all of IR generation. /// /// The IRGenerator delegates the emission of different top-level entities /// to different instances of IRGenModule, each of which creates a different /// llvm::Module. /// /// In single-threaded compilation, the IRGenerator creates only a single /// IRGenModule. In multi-threaded compilation, it contains multiple /// IRGenModules - one for each LLVM module (= one for each input/output file). class IRGenerator { public: const IRGenOptions &Opts; SILModule &SIL; private: llvm::DenseMap GenModules; // Stores the IGM from which a function is referenced the first time. // It is used if a function has no source-file association. llvm::DenseMap DefaultIGMForFunction; // Stores the IGM from which a global variable is referenced the first time. // It is used if a global variable has no source-file association. llvm::DenseMap DefaultIGMForGlobalVariable; // The IGMs where specializations of functions are emitted. The key is the // non-specialized function. // Storing all specializations of a function in the same IGM increases the // chances of function merging. llvm::DenseMap IGMForSpecializations; // The IGM of the first source file. IRGenModule *PrimaryIGM = nullptr; // The current IGM for which IR is generated. IRGenModule *CurrentIGM = nullptr; /// If this is true, adding anything to the below queues is an error. bool FinishedEmittingLazyDefinitions = false; /// A map recording if metadata can be emitted lazily for each nominal type. llvm::DenseMap HasLazyMetadata; struct LazyTypeGlobalsInfo { /// Is there a use of the type metadata? bool IsMetadataUsed = false; /// Is there a use of the nominal type descriptor? bool IsDescriptorUsed = false; /// Have we already emitted type metadata? bool IsMetadataEmitted = false; /// Have we already emitted a type context descriptor? bool IsDescriptorEmitted = false; }; /// The set of type metadata that have been enqueued for lazy emission. llvm::DenseMap LazyTypeGlobals; /// The queue of lazy type metadata to emit. llvm::SmallVector LazyTypeMetadata; /// The queue of lazy type context descriptors to emit. llvm::SmallVector LazyTypeContextDescriptors; /// Field metadata records that have already been lazily emitted, or are /// queued up. llvm::SmallPtrSet LazilyEmittedFieldMetadata; /// Maps every generic type whose metadata is specialized within the module /// to its specializations. llvm::DenseMap< NominalTypeDecl *, llvm::SmallVector, 4>> MetadataPrespecializationsForGenericTypes; llvm::DenseMap> CanonicalSpecializedAccessorsForGenericTypes; /// The queue of specialized generic types whose prespecialized metadata to /// emit. llvm::SmallVector, 4> LazySpecializedTypeMetadataRecords; llvm::SmallPtrSet LazilyReemittedTypeContextDescriptors; /// The queue of metadata accessors to emit. /// /// The accessors must be emitted after everything else which might result in /// a statically-known-canonical prespecialization. llvm::SmallSetVector LazyMetadataAccessors; /// The queue of prespecialized metadata accessors to emit. llvm::SmallSetVector LazyCanonicalSpecializedMetadataAccessors; struct LazyOpaqueInfo { bool IsDescriptorUsed = false; bool IsDescriptorEmitted = false; }; /// The set of opaque types enqueued for lazy emission. llvm::DenseMap LazyOpaqueTypes; /// The queue of opaque type descriptors to emit. llvm::SmallVector LazyOpaqueTypeDescriptors; /// The set of extension contenxts enqueued for lazy emission. llvm::DenseMap LazyExtensions; /// The queue of opaque type descriptors to emit. llvm::TinyPtrVector LazyExtensionDescriptors; public: /// The set of eagerly emitted opaque types. llvm::SmallPtrSet EmittedNonLazyOpaqueTypeDecls; private: /// The queue of lazy field metadata records to emit. llvm::SmallVector LazyFieldDescriptors; llvm::SetVector DynamicReplacements; /// SIL functions that have already been lazily emitted, or are queued up. llvm::SmallPtrSet LazilyEmittedFunctions; /// The queue of SIL functions to emit. llvm::SmallVector LazyFunctionDefinitions; /// SIL global variables that have already been lazily emitted, or are /// queued up. llvm::SmallPtrSet LazilyEmittedGlobalVariables; /// The queue of SIL global variables to emit. llvm::SmallVector LazyGlobalVariables; /// Witness tables that have already been lazily emitted, or are queued up. llvm::SmallPtrSet LazilyEmittedWitnessTables; /// The queue of lazy witness tables to emit. llvm::SmallVector LazyWitnessTables; llvm::SmallVector LazyClassMetadata; llvm::SmallPtrSet LazilyEmittedClassMetadata; llvm::SmallVector LazySpecializedClassMetadata; llvm::SmallPtrSet LazilyEmittedSpecializedClassMetadata; llvm::SmallVector ClassesForEagerInitialization; llvm::SmallVector ObjCActorsNeedingSuperclassSwizzle; /// The order in which all the SIL function definitions should /// appear in the translation unit. llvm::DenseMap FunctionOrder; /// The queue of IRGenModules for multi-threaded compilation. SmallVector Queue; std::atomic QueueIndex; friend class CurrentIGMPtr; public: explicit IRGenerator(const IRGenOptions &opts, SILModule &module); /// Attempt to create an llvm::TargetMachine for the current target. std::unique_ptr createTargetMachine(); /// Add an IRGenModule for a source file. /// Should only be called from IRGenModule's constructor. void addGenModule(SourceFile *SF, IRGenModule *IGM); /// Get an IRGenModule for a source file. IRGenModule *getGenModule(SourceFile *SF); SourceFile *getSourceFile(IRGenModule *module) { for (auto pair : GenModules) { if (pair.second == module) { return pair.first; } } return nullptr; } /// Get an IRGenModule for a declaration context. /// Returns the IRGenModule of the containing source file, or if this cannot /// be determined, returns the primary IRGenModule. IRGenModule *getGenModule(DeclContext *ctxt); /// Get an IRGenModule for a function. /// Returns the IRGenModule of the containing source file, or if this cannot /// be determined, returns the IGM from which the function is referenced the /// first time. IRGenModule *getGenModule(SILFunction *f); /// Get an IRGenModule for a global variable. /// Returns the IRGenModule of the containing source file, or if this cannot /// be determined, returns the IGM from which the global variable is /// referenced the first time. IRGenModule *getGenModule(SILGlobalVariable *v); /// Returns the primary IRGenModule. This is the first added IRGenModule. /// It is used for everything which cannot be correlated to a specific source /// file. And of course, in single-threaded compilation there is only the /// primary IRGenModule. IRGenModule *getPrimaryIGM() const { assert(PrimaryIGM); return PrimaryIGM; } bool hasMultipleIGMs() const { return GenModules.size() >= 2; } llvm::DenseMap::iterator begin() { return GenModules.begin(); } llvm::DenseMap::iterator end() { return GenModules.end(); } /// Emit functions, variables and tables which are needed anyway, e.g. because /// they are externally visible. void emitGlobalTopLevel(const std::vector &LinkerDirectives); /// Emit references to each of the protocol descriptors defined in this /// IR module. void emitSwiftProtocols(); /// Emit the protocol conformance records needed by each IR module. void emitProtocolConformances(); /// Emit type metadata records for types without explicit protocol conformance. void emitTypeMetadataRecords(); /// Emit type metadata records for functions that can be looked up by name at /// runtime. void emitAccessibleFunctions(); /// Emit reflection metadata records for builtin and imported types referenced /// from this module. void emitBuiltinReflectionMetadata(); /// Emit a symbol identifying the reflection metadata version. void emitReflectionMetadataVersion(); void emitEagerClassInitialization(); void emitObjCActorsNeedingSuperclassSwizzle(); // Emit the code to replace dynamicReplacement(for:) functions. void emitDynamicReplacements(); // Emit info that describes the entry point to the module, if it has one. void emitEntryPointInfo(); /// Emit coverage mapping info. void emitCoverageMapping(); /// Checks if metadata for this type can be emitted lazily. This is true for /// non-public types as well as imported types, except for classes and /// protocols which are always emitted eagerly. bool hasLazyMetadata(TypeDecl *type); /// Emit everything which is reachable from already emitted IR. void emitLazyDefinitions(); void addLazyFunction(SILFunction *f); void addLazyGlobalVariable(SILGlobalVariable *v); void addDynamicReplacement(SILFunction *f) { DynamicReplacements.insert(f); } void forceLocalEmitOfLazyFunction(SILFunction *f) { DefaultIGMForFunction[f] = CurrentIGM; } void ensureRelativeSymbolCollocation(SILWitnessTable &wt); void ensureRelativeSymbolCollocation(SILDefaultWitnessTable &wt); void ensureRelativeSymbolCollocation(SILDefaultOverrideTable &ot); llvm::SmallVector, 4> metadataPrespecializationsForType(NominalTypeDecl *type) { return MetadataPrespecializationsForGenericTypes.lookup(type); } void noteLazyReemissionOfNominalTypeDescriptor(NominalTypeDecl *decl) { assert(decl->isAvailableDuringLowering()); LazilyReemittedTypeContextDescriptors.insert(decl); } bool isLazilyReemittingNominalTypeDescriptor(NominalTypeDecl *decl) { return LazilyReemittedTypeContextDescriptors.find(decl) != std::end(LazilyReemittedTypeContextDescriptors); } void noteUseOfMetadataAccessor(NominalTypeDecl *decl) { assert(decl->isAvailableDuringLowering()); if (LazyMetadataAccessors.count(decl) == 0) { LazyMetadataAccessors.insert(decl); } } void noteUseOfClassMetadata(CanType classType); void noteUseOfSpecializedClassMetadata(CanType classType); void noteUseOfTypeMetadata(NominalTypeDecl *type) { noteUseOfTypeGlobals(type, true, RequireMetadata); } void noteUseOfSpecializedGenericTypeMetadata( IRGenModule &IGM, CanType theType, TypeMetadataCanonicality canonicality); void noteUseOfCanonicalSpecializedMetadataAccessor(CanType forType); void noteUseOfTypeMetadata(CanType type) { type.visit([&](Type t) { if (auto *nominal = t->getAnyNominal()) noteUseOfTypeMetadata(nominal); }); } void noteUseOfTypeContextDescriptor(NominalTypeDecl *type, RequireMetadata_t requireMetadata) { noteUseOfTypeGlobals(type, false, requireMetadata); } void noteUseOfOpaqueTypeDescriptor(OpaqueTypeDecl *opaque); void noteUseOfExtensionDescriptor(ExtensionDecl *ext); void noteUseOfFieldDescriptor(NominalTypeDecl *type); void noteUseOfFieldDescriptors(CanType type) { type.visit([&](Type t) { if (auto *nominal = t->getAnyNominal()) noteUseOfFieldDescriptor(nominal); }); } private: void noteUseOfTypeGlobals(NominalTypeDecl *type, bool isUseOfMetadata, RequireMetadata_t requireMetadata); public: /// Return true if \p wt can be emitted lazily. bool canEmitWitnessTableLazily(SILWitnessTable *wt); /// Adds \p Conf to LazyWitnessTables if it has not been added yet. void addLazyWitnessTable(const ProtocolConformance *Conf); void addClassForEagerInitialization(ClassDecl *ClassDecl); void addBackDeployedObjCActorInitialization(ClassDecl *ClassDecl); unsigned getFunctionOrder(SILFunction *F) { auto it = FunctionOrder.find(F); assert(it != FunctionOrder.end() && "no order number for SIL function definition?"); return it->second; } /// In multi-threaded compilation fetch the next IRGenModule from the queue. IRGenModule *fetchFromQueue() { int idx = QueueIndex++; if (idx < (int)Queue.size()) { return Queue[idx]; } return nullptr; } /// Return the effective triple used by clang. llvm::Triple getEffectiveClangTriple(); /// Return the effective variant triple used by clang. llvm::Triple getEffectiveClangVariantTriple(); const llvm::StringRef getClangDataLayoutString(); }; class ConstantReference { public: enum Directness : bool { Direct, Indirect }; private: llvm::PointerIntPair ValueAndIsIndirect; public: ConstantReference() {} ConstantReference(llvm::Constant *value, Directness isIndirect) : ValueAndIsIndirect(value, isIndirect) {} Directness isIndirect() const { return ValueAndIsIndirect.getInt(); } llvm::Constant *getValue() const { return ValueAndIsIndirect.getPointer(); } llvm::Constant *getDirectValue() const { assert(!isIndirect()); return getValue(); } explicit operator bool() const { return ValueAndIsIndirect.getPointer() != nullptr; } }; /// A reference to a declared type entity. class TypeEntityReference { TypeReferenceKind Kind; llvm::Constant *Value; public: TypeEntityReference(TypeReferenceKind kind, llvm::Constant *value) : Kind(kind), Value(value) {} TypeReferenceKind getKind() const { return Kind; } llvm::Constant *getValue() const { return Value; } }; /// Describes the role of a mangled type reference string. enum class MangledTypeRefRole { /// The mangled type reference is used for field metadata, which is used /// by both in-process and out-of-process reflection, so still requires /// referenced types' metadata to be fully emitted. FieldMetadata, /// The mangled type reference is used for normal metadata. Metadata, /// The mangled type reference is used for reflection metadata. Reflection, /// The mangled type reference is used for a default associated type /// witness. DefaultAssociatedTypeWitness, /// The mangled type reference must be a flat string (i.e. no /// symbolic references) and unique for the target type. FlatUnique, }; struct AccessibleFunction { private: std::string RecordName; std::string FunctionName; bool IsDistributed: 1; CanSILFunctionType Type; llvm::Constant *Address; explicit AccessibleFunction(std::string recordName, std::string funcName, bool isDistributed, CanSILFunctionType type, llvm::Constant *addr) : RecordName(recordName), FunctionName(funcName), IsDistributed(isDistributed), Type(type), Address(addr) {} public: StringRef getRecordName() const { return RecordName; } StringRef getFunctionName() const { return FunctionName; } bool isDistributed() const { return IsDistributed; } CanSILFunctionType getType() const { return Type; } llvm::Constant *getAddress() const { return Address; } static AccessibleFunction forSILFunction(IRGenModule &IGM, SILFunction *func); static AccessibleFunction forDistributed(std::string recordName, std::string accessorName, CanSILFunctionType type, llvm::Constant *address); }; enum class CStringSectionType { Default, ObjCClassName, ObjCMethodName, ObjCMethodType, OSLogString, // Place all new section types above this line NumTypes, // Place all alias below this line ObjCPropertyName = ObjCMethodName, }; /// IRGenModule - Primary class for emitting IR for global declarations. /// class IRGenModule { public: // The ABI version of the Swift data generated by this file. static const uint32_t swiftVersion = 7; std::unique_ptr LLVMContext; IRGenerator &IRGen; ASTContext &Context; std::unique_ptr ClangCodeGen; llvm::Module &Module; const llvm::DataLayout DataLayout; const llvm::Triple Triple; const llvm::Triple VariantTriple; std::unique_ptr TargetMachine; ModuleDecl *getSwiftModule() const; AvailabilityRange getAvailabilityRange() const; Lowering::TypeConverter &getSILTypes() const; SILModule &getSILModule() const { return IRGen.SIL; } const IRGenOptions &getOptions() const { return IRGen.Opts; } SILModuleConventions silConv; ModuleDecl *ObjCModule = nullptr; ModuleDecl *ClangImporterModule = nullptr; std::unique_ptr RemarkStream; llvm::StringMap OriginalModules; llvm::SmallString<128> OutputFilename; llvm::SmallString<128> MainInputFilenameForDebugInfo; /// Order dependency -- TargetInfo must be initialized after Opts. const SwiftTargetInfo TargetInfo; /// Holds lexical scope info, etc. Is a nullptr if we compile without -g. std::unique_ptr DebugInfo; /// A global variable which stores the hash of the module. Used for /// incremental compilation. llvm::GlobalVariable *ModuleHash; TypeLayoutCache typeLayoutCache; /// Does the current target require Objective-C interoperation? bool ObjCInterop = true; /// Is the current target using the Darwin pre-stable ABI's class marker bit? bool UseDarwinPreStableABIBit = true; /// Should we add value names to local IR values? bool EnableValueNames = false; // Should `swifterror` attribute be explicitly added for the target ABI. bool ShouldUseSwiftError; llvm::Type *VoidTy; /// void (usually {}) llvm::IntegerType *Int1Ty; /// i1 llvm::IntegerType *Int8Ty; /// i8 llvm::IntegerType *Int16Ty; /// i16 llvm::IntegerType *Int32Ty; /// i32 llvm::IntegerType *RelativeAddressTy; llvm::IntegerType *Int64Ty; /// i64 union { llvm::IntegerType *SizeTy; /// usually i32 or i64 llvm::IntegerType *IntPtrTy; llvm::IntegerType *MetadataKindTy; llvm::IntegerType *OnceTy; llvm::IntegerType *FarRelativeAddressTy; llvm::IntegerType *ProtocolDescriptorRefTy; }; llvm::IntegerType *ObjCBoolTy; /// i8 or i1 union { llvm::PointerType *PtrTy; /// ptr llvm::PointerType *BridgeObjectPtrTy; /// %swift.bridge* llvm::PointerType *CaptureDescriptorPtrTy; llvm::PointerType *ContinuationAsyncContextPtrTy; llvm::PointerType *CoroAllocationTy; llvm::PointerType *CoroAllocatorPtrTy; llvm::PointerType *CoroFunctionPointerPtrTy; llvm::PointerType *DynamicReplacementLinkEntryPtrTy; /// %link_entry* llvm::PointerType *DynamicReplacementsPtrTy; /// { i8**, i8* }* llvm::PointerType *ErrorPtrTy; /// %swift.error* llvm::PointerType *FieldDescriptorPtrTy; llvm::PointerType *FieldDescriptorPtrPtrTy; llvm::PointerType *FullBoxMetadataPtrTy; /// %swift.full_boxmetadata* llvm::PointerType *FullHeapMetadataPtrTy; /// %swift.full_heapmetadata* llvm::PointerType *FullTypeMetadataPtrTy; /// %swift.full_type* llvm::PointerType *FunctionPtrTy; llvm::PointerType *Int8PtrTy; /// i8* llvm::PointerType *Int8PtrPtrTy; /// i8** llvm::PointerType *Int32PtrTy; /// i32 * llvm::PointerType *ObjCBlockPtrTy; /// %objc_block* llvm::PointerType *ObjCClassPtrTy; /// %objc_class* llvm::PointerType *ObjCPtrTy; /// %objc_object* llvm::PointerType *ObjCSELTy; llvm::PointerType *ObjCSuperPtrTy; /// %objc_super* llvm::PointerType *OpaquePtrTy; /// %swift.opaque* llvm::PointerType *OpaqueTypeDescriptorPtrTy; llvm::PointerType *OpenedErrorTriplePtrTy; /// { %swift.opaque*, %swift.type*, i8** }* llvm::PointerType *ProtocolConformanceDescriptorPtrTy; llvm::PointerType *ProtocolDescriptorPtrTy; /// %swift.protocol* llvm::PointerType *ProtocolRecordPtrTy; llvm::PointerType *RelativeAddressPtrTy; llvm::PointerType *RefCountedPtrTy; /// %swift.refcounted* #define CHECKED_REF_STORAGE(Name, ...) \ llvm::PointerType *Name##ReferencePtrTy; /// %swift. #name _reference* #include "swift/AST/ReferenceStorage.def" llvm::PointerType *SwiftAsyncLetPtrTy; llvm::PointerType *SwiftContextPtrTy; llvm::PointerType *SwiftJobPtrTy; llvm::PointerType *SwiftTaskGroupPtrTy; llvm::PointerType *SwiftTaskOptionRecordPtrTy; llvm::PointerType *SwiftTaskPtrTy; llvm::PointerType *AsyncFunctionPointerPtrTy; llvm::PointerType *TaskContinuationFunctionPtrTy; llvm::PointerType *TupleTypeMetadataPtrTy; /// %swift.tuple_type* llvm::PointerType *TypeContextDescriptorPtrTy; llvm::PointerType *TypeMetadataPtrTy; /// %swift.type* llvm::PointerType *TypeMetadataPtrPtrTy; /// %swift.type** llvm::PointerType *TypeMetadataRecordPtrTy; llvm::PointerType *UnknownRefCountedPtrTy; llvm::PointerType *WitnessTablePtrTy; llvm::PointerType *WitnessTablePtrPtrTy; /// i8*** llvm::PointerType *WitnessTableTy; }; llvm::StructType *RefCountedStructTy;/// %swift.refcounted = type { ... } Size RefCountedStructSize; /// sizeof(%swift.refcounted) #define CHECKED_REF_STORAGE(Name, ...) \ llvm::StructType *Name##ReferenceStructTy; /// %swift. #name _reference #include "swift/AST/ReferenceStorage.def" llvm::Constant *RefCountedNull; /// %swift.refcounted* null llvm::StructType *FunctionPairTy; /// { i8*, %swift.refcounted* } llvm::StructType *NoEscapeFunctionPairTy; /// { i8*, %swift.opaque* } llvm::FunctionType *DeallocatingDtorTy; /// void (%swift.refcounted*) llvm::StructType *TypeMetadataStructTy; /// %swift.type = type { ... } union { llvm::StructType *TypeMetadataResponseTy; /// { %swift.type*, iSize } llvm::StructType *TypeMetadataDependencyTy; /// { %swift.type*, iSize } }; llvm::StructType *OffsetPairTy; /// { iSize, iSize } llvm::StructType *FullTypeLayoutTy; /// %swift.full_type_layout = { ... } llvm::StructType *TypeLayoutTy; /// %swift.type_layout = { ... } llvm::StructType *TupleTypeMetadataTy; /// %swift.tuple_type llvm::StructType *FullHeapMetadataStructTy; /// %swift.full_heapmetadata = type { ... } llvm::StructType *FullBoxMetadataStructTy; /// %swift.full_boxmetadata = type { ... } llvm::StructType *FullTypeMetadataStructTy; /// %swift.full_type = type { ... } llvm::StructType *FullExistentialTypeMetadataStructTy; /// %swift.full_existential_type = type { ... } llvm::StructType *FullForeignTypeMetadataStructTy; /// %swift.full_foreign_type = type { ... } llvm::StructType *ProtocolDescriptorStructTy; /// %swift.protocol = type { ... } llvm::StructType *ProtocolRequirementStructTy; /// %swift.protocol_requirement llvm::StructType *OpaqueTy; /// %swift.opaque llvm::StructType *ObjCClassStructTy; /// %objc_class llvm::StructType *ObjCSuperStructTy; /// %objc_super llvm::StructType *ObjCBlockStructTy; /// %objc_block llvm::FunctionType *ObjCUpdateCallbackTy; llvm::StructType *ObjCFullResilientClassStubTy; /// %objc_full_class_stub llvm::StructType *ObjCResilientClassStubTy; /// %objc_class_stub llvm::StructType *ProtocolRecordTy; llvm::StructType *ProtocolConformanceDescriptorTy; llvm::StructType *TypeContextDescriptorTy; llvm::StructType *ClassContextDescriptorTy; llvm::StructType *MethodDescriptorStructTy; /// %swift.method_descriptor llvm::StructType *MethodOverrideDescriptorStructTy; /// %swift.method_override_descriptor llvm::StructType *MethodDefaultOverrideDescriptorStructTy; /// %swift.method_default_override_descriptor llvm::StructType *TypeMetadataRecordTy; llvm::StructType *FieldDescriptorTy; llvm::StructType *OpenedErrorTripleTy; /// { %swift.opaque*, %swift.type*, i8** } llvm::StructType *OpaqueTypeDescriptorTy; llvm::Type *FloatTy; llvm::Type *DoubleTy; llvm::StructType *DynamicReplacementsTy; // { i8**, i8* } llvm::StructType *DynamicReplacementLinkEntryTy; // %link_entry = { i8*, %link_entry*} llvm::StructType *DynamicReplacementKeyTy; // { i32, i32} llvm::StructType *AccessibleFunctionRecordTy; // { i32*, i32*, i32*, i32} // clang-format off llvm::StructType *AsyncFunctionPointerTy; // { i32, i32 } llvm::StructType *SwiftContextTy; llvm::StructType *SwiftTaskTy; llvm::StructType *SwiftJobTy; llvm::StructType *SwiftExecutorTy; llvm::StructType *SwiftTaskOptionRecordTy; llvm::StructType *SwiftInitialSerialExecutorTaskOptionRecordTy; llvm::StructType *SwiftTaskGroupTaskOptionRecordTy; llvm::StructType *SwiftInitialTaskExecutorUnownedPreferenceTaskOptionRecordTy; llvm::StructType *SwiftInitialTaskExecutorOwnedPreferenceTaskOptionRecordTy; llvm::StructType *SwiftInitialTaskNameTaskOptionRecordTy; llvm::StructType *SwiftResultTypeInfoTaskOptionRecordTy; llvm::IntegerType *ExecutorFirstTy; llvm::IntegerType *ExecutorSecondTy; llvm::FunctionType *TaskContinuationFunctionTy; llvm::StructType *AsyncTaskAndContextTy; llvm::StructType *ContinuationAsyncContextTy; llvm::StructType *ClassMetadataBaseOffsetTy; llvm::StructType *DifferentiabilityWitnessTy; // { i8*, i8* } // clang-format on llvm::StructType *CoroFunctionPointerTy; // { i32, i32, i64 } llvm::FunctionType *CoroAllocateFnTy; llvm::FunctionType *CoroDeallocateFnTy; llvm::IntegerType *CoroAllocatorFlagsTy; llvm::StructType *CoroAllocatorTy; llvm::StructType *SwiftImplicitActorType; // { %swift.refcounted, i8* } llvm::GlobalVariable *TheTrivialPropertyDescriptor = nullptr; llvm::Constant *swiftImmortalRefCount = nullptr; llvm::Constant *swiftStaticArrayMetadata = nullptr; llvm::StructType * createTransientStructType(StringRef name, std::initializer_list types, bool packed = false); /// Used to create unique names for class layout types with tail allocated /// elements. unsigned TailElemTypeID = 0; unsigned InvariantMetadataID; /// !invariant.load unsigned DereferenceableID; /// !dereferenceable llvm::MDNode *InvariantNode; #ifdef CHECK_RUNTIME_EFFECT_ANALYSIS RuntimeEffect effectOfRuntimeFuncs = RuntimeEffect::NoEffect; SmallVector emittedRuntimeFuncs; void registerRuntimeEffect(ArrayRef realtime, const char *funcName); #endif llvm::CallingConv::ID C_CC; /// standard C calling convention llvm::CallingConv::ID DefaultCC; /// default calling convention llvm::CallingConv::ID SwiftCC; /// swift calling convention llvm::CallingConv::ID SwiftAsyncCC; /// swift calling convention for async llvm::CallingConv::ID SwiftCoroCC; /// swift calling convention for callee-allocated coroutines llvm::CallingConv::ID SwiftDirectRR_CC; /// swift direct retain/release calling convention /// What kind of tail call should be used for async->async calls. llvm::CallInst::TailCallKind AsyncTailCallKind; Signature getAssociatedTypeWitnessTableAccessFunctionSignature(); /// Get the bit width of an integer type for the target platform. unsigned getBuiltinIntegerWidth(BuiltinIntegerType *t); unsigned getBuiltinIntegerWidth(BuiltinIntegerWidth w); Size getPointerSize() const { return PtrSize; } Alignment getPointerAlignment() const { // We always use the pointer's width as its swift ABI alignment. return Alignment(PtrSize.getValue()); } Alignment getWitnessTableAlignment() const { return getPointerAlignment(); } Alignment getTypeMetadataAlignment() const { return getPointerAlignment(); } Alignment getAsyncContextAlignment() const; Alignment getCoroStaticFrameAlignment() const; /// Return the offset, relative to the address point, of the start of the /// type-specific members of an enum metadata. Size getOffsetOfEnumTypeSpecificMetadataMembers() { return getPointerSize() * 2; } /// Return the offset, relative to the address point, of the start of the /// type-specific members of a struct metadata. Size getOffsetOfStructTypeSpecificMetadataMembers() { return getPointerSize() * 2; } Size::int_type getOffsetInWords(Size offset) { assert(offset.isMultipleOf(getPointerSize())); return offset / getPointerSize(); } llvm::Type *getReferenceType(ReferenceCounting style); llvm::PointerType *getOpaquePointerType(unsigned AddressSpace) const; static bool isLoadableReferenceAddressOnly(ReferenceCounting style) { switch (style) { case ReferenceCounting::Native: return false; case ReferenceCounting::Unknown: case ReferenceCounting::ObjC: case ReferenceCounting::Block: case ReferenceCounting::None: case ReferenceCounting::Custom: return true; case ReferenceCounting::Bridge: case ReferenceCounting::Error: llvm_unreachable("loadable references to this type are not supported"); } llvm_unreachable("Not a valid ReferenceCounting."); } /// Return the spare bit mask to use for types that comprise heap object /// pointers. const SpareBitVector &getHeapObjectSpareBits() const; const SpareBitVector &getFunctionPointerSpareBits() const; const SpareBitVector &getWitnessTablePtrSpareBits() const; /// Return runtime specific extra inhabitant and spare bits policies. unsigned getReferenceStorageExtraInhabitantCount(ReferenceOwnership ownership, ReferenceCounting style) const; SpareBitVector getReferenceStorageSpareBits(ReferenceOwnership ownership, ReferenceCounting style) const; APInt getReferenceStorageExtraInhabitantValue(unsigned bits, unsigned index, ReferenceOwnership ownership, ReferenceCounting style) const; APInt getReferenceStorageExtraInhabitantMask(ReferenceOwnership ownership, ReferenceCounting style) const; llvm::Type *getFixedBufferTy(); llvm::Type *getExistentialType(unsigned numTables); llvm::Type *getValueWitnessTy(ValueWitness index); Signature getValueWitnessSignature(ValueWitness index); llvm::StructType *getIntegerLiteralTy(); llvm::StructType *getValueWitnessTableTy(); llvm::StructType *getEnumValueWitnessTableTy(); llvm::IntegerType *getTypeMetadataRequestParamTy(); llvm::StructType *getTypeMetadataResponseTy(); void unimplemented(SourceLoc, StringRef Message); [[noreturn]] void fatal_unimplemented(SourceLoc, StringRef Message); void error(SourceLoc loc, const Twine &message); bool shouldPrespecializeGenericMetadata(); bool canMakeStaticObjectReadOnly(SILType objectType); ClassDecl *getStaticArrayStorageDecl(); #define FEATURE(N, V) \ bool is##N##FeatureAvailable(const ASTContext &context); \ inline bool is##N##FeatureAvailable() { \ return is##N##FeatureAvailable(Context); \ } #include "swift/AST/FeatureAvailability.def" bool canUseObjCSymbolicReferences(); Size getAtomicBoolSize() const { return AtomicBoolSize; } Alignment getAtomicBoolAlignment() const { return AtomicBoolAlign; } enum class ObjCLabelType { ClassName, MethodVarName, MethodVarType, PropertyName, }; std::string GetObjCSectionName(StringRef Section, StringRef MachOAttributes); void SetCStringLiteralSection(llvm::GlobalVariable *GV, ObjCLabelType Type); void addAsyncCoroIDMapping(llvm::GlobalVariable *asyncFunctionPointer, llvm::CallInst *coro_id_builtin); llvm::CallInst *getAsyncCoroIDMapping( llvm::GlobalVariable *asyncFunctionPointer); void markAsyncFunctionPointerForPadding( llvm::GlobalVariable *asyncFunctionPointer); bool isAsyncFunctionPointerMarkedForPadding( llvm::GlobalVariable *asyncFunctionPointer); private: Size PtrSize; Size AtomicBoolSize; Alignment AtomicBoolAlign; llvm::Type *FixedBufferTy; /// [N x i8], where N == 3 * sizeof(void*) llvm::Type *ValueWitnessTys[MaxNumValueWitnesses]; llvm::FunctionType *AssociatedTypeWitnessTableAccessFunctionTy = nullptr; llvm::StructType *GenericWitnessTableCacheTy = nullptr; llvm::StructType *IntegerLiteralTy = nullptr; llvm::StructType *ValueWitnessTableTy = nullptr; llvm::StructType *EnumValueWitnessTableTy = nullptr; llvm::DenseMap SpareBitsForTypes; // Mapping of AsyncFunctionPointer records to their corresponding // `@llvm.coro.id.async` intrinsic tag in the function implementation. // This is used for a runtime bug workaround where we need to pad the initial // context size for tasks used as `async let` entry points. // // An entry in the map may have a null value, to indicate that a not-yet- // emitted async function pointer should get the padding applied when it is // emitted. llvm::DenseMap AsyncCoroIDsForPadding; /// The personality function used for foreign exception handling in this /// module. llvm::Function *foreignExceptionHandlingPersonalityFunc = nullptr; public: /// The set of emitted foreign function thunks that trap on exception in the /// underlying call that the thunk dispatches. llvm::SmallPtrSet emittedForeignFunctionThunksWithExceptionTraps; //--- Types ----------------------------------------------------------------- const ProtocolInfo &getProtocolInfo(ProtocolDecl *D, ProtocolInfoKind kind); // Not strictly a type operation, but similar. const ConformanceInfo & getConformanceInfo(const ProtocolDecl *protocol, const ProtocolConformance *conformance); SILType getLoweredType(AbstractionPattern orig, Type subst) const; SILType getLoweredType(Type subst) const; const Lowering::TypeLowering &getTypeLowering(SILType type) const; SILTypeProperties getTypeProperties(SILType type) const; SILTypeProperties getTypeProperties(SILType type, TypeExpansionContext forExpansion) const; SILTypeProperties getTypeProperties(AbstractionPattern origType, Type substType, TypeExpansionContext forExpansion) const; bool isTypeABIAccessible(SILType type) const; const TypeInfo &getTypeInfoForUnlowered(AbstractionPattern orig, CanType subst); const TypeInfo &getTypeInfoForUnlowered(AbstractionPattern orig, Type subst); const TypeInfo &getTypeInfoForUnlowered(Type subst); const TypeInfo &getTypeInfoForLowered(CanType T); const TypeInfo &getTypeInfo(SILType T); const TypeInfo &getWitnessTablePtrTypeInfo(); const TypeInfo &getTypeMetadataPtrTypeInfo(); const TypeInfo &getSwiftContextPtrTypeInfo(); const TypeInfo &getTaskContinuationFunctionPtrTypeInfo(); const LoadableTypeInfo &getExecutorTypeInfo(); const TypeInfo &getObjCClassPtrTypeInfo(); const LoadableTypeInfo &getOpaqueStorageTypeInfo(Size size, Alignment align); const LoadableTypeInfo & getReferenceObjectTypeInfo(ReferenceCounting refcounting); const LoadableTypeInfo &getNativeObjectTypeInfo(); const LoadableTypeInfo &getImplicitActorTypeInfo(); const LoadableTypeInfo &getUnknownObjectTypeInfo(); const LoadableTypeInfo &getBridgeObjectTypeInfo(); const LoadableTypeInfo &getRawPointerTypeInfo(); const LoadableTypeInfo &getRawUnsafeContinuationTypeInfo(); llvm::Type *getStorageTypeForUnlowered(Type T); llvm::Type *getStorageTypeForLowered(CanType T); llvm::Type *getStorageType(SILType T); llvm::StructType *createNominalType(CanType type); llvm::StructType *createNominalType(ProtocolCompositionType *T); clang::CanQual getClangType(CanType type); clang::CanQual getClangType(SILType type); clang::CanQual getClangType(SILParameterInfo param, CanSILFunctionType funcTy); const TypeLayoutEntry &getTypeLayoutEntry(SILType T, bool useStructLayouts); const clang::ASTContext &getClangASTContext() { assert(ClangASTContext && "requesting clang AST context without clang importer!"); return *ClangASTContext; } clang::CodeGen::CodeGenModule &getClangCGM() const; CanType getRuntimeReifiedType(CanType type); Type substOpaqueTypesWithUnderlyingTypes(Type type); CanType substOpaqueTypesWithUnderlyingTypes(CanType type); SILType substOpaqueTypesWithUnderlyingTypes(SILType type); ProtocolConformanceRef substOpaqueTypesWithUnderlyingTypes(ProtocolConformanceRef conformance); bool isResilient(NominalTypeDecl *decl, ResilienceExpansion expansion, ClassDecl *asViewedFromRootClass = nullptr); bool hasResilientMetadata(ClassDecl *decl, ResilienceExpansion expansion, ClassDecl *asViewedFromRootClass = nullptr); ResilienceExpansion getResilienceExpansionForAccess(NominalTypeDecl *decl); ResilienceExpansion getResilienceExpansionForLayout(NominalTypeDecl *decl); ResilienceExpansion getResilienceExpansionForLayout(SILGlobalVariable *var); TypeExpansionContext getMaximalTypeExpansionContext() const; bool isResilientConformance(const NormalProtocolConformance *conformance, bool disableOptimizations = false); bool isResilientConformance(const RootProtocolConformance *root, bool disableOptimizations = false); bool isDependentConformance(const RootProtocolConformance *conformance); Alignment getCappedAlignment(Alignment alignment); SpareBitVector getSpareBitsForType(llvm::Type *scalarTy, Size size); MetadataLayout &getMetadataLayout(NominalTypeDecl *decl); NominalMetadataLayout &getNominalMetadataLayout(NominalTypeDecl *decl); StructMetadataLayout &getMetadataLayout(StructDecl *decl); ClassMetadataLayout &getClassMetadataLayout(ClassDecl *decl); EnumMetadataLayout &getMetadataLayout(EnumDecl *decl); ForeignClassMetadataLayout &getForeignMetadataLayout(ClassDecl *decl); ClassMetadataStrategy getClassMetadataStrategy(const ClassDecl *theClass); bool IsWellKnownBuiltinOrStructralType(CanType type) const; private: TypeConverter &Types; friend TypeConverter; const clang::ASTContext *ClangASTContext; llvm::DenseMap MetadataLayouts; void destroyMetadataLayoutMap(); llvm::DenseMap> Conformances; friend class GenericContextScope; friend class LoweringModeScope; //--- Globals --------------------------------------------------------------- public: std::pair createStringConstant( StringRef Str, bool willBeRelativelyAddressed = false, StringRef sectionName = "", StringRef name = ""); llvm::Constant *getAddrOfGlobalString( StringRef utf8, CStringSectionType sectionType = CStringSectionType::Default, bool willBeRelativelyAddressed = false); llvm::Constant *getAddrOfGlobalUTF16String(StringRef utf8); llvm::Constant * getAddrOfGlobalIdentifierString(StringRef utf8, bool willBeRelativelyAddressed = false); llvm::Constant *getAddrOfObjCSelectorRef(StringRef selector); llvm::Constant *getAddrOfObjCSelectorRef(SILDeclRef method); std::string getObjCSelectorName(SILDeclRef method); llvm::Constant *getAddrOfObjCMethodName(StringRef methodName); llvm::Constant *getAddrOfObjCProtocolRecord(ProtocolDecl *proto, ForDefinition_t forDefinition); Address getAddrOfObjCProtocolRef(ProtocolDecl *proto, ForDefinition_t forDefinition); llvm::Constant *getAddrOfKeyPathPattern(KeyPathPattern *pattern, SILLocation diagLoc); llvm::Constant *getAddrOfOpaqueTypeDescriptor(OpaqueTypeDecl *opaqueType, ConstantInit forDefinition); llvm::Constant * emitClangProtocolObject(const clang::ObjCProtocolDecl *objcProtocol); ConstantReference getConstantReferenceForProtocolDescriptor(ProtocolDecl *proto); ConstantIntegerLiteral getConstantIntegerLiteral(APInt value); llvm::Constant *getOrCreateLazyGlobalVariable(LinkEntity entity, llvm::function_ref build, llvm::function_ref finish); void addUsedGlobal(llvm::GlobalValue *global); void addCompilerUsedGlobal(llvm::GlobalValue *global); void addGenericROData(llvm::Constant *addr); void addObjCClass(llvm::Constant *addr, bool nonlazy); void addObjCClassStub(llvm::Constant *addr); void addProtocolConformance(ConformanceDescription &&conformance); void addAccessibleFunction(AccessibleFunction func); llvm::Constant *emitSwiftProtocols(bool asContiguousArray); llvm::Constant *emitProtocolConformances(bool asContiguousArray); llvm::Constant *emitTypeMetadataRecords(bool asContiguousArray); void emitAccessibleFunctions(); void emitAccessibleFunction(StringRef sectionName, const AccessibleFunction &func); llvm::Constant *getConstantSignedFunctionPointer(llvm::Constant *fn, CanSILFunctionType fnType); llvm::Constant *getConstantSignedCFunctionPointer(llvm::Constant *fn); llvm::Constant * getConstantSignedPointer(llvm::Constant *pointer, unsigned key, llvm::Constant *storageAddress, llvm::ConstantInt *otherDiscriminator); llvm::Constant *getConstantSignedPointer(llvm::Constant *pointer, const clang::PointerAuthSchema &schema, const PointerAuthEntity &entity, llvm::Constant *storageAddress); llvm::Constant *getOrCreateHelperFunction( StringRef name, llvm::Type *resultType, ArrayRef paramTypes, llvm::function_ref generate, bool setIsNoInline = false, bool forPrologue = false, bool isPerformanceConstraint = false, IRLinkage *optionalLinkage = nullptr, std::optional specialCallingConv = std::nullopt, std::optional> transformAttrs = std::nullopt); llvm::Constant *getOrCreateRetainFunction(const TypeInfo &objectTI, SILType t, llvm::Type *llvmType, Atomicity atomicity); llvm::Constant * getOrCreateReleaseFunction(const TypeInfo &objectTI, SILType t, llvm::Type *llvmType, Atomicity atomicity, const OutliningMetadataCollector &collector); llvm::Constant *getOrCreateOutlinedInitializeWithTakeFunction( SILType objectType, const TypeInfo &objectTI, const OutliningMetadataCollector &collector); llvm::Constant *getOrCreateOutlinedInitializeWithCopyFunction( SILType objectType, const TypeInfo &objectTI, const OutliningMetadataCollector &collector); llvm::Constant *getOrCreateOutlinedAssignWithTakeFunction( SILType objectType, const TypeInfo &objectTI, const OutliningMetadataCollector &collector); llvm::Constant *getOrCreateOutlinedAssignWithCopyFunction( SILType objectType, const TypeInfo &objectTI, const OutliningMetadataCollector &collector); llvm::Constant *getOrCreateOutlinedDestroyFunction( SILType objectType, const TypeInfo &objectTI, const OutliningMetadataCollector &collector); llvm::Constant *getOrCreateOutlinedEnumTagStoreFunction( SILType T, const TypeInfo &ti, EnumElementDecl *theCase, unsigned caseIdx); llvm::Constant *getOrCreateOutlinedDestructiveProjectDataForLoad( SILType T, const TypeInfo &ti, EnumElementDecl *theCase, unsigned caseIdx); llvm::Constant *getAddrOfClangGlobalDecl(clang::GlobalDecl global, ForDefinition_t forDefinition); private: using CopyAddrHelperGenerator = llvm::function_ref; llvm::Constant *getOrCreateOutlinedCopyAddrHelperFunction( SILType objectType, const TypeInfo &objectTI, const OutliningMetadataCollector &collector, StringRef funcName, CopyAddrHelperGenerator generator); llvm::Constant *getOrCreateGOTEquivalent(llvm::Constant *global, LinkEntity entity); llvm::DenseMap GlobalVars; llvm::DenseMap IndirectAsyncFunctionPointers; llvm::DenseMap IndirectCoroFunctionPointers; llvm::DenseMap GlobalGOTEquivalents; llvm::DenseMap GlobalFuncs; llvm::DenseSet GlobalClangDecls; // Maps sectionName -> string data -> constant std::array< llvm::StringMap>, static_cast(CStringSectionType::NumTypes)> GlobalStrings; llvm::StringMap GlobalUTF16Strings; llvm::StringMap> StringsForTypeRef; llvm::StringMap> FieldNames; llvm::StringMap ObjCSelectorRefs; llvm::StringMap ObjCMethodNames; std::unique_ptr ConstantIntegerLiterals; /// Maps to constant swift 'String's. llvm::StringMap GlobalConstantStrings; llvm::StringMap GlobalConstantUTF16Strings; struct PointerAuthCachesType; PointerAuthCachesType *PointerAuthCaches = nullptr; PointerAuthCachesType &getPointerAuthCaches(); void destroyPointerAuthCaches(); friend class PointerAuthEntity; /// LLVMUsed - List of global values which are required to be /// present in the object file; bitcast to i8*. This is used for /// forcing visibility of symbols which may otherwise be optimized /// out. SmallVector LLVMUsed; /// LLVMCompilerUsed - List of global values which are required to be /// present in the object file; bitcast to i8*. This is used for /// forcing visibility of symbols which may otherwise be optimized /// out. /// /// Similar to LLVMUsed, but emitted as llvm.compiler.used. SmallVector LLVMCompilerUsed; /// Metadata nodes for autolinking info. SmallVector AutolinkEntries; // List of ro_data_t referenced from generic class patterns. SmallVector GenericRODatas; /// List of Objective-C classes, bitcast to i8*. SmallVector ObjCClasses; /// List of Objective-C classes that require nonlazy realization, bitcast to /// i8*. SmallVector ObjCNonLazyClasses; /// List of Objective-C resilient class stubs, bitcast to i8*. SmallVector ObjCClassStubs; /// List of Objective-C categories, bitcast to i8*. SmallVector ObjCCategories; /// List of Objective-C categories on class stubs, bitcast to i8*. SmallVector ObjCCategoriesOnStubs; /// List of non-ObjC protocols described by this module. SmallVector SwiftProtocols; /// List of protocol conformances to generate descriptors for. std::vector ProtocolConformances; /// List of types to generate runtime-resolvable metadata records for that /// are consumable for any Swift runtime. SmallVector RuntimeResolvableTypes; /// List of types to generate runtime-resolvable metadata records for that /// are consumable for any Swift runtime aware of noncopyable types. SmallVector RuntimeResolvableTypes2; /// List of ExtensionDecls corresponding to the generated /// categories. SmallVector ObjCCategoryDecls; /// List of all of the functions, which can be lookup by name /// up at runtime. SmallVector AccessibleFunctions; /// Map of Objective-C protocols and protocol references, bitcast to i8*. /// The interesting global variables relating to an ObjC protocol. struct ObjCProtocolPair { /// The global variable that contains the protocol record. llvm::WeakTrackingVH record; /// The global variable that contains the indirect reference to the /// protocol record. llvm::WeakTrackingVH ref; }; llvm::DenseMap ObjCProtocols; llvm::DenseMap ObjCProtocolSymRefs; llvm::SmallVector LazyObjCProtocolDefinitions; llvm::DenseMap KeyPathPatterns; /// Uniquing key for a fixed type layout record. struct FixedLayoutKey { unsigned size; unsigned numExtraInhabitants; unsigned align: 16; unsigned pod: 1; unsigned bitwiseTakable: 2; }; friend struct ::llvm::DenseMapInfo; llvm::DenseMap PrivateFixedLayouts; /// Captures a static object layout. struct StaticObjectLayout { std::unique_ptr layout; llvm::StructType *containerTy = nullptr; }; /// A cache for layouts of statically initialized objects. llvm::DenseMap StaticObjectLayouts; /// A mapping from order numbers to the LLVM functions which we /// created for the SIL functions with those orders. SuccessorMap EmittedFunctionsByOrder; ObjCProtocolPair getObjCProtocolGlobalVars(ProtocolDecl *proto); llvm::Constant *getObjCProtocolRefSymRefDescriptor(ProtocolDecl *protocol); void emitLazyObjCProtocolDefinitions(); void emitLazyObjCProtocolDefinition(ProtocolDecl *proto); SmallVector UsedConditionals; void emitUsedConditionals(); void emitGlobalLists(); void emitAutolinkInfo(); void cleanupClangCodeGenMetadata(); //--- Remote reflection metadata -------------------------------------------- public: /// Section names. std::string FieldTypeSection; std::string BuiltinTypeSection; std::string AssociatedTypeSection; std::string CaptureDescriptorSection; std::string ReflectionStringsSection; std::string ReflectionTypeRefSection; std::string MultiPayloadEnumDescriptorSection; /// Builtin types referenced by types in this module when emitting /// reflection metadata. llvm::SetVector BuiltinTypes; std::pair getTypeRef(Type type, GenericSignature genericSig, MangledTypeRefRole role); std::pair getTypeRef(CanType type, CanGenericSignature sig, MangledTypeRefRole role); std::pair getLoweredTypeRef(SILType loweredType, CanGenericSignature genericSig, MangledTypeRefRole role); llvm::Constant *emitWitnessTableRefString(CanType type, ProtocolConformanceRef conformance, GenericSignature genericSig, bool shouldSetLowBit); llvm::Constant *getMangledAssociatedConformance( const NormalProtocolConformance *conformance, const AssociatedConformance &requirement); llvm::Constant *getAddrOfStringForTypeRef(StringRef mangling, MangledTypeRefRole role); llvm::Constant *getAddrOfStringForTypeRef(const SymbolicMangling &mangling, MangledTypeRefRole role); /// Retrieve the address of a mangled string used for some kind of metadata /// reference. /// /// \param symbolName The name of the symbol that describes the metadata /// being referenced. /// \param alignment If non-zero, the alignment of the requested variable. /// \param shouldSetLowBit Whether to set the low bit of the result /// constant, which is used by some clients to indicate that the result is /// a mangled name. /// \param body The body of a function that will create the metadata value /// itself, given a constant building and producing a future for the /// initializer. /// \returns the address of the global variable describing this metadata. llvm::Constant *getAddrOfStringForMetadataRef( StringRef symbolName, unsigned alignment, bool shouldSetLowBit, llvm::function_ref body); llvm::Constant *getAddrOfFieldName(StringRef Name); llvm::Constant *getAddrOfCaptureDescriptor(SILFunction &caller, CanSILFunctionType origCalleeType, CanSILFunctionType substCalleeType, SubstitutionMap subs, const HeapLayout &layout); llvm::Constant *getAddrOfBoxDescriptor(SILType boxedType, CanGenericSignature genericSig); /// Produce an associated type witness that refers to the given type. llvm::Constant *getAssociatedTypeWitness(Type type, GenericSignature sig, bool inProtocolContext); void emitAssociatedTypeMetadataRecord(const RootProtocolConformance *C); void emitFieldDescriptor(const NominalTypeDecl *Decl); /// Emit a reflection metadata record for a builtin type referenced /// from this module. void emitBuiltinTypeMetadataRecord(CanType builtinType); /// Emit reflection metadata records for builtin and imported types referenced /// from this module. void emitBuiltinReflectionMetadata(); /// Emit a symbol identifying the reflection metadata version. void emitReflectionMetadataVersion(); const char *getBuiltinTypeMetadataSectionName(); const char *getFieldTypeMetadataSectionName(); const char *getAssociatedTypeMetadataSectionName(); const char *getCaptureDescriptorMetadataSectionName(); const char *getReflectionStringsSectionName(); const char *getReflectionTypeRefSectionName(); const char *getMultiPayloadEnumDescriptorSectionName(); static constexpr const char ObjCClassNameSectionName[] = "__TEXT,__objc_classname,cstring_literals"; static constexpr const char ObjCMethodNameSectionName[] = "__TEXT,__objc_methname,cstring_literals"; static constexpr const char ObjCMethodTypeSectionName[] = "__TEXT,__objc_methtype,cstring_literals"; static constexpr const char OSLogStringSectionName[] = "__TEXT,__oslogstring,cstring_literals"; /// Returns the special builtin types that should be emitted in the stdlib /// module. llvm::ArrayRef getOrCreateSpecialStlibBuiltinTypes(); private: /// The special builtin types that should be emitted in the stdlib module. llvm::SmallVector SpecialStdlibBuiltinTypes; //--- Runtime --------------------------------------------------------------- public: llvm::Constant *getEmptyTupleMetadata(); llvm::Constant *getAnyExistentialMetadata(); llvm::Constant *getAnyObjectExistentialMetadata(); llvm::Constant *getObjCEmptyCachePtr(); llvm::Constant *getObjCEmptyVTablePtr(); llvm::InlineAsm *getObjCRetainAutoreleasedReturnValueMarker(); ClassDecl *getObjCRuntimeBaseForSwiftRootClass(ClassDecl *theClass); ClassDecl *getObjCRuntimeBaseClass(Identifier name, Identifier objcName); ClassDecl *getSwiftNativeNSObjectDecl(); llvm::Module *getModule() const; llvm::AttributeList getAllocAttrs(); llvm::Constant *getDeletedAsyncMethodErrorAsyncFunctionPointer(); llvm::Constant * getDeletedCalleeAllocatedCoroutineMethodErrorCoroFunctionPointer(); private: llvm::Constant *EmptyTupleMetadata = nullptr; llvm::Constant *AnyExistentialMetadata = nullptr; llvm::Constant *AnyObjectExistentialMetadata = nullptr; llvm::Constant *ObjCEmptyCachePtr = nullptr; llvm::Constant *ObjCEmptyVTablePtr = nullptr; llvm::Constant *ObjCISAMaskPtr = nullptr; std::optional ObjCRetainAutoreleasedReturnValueMarker; llvm::DenseMap SwiftRootClasses; llvm::AttributeList AllocAttrs; #define FUNCTION_ID(Id) \ public: \ llvm::Constant *get##Id##Fn(); \ FunctionPointer get##Id##FunctionPointer(); \ llvm::FunctionType *get##Id##FnType(); \ \ private: \ llvm::Constant *Id##Fn = nullptr; #include "swift/Runtime/RuntimeFunctions.def" std::optional FixedClassInitializationFn; llvm::Constant *FixLifetimeFn = nullptr; mutable std::optional HeapPointerSpareBits; //--- Generic --------------------------------------------------------------- public: llvm::Constant *getFixLifetimeFn(); FunctionPointer getFixedClassInitializationFn(); llvm::Function *getAwaitAsyncContinuationFn(); /// The constructor used when generating code. /// /// The \p SF is the source file for which the llvm module is generated when /// doing multi-threaded whole-module compilation. Otherwise it is null. IRGenModule(IRGenerator &irgen, std::unique_ptr &&target, SourceFile *SF, StringRef ModuleName, StringRef OutputFilename, StringRef MainInputFilenameForDebugInfo, StringRef PrivateDiscriminator); /// The constructor used when we just need an IRGenModule for type lowering. IRGenModule(IRGenerator &irgen, std::unique_ptr &&target) : IRGenModule(irgen, std::move(target), /*SF=*/nullptr, "", "", "", "") {} ~IRGenModule(); public: GeneratedModule intoGeneratedModule() &&; public: llvm::LLVMContext &getLLVMContext() const { return *LLVMContext; } void emitSourceFile(SourceFile &SF); void emitSynthesizedFileUnit(SynthesizedFileUnit &SFU); void addLinkLibraries(); void addLinkLibrary(const LinkLibrary &linkLib); /// Attempt to finalize the module. /// /// This can fail, in which it will return false and the module will be /// invalid. bool finalize(); void constructInitialFnAttributes( llvm::AttrBuilder &Attrs, OptimizationMode FuncOptMode = OptimizationMode::NotSet, StackProtectorMode stackProtect = StackProtectorMode::NoStackProtector); void setHasNoFramePointer(llvm::AttrBuilder &Attrs); void setHasNoFramePointer(llvm::Function *F); void setMustHaveFramePointer(llvm::Function *F); llvm::AttributeList constructInitialAttributes(); StackProtectorMode shouldEmitStackProtector(SILFunction *f); llvm::ConstantInt *getMallocTypeId(llvm::Function *fn); void emitProtocolDecl(ProtocolDecl *D); void emitEnumDecl(EnumDecl *D); void emitStructDecl(StructDecl *D); void emitClassDecl(ClassDecl *D); void emitExtension(ExtensionDecl *D); void emitOpaqueTypeDecl(OpaqueTypeDecl *D); /// This method does additional checking vs. \c emitOpaqueTypeDecl /// based on the state and flags associated with the module. void maybeEmitOpaqueTypeDecl(OpaqueTypeDecl *D); void emitSILGlobalVariable(SILGlobalVariable *gv); void emitCoverageMaps(ArrayRef Mappings); void emitSILFunction(SILFunction *f); void emitSILWitnessTable(SILWitnessTable *wt); void emitSILProperty(SILProperty *prop); void emitSILDifferentiabilityWitness(SILDifferentiabilityWitness *dw); llvm::Constant *emitFixedTypeLayout(CanType t, const FixedTypeInfo &ti); void emitProtocolConformance(const ConformanceDescription &record); void emitNestedTypeDecls(DeclRange members); void emitClangDecl(const clang::Decl *decl); void finalizeClangCodeGen(); void finishEmitAfterTopLevel(); Signature getSignature(CanSILFunctionType fnType, const clang::CXXConstructorDecl *cxxCtorDecl = nullptr); Signature getSignature(CanSILFunctionType fnType, FunctionPointerKind kind, bool forStaticCall = false, const clang::CXXConstructorDecl *cxxCtorDecl = nullptr); llvm::FunctionType *getFunctionType(CanSILFunctionType type, llvm::AttributeList &attrs, ForeignFunctionInfo *foreignInfo=nullptr); ForeignFunctionInfo getForeignFunctionInfo(CanSILFunctionType type); void ensureImplicitCXXDestructorBodyIsDefined(clang::CXXDestructorDecl *cxxDtor); llvm::ConstantInt *getInt32(uint32_t value); llvm::ConstantInt *getSize(Size size); llvm::Constant *getAlignment(Alignment align); llvm::Constant *getBool(bool condition); /// Cast the given constant to i8*. llvm::Constant *getOpaquePtr(llvm::Constant *pointer); llvm::Constant *getAddrOfAsyncFunctionPointer(LinkEntity entity); llvm::Constant *getAddrOfAsyncFunctionPointer(SILFunction *function); llvm::Constant *defineAsyncFunctionPointer(LinkEntity entity, ConstantInit init); SILFunction *getSILFunctionForAsyncFunctionPointer(llvm::Constant *afp); llvm::Constant *getAddrOfCoroFunctionPointer(LinkEntity entity); llvm::Constant *getAddrOfCoroFunctionPointer(SILFunction *function); llvm::Constant *defineCoroFunctionPointer(LinkEntity entity, ConstantInit init); SILFunction *getSILFunctionForCoroFunctionPointer(llvm::Constant *cfp); llvm::Constant *getAddrOfGlobalCoroMallocAllocator(); llvm::Constant *getAddrOfGlobalCoroTypedMallocAllocator(); llvm::Constant *getAddrOfGlobalCoroAsyncTaskAllocator(); llvm::Function *getAddrOfDispatchThunk(SILDeclRef declRef, ForDefinition_t forDefinition); void emitDispatchThunk(SILDeclRef declRef); llvm::Function *getAddrOfMethodLookupFunction(ClassDecl *classDecl, ForDefinition_t forDefinition); void emitMethodLookupFunction(ClassDecl *classDecl); llvm::GlobalValue *defineAlias(LinkEntity entity, llvm::Constant *definition, llvm::Type *typeOfDefinitionValue); llvm::GlobalValue *defineMethodDescriptor(SILDeclRef declRef, NominalTypeDecl *nominalDecl, llvm::Constant *definition, llvm::Type *typeOfDefinitionValue); llvm::Constant *getAddrOfMethodDescriptor(SILDeclRef declRef, ForDefinition_t forDefinition); void emitNonoverriddenMethodDescriptor(const SILVTable *VTable, SILDeclRef declRef, ClassDecl *classDecl); Address getAddrOfEnumCase(EnumElementDecl *Case, ForDefinition_t forDefinition); Address getAddrOfFieldOffset(VarDecl *D, ForDefinition_t forDefinition); llvm::Function *getOrCreateValueWitnessFunction(ValueWitness index, FixedPacking packing, CanType abstractType, SILType concreteType, const TypeInfo &type); llvm::Function *getAddrOfValueWitness(CanType concreteType, ValueWitness index, ForDefinition_t forDefinition); llvm::Constant *getAddrOfValueWitnessTable(CanType concreteType, ConstantInit init = ConstantInit()); std::optional getAddrOfIVarInitDestroy(ClassDecl *cd, bool isDestroyer, bool isForeign, ForDefinition_t forDefinition); void setVCallVisibility(llvm::GlobalVariable *var, llvm::GlobalObject::VCallVisibility visibility, std::pair range); void addVTableTypeMetadata( ClassDecl *decl, llvm::GlobalVariable *var, SmallVector, 8> vtableEntries); llvm::GlobalValue *defineTypeMetadata( CanType concreteType, bool isPattern, bool isConstant, ConstantInitFuture init, llvm::StringRef section = {}, SmallVector, 8> vtableEntries = {}); TypeEntityReference getContextDescriptorEntityReference(const LinkEntity &entity); TypeEntityReference getTypeEntityReference(GenericTypeDecl *D); void appendLLVMUsedConditionalEntry(llvm::GlobalVariable *var, llvm::Constant *dependsOn); void appendLLVMUsedConditionalEntry(llvm::GlobalVariable *var, const ProtocolConformance *conformance); void setColocateMetadataSection(llvm::Function *f); void setColocateTypeDescriptorSection(llvm::GlobalVariable *v); llvm::Constant * getAddrOfTypeMetadata(CanType concreteType, TypeMetadataCanonicality canonicality = TypeMetadataCanonicality::Canonical); ConstantReference getAddrOfTypeMetadata(CanType concreteType, SymbolReferenceKind kind, TypeMetadataCanonicality canonicality = TypeMetadataCanonicality::Canonical); llvm::Constant *getAddrOfTypeMetadataPattern(NominalTypeDecl *D); llvm::Constant *getAddrOfTypeMetadataPattern(NominalTypeDecl *D, ConstantInit init, StringRef section); llvm::Function *getAddrOfTypeMetadataCompletionFunction(NominalTypeDecl *D, ForDefinition_t forDefinition); llvm::Function *getAddrOfTypeMetadataInstantiationFunction(NominalTypeDecl *D, ForDefinition_t forDefinition); llvm::Constant *getAddrOfTypeMetadataInstantiationCache(NominalTypeDecl *D, ForDefinition_t forDefinition); llvm::Constant *getAddrOfTypeMetadataSingletonInitializationCache( NominalTypeDecl *D, ForDefinition_t forDefinition); llvm::Function *getAddrOfTypeMetadataAccessFunction(CanType type, ForDefinition_t forDefinition); llvm::Function *getAddrOfGenericTypeMetadataAccessFunction( NominalTypeDecl *nominal, ArrayRef genericArgs, ForDefinition_t forDefinition); llvm::Function * getAddrOfCanonicalSpecializedGenericTypeMetadataAccessFunction( CanType theType, ForDefinition_t forDefinition); llvm::Constant *getAddrOfTypeMetadataLazyCacheVariable(CanType type); llvm::Constant *getAddrOfTypeMetadataDemanglingCacheVariable(CanType type, ConstantInit definition); llvm::Constant *getAddrOfCanonicalPrespecializedGenericTypeCachingOnceToken( NominalTypeDecl *decl); llvm::Constant *getAddrOfNoncanonicalSpecializedGenericTypeMetadataCacheVariable(CanType type); llvm::Constant *getAddrOfClassMetadataBounds(ClassDecl *D, ForDefinition_t forDefinition); llvm::Constant *getAddrOfTypeContextDescriptor(NominalTypeDecl *D, RequireMetadata_t requireMetadata, ConstantInit definition = ConstantInit()); llvm::Constant *getAddrOfAnonymousContextDescriptor( PointerUnion Name, ConstantInit definition = ConstantInit()); llvm::Constant *getAddrOfExtensionContextDescriptor(ExtensionDecl *ED, ConstantInit definition = ConstantInit()); llvm::Constant *getAddrOfModuleContextDescriptor(ModuleDecl *D, ConstantInit definition = ConstantInit()); llvm::Constant *getAddrOfReflectionFieldDescriptor(CanType type, ConstantInit definition = ConstantInit()); llvm::Constant *getAddrOfReflectionBuiltinDescriptor(CanType type, ConstantInit definition = ConstantInit()); llvm::Constant *getAddrOfReflectionAssociatedTypeDescriptor( const ProtocolConformance *c, ConstantInit definition = ConstantInit()); llvm::Constant *getAddrOfObjCModuleContextDescriptor(); llvm::Constant *getAddrOfClangImporterModuleContextDescriptor(); llvm::Constant *getAddrOfOriginalModuleContextDescriptor(StringRef Name); ConstantReference getAddrOfParentContextDescriptor(DeclContext *from, bool fromAnonymousContext); ConstantReference getAddrOfContextDescriptorForParent(DeclContext *parent, DeclContext *ofChild, bool fromAnonymousContext); llvm::Constant *getAddrOfGenericEnvironment(CanGenericSignature signature); llvm::Constant *getAddrOfProtocolRequirementsBaseDescriptor( ProtocolDecl *proto); llvm::GlobalValue *defineProtocolRequirementsBaseDescriptor( ProtocolDecl *proto, llvm::Constant *definition); llvm::Constant *getAddrOfAssociatedTypeDescriptor( AssociatedTypeDecl *assocType); llvm::GlobalValue *defineAssociatedTypeDescriptor( AssociatedTypeDecl *assocType, llvm::Constant *definition); llvm::Constant *getAddrOfAssociatedConformanceDescriptor( AssociatedConformance conformance); llvm::GlobalValue *defineAssociatedConformanceDescriptor( AssociatedConformance conformance, llvm::Constant *definition); llvm::Constant *getAddrOfBaseConformanceDescriptor( BaseConformance conformance); llvm::GlobalValue *defineBaseConformanceDescriptor( BaseConformance conformance, llvm::Constant *definition); llvm::Constant *getAddrOfProtocolDescriptor(ProtocolDecl *D, ConstantInit definition = ConstantInit()); llvm::Constant *getAddrOfProtocolConformanceDescriptor( const RootProtocolConformance *conformance, ConstantInit definition = ConstantInit()); llvm::Constant *getAddrOfPropertyDescriptor(AbstractStorageDecl *D, ConstantInit definition = ConstantInit()); llvm::Constant *getAddrOfObjCClass(ClassDecl *D, ForDefinition_t forDefinition); Address getAddrOfObjCClassRef(ClassDecl *D); llvm::Constant *getAddrOfMetaclassObject(ClassDecl *D, ForDefinition_t forDefinition); llvm::Constant *getAddrOfCanonicalSpecializedGenericMetaclassObject( CanType concreteType, ForDefinition_t forDefinition); llvm::Function *getAddrOfObjCMetadataUpdateFunction(ClassDecl *D, ForDefinition_t forDefinition); llvm::Constant *getAddrOfObjCResilientClassStub(ClassDecl *D, ForDefinition_t forDefinition, TypeMetadataAddress addr); llvm::Function * getAddrOfSILFunction(SILFunction *f, ForDefinition_t forDefinition, bool isDynamicallyReplaceableImplementation = false, bool shouldCallPreviousImplementation = false); llvm::Function * getAddrOfWitnessTableProfilingThunk(llvm::Function *witness, const NormalProtocolConformance &C); llvm::Function * getAddrOfVTableProfilingThunk(llvm::Function *f, ClassDecl *decl); llvm::Function *getOrCreateProfilingThunk(llvm::Function *f, StringRef prefix); void emitDynamicReplacementOriginalFunctionThunk(SILFunction *f); llvm::Function *getAddrOfContinuationPrototype(CanSILFunctionType fnType, CanGenericSignature sig); Address getAddrOfSILGlobalVariable(SILGlobalVariable *var, const TypeInfo &ti, ForDefinition_t forDefinition); llvm::Constant *getGlobalInitValue(SILGlobalVariable *var, llvm::Type *storageType, Alignment alignment); llvm::Constant *getConstantValue(Explosion &&initExp, Size::int_type paddingBytes); llvm::Function *getAddrOfWitnessTableLazyAccessFunction( const NormalProtocolConformance *C, CanType conformingType, ForDefinition_t forDefinition); llvm::Constant *getAddrOfWitnessTableLazyCacheVariable( const NormalProtocolConformance *C, CanType conformingType, ForDefinition_t forDefinition); llvm::Constant *getAddrOfWitnessTable(const ProtocolConformance *C, ConstantInit definition = ConstantInit()); llvm::Constant *getAddrOfWitnessTablePattern( const NormalProtocolConformance *C, ConstantInit definition = ConstantInit()); llvm::Function * getAddrOfGenericWitnessTableInstantiationFunction( const NormalProtocolConformance *C); llvm::Function *getAddrOfAssociatedTypeWitnessTableAccessFunction( const NormalProtocolConformance *C, const AssociatedConformance &association); llvm::Function *getAddrOfDefaultAssociatedConformanceAccessor( AssociatedConformance requirement); llvm::Constant * getAddrOfDifferentiabilityWitness(const SILDifferentiabilityWitness *witness, ConstantInit definition = ConstantInit()); Address getAddrOfObjCISAMask(); llvm::Function * getAddrOfDistributedTargetAccessor(LinkEntity accessor, ForDefinition_t forDefinition); /// Emit a distributed accessor function for the given distributed thunk or /// protocol requirement. void emitDistributedTargetAccessor( llvm::PointerUnion thunkOrRequirement); llvm::Constant *getAddrOfAccessibleFunctionRecord(SILFunction *accessibleFn); /// Retrieve the generic signature for the current generic context, or null if no /// generic environment is active. CanGenericSignature getCurGenericContext(); /// Retrieve the generic environment for the current generic context. /// /// Fails if there is no generic context. GenericEnvironment *getGenericEnvironment(); ConstantReference getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity); llvm::Constant *getAddrOfLLVMVariable(LinkEntity entity, ConstantInit definition, DebugTypeInfo debugType, llvm::Type *overrideDeclType = nullptr); llvm::Constant *getAddrOfLLVMVariable(LinkEntity entity, ForDefinition_t forDefinition, DebugTypeInfo debugType); llvm::Constant *emitRelativeReference(ConstantReference target, llvm::GlobalValue *base, ArrayRef baseIndices); llvm::Constant *emitDirectRelativeReference(llvm::Constant *target, llvm::GlobalValue *base, ArrayRef baseIndices); /// Mark a global variable as true-const by putting it in the text section of /// the binary. void setTrueConstGlobal(llvm::GlobalVariable *var); /// Add the swiftself attribute. void addSwiftSelfAttributes(llvm::AttributeList &attrs, unsigned argIndex); void addSwiftCoroAttributes(llvm::AttributeList &attrs, unsigned argIndex); void addSwiftAsyncContextAttributes(llvm::AttributeList &attrs, unsigned argIndex); /// Add the swifterror attribute. void addSwiftErrorAttributes(llvm::AttributeList &attrs, unsigned argIndex); void emitSharedContextDescriptor(DeclContext *dc); llvm::GlobalVariable * getGlobalForDynamicallyReplaceableThunk(LinkEntity &entity, llvm::Type *type, ForDefinition_t forDefinition); FunctionPointer getAddrOfOpaqueTypeDescriptorAccessFunction( OpaqueTypeDecl *decl, ForDefinition_t forDefinition, bool implementation); void createReplaceableProlog(IRGenFunction &IGF, SILFunction *f); void emitOpaqueTypeDescriptorAccessor(OpaqueTypeDecl *); /// We emit Objective-C class stubs for non-generic classes with resilient /// ancestry. This lets us attach categories to the class even though it /// does not have statically-emitted metadata. bool hasObjCResilientClassStub(ClassDecl *D); /// Emit a resilient class stub. llvm::Constant *emitObjCResilientClassStub(ClassDecl *D, bool isPublic); /// Runs additional lowering logic on the given SIL function to ensure that /// the SIL function is correctly lowered even if the lowering passes do not /// run on the SIL module that owns this function. void lowerSILFunction(SILFunction *f); llvm::Function *getForeignExceptionHandlingPersonalityFunc(); bool isForeignExceptionHandlingEnabled() const; /// Returns true if the given Clang function does not throw exceptions. bool isCxxNoThrow(clang::FunctionDecl *fd, bool defaultNoThrow = false); private: llvm::Constant * getAddrOfSharedContextDescriptor(LinkEntity entity, ConstantInit definition, llvm::function_ref emit); ConstantReference getAddrOfLLVMVariable(LinkEntity entity, ConstantInit definition, DebugTypeInfo debugType, SymbolReferenceKind refKind, llvm::Type *overrideDeclType = nullptr); void emitLazyPrivateDefinitions(); void addRuntimeResolvableType(GenericTypeDecl *nominal); /// Add all conformances of the given \c IterableDeclContext /// LazyWitnessTables. void addLazyConformances(const IterableDeclContext *idc); //--- Global context emission -------------------------------------------------- bool hasSwiftAsyncFunctionDef = false; llvm::Value *extendedFramePointerFlagsWeakRef = nullptr; /// Emit a weak reference to the `swift_async_extendedFramePointerFlags` /// symbol needed by Swift async functions. void emitSwiftAsyncExtendedFrameInfoWeakRef(); public: bool isConcurrencyAvailable(); void noteSwiftAsyncFunctionDef() { hasSwiftAsyncFunctionDef = true; } void emitRuntimeRegistration(); void emitVTableStubs(); void emitTypeVerifier(); llvm::Function *emitHasSymbolFunction(ValueDecl *decl); /// Create llvm metadata which encodes the branch weights given by /// \p TrueCount and \p FalseCount. llvm::MDNode *createProfileWeights(uint64_t TrueCount, uint64_t FalseCount) const; private: void emitGlobalDecl(Decl *D); }; /// Stores a pointer to an IRGenModule. /// As long as the CurrentIGMPtr is alive, the CurrentIGM in the dispatcher /// is set to the containing IRGenModule. class CurrentIGMPtr { IRGenModule *IGM; public: CurrentIGMPtr(IRGenModule *IGM) : IGM(IGM) { assert(IGM); assert(!IGM->IRGen.CurrentIGM && "Another CurrentIGMPtr is alive"); IGM->IRGen.CurrentIGM = IGM; } ~CurrentIGMPtr() { IGM->IRGen.CurrentIGM = nullptr; } IRGenModule *get() const { return IGM; } IRGenModule *operator->() const { return IGM; } }; /// Workaround to disable thumb-mode until debugger support is there. bool shouldRemoveTargetFeature(StringRef); struct CXXBaseRecordLayout { const clang::CXXRecordDecl *decl; Size offset; Size size; }; /// Retrieves the base classes of a C++ struct/class ordered by their offset in /// the derived type's memory layout. SmallVector getBasesAndOffsets(const clang::CXXRecordDecl *decl); } // end namespace irgen } // end namespace swift namespace llvm { template<> struct DenseMapInfo { using FixedLayoutKey = swift::irgen::IRGenModule::FixedLayoutKey; static inline FixedLayoutKey getEmptyKey() { return {0, 0xFFFFFFFFu, 0, 0, 0}; } static inline FixedLayoutKey getTombstoneKey() { return {0, 0xFFFFFFFEu, 0, 0, 0}; } static unsigned getHashValue(const FixedLayoutKey &key) { return hash_combine(key.size, key.numExtraInhabitants, key.align, (bool)key.pod, (bool)key.bitwiseTakable); } static bool isEqual(const FixedLayoutKey &a, const FixedLayoutKey &b) { return a.size == b.size && a.numExtraInhabitants == b.numExtraInhabitants && a.align == b.align && a.pod == b.pod && a.bitwiseTakable == b.bitwiseTakable; } }; } #endif