Skip to content

Commit 9e2e090

Browse files
committed
[IRGen] Emit metadata accessors last.
Metadata accessors are dependent on prespecializations of the metadata of generic, in-module types. Those prespecializations are themselves dependent on usages of the types in functions. Consequently, the accessors must be emitted after all the functions are emitted.
1 parent c4d13e4 commit 9e2e090

File tree

7 files changed

+153
-71
lines changed

7 files changed

+153
-71
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,12 @@ void IRGenerator::emitLazyDefinitions() {
11921192
}
11931193
}
11941194

1195+
while (!LazyMetadataAccessors.empty()) {
1196+
NominalTypeDecl *nominal = LazyMetadataAccessors.pop_back_val();
1197+
CurrentIGMPtr IGM = getGenModule(nominal->getDeclContext());
1198+
emitLazyMetadataAccessor(*IGM.get(), nominal);
1199+
}
1200+
11951201
FinishedEmittingLazyDefinitions = true;
11961202
}
11971203

lib/IRGen/GenMeta.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include "GenPoly.h"
5555
#include "GenStruct.h"
5656
#include "GenValueWitness.h"
57+
#include "GenericArguments.h"
5758
#include "HeapTypeInfo.h"
5859
#include "IRGenDebugInfo.h"
5960
#include "IRGenMangler.h"
@@ -1835,6 +1836,29 @@ void irgen::emitLazyTypeMetadata(IRGenModule &IGM, NominalTypeDecl *type) {
18351836
}
18361837
}
18371838

1839+
void irgen::emitLazyMetadataAccessor(IRGenModule &IGM,
1840+
NominalTypeDecl *nominal) {
1841+
GenericArguments genericArgs;
1842+
genericArgs.collectTypes(IGM, nominal);
1843+
1844+
llvm::Function *accessor = IGM.getAddrOfGenericTypeMetadataAccessFunction(
1845+
nominal, genericArgs.Types, ForDefinition);
1846+
1847+
if (IGM.getOptions().optimizeForSize())
1848+
accessor->addFnAttr(llvm::Attribute::NoInline);
1849+
1850+
bool isReadNone = (genericArgs.Types.size() <=
1851+
NumDirectGenericTypeMetadataAccessFunctionArgs);
1852+
1853+
emitCacheAccessFunction(
1854+
IGM, accessor, /*cache*/ nullptr, CacheStrategy::None,
1855+
[&](IRGenFunction &IGF, Explosion &params) {
1856+
return emitGenericTypeMetadataAccessFunction(IGF, params, nominal,
1857+
genericArgs);
1858+
},
1859+
isReadNone);
1860+
}
1861+
18381862
void irgen::emitLazySpecializedGenericTypeMetadata(IRGenModule &IGM,
18391863
CanType type) {
18401864
emitSpecializedGenericStructMetadata(IGM, type);

lib/IRGen/GenMeta.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ namespace irgen {
7171
/// generated definitions.
7272
void emitLazyTypeMetadata(IRGenModule &IGM, NominalTypeDecl *type);
7373

74+
/// Emit the type metadata accessor for a type for which it might be used.
75+
void emitLazyMetadataAccessor(IRGenModule &IGM, NominalTypeDecl *type);
76+
7477
void emitLazySpecializedGenericTypeMetadata(IRGenModule &IGM, CanType type);
7578

7679
/// Emit metadata for a foreign struct, enum or class.

lib/IRGen/GenericArguments.h

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
//===--- MetadataRequest.cpp - IR generation for metadata requests --------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file implements IR generation for accessing metadata.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_IRGEN_GENERICARGUMENTS_H
18+
#define SWIFT_IRGEN_GENERICARGUMENTS_H
19+
20+
#include "Explosion.h"
21+
#include "FixedTypeInfo.h"
22+
#include "GenArchetype.h"
23+
#include "GenClass.h"
24+
#include "GenMeta.h"
25+
#include "GenProto.h"
26+
#include "GenType.h"
27+
#include "GenericRequirement.h"
28+
#include "IRGenDebugInfo.h"
29+
#include "IRGenFunction.h"
30+
#include "IRGenMangler.h"
31+
#include "IRGenModule.h"
32+
#include "swift/AST/ASTContext.h"
33+
#include "swift/AST/ExistentialLayout.h"
34+
#include "swift/AST/GenericEnvironment.h"
35+
#include "swift/AST/IRGenOptions.h"
36+
#include "swift/AST/SubstitutionMap.h"
37+
#include "swift/ClangImporter/ClangModule.h"
38+
#include "swift/IRGen/Linking.h"
39+
#include "llvm/ADT/STLExtras.h"
40+
41+
namespace swift {
42+
namespace irgen {
43+
44+
/// A structure for collecting generic arguments for emitting a
45+
/// nominal metadata reference. The structure produced here is
46+
/// consumed by swift_getGenericMetadata() and must correspond to
47+
/// the fill operations that the compiler emits for the bound decl.
48+
struct GenericArguments {
49+
/// The values to use to initialize the arguments structure.
50+
SmallVector<llvm::Value *, 8> Values;
51+
SmallVector<llvm::Type *, 8> Types;
52+
53+
static unsigned getNumGenericArguments(IRGenModule &IGM,
54+
NominalTypeDecl *nominal) {
55+
GenericTypeRequirements requirements(IGM, nominal);
56+
return requirements.getNumTypeRequirements();
57+
}
58+
59+
void collectTypes(IRGenModule &IGM, NominalTypeDecl *nominal) {
60+
GenericTypeRequirements requirements(IGM, nominal);
61+
collectTypes(IGM, requirements);
62+
}
63+
64+
void collectTypes(IRGenModule &IGM,
65+
const GenericTypeRequirements &requirements) {
66+
for (auto &requirement : requirements.getRequirements()) {
67+
if (requirement.Protocol) {
68+
Types.push_back(IGM.WitnessTablePtrTy);
69+
} else {
70+
Types.push_back(IGM.TypeMetadataPtrTy);
71+
}
72+
}
73+
}
74+
75+
void collect(IRGenFunction &IGF, CanType type) {
76+
auto *decl = type.getNominalOrBoundGenericNominal();
77+
GenericTypeRequirements requirements(IGF.IGM, decl);
78+
79+
auto subs = type->getContextSubstitutionMap(IGF.IGM.getSwiftModule(), decl);
80+
requirements.enumerateFulfillments(
81+
IGF.IGM, subs,
82+
[&](unsigned reqtIndex, CanType type, ProtocolConformanceRef conf) {
83+
if (conf) {
84+
Values.push_back(emitWitnessTableRef(IGF, type, conf));
85+
} else {
86+
Values.push_back(IGF.emitAbstractTypeMetadataRef(type));
87+
}
88+
});
89+
90+
collectTypes(IGF.IGM, decl);
91+
assert(Types.size() == Values.size());
92+
}
93+
};
94+
95+
} // namespace irgen
96+
} // namespace swift
97+
98+
#endif

lib/IRGen/IRGenModule.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,12 @@ class IRGenerator {
253253
/// emit.
254254
llvm::SmallVector<CanType, 4> LazySpecializedTypeMetadataRecords;
255255

256+
/// The queue of metadata accessors to emit.
257+
///
258+
/// The accessors must be emitted after everything else which might result in
259+
/// a statically-known-canonical prespecialization.
260+
llvm::SmallSetVector<NominalTypeDecl *, 4> LazyMetadataAccessors;
261+
256262
struct LazyOpaqueInfo {
257263
bool IsDescriptorUsed = false;
258264
bool IsDescriptorEmitted = false;
@@ -388,6 +394,12 @@ class IRGenerator {
388394
return SpecializationsForGenericTypes.lookup(type);
389395
}
390396

397+
void noteUseOfMetadataAccessor(NominalTypeDecl *decl) {
398+
if (LazyMetadataAccessors.count(decl) == 0) {
399+
LazyMetadataAccessors.insert(decl);
400+
}
401+
}
402+
391403
void noteUseOfTypeMetadata(NominalTypeDecl *type) {
392404
noteUseOfTypeGlobals(type, true, RequireMetadata);
393405
}

lib/IRGen/MetadataRequest.cpp

Lines changed: 5 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "GenMeta.h"
2525
#include "GenProto.h"
2626
#include "GenType.h"
27+
#include "GenericArguments.h"
2728
#include "GenericRequirement.h"
2829
#include "IRGenDebugInfo.h"
2930
#include "IRGenFunction.h"
@@ -438,60 +439,6 @@ static llvm::Value *emitObjCMetadataRef(IRGenFunction &IGF,
438439
return emitObjCMetadataRefForMetadata(IGF, classPtr);
439440
}
440441

441-
namespace {
442-
/// A structure for collecting generic arguments for emitting a
443-
/// nominal metadata reference. The structure produced here is
444-
/// consumed by swift_getGenericMetadata() and must correspond to
445-
/// the fill operations that the compiler emits for the bound decl.
446-
struct GenericArguments {
447-
/// The values to use to initialize the arguments structure.
448-
SmallVector<llvm::Value *, 8> Values;
449-
SmallVector<llvm::Type *, 8> Types;
450-
451-
static unsigned getNumGenericArguments(IRGenModule &IGM,
452-
NominalTypeDecl *nominal) {
453-
GenericTypeRequirements requirements(IGM, nominal);
454-
return requirements.getNumTypeRequirements();
455-
}
456-
457-
void collectTypes(IRGenModule &IGM, NominalTypeDecl *nominal) {
458-
GenericTypeRequirements requirements(IGM, nominal);
459-
collectTypes(IGM, requirements);
460-
}
461-
462-
void collectTypes(IRGenModule &IGM,
463-
const GenericTypeRequirements &requirements) {
464-
for (auto &requirement : requirements.getRequirements()) {
465-
if (requirement.Protocol) {
466-
Types.push_back(IGM.WitnessTablePtrTy);
467-
} else {
468-
Types.push_back(IGM.TypeMetadataPtrTy);
469-
}
470-
}
471-
}
472-
473-
void collect(IRGenFunction &IGF, CanType type) {
474-
auto *decl = type.getNominalOrBoundGenericNominal();
475-
GenericTypeRequirements requirements(IGF.IGM, decl);
476-
477-
auto subs =
478-
type->getContextSubstitutionMap(IGF.IGM.getSwiftModule(), decl);
479-
requirements.enumerateFulfillments(
480-
IGF.IGM, subs,
481-
[&](unsigned reqtIndex, CanType type, ProtocolConformanceRef conf) {
482-
if (conf) {
483-
Values.push_back(emitWitnessTableRef(IGF, type, conf));
484-
} else {
485-
Values.push_back(IGF.emitAbstractTypeMetadataRef(type));
486-
}
487-
});
488-
489-
collectTypes(IGF.IGM, decl);
490-
assert(Types.size() == Values.size());
491-
}
492-
};
493-
} // end anonymous namespace
494-
495442
static bool isTypeErasedGenericClass(NominalTypeDecl *ntd) {
496443
// ObjC classes are type erased.
497444
// TODO: Unless they have magic methods...
@@ -1857,11 +1804,9 @@ static void emitCanonicalSpecializationsForGenericTypeMetadataAccessFunction(
18571804
}
18581805
}
18591806

1860-
static MetadataResponse
1861-
emitGenericTypeMetadataAccessFunction(IRGenFunction &IGF,
1862-
Explosion &params,
1863-
NominalTypeDecl *nominal,
1864-
GenericArguments &genericArgs) {
1807+
MetadataResponse irgen::emitGenericTypeMetadataAccessFunction(
1808+
IRGenFunction &IGF, Explosion &params, NominalTypeDecl *nominal,
1809+
GenericArguments &genericArgs) {
18651810
auto &IGM = IGF.IGM;
18661811

18671812
llvm::Constant *descriptor =
@@ -2181,18 +2126,7 @@ irgen::getGenericTypeMetadataAccessFunction(IRGenModule &IGM,
21812126
if (!shouldDefine || !accessor->empty())
21822127
return accessor;
21832128

2184-
if (IGM.getOptions().optimizeForSize())
2185-
accessor->addFnAttr(llvm::Attribute::NoInline);
2186-
2187-
bool isReadNone =
2188-
(genericArgs.Types.size() <= NumDirectGenericTypeMetadataAccessFunctionArgs);
2189-
2190-
emitCacheAccessFunction(IGM, accessor, /*cache*/nullptr, CacheStrategy::None,
2191-
[&](IRGenFunction &IGF, Explosion &params) {
2192-
return emitGenericTypeMetadataAccessFunction(
2193-
IGF, params, nominal, genericArgs);
2194-
},
2195-
isReadNone);
2129+
IGM.IRGen.noteUseOfMetadataAccessor(nominal);
21962130

21972131
return accessor;
21982132
}

lib/IRGen/MetadataRequest.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ enum ForDefinition_t : bool;
3434
namespace irgen {
3535
class ConstantReference;
3636
class Explosion;
37+
struct GenericArguments;
3738
class IRGenFunction;
3839
class IRGenModule;
3940
class MetadataDependencyCollector;
@@ -587,6 +588,10 @@ void emitCacheAccessFunction(IRGenModule &IGM,
587588
CacheStrategy cacheStrategy,
588589
CacheEmitter getValue,
589590
bool isReadNone = true);
591+
MetadataResponse
592+
emitGenericTypeMetadataAccessFunction(IRGenFunction &IGF, Explosion &params,
593+
NominalTypeDecl *nominal,
594+
GenericArguments &genericArgs);
590595

591596
/// Emit a declaration reference to a metatype object.
592597
void emitMetatypeRef(IRGenFunction &IGF, CanMetatypeType type,

0 commit comments

Comments
 (0)