Skip to content

Split the instantiation function into two phases #15016

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Globals
global ::= type 'MP' // type metadata pattern
global ::= type 'Ma' // type metadata access function
global ::= type 'ML' // type metadata lazy cache variable
global ::= nominal-type 'Mr' // generic type completion function
global ::= nominal-type 'Mi' // generic type instantiation function
global ::= nominal-type 'MI' // generic type instantiation cache
global ::= nominal-type 'Mm' // class metaclass
Expand Down
3 changes: 3 additions & 0 deletions include/swift/ABI/MetadataValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ enum {
/// The number of words (pointers) in a value buffer.
NumWords_ValueBuffer = 3,

/// The number of words in a metadata completion context.
NumWords_MetadataCompletionContext = 4,

/// The number of words in a yield-once coroutine buffer.
NumWords_YieldOnceBuffer = 4,

Expand Down
1 change: 1 addition & 0 deletions include/swift/Demangling/DemangleNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ NODE(TypeList)
NODE(TypeMangling)
NODE(TypeMetadata)
NODE(TypeMetadataAccessFunction)
NODE(TypeMetadataCompletionFunction)
NODE(TypeMetadataInstantiationCache)
NODE(TypeMetadataInstantiationFunction)
NODE(TypeMetadataLazyCache)
Expand Down
10 changes: 10 additions & 0 deletions include/swift/IRGen/Linking.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ class LinkEntity {
/// The pointer is a NominalTypeDecl*.
TypeMetadataInstantiationFunction,

/// The completion function for a generic or resilient nominal type.
/// The pointer is a NominalTypeDecl*.
TypeMetadataCompletionFunction,

/// The module descriptor for a module.
/// The pointer is a ModuleDecl*.
ModuleDescriptor,
Expand Down Expand Up @@ -488,6 +492,12 @@ class LinkEntity {
return entity;
}

static LinkEntity forTypeMetadataCompletionFunction(NominalTypeDecl *decl) {
LinkEntity entity;
entity.setForDecl(Kind::TypeMetadataCompletionFunction, decl);
return entity;
}

static LinkEntity forTypeMetadataLazyCacheVariable(CanType type) {
LinkEntity entity;
entity.setForType(Kind::TypeMetadataLazyCacheVariable, type);
Expand Down
65 changes: 59 additions & 6 deletions include/swift/Runtime/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -3067,18 +3067,71 @@ struct TargetGenericMetadataInstantiationCache {
using GenericMetadataInstantiationCache =
TargetGenericMetadataInstantiationCache<InProcess>;

/// A function that instantiates metadata. This function is required
/// to succeed.
///
/// In general, the metadata returned by this function should have all the
/// basic structure necessary to identify itself: that is, it must have a
/// type descriptor and generic arguments. However, it does not need to be
/// fully functional as type metadata; for example, it does not need to have
/// a meaningful value witness table, v-table entries, or a superclass.
///
/// Operations which may fail (due to e.g. recursive dependencies) but which
/// must be performed in order to prepare the metadata object to be fully
/// functional as type metadata should be delayed until the completion
/// function.
using MetadataInstantiator =
Metadata *(const TargetTypeContextDescriptor<InProcess> *type,
const void *arguments,
const TargetGenericMetadataPattern<InProcess> *pattern);

/// The opaque completion context of a metadata completion function.
/// A completion function that needs to report a completion dependency
/// can use this to figure out where it left off and thus avoid redundant
/// work when re-invoked. It will be zero on first entry for a type, and
/// the runtime is free to copy it to a different location between
/// invocations.
struct MetadataCompletionContext {
void *Data[NumWords_MetadataCompletionContext];
};

/// A function which attempts to complete the given metadata.
///
/// This function may fail due to a dependency on the completion of some
/// other metadata object. It can indicate this by returning the metadata
/// on which it depends. In this case, the function will be invoked again
/// when the dependency is resolved. The function must be careful not to
/// indicate a completion dependency on a type that has always been
/// completed; the runtime cannot reliably distinguish this sort of
/// programming failure from a race in which the dependent type was
/// completed immediately after it was observed to be incomplete, and so
/// the function will be repeatedly re-invoked.
///
/// The function will never be called multiple times simultaneously, but
/// it may be called many times as successive dependencies are resolved.
/// If the function ever completes successfully (by returning null), it
/// will not be called again for the same type.
///
/// \return null to indicate that the type has been completed, or a non-null
/// pointer to indicate that completion is blocked on the completion of
/// some other type
using MetadataCompleter =
Metadata *(const Metadata *type,
MetadataCompletionContext *context,
const TargetGenericMetadataPattern<InProcess> *pattern);

/// An instantiation pattern for type metadata.
template <typename Runtime>
struct TargetGenericMetadataPattern {
using InstantiationFunction_t =
TargetMetadata<Runtime> *(const TargetTypeContextDescriptor<Runtime> *type,
const void *arguments,
const TargetGenericMetadataPattern<Runtime> *pattern);

/// The function to call to instantiate the template.
TargetRelativeDirectPointer<Runtime, InstantiationFunction_t>
TargetRelativeDirectPointer<Runtime, MetadataInstantiator>
InstantiationFunction;

/// The function to call to complete the instantiation. If this is null,
/// the instantiation function must always generate complete metadata.
TargetRelativeDirectPointer<Runtime, MetadataCompleter, /*nullable*/ true>
CompletionFunction;

/// Flags describing the layout of this instantiation pattern.
GenericMetadataPatternFlags PatternFlags;

Expand Down
2 changes: 2 additions & 0 deletions lib/Demangling/Demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1441,6 +1441,8 @@ NodePointer Demangler::demangleMetatype() {
return createWithPoppedType(Node::Kind::TypeMetadataInstantiationCache);
case 'i':
return createWithPoppedType(Node::Kind::TypeMetadataInstantiationFunction);
case 'r':
return createWithPoppedType(Node::Kind::TypeMetadataCompletionFunction);
case 'L':
return createWithPoppedType(Node::Kind::TypeMetadataLazyCache);
case 'm':
Expand Down
5 changes: 5 additions & 0 deletions lib/Demangling/NodePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ class NodePrinter {
case Node::Kind::TypeMangling:
case Node::Kind::TypeMetadata:
case Node::Kind::TypeMetadataAccessFunction:
case Node::Kind::TypeMetadataCompletionFunction:
case Node::Kind::TypeMetadataInstantiationCache:
case Node::Kind::TypeMetadataInstantiationFunction:
case Node::Kind::TypeMetadataLazyCache:
Expand Down Expand Up @@ -1456,6 +1457,10 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
Printer << "type metadata instantiation function for ";
print(Node->getChild(0));
return nullptr;
case Node::Kind::TypeMetadataCompletionFunction:
Printer << "type metadata completion function for ";
print(Node->getChild(0));
return nullptr;
case Node::Kind::TypeMetadataLazyCache:
Printer << "lazy cache variable for type metadata for ";
print(Node->getChild(0));
Expand Down
5 changes: 5 additions & 0 deletions lib/Demangling/OldRemangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,11 @@ void Remangler::mangleTypeMetadataInstantiationFunction(Node *node) {
mangleSingleChildNode(node); // type
}

void Remangler::mangleTypeMetadataCompletionFunction(Node *node) {
Out << "Mr";
mangleSingleChildNode(node); // type
}

void Remangler::mangleTypeMetadataLazyCache(Node *node) {
Out << "ML";
mangleSingleChildNode(node); // type
Expand Down
5 changes: 5 additions & 0 deletions lib/Demangling/Remangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1712,6 +1712,11 @@ void Remangler::mangleTypeMetadataInstantiationFunction(Node *node) {
Buffer << "Mi";
}

void Remangler::mangleTypeMetadataCompletionFunction(Node *node) {
mangleSingleChildNode(node);
Buffer << "Mr";
}

void Remangler::mangleTypeMetadataLazyCache(Node *node) {
mangleChildNodes(node);
Buffer << "ML";
Expand Down
28 changes: 28 additions & 0 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1459,6 +1459,7 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {

case Kind::TypeMetadataInstantiationCache:
case Kind::TypeMetadataInstantiationFunction:
case Kind::TypeMetadataCompletionFunction:
case Kind::TypeMetadataPattern:
return SILLinkage::Private;

Expand Down Expand Up @@ -1652,6 +1653,7 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
case Kind::AnonymousDescriptor:
case Kind::TypeMetadataInstantiationCache:
case Kind::TypeMetadataInstantiationFunction:
case Kind::TypeMetadataCompletionFunction:
case Kind::TypeMetadataPattern:
return false;

Expand Down Expand Up @@ -3392,6 +3394,32 @@ IRGenModule::getAddrOfTypeMetadataInstantiationFunction(NominalTypeDecl *D,
return entry;
}

llvm::Function *
IRGenModule::getAddrOfTypeMetadataCompletionFunction(NominalTypeDecl *D,
ForDefinition_t forDefinition) {
LinkEntity entity = LinkEntity::forTypeMetadataCompletionFunction(D);
llvm::Function *&entry = GlobalFuncs[entity];
if (entry) {
if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
return entry;
}

llvm::Type *argTys[] = {
/// Type metadata.
TypeMetadataPtrTy,
/// Metadata completion context.
Int8PtrTy,
/// Generic metadata pattern.
Int8PtrPtrTy
};
auto fnType = llvm::FunctionType::get(TypeMetadataPtrTy,
argTys, /*isVarArg*/ false);
Signature signature(fnType, llvm::AttributeList(), DefaultCC);
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
entry = createFunction(*this, link, signature);
return entry;
}

/// Return the address of a nominal type descriptor.
llvm::Constant *IRGenModule::getAddrOfTypeContextDescriptor(NominalTypeDecl *D,
RequireMetadata_t requireMetadata,
Expand Down
Loading