Skip to content

Commit 0a775da

Browse files
committed
[Runtime] Extract a function object for demangling using base metadata.
The field metadata translation has a great little lambda for extracting generic arguments from metadata when demangling. Extract it into a reusable function object.
1 parent 298458a commit 0a775da

File tree

3 files changed

+57
-36
lines changed

3 files changed

+57
-36
lines changed

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,5 +1223,44 @@ swift_getTypeByMangledNameImpl(const char *typeNameStart, size_t typeNameLength,
12231223
return swift_checkMetadataState(MetadataState::Complete, metadata).Value;
12241224
}
12251225

1226+
const Metadata *
1227+
SubstGenericParametersFromMetadata::operator()(
1228+
unsigned depth, unsigned index) const {
1229+
// On first access, compute the descriptor path.
1230+
if (descriptorPath.empty()) {
1231+
if (auto *baseDesc = base->getTypeContextDescriptor()) {
1232+
const auto *parent = reinterpret_cast<
1233+
const ContextDescriptor *>(baseDesc);
1234+
while (parent) {
1235+
if (parent->isGeneric())
1236+
descriptorPath.push_back(parent);
1237+
1238+
parent = parent->Parent.get();
1239+
}
1240+
}
1241+
}
1242+
1243+
if (depth >= descriptorPath.size())
1244+
return nullptr;
1245+
1246+
unsigned currentDepth = 0;
1247+
unsigned flatIndex = index;
1248+
const ContextDescriptor *currentContext = descriptorPath.back();
1249+
1250+
for (const auto *context : llvm::reverse(descriptorPath)) {
1251+
if (currentDepth >= depth)
1252+
break;
1253+
1254+
flatIndex += context->getNumGenericParams();
1255+
currentContext = context;
1256+
++currentDepth;
1257+
}
1258+
1259+
if (index >= currentContext->getNumGenericParams())
1260+
return nullptr;
1261+
1262+
return base->getGenericArgs()[flatIndex];
1263+
}
1264+
12261265
#define OVERRIDE_METADATALOOKUP COMPATIBILITY_OVERRIDE
12271266
#include "CompatibilityOverride.def"

stdlib/public/runtime/Private.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,22 @@ class TypeInfo {
235235
using SubstGenericParameterFn =
236236
llvm::function_ref<const Metadata *(unsigned depth, unsigned index)>;
237237

238+
/// Function object that produces substitutions for the generic parameters
239+
/// that occur within a mangled name, using the generic arguments from
240+
/// the given metadata.
241+
///
242+
/// Use with \c _getTypeByMangledName to decode potentially-generic types.
243+
class SWIFT_RUNTIME_LIBRARY_VISIBILITY SubstGenericParametersFromMetadata {
244+
const Metadata *base;
245+
mutable std::vector<const ContextDescriptor *> descriptorPath;
246+
247+
public:
248+
explicit SubstGenericParametersFromMetadata(const Metadata *base)
249+
: base(base) { }
250+
251+
const Metadata *operator()(unsigned depth, unsigned index) const;
252+
};
253+
238254
/// Retrieve the type metadata described by the given type name.
239255
///
240256
/// \p substGenericParam Function that provides generic argument metadata

stdlib/public/runtime/ReflectionMirror.mm

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -332,44 +332,10 @@ static bool _shouldReportMissingReflectionMetadataWarnings() {
332332
if (!field.hasMangledTypeName())
333333
return {name, FieldType().withIndirect(field.isIndirectCase())};
334334

335-
std::vector<const ContextDescriptor *> descriptorPath;
336-
{
337-
const auto *parent = reinterpret_cast<
338-
const ContextDescriptor *>(baseDesc);
339-
while (parent) {
340-
if (parent->isGeneric())
341-
descriptorPath.push_back(parent);
342-
343-
parent = parent->Parent.get();
344-
}
345-
}
346-
347335
auto typeName = field.getMangledTypeName(0);
348336

349-
auto typeInfo = _getTypeByMangledName(
350-
typeName,
351-
[&](unsigned depth, unsigned index) -> const Metadata * {
352-
if (depth >= descriptorPath.size())
353-
return nullptr;
354-
355-
unsigned currentDepth = 0;
356-
unsigned flatIndex = index;
357-
const ContextDescriptor *currentContext = descriptorPath.back();
358-
359-
for (const auto *context : llvm::reverse(descriptorPath)) {
360-
if (currentDepth >= depth)
361-
break;
362-
363-
flatIndex += context->getNumGenericParams();
364-
currentContext = context;
365-
++currentDepth;
366-
}
367-
368-
if (index >= currentContext->getNumGenericParams())
369-
return nullptr;
370-
371-
return base->getGenericArgs()[flatIndex];
372-
});
337+
SubstGenericParametersFromMetadata substitutions(base);
338+
auto typeInfo = _getTypeByMangledName(typeName, substitutions);
373339

374340
// Complete the type metadata before returning it to the caller.
375341
if (typeInfo) {

0 commit comments

Comments
 (0)