Skip to content

Commit 15214b3

Browse files
authored
Merge pull request swiftlang#19483 from DougGregor/runtime-demangle-fixes
[Runtime] Fixes for demangling to metadata
2 parents a62ebd9 + 298458a commit 15214b3

13 files changed

+172
-161
lines changed

docs/ABI/Mangling.rst

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Globals
6464
global ::= context 'MXE' // extension descriptor
6565
global ::= context 'MXX' // anonymous context descriptor
6666
global ::= context identifier 'MXY' // anonymous context descriptor
67-
global ::= type assoc_type_path 'MXA' // generic parameter ref
67+
global ::= type assoc-type-list 'MXA' // generic parameter ref
6868
global ::= protocol 'Mp' // protocol descriptor
6969

7070
global ::= nominal-type 'Mo' // class metadata immediate member base offset
@@ -91,15 +91,13 @@ Globals
9191
global ::= type protocol-conformance 'WL' // lazy protocol witness table cache variable
9292

9393
global ::= protocol-conformance identifier 'Wt' // associated type metadata accessor
94-
global ::= protocol-conformance assoc_type_path nominal-type 'WT' // associated type witness table accessor
94+
global ::= protocol-conformance assoc-type-list nominal-type 'WT' // associated type witness table accessor
9595
global ::= type protocol-conformance 'Wl' // lazy protocol witness table accessor
9696

9797
global ::= type 'WV' // value witness table
9898
global ::= entity 'Wvd' // field offset
9999
global ::= entity 'WC' // resilient enum tag index
100100

101-
assoc_type_path ::= identifier '_' identifier*
102-
103101
A direct symbol resolves directly to the address of an object. An
104102
indirect symbol resolves to the address of a pointer to the object.
105103
They are distinct manglings to make a certain class of bugs

lib/Demangling/Demangler.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,10 +1666,10 @@ NodePointer Demangler::popAssocTypePath() {
16661666
bool firstElem = false;
16671667
do {
16681668
firstElem = (popNode(Node::Kind::FirstElementMarker) != nullptr);
1669-
NodePointer AssocTyName = popNode(isDeclName);
1670-
if (!AssocTyName)
1669+
NodePointer AssocTy = popAssocTypeName();
1670+
if (!AssocTy)
16711671
return nullptr;
1672-
AssocTypePath->addChild(AssocTyName, *this);
1672+
AssocTypePath->addChild(AssocTy, *this);
16731673
} while (!firstElem);
16741674
AssocTypePath->reverseChildren();
16751675
return AssocTypePath;

lib/IRGen/GenDecl.cpp

Lines changed: 0 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -2453,135 +2453,6 @@ llvm::Constant *IRGenModule::emitSwiftProtocols() {
24532453
return var;
24542454
}
24552455

2456-
namespace {
2457-
/// Builds a protocol conformance descriptor.
2458-
class ProtocolConformanceDescriptorBuilder {
2459-
IRGenModule &IGM;
2460-
ConstantStructBuilder &B;
2461-
const NormalProtocolConformance *Conformance;
2462-
ConformanceFlags Flags;
2463-
2464-
public:
2465-
ProtocolConformanceDescriptorBuilder(
2466-
IRGenModule &IGM,
2467-
ConstantStructBuilder &B,
2468-
const NormalProtocolConformance *conformance)
2469-
: IGM(IGM), B(B), Conformance(conformance) { }
2470-
2471-
void layout() {
2472-
addProtocol();
2473-
addConformingType();
2474-
addWitnessTable();
2475-
addFlags();
2476-
addContext();
2477-
addConditionalRequirements();
2478-
2479-
B.suggestType(IGM.ProtocolConformanceDescriptorTy);
2480-
}
2481-
2482-
void addProtocol() {
2483-
// Relative reference to the protocol descriptor.
2484-
auto protocol = Conformance->getProtocol();
2485-
auto descriptorRef = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
2486-
LinkEntity::forProtocolDescriptor(protocol),
2487-
IGM.getPointerAlignment(), IGM.ProtocolDescriptorStructTy);
2488-
B.addRelativeAddress(descriptorRef);
2489-
}
2490-
2491-
void addConformingType() {
2492-
// Add a relative reference to the type, with the type reference
2493-
// kind stored in the flags.
2494-
auto ref =
2495-
IGM.getTypeEntityReference(Conformance->getType()->getAnyNominal());
2496-
B.addRelativeAddress(ref.getValue());
2497-
Flags = Flags.withTypeReferenceKind(ref.getKind());
2498-
}
2499-
2500-
void addWitnessTable() {
2501-
using ConformanceKind = ConformanceFlags::ConformanceKind;
2502-
2503-
// Figure out what kind of witness table we have.
2504-
llvm::Constant *witnessTableVar;
2505-
2506-
if (Conformance->getConditionalRequirements().empty()) {
2507-
if (!isDependentConformance(Conformance) &&
2508-
!Conformance->isSynthesizedNonUnique()) {
2509-
Flags = Flags.withConformanceKind(ConformanceKind::WitnessTable);
2510-
witnessTableVar = IGM.getAddrOfWitnessTable(Conformance);
2511-
} else {
2512-
Flags = Flags.withConformanceKind(
2513-
ConformanceKind::WitnessTableAccessor);
2514-
witnessTableVar = IGM.getAddrOfWitnessTableAccessFunction(
2515-
Conformance, ForDefinition);
2516-
}
2517-
} else {
2518-
Flags =
2519-
Flags.withConformanceKind(
2520-
ConformanceKind::ConditionalWitnessTableAccessor)
2521-
.withNumConditionalRequirements(
2522-
Conformance->getConditionalRequirements().size());
2523-
2524-
witnessTableVar = IGM.getAddrOfWitnessTableAccessFunction(
2525-
Conformance, ForDefinition);
2526-
}
2527-
2528-
// Relative reference to the witness table.
2529-
auto witnessTableRef =
2530-
ConstantReference(witnessTableVar, ConstantReference::Direct);
2531-
B.addRelativeAddress(witnessTableRef);
2532-
}
2533-
2534-
void addFlags() {
2535-
// Miscellaneous flags.
2536-
Flags = Flags.withIsRetroactive(Conformance->isRetroactive());
2537-
Flags =
2538-
Flags.withIsSynthesizedNonUnique(Conformance->isSynthesizedNonUnique());
2539-
2540-
// Add the flags.
2541-
B.addInt32(Flags.getIntValue());
2542-
}
2543-
2544-
void addContext() {
2545-
if (!Conformance->isRetroactive())
2546-
return;
2547-
2548-
auto moduleContext =
2549-
Conformance->getDeclContext()->getModuleScopeContext();
2550-
ConstantReference moduleContextRef =
2551-
IGM.getAddrOfParentContextDescriptor(moduleContext);
2552-
B.addRelativeAddress(moduleContextRef);
2553-
}
2554-
2555-
void addConditionalRequirements() {
2556-
if (Conformance->getConditionalRequirements().empty())
2557-
return;
2558-
2559-
auto nominal = Conformance->getType()->getAnyNominal();
2560-
irgen::addGenericRequirements(IGM, B,
2561-
nominal->getGenericSignatureOfContext(),
2562-
Conformance->getConditionalRequirements());
2563-
}
2564-
};
2565-
}
2566-
2567-
void IRGenModule::emitProtocolConformance(
2568-
const NormalProtocolConformance *conformance) {
2569-
// Emit additional metadata to be used by reflection.
2570-
emitAssociatedTypeMetadataRecord(conformance);
2571-
2572-
// Form the protocol conformance descriptor.
2573-
ConstantInitBuilder initBuilder(*this);
2574-
auto init = initBuilder.beginStruct();
2575-
ProtocolConformanceDescriptorBuilder builder(*this, init, conformance);
2576-
builder.layout();
2577-
2578-
auto var =
2579-
cast<llvm::GlobalVariable>(
2580-
getAddrOfProtocolConformanceDescriptor(conformance,
2581-
init.finishAndCreateFuture()));
2582-
var->setConstant(true);
2583-
}
2584-
25852456
void IRGenModule::addProtocolConformance(
25862457
const NormalProtocolConformance *conformance) {
25872458
// Add this protocol conformance.

lib/IRGen/GenProto.cpp

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2196,6 +2196,135 @@ llvm::Constant *WitnessTableBuilder::buildInstantiationFunction() {
21962196
return fn;
21972197
}
21982198

2199+
namespace {
2200+
/// Builds a protocol conformance descriptor.
2201+
class ProtocolConformanceDescriptorBuilder {
2202+
IRGenModule &IGM;
2203+
ConstantStructBuilder &B;
2204+
const NormalProtocolConformance *Conformance;
2205+
ConformanceFlags Flags;
2206+
2207+
public:
2208+
ProtocolConformanceDescriptorBuilder(
2209+
IRGenModule &IGM,
2210+
ConstantStructBuilder &B,
2211+
const NormalProtocolConformance *conformance)
2212+
: IGM(IGM), B(B), Conformance(conformance) { }
2213+
2214+
void layout() {
2215+
addProtocol();
2216+
addConformingType();
2217+
addWitnessTable();
2218+
addFlags();
2219+
addContext();
2220+
addConditionalRequirements();
2221+
2222+
B.suggestType(IGM.ProtocolConformanceDescriptorTy);
2223+
}
2224+
2225+
void addProtocol() {
2226+
// Relative reference to the protocol descriptor.
2227+
auto protocol = Conformance->getProtocol();
2228+
auto descriptorRef = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
2229+
LinkEntity::forProtocolDescriptor(protocol),
2230+
IGM.getPointerAlignment(), IGM.ProtocolDescriptorStructTy);
2231+
B.addRelativeAddress(descriptorRef);
2232+
}
2233+
2234+
void addConformingType() {
2235+
// Add a relative reference to the type, with the type reference
2236+
// kind stored in the flags.
2237+
auto ref =
2238+
IGM.getTypeEntityReference(Conformance->getType()->getAnyNominal());
2239+
B.addRelativeAddress(ref.getValue());
2240+
Flags = Flags.withTypeReferenceKind(ref.getKind());
2241+
}
2242+
2243+
void addWitnessTable() {
2244+
using ConformanceKind = ConformanceFlags::ConformanceKind;
2245+
2246+
// Figure out what kind of witness table we have.
2247+
llvm::Constant *witnessTableVar;
2248+
2249+
if (Conformance->getConditionalRequirements().empty()) {
2250+
if (!isDependentConformance(Conformance) &&
2251+
!Conformance->isSynthesizedNonUnique()) {
2252+
Flags = Flags.withConformanceKind(ConformanceKind::WitnessTable);
2253+
witnessTableVar = IGM.getAddrOfWitnessTable(Conformance);
2254+
} else {
2255+
Flags = Flags.withConformanceKind(
2256+
ConformanceKind::WitnessTableAccessor);
2257+
witnessTableVar = IGM.getAddrOfWitnessTableAccessFunction(
2258+
Conformance, ForDefinition);
2259+
}
2260+
} else {
2261+
Flags =
2262+
Flags.withConformanceKind(
2263+
ConformanceKind::ConditionalWitnessTableAccessor)
2264+
.withNumConditionalRequirements(
2265+
Conformance->getConditionalRequirements().size());
2266+
2267+
witnessTableVar = IGM.getAddrOfWitnessTableAccessFunction(
2268+
Conformance, ForDefinition);
2269+
}
2270+
2271+
// Relative reference to the witness table.
2272+
auto witnessTableRef =
2273+
ConstantReference(witnessTableVar, ConstantReference::Direct);
2274+
B.addRelativeAddress(witnessTableRef);
2275+
}
2276+
2277+
void addFlags() {
2278+
// Miscellaneous flags.
2279+
Flags = Flags.withIsRetroactive(Conformance->isRetroactive());
2280+
Flags =
2281+
Flags.withIsSynthesizedNonUnique(Conformance->isSynthesizedNonUnique());
2282+
2283+
// Add the flags.
2284+
B.addInt32(Flags.getIntValue());
2285+
}
2286+
2287+
void addContext() {
2288+
if (!Conformance->isRetroactive())
2289+
return;
2290+
2291+
auto moduleContext =
2292+
Conformance->getDeclContext()->getModuleScopeContext();
2293+
ConstantReference moduleContextRef =
2294+
IGM.getAddrOfParentContextDescriptor(moduleContext);
2295+
B.addRelativeAddress(moduleContextRef);
2296+
}
2297+
2298+
void addConditionalRequirements() {
2299+
if (Conformance->getConditionalRequirements().empty())
2300+
return;
2301+
2302+
auto nominal = Conformance->getType()->getAnyNominal();
2303+
irgen::addGenericRequirements(IGM, B,
2304+
nominal->getGenericSignatureOfContext(),
2305+
Conformance->getConditionalRequirements());
2306+
}
2307+
};
2308+
}
2309+
2310+
void IRGenModule::emitProtocolConformance(
2311+
const NormalProtocolConformance *conformance) {
2312+
// Emit additional metadata to be used by reflection.
2313+
emitAssociatedTypeMetadataRecord(conformance);
2314+
2315+
// Form the protocol conformance descriptor.
2316+
ConstantInitBuilder initBuilder(*this);
2317+
auto init = initBuilder.beginStruct();
2318+
ProtocolConformanceDescriptorBuilder builder(*this, init, conformance);
2319+
builder.layout();
2320+
2321+
auto var =
2322+
cast<llvm::GlobalVariable>(
2323+
getAddrOfProtocolConformanceDescriptor(conformance,
2324+
init.finishAndCreateFuture()));
2325+
var->setConstant(true);
2326+
}
2327+
21992328
void IRGenModule::ensureRelativeSymbolCollocation(SILWitnessTable &wt) {
22002329
// Only resilient conformances use relative pointers for witness methods.
22012330
if (wt.isDeclaration() || isAvailableExternally(wt.getLinkage()) ||

lib/IRGen/IRGenMangler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ class IRGenMangler : public Mangle::ASTMangler {
329329
void appendAssociatedTypePath(CanType associatedType, bool &isFirst) {
330330
if (auto memberType = dyn_cast<DependentMemberType>(associatedType)) {
331331
appendAssociatedTypePath(memberType.getBase(), isFirst);
332-
appendIdentifier(memberType->getName().str());
332+
appendAssociatedTypeName(memberType);
333333
appendListSeparator(isFirst);
334334
} else {
335335
assert(isa<GenericTypeParamType>(associatedType));

stdlib/public/runtime/Demangle.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ swift::_buildDemanglingForContext(const ContextDescriptor *context,
8787
auto extension = llvm::cast<ExtensionContextDescriptor>(component);
8888
// Demangle the extension self type.
8989
auto selfType = Dem.demangleType(extension->getMangledExtendedContext());
90-
assert(selfType->getKind() == Node::Kind::Type);
91-
selfType = selfType->getChild(0);
90+
if (selfType->getKind() == Node::Kind::Type)
91+
selfType = selfType->getChild(0);
9292

9393
// Substitute in the generic arguments.
9494
// TODO: This kludge only kinda works if there are no same-type

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,7 +1024,7 @@ class DecodedMetadataBuilder {
10241024
auto accessFunction = typeDecl->getAccessFunction();
10251025
if (!accessFunction) return BuiltType();
10261026

1027-
return accessFunction(MetadataState::Complete, allGenericArgs).Value;
1027+
return accessFunction(MetadataState::Abstract, allGenericArgs).Value;
10281028
}
10291029

10301030
BuiltType createBuiltinType(StringRef mangledName) const {
@@ -1102,7 +1102,7 @@ class DecodedMetadataBuilder {
11021102
auto flags = TupleTypeFlags().withNumElements(elements.size());
11031103
if (!labels.empty())
11041104
flags = flags.withNonConstantLabels(true);
1105-
return swift_getTupleTypeMetadata(MetadataState::Complete,
1105+
return swift_getTupleTypeMetadata(MetadataState::Abstract,
11061106
flags, elements.data(),
11071107
labels.empty() ? nullptr : labels.c_str(),
11081108
/*proposedWitnesses=*/nullptr).Value;
@@ -1189,10 +1189,8 @@ swift::_getTypeByMangledName(StringRef typeName,
11891189
if (!assocTypeReqIndex) return nullptr;
11901190

11911191
// Call the associated type access function.
1192-
// TODO: can we just request abstract metadata? If so, do we have
1193-
// a responsibility to try to finish it later?
11941192
return ((AssociatedTypeAccessFunction * const *)witnessTable)[*assocTypeReqIndex]
1195-
(MetadataState::Complete, base, witnessTable).Value;
1193+
(MetadataState::Abstract, base, witnessTable).Value;
11961194
});
11971195

11981196
auto type = Demangle::decodeMangledType(builder, node);
@@ -1205,7 +1203,7 @@ swift_getTypeByMangledNameImpl(const char *typeNameStart, size_t typeNameLength,
12051203
size_t *parametersPerLevel,
12061204
const Metadata * const *flatSubstitutions) {
12071205
llvm::StringRef typeName(typeNameStart, typeNameLength);
1208-
return _getTypeByMangledName(typeName,
1206+
auto metadata = _getTypeByMangledName(typeName,
12091207
[&](unsigned depth, unsigned index) -> const Metadata * {
12101208
if (depth >= numberOfLevels)
12111209
return nullptr;
@@ -1219,6 +1217,10 @@ swift_getTypeByMangledNameImpl(const char *typeNameStart, size_t typeNameLength,
12191217

12201218
return flatSubstitutions[flatIndex];
12211219
});
1220+
1221+
if (!metadata) return nullptr;
1222+
1223+
return swift_checkMetadataState(MetadataState::Complete, metadata).Value;
12221224
}
12231225

12241226
#define OVERRIDE_METADATALOOKUP COMPATIBILITY_OVERRIDE

stdlib/public/runtime/Private.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ class TypeInfo {
6969
bool isWeak() const { return ReferenceOwnership.isWeak(); }
7070
bool isUnowned() const { return ReferenceOwnership.isUnowned(); }
7171
bool isUnmanaged() const { return ReferenceOwnership.isUnmanaged(); }
72+
73+
TypeReferenceOwnership getReferenceOwnership() const {
74+
return ReferenceOwnership;
75+
}
7276
};
7377

7478
#if SWIFT_HAS_ISA_MASKING

0 commit comments

Comments
 (0)