static Type findBaseTypeForReplacingArchetype(const ValueDecl *VD, const Type Ty) { if (Ty.isNull()) return Type(); // Find the nominal type decl related to VD. auto TC = VD->getDeclContext()->getInnermostTypeContext(); NominalTypeDecl *NTD = dyn_cast_or_null<NominalTypeDecl>(TC); if (!NTD) { ExtensionDecl *ED = dyn_cast_or_null<ExtensionDecl>(TC); if (ED) { if (auto T = ED->getExtendedType()) NTD = T->getAnyNominal(); } } if (!NTD) return Type(); Type Result; // Walk the type tree to find the a sub-type who's convertible to the // found nominal. Ty.visit([&](Type T) { if (!Result && (T->getAnyNominal() == NTD || isConvertibleTo(T, NTD->getDeclaredType(), VD->getDeclContext()))) { Result = T; } }); return Result; }
void layout() override { PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD); auto type = NTD->getDeclaredType()->getCanonicalType(); addTypeRef(NTD->getModuleContext(), type); if (NTD->hasClangNode() && !isa<ClassDecl>(NTD) && !isa<ProtocolDecl>(NTD)) return; 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; } }
void layout() { using swift::reflection::FieldDescriptorKind; PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD); auto type = NTD->getDeclaredType()->getCanonicalType(); addTypeRef(NTD->getModuleContext(), type); switch (NTD->getKind()) { case DeclKind::Class: case DeclKind::Struct: { auto properties = NTD->getStoredProperties(); addConstantInt16(uint16_t(isa<StructDecl>(NTD) ? FieldDescriptorKind::Struct : FieldDescriptorKind::Class)); addConstantInt16(fieldRecordSize); addConstantInt32(std::distance(properties.begin(), properties.end())); for (auto property : properties) addFieldDecl(property, property->getInterfaceType() ->getCanonicalType()); break; } case DeclKind::Enum: { auto enumDecl = cast<EnumDecl>(NTD); auto cases = enumDecl->getAllElements(); addConstantInt16(uint16_t(FieldDescriptorKind::Enum)); addConstantInt16(fieldRecordSize); addConstantInt32(std::distance(cases.begin(), cases.end())); for (auto enumCase : cases) { if (enumCase->hasArgumentType()) { addFieldDecl(enumCase, enumCase->getArgumentInterfaceType() ->getCanonicalType()); } else { addFieldDecl(enumCase, CanType()); } } break; } case DeclKind::Protocol: { auto protocolDecl = cast<ProtocolDecl>(NTD); FieldDescriptorKind Kind; if (protocolDecl->isObjC()) Kind = FieldDescriptorKind::ObjCProtocol; else if (protocolDecl->requiresClass()) Kind = FieldDescriptorKind::ClassProtocol; else Kind = FieldDescriptorKind::Protocol; addConstantInt16(uint16_t(Kind)); addConstantInt16(fieldRecordSize); addConstantInt32(0); break; } default: llvm_unreachable("Not a nominal type"); break; } }
static Type findBaseTypeForReplacingArchetype(const ValueDecl *VD, const Type Ty) { if (Ty.isNull()) return Type(); // Find the nominal type decl related to VD. NominalTypeDecl *NTD = VD->getDeclContext()-> getAsNominalTypeOrNominalTypeExtensionContext(); if (!NTD) return Type(); Type Result; // Walk the type tree to find the a sub-type who's convertible to the // found nominal. Ty.visit([&](Type T) { if (!Result && (T->getAnyNominal() == NTD || isConvertibleTo(T, NTD->getDeclaredType(), VD->getDeclContext()))) { Result = T; } }); return Result; }
void layout() { using swift::reflection::FieldDescriptorKind; PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD); auto type = NTD->getDeclaredType()->getCanonicalType(); addTypeRef(NTD->getModuleContext(), type); if (NTD->hasClangNode() && !isa<ClassDecl>(NTD) && !isa<ProtocolDecl>(NTD)) return; switch (NTD->getKind()) { case DeclKind::Class: case DeclKind::Struct: { auto kind = FieldDescriptorKind::Struct; if (auto CD = dyn_cast<ClassDecl>(NTD)) { auto RC = getReferenceCountingForClass(IGM, const_cast<ClassDecl *>(CD)); if (RC == ReferenceCounting::ObjC) kind = FieldDescriptorKind::ObjCClass; else kind = FieldDescriptorKind::Class; } addConstantInt16(uint16_t(kind)); addConstantInt16(fieldRecordSize); // Imported classes don't need field descriptors if (NTD->hasClangNode()) { assert(isa<ClassDecl>(NTD)); addConstantInt32(0); break; } auto properties = NTD->getStoredProperties(); addConstantInt32(std::distance(properties.begin(), properties.end())); for (auto property : properties) addFieldDecl(property, property->getInterfaceType() ->getCanonicalType()); break; } case DeclKind::Enum: { auto enumDecl = cast<EnumDecl>(NTD); auto cases = enumDecl->getAllElements(); addConstantInt16(uint16_t(FieldDescriptorKind::Enum)); addConstantInt16(fieldRecordSize); addConstantInt32(std::distance(cases.begin(), cases.end())); for (auto enumCase : cases) { if (enumCase->hasArgumentType()) { addFieldDecl(enumCase, enumCase->getArgumentInterfaceType() ->getCanonicalType()); } else { addFieldDecl(enumCase, CanType()); } } break; } case DeclKind::Protocol: { auto protocolDecl = cast<ProtocolDecl>(NTD); FieldDescriptorKind Kind; if (protocolDecl->isObjC()) Kind = FieldDescriptorKind::ObjCProtocol; else if (protocolDecl->requiresClass()) Kind = FieldDescriptorKind::ClassProtocol; else Kind = FieldDescriptorKind::Protocol; addConstantInt16(uint16_t(Kind)); addConstantInt16(fieldRecordSize); addConstantInt32(0); break; } default: llvm_unreachable("Not a nominal type"); break; } }
llvm::GlobalVariable *emit() { auto entity = LinkEntity::forReflectionFieldDescriptor( NTD->getDeclaredType()->getCanonicalType()); auto section = IGM.getFieldTypeMetadataSectionName(); return ReflectionMetadataBuilder::emit(entity, section); }