Skip to content

Commit 9bd1ac9

Browse files
authored
Merge pull request #15016 from rjmccall/split-metadata-instantiation
2 parents eb96da5 + 9a4540e commit 9bd1ac9

22 files changed

+277
-34
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ Globals
5353
global ::= type 'MP' // type metadata pattern
5454
global ::= type 'Ma' // type metadata access function
5555
global ::= type 'ML' // type metadata lazy cache variable
56+
global ::= nominal-type 'Mr' // generic type completion function
5657
global ::= nominal-type 'Mi' // generic type instantiation function
5758
global ::= nominal-type 'MI' // generic type instantiation cache
5859
global ::= nominal-type 'Mm' // class metaclass

include/swift/ABI/MetadataValues.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ enum {
3333
/// The number of words (pointers) in a value buffer.
3434
NumWords_ValueBuffer = 3,
3535

36+
/// The number of words in a metadata completion context.
37+
NumWords_MetadataCompletionContext = 4,
38+
3639
/// The number of words in a yield-once coroutine buffer.
3740
NumWords_YieldOnceBuffer = 4,
3841

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ NODE(TypeList)
173173
NODE(TypeMangling)
174174
NODE(TypeMetadata)
175175
NODE(TypeMetadataAccessFunction)
176+
NODE(TypeMetadataCompletionFunction)
176177
NODE(TypeMetadataInstantiationCache)
177178
NODE(TypeMetadataInstantiationFunction)
178179
NODE(TypeMetadataLazyCache)

include/swift/IRGen/Linking.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ class LinkEntity {
159159
/// The pointer is a NominalTypeDecl*.
160160
TypeMetadataInstantiationFunction,
161161

162+
/// The completion function for a generic or resilient nominal type.
163+
/// The pointer is a NominalTypeDecl*.
164+
TypeMetadataCompletionFunction,
165+
162166
/// The module descriptor for a module.
163167
/// The pointer is a ModuleDecl*.
164168
ModuleDescriptor,
@@ -488,6 +492,12 @@ class LinkEntity {
488492
return entity;
489493
}
490494

495+
static LinkEntity forTypeMetadataCompletionFunction(NominalTypeDecl *decl) {
496+
LinkEntity entity;
497+
entity.setForDecl(Kind::TypeMetadataCompletionFunction, decl);
498+
return entity;
499+
}
500+
491501
static LinkEntity forTypeMetadataLazyCacheVariable(CanType type) {
492502
LinkEntity entity;
493503
entity.setForType(Kind::TypeMetadataLazyCacheVariable, type);

include/swift/Runtime/Metadata.h

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3067,18 +3067,71 @@ struct TargetGenericMetadataInstantiationCache {
30673067
using GenericMetadataInstantiationCache =
30683068
TargetGenericMetadataInstantiationCache<InProcess>;
30693069

3070+
/// A function that instantiates metadata. This function is required
3071+
/// to succeed.
3072+
///
3073+
/// In general, the metadata returned by this function should have all the
3074+
/// basic structure necessary to identify itself: that is, it must have a
3075+
/// type descriptor and generic arguments. However, it does not need to be
3076+
/// fully functional as type metadata; for example, it does not need to have
3077+
/// a meaningful value witness table, v-table entries, or a superclass.
3078+
///
3079+
/// Operations which may fail (due to e.g. recursive dependencies) but which
3080+
/// must be performed in order to prepare the metadata object to be fully
3081+
/// functional as type metadata should be delayed until the completion
3082+
/// function.
3083+
using MetadataInstantiator =
3084+
Metadata *(const TargetTypeContextDescriptor<InProcess> *type,
3085+
const void *arguments,
3086+
const TargetGenericMetadataPattern<InProcess> *pattern);
3087+
3088+
/// The opaque completion context of a metadata completion function.
3089+
/// A completion function that needs to report a completion dependency
3090+
/// can use this to figure out where it left off and thus avoid redundant
3091+
/// work when re-invoked. It will be zero on first entry for a type, and
3092+
/// the runtime is free to copy it to a different location between
3093+
/// invocations.
3094+
struct MetadataCompletionContext {
3095+
void *Data[NumWords_MetadataCompletionContext];
3096+
};
3097+
3098+
/// A function which attempts to complete the given metadata.
3099+
///
3100+
/// This function may fail due to a dependency on the completion of some
3101+
/// other metadata object. It can indicate this by returning the metadata
3102+
/// on which it depends. In this case, the function will be invoked again
3103+
/// when the dependency is resolved. The function must be careful not to
3104+
/// indicate a completion dependency on a type that has always been
3105+
/// completed; the runtime cannot reliably distinguish this sort of
3106+
/// programming failure from a race in which the dependent type was
3107+
/// completed immediately after it was observed to be incomplete, and so
3108+
/// the function will be repeatedly re-invoked.
3109+
///
3110+
/// The function will never be called multiple times simultaneously, but
3111+
/// it may be called many times as successive dependencies are resolved.
3112+
/// If the function ever completes successfully (by returning null), it
3113+
/// will not be called again for the same type.
3114+
///
3115+
/// \return null to indicate that the type has been completed, or a non-null
3116+
/// pointer to indicate that completion is blocked on the completion of
3117+
/// some other type
3118+
using MetadataCompleter =
3119+
Metadata *(const Metadata *type,
3120+
MetadataCompletionContext *context,
3121+
const TargetGenericMetadataPattern<InProcess> *pattern);
3122+
30703123
/// An instantiation pattern for type metadata.
30713124
template <typename Runtime>
30723125
struct TargetGenericMetadataPattern {
3073-
using InstantiationFunction_t =
3074-
TargetMetadata<Runtime> *(const TargetTypeContextDescriptor<Runtime> *type,
3075-
const void *arguments,
3076-
const TargetGenericMetadataPattern<Runtime> *pattern);
3077-
30783126
/// The function to call to instantiate the template.
3079-
TargetRelativeDirectPointer<Runtime, InstantiationFunction_t>
3127+
TargetRelativeDirectPointer<Runtime, MetadataInstantiator>
30803128
InstantiationFunction;
30813129

3130+
/// The function to call to complete the instantiation. If this is null,
3131+
/// the instantiation function must always generate complete metadata.
3132+
TargetRelativeDirectPointer<Runtime, MetadataCompleter, /*nullable*/ true>
3133+
CompletionFunction;
3134+
30823135
/// Flags describing the layout of this instantiation pattern.
30833136
GenericMetadataPatternFlags PatternFlags;
30843137

lib/Demangling/Demangler.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,6 +1441,8 @@ NodePointer Demangler::demangleMetatype() {
14411441
return createWithPoppedType(Node::Kind::TypeMetadataInstantiationCache);
14421442
case 'i':
14431443
return createWithPoppedType(Node::Kind::TypeMetadataInstantiationFunction);
1444+
case 'r':
1445+
return createWithPoppedType(Node::Kind::TypeMetadataCompletionFunction);
14441446
case 'L':
14451447
return createWithPoppedType(Node::Kind::TypeMetadataLazyCache);
14461448
case 'm':

lib/Demangling/NodePrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ class NodePrinter {
419419
case Node::Kind::TypeMangling:
420420
case Node::Kind::TypeMetadata:
421421
case Node::Kind::TypeMetadataAccessFunction:
422+
case Node::Kind::TypeMetadataCompletionFunction:
422423
case Node::Kind::TypeMetadataInstantiationCache:
423424
case Node::Kind::TypeMetadataInstantiationFunction:
424425
case Node::Kind::TypeMetadataLazyCache:
@@ -1456,6 +1457,10 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
14561457
Printer << "type metadata instantiation function for ";
14571458
print(Node->getChild(0));
14581459
return nullptr;
1460+
case Node::Kind::TypeMetadataCompletionFunction:
1461+
Printer << "type metadata completion function for ";
1462+
print(Node->getChild(0));
1463+
return nullptr;
14591464
case Node::Kind::TypeMetadataLazyCache:
14601465
Printer << "lazy cache variable for type metadata for ";
14611466
print(Node->getChild(0));

lib/Demangling/OldRemangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,11 @@ void Remangler::mangleTypeMetadataInstantiationFunction(Node *node) {
712712
mangleSingleChildNode(node); // type
713713
}
714714

715+
void Remangler::mangleTypeMetadataCompletionFunction(Node *node) {
716+
Out << "Mr";
717+
mangleSingleChildNode(node); // type
718+
}
719+
715720
void Remangler::mangleTypeMetadataLazyCache(Node *node) {
716721
Out << "ML";
717722
mangleSingleChildNode(node); // type

lib/Demangling/Remangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,6 +1712,11 @@ void Remangler::mangleTypeMetadataInstantiationFunction(Node *node) {
17121712
Buffer << "Mi";
17131713
}
17141714

1715+
void Remangler::mangleTypeMetadataCompletionFunction(Node *node) {
1716+
mangleSingleChildNode(node);
1717+
Buffer << "Mr";
1718+
}
1719+
17151720
void Remangler::mangleTypeMetadataLazyCache(Node *node) {
17161721
mangleChildNodes(node);
17171722
Buffer << "ML";

lib/IRGen/GenDecl.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,6 +1459,7 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
14591459

14601460
case Kind::TypeMetadataInstantiationCache:
14611461
case Kind::TypeMetadataInstantiationFunction:
1462+
case Kind::TypeMetadataCompletionFunction:
14621463
case Kind::TypeMetadataPattern:
14631464
return SILLinkage::Private;
14641465

@@ -1652,6 +1653,7 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
16521653
case Kind::AnonymousDescriptor:
16531654
case Kind::TypeMetadataInstantiationCache:
16541655
case Kind::TypeMetadataInstantiationFunction:
1656+
case Kind::TypeMetadataCompletionFunction:
16551657
case Kind::TypeMetadataPattern:
16561658
return false;
16571659

@@ -3392,6 +3394,32 @@ IRGenModule::getAddrOfTypeMetadataInstantiationFunction(NominalTypeDecl *D,
33923394
return entry;
33933395
}
33943396

3397+
llvm::Function *
3398+
IRGenModule::getAddrOfTypeMetadataCompletionFunction(NominalTypeDecl *D,
3399+
ForDefinition_t forDefinition) {
3400+
LinkEntity entity = LinkEntity::forTypeMetadataCompletionFunction(D);
3401+
llvm::Function *&entry = GlobalFuncs[entity];
3402+
if (entry) {
3403+
if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
3404+
return entry;
3405+
}
3406+
3407+
llvm::Type *argTys[] = {
3408+
/// Type metadata.
3409+
TypeMetadataPtrTy,
3410+
/// Metadata completion context.
3411+
Int8PtrTy,
3412+
/// Generic metadata pattern.
3413+
Int8PtrPtrTy
3414+
};
3415+
auto fnType = llvm::FunctionType::get(TypeMetadataPtrTy,
3416+
argTys, /*isVarArg*/ false);
3417+
Signature signature(fnType, llvm::AttributeList(), DefaultCC);
3418+
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
3419+
entry = createFunction(*this, link, signature);
3420+
return entry;
3421+
}
3422+
33953423
/// Return the address of a nominal type descriptor.
33963424
llvm::Constant *IRGenModule::getAddrOfTypeContextDescriptor(NominalTypeDecl *D,
33973425
RequireMetadata_t requireMetadata,

0 commit comments

Comments
 (0)