| //===--- 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 "IRGen.h" |
| #include "SwiftTargetInfo.h" |
| #include "swift/AST/Decl.h" |
| #include "swift/AST/Module.h" |
| #include "swift/AST/ReferenceCounting.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/SILFunction.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/ValueHandle.h" |
| #include "llvm/Target/TargetMachine.h" |
| |
| #include <atomic> |
| |
| namespace llvm { |
| class Constant; |
| 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> class CanQual; |
| class CodeGenerator; |
| class Decl; |
| class GlobalDecl; |
| class Type; |
| namespace CodeGen { |
| class CGFunctionInfo; |
| class CodeGenModule; |
| } |
| } |
| |
| namespace swift { |
| class GenericSignature; |
| class GenericSignatureBuilder; |
| class AssociatedConformance; |
| class AssociatedType; |
| class ASTContext; |
| class BaseConformance; |
| class BraceStmt; |
| class CanType; |
| class LinkLibrary; |
| class SILFunction; |
| class IRGenOptions; |
| class NormalProtocolConformance; |
| class ProtocolConformance; |
| class ProtocolCompositionType; |
| class RootProtocolConformance; |
| struct SILDeclRef; |
| class SILGlobalVariable; |
| class SILModule; |
| class SILProperty; |
| class SILType; |
| 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 HeapLayout; |
| class StructLayout; |
| class IRGenDebugInfo; |
| class IRGenFunction; |
| class LinkEntity; |
| class LoadableTypeInfo; |
| class MetadataLayout; |
| class NecessaryBindings; |
| class NominalMetadataLayout; |
| class OutliningMetadataCollector; |
| class ProtocolInfo; |
| enum class ProtocolInfoKind : uint8_t; |
| class Signature; |
| class StructMetadataLayout; |
| struct SymbolicMangling; |
| class TypeConverter; |
| class TypeInfo; |
| enum class ValueWitness : unsigned; |
| |
| class IRGenModule; |
| |
| /// A type descriptor for a field type accessor. |
| class FieldTypeInfo { |
| llvm::PointerIntPair<CanType, 2, unsigned> 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 |
| }; |
| |
| /// 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: |
| IRGenOptions &Opts; |
| |
| SILModule &SIL; |
| |
| private: |
| llvm::DenseMap<SourceFile *, IRGenModule *> 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<SILFunction *, IRGenModule *> DefaultIGMForFunction; |
| |
| // The IGM of the first source file. |
| IRGenModule *PrimaryIGM = nullptr; |
| |
| // The current IGM for which IR is generated. |
| IRGenModule *CurrentIGM = nullptr; |
| |
| 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 a definition for the type metadata with |
| /// the current requirements? |
| bool IsMetadataEmitted = false; |
| |
| /// Have we already emitted a definition for the type descriptor with |
| /// the current requirements? |
| bool IsDescriptorEmitted = false; |
| |
| /// Is the type a lazy type? |
| bool IsLazy = false; |
| }; |
| |
| /// The set of type metadata that have been enqueued for lazy emission. |
| /// |
| /// It can also contain some eagerly emitted metadata. Those are ignored in |
| /// lazy emission. |
| llvm::DenseMap<NominalTypeDecl*, LazyTypeGlobalsInfo> LazyTypeGlobals; |
| |
| /// The queue of lazy type metadata to emit. |
| llvm::SmallVector<NominalTypeDecl*, 4> LazyTypeMetadata; |
| |
| /// The queue of lazy type context descriptors to emit. |
| llvm::SmallVector<NominalTypeDecl*, 4> LazyTypeContextDescriptors; |
| |
| llvm::SmallPtrSet<SILFunction*, 4> LazilyEmittedFunctions; |
| |
| llvm::SetVector<SILFunction*> DynamicReplacements; |
| |
| /// SIL functions that we need to emit lazily. |
| llvm::SmallVector<SILFunction*, 4> LazyFunctionDefinitions; |
| |
| /// The set of witness tables that have been enqueue for lazy emission. |
| llvm::SmallPtrSet<SILWitnessTable *, 4> LazilyEmittedWitnessTables; |
| |
| /// The queue of lazy witness tables to emit. |
| llvm::SmallVector<SILWitnessTable *, 4> LazyWitnessTables; |
| |
| llvm::SmallVector<ClassDecl *, 4> ClassesForEagerInitialization; |
| |
| /// The order in which all the SIL function definitions should |
| /// appear in the translation unit. |
| llvm::DenseMap<SILFunction*, unsigned> FunctionOrder; |
| |
| /// The queue of IRGenModules for multi-threaded compilation. |
| SmallVector<IRGenModule *, 8> Queue; |
| |
| std::atomic<int> QueueIndex; |
| |
| friend class CurrentIGMPtr; |
| public: |
| explicit IRGenerator(IRGenOptions &opts, SILModule &module); |
| |
| /// Attempt to create an llvm::TargetMachine for the current target. |
| std::unique_ptr<llvm::TargetMachine> 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) { |
| IRGenModule *IGM = GenModules[SF]; |
| assert(IGM); |
| return IGM; |
| } |
| |
| /// 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); |
| |
| /// 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<SourceFile *, IRGenModule *>::iterator begin() { |
| return GenModules.begin(); |
| } |
| |
| llvm::DenseMap<SourceFile *, IRGenModule *>::iterator end() { |
| return GenModules.end(); |
| } |
| |
| /// Emit functions, variables and tables which are needed anyway, e.g. because |
| /// they are externally visible. |
| /// If \p emitForParallelEmission is true ensures that symbols that are |
| /// expressed as relative pointers are collocated in the same output module |
| /// with their base symbol. For example, witness methods need to be collocated |
| /// with the witness table in the same LLVM module. |
| void emitGlobalTopLevel(bool emitForParallelEmission = false); |
| |
| /// 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 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(); |
| |
| // Emit the code to replace dynamicReplacement(for:) functions. |
| void emitDynamicReplacements(); |
| |
| /// Checks if the metadata of \p Nominal can be emitted lazily. |
| /// |
| /// If yes, \p Nominal is added to eligibleLazyMetadata and true is returned. |
| bool tryEnableLazyTypeMetadata(NominalTypeDecl *Nominal); |
| |
| /// Emit everything which is reachable from already emitted IR. |
| void emitLazyDefinitions(); |
| |
| void addLazyFunction(SILFunction *f); |
| |
| void addDynamicReplacement(SILFunction *f) { DynamicReplacements.insert(f); } |
| |
| void forceLocalEmitOfLazyFunction(SILFunction *f) { |
| DefaultIGMForFunction[f] = CurrentIGM; |
| } |
| |
| void noteUseOfTypeMetadata(NominalTypeDecl *type) { |
| noteUseOfTypeGlobals(type, true, RequireMetadata); |
| } |
| |
| void noteUseOfTypeMetadata(Type type) { |
| type.visit([&](Type t) { |
| if (auto *nominal = t->getAnyNominal()) |
| noteUseOfTypeMetadata(nominal); |
| }); |
| } |
| |
| void noteUseOfTypeContextDescriptor(NominalTypeDecl *type, |
| RequireMetadata_t requireMetadata) { |
| noteUseOfTypeGlobals(type, false, requireMetadata); |
| } |
| |
| void noteUseOfAnyParentTypeMetadata(NominalTypeDecl *type); |
| |
| 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); |
| |
| 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(); |
| |
| const llvm::DataLayout &getClangDataLayout(); |
| }; |
| |
| class ConstantReference { |
| public: |
| enum Directness : bool { Direct, Indirect }; |
| private: |
| llvm::PointerIntPair<llvm::Constant *, 1, Directness> 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 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, |
| }; |
| |
| /// 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 = 6; |
| |
| IRGenerator &IRGen; |
| ASTContext &Context; |
| std::unique_ptr<clang::CodeGenerator> ClangCodeGen; |
| llvm::Module &Module; |
| llvm::LLVMContext &LLVMContext; |
| const llvm::DataLayout DataLayout; |
| const llvm::Triple Triple; |
| std::unique_ptr<llvm::TargetMachine> TargetMachine; |
| ModuleDecl *getSwiftModule() 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; |
| SourceFile *CurSourceFile = nullptr; |
| |
| 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<IRGenDebugInfo> DebugInfo; |
| |
| /// A global variable which stores the hash of the module. Used for |
| /// incremental compilation. |
| llvm::GlobalVariable *ModuleHash; |
| |
| /// 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; |
| |
| // Is swifterror returned in a register by the target ABI. |
| bool IsSwiftErrorInRegister; |
| |
| llvm::Type *VoidTy; /// void (usually {}) |
| llvm::IntegerType *Int1Ty; /// i1 |
| llvm::IntegerType *Int8Ty; /// i8 |
| llvm::IntegerType *Int16Ty; /// i16 |
| llvm::IntegerType *Int32Ty; /// i32 |
| llvm::PointerType *Int32PtrTy; /// i32 * |
| llvm::IntegerType *RelativeAddressTy; |
| llvm::PointerType *RelativeAddressPtrTy; |
| 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 *Int8PtrTy; /// i8* |
| llvm::PointerType *WitnessTableTy; |
| llvm::PointerType *ObjCSELTy; |
| llvm::PointerType *FunctionPtrTy; |
| llvm::PointerType *CaptureDescriptorPtrTy; |
| }; |
| union { |
| llvm::PointerType *Int8PtrPtrTy; /// i8** |
| llvm::PointerType *WitnessTablePtrTy; |
| }; |
| llvm::StructType *RefCountedStructTy;/// %swift.refcounted = type { ... } |
| Size RefCountedStructSize; /// sizeof(%swift.refcounted) |
| llvm::PointerType *RefCountedPtrTy; /// %swift.refcounted* |
| #define CHECKED_REF_STORAGE(Name, ...) \ |
| llvm::PointerType *Name##ReferencePtrTy; /// %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 { ... } |
| llvm::PointerType *TypeMetadataPtrTy;/// %swift.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::PointerType *TupleTypeMetadataPtrTy; /// %swift.tuple_type* |
| llvm::StructType *FullHeapMetadataStructTy; /// %swift.full_heapmetadata = type { ... } |
| llvm::PointerType *FullHeapMetadataPtrTy;/// %swift.full_heapmetadata* |
| llvm::StructType *FullBoxMetadataStructTy; /// %swift.full_boxmetadata = type { ... } |
| llvm::PointerType *FullBoxMetadataPtrTy;/// %swift.full_boxmetadata* |
| llvm::StructType *FullTypeMetadataStructTy; /// %swift.full_type = type { ... } |
| llvm::PointerType *FullTypeMetadataPtrTy;/// %swift.full_type* |
| llvm::StructType *ProtocolDescriptorStructTy; /// %swift.protocol = type { ... } |
| llvm::PointerType *ProtocolDescriptorPtrTy; /// %swift.protocol* |
| llvm::StructType *ProtocolRequirementStructTy; /// %swift.protocol_requirement |
| union { |
| llvm::PointerType *ObjCPtrTy; /// %objc_object* |
| llvm::PointerType *UnknownRefCountedPtrTy; |
| }; |
| llvm::PointerType *BridgeObjectPtrTy;/// %swift.bridge* |
| llvm::StructType *OpaqueTy; /// %swift.opaque |
| llvm::PointerType *OpaquePtrTy; /// %swift.opaque* |
| llvm::StructType *ObjCClassStructTy; /// %objc_class |
| llvm::PointerType *ObjCClassPtrTy; /// %objc_class* |
| llvm::StructType *ObjCSuperStructTy; /// %objc_super |
| llvm::PointerType *ObjCSuperPtrTy; /// %objc_super* |
| llvm::StructType *ObjCBlockStructTy; /// %objc_block |
| llvm::PointerType *ObjCBlockPtrTy; /// %objc_block* |
| llvm::StructType *ProtocolRecordTy; |
| llvm::PointerType *ProtocolRecordPtrTy; |
| llvm::StructType *ProtocolConformanceDescriptorTy; |
| llvm::PointerType *ProtocolConformanceDescriptorPtrTy; |
| llvm::StructType *TypeContextDescriptorTy; |
| llvm::PointerType *TypeContextDescriptorPtrTy; |
| llvm::StructType *ClassContextDescriptorTy; |
| llvm::StructType *MethodDescriptorStructTy; /// %swift.method_descriptor |
| llvm::StructType *MethodOverrideDescriptorStructTy; /// %swift.method_override_descriptor |
| llvm::StructType *TypeMetadataRecordTy; |
| llvm::PointerType *TypeMetadataRecordPtrTy; |
| llvm::StructType *FieldDescriptorTy; |
| llvm::PointerType *FieldDescriptorPtrTy; |
| llvm::PointerType *FieldDescriptorPtrPtrTy; |
| llvm::PointerType *ErrorPtrTy; /// %swift.error* |
| llvm::StructType *OpenedErrorTripleTy; /// { %swift.opaque*, %swift.type*, i8** } |
| llvm::PointerType *OpenedErrorTriplePtrTy; /// { %swift.opaque*, %swift.type*, i8** }* |
| llvm::PointerType *WitnessTablePtrPtrTy; /// i8*** |
| llvm::Type *FloatTy; |
| llvm::Type *DoubleTy; |
| llvm::StructType *DynamicReplacementsTy; // { i8**, i8* } |
| llvm::PointerType *DynamicReplacementsPtrTy; |
| |
| llvm::StructType *DynamicReplacementLinkEntryTy; // %link_entry = { i8*, %link_entry*} |
| llvm::PointerType |
| *DynamicReplacementLinkEntryPtrTy; // %link_entry* |
| llvm::StructType *DynamicReplacementKeyTy; // { i32, i32} |
| |
| llvm::GlobalVariable *TheTrivialPropertyDescriptor = nullptr; |
| |
| /// 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; |
| |
| llvm::CallingConv::ID C_CC; /// standard C calling convention |
| llvm::CallingConv::ID DefaultCC; /// default calling convention |
| llvm::CallingConv::ID SwiftCC; /// swift calling convention |
| |
| 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(); |
| } |
| |
| /// 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); |
| |
| static bool isLoadableReferenceAddressOnly(ReferenceCounting style) { |
| switch (style) { |
| case ReferenceCounting::Native: |
| return false; |
| |
| case ReferenceCounting::Unknown: |
| case ReferenceCounting::ObjC: |
| case ReferenceCounting::Block: |
| 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 *getValueWitnessTy(ValueWitness index); |
| Signature getValueWitnessSignature(ValueWitness index); |
| |
| llvm::StructType *getIntegerLiteralTy(); |
| |
| llvm::StructType *getValueWitnessTableTy(); |
| llvm::StructType *getEnumValueWitnessTableTy(); |
| llvm::PointerType *getValueWitnessTablePtrTy(); |
| llvm::PointerType *getEnumValueWitnessTablePtrTy(); |
| |
| void unimplemented(SourceLoc, StringRef Message); |
| LLVM_ATTRIBUTE_NORETURN |
| void fatal_unimplemented(SourceLoc, StringRef Message); |
| void error(SourceLoc loc, const Twine &message); |
| |
| bool useDllStorage(); |
| |
| 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); |
| |
| 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::PointerType *ValueWitnessTablePtrTy = nullptr; |
| llvm::PointerType *EnumValueWitnessTablePtrTy = nullptr; |
| |
| llvm::DenseMap<llvm::Type *, SpareBitVector> SpareBitsForTypes; |
| |
| //--- Types ----------------------------------------------------------------- |
| public: |
| 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); |
| SILType getLoweredType(Type subst); |
| 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 &getObjCClassPtrTypeInfo(); |
| const LoadableTypeInfo &getOpaqueStorageTypeInfo(Size size, Alignment align); |
| const LoadableTypeInfo & |
| getReferenceObjectTypeInfo(ReferenceCounting refcounting); |
| const LoadableTypeInfo &getNativeObjectTypeInfo(); |
| const LoadableTypeInfo &getUnknownObjectTypeInfo(); |
| const LoadableTypeInfo &getBridgeObjectTypeInfo(); |
| const LoadableTypeInfo &getRawPointerTypeInfo(); |
| llvm::Type *getStorageTypeForUnlowered(Type T); |
| llvm::Type *getStorageTypeForLowered(CanType T); |
| llvm::Type *getStorageType(SILType T); |
| llvm::PointerType *getStoragePointerTypeForUnlowered(Type T); |
| llvm::PointerType *getStoragePointerTypeForLowered(CanType T); |
| llvm::PointerType *getStoragePointerType(SILType T); |
| llvm::StructType *createNominalType(CanType type); |
| llvm::StructType *createNominalType(ProtocolCompositionType *T); |
| clang::CanQual<clang::Type> getClangType(CanType type); |
| clang::CanQual<clang::Type> getClangType(SILType type); |
| clang::CanQual<clang::Type> getClangType(SILParameterInfo param); |
| |
| const clang::ASTContext &getClangASTContext() { |
| assert(ClangASTContext && |
| "requesting clang AST context without clang importer!"); |
| return *ClangASTContext; |
| } |
| |
| clang::CodeGen::CodeGenModule &getClangCGM() const; |
| |
| bool isResilient(NominalTypeDecl *decl, ResilienceExpansion expansion); |
| bool hasResilientMetadata(ClassDecl *decl, ResilienceExpansion expansion); |
| ResilienceExpansion getResilienceExpansionForAccess(NominalTypeDecl *decl); |
| ResilienceExpansion getResilienceExpansionForLayout(NominalTypeDecl *decl); |
| ResilienceExpansion getResilienceExpansionForLayout(SILGlobalVariable *var); |
| |
| 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); |
| |
| private: |
| TypeConverter &Types; |
| friend class TypeConverter; |
| |
| const clang::ASTContext *ClangASTContext; |
| ClangTypeConverter *ClangTypes; |
| void initClangTypeConverter(); |
| void destroyClangTypeConverter(); |
| |
| llvm::DenseMap<Decl*, MetadataLayout*> MetadataLayouts; |
| void destroyMetadataLayoutMap(); |
| |
| llvm::DenseMap<const ProtocolConformance *, |
| std::unique_ptr<const ConformanceInfo>> Conformances; |
| |
| friend class GenericContextScope; |
| friend class LoweringModeScope; |
| |
| //--- Globals --------------------------------------------------------------- |
| public: |
| std::pair<llvm::GlobalVariable *, llvm::Constant *> |
| createStringConstant(StringRef Str, bool willBeRelativelyAddressed = false, |
| StringRef sectionName = ""); |
| llvm::Constant *getAddrOfGlobalString(StringRef utf8, |
| bool willBeRelativelyAddressed = false); |
| llvm::Constant *getAddrOfGlobalUTF16String(StringRef utf8); |
| llvm::Constant *getAddrOfObjCSelectorRef(StringRef selector); |
| llvm::Constant *getAddrOfObjCSelectorRef(SILDeclRef method); |
| llvm::Constant *getAddrOfObjCMethodName(StringRef methodName); |
| llvm::Constant *getAddrOfObjCProtocolRecord(ProtocolDecl *proto, |
| ForDefinition_t forDefinition); |
| llvm::Constant *getAddrOfObjCProtocolRef(ProtocolDecl *proto, |
| ForDefinition_t forDefinition); |
| llvm::Constant *getAddrOfKeyPathPattern(KeyPathPattern *pattern, |
| SILLocation diagLoc); |
| ConstantReference getConstantReferenceForProtocolDescriptor(ProtocolDecl *proto); |
| |
| ConstantIntegerLiteral getConstantIntegerLiteral(APInt value); |
| |
| void addUsedGlobal(llvm::GlobalValue *global); |
| void addCompilerUsedGlobal(llvm::GlobalValue *global); |
| void addObjCClass(llvm::Constant *addr, bool nonlazy); |
| void addProtocolConformance(ConformanceDescription &&conformance); |
| |
| llvm::Constant *emitSwiftProtocols(); |
| llvm::Constant *emitProtocolConformances(); |
| llvm::Constant *emitTypeMetadataRecords(); |
| llvm::Constant *emitFieldDescriptors(); |
| |
| llvm::Constant *getOrCreateHelperFunction(StringRef name, |
| llvm::Type *resultType, |
| ArrayRef<llvm::Type*> paramTypes, |
| llvm::function_ref<void(IRGenFunction &IGF)> generate, |
| bool setIsNoInline = false); |
| |
| llvm::Constant *getOrCreateRetainFunction(const TypeInfo &objectTI, SILType t, |
| llvm::Type *llvmType); |
| |
| llvm::Constant *getOrCreateReleaseFunction(const TypeInfo &objectTI, SILType t, |
| llvm::Type *llvmType); |
| |
| 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); |
| |
| private: |
| llvm::Constant *getAddrOfClangGlobalDecl(clang::GlobalDecl global, |
| ForDefinition_t forDefinition); |
| |
| using CopyAddrHelperGenerator = |
| llvm::function_ref<void(IRGenFunction &IGF, Address dest, Address src, |
| SILType objectType, const TypeInfo &objectTI)>; |
| |
| 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<LinkEntity, llvm::Constant*> GlobalVars; |
| llvm::DenseMap<LinkEntity, llvm::Constant*> GlobalGOTEquivalents; |
| llvm::DenseMap<LinkEntity, llvm::Function*> GlobalFuncs; |
| llvm::DenseSet<const clang::Decl *> GlobalClangDecls; |
| llvm::StringMap<std::pair<llvm::GlobalVariable*, llvm::Constant*>> |
| GlobalStrings; |
| llvm::StringMap<llvm::Constant*> GlobalUTF16Strings; |
| llvm::StringMap<std::pair<llvm::GlobalVariable*, llvm::Constant*>> |
| StringsForTypeRef; |
| llvm::DenseMap<CanType, llvm::GlobalVariable*> TypeRefs; |
| llvm::StringMap<std::pair<llvm::GlobalVariable*, llvm::Constant*>> FieldNames; |
| llvm::StringMap<llvm::Constant*> ObjCSelectorRefs; |
| llvm::StringMap<llvm::Constant*> ObjCMethodNames; |
| |
| std::unique_ptr<ConstantIntegerLiteralMap> ConstantIntegerLiterals; |
| |
| /// Maps to constant swift 'String's. |
| llvm::StringMap<llvm::Constant*> GlobalConstantStrings; |
| llvm::StringMap<llvm::Constant*> GlobalConstantUTF16Strings; |
| |
| /// 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<llvm::WeakTrackingVH, 4> 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<llvm::WeakTrackingVH, 4> LLVMCompilerUsed; |
| |
| /// Metadata nodes for autolinking info. |
| SmallVector<llvm::MDNode *, 32> AutolinkEntries; |
| |
| /// List of Objective-C classes, bitcast to i8*. |
| SmallVector<llvm::WeakTrackingVH, 4> ObjCClasses; |
| /// List of Objective-C classes that require nonlazy realization, bitcast to |
| /// i8*. |
| SmallVector<llvm::WeakTrackingVH, 4> ObjCNonLazyClasses; |
| /// List of Objective-C categories, bitcast to i8*. |
| SmallVector<llvm::WeakTrackingVH, 4> ObjCCategories; |
| /// List of non-ObjC protocols described by this module. |
| SmallVector<ProtocolDecl *, 4> SwiftProtocols; |
| /// List of protocol conformances to generate descriptors for. |
| std::vector<ConformanceDescription> ProtocolConformances; |
| /// List of nominal types to generate type metadata records for. |
| SmallVector<NominalTypeDecl *, 4> RuntimeResolvableTypes; |
| /// List of ExtensionDecls corresponding to the generated |
| /// categories. |
| SmallVector<ExtensionDecl*, 4> ObjCCategoryDecls; |
| |
| /// List of fields descriptors to register in runtime. |
| SmallVector<llvm::GlobalVariable *, 4> FieldDescriptors; |
| |
| /// 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<ProtocolDecl*, ObjCProtocolPair> ObjCProtocols; |
| llvm::SmallVector<ProtocolDecl*, 4> LazyObjCProtocolDefinitions; |
| llvm::DenseMap<KeyPathPattern*, llvm::GlobalVariable*> KeyPathPatterns; |
| |
| /// Uniquing key for a fixed type layout record. |
| struct FixedLayoutKey { |
| unsigned size; |
| unsigned numExtraInhabitants; |
| unsigned align: 16; |
| unsigned pod: 1; |
| unsigned bitwiseTakable: 1; |
| }; |
| friend struct ::llvm::DenseMapInfo<swift::irgen::IRGenModule::FixedLayoutKey>; |
| llvm::DenseMap<FixedLayoutKey, llvm::Constant *> PrivateFixedLayouts; |
| |
| /// A cache for layouts of statically initialized objects. |
| llvm::DenseMap<SILGlobalVariable *, std::unique_ptr<StructLayout>> |
| StaticObjectLayouts; |
| |
| /// A mapping from order numbers to the LLVM functions which we |
| /// created for the SIL functions with those orders. |
| SuccessorMap<unsigned, llvm::Function*> EmittedFunctionsByOrder; |
| |
| ObjCProtocolPair getObjCProtocolGlobalVars(ProtocolDecl *proto); |
| void emitLazyObjCProtocolDefinitions(); |
| void emitLazyObjCProtocolDefinition(ProtocolDecl *proto); |
| |
| 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; |
| |
| /// Builtin types referenced by types in this module when emitting |
| /// reflection metadata. |
| llvm::SetVector<CanType> BuiltinTypes; |
| /// Opaque but fixed-size types for which we also emit builtin type |
| /// descriptors, allowing the reflection library to layout these types |
| /// without knowledge of their contents. This includes imported structs |
| /// and fixed-size multi-payload enums. |
| llvm::SetVector<const NominalTypeDecl *> OpaqueTypes; |
| /// Imported structs referenced by types in this module when emitting |
| /// reflection metadata. |
| llvm::SetVector<const StructDecl *> ImportedStructs; |
| |
| llvm::Constant *getTypeRef(CanType type, MangledTypeRefRole role); |
| 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<ConstantInitFuture(ConstantInitBuilder &)> body); |
| |
| llvm::Constant *getAddrOfFieldName(StringRef Name); |
| llvm::Constant *getAddrOfCaptureDescriptor(SILFunction &caller, |
| CanSILFunctionType origCalleeType, |
| CanSILFunctionType substCalleeType, |
| SubstitutionMap subs, |
| const HeapLayout &layout); |
| llvm::Constant *getAddrOfBoxDescriptor(CanType boxedType); |
| |
| /// Produce an associated type witness that refers to the given type. |
| llvm::Constant *getAssociatedTypeWitness(CanType type, |
| bool inProtocolContext); |
| |
| void emitAssociatedTypeMetadataRecord(const RootProtocolConformance *C); |
| void emitFieldMetadataRecord(const NominalTypeDecl *Decl); |
| |
| /// Emit a reflection metadata record for a builtin type referenced |
| /// from this module. |
| void emitBuiltinTypeMetadataRecord(CanType builtinType); |
| |
| /// Emit a reflection metadata record for an imported type referenced |
| /// from this module. |
| void emitOpaqueTypeMetadataRecord(const NominalTypeDecl *nominalDecl); |
| |
| /// Some nominal type declarations require us to emit a fixed-size type |
| /// descriptor, because they have special layout considerations. |
| bool shouldEmitOpaqueTypeMetadataRecord(const NominalTypeDecl *nominalDecl); |
| |
| /// 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(); |
| |
| //--- 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); |
| llvm::Module *getModule() const; |
| llvm::Module *releaseModule(); |
| llvm::AttributeList getAllocAttrs(); |
| |
| bool isStandardLibrary() const; |
| |
| 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; |
| Optional<llvm::InlineAsm*> ObjCRetainAutoreleasedReturnValueMarker; |
| llvm::DenseMap<Identifier, ClassDecl*> SwiftRootClasses; |
| llvm::AttributeList AllocAttrs; |
| |
| #define FUNCTION_ID(Id) \ |
| public: \ |
| llvm::Constant *get##Id##Fn(); \ |
| private: \ |
| llvm::Constant *Id##Fn = nullptr; |
| #include "swift/Runtime/RuntimeFunctions.def" |
| |
| llvm::Constant *FixLifetimeFn = nullptr; |
| |
| mutable Optional<SpareBitVector> HeapPointerSpareBits; |
| |
| //--- Generic --------------------------------------------------------------- |
| public: |
| llvm::Constant *getFixLifetimeFn(); |
| |
| /// 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<llvm::TargetMachine> &&target, |
| SourceFile *SF, llvm::LLVMContext &LLVMContext, |
| StringRef ModuleName, StringRef OutputFilename, |
| StringRef MainInputFilenameForDebugInfo); |
| |
| /// The constructor used when we just need an IRGenModule for type lowering. |
| IRGenModule(IRGenerator &irgen, std::unique_ptr<llvm::TargetMachine> &&target, |
| llvm::LLVMContext &LLVMContext) |
| : IRGenModule(irgen, std::move(target), /*SF=*/nullptr, LLVMContext, |
| "<fake module name>", "<fake output filename>", |
| "<fake main input filename>") {} |
| |
| ~IRGenModule(); |
| |
| llvm::LLVMContext &getLLVMContext() const { return LLVMContext; } |
| |
| void emitSourceFile(SourceFile &SF); |
| 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); |
| llvm::AttributeList constructInitialAttributes(); |
| |
| void emitProtocolDecl(ProtocolDecl *D); |
| void emitEnumDecl(EnumDecl *D); |
| void emitStructDecl(StructDecl *D); |
| void emitClassDecl(ClassDecl *D); |
| void emitExtension(ExtensionDecl *D); |
| void emitSILGlobalVariable(SILGlobalVariable *gv); |
| void emitCoverageMapping(); |
| void emitSILFunction(SILFunction *f); |
| void emitSILWitnessTable(SILWitnessTable *wt); |
| void emitSILProperty(SILProperty *prop); |
| void emitSILStaticInitializers(); |
| 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); |
| llvm::FunctionType *getFunctionType(CanSILFunctionType type, |
| llvm::AttributeList &attrs, |
| ForeignFunctionInfo *foreignInfo=nullptr); |
| ForeignFunctionInfo getForeignFunctionInfo(CanSILFunctionType type); |
| |
| llvm::Constant *getInt32(uint32_t value); |
| llvm::Constant *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::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::GlobalValue *defineMethodDescriptor(SILDeclRef declRef, |
| NominalTypeDecl *nominalDecl, |
| llvm::Constant *definition); |
| llvm::Constant *getAddrOfMethodDescriptor(SILDeclRef declRef, |
| ForDefinition_t forDefinition); |
| |
| Address getAddrOfEnumCase(EnumElementDecl *Case, |
| ForDefinition_t forDefinition); |
| Address getAddrOfFieldOffset(VarDecl *D, ForDefinition_t forDefinition); |
| llvm::Function *getAddrOfValueWitness(CanType concreteType, |
| ValueWitness index, |
| ForDefinition_t forDefinition); |
| llvm::Constant *getAddrOfValueWitnessTable(CanType concreteType, |
| ConstantInit init = ConstantInit()); |
| Optional<llvm::Function*> getAddrOfIVarInitDestroy(ClassDecl *cd, |
| bool isDestroyer, |
| bool isForeign, |
| ForDefinition_t forDefinition); |
| llvm::GlobalValue *defineTypeMetadata(CanType concreteType, |
| bool isPattern, |
| bool isConstant, |
| ConstantInitFuture init, |
| llvm::StringRef section = {}); |
| |
| TypeEntityReference getTypeEntityReference(NominalTypeDecl *D); |
| |
| llvm::Constant *getAddrOfTypeMetadata(CanType concreteType); |
| ConstantReference getAddrOfTypeMetadata(CanType concreteType, |
| SymbolReferenceKind kind); |
| 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<llvm::Type *> genericArgs, |
| ForDefinition_t forDefinition); |
| llvm::Constant *getAddrOfTypeMetadataLazyCacheVariable(CanType type, |
| ForDefinition_t forDefinition); |
| llvm::Constant *getAddrOfForeignTypeMetadataCandidate(CanType concreteType); |
| |
| llvm::Constant *getAddrOfClassMetadataBounds(ClassDecl *D, |
| ForDefinition_t forDefinition); |
| llvm::Constant *getAddrOfTypeContextDescriptor(NominalTypeDecl *D, |
| RequireMetadata_t requireMetadata, |
| ConstantInit definition = ConstantInit()); |
| llvm::Constant *getAddrOfAnonymousContextDescriptor(DeclContext *DC, |
| 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(); |
| ConstantReference getAddrOfParentContextDescriptor(DeclContext *from, |
| 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::Function *getAddrOfObjCMetadataUpdateFunction(ClassDecl *D, |
| ForDefinition_t forDefinition); |
| |
| llvm::Function * |
| getAddrOfSILFunction(SILFunction *f, ForDefinition_t forDefinition, |
| bool isDynamicallyReplaceableImplementation = false, |
| bool shouldCallPreviousImplementation = false); |
| |
| void emitDynamicReplacementOriginalFunctionThunk(SILFunction *f); |
| |
| llvm::Function *getAddrOfContinuationPrototype(CanSILFunctionType fnType); |
| Address getAddrOfSILGlobalVariable(SILGlobalVariable *var, |
| const TypeInfo &ti, |
| ForDefinition_t forDefinition); |
| 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 RootProtocolConformance *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); |
| |
| Address getAddrOfObjCISAMask(); |
| |
| /// Retrieve the generic environment for the current generic context. |
| /// |
| /// Fails if there is no generic context. |
| GenericEnvironment *getGenericEnvironment(); |
| |
| ConstantReference |
| getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity, |
| ConstantReference::Directness forceIndirect = ConstantReference::Direct); |
| |
| llvm::Constant * |
| emitRelativeReference(ConstantReference target, |
| llvm::Constant *base, |
| ArrayRef<unsigned> baseIndices); |
| |
| llvm::Constant * |
| emitDirectRelativeReference(llvm::Constant *target, |
| llvm::Constant *base, |
| ArrayRef<unsigned> 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); |
| |
| /// Add the swifterror attribute. |
| void addSwiftErrorAttributes(llvm::AttributeList &attrs, unsigned argIndex); |
| |
| void emitSharedContextDescriptor(DeclContext *dc); |
| |
| void ensureRelativeSymbolCollocation(SILWitnessTable &wt); |
| |
| llvm::GlobalVariable * |
| getGlobalForDynamicallyReplaceableThunk(LinkEntity &entity, llvm::Type *type, |
| ForDefinition_t forDefinition); |
| |
| private: |
| llvm::Constant * |
| getAddrOfSharedContextDescriptor(LinkEntity entity, |
| ConstantInit definition, |
| llvm::function_ref<void()> emit); |
| |
| llvm::Constant *getAddrOfLLVMVariable(LinkEntity entity, |
| ConstantInit definition, |
| DebugTypeInfo debugType, |
| llvm::Type *overrideDeclType = nullptr); |
| llvm::Constant *getAddrOfLLVMVariable(LinkEntity entity, |
| ForDefinition_t forDefinition, |
| DebugTypeInfo debugType); |
| ConstantReference getAddrOfLLVMVariable(LinkEntity entity, |
| ConstantInit definition, |
| DebugTypeInfo debugType, |
| SymbolReferenceKind refKind, |
| llvm::Type *overrideDeclType = nullptr); |
| |
| void emitLazyPrivateDefinitions(); |
| void addRuntimeResolvableType(NominalTypeDecl *nominal); |
| |
| /// Add all conformances of the given \c DeclContext LazyWitnessTables. |
| void addLazyConformances(DeclContext *dc); |
| |
| //--- Global context emission -------------------------------------------------- |
| public: |
| void emitRuntimeRegistration(); |
| void emitVTableStubs(); |
| void emitTypeVerifier(); |
| |
| /// 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); |
| |
| } // end namespace irgen |
| } // end namespace swift |
| |
| namespace llvm { |
| |
| template<> |
| struct DenseMapInfo<swift::irgen::IRGenModule::FixedLayoutKey> { |
| 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 |