Skip to content

Commit 23886ba

Browse files
committed
[Metadata reader] Form demangle trees for generic extension contexts.
Translate the metadata for the generic requirements of an extension context into a demangle tree that is associated with the demangling of an extension. Teach the ASTDemangler how to handle class layout constraints as well. With this, RemoteAST can resolve types nested within most constrained extensions.
1 parent ff68796 commit 23886ba

File tree

4 files changed

+267
-10
lines changed

4 files changed

+267
-10
lines changed

include/swift/ABI/Metadata.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,10 +1547,10 @@ class TargetProtocolDescriptorRef {
15471547
/// is clear).
15481548
StoredPointer storage;
15491549

1550+
public:
15501551
constexpr TargetProtocolDescriptorRef(StoredPointer storage)
15511552
: storage(storage) { }
15521553

1553-
public:
15541554
constexpr TargetProtocolDescriptorRef() : storage() { }
15551555

15561556
TargetProtocolDescriptorRef(
@@ -2519,7 +2519,6 @@ class TargetGenericRequirementDescriptor {
25192519
/// The type that's constrained, described as a mangled name.
25202520
RelativeDirectPointer<const char, /*nullable*/ false> Param;
25212521

2522-
private:
25232522
union {
25242523
/// A mangled representation of the same-type or base class the param is
25252524
/// constrained to.
@@ -2544,7 +2543,6 @@ class TargetGenericRequirementDescriptor {
25442543
GenericRequirementLayoutKind Layout;
25452544
};
25462545

2547-
public:
25482546
constexpr GenericRequirementFlags getFlags() const {
25492547
return Flags;
25502548
}

include/swift/Remote/MetadataReader.h

Lines changed: 173 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,6 +1655,48 @@ class MetadataReader {
16551655
return nameChild;
16561656
}
16571657

1658+
/// Resolve a relative target protocol descriptor pointer, which uses
1659+
/// the lowest bit to indicate an indirect vs. direct relative reference and
1660+
/// the second lowest bit to indicate whether it is an Objective-C protocol.
1661+
StoredPointer resolveRelativeIndirectProtocol(
1662+
ContextDescriptorRef descriptor,
1663+
const RelativeTargetProtocolDescriptorPointer<Runtime> &protocol) {
1664+
// Map the offset from within our local buffer to the remote address.
1665+
auto distance = (intptr_t)&protocol - (intptr_t)descriptor.getLocalBuffer();
1666+
StoredPointer targetAddress(descriptor.getAddress() + distance);
1667+
1668+
// Read the relative offset.
1669+
int32_t relative;
1670+
if (!Reader->readInteger(RemoteAddress(targetAddress), &relative))
1671+
return StoredPointer();
1672+
1673+
// Collect and mask off the 'indirect' and 'isObjC' bits.
1674+
bool indirect = relative & 1;
1675+
relative &= ~1u;
1676+
bool isObjC = relative & 2;
1677+
relative &= ~2u;
1678+
1679+
using SignedPointer = typename std::make_signed<StoredPointer>::type;
1680+
auto signext = (SignedPointer)(int32_t)relative;
1681+
1682+
StoredPointer resultAddress = targetAddress + signext;
1683+
1684+
// Low bit set in the offset indicates that the offset leads to the absolute
1685+
// address in memory.
1686+
if (indirect) {
1687+
if (!Reader->readBytes(RemoteAddress(resultAddress),
1688+
(uint8_t *)&resultAddress,
1689+
sizeof(StoredPointer)))
1690+
return StoredPointer();
1691+
}
1692+
1693+
// Add back the Objective-C bit.
1694+
if (isObjC)
1695+
resultAddress |= 0x1;
1696+
1697+
return resultAddress;
1698+
}
1699+
16581700
Demangle::NodePointer
16591701
buildContextDescriptorMangling(ContextDescriptorRef descriptor,
16601702
Demangler &dem) {
@@ -1748,14 +1790,141 @@ class MetadataReader {
17481790
MangledNameKind::Type,
17491791
dem);
17501792

1751-
// FIXME: If there are generic requirements, turn them into a demangle
1752-
// tree.
17531793
auto demangling = dem.createNode(Node::Kind::Extension);
17541794
demangling->addChild(parentDemangling, dem);
17551795
demangling->addChild(demangledExtendedContext, dem);
1756-
return demangling;
17571796

1758-
return nullptr;
1797+
/// Resolver to turn a protocol reference into a demangling.
1798+
struct ProtocolResolver {
1799+
using Result = Demangle::Node *;
1800+
1801+
Demangler &dem;
1802+
1803+
Result failure() const {
1804+
return nullptr;
1805+
}
1806+
1807+
Result swiftProtocol(Demangle::Node *node) {
1808+
return node;
1809+
}
1810+
1811+
#if SWIFT_OBJC_INTEROP
1812+
Result objcProtocol(StringRef name) {
1813+
// FIXME: Unify this with the runtime's Demangle.cpp
1814+
auto module = dem.createNode(Node::Kind::Module,
1815+
MANGLING_MODULE_OBJC);
1816+
auto node = dem.createNode(Node::Kind::Protocol);
1817+
node->addChild(module, dem);
1818+
node->addChild(dem.createNode(Node::Kind::Identifier, name),
1819+
dem);
1820+
return node;
1821+
}
1822+
#endif
1823+
} protocolResolver{dem};
1824+
1825+
// If there are generic requirements, form the generic signature.
1826+
auto requirements = extensionBuffer->getGenericRequirements();
1827+
if (!requirements.empty()) {
1828+
auto signatureNode =
1829+
dem.createNode(Node::Kind::DependentGenericSignature);
1830+
bool failed = false;
1831+
for (const auto &req : requirements) {
1832+
if (failed)
1833+
break;
1834+
1835+
// Demangle the subject.
1836+
auto subjectAddress = resolveRelativeField(descriptor, req.Param);
1837+
NodePointer subject = readMangledName(RemoteAddress(subjectAddress),
1838+
MangledNameKind::Type,
1839+
dem);
1840+
if (!subject) {
1841+
failed = true;
1842+
break;
1843+
}
1844+
1845+
switch (req.Flags.getKind()) {
1846+
case GenericRequirementKind::Protocol: {
1847+
auto protocolAddress =
1848+
resolveRelativeIndirectProtocol(descriptor, req.Protocol);
1849+
auto protocol = readProtocol(protocolAddress, dem,
1850+
protocolResolver);
1851+
if (!protocol) {
1852+
failed = true;
1853+
break;
1854+
}
1855+
1856+
auto reqNode =
1857+
dem.createNode(
1858+
Node::Kind::DependentGenericConformanceRequirement);
1859+
reqNode->addChild(subject, dem);
1860+
reqNode->addChild(protocol, dem);
1861+
signatureNode->addChild(reqNode, dem);
1862+
break;
1863+
}
1864+
1865+
case GenericRequirementKind::SameType:
1866+
case GenericRequirementKind::BaseClass: {
1867+
// Demangle the right-hand type.
1868+
auto typeAddress = resolveRelativeField(descriptor, req.Type);
1869+
NodePointer type = readMangledName(RemoteAddress(typeAddress),
1870+
MangledNameKind::Type,
1871+
dem);
1872+
if (!type) {
1873+
failed = true;
1874+
break;
1875+
}
1876+
1877+
Node::Kind nodeKind;
1878+
if (req.Flags.getKind() == GenericRequirementKind::SameType)
1879+
nodeKind = Node::Kind::DependentGenericSameTypeRequirement;
1880+
else
1881+
nodeKind = Node::Kind::DependentGenericConformanceRequirement;
1882+
1883+
auto reqNode = dem.createNode(nodeKind);
1884+
reqNode->addChild(subject, dem);
1885+
reqNode->addChild(type, dem);
1886+
signatureNode->addChild(reqNode, dem);
1887+
break;
1888+
}
1889+
1890+
case GenericRequirementKind::SameConformance:
1891+
// Do nothing
1892+
break;
1893+
1894+
case GenericRequirementKind::Layout: {
1895+
// Map the offset from within our local buffer to the remote
1896+
// address.
1897+
auto distance =
1898+
(intptr_t)&req.Layout - (intptr_t)descriptor.getLocalBuffer();
1899+
StoredPointer targetAddress(descriptor.getAddress() + distance);
1900+
1901+
GenericRequirementLayoutKind kind;
1902+
if (!Reader->readBytes(RemoteAddress(targetAddress),
1903+
(uint8_t *)&kind, sizeof(kind))) {
1904+
failed = true;
1905+
break;
1906+
}
1907+
1908+
if (kind == GenericRequirementLayoutKind::Class) {
1909+
auto reqNode =
1910+
dem.createNode(Node::Kind::DependentGenericLayoutRequirement);
1911+
reqNode->addChild(subject, dem);
1912+
auto idNode = dem.createNode(Node::Kind::Identifier, "C");
1913+
reqNode->addChild(idNode, dem);
1914+
signatureNode->addChild(reqNode, dem);
1915+
} else {
1916+
failed = true;
1917+
}
1918+
break;
1919+
}
1920+
}
1921+
}
1922+
1923+
if (!failed) {
1924+
demangling->addChild(signatureNode, dem);
1925+
}
1926+
}
1927+
return demangling;
17591928
}
17601929

17611930
case ContextDescriptorKind::Anonymous: {

lib/AST/ASTDemangler.cpp

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -531,11 +531,20 @@ CanGenericSignature ASTBuilder::demangleGenericSignature(
531531
return CanGenericSignature();
532532
auto subjectType = swift::Demangle::decodeMangledType(
533533
*this, child->getChild(0));
534-
auto constraintType = swift::Demangle::decodeMangledType(
535-
*this, child->getChild(1));
536-
if (!subjectType || !constraintType)
534+
if (!subjectType)
537535
return CanGenericSignature();
538536

537+
Type constraintType;
538+
if (child->getKind() ==
539+
Demangle::Node::Kind::DependentGenericConformanceRequirement ||
540+
child->getKind() ==
541+
Demangle::Node::Kind::DependentGenericSameTypeRequirement) {
542+
constraintType = swift::Demangle::decodeMangledType(
543+
*this, child->getChild(1));
544+
if (!constraintType)
545+
return CanGenericSignature();
546+
}
547+
539548
auto source =
540549
GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
541550

@@ -556,6 +565,24 @@ CanGenericSignature ASTBuilder::demangleGenericSignature(
556565
source, nullptr);
557566
break;
558567
}
568+
case Demangle::Node::Kind::DependentGenericLayoutRequirement: {
569+
// FIXME: Other layout constraints
570+
LayoutConstraint constraint;
571+
auto kindChild = child->getChild(1);
572+
if (kindChild->getKind() != Demangle::Node::Kind::Identifier)
573+
return CanGenericSignature();
574+
575+
if (kindChild->getText() == "C") {
576+
auto kind = LayoutConstraintKind::Class;
577+
auto layout = LayoutConstraint::getLayoutConstraint(kind, Ctx);
578+
builder.addRequirement(
579+
Requirement(RequirementKind::Layout, subjectType, layout),
580+
source, nullptr);
581+
break;
582+
}
583+
584+
return CanGenericSignature();
585+
}
559586
default:
560587
return CanGenericSignature();
561588
}
@@ -570,6 +597,11 @@ ASTBuilder::findDeclContext(const Demangle::NodePointer &node) {
570597
switch (node->getKind()) {
571598
case Demangle::Node::Kind::DeclContext:
572599
case Demangle::Node::Kind::Type:
600+
case Demangle::Node::Kind::BoundGenericClass:
601+
case Demangle::Node::Kind::BoundGenericEnum:
602+
case Demangle::Node::Kind::BoundGenericProtocol:
603+
case Demangle::Node::Kind::BoundGenericStructure:
604+
case Demangle::Node::Kind::BoundGenericTypeAlias:
573605
return findDeclContext(node->getFirstChild());
574606

575607
case Demangle::Node::Kind::Module:

test/RemoteAST/extensions.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,61 @@ extension Int.Inner {
1818

1919
// CHECK: Int.Inner.MoreInner
2020
printType(Int.Inner.MoreInner.self)
21+
22+
protocol P {
23+
associatedtype Assoc
24+
}
25+
26+
struct A<T: P, U: P> { }
27+
28+
extension Int: P {
29+
typealias Assoc = Double
30+
}
31+
32+
extension String: P {
33+
typealias Assoc = Double
34+
}
35+
36+
extension A where T.Assoc == U.Assoc {
37+
struct ViaSameType { }
38+
}
39+
40+
// CHECK: A<Int, String>.ViaSameType
41+
printType(A<Int, String>.ViaSameType.self)
42+
43+
protocol Q { }
44+
extension Int: Q { }
45+
46+
extension A where T: Q {
47+
struct ViaProtocolConformance { }
48+
}
49+
50+
// CHECK: A<Int, String>.ViaProtocolConformance
51+
printType(A<Int, String>.ViaProtocolConformance.self)
52+
53+
class B { }
54+
55+
class C: B { }
56+
57+
extension B: P {
58+
typealias Assoc = Int
59+
}
60+
61+
extension A where U: B {
62+
struct ViaBaseClass { }
63+
}
64+
65+
// CHECK: A<Int, B>.ViaBaseClass
66+
printType(A<Int, B>.ViaBaseClass.self)
67+
68+
// CHECK: A<Int, C>.ViaBaseClass
69+
printType(A<Int, C>.ViaBaseClass.self)
70+
71+
extension A where T: AnyObject {
72+
struct ViaAnyObject {
73+
func wobble() {}
74+
}
75+
}
76+
77+
// CHECK: A<C, Int>.ViaAnyObject
78+
printType(A<C, Int>.ViaAnyObject.self)

0 commit comments

Comments
 (0)