Skip to content

[Runtime/ABI] Replace emitTypeFieldAccessor with a single runtime method #13926

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 15 commits into from
Feb 21, 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
3 changes: 2 additions & 1 deletion include/swift/Demangling/TypeDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ class TypeDecoder {
}
case NodeKind::BoundGenericClass:
case NodeKind::BoundGenericEnum:
case NodeKind::BoundGenericStructure: {
case NodeKind::BoundGenericStructure:
case NodeKind::BoundGenericOtherNominalType: {
if (Node->getNumChildren() != 2)
return BuiltType();

Expand Down
5 changes: 5 additions & 0 deletions include/swift/Reflection/Records.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "swift/Basic/RelativePointer.h"
#include "swift/Demangling/Demangle.h"
#include "llvm/ADT/ArrayRef.h"

const uint16_t SWIFT_REFLECTION_METADATA_VERSION = 3; // superclass field

Expand Down Expand Up @@ -204,6 +205,10 @@ class FieldDescriptor {
return const_iterator { End, End };
}

llvm::ArrayRef<FieldRecord> getFields() const {
return {getFieldRecordBuffer(), NumFields};
}

bool hasMangledTypeName() const {
return MangledTypeName;
}
Expand Down
81 changes: 33 additions & 48 deletions include/swift/Runtime/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@
#include "swift/Basic/RelativePointer.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Demangling/ManglingMacros.h"
#include "swift/Reflection/Records.h"
#include "swift/Runtime/Unreachable.h"
#include "../../../stdlib/public/SwiftShims/HeapObject.h"
#if SWIFT_OBJC_INTEROP
#include <objc/runtime.h>
#endif
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Casting.h"

namespace swift {
Expand Down Expand Up @@ -1287,16 +1289,6 @@ struct TargetClassMetadata : public TargetHeapMetadata<Runtime> {
auto asWords = reinterpret_cast<const void * const*>(this);
return reinterpret_cast<const StoredPointer *>(asWords + offset);
}

/// Get a pointer to the field type vector, if present, or null.
const FieldType *getFieldTypes() const {
assert(isTypeMetadata());
auto *getter = getDescription()->GetFieldTypes.get();
if (!getter)
return nullptr;

return getter(this);
}

uint32_t getSizeInWords() const {
assert(isTypeMetadata());
Expand Down Expand Up @@ -1569,15 +1561,6 @@ struct TargetStructMetadata : public TargetValueMetadata<Runtime> {
auto asWords = reinterpret_cast<const void * const*>(this);
return reinterpret_cast<const StoredPointer *>(asWords + offset);
}

/// Get a pointer to the field type vector, if present, or null.
const FieldType *getFieldTypes() const {
auto *getter = getDescription()->GetFieldTypes.get();
if (!getter)
return nullptr;

return getter(this);
}

static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Struct;
Expand Down Expand Up @@ -2531,6 +2514,12 @@ struct TargetContextDescriptor {
/// context is not generic.
const TargetGenericContext<Runtime> *getGenericContext() const;

unsigned getNumGenericParams() const {
auto *genericContext = getGenericContext();
return genericContext
? genericContext->getGenericContextHeader().NumParams
: 0;
}
private:
TargetContextDescriptor(const TargetContextDescriptor &) = delete;
TargetContextDescriptor(TargetContextDescriptor &&) = delete;
Expand Down Expand Up @@ -3165,15 +3154,11 @@ class TargetClassDescriptor final
}

public:
/// The field names. A doubly-null-terminated list of strings, whose
/// length and order is consistent with that of the field offset vector.
RelativeDirectPointer<const char, /*nullable*/ true> FieldNames;

/// The field type vector accessor. Returns a pointer to an array of
/// type metadata references whose order is consistent with that of the
/// field offset vector.
RelativeDirectPointer<const FieldType *
(const TargetMetadata<Runtime> *)> GetFieldTypes;
/// Indicates if the type represented by this descriptor
/// supports reflection (C and Obj-C enums currently don't).
/// FIXME: This is temporarily left as 32-bit integer to avoid
/// changing layout of context descriptor.
uint32_t IsReflectable;

/// True if metadata records for this type have a field offset vector for
/// its stored properties.
Expand Down Expand Up @@ -3275,15 +3260,11 @@ class TargetStructDescriptor final
/// vector.
uint32_t FieldOffsetVectorOffset;

/// The field names. A doubly-null-terminated list of strings, whose
/// length and order is consistent with that of the field offset vector.
RelativeDirectPointer<const char, /*nullable*/ true> FieldNames;

/// The field type vector accessor. Returns a pointer to an array of
/// type metadata references whose order is consistent with that of the
/// field offset vector.
RelativeDirectPointer<const FieldType *
(const TargetMetadata<Runtime> *)> GetFieldTypes;
/// Indicates if the type represented by this descriptor
/// supports reflection (C and Obj-C enums currently don't).
/// FIXME: This is temporarily left as 32-bit integer to avoid
/// changing layout of context descriptor.
uint32_t IsReflectable;

/// True if metadata records for this type have a field offset vector for
/// its stored properties.
Expand Down Expand Up @@ -3327,17 +3308,11 @@ class TargetEnumDescriptor final
/// The number of empty cases in the enum.
uint32_t NumEmptyCases;

/// The names of the cases. A doubly-null-terminated list of strings,
/// whose length is NumNonEmptyCases + NumEmptyCases. Cases are named in
/// tag order, non-empty cases first, followed by empty cases.
RelativeDirectPointer<const char, /*nullable*/ true> CaseNames;

/// The field type vector accessor. Returns a pointer to an array of
/// type metadata references whose order is consistent with that of the
/// CaseNames. Only types for payload cases are provided.
RelativeDirectPointer<
const FieldType * (const TargetMetadata<Runtime> *)>
GetCaseTypes;
/// Indicates if the type represented by this descriptor
/// supports reflection (C and Obj-C enums currently don't).
/// FIXME: This is temporarily left as 32-bit integer to avoid
/// changing layout of context descriptor.
uint32_t IsReflectable;

uint32_t getNumPayloadCases() const {
return NumPayloadCasesAndPayloadSizeOffset & 0x00FFFFFFU;
Expand Down Expand Up @@ -3760,12 +3735,22 @@ SWIFT_RUNTIME_EXPORT
void swift_registerTypeMetadataRecords(const TypeMetadataRecord *begin,
const TypeMetadataRecord *end);

/// Register a block of type field records for dynamic lookup.
SWIFT_RUNTIME_EXPORT
void swift_registerFieldDescriptors(const reflection::FieldDescriptor **records,
size_t size);

/// Return the superclass, if any. The result is nullptr for root
/// classes and class protocol types.
SWIFT_CC(swift)
SWIFT_RUNTIME_STDLIB_INTERFACE
const Metadata *_swift_class_getSuperclass(const Metadata *theClass);

SWIFT_RUNTIME_STDLIB_INTERFACE
void swift_getFieldAt(
const Metadata *type, unsigned index,
std::function<void(llvm::StringRef name, FieldType type)> callback);

} // end namespace swift

#pragma clang diagnostic pop
Expand Down
5 changes: 5 additions & 0 deletions include/swift/Runtime/RuntimeFunctions.def
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,11 @@ FUNCTION(RegisterTypeMetadataRecords,
RETURNS(VoidTy),
ARGS(TypeMetadataRecordPtrTy, TypeMetadataRecordPtrTy),
ATTRS(NoUnwind))
FUNCTION(RegisterFieldDescriptors,
swift_registerFieldDescriptors, DefaultCC,
RETURNS(VoidTy),
ARGS(FieldDescriptorPtrPtrTy, SizeTy),
ATTRS(NoUnwind))

// void swift_beginAccess(void *pointer, ValueBuffer *scratch, size_t flags);
FUNCTION(BeginAccess, swift_beginAccess, C_CC,
Expand Down
32 changes: 31 additions & 1 deletion lib/Demangling/Demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ static bool isAnyGeneric(Node::Kind kind) {
case Node::Kind::Class:
case Node::Kind::Enum:
case Node::Kind::Protocol:
case Node::Kind::OtherNominalType:
case Node::Kind::TypeAlias:
case Node::Kind::SymbolicReference:
case Node::Kind::UnresolvedSymbolicReference:
return true;
default:
return false;
Expand Down Expand Up @@ -1237,11 +1240,35 @@ NodePointer Demangler::demangleBoundGenericType() {
NodePointer Demangler::demangleBoundGenericArgs(NodePointer Nominal,
const Vector<NodePointer> &TypeLists,
size_t TypeListIdx) {
if (!Nominal || Nominal->getNumChildren() < 2)
// TODO: This would be a lot easier if we represented bound generic args
// flatly in the demangling tree, since that's how they're mangled and also
// how the runtime generally wants to consume them.

if (!Nominal)
return nullptr;

if (TypeListIdx >= TypeLists.size())
return nullptr;

// Associate a symbolic reference with all remaining generic arguments.
if (Nominal->getKind() == Node::Kind::SymbolicReference
|| Nominal->getKind() == Node::Kind::UnresolvedSymbolicReference) {
auto remainingTypeList = createNode(Node::Kind::TypeList);
for (unsigned i = TypeLists.size() - 1;
i >= TypeListIdx && i < TypeLists.size();
--i) {
auto list = TypeLists[i];
for (auto child : *list) {
remainingTypeList->addChild(child, *this);
}
}
return createWithChildren(Node::Kind::BoundGenericOtherNominalType,
createType(Nominal), remainingTypeList);
}

if (Nominal->getNumChildren() < 2)
return nullptr;

NodePointer args = TypeLists[TypeListIdx++];

// Generic arguments for the outermost type come first.
Expand Down Expand Up @@ -1286,6 +1313,9 @@ NodePointer Demangler::demangleBoundGenericArgs(NodePointer Nominal,
case Node::Kind::Enum:
kind = Node::Kind::BoundGenericEnum;
break;
case Node::Kind::OtherNominalType:
kind = Node::Kind::BoundGenericOtherNominalType;
break;
default:
return nullptr;
}
Expand Down
9 changes: 7 additions & 2 deletions lib/Demangling/Remangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ void Remangler::mangleGenericArgs(Node *node, char &Separator) {
Separator = '_';
break;

case Node::Kind::BoundGenericOtherNominalType:
case Node::Kind::BoundGenericStructure:
case Node::Kind::BoundGenericEnum:
case Node::Kind::BoundGenericClass: {
Expand Down Expand Up @@ -1983,11 +1984,13 @@ bool Demangle::isSpecialized(Node *node) {
case Node::Kind::BoundGenericStructure:
case Node::Kind::BoundGenericEnum:
case Node::Kind::BoundGenericClass:
case Node::Kind::BoundGenericOtherNominalType:
return true;

case Node::Kind::Structure:
case Node::Kind::Enum:
case Node::Kind::Class:
case Node::Kind::OtherNominalType:
return isSpecialized(node->getChild(0));

case Node::Kind::Extension:
Expand All @@ -2002,7 +2005,8 @@ NodePointer Demangle::getUnspecialized(Node *node, NodeFactory &Factory) {
switch (node->getKind()) {
case Node::Kind::Structure:
case Node::Kind::Enum:
case Node::Kind::Class: {
case Node::Kind::Class:
case Node::Kind::OtherNominalType: {
NodePointer result = Factory.createNode(node->getKind());
NodePointer parentOrModule = node->getChild(0);
if (isSpecialized(parentOrModule))
Expand All @@ -2015,7 +2019,8 @@ NodePointer Demangle::getUnspecialized(Node *node, NodeFactory &Factory) {

case Node::Kind::BoundGenericStructure:
case Node::Kind::BoundGenericEnum:
case Node::Kind::BoundGenericClass: {
case Node::Kind::BoundGenericClass:
case Node::Kind::BoundGenericOtherNominalType: {
NodePointer unboundType = node->getChild(0);
assert(unboundType->getKind() == Node::Kind::Type);
NodePointer nominalType = unboundType->getChild(0);
Expand Down
4 changes: 3 additions & 1 deletion lib/Demangling/TypeDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ NodePointer Demangle::stripGenericArgsFromContextNode(const NodePointer &node,
case Demangle::Node::Kind::BoundGenericClass:
case Demangle::Node::Kind::BoundGenericEnum:
case Demangle::Node::Kind::BoundGenericStructure:
case Demangle::Node::Kind::BoundGenericOtherNominalType:
// Bound generic types have a 'Type' node under them, whose child is
// the non-generic reference. If we don't see that structure, do nothing.
if (node->getNumChildren() < 2 ||
Expand All @@ -37,7 +38,8 @@ NodePointer Demangle::stripGenericArgsFromContextNode(const NodePointer &node,

case Demangle::Node::Kind::Class:
case Demangle::Node::Kind::Enum:
case Demangle::Node::Kind::Structure: {
case Demangle::Node::Kind::Structure:
case Demangle::Node::Kind::OtherNominalType: {
if (node->getNumChildren() < 2)
return node;

Expand Down
2 changes: 2 additions & 0 deletions lib/IDE/TypeReconstruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2105,6 +2105,7 @@ static void VisitNode(
case Demangle::Node::Kind::BoundGenericClass:
case Demangle::Node::Kind::BoundGenericStructure:
case Demangle::Node::Kind::BoundGenericEnum:
case Demangle::Node::Kind::BoundGenericOtherNominalType:
VisitNodeBoundGeneric(ast, node, result);
break;

Expand All @@ -2115,6 +2116,7 @@ static void VisitNode(
case Demangle::Node::Kind::Structure:
case Demangle::Node::Kind::Class:
case Demangle::Node::Kind::Enum:
case Demangle::Node::Kind::OtherNominalType:
case Demangle::Node::Kind::Protocol:
VisitNodeNominal(ast, node, result);
break;
Expand Down
Loading