mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Implement reflection support for Symbolic Extended Existential types.
This patch adds a new SymbolicExtendedExistentialTypeRef kind, and wires it up in TypeDecoder, TypeRefBuilder, TypeLowering, and ASTDemangler. This is tested indirectly via the matching LLDB commit.
This commit is contained in:
@@ -193,6 +193,7 @@ public:
|
||||
};
|
||||
|
||||
using IndexType = uint64_t;
|
||||
using RemoteAddressType = std::pair<uint64_t, uint8_t>;
|
||||
|
||||
friend class NodeFactory;
|
||||
|
||||
@@ -209,14 +210,20 @@ private:
|
||||
IndexType Index;
|
||||
NodePointer InlineChildren[2];
|
||||
NodeVector Children;
|
||||
RemoteAddressType RemoteAddress;
|
||||
};
|
||||
|
||||
|
||||
Kind NodeKind;
|
||||
|
||||
enum class PayloadKind : uint8_t {
|
||||
None = 0, OneChild = 1, TwoChildren = 2,
|
||||
Text, Index, ManyChildren
|
||||
None = 0,
|
||||
OneChild = 1,
|
||||
TwoChildren = 2,
|
||||
Text,
|
||||
Index,
|
||||
ManyChildren,
|
||||
RemoteAddress
|
||||
};
|
||||
PayloadKind NodePayloadKind;
|
||||
|
||||
@@ -231,6 +238,10 @@ private:
|
||||
: NodeKind(k), NodePayloadKind(PayloadKind::Index) {
|
||||
Index = index;
|
||||
}
|
||||
Node(Kind k, uint64_t remoteAddress, uint8_t addressSpace)
|
||||
: NodeKind(k), NodePayloadKind(PayloadKind::RemoteAddress) {
|
||||
RemoteAddress = {remoteAddress, addressSpace};
|
||||
}
|
||||
Node(const Node &) = delete;
|
||||
Node &operator=(const Node &) = delete;
|
||||
|
||||
@@ -284,6 +295,14 @@ public:
|
||||
return Index;
|
||||
}
|
||||
|
||||
bool hasRemoteAddress() const {
|
||||
return NodePayloadKind == PayloadKind::RemoteAddress;
|
||||
}
|
||||
std::pair<uint64_t, uint8_t> getRemoteAddress() const {
|
||||
assert(hasRemoteAddress());
|
||||
return RemoteAddress;
|
||||
}
|
||||
|
||||
using iterator = const NodePointer *;
|
||||
|
||||
size_t getNumChildren() const {
|
||||
|
||||
@@ -249,6 +249,12 @@ public:
|
||||
/// Creates a node of kind \p K with an \p Index payload.
|
||||
NodePointer createNode(Node::Kind K, Node::IndexType Index);
|
||||
|
||||
/// Creates a node of kind \p K with a \p RemoteAddress payload.
|
||||
///
|
||||
/// These nodes are created and consumed by the reflection library.
|
||||
NodePointer createNode(Node::Kind K, uint64_t RemoteAddress,
|
||||
uint8_t AddressSpace);
|
||||
|
||||
/// Creates a node of kind \p K with a \p Text payload.
|
||||
///
|
||||
/// The \p Text string must be already allocated with the Factory and therefore
|
||||
|
||||
@@ -573,6 +573,43 @@ void decodeRequirement(
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract the protocol and requirement nodes from a shape symbol.
|
||||
static inline std::pair<NodePointer, NodePointer>
|
||||
decodeShape(NodePointer Node) {
|
||||
if (!Node || Node->getKind() != Node::Kind::Global ||
|
||||
Node->getNumChildren() != 1)
|
||||
return {nullptr, nullptr};
|
||||
Node = Node->getChild(0);
|
||||
if (Node && (Node->getKind() == Node::Kind::Uniquable) &&
|
||||
Node->getNumChildren() == 1)
|
||||
Node = Node->getChild(0);
|
||||
if (!Node || Node->getKind() != Node::Kind::ExtendedExistentialTypeShape ||
|
||||
Node->getNumChildren() != 2)
|
||||
return {nullptr, nullptr};
|
||||
Node = Node->getChild(1);
|
||||
if (!Node || Node->getKind() != Node::Kind::Type ||
|
||||
Node->getNumChildren() != 1)
|
||||
return {nullptr, nullptr};
|
||||
Node = Node->getChild(0);
|
||||
if (!Node || Node->getKind() != Node::Kind::ConstrainedExistential ||
|
||||
Node->getNumChildren() != 2)
|
||||
return {nullptr, nullptr};
|
||||
NodePointer Requirements = Node->getChild(1);
|
||||
if (!Requirements || Requirements->getKind() !=
|
||||
Node::Kind::ConstrainedExistentialRequirementList)
|
||||
return {nullptr, nullptr};
|
||||
|
||||
Node = Node->getChild(0);
|
||||
if (!Node || Node->getKind() != Node::Kind::Type ||
|
||||
Node->getNumChildren() != 1)
|
||||
return {nullptr, nullptr};
|
||||
NodePointer Protocol = Node;
|
||||
if (!Protocol)
|
||||
return {nullptr, nullptr};
|
||||
|
||||
return {Protocol, Requirements};
|
||||
}
|
||||
|
||||
#define MAKE_NODE_TYPE_ERROR(Node, Fmt, ...) \
|
||||
TYPE_LOOKUP_ERROR_FMT("TypeDecoder.h:%u: Node kind %u \"%.*s\" - " Fmt, \
|
||||
__LINE__, (unsigned)Node->getKind(), \
|
||||
|
||||
@@ -480,16 +480,13 @@ public:
|
||||
// Try to preserve a reference to an OpaqueTypeDescriptor
|
||||
// symbolically, since we'd like to read out and resolve the type ref
|
||||
// to the underlying type if available.
|
||||
if (useOpaqueTypeSymbolicReferences
|
||||
&& context.isResolved()
|
||||
&& context.getResolved()->getKind() == ContextDescriptorKind::OpaqueType){
|
||||
// FIXME: this loses the address space. This can be fixed by adding an
|
||||
// opaque field in Node that can store the address space. This
|
||||
// wouldn't degrade performance as Node's address is part of an union
|
||||
// which is 16 bytes longs
|
||||
if (useOpaqueTypeSymbolicReferences && context.isResolved() &&
|
||||
context.getResolved()->getKind() ==
|
||||
ContextDescriptorKind::OpaqueType) {
|
||||
return dem.createNode(
|
||||
Node::Kind::OpaqueTypeDescriptorSymbolicReference,
|
||||
context.getResolved().getRemoteAddress().getRawAddress());
|
||||
context.getResolved().getRemoteAddress().getRawAddress(),
|
||||
context.getResolved().getRemoteAddress().getAddressSpace());
|
||||
}
|
||||
|
||||
return buildContextMangling(context, dem);
|
||||
@@ -504,15 +501,16 @@ public:
|
||||
// existential type shape.
|
||||
return dem.createNode(
|
||||
Node::Kind::UniqueExtendedExistentialTypeShapeSymbolicReference,
|
||||
resolved.getResolvedAddress().getRawAddress());
|
||||
resolved.getResolvedAddress().getRawAddress(),
|
||||
resolved.getResolvedAddress().getAddressSpace());
|
||||
}
|
||||
case Demangle::SymbolicReferenceKind::NonUniqueExtendedExistentialTypeShape: {
|
||||
// The symbolic reference points at a non-unique extended
|
||||
// existential type shape.
|
||||
// FIXME: this loses the address space.
|
||||
return dem.createNode(
|
||||
Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference,
|
||||
resolved.getResolvedAddress().getRawAddress());
|
||||
resolved.getResolvedAddress().getRawAddress(),
|
||||
resolved.getResolvedAddress().getAddressSpace());
|
||||
}
|
||||
case Demangle::SymbolicReferenceKind::ObjectiveCProtocol: {
|
||||
// 'resolved' points to a struct of two relative addresses.
|
||||
@@ -879,6 +877,73 @@ public:
|
||||
return resolver.swiftProtocol(Demangled);
|
||||
}
|
||||
|
||||
BuiltType readTypeFromShape(
|
||||
RemoteAbsolutePointer shapeAddress,
|
||||
std::function<std::optional<std::vector<BuiltType>>(unsigned)> getArgs) {
|
||||
RemoteAddress addr = shapeAddress.getResolvedAddress();
|
||||
ShapeRef Shape = readShape(addr);
|
||||
if (!Shape)
|
||||
return BuiltType();
|
||||
|
||||
assert(Shape->hasGeneralizationSignature());
|
||||
|
||||
// Pull out the existential type from the mangled type name.
|
||||
Demangler dem;
|
||||
auto mangledExistentialAddr =
|
||||
resolveRelativeField(Shape, Shape->ExistentialType);
|
||||
auto node =
|
||||
readMangledName(mangledExistentialAddr, MangledNameKind::Type, dem);
|
||||
if (!node)
|
||||
return BuiltType();
|
||||
|
||||
BuiltType builtProto = decodeMangledType(node).getType();
|
||||
if (!builtProto)
|
||||
return BuiltType();
|
||||
|
||||
if (auto builtArgs = getArgs(Shape->getGenSigArgumentLayoutSizeInWords())) {
|
||||
// Build up a substitution map for the generalized signature.
|
||||
BuiltGenericSignature sig =
|
||||
decodeRuntimeGenericSignature(Shape,
|
||||
Shape->getGeneralizationSignature())
|
||||
.getType();
|
||||
if (!sig)
|
||||
return BuiltType();
|
||||
|
||||
BuiltSubstitutionMap subst =
|
||||
Builder.createSubstitutionMap(sig, *builtArgs);
|
||||
if (subst.empty())
|
||||
return BuiltType();
|
||||
|
||||
builtProto = Builder.subst(builtProto, subst);
|
||||
if (!builtProto)
|
||||
return BuiltType();
|
||||
}
|
||||
|
||||
// Read the type expression to build up any remaining layers of
|
||||
// existential metatype.
|
||||
if (Shape->Flags.hasTypeExpression()) {
|
||||
Demangler dem;
|
||||
|
||||
// Read the mangled name.
|
||||
auto mangledContextName = Shape->getTypeExpression();
|
||||
auto mangledNameAddress =
|
||||
resolveRelativeField(Shape, mangledContextName->name);
|
||||
auto node =
|
||||
readMangledName(mangledNameAddress, MangledNameKind::Type, dem);
|
||||
if (!node)
|
||||
return BuiltType();
|
||||
|
||||
while (node->getKind() == Demangle::Node::Kind::Type &&
|
||||
node->hasChildren() &&
|
||||
node->getChild(0)->getKind() == Demangle::Node::Kind::Metatype &&
|
||||
node->getChild(0)->getNumChildren()) {
|
||||
builtProto = Builder.createExistentialMetatypeType(builtProto);
|
||||
node = node->getChild(0)->getChild(0);
|
||||
}
|
||||
}
|
||||
return builtProto;
|
||||
}
|
||||
|
||||
/// Given a remote pointer to metadata, attempt to turn it into a type.
|
||||
BuiltType
|
||||
readTypeFromMetadata(RemoteAddress MetadataAddress,
|
||||
@@ -1091,82 +1156,27 @@ public:
|
||||
}
|
||||
case MetadataKind::ExtendedExistential: {
|
||||
auto Exist = cast<TargetExtendedExistentialTypeMetadata<Runtime>>(Meta);
|
||||
|
||||
// Read the shape for this existential.
|
||||
|
||||
RemoteAddress shapeAddress = stripSignedPointer(Exist->Shape);
|
||||
ShapeRef Shape = readShape(shapeAddress);
|
||||
if (!Shape)
|
||||
return BuiltType();
|
||||
|
||||
const unsigned shapeArgumentCount
|
||||
= Shape->getGenSigArgumentLayoutSizeInWords();
|
||||
// Pull out the arguments to the generalization signature.
|
||||
assert(Shape->hasGeneralizationSignature());
|
||||
std::vector<BuiltType> builtArgs;
|
||||
for (unsigned i = 0; i < shapeArgumentCount; ++i) {
|
||||
auto remoteArg = Exist->getGeneralizationArguments()[i];
|
||||
auto remoteArgAddress =
|
||||
RemoteAddress(remoteArg, MetadataAddress.getAddressSpace());
|
||||
auto builtArg =
|
||||
readTypeFromMetadata(remoteArgAddress, false, recursion_limit);
|
||||
if (!builtArg)
|
||||
return BuiltType();
|
||||
builtArgs.push_back(builtArg);
|
||||
}
|
||||
|
||||
// Pull out the existential type from the mangled type name.
|
||||
Demangler dem;
|
||||
auto mangledExistentialAddr =
|
||||
resolveRelativeField(Shape, Shape->ExistentialType);
|
||||
auto node =
|
||||
readMangledName(mangledExistentialAddr, MangledNameKind::Type, dem);
|
||||
if (!node)
|
||||
return BuiltType();
|
||||
|
||||
BuiltType builtProto = decodeMangledType(node).getType();
|
||||
if (!builtProto)
|
||||
return BuiltType();
|
||||
|
||||
// Build up a substitution map for the generalized signature.
|
||||
BuiltGenericSignature sig =
|
||||
decodeRuntimeGenericSignature(Shape,
|
||||
Shape->getGeneralizationSignature())
|
||||
.getType();
|
||||
if (!sig)
|
||||
return BuiltType();
|
||||
|
||||
BuiltSubstitutionMap subst =
|
||||
Builder.createSubstitutionMap(sig, builtArgs);
|
||||
if (subst.empty())
|
||||
return BuiltType();
|
||||
|
||||
builtProto = Builder.subst(builtProto, subst);
|
||||
if (!builtProto)
|
||||
return BuiltType();
|
||||
|
||||
// Read the type expression to build up any remaining layers of
|
||||
// existential metatype.
|
||||
if (Shape->Flags.hasTypeExpression()) {
|
||||
Demangler dem;
|
||||
|
||||
// Read the mangled name.
|
||||
auto mangledContextName = Shape->getTypeExpression();
|
||||
auto mangledNameAddress =
|
||||
resolveRelativeField(Shape, mangledContextName->name);
|
||||
auto node =
|
||||
readMangledName(mangledNameAddress, MangledNameKind::Type, dem);
|
||||
if (!node)
|
||||
return BuiltType();
|
||||
|
||||
while (node->getKind() == Demangle::Node::Kind::Type &&
|
||||
node->getNumChildren() &&
|
||||
node->getChild(0)->getKind() == Demangle::Node::Kind::Metatype &&
|
||||
node->getChild(0)->getNumChildren()) {
|
||||
builtProto = Builder.createExistentialMetatypeType(builtProto);
|
||||
node = node->getChild(0)->getChild(0);
|
||||
}
|
||||
}
|
||||
|
||||
auto builtProto = readTypeFromShape(
|
||||
RemoteAddress(shapeAddress),
|
||||
[&](unsigned shapeArgumentCount)
|
||||
-> std::optional<std::vector<BuiltType>> {
|
||||
// Pull out the arguments to the generalization signature.
|
||||
std::vector<BuiltType> builtArgs;
|
||||
for (unsigned i = 0; i < shapeArgumentCount; ++i) {
|
||||
auto remoteArg = Exist->getGeneralizationArguments()[i];
|
||||
auto builtArg = readTypeFromMetadata(
|
||||
remote::RemoteAddress(remoteArg,
|
||||
shapeAddress.getAddressSpace()),
|
||||
false, recursion_limit);
|
||||
if (!builtArg)
|
||||
return std::nullopt;
|
||||
builtArgs.push_back(builtArg);
|
||||
}
|
||||
return builtArgs;
|
||||
});
|
||||
TypeCache[TypeCacheKey] = builtProto;
|
||||
return builtProto;
|
||||
}
|
||||
@@ -1405,51 +1415,51 @@ public:
|
||||
if (!address)
|
||||
return nullptr;
|
||||
|
||||
using ShapeHeader = TargetExtendedExistentialTypeShape<Runtime>;
|
||||
auto cached = ShapeCache.find(address);
|
||||
if (cached != ShapeCache.end())
|
||||
return ShapeRef(address,
|
||||
reinterpret_cast<const TargetExtendedExistentialTypeShape<Runtime> *>(
|
||||
cached->second.get()));
|
||||
return ShapeRef(
|
||||
address, reinterpret_cast<const ShapeHeader *>(cached->second.get()));
|
||||
|
||||
ExtendedExistentialTypeShapeFlags flags;
|
||||
if (!Reader->readBytes(address, (uint8_t *)&flags, sizeof(flags)))
|
||||
return nullptr;
|
||||
|
||||
// Read the size of the requirement signature.
|
||||
uint64_t reqSigGenericSize = 0;
|
||||
uint64_t genericHeaderSize = sizeof(GenericContextDescriptorHeader);
|
||||
uint64_t descriptorSize;
|
||||
{
|
||||
GenericContextDescriptorHeader header;
|
||||
auto headerAddr = address + sizeof(flags);
|
||||
|
||||
if (!Reader->readBytes(headerAddr, (uint8_t *)&header, sizeof(header)))
|
||||
auto readResult =
|
||||
Reader->readBytes(RemoteAddress(address), sizeof(ShapeHeader));
|
||||
if (!readResult)
|
||||
return nullptr;
|
||||
auto shapeHeader =
|
||||
reinterpret_cast<const ShapeHeader *>(readResult.get());
|
||||
|
||||
reqSigGenericSize = reqSigGenericSize
|
||||
+ (header.NumParams + 3u & ~3u)
|
||||
+ header.NumRequirements
|
||||
* sizeof(TargetGenericRequirementDescriptor<Runtime>);
|
||||
// Read the size of the requirement signature.
|
||||
uint64_t reqSigGenericSize = 0;
|
||||
auto flags = shapeHeader->Flags;
|
||||
auto &reqSigHeader = shapeHeader->ReqSigHeader;
|
||||
reqSigGenericSize =
|
||||
reqSigGenericSize + (reqSigHeader.NumParams + 3u & ~3u) +
|
||||
reqSigHeader.NumRequirements *
|
||||
sizeof(TargetGenericRequirementDescriptor<Runtime>);
|
||||
uint64_t typeExprSize =
|
||||
flags.hasTypeExpression() ? sizeof(StoredPointer) : 0;
|
||||
uint64_t suggestedVWSize =
|
||||
flags.hasSuggestedValueWitnesses() ? sizeof(StoredPointer) : 0;
|
||||
|
||||
descriptorSize = sizeof(shapeHeader) + typeExprSize + suggestedVWSize +
|
||||
reqSigGenericSize;
|
||||
}
|
||||
uint64_t typeExprSize = flags.hasTypeExpression() ? sizeof(StoredPointer) : 0;
|
||||
uint64_t suggestedVWSize = flags.hasSuggestedValueWitnesses() ? sizeof(StoredPointer) : 0;
|
||||
|
||||
uint64_t size = sizeof(ExtendedExistentialTypeShapeFlags) +
|
||||
sizeof(TargetRelativeDirectPointer<Runtime, const char,
|
||||
/*nullable*/ false>) +
|
||||
genericHeaderSize + typeExprSize + suggestedVWSize +
|
||||
reqSigGenericSize;
|
||||
if (size > MaxMetadataSize)
|
||||
if (descriptorSize > MaxMetadataSize)
|
||||
return nullptr;
|
||||
auto readResult = Reader->readBytes(address, size);
|
||||
auto readResult = Reader->readBytes(RemoteAddress(address), descriptorSize);
|
||||
if (!readResult)
|
||||
return nullptr;
|
||||
|
||||
auto descriptor =
|
||||
reinterpret_cast<const TargetExtendedExistentialTypeShape<Runtime> *>(
|
||||
readResult.get());
|
||||
auto descriptor = reinterpret_cast<const ShapeHeader *>(readResult.get());
|
||||
|
||||
ShapeCache.insert(
|
||||
std::make_pair(address, std::move(readResult)));
|
||||
ShapeCache.insert(std::make_pair(address, std::move(readResult)));
|
||||
return ShapeRef(address, descriptor);
|
||||
}
|
||||
|
||||
|
||||
@@ -731,6 +731,64 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class SymbolicExtendedExistentialTypeRef final : public TypeRef {
|
||||
const ProtocolCompositionTypeRef *Protocol;
|
||||
std::vector<TypeRefRequirement> Requirements;
|
||||
std::vector<const TypeRef *> Arguments;
|
||||
ExtendedExistentialTypeShapeFlags Flags;
|
||||
|
||||
static TypeRefID Profile(const ProtocolCompositionTypeRef *Protocol,
|
||||
llvm::ArrayRef<TypeRefRequirement> Requirements,
|
||||
llvm::ArrayRef<const TypeRef *> Arguments,
|
||||
ExtendedExistentialTypeShapeFlags Flags) {
|
||||
TypeRefID ID;
|
||||
ID.addPointer(Protocol);
|
||||
for (auto reqt : Requirements) {
|
||||
ID.addPointer(reqt.getFirstType());
|
||||
if (reqt.getKind() != RequirementKind::Layout)
|
||||
ID.addPointer(reqt.getSecondType());
|
||||
else
|
||||
ID.addInteger(
|
||||
unsigned(0)); // FIXME: Layout constraints aren't implemented yet
|
||||
ID.addInteger(unsigned(reqt.getKind()));
|
||||
}
|
||||
|
||||
for (auto &Arg : Arguments)
|
||||
ID.addPointer(Arg);
|
||||
return ID;
|
||||
}
|
||||
|
||||
public:
|
||||
SymbolicExtendedExistentialTypeRef(
|
||||
const ProtocolCompositionTypeRef *Protocol,
|
||||
llvm::ArrayRef<TypeRefRequirement> Requirements,
|
||||
llvm::ArrayRef<const TypeRef *> Args,
|
||||
ExtendedExistentialTypeShapeFlags Flags)
|
||||
: TypeRef(TypeRefKind::SymbolicExtendedExistential), Protocol(Protocol),
|
||||
Requirements(Requirements), Arguments(Args), Flags(Flags) {}
|
||||
|
||||
template <typename Allocator>
|
||||
static const SymbolicExtendedExistentialTypeRef *
|
||||
create(Allocator &A, const ProtocolCompositionTypeRef *Protocol,
|
||||
llvm::ArrayRef<TypeRefRequirement> Requirements,
|
||||
llvm::ArrayRef<const TypeRef *> Args,
|
||||
ExtendedExistentialTypeShapeFlags Flags) {
|
||||
FIND_OR_CREATE_TYPEREF(A, SymbolicExtendedExistentialTypeRef, Protocol,
|
||||
Requirements, Args, Flags);
|
||||
}
|
||||
|
||||
const ProtocolCompositionTypeRef *getProtocol() const { return Protocol; }
|
||||
llvm::ArrayRef<TypeRefRequirement> getRequirements() const {
|
||||
return Requirements;
|
||||
}
|
||||
llvm::ArrayRef<const TypeRef *> getArguments() const { return Arguments; }
|
||||
ExtendedExistentialTypeShapeFlags getFlags() const { return Flags; }
|
||||
|
||||
static bool classof(const TypeRef *TR) {
|
||||
return TR->getKind() == TypeRefKind::SymbolicExtendedExistential;
|
||||
}
|
||||
};
|
||||
|
||||
class MetatypeTypeRef final : public TypeRef {
|
||||
const TypeRef *InstanceType;
|
||||
bool WasAbstract;
|
||||
|
||||
@@ -1113,12 +1113,9 @@ public:
|
||||
// Try to resolve to the underlying type, if we can.
|
||||
if (opaqueDescriptor->getKind() ==
|
||||
Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
|
||||
// FIXME: Node should carry a data structure that can fit a remote
|
||||
// address. For now assume that this is a virtual address.
|
||||
auto [address, space] = opaqueDescriptor->getRemoteAddress();
|
||||
auto underlyingTy = OpaqueUnderlyingTypeReader(
|
||||
remote::RemoteAddress(opaqueDescriptor->getIndex(),
|
||||
remote::RemoteAddress::DefaultAddressSpace),
|
||||
ordinal);
|
||||
remote::RemoteAddress(address, space), ordinal);
|
||||
|
||||
if (!underlyingTy)
|
||||
return nullptr;
|
||||
@@ -1293,8 +1290,28 @@ public:
|
||||
const TypeRef *
|
||||
createSymbolicExtendedExistentialType(NodePointer shapeNode,
|
||||
llvm::ArrayRef<const TypeRef *> args) {
|
||||
// Can't handle this here.
|
||||
return nullptr;
|
||||
// Non-unique shape symbols start with an offset to a cache variable, right
|
||||
// before the shape. Metadata pointers point directly to the shape, but when
|
||||
// reading from a shape symbol, this needs to be corrected.
|
||||
uint32_t offset = 0;
|
||||
if (shapeNode->getKind() ==
|
||||
Node::Kind::NonUniqueExtendedExistentialTypeShapeSymbolicReference)
|
||||
offset = sizeof(uint32_t);
|
||||
auto [address, space] = shapeNode->getRemoteAddress();
|
||||
remote::RemoteAddress shape(address, space);
|
||||
shape += offset;
|
||||
|
||||
return OpaqueShapeReader(
|
||||
shape,
|
||||
[&](unsigned shapeArgumentCount)
|
||||
-> std::optional<std::vector<const TypeRef *>> {
|
||||
if (args.size() != shapeArgumentCount)
|
||||
return std::nullopt;
|
||||
if (llvm::any_of(
|
||||
args, [](const TypeRef *arg) { return !arg->isConcrete(); }))
|
||||
return std::nullopt;
|
||||
return args;
|
||||
});
|
||||
}
|
||||
|
||||
const ExistentialMetatypeTypeRef *createExistentialMetatypeType(
|
||||
@@ -1322,8 +1339,7 @@ public:
|
||||
|
||||
const DependentMemberTypeRef *
|
||||
createDependentMemberType(const std::string &member, const TypeRef *base) {
|
||||
// Should not have unresolved dependent member types here.
|
||||
return nullptr;
|
||||
return DependentMemberTypeRef::create(*this, member, base, "");
|
||||
}
|
||||
|
||||
const DependentMemberTypeRef *
|
||||
@@ -1489,6 +1505,13 @@ private:
|
||||
using PointerReader =
|
||||
std::function<std::optional<remote::RemoteAbsolutePointer>(
|
||||
remote::RemoteAddress, unsigned)>;
|
||||
using ShapeReader = std::function<const TypeRef *(
|
||||
remote::RemoteAbsolutePointer,
|
||||
std::function<std::optional<std::vector<const TypeRef *>>(unsigned)>)>;
|
||||
|
||||
using PointerSymbolResolver =
|
||||
std::function<std::optional<remote::RemoteAbsolutePointer>(
|
||||
remote::RemoteAddress)>;
|
||||
using DynamicSymbolResolver =
|
||||
std::function<std::optional<remote::RemoteAbsolutePointer>(
|
||||
remote::RemoteAddress)>;
|
||||
@@ -1521,6 +1544,8 @@ private:
|
||||
ByteReader OpaqueByteReader;
|
||||
StringReader OpaqueStringReader;
|
||||
PointerReader OpaquePointerReader;
|
||||
ShapeReader OpaqueShapeReader;
|
||||
PointerSymbolResolver OpaquePointerSymbolResolver;
|
||||
DynamicSymbolResolver OpaqueDynamicSymbolResolver;
|
||||
IntVariableReader OpaqueIntVariableReader;
|
||||
|
||||
@@ -1559,6 +1584,18 @@ public:
|
||||
-> std::optional<remote::RemoteAbsolutePointer> {
|
||||
return reader.Reader->readPointer(address, size);
|
||||
}),
|
||||
OpaqueShapeReader(
|
||||
[&reader](remote::RemoteAbsolutePointer pointer,
|
||||
std::function<std::optional<std::vector<const TypeRef *>>(
|
||||
unsigned)>
|
||||
getArgs) -> const TypeRef * {
|
||||
return reader.readTypeFromShape(pointer, getArgs);
|
||||
}),
|
||||
OpaquePointerSymbolResolver(
|
||||
[&reader](remote::RemoteAddress address)
|
||||
-> std::optional<remote::RemoteAbsolutePointer> {
|
||||
return reader.Reader->resolvePointerAsSymbol(address);
|
||||
}),
|
||||
OpaqueDynamicSymbolResolver(
|
||||
[&reader](remote::RemoteAddress address)
|
||||
-> std::optional<remote::RemoteAbsolutePointer> {
|
||||
@@ -1710,9 +1747,10 @@ public:
|
||||
Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
|
||||
// FIXME: Node should carry a data structure that can fit a remote
|
||||
// address. For now assume that this is a process address.
|
||||
auto [address, space] =
|
||||
opaqueTypeChildDemangleTree->getRemoteAddress();
|
||||
extractOpaqueTypeProtocolRequirements<ObjCInteropKind, PointerSize>(
|
||||
remote::RemoteAddress(opaqueTypeChildDemangleTree->getIndex(),
|
||||
remote::RemoteAddress::DefaultAddressSpace),
|
||||
remote::RemoteAddress(address, space),
|
||||
opaqueTypeConformanceRequirements, sameTypeRequirements);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ TYPEREF(Tuple, TypeRef)
|
||||
TYPEREF(Function, TypeRef)
|
||||
TYPEREF(ProtocolComposition, TypeRef)
|
||||
TYPEREF(ConstrainedExistential, TypeRef)
|
||||
TYPEREF(SymbolicExtendedExistential, TypeRef)
|
||||
TYPEREF(Metatype, TypeRef)
|
||||
TYPEREF(ExistentialMetatype, TypeRef)
|
||||
TYPEREF(GenericTypeParameter, TypeRef)
|
||||
|
||||
@@ -791,7 +791,9 @@ Type ASTBuilder::createConstrainedExistentialType(
|
||||
if (auto *memberTy = req.getFirstType()->getAs<DependentMemberType>()) {
|
||||
if (memberTy->getBase()->is<GenericTypeParamType>()) {
|
||||
// This is the only case we understand so far.
|
||||
primaryAssociatedTypes[memberTy->getAssocType()] = req.getSecondType();
|
||||
if (auto *assocTy = memberTy->getAssocType())
|
||||
primaryAssociatedTypes[assocTy] = req.getSecondType();
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -809,10 +811,11 @@ Type ASTBuilder::createConstrainedExistentialType(
|
||||
llvm::SmallVector<Type, 4> args;
|
||||
for (auto *assocTy : proto->getPrimaryAssociatedTypes()) {
|
||||
auto found = primaryAssociatedTypes.find(assocTy);
|
||||
if (found == primaryAssociatedTypes.end())
|
||||
return protoTy;
|
||||
args.push_back(found->second);
|
||||
claimed.insert(found->first);
|
||||
if (found != primaryAssociatedTypes.end()) {
|
||||
args.push_back(found->second);
|
||||
claimed.insert(found->first);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// We may not have any arguments because the constrained existential is a
|
||||
|
||||
@@ -601,6 +601,11 @@ NodePointer NodeFactory::createNode(Node::Kind K) {
|
||||
NodePointer NodeFactory::createNode(Node::Kind K, Node::IndexType Index) {
|
||||
return new (Allocate<Node>()) Node(K, Index);
|
||||
}
|
||||
NodePointer NodeFactory::createNode(Node::Kind K, uint64_t RemoteAddress,
|
||||
uint8_t AddressSpace) {
|
||||
return new (Allocate<Node>()) Node(K, RemoteAddress, AddressSpace);
|
||||
}
|
||||
|
||||
NodePointer NodeFactory::createNodeWithAllocatedText(Node::Kind K,
|
||||
llvm::StringRef Text) {
|
||||
return new (Allocate<Node>()) Node(K, Text);
|
||||
|
||||
@@ -1153,6 +1153,7 @@ class ExistentialTypeInfoBuilder {
|
||||
TypeConverter &TC;
|
||||
std::vector<const TypeRef *> Protocols;
|
||||
const TypeRef *Superclass = nullptr;
|
||||
remote::RemoteAbsolutePointer Shape;
|
||||
ExistentialTypeRepresentation Representation;
|
||||
ReferenceCounting Refcounting;
|
||||
bool ObjC;
|
||||
@@ -1320,6 +1321,24 @@ public:
|
||||
Representation = ExistentialTypeRepresentation::Class;
|
||||
}
|
||||
|
||||
void addShape(const ProtocolCompositionTypeRef *Protocol,
|
||||
ExtendedExistentialTypeShapeFlags Flags) {
|
||||
switch (Flags.getSpecialKind()) {
|
||||
case ExtendedExistentialTypeShapeFlags::SpecialKind::Class:
|
||||
Representation = ExistentialTypeRepresentation::Class;
|
||||
break;
|
||||
case ExtendedExistentialTypeShapeFlags::SpecialKind::Metatype:
|
||||
case ExtendedExistentialTypeShapeFlags::SpecialKind::ExplicitLayout:
|
||||
case ExtendedExistentialTypeShapeFlags::SpecialKind::None:
|
||||
Representation = ExistentialTypeRepresentation::Opaque;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Protocol)
|
||||
for (auto *Protocol : Protocol->getProtocols())
|
||||
addProtocol(Protocol);
|
||||
}
|
||||
|
||||
const TypeInfo *build(remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
examineProtocols();
|
||||
|
||||
@@ -1779,6 +1798,11 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visitSymbolicExtendedExistentialTypeRef(
|
||||
const SymbolicExtendedExistentialTypeRef *SEET) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
visitSILBoxTypeRef(const SILBoxTypeRef *SB) {
|
||||
return true;
|
||||
@@ -1922,6 +1946,11 @@ public:
|
||||
return MetatypeRepresentation::Thin;
|
||||
}
|
||||
|
||||
MetatypeRepresentation visitSymbolicExtendedExistentialTypeRef(
|
||||
const SymbolicExtendedExistentialTypeRef *SEET) {
|
||||
return MetatypeRepresentation::Thin;
|
||||
}
|
||||
|
||||
MetatypeRepresentation visitMetatypeTypeRef(const MetatypeTypeRef *M) {
|
||||
if (M->wasAbstract())
|
||||
return MetatypeRepresentation::Thick;
|
||||
@@ -2519,6 +2548,13 @@ public:
|
||||
return builder.buildMetatype(ExternalTypeInfo);
|
||||
}
|
||||
|
||||
const TypeInfo *visitSymbolicExtendedExistentialTypeRef(
|
||||
const SymbolicExtendedExistentialTypeRef *SEET) {
|
||||
ExistentialTypeInfoBuilder builder(TC);
|
||||
builder.addShape(SEET->getProtocol(), SEET->getFlags());
|
||||
return builder.build(ExternalTypeInfo);
|
||||
}
|
||||
|
||||
const TypeInfo *
|
||||
visitGenericTypeParameterTypeRef(const GenericTypeParameterTypeRef *GTP) {
|
||||
DEBUG_LOG(fprintf(stderr, "Unresolved generic TypeRef: "); GTP->dump());
|
||||
|
||||
@@ -289,6 +289,15 @@ public:
|
||||
stream << ")";
|
||||
}
|
||||
|
||||
void visitSymbolicExtendedExistentialTypeRef(
|
||||
const SymbolicExtendedExistentialTypeRef *CET) {
|
||||
printHeader("symbolic_extended_existential_type");
|
||||
printRec(CET->getProtocol());
|
||||
for (auto &arg : CET->getArguments())
|
||||
printRec(arg);
|
||||
stream << ")";
|
||||
}
|
||||
|
||||
void visitMetatypeTypeRef(const MetatypeTypeRef *M) {
|
||||
printHeader("metatype");
|
||||
if (M->wasAbstract())
|
||||
@@ -513,6 +522,15 @@ struct TypeRefIsConcrete
|
||||
return visit(CET->getBase());
|
||||
}
|
||||
|
||||
bool visitSymbolicExtendedExistentialTypeRef(
|
||||
const SymbolicExtendedExistentialTypeRef *SEET) {
|
||||
visit(SEET->getProtocol());
|
||||
for (auto &Arg : SEET->getArguments())
|
||||
if (!visit(Arg))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visitMetatypeTypeRef(const MetatypeTypeRef *M) {
|
||||
return visit(M->getInstanceType());
|
||||
}
|
||||
@@ -952,6 +970,19 @@ public:
|
||||
return node;
|
||||
}
|
||||
|
||||
Demangle::NodePointer visitSymbolicExtendedExistentialTypeRef(
|
||||
const SymbolicExtendedExistentialTypeRef *SEET) {
|
||||
auto node = Dem.createNode(Node::Kind::ConstrainedExistential);
|
||||
node->addChild(visit(SEET->getProtocol()), Dem);
|
||||
auto constraintList =
|
||||
Dem.createNode(Node::Kind::ConstrainedExistentialRequirementList);
|
||||
for (auto req : SEET->getRequirements())
|
||||
constraintList->addChild(visitTypeRefRequirement(req), Dem);
|
||||
node->addChild(constraintList, Dem);
|
||||
// FIXME: This is lossy. We're dropping the Arguments here.
|
||||
return node;
|
||||
}
|
||||
|
||||
Demangle::NodePointer visitMetatypeTypeRef(const MetatypeTypeRef *M) {
|
||||
auto node = Dem.createNode(Node::Kind::Metatype);
|
||||
// FIXME: This is lossy. @objc_metatype is also abstract.
|
||||
@@ -1354,6 +1385,11 @@ public:
|
||||
CET->getRequirements());
|
||||
}
|
||||
|
||||
const TypeRef *visitSymbolicExtendedExistentialTypeRef(
|
||||
const SymbolicExtendedExistentialTypeRef *SEET) {
|
||||
return SEET;
|
||||
}
|
||||
|
||||
const TypeRef *visitMetatypeTypeRef(const MetatypeTypeRef *M) {
|
||||
return MetatypeTypeRef::create(Builder, visit(M->getInstanceType()),
|
||||
/*WasAbstract=*/true);
|
||||
@@ -1641,6 +1677,27 @@ public:
|
||||
constraints);
|
||||
}
|
||||
|
||||
const TypeRef *visitSymbolicExtendedExistentialTypeRef(
|
||||
const SymbolicExtendedExistentialTypeRef *SEET) {
|
||||
std::vector<TypeRefRequirement> reqs;
|
||||
for (auto &req : SEET->getRequirements()) {
|
||||
auto substReq = visitTypeRefRequirement(req);
|
||||
if (!substReq)
|
||||
continue;
|
||||
reqs.emplace_back(*substReq);
|
||||
}
|
||||
|
||||
std::vector<const TypeRef *> args;
|
||||
for (auto *arg : SEET->getArguments()) {
|
||||
auto *substArg = visit(arg);
|
||||
if (!substArg)
|
||||
return nullptr;
|
||||
args.push_back(substArg);
|
||||
}
|
||||
return SymbolicExtendedExistentialTypeRef::create(
|
||||
Builder, SEET->getProtocol(), reqs, args, SEET->getFlags());
|
||||
}
|
||||
|
||||
const TypeRef *
|
||||
visitGenericTypeParameterTypeRef(const GenericTypeParameterTypeRef *GTP) {
|
||||
auto found = Substitutions.find({GTP->getDepth(), GTP->getIndex()});
|
||||
|
||||
Reference in New Issue
Block a user