IRGenModule::IRGenModule(IRGenerator &irgen, std::unique_ptr<llvm::TargetMachine> &&target, SourceFile *SF, llvm::LLVMContext &LLVMContext, StringRef ModuleName, StringRef OutputFilename, StringRef MainInputFilenameForDebugInfo) : IRGen(irgen), Context(irgen.SIL.getASTContext()), ClangCodeGen(createClangCodeGenerator(Context, LLVMContext, irgen.Opts, ModuleName)), Module(*ClangCodeGen->GetModule()), LLVMContext(Module.getContext()), DataLayout(irgen.getClangDataLayout()), Triple(irgen.getEffectiveClangTriple()), TargetMachine(std::move(target)), silConv(irgen.SIL), OutputFilename(OutputFilename), MainInputFilenameForDebugInfo(MainInputFilenameForDebugInfo), TargetInfo(SwiftTargetInfo::get(*this)), DebugInfo(nullptr), ModuleHash(nullptr), ObjCInterop(Context.LangOpts.EnableObjCInterop), UseDarwinPreStableABIBit(Context.LangOpts.UseDarwinPreStableABIBit), Types(*new TypeConverter(*this)) { irgen.addGenModule(SF, this); auto &opts = irgen.Opts; EnableValueNames = opts.shouldProvideValueNames(); VoidTy = llvm::Type::getVoidTy(getLLVMContext()); Int1Ty = llvm::Type::getInt1Ty(getLLVMContext()); Int8Ty = llvm::Type::getInt8Ty(getLLVMContext()); Int16Ty = llvm::Type::getInt16Ty(getLLVMContext()); Int32Ty = llvm::Type::getInt32Ty(getLLVMContext()); Int32PtrTy = Int32Ty->getPointerTo(); Int64Ty = llvm::Type::getInt64Ty(getLLVMContext()); Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); Int8PtrPtrTy = Int8PtrTy->getPointerTo(0); SizeTy = DataLayout.getIntPtrType(getLLVMContext(), /*addrspace*/ 0); // For the relative address type, we want to use the int32 bit type // on most architectures, e.g. x86_64, because it produces valid // fixups/relocations. The exception is 16-bit architectures, // so we shorten the relative address type there. if (SizeTy->getBitWidth()<32) { RelativeAddressTy = SizeTy; } else { RelativeAddressTy = Int32Ty; } RelativeAddressPtrTy = RelativeAddressTy->getPointerTo(); FloatTy = llvm::Type::getFloatTy(getLLVMContext()); DoubleTy = llvm::Type::getDoubleTy(getLLVMContext()); auto CI = static_cast<ClangImporter*>(&*Context.getClangModuleLoader()); assert(CI && "no clang module loader"); auto &clangASTContext = CI->getClangASTContext(); ObjCBoolTy = Int1Ty; if (clangASTContext.getTargetInfo().useSignedCharForObjCBool()) ObjCBoolTy = Int8Ty; RefCountedStructTy = llvm::StructType::create(getLLVMContext(), "swift.refcounted"); RefCountedPtrTy = RefCountedStructTy->getPointerTo(/*addrspace*/ 0); RefCountedNull = llvm::ConstantPointerNull::get(RefCountedPtrTy); // For now, references storage types are just pointers. #define CHECKED_REF_STORAGE(Name, name, ...) \ Name##ReferencePtrTy = \ createStructPointerType(*this, "swift." #name, { RefCountedPtrTy }); #include "swift/AST/ReferenceStorage.def" // A type metadata record is the structure pointed to by the canonical // address point of a type metadata. This is at least one word, and // potentially more than that, past the start of the actual global // structure. TypeMetadataStructTy = createStructType(*this, "swift.type", { MetadataKindTy // MetadataKind Kind; }); TypeMetadataPtrTy = TypeMetadataStructTy->getPointerTo(DefaultAS); TypeMetadataResponseTy = createStructType(*this, "swift.metadata_response", { TypeMetadataPtrTy, SizeTy }); OffsetPairTy = llvm::StructType::get(getLLVMContext(), { SizeTy, SizeTy }); // The TypeLayout structure, including all possible trailing components. FullTypeLayoutTy = createStructType(*this, "swift.full_type_layout", { SizeTy, // size SizeTy, // flags SizeTy, // alignment SizeTy // extra inhabitant flags (optional) }); // A protocol descriptor describes a protocol. It is not type metadata in // and of itself, but is referenced in the structure of existential type // metadata records. ProtocolDescriptorStructTy = createStructType(*this, "swift.protocol", { Int8PtrTy, // objc isa Int8PtrTy, // name Int8PtrTy, // inherited protocols Int8PtrTy, // required objc instance methods Int8PtrTy, // required objc class methods Int8PtrTy, // optional objc instance methods Int8PtrTy, // optional objc class methods Int8PtrTy, // objc properties Int32Ty, // size Int32Ty, // flags Int32Ty, // total requirement count Int32Ty, // requirements array RelativeAddressTy, // superclass RelativeAddressTy // associated type names }); ProtocolDescriptorPtrTy = ProtocolDescriptorStructTy->getPointerTo(); ProtocolRequirementStructTy = createStructType(*this, "swift.protocol_requirement", { Int32Ty, // flags RelativeAddressTy, // default implementation }); // A tuple type metadata record has a couple extra fields. auto tupleElementTy = createStructType(*this, "swift.tuple_element_type", { TypeMetadataPtrTy, // Metadata *Type; SizeTy // size_t Offset; }); TupleTypeMetadataPtrTy = createStructPointerType(*this, "swift.tuple_type", { TypeMetadataStructTy, // (base) SizeTy, // size_t NumElements; Int8PtrTy, // const char *Labels; llvm::ArrayType::get(tupleElementTy, 0) // Element Elements[]; }); // A full type metadata record is basically just an adjustment to the // address point of a type metadata. Resilience may cause // additional data to be laid out prior to this address point. FullTypeMetadataStructTy = createStructType(*this, "swift.full_type", { WitnessTablePtrTy, TypeMetadataStructTy }); FullTypeMetadataPtrTy = FullTypeMetadataStructTy->getPointerTo(DefaultAS); DeallocatingDtorTy = llvm::FunctionType::get(VoidTy, RefCountedPtrTy, false); llvm::Type *dtorPtrTy = DeallocatingDtorTy->getPointerTo(); // A full heap metadata is basically just an additional small prefix // on a full metadata, used for metadata corresponding to heap // allocations. FullHeapMetadataStructTy = createStructType(*this, "swift.full_heapmetadata", { dtorPtrTy, WitnessTablePtrTy, TypeMetadataStructTy }); FullHeapMetadataPtrTy = FullHeapMetadataStructTy->getPointerTo(DefaultAS); // A full box metadata is non-type heap metadata for a heap allocation of a // single value. The box tracks the offset to the value inside the box. FullBoxMetadataStructTy = createStructType(*this, "swift.full_boxmetadata", { dtorPtrTy, WitnessTablePtrTy, TypeMetadataStructTy, Int32Ty, CaptureDescriptorPtrTy, }); FullBoxMetadataPtrTy = FullBoxMetadataStructTy->getPointerTo(DefaultAS); // This must match struct HeapObject in the runtime. llvm::Type *refCountedElts[] = {TypeMetadataPtrTy, IntPtrTy}; RefCountedStructTy->setBody(refCountedElts); RefCountedStructSize = Size(DataLayout.getStructLayout(RefCountedStructTy)->getSizeInBytes()); PtrSize = Size(DataLayout.getPointerSize(DefaultAS)); FunctionPairTy = createStructType(*this, "swift.function", { FunctionPtrTy, RefCountedPtrTy, }); OpaqueTy = llvm::StructType::create(LLVMContext, "swift.opaque"); OpaquePtrTy = OpaqueTy->getPointerTo(DefaultAS); NoEscapeFunctionPairTy = createStructType(*this, "swift.noescape.function", { FunctionPtrTy, OpaquePtrTy, }); ProtocolRecordTy = createStructType(*this, "swift.protocolref", { RelativeAddressTy }); ProtocolRecordPtrTy = ProtocolRecordTy->getPointerTo(); ProtocolConformanceDescriptorTy = createStructType(*this, "swift.protocol_conformance_descriptor", { RelativeAddressTy, RelativeAddressTy, RelativeAddressTy, Int32Ty }); ProtocolConformanceDescriptorPtrTy = ProtocolConformanceDescriptorTy->getPointerTo(DefaultAS); TypeContextDescriptorTy = llvm::StructType::create(LLVMContext, "swift.type_descriptor"); TypeContextDescriptorPtrTy = TypeContextDescriptorTy->getPointerTo(DefaultAS); ClassContextDescriptorTy = llvm::StructType::get(LLVMContext, { Int32Ty, // context flags Int32Ty, // parent Int32Ty, // name Int32Ty, // kind Int32Ty, // accessor function Int32Ty, // num fields Int32Ty, // field offset vector Int32Ty, // is_reflectable flag Int32Ty, // (Generics Descriptor) argument offset Int32Ty, // (Generics Descriptor) num params Int32Ty, // (Generics Descriptor) num requirements Int32Ty, // (Generics Descriptor) num key arguments Int32Ty, // (Generics Descriptor) num extra arguments Int32Ty, // (VTable Descriptor) offset Int32Ty, // (VTable Descriptor) size Int32Ty, // (Methods Descriptor) accessor Int32Ty, // (Methods Descriptor) flags }, /*packed=*/true); MethodDescriptorStructTy = createStructType(*this, "swift.method_descriptor", { Int32Ty, RelativeAddressTy, }); MethodOverrideDescriptorStructTy = createStructType(*this, "swift.method_override_descriptor", { RelativeAddressTy, RelativeAddressTy, RelativeAddressTy }); TypeMetadataRecordTy = createStructType(*this, "swift.type_metadata_record", { RelativeAddressTy }); TypeMetadataRecordPtrTy = TypeMetadataRecordTy->getPointerTo(DefaultAS); FieldDescriptorTy = llvm::StructType::create(LLVMContext, "swift.field_descriptor"); FieldDescriptorPtrTy = FieldDescriptorTy->getPointerTo(DefaultAS); FieldDescriptorPtrPtrTy = FieldDescriptorPtrTy->getPointerTo(DefaultAS); FixedBufferTy = nullptr; for (unsigned i = 0; i != MaxNumValueWitnesses; ++i) ValueWitnessTys[i] = nullptr; ObjCPtrTy = llvm::StructType::create(getLLVMContext(), "objc_object") ->getPointerTo(DefaultAS); BridgeObjectPtrTy = llvm::StructType::create(getLLVMContext(), "swift.bridge") ->getPointerTo(DefaultAS); ObjCClassStructTy = llvm::StructType::create(LLVMContext, "objc_class"); ObjCClassPtrTy = ObjCClassStructTy->getPointerTo(DefaultAS); llvm::Type *objcClassElts[] = { ObjCClassPtrTy, ObjCClassPtrTy, OpaquePtrTy, OpaquePtrTy, IntPtrTy }; ObjCClassStructTy->setBody(objcClassElts); ObjCSuperStructTy = llvm::StructType::create(LLVMContext, "objc_super"); ObjCSuperPtrTy = ObjCSuperStructTy->getPointerTo(DefaultAS); llvm::Type *objcSuperElts[] = { ObjCPtrTy, ObjCClassPtrTy }; ObjCSuperStructTy->setBody(objcSuperElts); ObjCBlockStructTy = llvm::StructType::create(LLVMContext, "objc_block"); ObjCBlockPtrTy = ObjCBlockStructTy->getPointerTo(DefaultAS); llvm::Type *objcBlockElts[] = { ObjCClassPtrTy, // isa Int32Ty, // flags Int32Ty, // reserved FunctionPtrTy, // invoke function pointer Int8PtrTy, // TODO: block descriptor pointer. // We will probably need a struct type for that at some // point too. }; ObjCBlockStructTy->setBody(objcBlockElts); auto ErrorStructTy = llvm::StructType::create(LLVMContext, "swift.error"); // ErrorStruct is currently opaque to the compiler. ErrorPtrTy = ErrorStructTy->getPointerTo(DefaultAS); llvm::Type *openedErrorTriple[] = { OpaquePtrTy, TypeMetadataPtrTy, WitnessTablePtrTy, }; OpenedErrorTripleTy = llvm::StructType::get(getLLVMContext(), openedErrorTriple, /*packed*/ false); OpenedErrorTriplePtrTy = OpenedErrorTripleTy->getPointerTo(DefaultAS); WitnessTablePtrPtrTy = WitnessTablePtrTy->getPointerTo(DefaultAS); InvariantMetadataID = LLVMContext.getMDKindID("invariant.load"); InvariantNode = llvm::MDNode::get(LLVMContext, {}); DereferenceableID = LLVMContext.getMDKindID("dereferenceable"); C_CC = llvm::CallingConv::C; // TODO: use "tinycc" on platforms that support it DefaultCC = SWIFT_DEFAULT_LLVM_CC; SwiftCC = llvm::CallingConv::Swift; if (opts.DebugInfoLevel > IRGenDebugInfoLevel::None) DebugInfo = IRGenDebugInfo::createIRGenDebugInfo(IRGen.Opts, *CI, *this, Module, MainInputFilenameForDebugInfo); initClangTypeConverter(); if (ClangASTContext) { auto atomicBoolTy = ClangASTContext->getAtomicType(ClangASTContext->BoolTy); AtomicBoolSize = Size(ClangASTContext->getTypeSize(atomicBoolTy)); AtomicBoolAlign = Alignment(ClangASTContext->getTypeSize(atomicBoolTy)); } IsSwiftErrorInRegister = clang::CodeGen::swiftcall::isSwiftErrorLoweredInRegister( ClangCodeGen->CGM()); DynamicReplacementsTy = llvm::StructType::get(getLLVMContext(), {Int8PtrPtrTy, Int8PtrTy}); DynamicReplacementsPtrTy = DynamicReplacementsTy->getPointerTo(DefaultAS); DynamicReplacementLinkEntryTy = llvm::StructType::create(getLLVMContext(), "swift.dyn_repl_link_entry"); DynamicReplacementLinkEntryPtrTy = DynamicReplacementLinkEntryTy->getPointerTo(DefaultAS); llvm::Type *linkEntryFields[] = { Int8PtrTy, // function pointer. DynamicReplacementLinkEntryPtrTy // next. }; DynamicReplacementLinkEntryTy->setBody(linkEntryFields); DynamicReplacementKeyTy = createStructType(*this, "swift.dyn_repl_key", {RelativeAddressTy, Int32Ty}); }
IRGenModule::IRGenModule(IRGenModuleDispatcher &dispatcher, SourceFile *SF, ASTContext &Context, llvm::LLVMContext &LLVMContext, IRGenOptions &Opts, StringRef ModuleName, const llvm::DataLayout &DataLayout, const llvm::Triple &Triple, llvm::TargetMachine *TargetMachine, SILModule *SILMod, StringRef OutputFilename) : Context(Context), Opts(Opts), ClangCodeGen(createClangCodeGenerator(Context, LLVMContext, Opts, ModuleName)), Module(*ClangCodeGen->GetModule()), LLVMContext(Module.getContext()), DataLayout(DataLayout), Triple(Triple), TargetMachine(TargetMachine), SILMod(SILMod), OutputFilename(OutputFilename), dispatcher(dispatcher), TargetInfo(SwiftTargetInfo::get(*this)), DebugInfo(0), ModuleHash(nullptr), ObjCInterop(Context.LangOpts.EnableObjCInterop), Types(*new TypeConverter(*this)) { dispatcher.addGenModule(SF, this); // If the command line contains an explicit request about whether to add // LLVM value names, honor it. Otherwise, add value names only if the // final result is textual LLVM assembly. if (Opts.HasValueNamesSetting) { EnableValueNames = Opts.ValueNames; } else { EnableValueNames = (Opts.OutputKind == IRGenOutputKind::LLVMAssembly); } VoidTy = llvm::Type::getVoidTy(getLLVMContext()); Int1Ty = llvm::Type::getInt1Ty(getLLVMContext()); Int8Ty = llvm::Type::getInt8Ty(getLLVMContext()); Int16Ty = llvm::Type::getInt16Ty(getLLVMContext()); Int32Ty = llvm::Type::getInt32Ty(getLLVMContext()); Int64Ty = llvm::Type::getInt64Ty(getLLVMContext()); Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); Int8PtrPtrTy = Int8PtrTy->getPointerTo(0); SizeTy = DataLayout.getIntPtrType(getLLVMContext(), /*addrspace*/ 0); auto CI = static_cast<ClangImporter*>(&*Context.getClangModuleLoader()); assert(CI && "no clang module loader"); auto &clangASTContext = CI->getClangASTContext(); ObjCBoolTy = Int1Ty; if (clangASTContext.getTargetInfo().useSignedCharForObjCBool()) ObjCBoolTy = Int8Ty; RefCountedStructTy = llvm::StructType::create(getLLVMContext(), "swift.refcounted"); RefCountedPtrTy = RefCountedStructTy->getPointerTo(/*addrspace*/ 0); RefCountedNull = llvm::ConstantPointerNull::get(RefCountedPtrTy); // For now, native weak references are just a pointer. WeakReferencePtrTy = createStructPointerType(*this, "swift.weak", { RefCountedPtrTy }); // Native unowned references are just a pointer. UnownedReferencePtrTy = createStructPointerType(*this, "swift.unowned", { RefCountedPtrTy }); // A type metadata record is the structure pointed to by the canonical // address point of a type metadata. This is at least one word, and // potentially more than that, past the start of the actual global // structure. TypeMetadataStructTy = createStructType(*this, "swift.type", { MetadataKindTy // MetadataKind Kind; }); TypeMetadataPtrTy = TypeMetadataStructTy->getPointerTo(DefaultAS); // A protocol descriptor describes a protocol. It is not type metadata in // and of itself, but is referenced in the structure of existential type // metadata records. ProtocolDescriptorStructTy = createStructType(*this, "swift.protocol", { Int8PtrTy, // objc isa Int8PtrTy, // name Int8PtrTy, // inherited protocols Int8PtrTy, // required objc instance methods Int8PtrTy, // required objc class methods Int8PtrTy, // optional objc instance methods Int8PtrTy, // optional objc class methods Int8PtrTy, // objc properties Int32Ty, // size Int32Ty, // flags Int16Ty, // minimum witness count Int16Ty // default witness count }); ProtocolDescriptorPtrTy = ProtocolDescriptorStructTy->getPointerTo(); // A tuple type metadata record has a couple extra fields. auto tupleElementTy = createStructType(*this, "swift.tuple_element_type", { TypeMetadataPtrTy, // Metadata *Type; SizeTy // size_t Offset; }); TupleTypeMetadataPtrTy = createStructPointerType(*this, "swift.tuple_type", { TypeMetadataStructTy, // (base) SizeTy, // size_t NumElements; Int8PtrTy, // const char *Labels; llvm::ArrayType::get(tupleElementTy, 0) // Element Elements[]; }); // A full type metadata record is basically just an adjustment to the // address point of a type metadata. Resilience may cause // additional data to be laid out prior to this address point. FullTypeMetadataStructTy = createStructType(*this, "swift.full_type", { WitnessTablePtrTy, TypeMetadataStructTy }); FullTypeMetadataPtrTy = FullTypeMetadataStructTy->getPointerTo(DefaultAS); // A metadata pattern is a structure from which generic type // metadata are allocated. We leave this struct type intentionally // opaque, because the compiler basically never needs to access // anything from one. TypeMetadataPatternStructTy = llvm::StructType::create(getLLVMContext(), "swift.type_pattern"); TypeMetadataPatternPtrTy = TypeMetadataPatternStructTy->getPointerTo(DefaultAS); DeallocatingDtorTy = llvm::FunctionType::get(VoidTy, RefCountedPtrTy, false); llvm::Type *dtorPtrTy = DeallocatingDtorTy->getPointerTo(); // A full heap metadata is basically just an additional small prefix // on a full metadata, used for metadata corresponding to heap // allocations. FullHeapMetadataStructTy = createStructType(*this, "swift.full_heapmetadata", { dtorPtrTy, WitnessTablePtrTy, TypeMetadataStructTy }); FullHeapMetadataPtrTy = FullHeapMetadataStructTy->getPointerTo(DefaultAS); // A full box metadata is non-type heap metadata for a heap allocation of a // single value. The box tracks the offset to the value inside the box. FullBoxMetadataStructTy = createStructType(*this, "swift.full_boxmetadata", { dtorPtrTy, WitnessTablePtrTy, TypeMetadataStructTy, Int32Ty, }); FullBoxMetadataPtrTy = FullBoxMetadataStructTy->getPointerTo(DefaultAS); llvm::Type *refCountedElts[] = { TypeMetadataPtrTy, Int32Ty, Int32Ty }; RefCountedStructTy->setBody(refCountedElts); PtrSize = Size(DataLayout.getPointerSize(DefaultAS)); FunctionPairTy = createStructType(*this, "swift.function", { FunctionPtrTy, RefCountedPtrTy, }); OpaquePtrTy = llvm::StructType::create(LLVMContext, "swift.opaque") ->getPointerTo(DefaultAS); ProtocolConformanceRecordTy = createStructType(*this, "swift.protocol_conformance", { RelativeAddressTy, RelativeAddressTy, RelativeAddressTy, Int32Ty }); ProtocolConformanceRecordPtrTy = ProtocolConformanceRecordTy->getPointerTo(DefaultAS); NominalTypeDescriptorTy = llvm::StructType::create(LLVMContext, "swift.type_descriptor"); NominalTypeDescriptorPtrTy = NominalTypeDescriptorTy->getPointerTo(DefaultAS); TypeMetadataRecordTy = createStructType(*this, "swift.type_metadata_record", { RelativeAddressTy, Int32Ty }); TypeMetadataRecordPtrTy = TypeMetadataRecordTy->getPointerTo(DefaultAS); FieldDescriptorTy = llvm::StructType::create(LLVMContext, "swift.field_descriptor"); FieldDescriptorPtrTy = FieldDescriptorTy->getPointerTo(DefaultAS); FixedBufferTy = nullptr; for (unsigned i = 0; i != MaxNumValueWitnesses; ++i) ValueWitnessTys[i] = nullptr; ObjCPtrTy = llvm::StructType::create(getLLVMContext(), "objc_object") ->getPointerTo(DefaultAS); BridgeObjectPtrTy = llvm::StructType::create(getLLVMContext(), "swift.bridge") ->getPointerTo(DefaultAS); ObjCClassStructTy = llvm::StructType::create(LLVMContext, "objc_class"); ObjCClassPtrTy = ObjCClassStructTy->getPointerTo(DefaultAS); llvm::Type *objcClassElts[] = { ObjCClassPtrTy, ObjCClassPtrTy, OpaquePtrTy, OpaquePtrTy, IntPtrTy }; ObjCClassStructTy->setBody(objcClassElts); ObjCSuperStructTy = llvm::StructType::create(LLVMContext, "objc_super"); ObjCSuperPtrTy = ObjCSuperStructTy->getPointerTo(DefaultAS); llvm::Type *objcSuperElts[] = { ObjCPtrTy, ObjCClassPtrTy }; ObjCSuperStructTy->setBody(objcSuperElts); ObjCBlockStructTy = llvm::StructType::create(LLVMContext, "objc_block"); ObjCBlockPtrTy = ObjCBlockStructTy->getPointerTo(DefaultAS); llvm::Type *objcBlockElts[] = { ObjCClassPtrTy, // isa Int32Ty, // flags Int32Ty, // reserved FunctionPtrTy, // invoke function pointer Int8PtrTy, // TODO: block descriptor pointer. // We will probably need a struct type for that at some // point too. }; ObjCBlockStructTy->setBody(objcBlockElts); auto ErrorStructTy = llvm::StructType::create(LLVMContext, "swift.error"); // ErrorStruct is currently opaque to the compiler. ErrorPtrTy = ErrorStructTy->getPointerTo(DefaultAS); llvm::Type *openedErrorTriple[] = { OpaquePtrTy, TypeMetadataPtrTy, WitnessTablePtrTy, }; OpenedErrorTripleTy = llvm::StructType::get(getLLVMContext(), openedErrorTriple, /*packed*/ false); OpenedErrorTriplePtrTy = OpenedErrorTripleTy->getPointerTo(DefaultAS); InvariantMetadataID = LLVMContext.getMDKindID("invariant.load"); InvariantNode = llvm::MDNode::get(LLVMContext, {}); DereferenceableID = LLVMContext.getMDKindID("dereferenceable"); // TODO: use "tinycc" on platforms that support it RuntimeCC = llvm::CallingConv::C; ABITypes = new CodeGenABITypes(clangASTContext, Module); if (Opts.DebugInfoKind != IRGenDebugInfoKind::None) { DebugInfo = new IRGenDebugInfo(Opts, *CI, *this, Module, SF); } initClangTypeConverter(); }
IRGenModule::IRGenModule(IRGenerator &irgen, std::unique_ptr<llvm::TargetMachine> &&target, SourceFile *SF, llvm::LLVMContext &LLVMContext, StringRef ModuleName, StringRef OutputFilename) : IRGen(irgen), Context(irgen.SIL.getASTContext()), ClangCodeGen(createClangCodeGenerator(Context, LLVMContext, irgen.Opts, ModuleName)), Module(*ClangCodeGen->GetModule()), LLVMContext(Module.getContext()), DataLayout(target->createDataLayout()), Triple(Context.LangOpts.Target), TargetMachine(std::move(target)), silConv(irgen.SIL), OutputFilename(OutputFilename), TargetInfo(SwiftTargetInfo::get(*this)), DebugInfo(nullptr), ModuleHash(nullptr), ObjCInterop(Context.LangOpts.EnableObjCInterop), Types(*new TypeConverter(*this)) { irgen.addGenModule(SF, this); auto &opts = irgen.Opts; EnableValueNames = opts.shouldProvideValueNames(); VoidTy = llvm::Type::getVoidTy(getLLVMContext()); Int1Ty = llvm::Type::getInt1Ty(getLLVMContext()); Int8Ty = llvm::Type::getInt8Ty(getLLVMContext()); Int16Ty = llvm::Type::getInt16Ty(getLLVMContext()); Int32Ty = llvm::Type::getInt32Ty(getLLVMContext()); Int64Ty = llvm::Type::getInt64Ty(getLLVMContext()); Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); Int8PtrPtrTy = Int8PtrTy->getPointerTo(0); SizeTy = DataLayout.getIntPtrType(getLLVMContext(), /*addrspace*/ 0); auto CI = static_cast<ClangImporter*>(&*Context.getClangModuleLoader()); assert(CI && "no clang module loader"); auto &clangASTContext = CI->getClangASTContext(); ObjCBoolTy = Int1Ty; if (clangASTContext.getTargetInfo().useSignedCharForObjCBool()) ObjCBoolTy = Int8Ty; RefCountedStructTy = llvm::StructType::create(getLLVMContext(), "swift.refcounted"); RefCountedPtrTy = RefCountedStructTy->getPointerTo(/*addrspace*/ 0); RefCountedNull = llvm::ConstantPointerNull::get(RefCountedPtrTy); // For now, native weak references are just a pointer. WeakReferencePtrTy = createStructPointerType(*this, "swift.weak", { RefCountedPtrTy }); // Native unowned references are just a pointer. UnownedReferencePtrTy = createStructPointerType(*this, "swift.unowned", { RefCountedPtrTy }); // A type metadata record is the structure pointed to by the canonical // address point of a type metadata. This is at least one word, and // potentially more than that, past the start of the actual global // structure. TypeMetadataStructTy = createStructType(*this, "swift.type", { MetadataKindTy // MetadataKind Kind; }); TypeMetadataPtrTy = TypeMetadataStructTy->getPointerTo(DefaultAS); // A protocol descriptor describes a protocol. It is not type metadata in // and of itself, but is referenced in the structure of existential type // metadata records. ProtocolDescriptorStructTy = createStructType(*this, "swift.protocol", { Int8PtrTy, // objc isa Int8PtrTy, // name Int8PtrTy, // inherited protocols Int8PtrTy, // required objc instance methods Int8PtrTy, // required objc class methods Int8PtrTy, // optional objc instance methods Int8PtrTy, // optional objc class methods Int8PtrTy, // objc properties Int32Ty, // size Int32Ty, // flags Int16Ty, // minimum witness count Int16Ty, // default witness count Int32Ty // padding }); ProtocolDescriptorPtrTy = ProtocolDescriptorStructTy->getPointerTo(); // A tuple type metadata record has a couple extra fields. auto tupleElementTy = createStructType(*this, "swift.tuple_element_type", { TypeMetadataPtrTy, // Metadata *Type; SizeTy // size_t Offset; }); TupleTypeMetadataPtrTy = createStructPointerType(*this, "swift.tuple_type", { TypeMetadataStructTy, // (base) SizeTy, // size_t NumElements; Int8PtrTy, // const char *Labels; llvm::ArrayType::get(tupleElementTy, 0) // Element Elements[]; }); // A full type metadata record is basically just an adjustment to the // address point of a type metadata. Resilience may cause // additional data to be laid out prior to this address point. FullTypeMetadataStructTy = createStructType(*this, "swift.full_type", { WitnessTablePtrTy, TypeMetadataStructTy }); FullTypeMetadataPtrTy = FullTypeMetadataStructTy->getPointerTo(DefaultAS); // A metadata pattern is a structure from which generic type // metadata are allocated. We leave this struct type intentionally // opaque, because the compiler basically never needs to access // anything from one. TypeMetadataPatternStructTy = llvm::StructType::create(getLLVMContext(), "swift.type_pattern"); TypeMetadataPatternPtrTy = TypeMetadataPatternStructTy->getPointerTo(DefaultAS); DeallocatingDtorTy = llvm::FunctionType::get(VoidTy, RefCountedPtrTy, false); llvm::Type *dtorPtrTy = DeallocatingDtorTy->getPointerTo(); // A full heap metadata is basically just an additional small prefix // on a full metadata, used for metadata corresponding to heap // allocations. FullHeapMetadataStructTy = createStructType(*this, "swift.full_heapmetadata", { dtorPtrTy, WitnessTablePtrTy, TypeMetadataStructTy }); FullHeapMetadataPtrTy = FullHeapMetadataStructTy->getPointerTo(DefaultAS); // A full box metadata is non-type heap metadata for a heap allocation of a // single value. The box tracks the offset to the value inside the box. FullBoxMetadataStructTy = createStructType(*this, "swift.full_boxmetadata", { dtorPtrTy, WitnessTablePtrTy, TypeMetadataStructTy, Int32Ty, CaptureDescriptorPtrTy, }); FullBoxMetadataPtrTy = FullBoxMetadataStructTy->getPointerTo(DefaultAS); llvm::Type *refCountedElts[] = {TypeMetadataPtrTy, Int32Ty, Int32Ty}; RefCountedStructTy->setBody(refCountedElts); PtrSize = Size(DataLayout.getPointerSize(DefaultAS)); FunctionPairTy = createStructType(*this, "swift.function", { FunctionPtrTy, RefCountedPtrTy, }); OpaqueTy = llvm::StructType::create(LLVMContext, "swift.opaque"); OpaquePtrTy = OpaqueTy->getPointerTo(DefaultAS); ProtocolConformanceRecordTy = createStructType(*this, "swift.protocol_conformance", { RelativeAddressTy, RelativeAddressTy, RelativeAddressTy, Int32Ty }); ProtocolConformanceRecordPtrTy = ProtocolConformanceRecordTy->getPointerTo(DefaultAS); NominalTypeDescriptorTy = llvm::StructType::create(LLVMContext, "swift.type_descriptor"); NominalTypeDescriptorPtrTy = NominalTypeDescriptorTy->getPointerTo(DefaultAS); TypeMetadataRecordTy = createStructType(*this, "swift.type_metadata_record", { RelativeAddressTy, Int32Ty }); TypeMetadataRecordPtrTy = TypeMetadataRecordTy->getPointerTo(DefaultAS); FieldDescriptorTy = llvm::StructType::create(LLVMContext, "swift.field_descriptor"); FieldDescriptorPtrTy = FieldDescriptorTy->getPointerTo(DefaultAS); FixedBufferTy = nullptr; for (unsigned i = 0; i != MaxNumValueWitnesses; ++i) ValueWitnessTys[i] = nullptr; ObjCPtrTy = llvm::StructType::create(getLLVMContext(), "objc_object") ->getPointerTo(DefaultAS); BridgeObjectPtrTy = llvm::StructType::create(getLLVMContext(), "swift.bridge") ->getPointerTo(DefaultAS); ObjCClassStructTy = llvm::StructType::create(LLVMContext, "objc_class"); ObjCClassPtrTy = ObjCClassStructTy->getPointerTo(DefaultAS); llvm::Type *objcClassElts[] = { ObjCClassPtrTy, ObjCClassPtrTy, OpaquePtrTy, OpaquePtrTy, IntPtrTy }; ObjCClassStructTy->setBody(objcClassElts); ObjCSuperStructTy = llvm::StructType::create(LLVMContext, "objc_super"); ObjCSuperPtrTy = ObjCSuperStructTy->getPointerTo(DefaultAS); llvm::Type *objcSuperElts[] = { ObjCPtrTy, ObjCClassPtrTy }; ObjCSuperStructTy->setBody(objcSuperElts); ObjCBlockStructTy = llvm::StructType::create(LLVMContext, "objc_block"); ObjCBlockPtrTy = ObjCBlockStructTy->getPointerTo(DefaultAS); llvm::Type *objcBlockElts[] = { ObjCClassPtrTy, // isa Int32Ty, // flags Int32Ty, // reserved FunctionPtrTy, // invoke function pointer Int8PtrTy, // TODO: block descriptor pointer. // We will probably need a struct type for that at some // point too. }; ObjCBlockStructTy->setBody(objcBlockElts); auto ErrorStructTy = llvm::StructType::create(LLVMContext, "swift.error"); // ErrorStruct is currently opaque to the compiler. ErrorPtrTy = ErrorStructTy->getPointerTo(DefaultAS); llvm::Type *openedErrorTriple[] = { OpaquePtrTy, TypeMetadataPtrTy, WitnessTablePtrTy, }; OpenedErrorTripleTy = llvm::StructType::get(getLLVMContext(), openedErrorTriple, /*packed*/ false); OpenedErrorTriplePtrTy = OpenedErrorTripleTy->getPointerTo(DefaultAS); InvariantMetadataID = LLVMContext.getMDKindID("invariant.load"); InvariantNode = llvm::MDNode::get(LLVMContext, {}); DereferenceableID = LLVMContext.getMDKindID("dereferenceable"); C_CC = llvm::CallingConv::C; // TODO: use "tinycc" on platforms that support it DefaultCC = SWIFT_LLVM_CC(DefaultCC); // If it is an interpreter, don't use try to use any // advanced calling conventions and use instead a // more conservative C calling convention. This // makes sure that none of the registers eventually // used by the dynamic linker are used by generated code. // TODO: Check that the deployment target supports the new // calling convention. Older versions of the runtime library // may not contain the entries using the new calling convention. // Only use the new calling conventions on platforms that support it. auto Arch = Triple.getArch(); (void)Arch; if (SWIFT_RT_USE_RegisterPreservingCC && Arch == llvm::Triple::ArchType::aarch64) RegisterPreservingCC = SWIFT_LLVM_CC(RegisterPreservingCC); else RegisterPreservingCC = DefaultCC; SwiftCC = SWIFT_LLVM_CC(SwiftCC); UseSwiftCC = (SwiftCC == llvm::CallingConv::Swift); if (IRGen.Opts.DebugInfoKind > IRGenDebugInfoKind::None) DebugInfo = IRGenDebugInfo::createIRGenDebugInfo(IRGen.Opts, *CI, *this, Module, SF); initClangTypeConverter(); if (ClangASTContext) { auto atomicBoolTy = ClangASTContext->getAtomicType(ClangASTContext->BoolTy); AtomicBoolSize = Size(ClangASTContext->getTypeSize(atomicBoolTy)); AtomicBoolAlign = Alignment(ClangASTContext->getTypeSize(atomicBoolTy)); } IsSwiftErrorInRegister = clang::CodeGen::swiftcall::isSwiftErrorLoweredInRegister( ClangCodeGen->CGM()); }