//===--- GenReflection.cpp - IR generation for nominal type reflection ----===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file implements IR generation of type metadata for struct/class // stored properties and enum cases for use with reflection. //===----------------------------------------------------------------------===// #include "swift/AST/Decl.h" #include "swift/AST/IRGenOptions.h" #include "swift/AST/PrettyStackTrace.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/SubstitutionMap.h" #include "swift/IRGen/Linking.h" #include "swift/Reflection/MetadataSourceBuilder.h" #include "swift/Reflection/Records.h" #include "swift/SIL/SILModule.h" #include "ConstantBuilder.h" #include "GenClass.h" #include "GenDecl.h" #include "GenEnum.h" #include "GenHeap.h" #include "GenProto.h" #include "GenType.h" #include "IRGenMangler.h" #include "IRGenModule.h" #include "LoadableTypeInfo.h" using namespace swift; using namespace irgen; using namespace reflection; class MetadataSourceEncoder : public MetadataSourceVisitor { llvm::raw_ostream &OS; public: MetadataSourceEncoder(llvm::raw_ostream &OS) : OS(OS) {} void visitClosureBindingMetadataSource(const ClosureBindingMetadataSource *CB) { OS << 'B'; OS << CB->getIndex(); } void visitReferenceCaptureMetadataSource(const ReferenceCaptureMetadataSource *RC){ OS << 'R'; OS << RC->getIndex(); } void visitMetadataCaptureMetadataSource(const MetadataCaptureMetadataSource *MC) { OS << 'M'; OS << MC->getIndex(); } void visitGenericArgumentMetadataSource(const GenericArgumentMetadataSource *GA) { OS << 'G'; OS << GA->getIndex(); visit(GA->getSource()); OS << '_'; } void visitSelfMetadataSource(const SelfMetadataSource *S) { OS << 'S'; } void visitSelfWitnessTableMetadataSource(const SelfWitnessTableMetadataSource *S) { OS << 'W'; } }; class PrintMetadataSource : public MetadataSourceVisitor { llvm::raw_ostream &OS; unsigned Indent; llvm::raw_ostream &indent(unsigned Amount) { for (unsigned i = 0; i < Amount; ++i) OS << ' '; return OS; } llvm::raw_ostream &printHeader(std::string Name) { indent(Indent) << '(' << Name; return OS; } template llvm::raw_ostream &printField(std::string name, const T &value) { if (!name.empty()) OS << " " << name << "=" << value; else OS << " " << value; return OS; } void printRec(const reflection::MetadataSource *MS) { OS << "\n"; Indent += 2; visit(MS); Indent -= 2; } void closeForm() { OS << ')'; } public: PrintMetadataSource(llvm::raw_ostream &OS, unsigned Indent) : OS(OS), Indent(Indent) {} void visitClosureBindingMetadataSource(const ClosureBindingMetadataSource *CB) { printHeader("closure-binding"); printField("index", CB->getIndex()); closeForm(); } void visitReferenceCaptureMetadataSource(const ReferenceCaptureMetadataSource *RC){ printHeader("reference-capture"); printField("index", RC->getIndex()); closeForm(); } void visitMetadataCaptureMetadataSource(const MetadataCaptureMetadataSource *MC){ printHeader("metadata-capture"); printField("index", MC->getIndex()); closeForm(); } void visitGenericArgumentMetadataSource(const GenericArgumentMetadataSource *GA) { printHeader("generic-argument"); printField("index", GA->getIndex()); printRec(GA->getSource()); closeForm(); } void visitSelfMetadataSource(const SelfMetadataSource *S) { printHeader("self"); closeForm(); } void visitSelfWitnessTableMetadataSource(const SelfWitnessTableMetadataSource *S) { printHeader("self-witness-table"); closeForm(); } }; llvm::Constant *IRGenModule::getTypeRef(CanType type) { IRGenMangler Mangler; auto SymbolicName = Mangler.mangleTypeForReflection(*this, type); return getAddrOfStringForTypeRef(SymbolicName); } class ReflectionMetadataBuilder { protected: IRGenModule &IGM; ConstantInitBuilder InitBuilder; ConstantStructBuilder B; ReflectionMetadataBuilder(IRGenModule &IGM) : IGM(IGM), InitBuilder(IGM), B(InitBuilder.beginStruct()) {} virtual ~ReflectionMetadataBuilder() {} // Collect any builtin types referenced from this type. void addBuiltinTypeRefs(CanType type) { type.visit([&](CanType t) { if (IGM.getSwiftModule()->isStdlibModule() && isa(t)) IGM.BuiltinTypes.insert(t); // We need size/alignment information for imported value types, // so emit builtin descriptors for them. // // In effect they're treated like an opaque blob, which is OK // for now, at least until we want to import C++ types or // something like that. // // Classes and protocols go down a different path. if (auto Nominal = t->getAnyNominal()) if (Nominal->hasClangNode()) { if (auto CD = dyn_cast(Nominal)) IGM.ImportedClasses.insert(CD); else if (auto PD = dyn_cast(Nominal)) IGM.ImportedProtocols.insert(PD); else IGM.OpaqueTypes.insert(Nominal); } }); } /// Add a 32-bit relative offset to a mangled typeref string /// in the typeref reflection section. void addTypeRef(CanType type) { B.addRelativeAddress(IGM.getTypeRef(type)); } /// Add a 32-bit relative offset to a mangled nominal type string /// in the typeref reflection section. void addNominalRef(const NominalTypeDecl *nominal) { if (auto proto = dyn_cast(nominal)) { IRGenMangler mangler; SymbolicMangling mangledStr; mangledStr.String = mangler.mangleBareProtocol(proto); auto mangledName = IGM.getAddrOfStringForTypeRef(mangledStr); B.addRelativeAddress(mangledName); } else { CanType type = nominal->getDeclaredType()->getCanonicalType(); B.addRelativeAddress(IGM.getTypeRef(type)); } } llvm::GlobalVariable *emit(Optional entity, const char *section) { layout(); llvm::GlobalVariable *var; // Some reflection records have a mangled symbol name, for uniquing // imported type metadata. if (entity) { auto info = LinkInfo::get(IGM, *entity, ForDefinition); auto init = B.finishAndCreateFuture(); var = createVariable(IGM, info, init.getType(), Alignment(4)); var->setConstant(true); init.installInGlobal(var); // Others, such as capture descriptors, do not have a name. } else { var = B.finishAndCreateGlobal("\x01l__swift5_reflection_descriptor", Alignment(4), /*isConstant*/ true, llvm::GlobalValue::PrivateLinkage); } var->setSection(section); IGM.addUsedGlobal(var); disableAddressSanitizer(IGM, var); return var; } virtual void layout() = 0; }; class AssociatedTypeMetadataBuilder : public ReflectionMetadataBuilder { static const uint32_t AssociatedTypeRecordSize = 8; const ProtocolConformance *Conformance; ArrayRef> AssociatedTypes; void layout() override { // If the conforming type is generic, we just want to emit the // unbound generic type here. auto *Nominal = Conformance->getType()->getAnyNominal(); assert(Nominal && "Structural conformance?"); PrettyStackTraceDecl DebugStack("emitting associated type metadata", Nominal); addTypeRef(Nominal->getDeclaredType()->getCanonicalType()); addNominalRef(Conformance->getProtocol()); B.addInt32(AssociatedTypes.size()); B.addInt32(AssociatedTypeRecordSize); for (auto AssocTy : AssociatedTypes) { auto NameGlobal = IGM.getAddrOfFieldName(AssocTy.first); B.addRelativeAddress(NameGlobal); addBuiltinTypeRefs(AssocTy.second); addTypeRef(AssocTy.second); } } public: AssociatedTypeMetadataBuilder(IRGenModule &IGM, const ProtocolConformance *Conformance, ArrayRef> AssociatedTypes) : ReflectionMetadataBuilder(IGM), Conformance(Conformance), AssociatedTypes(AssociatedTypes) {} llvm::GlobalVariable *emit() { auto entity = LinkEntity::forReflectionAssociatedTypeDescriptor(Conformance); auto section = IGM.getAssociatedTypeMetadataSectionName(); return ReflectionMetadataBuilder::emit(entity, section); } }; class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder { const uint32_t fieldRecordSize = 12; const NominalTypeDecl *NTD; void addFieldDecl(const ValueDecl *value, CanType type, bool indirect=false) { reflection::FieldRecordFlags flags; flags.setIsIndirectCase(indirect); if (auto var = dyn_cast(value)) flags.setIsVar(!var->isLet()); B.addInt32(flags.getRawValue()); if (!type) { B.addInt32(0); } else { addTypeRef(type); addBuiltinTypeRefs(type); } if (IGM.IRGen.Opts.EnableReflectionNames) { auto name = value->getBaseName().getIdentifier().str(); auto fieldName = IGM.getAddrOfFieldName(name); B.addRelativeAddress(fieldName); } else { B.addInt32(0); } } void layoutRecord() { auto kind = FieldDescriptorKind::Struct; if (auto CD = dyn_cast(NTD)) { auto type = CD->getDeclaredType()->getCanonicalType(); auto RC = getReferenceCountingForType(IGM, type); if (RC == ReferenceCounting::ObjC) kind = FieldDescriptorKind::ObjCClass; else kind = FieldDescriptorKind::Class; } B.addInt16(uint16_t(kind)); B.addInt16(fieldRecordSize); // Imported classes don't need field descriptors if (NTD->hasClangNode() && isa(NTD)) { B.addInt32(0); return; } assert(!NTD->hasClangNode() || isa(NTD)); auto properties = NTD->getStoredProperties(); B.addInt32(std::distance(properties.begin(), properties.end())); for (auto property : properties) addFieldDecl(property, property->getInterfaceType() ->getCanonicalType()); } void layoutEnum() { auto enumDecl = cast(NTD); auto &strategy = irgen::getEnumImplStrategy( IGM, enumDecl->getDeclaredTypeInContext() ->getCanonicalType()); auto kind = FieldDescriptorKind::Enum; // If this is a fixed-size multi-payload enum, we have to emit a descriptor // with the size and alignment of the type, because the reflection library // cannot derive this information at runtime. if (strategy.getElementsWithPayload().size() > 1 && !strategy.needsPayloadSizeInMetadata()) { kind = FieldDescriptorKind::MultiPayloadEnum; IGM.OpaqueTypes.insert(enumDecl); } B.addInt16(uint16_t(kind)); B.addInt16(fieldRecordSize); B.addInt32(strategy.getElementsWithPayload().size() + strategy.getElementsWithNoPayload().size()); for (auto enumCase : strategy.getElementsWithPayload()) { bool indirect = (enumCase.decl->isIndirect() || enumDecl->isIndirect()); addFieldDecl(enumCase.decl, enumCase.decl->getArgumentInterfaceType() ->getCanonicalType(), indirect); } for (auto enumCase : strategy.getElementsWithNoPayload()) { addFieldDecl(enumCase.decl, CanType()); } } void layoutProtocol() { auto protocolDecl = cast(NTD); FieldDescriptorKind Kind; if (protocolDecl->isObjC()) Kind = FieldDescriptorKind::ObjCProtocol; else if (protocolDecl->requiresClass()) Kind = FieldDescriptorKind::ClassProtocol; else Kind = FieldDescriptorKind::Protocol; B.addInt16(uint16_t(Kind)); B.addInt16(fieldRecordSize); B.addInt32(0); } void layout() override { if (NTD->hasClangNode() && !isa(NTD) && !isa(NTD) && !isa(NTD)) return; PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD); addNominalRef(NTD); auto *CD = dyn_cast(NTD); if (CD && CD->getSuperclass()) { addTypeRef(CD->getSuperclass()->getCanonicalType()); } else { B.addInt32(0); } switch (NTD->getKind()) { case DeclKind::Class: case DeclKind::Struct: layoutRecord(); break; case DeclKind::Enum: layoutEnum(); break; case DeclKind::Protocol: layoutProtocol(); break; default: llvm_unreachable("Not a nominal type"); break; } } public: FieldTypeMetadataBuilder(IRGenModule &IGM, const NominalTypeDecl * NTD) : ReflectionMetadataBuilder(IGM), NTD(NTD) {} llvm::GlobalVariable *emit() { auto entity = LinkEntity::forReflectionFieldDescriptor( NTD->getDeclaredType()->getCanonicalType()); auto section = IGM.getFieldTypeMetadataSectionName(); return ReflectionMetadataBuilder::emit(entity, section); } }; class FixedTypeMetadataBuilder : public ReflectionMetadataBuilder { ModuleDecl *module; CanType type; const FixedTypeInfo *ti; public: FixedTypeMetadataBuilder(IRGenModule &IGM, CanType builtinType) : ReflectionMetadataBuilder(IGM) { module = builtinType->getASTContext().TheBuiltinModule; type = builtinType; ti = &cast(IGM.getTypeInfoForUnlowered(builtinType)); } FixedTypeMetadataBuilder(IRGenModule &IGM, const NominalTypeDecl *nominalDecl) : ReflectionMetadataBuilder(IGM) { module = nominalDecl->getParentModule(); type = nominalDecl->getDeclaredType()->getCanonicalType(); ti = &cast(IGM.getTypeInfoForUnlowered( nominalDecl->getDeclaredTypeInContext()->getCanonicalType())); } void layout() override { addTypeRef(type); B.addInt32(ti->getFixedSize().getValue()); B.addInt32(ti->getFixedAlignment().getValue()); B.addInt32(ti->getFixedStride().getValue()); B.addInt32(ti->getFixedExtraInhabitantCount(IGM)); } llvm::GlobalVariable *emit() { auto entity = LinkEntity::forReflectionBuiltinDescriptor(type); auto section = IGM.getBuiltinTypeMetadataSectionName(); return ReflectionMetadataBuilder::emit(entity, section); } }; void IRGenModule::emitBuiltinTypeMetadataRecord(CanType builtinType) { FixedTypeMetadataBuilder builder(*this, builtinType); builder.emit(); } void IRGenModule::emitOpaqueTypeMetadataRecord(const NominalTypeDecl *nominalDecl) { FixedTypeMetadataBuilder builder(*this, nominalDecl); builder.emit(); } bool IRGenModule::shouldEmitOpaqueTypeMetadataRecord( const NominalTypeDecl *nominalDecl) { if (nominalDecl->getAttrs().hasAttribute()) { auto &ti = getTypeInfoForUnlowered(nominalDecl->getDeclaredTypeInContext()); if (isa(ti)) return true; } return false; } /// Builds a constant LLVM struct describing the layout of a fixed-size /// SIL @box. These look like closure contexts, but without any necessary /// bindings or metadata sources, and only a single captured value. class BoxDescriptorBuilder : public ReflectionMetadataBuilder { CanType BoxedType; public: BoxDescriptorBuilder(IRGenModule &IGM, CanType BoxedType) : ReflectionMetadataBuilder(IGM), BoxedType(BoxedType) {} void layout() override { B.addInt32(1); B.addInt32(0); // Number of sources B.addInt32(0); // Number of generic bindings addTypeRef(BoxedType); addBuiltinTypeRefs(BoxedType); } llvm::GlobalVariable *emit() { auto section = IGM.getCaptureDescriptorMetadataSectionName(); return ReflectionMetadataBuilder::emit(None, section); } }; /// Builds a constant LLVM struct describing the layout of a heap closure, /// the types of its captures, and the sources of metadata if any of the /// captures are generic. class CaptureDescriptorBuilder : public ReflectionMetadataBuilder { swift::reflection::MetadataSourceBuilder SourceBuilder; CanSILFunctionType OrigCalleeType; CanSILFunctionType SubstCalleeType; SubstitutionMap Subs; const HeapLayout &Layout; public: CaptureDescriptorBuilder(IRGenModule &IGM, CanSILFunctionType OrigCalleeType, CanSILFunctionType SubstCalleeType, SubstitutionMap Subs, const HeapLayout &Layout) : ReflectionMetadataBuilder(IGM), OrigCalleeType(OrigCalleeType), SubstCalleeType(SubstCalleeType), Subs(Subs), Layout(Layout) {} using MetadataSourceMap = std::vector>; void addMetadataSource(const reflection::MetadataSource *Source) { if (Source == nullptr) { B.addInt32(0); } else { SmallString<16> EncodeBuffer; llvm::raw_svector_ostream OS(EncodeBuffer); MetadataSourceEncoder Encoder(OS); Encoder.visit(Source); auto EncodedSource = IGM.getAddrOfStringForTypeRef(OS.str()); B.addRelativeAddress(EncodedSource); } } /// Give up if we captured an opened existential type. Eventually we /// should figure out how to represent this. static bool hasOpenedExistential(CanSILFunctionType OrigCalleeType, const HeapLayout &Layout) { if (!OrigCalleeType->isPolymorphic() || OrigCalleeType->isPseudogeneric()) return false; auto &Bindings = Layout.getBindings(); for (unsigned i = 0; i < Bindings.size(); ++i) { // Skip protocol requirements (FIXME: for now?) if (Bindings[i].Protocol != nullptr) continue; if (Bindings[i].TypeParameter->hasOpenedExistential()) return true; } auto ElementTypes = Layout.getElementTypes().slice( Layout.hasBindings() ? 1 : 0); for (auto ElementType : ElementTypes) { auto SwiftType = ElementType.getASTType(); if (SwiftType->hasOpenedExistential()) return true; } return false; } /// Slice off the NecessaryBindings struct at the beginning, if it's there. /// We'll keep track of how many things are in the bindings struct with its /// own count in the capture descriptor. ArrayRef getElementTypes() { return Layout.getElementTypes().slice(Layout.hasBindings() ? 1 : 0); } /// Build a map from generic parameter -> source of its metadata at runtime. /// /// If the callee that we are partially applying to create a box/closure /// isn't generic, then the map is empty. MetadataSourceMap getMetadataSourceMap() { MetadataSourceMap SourceMap; // Generic parameters of pseudogeneric functions do not have // runtime metadata. if (!OrigCalleeType->isPolymorphic() || OrigCalleeType->isPseudogeneric()) return SourceMap; // Any generic parameters that are not fulfilled are passed in via the // bindings. Structural types are decomposed, so emit the contents of // the bindings structure directly. auto &Bindings = Layout.getBindings(); for (unsigned i = 0; i < Bindings.size(); ++i) { // Skip protocol requirements (FIXME: for now?) if (Bindings[i].Protocol != nullptr) continue; auto Source = SourceBuilder.createClosureBinding(i); auto BindingType = Bindings[i].TypeParameter; auto InterfaceType = BindingType->mapTypeOutOfContext(); SourceMap.push_back({InterfaceType->getCanonicalType(), Source}); } // Check if any requirements were fulfilled by metadata stored inside a // captured value. enumerateGenericParamFulfillments(IGM, OrigCalleeType, [&](CanType GenericParam, const irgen::MetadataSource &Source, const MetadataPath &Path) { const reflection::MetadataSource *Root; switch (Source.getKind()) { case irgen::MetadataSource::Kind::SelfMetadata: case irgen::MetadataSource::Kind::SelfWitnessTable: // Handled as part of bindings return; case irgen::MetadataSource::Kind::GenericLValueMetadata: // FIXME? return; case irgen::MetadataSource::Kind::ClassPointer: Root = SourceBuilder.createReferenceCapture(Source.getParamIndex()); break; case irgen::MetadataSource::Kind::Metadata: Root = SourceBuilder.createMetadataCapture(Source.getParamIndex()); break; } // The metadata might be reached via a non-trivial path (eg, // dereferencing an isa pointer or a generic argument). Record // the path. We assume captured values map 1-1 with function // parameters. auto Src = Path.getMetadataSource(SourceBuilder, Root); auto SubstType = GenericParam.subst(Subs); auto InterfaceType = SubstType->mapTypeOutOfContext(); SourceMap.push_back({InterfaceType->getCanonicalType(), Src}); }); return SourceMap; } /// Get the interface types of all of the captured values, mapped out of the /// context of the callee we're partially applying. std::vector getCaptureTypes() { std::vector CaptureTypes; for (auto ElementType : getElementTypes()) { auto SwiftType = ElementType.getASTType(); // Erase pseudogeneric captures down to AnyObject. if (OrigCalleeType->isPseudogeneric()) { SwiftType = SwiftType.transform([&](Type t) -> Type { if (auto *archetype = t->getAs()) { assert(archetype->requiresClass() && "don't know what to do"); return IGM.Context.getAnyObjectType(); } return t; })->getCanonicalType(); } auto InterfaceType = SwiftType->mapTypeOutOfContext(); CaptureTypes.push_back(InterfaceType->getCanonicalType()); } return CaptureTypes; } void layout() override { auto CaptureTypes = getCaptureTypes(); auto MetadataSources = getMetadataSourceMap(); B.addInt32(CaptureTypes.size()); B.addInt32(MetadataSources.size()); B.addInt32(Layout.getBindings().size()); // Now add typerefs of all of the captures. for (auto CaptureType : CaptureTypes) { addTypeRef(CaptureType); addBuiltinTypeRefs(CaptureType); } // Add the pairs that make up the generic param -> metadata source map // to the struct. for (auto GenericAndSource : MetadataSources) { auto GenericParam = GenericAndSource.first->getCanonicalType(); auto Source = GenericAndSource.second; addTypeRef(GenericParam); addMetadataSource(Source); } } llvm::GlobalVariable *emit() { auto section = IGM.getCaptureDescriptorMetadataSectionName(); return ReflectionMetadataBuilder::emit(None, section); } }; static std::string getReflectionSectionName(IRGenModule &IGM, StringRef LongName, StringRef FourCC) { SmallString<50> SectionName; llvm::raw_svector_ostream OS(SectionName); switch (IGM.TargetInfo.OutputObjectFormat) { case llvm::Triple::UnknownObjectFormat: llvm_unreachable("unknown object format"); case llvm::Triple::COFF: assert(FourCC.size() <= 4 && "COFF section name length must be <= 8 characters"); OS << ".sw5" << FourCC << "$B"; break; case llvm::Triple::ELF: OS << "swift5_" << LongName; break; case llvm::Triple::MachO: assert(LongName.size() <= 7 && "Mach-O section name length must be <= 16 characters"); OS << "__TEXT,__swift5_" << LongName << ", regular, no_dead_strip"; break; case llvm::Triple::Wasm: llvm_unreachable("web assembly object format is not supported."); break; } return OS.str(); } const char *IRGenModule::getFieldTypeMetadataSectionName() { if (FieldTypeSection.empty()) FieldTypeSection = getReflectionSectionName(*this, "fieldmd", "flmd"); return FieldTypeSection.c_str(); } const char *IRGenModule::getBuiltinTypeMetadataSectionName() { if (BuiltinTypeSection.empty()) BuiltinTypeSection = getReflectionSectionName(*this, "builtin", "bltn"); return BuiltinTypeSection.c_str(); } const char *IRGenModule::getAssociatedTypeMetadataSectionName() { if (AssociatedTypeSection.empty()) AssociatedTypeSection = getReflectionSectionName(*this, "assocty", "asty"); return AssociatedTypeSection.c_str(); } const char *IRGenModule::getCaptureDescriptorMetadataSectionName() { if (CaptureDescriptorSection.empty()) CaptureDescriptorSection = getReflectionSectionName(*this, "capture", "cptr"); return CaptureDescriptorSection.c_str(); } const char *IRGenModule::getReflectionStringsSectionName() { if (ReflectionStringsSection.empty()) ReflectionStringsSection = getReflectionSectionName(*this, "reflstr", "rfst"); return ReflectionStringsSection.c_str(); } const char *IRGenModule::getReflectionTypeRefSectionName() { if (ReflectionTypeRefSection.empty()) ReflectionTypeRefSection = getReflectionSectionName(*this, "typeref", "tyrf"); return ReflectionTypeRefSection.c_str(); } llvm::Constant *IRGenModule::getAddrOfFieldName(StringRef Name) { auto &entry = FieldNames[Name]; if (entry.second) return entry.second; entry = createStringConstant(Name, /*willBeRelativelyAddressed*/ true, getReflectionStringsSectionName()); disableAddressSanitizer(*this, entry.first); return entry.second; } llvm::Constant * IRGenModule::getAddrOfBoxDescriptor(CanType BoxedType) { if (!IRGen.Opts.EnableReflectionMetadata) return llvm::Constant::getNullValue(CaptureDescriptorPtrTy); BoxDescriptorBuilder builder(*this, BoxedType); auto var = builder.emit(); return llvm::ConstantExpr::getBitCast(var, CaptureDescriptorPtrTy); } llvm::Constant * IRGenModule::getAddrOfCaptureDescriptor(SILFunction &Caller, CanSILFunctionType OrigCalleeType, CanSILFunctionType SubstCalleeType, SubstitutionMap Subs, const HeapLayout &Layout) { if (!IRGen.Opts.EnableReflectionMetadata) return llvm::Constant::getNullValue(CaptureDescriptorPtrTy); if (CaptureDescriptorBuilder::hasOpenedExistential(OrigCalleeType, Layout)) return llvm::Constant::getNullValue(CaptureDescriptorPtrTy); CaptureDescriptorBuilder builder(*this, OrigCalleeType, SubstCalleeType, Subs, Layout); auto var = builder.emit(); return llvm::ConstantExpr::getBitCast(var, CaptureDescriptorPtrTy); } void IRGenModule:: emitAssociatedTypeMetadataRecord(const ProtocolConformance *Conformance) { if (!IRGen.Opts.EnableReflectionMetadata) return; SmallVector, 2> AssociatedTypes; auto collectTypeWitness = [&](const AssociatedTypeDecl *AssocTy, Type Replacement, const TypeDecl *TD) -> bool { AssociatedTypes.push_back({ AssocTy->getNameStr(), Replacement->getCanonicalType() }); return false; }; Conformance->forEachTypeWitness(/*resolver*/ nullptr, collectTypeWitness); // If there are no associated types, don't bother emitting any // metadata. if (AssociatedTypes.empty()) return; AssociatedTypeMetadataBuilder builder(*this, Conformance, AssociatedTypes); builder.emit(); } void IRGenModule::emitBuiltinReflectionMetadata() { if (getSwiftModule()->isStdlibModule()) { BuiltinTypes.insert(Context.TheNativeObjectType); BuiltinTypes.insert(Context.TheUnknownObjectType); BuiltinTypes.insert(Context.TheBridgeObjectType); BuiltinTypes.insert(Context.TheRawPointerType); BuiltinTypes.insert(Context.TheUnsafeValueBufferType); // This would not be necessary if RawPointer had the same set of // extra inhabitants as these. But maybe it's best not to codify // that in the ABI anyway. CanType thinFunction = CanFunctionType::get( AnyFunctionType::CanParamArrayRef(), Context.TheEmptyTupleType, AnyFunctionType::ExtInfo().withRepresentation( FunctionTypeRepresentation::Thin)); BuiltinTypes.insert(thinFunction); CanType anyMetatype = CanExistentialMetatypeType::get( Context.TheAnyType); BuiltinTypes.insert(anyMetatype); } for (auto CD : ImportedClasses) emitFieldMetadataRecord(CD); for (auto PD : ImportedProtocols) emitFieldMetadataRecord(PD); for (auto SD : ImportedStructs) emitFieldMetadataRecord(SD); for (auto builtinType : BuiltinTypes) emitBuiltinTypeMetadataRecord(builtinType); for (auto nominalDecl : OpaqueTypes) emitOpaqueTypeMetadataRecord(nominalDecl); } void IRGenerator::emitBuiltinReflectionMetadata() { for (auto &m : *this) { m.second->emitBuiltinReflectionMetadata(); } } void IRGenModule::emitFieldMetadataRecord(const NominalTypeDecl *Decl) { if (!IRGen.Opts.EnableReflectionMetadata) return; // @objc enums never have generic parameters or payloads, // and lower as their raw type. if (auto *ED = dyn_cast(Decl)) if (ED->isObjC()) { emitOpaqueTypeMetadataRecord(ED); return; } FieldTypeMetadataBuilder builder(*this, Decl); FieldDescriptors.push_back(builder.emit()); } void IRGenModule::emitReflectionMetadataVersion() { auto Init = llvm::ConstantInt::get(Int16Ty, SWIFT_REFLECTION_METADATA_VERSION); auto Version = new llvm::GlobalVariable(Module, Int16Ty, /*constant*/ true, llvm::GlobalValue::LinkOnceODRLinkage, Init, "__swift_reflection_version"); Version->setVisibility(llvm::GlobalValue::HiddenVisibility); addUsedGlobal(Version); } void IRGenerator::emitReflectionMetadataVersion() { for (auto &m : *this) { m.second->emitReflectionMetadataVersion(); } }