Skip to content

Commit a1ff1e6

Browse files
committed
Eagerly emit reflection metadata as decls are emitted
Rather than collection nominal type and extension decls and emit reflection metadata records in one go, we can emit them as they are encountered and instead collection builtin types referenced by those at the end.
1 parent 857489c commit a1ff1e6

File tree

10 files changed

+156
-153
lines changed

10 files changed

+156
-153
lines changed

lib/IRGen/GenClass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,7 @@ void IRGenModule::emitClassDecl(ClassDecl *D) {
773773
classTI.getLayout(*this, selfType),
774774
classTI.getClassLayout(*this, selfType));
775775
emitNestedTypeDecls(D->getMembers());
776-
addNominalTypeDecl(D);
776+
emitReflectionMetadata(D);
777777
}
778778

779779
namespace {

lib/IRGen/GenDecl.cpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -849,10 +849,6 @@ void IRGenModule::finishEmitAfterTopLevel() {
849849
finalizeClangCodeGen();
850850
}
851851

852-
void IRGenModule::addNominalTypeDecl(const NominalTypeDecl *Decl) {
853-
NominalTypeDecls.push_back(Decl);
854-
}
855-
856852
static void emitLazyTypeMetadata(IRGenModule &IGM, CanType type) {
857853
auto decl = type.getAnyNominal();
858854
assert(decl);
@@ -880,13 +876,6 @@ void IRGenerator::emitTypeMetadataRecords() {
880876
}
881877
}
882878

883-
void IRGenerator::emitReflectionMetadataRecords() {
884-
for (auto &m : *this) {
885-
m.second->emitReflectionMetadataRecords();
886-
}
887-
}
888-
889-
890879
/// Emit any lazy definitions (of globals or functions or whatever
891880
/// else) that we require.
892881
void IRGenerator::emitLazyDefinitions() {
@@ -2766,8 +2755,7 @@ static bool shouldEmitCategory(IRGenModule &IGM, ExtensionDecl *ext) {
27662755
}
27672756

27682757
void IRGenModule::emitExtension(ExtensionDecl *ext) {
2769-
ExtensionDecls.push_back(ext);
2770-
2758+
emitAssociatedTypeMetadataRecord(ext);
27712759
emitNestedTypeDecls(ext->getMembers());
27722760

27732761
// Generate a category if the extension either introduces a

lib/IRGen/GenEnum.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5514,7 +5514,7 @@ const TypeInfo *TypeConverter::convertEnumType(TypeBase *key, CanType type,
55145514
void IRGenModule::emitEnumDecl(EnumDecl *theEnum) {
55155515
emitEnumMetadata(*this, theEnum);
55165516
emitNestedTypeDecls(theEnum->getMembers());
5517-
addNominalTypeDecl(theEnum);
5517+
emitReflectionMetadata(theEnum);
55185518
}
55195519

55205520
void irgen::emitSwitchAddressOnlyEnumDispatch(IRGenFunction &IGF,

lib/IRGen/GenMeta.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5675,7 +5675,7 @@ void IRGenModule::emitProtocolDecl(ProtocolDecl *protocol) {
56755675
var->setConstant(true);
56765676
var->setInitializer(init);
56775677

5678-
addNominalTypeDecl(protocol);
5678+
emitReflectionMetadata(protocol);
56795679
}
56805680

56815681
/// \brief Load a reference to the protocol descriptor for the given protocol.

lib/IRGen/GenReflection.cpp

Lines changed: 124 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,9 @@ class ReflectionMetadataBuilder : public ConstantBuilder<> {
207207

208208
class AssociatedTypeMetadataBuilder : public ReflectionMetadataBuilder {
209209
static const uint32_t AssociatedTypeRecordSize = 8;
210-
ArrayRef<const NominalTypeDecl *> NominalTypeDecls;
211-
ArrayRef<const ExtensionDecl *> ExtensionDecls;
210+
211+
llvm::PointerUnion<const NominalTypeDecl *, const ExtensionDecl *>
212+
NominalOrExtensionDecl;
212213

213214
void addConformance(Module *ModuleContext,
214215
CanType ConformingType,
@@ -247,19 +248,26 @@ class AssociatedTypeMetadataBuilder : public ReflectionMetadataBuilder {
247248
}
248249
}
249250

251+
const NominalTypeDecl *getNominalTypeDecl() const {
252+
return NominalOrExtensionDecl.dyn_cast<const NominalTypeDecl *>();
253+
}
254+
255+
const ExtensionDecl *getExtensionDecl() const {
256+
return NominalOrExtensionDecl.dyn_cast<const ExtensionDecl *>();
257+
}
258+
250259
void layout() {
251-
for (auto Decl : NominalTypeDecls) {
252-
PrettyStackTraceDecl DebugStack("emitting associated type metadata", Decl);
260+
if (auto Decl = getNominalTypeDecl()) {
261+
PrettyStackTraceDecl DebugStack("emitting associated type metadata",
262+
Decl);
253263
for (auto Conformance : Decl->getAllConformances()) {
254264
if (Conformance->isIncomplete())
255265
continue;
256266
addConformance(Decl->getModuleContext(),
257267
Decl->getDeclaredType()->getCanonicalType(),
258268
Conformance);
259269
}
260-
}
261-
262-
for (auto Ext : ExtensionDecls) {
270+
} else if (auto Ext = getExtensionDecl()) {
263271
PrettyStackTraceDecl DebugStack("emitting associated type metadata", Ext);
264272
for (auto Conformance : Ext->getLocalConformances()) {
265273
auto Decl = Ext->getExtendedType()->getNominalOrBoundGenericNominal();
@@ -271,13 +279,16 @@ class AssociatedTypeMetadataBuilder : public ReflectionMetadataBuilder {
271279
}
272280

273281
public:
274-
AssociatedTypeMetadataBuilder(IRGenModule &IGM,
275-
ArrayRef<const NominalTypeDecl *> NominalTypeDecls,
276-
ArrayRef<const ExtensionDecl *> ExtensionDecls,
277-
llvm::SetVector<CanType> &BuiltinTypes)
282+
AssociatedTypeMetadataBuilder(IRGenModule &IGM, const NominalTypeDecl *Decl,
283+
llvm::SetVector<CanType> &BuiltinTypes)
278284
: ReflectionMetadataBuilder(IGM, BuiltinTypes),
279-
NominalTypeDecls(NominalTypeDecls),
280-
ExtensionDecls(ExtensionDecls) {}
285+
NominalOrExtensionDecl(Decl) {}
286+
287+
AssociatedTypeMetadataBuilder(IRGenModule &IGM, const ExtensionDecl *Decl,
288+
llvm::SetVector<CanType> &BuiltinTypes)
289+
: ReflectionMetadataBuilder(IGM, BuiltinTypes),
290+
NominalOrExtensionDecl(Decl) {}
291+
281292

282293
llvm::GlobalVariable *emit() {
283294
auto tempBase = std::unique_ptr<llvm::GlobalVariable>(
@@ -307,7 +318,7 @@ class AssociatedTypeMetadataBuilder : public ReflectionMetadataBuilder {
307318

308319
class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
309320
const uint32_t fieldRecordSize = 12;
310-
ArrayRef<const NominalTypeDecl *> NominalTypeDecls;
321+
const NominalTypeDecl *NTD;
311322

312323
void addFieldDecl(const ValueDecl *value, CanType type) {
313324
reflection::FieldRecordFlags Flags;
@@ -330,77 +341,71 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
330341
}
331342
}
332343

333-
void addDecl(const NominalTypeDecl *decl) {
344+
void layout() {
334345
using swift::reflection::FieldDescriptorKind;
335346

336-
PrettyStackTraceDecl DebugStack("emitting field type metadata", decl);
337-
auto type = decl->getDeclaredType()->getCanonicalType();
338-
addTypeRef(decl->getModuleContext(), type);
339-
340-
switch (decl->getKind()) {
341-
case DeclKind::Class:
342-
case DeclKind::Struct: {
343-
auto properties = decl->getStoredProperties();
344-
addConstantInt16(uint16_t(isa<StructDecl>(decl)
345-
? FieldDescriptorKind::Struct
346-
: FieldDescriptorKind::Class));
347-
addConstantInt16(fieldRecordSize);
348-
addConstantInt32(std::distance(properties.begin(), properties.end()));
349-
for (auto property : properties)
350-
addFieldDecl(property,
351-
property->getInterfaceType()
347+
PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD);
348+
auto type = NTD->getDeclaredType()->getCanonicalType();
349+
addTypeRef(NTD->getModuleContext(), type);
350+
351+
switch (NTD->getKind()) {
352+
case DeclKind::Class:
353+
case DeclKind::Struct: {
354+
auto properties = NTD->getStoredProperties();
355+
addConstantInt16(uint16_t(isa<StructDecl>(NTD)
356+
? FieldDescriptorKind::Struct
357+
: FieldDescriptorKind::Class));
358+
addConstantInt16(fieldRecordSize);
359+
addConstantInt32(std::distance(properties.begin(), properties.end()));
360+
for (auto property : properties)
361+
addFieldDecl(property,
362+
property->getInterfaceType()
352363
->getCanonicalType());
353-
break;
354-
}
355-
case DeclKind::Enum: {
356-
auto enumDecl = cast<EnumDecl>(decl);
357-
auto cases = enumDecl->getAllElements();
358-
addConstantInt16(uint16_t(FieldDescriptorKind::Enum));
359-
addConstantInt16(fieldRecordSize);
360-
addConstantInt32(std::distance(cases.begin(), cases.end()));
361-
for (auto enumCase : cases) {
362-
if (enumCase->hasArgumentType()) {
363-
addFieldDecl(enumCase,
364-
enumCase->getArgumentInterfaceType()
364+
break;
365+
}
366+
case DeclKind::Enum: {
367+
auto enumDecl = cast<EnumDecl>(NTD);
368+
auto cases = enumDecl->getAllElements();
369+
addConstantInt16(uint16_t(FieldDescriptorKind::Enum));
370+
addConstantInt16(fieldRecordSize);
371+
addConstantInt32(std::distance(cases.begin(), cases.end()));
372+
for (auto enumCase : cases) {
373+
if (enumCase->hasArgumentType()) {
374+
addFieldDecl(enumCase,
375+
enumCase->getArgumentInterfaceType()
365376
->getCanonicalType());
366-
} else {
367-
addFieldDecl(enumCase, CanType());
377+
} else {
378+
addFieldDecl(enumCase, CanType());
379+
}
368380
}
381+
break;
369382
}
370-
break;
371-
}
372-
case DeclKind::Protocol: {
373-
auto protocolDecl = cast<ProtocolDecl>(decl);
374-
FieldDescriptorKind Kind;
375-
if (protocolDecl->isObjC())
376-
Kind = FieldDescriptorKind::ObjCProtocol;
377-
else if (protocolDecl->requiresClass())
378-
Kind = FieldDescriptorKind::ClassProtocol;
379-
else
380-
Kind = FieldDescriptorKind::Protocol;
381-
addConstantInt16(uint16_t(Kind));
382-
addConstantInt16(fieldRecordSize);
383-
addConstantInt32(0);
384-
break;
385-
}
386-
default:
387-
llvm_unreachable("Not a nominal type");
388-
break;
389-
}
390-
}
391-
392-
void layout() {
393-
for (auto decl : NominalTypeDecls) {
394-
addDecl(decl);
383+
case DeclKind::Protocol: {
384+
auto protocolDecl = cast<ProtocolDecl>(NTD);
385+
FieldDescriptorKind Kind;
386+
if (protocolDecl->isObjC())
387+
Kind = FieldDescriptorKind::ObjCProtocol;
388+
else if (protocolDecl->requiresClass())
389+
Kind = FieldDescriptorKind::ClassProtocol;
390+
else
391+
Kind = FieldDescriptorKind::Protocol;
392+
addConstantInt16(uint16_t(Kind));
393+
addConstantInt16(fieldRecordSize);
394+
addConstantInt32(0);
395+
break;
396+
}
397+
default:
398+
llvm_unreachable("Not a nominal type");
399+
break;
395400
}
396401
}
397402

398403
public:
399404
FieldTypeMetadataBuilder(IRGenModule &IGM,
400-
ArrayRef<const NominalTypeDecl *> NominalTypeDecls,
405+
const NominalTypeDecl * NTD,
401406
llvm::SetVector<CanType> &BuiltinTypes)
402407
: ReflectionMetadataBuilder(IGM, BuiltinTypes),
403-
NominalTypeDecls(NominalTypeDecls) {}
408+
NTD(NTD) {}
404409

405410
llvm::GlobalVariable *emit() {
406411

@@ -776,46 +781,58 @@ llvm::Constant *IRGenModule::getAddrOfCaptureDescriptor(SILFunction &SILFn,
776781
return llvm::ConstantExpr::getBitCast(var, CaptureDescriptorPtrTy);
777782
}
778783

779-
void IRGenModule::emitReflectionMetadataRecords() {
780-
auto DoNotHaveDecls = NominalTypeDecls.empty() && ExtensionDecls.empty();
781-
if (!IRGen.Opts.EnableReflectionMetadata ||
782-
(!IRGen.Opts.EnableReflectionBuiltins && DoNotHaveDecls))
784+
void IRGenModule::emitReflectionMetadata(const NominalTypeDecl *Decl) {
785+
if (!IRGen.Opts.EnableReflectionMetadata)
783786
return;
784787

785-
// We collect all referenced builtin types and emit records for them.
786-
// In practice only the standard library should directly reference
787-
// builtin types.
788-
//
789-
// FIXME: This metadata should be in the runtime instead.
790788
llvm::SetVector<CanType> BuiltinTypes;
791789

792-
{
793-
FieldTypeMetadataBuilder builder(*this, NominalTypeDecls, BuiltinTypes);
794-
auto var = builder.emit();
795-
if (var)
796-
addUsedGlobal(var);
797-
}
790+
emitFieldMetadataRecord(Decl);
791+
emitAssociatedTypeMetadataRecord(Decl);
792+
}
798793

799-
{
800-
AssociatedTypeMetadataBuilder builder(*this,
801-
NominalTypeDecls,
802-
ExtensionDecls,
803-
BuiltinTypes);
804-
auto var = builder.emit();
805-
if (var)
806-
addUsedGlobal(var);
807-
}
794+
void IRGenModule::emitAssociatedTypeMetadataRecord(const NominalTypeDecl *Decl){
795+
if (!IRGen.Opts.EnableReflectionMetadata)
796+
return;
797+
798+
AssociatedTypeMetadataBuilder builder(*this, Decl, BuiltinTypes);
799+
auto var = builder.emit();
800+
if (var)
801+
addUsedGlobal(var);
802+
}
808803

809-
if (IRGen.Opts.EnableReflectionBuiltins) {
810-
BuiltinTypes.insert(Context.TheNativeObjectType);
811-
BuiltinTypes.insert(Context.TheUnknownObjectType);
812-
BuiltinTypes.insert(Context.TheBridgeObjectType);
813-
BuiltinTypes.insert(Context.TheRawPointerType);
814-
BuiltinTypes.insert(Context.TheUnsafeValueBufferType);
804+
void IRGenModule::emitAssociatedTypeMetadataRecord(const ExtensionDecl *Ext) {
805+
if (!IRGen.Opts.EnableReflectionMetadata)
806+
return;
815807

816-
BuiltinTypeMetadataBuilder builder(*this, BuiltinTypes);
817-
auto var = builder.emit();
818-
if (var)
819-
addUsedGlobal(var);
820-
}
808+
AssociatedTypeMetadataBuilder builder(*this, Ext, BuiltinTypes);
809+
auto var = builder.emit();
810+
if (var)
811+
addUsedGlobal(var);
812+
}
813+
814+
void IRGenModule::emitBuiltinReflectionMetadata() {
815+
if (!IRGen.Opts.EnableReflectionBuiltins)
816+
return;
817+
818+
BuiltinTypes.insert(Context.TheNativeObjectType);
819+
BuiltinTypes.insert(Context.TheUnknownObjectType);
820+
BuiltinTypes.insert(Context.TheBridgeObjectType);
821+
BuiltinTypes.insert(Context.TheRawPointerType);
822+
BuiltinTypes.insert(Context.TheUnsafeValueBufferType);
823+
824+
BuiltinTypeMetadataBuilder builder(*this, BuiltinTypes);
825+
auto var = builder.emit();
826+
if (var)
827+
addUsedGlobal(var);
828+
}
829+
830+
void IRGenModule::emitFieldMetadataRecord(const NominalTypeDecl *Decl) {
831+
if (!IRGen.Opts.EnableReflectionMetadata)
832+
return;
833+
834+
FieldTypeMetadataBuilder builder(*this, Decl, BuiltinTypes);
835+
auto var = builder.emit();
836+
if (var)
837+
addUsedGlobal(var);
821838
}

lib/IRGen/GenStruct.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ irgen::getPhysicalStructMemberAccessStrategy(IRGenModule &IGM,
811811
void IRGenModule::emitStructDecl(StructDecl *st) {
812812
emitStructMetadata(*this, st);
813813
emitNestedTypeDecls(st->getMembers());
814-
addNominalTypeDecl(st);
814+
emitReflectionMetadata(st);
815815
}
816816

817817
namespace {

lib/IRGen/IRGen.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ static std::unique_ptr<llvm::Module> performIRGeneration(IRGenOptions &Opts,
586586
// In JIT mode these are manually registered above.
587587
IGM.emitProtocolConformances();
588588
IGM.emitTypeMetadataRecords();
589-
IGM.emitReflectionMetadataRecords();
589+
IGM.emitBuiltinReflectionMetadata();
590590
}
591591

592592
// Okay, emit any definitions that we suddenly need.
@@ -739,7 +739,6 @@ static void performParallelIRGeneration(IRGenOptions &Opts,
739739
IRGenModule *PrimaryGM = irgen.getPrimaryIGM();
740740

741741
irgen.emitProtocolConformances();
742-
irgen.emitReflectionMetadataRecords();
743742

744743
// Okay, emit any definitions that we suddenly need.
745744
irgen.emitLazyDefinitions();

0 commit comments

Comments
 (0)