blob: 0af1e53b3f9d74beaadcca6eca029d19a4443704 [file] [log] [blame]
//===--- SwiftRemoteMirror.cpp - C wrapper for Reflection API -------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/SwiftRemoteMirror/Platform.h"
#include "swift/SwiftRemoteMirror/SwiftRemoteMirror.h"
#define SWIFT_CLASS_IS_SWIFT_MASK swift_reflection_classIsSwiftMask
extern "C" {
SWIFT_REMOTE_MIRROR_LINKAGE
unsigned long long swift_reflection_classIsSwiftMask = 2;
}
#include "swift/Demangling/Demangler.h"
#include "swift/Reflection/ReflectionContext.h"
#include "swift/Reflection/TypeLowering.h"
#include "swift/Remote/CMemoryReader.h"
#include "swift/Basic/Unreachable.h"
#if defined(__APPLE__) && defined(__MACH__)
#include <TargetConditionals.h>
#endif
using namespace swift;
using namespace swift::reflection;
using namespace swift::remote;
using Runtime = External<RuntimeTarget<sizeof(uintptr_t)>>;
using NativeReflectionContext = swift::reflection::ReflectionContext<Runtime>;
struct SwiftReflectionContext {
NativeReflectionContext *nativeContext;
std::vector<std::function<void()>> freeFuncs;
std::vector<std::tuple<swift_addr_t, swift_addr_t>> dataSegments;
std::string lastString;
SwiftReflectionContext(MemoryReaderImpl impl) {
auto Reader = std::make_shared<CMemoryReader>(impl);
nativeContext = new NativeReflectionContext(Reader);
}
~SwiftReflectionContext() {
delete nativeContext;
for (auto f : freeFuncs)
f();
}
};
uint16_t
swift_reflection_getSupportedMetadataVersion() {
return SWIFT_REFLECTION_METADATA_VERSION;
}
template <uint8_t WordSize>
static int minimalDataLayoutQueryFunction(void *ReaderContext,
DataLayoutQueryType type,
void *inBuffer, void *outBuffer) {
// TODO: The following should be set based on the target.
// This code sets it to match the platform this code was compiled for.
#if defined(__APPLE__) && __APPLE__
auto applePlatform = true;
#else
auto applePlatform = false;
#endif
#if defined(__APPLE__) && __APPLE__ && ((defined(TARGET_OS_IOS) && TARGET_OS_IOS) || (defined(TARGET_OS_IOS) && TARGET_OS_WATCH) || (defined(TARGET_OS_TV) && TARGET_OS_TV) || defined(__arm64__))
auto iosDerivedPlatform = true;
#else
auto iosDerivedPlatform = false;
#endif
if (type == DLQ_GetPointerSize || type == DLQ_GetSizeSize) {
auto result = static_cast<uint8_t *>(outBuffer);
*result = WordSize;
return 1;
}
if (type == DLQ_GetObjCReservedLowBits) {
auto result = static_cast<uint8_t *>(outBuffer);
if (applePlatform && !iosDerivedPlatform && WordSize == 8) {
// Obj-C reserves low bit on 64-bit macOS only.
// Other Apple platforms don't reserve this bit (even when
// running on x86_64-based simulators).
*result = 1;
} else {
*result = 0;
}
return 1;
}
if (type == DLQ_GetLeastValidPointerValue) {
auto result = static_cast<uint64_t *>(outBuffer);
if (applePlatform && WordSize == 8) {
// Swift reserves the first 4GiB on all 64-bit Apple platforms
*result = 0x100000000;
} else {
// Swift reserves the first 4KiB everywhere else
*result = 0x1000;
}
return 1;
}
return 0;
}
// Caveat: This basically only works correctly if running on the same
// host as the target. Otherwise, you'll need to use
// swift_reflection_createReflectionContextWithDataLayout() below
// with an appropriate data layout query function that understands
// the target environment.
SwiftReflectionContextRef
swift_reflection_createReflectionContext(void *ReaderContext,
uint8_t PointerSize,
FreeBytesFunction Free,
ReadBytesFunction ReadBytes,
GetStringLengthFunction GetStringLength,
GetSymbolAddressFunction GetSymbolAddress) {
assert((PointerSize == 4 || PointerSize == 8) && "We only support 32-bit and 64-bit.");
assert(PointerSize == sizeof(uintptr_t) &&
"We currently only support the pointer size this file was compiled with.");
auto *DataLayout = PointerSize == 4 ? minimalDataLayoutQueryFunction<4>
: minimalDataLayoutQueryFunction<8>;
MemoryReaderImpl ReaderImpl {
ReaderContext,
DataLayout,
Free,
ReadBytes,
GetStringLength,
GetSymbolAddress
};
return new SwiftReflectionContext(ReaderImpl);
}
SwiftReflectionContextRef
swift_reflection_createReflectionContextWithDataLayout(void *ReaderContext,
QueryDataLayoutFunction DataLayout,
FreeBytesFunction Free,
ReadBytesFunction ReadBytes,
GetStringLengthFunction GetStringLength,
GetSymbolAddressFunction GetSymbolAddress) {
MemoryReaderImpl ReaderImpl {
ReaderContext,
DataLayout,
Free,
ReadBytes,
GetStringLength,
GetSymbolAddress
};
return new SwiftReflectionContext(ReaderImpl);
}
void swift_reflection_destroyReflectionContext(SwiftReflectionContextRef ContextRef) {
delete ContextRef;
}
template<typename Iterator>
ReflectionSection<Iterator> sectionFromInfo(const swift_reflection_info_t &Info,
const swift_reflection_section_pair_t &Section) {
auto RemoteSectionStart = (uint64_t)(uintptr_t)Section.section.Begin
- Info.LocalStartAddress
+ Info.RemoteStartAddress;
auto Start = RemoteRef<void>(RemoteSectionStart, Section.section.Begin);
return ReflectionSection<Iterator>(Start,
(uintptr_t)Section.section.End - (uintptr_t)Section.section.Begin);
}
template <typename Iterator>
ReflectionSection<Iterator> reflectionSectionFromLocalAndRemote(
const swift_reflection_section_mapping_t &Section) {
auto RemoteSectionStart = (uint64_t)Section.remote_section.StartAddress;
auto Start = RemoteRef<void>(RemoteSectionStart, Section.local_section.Begin);
return ReflectionSection<Iterator>(Start,
(uintptr_t)Section.remote_section.Size);
}
void
swift_reflection_addReflectionInfo(SwiftReflectionContextRef ContextRef,
swift_reflection_info_t Info) {
auto Context = ContextRef->nativeContext;
// The `offset` fields must be zero.
if (Info.field.offset != 0
|| Info.associated_types.offset != 0
|| Info.builtin_types.offset != 0
|| Info.capture.offset != 0
|| Info.type_references.offset != 0
|| Info.reflection_strings.offset != 0) {
fprintf(stderr, "reserved field in swift_reflection_info_t is not zero\n");
abort();
}
ReflectionInfo ContextInfo{
sectionFromInfo<FieldDescriptorIterator>(Info, Info.field),
sectionFromInfo<AssociatedTypeIterator>(Info, Info.associated_types),
sectionFromInfo<BuiltinTypeDescriptorIterator>(Info, Info.builtin_types),
sectionFromInfo<CaptureDescriptorIterator>(Info, Info.capture),
sectionFromInfo<const void *>(Info, Info.type_references),
sectionFromInfo<const void *>(Info, Info.reflection_strings)};
Context->addReflectionInfo(ContextInfo);
}
void swift_reflection_addReflectionMappingInfo(
SwiftReflectionContextRef ContextRef,
swift_reflection_mapping_info_t Info) {
auto Context = ContextRef->nativeContext;
ReflectionInfo ContextInfo{
reflectionSectionFromLocalAndRemote<FieldDescriptorIterator>(Info.field),
reflectionSectionFromLocalAndRemote<AssociatedTypeIterator>(
Info.associated_types),
reflectionSectionFromLocalAndRemote<BuiltinTypeDescriptorIterator>(
Info.builtin_types),
reflectionSectionFromLocalAndRemote<CaptureDescriptorIterator>(
Info.capture),
reflectionSectionFromLocalAndRemote<const void *>(Info.type_references),
reflectionSectionFromLocalAndRemote<const void *>(
Info.reflection_strings)};
Context->addReflectionInfo(ContextInfo);
}
int
swift_reflection_addImage(SwiftReflectionContextRef ContextRef,
swift_addr_t imageStart) {
auto Context = ContextRef->nativeContext;
return Context->addImage(RemoteAddress(imageStart));
}
int
swift_reflection_readIsaMask(SwiftReflectionContextRef ContextRef,
uintptr_t *outIsaMask) {
auto Context = ContextRef->nativeContext;
auto isaMask = Context->readIsaMask();
if (isaMask) {
*outIsaMask = *isaMask;
return true;
}
*outIsaMask = 0;
return false;
}
swift_typeref_t
swift_reflection_typeRefForMetadata(SwiftReflectionContextRef ContextRef,
uintptr_t Metadata) {
auto Context = ContextRef->nativeContext;
auto TR = Context->readTypeFromMetadata(Metadata);
return reinterpret_cast<swift_typeref_t>(TR);
}
int
swift_reflection_ownsObject(SwiftReflectionContextRef ContextRef, uintptr_t Object) {
auto Context = ContextRef->nativeContext;
return Context->ownsObject(RemoteAddress(Object));
}
int
swift_reflection_ownsAddress(SwiftReflectionContextRef ContextRef, uintptr_t Address) {
auto Context = ContextRef->nativeContext;
return Context->ownsAddress(RemoteAddress(Address));
}
uintptr_t
swift_reflection_metadataForObject(SwiftReflectionContextRef ContextRef,
uintptr_t Object) {
auto Context = ContextRef->nativeContext;
auto MetadataAddress = Context->readMetadataFromInstance(Object);
if (!MetadataAddress)
return 0;
return *MetadataAddress;
}
swift_typeref_t
swift_reflection_typeRefForInstance(SwiftReflectionContextRef ContextRef,
uintptr_t Object) {
auto Context = ContextRef->nativeContext;
auto MetadataAddress = Context->readMetadataFromInstance(Object);
if (!MetadataAddress)
return 0;
auto TR = Context->readTypeFromMetadata(*MetadataAddress);
return reinterpret_cast<swift_typeref_t>(TR);
}
swift_typeref_t
swift_reflection_typeRefForMangledTypeName(SwiftReflectionContextRef ContextRef,
const char *MangledTypeName,
uint64_t Length) {
auto Context = ContextRef->nativeContext;
auto TR = Context->readTypeFromMangledName(MangledTypeName, Length).getType();
return reinterpret_cast<swift_typeref_t>(TR);
}
char *
swift_reflection_copyDemangledNameForTypeRef(
SwiftReflectionContextRef ContextRef, swift_typeref_t OpaqueTypeRef) {
auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
Demangle::Demangler Dem;
auto Name = nodeToString(TR->getDemangling(Dem));
return strdup(Name.c_str());
}
SWIFT_REMOTE_MIRROR_LINKAGE
char *
swift_reflection_copyDemangledNameForProtocolDescriptor(
SwiftReflectionContextRef ContextRef, swift_reflection_ptr_t Proto) {
auto Context = ContextRef->nativeContext;
Demangle::Demangler Dem;
auto Demangling = Context->readDemanglingForContextDescriptor(Proto, Dem);
auto Name = nodeToString(Demangling);
return strdup(Name.c_str());
}
swift_typeref_t
swift_reflection_genericArgumentOfTypeRef(swift_typeref_t OpaqueTypeRef,
unsigned Index) {
auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
if (auto BG = dyn_cast<BoundGenericTypeRef>(TR)) {
auto &Params = BG->getGenericParams();
assert(Index < Params.size());
return reinterpret_cast<swift_typeref_t>(Params[Index]);
}
return 0;
}
unsigned
swift_reflection_genericArgumentCountOfTypeRef(swift_typeref_t OpaqueTypeRef) {
auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
if (auto BG = dyn_cast<BoundGenericTypeRef>(TR)) {
auto &Params = BG->getGenericParams();
return Params.size();
}
return 0;
}
swift_layout_kind_t getTypeInfoKind(const TypeInfo &TI) {
switch (TI.getKind()) {
case TypeInfoKind::Invalid: {
return SWIFT_UNKNOWN;
}
case TypeInfoKind::Builtin: {
auto &BuiltinTI = cast<BuiltinTypeInfo>(TI);
if (BuiltinTI.getMangledTypeName() == "Bp")
return SWIFT_RAW_POINTER;
return SWIFT_BUILTIN;
}
case TypeInfoKind::Record: {
auto &RecordTI = cast<RecordTypeInfo>(TI);
switch (RecordTI.getRecordKind()) {
case RecordKind::Invalid:
return SWIFT_UNKNOWN;
case RecordKind::Tuple:
return SWIFT_TUPLE;
case RecordKind::Struct:
return SWIFT_STRUCT;
case RecordKind::ThickFunction:
return SWIFT_THICK_FUNCTION;
case RecordKind::OpaqueExistential:
return SWIFT_OPAQUE_EXISTENTIAL;
case RecordKind::ClassExistential:
return SWIFT_CLASS_EXISTENTIAL;
case RecordKind::ErrorExistential:
return SWIFT_ERROR_EXISTENTIAL;
case RecordKind::ExistentialMetatype:
return SWIFT_EXISTENTIAL_METATYPE;
case RecordKind::ClassInstance:
return SWIFT_CLASS_INSTANCE;
case RecordKind::ClosureContext:
return SWIFT_CLOSURE_CONTEXT;
}
}
case TypeInfoKind::Enum: {
auto &EnumTI = cast<EnumTypeInfo>(TI);
switch (EnumTI.getEnumKind()) {
case EnumKind::NoPayloadEnum:
return SWIFT_NO_PAYLOAD_ENUM;
case EnumKind::SinglePayloadEnum:
return SWIFT_SINGLE_PAYLOAD_ENUM;
case EnumKind::MultiPayloadEnum:
return SWIFT_MULTI_PAYLOAD_ENUM;
}
}
case TypeInfoKind::Reference: {
auto &ReferenceTI = cast<ReferenceTypeInfo>(TI);
switch (ReferenceTI.getReferenceKind()) {
case ReferenceKind::Strong: return SWIFT_STRONG_REFERENCE;
#define REF_STORAGE(Name, name, NAME) \
case ReferenceKind::Name: return SWIFT_##NAME##_REFERENCE;
#include "swift/AST/ReferenceStorage.def"
}
}
}
swift_unreachable("Unhandled TypeInfoKind in switch");
}
static swift_typeinfo_t convertTypeInfo(const TypeInfo *TI) {
if (TI == nullptr) {
return {
SWIFT_UNKNOWN,
0,
0,
0,
0
};
}
unsigned NumFields = 0;
if (auto *RecordTI = dyn_cast<EnumTypeInfo>(TI)) {
NumFields = RecordTI->getNumCases();
} else if (auto *RecordTI = dyn_cast<RecordTypeInfo>(TI)) {
NumFields = RecordTI->getNumFields();
}
return {
getTypeInfoKind(*TI),
TI->getSize(),
TI->getAlignment(),
TI->getStride(),
NumFields
};
}
static swift_childinfo_t convertChild(const TypeInfo *TI, unsigned Index) {
if (!TI)
return {};
const FieldInfo *FieldInfo;
if (auto *EnumTI = dyn_cast<EnumTypeInfo>(TI)) {
FieldInfo = &(EnumTI->getCases()[Index]);
} else if (auto *RecordTI = dyn_cast<RecordTypeInfo>(TI)) {
FieldInfo = &(RecordTI->getFields()[Index]);
} else {
assert(false && "convertChild(TI): TI must be record or enum typeinfo");
return {
"unknown TypeInfo kind",
0,
SWIFT_UNKNOWN,
0,
};
}
return {
FieldInfo->Name.c_str(),
FieldInfo->Offset,
getTypeInfoKind(FieldInfo->TI),
reinterpret_cast<swift_typeref_t>(FieldInfo->TR),
};
}
static const char *returnableCString(SwiftReflectionContextRef ContextRef,
llvm::Optional<std::string> String) {
if (String) {
ContextRef->lastString = *String;
return ContextRef->lastString.c_str();
}
return nullptr;
}
swift_typeinfo_t
swift_reflection_infoForTypeRef(SwiftReflectionContextRef ContextRef,
swift_typeref_t OpaqueTypeRef) {
auto Context = ContextRef->nativeContext;
auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
auto TI = Context->getTypeInfo(TR, nullptr);
return convertTypeInfo(TI);
}
swift_childinfo_t
swift_reflection_childOfTypeRef(SwiftReflectionContextRef ContextRef,
swift_typeref_t OpaqueTypeRef,
unsigned Index) {
auto Context = ContextRef->nativeContext;
auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
auto *TI = Context->getTypeInfo(TR, nullptr);
return convertChild(TI, Index);
}
swift_typeinfo_t
swift_reflection_infoForMetadata(SwiftReflectionContextRef ContextRef,
uintptr_t Metadata) {
auto Context = ContextRef->nativeContext;
auto *TI = Context->getMetadataTypeInfo(Metadata, nullptr);
return convertTypeInfo(TI);
}
swift_childinfo_t
swift_reflection_childOfMetadata(SwiftReflectionContextRef ContextRef,
uintptr_t Metadata,
unsigned Index) {
auto Context = ContextRef->nativeContext;
auto *TI = Context->getMetadataTypeInfo(Metadata, nullptr);
return convertChild(TI, Index);
}
swift_typeinfo_t
swift_reflection_infoForInstance(SwiftReflectionContextRef ContextRef,
uintptr_t Object) {
auto Context = ContextRef->nativeContext;
auto *TI = Context->getInstanceTypeInfo(Object, nullptr);
return convertTypeInfo(TI);
}
swift_childinfo_t
swift_reflection_childOfInstance(SwiftReflectionContextRef ContextRef,
uintptr_t Object,
unsigned Index) {
auto Context = ContextRef->nativeContext;
auto *TI = Context->getInstanceTypeInfo(Object, nullptr);
return convertChild(TI, Index);
}
int swift_reflection_projectExistential(SwiftReflectionContextRef ContextRef,
swift_addr_t ExistentialAddress,
swift_typeref_t ExistentialTypeRef,
swift_typeref_t *InstanceTypeRef,
swift_addr_t *StartOfInstanceData) {
auto Context = ContextRef->nativeContext;
auto ExistentialTR = reinterpret_cast<const TypeRef *>(ExistentialTypeRef);
auto RemoteExistentialAddress = RemoteAddress(ExistentialAddress);
const TypeRef *InstanceTR = nullptr;
RemoteAddress RemoteStartOfInstanceData(nullptr);
auto Success = Context->projectExistential(
RemoteExistentialAddress, ExistentialTR, &InstanceTR,
&RemoteStartOfInstanceData, nullptr);
if (Success) {
*InstanceTypeRef = reinterpret_cast<swift_typeref_t>(InstanceTR);
*StartOfInstanceData = RemoteStartOfInstanceData.getAddressData();
}
return Success;
}
int swift_reflection_projectEnumValue(SwiftReflectionContextRef ContextRef,
swift_addr_t EnumAddress,
swift_typeref_t EnumTypeRef,
int *CaseIndex) {
auto Context = ContextRef->nativeContext;
auto EnumTR = reinterpret_cast<const TypeRef *>(EnumTypeRef);
auto RemoteEnumAddress = RemoteAddress(EnumAddress);
if (!Context->projectEnumValue(RemoteEnumAddress, EnumTR, CaseIndex,
nullptr)) {
return false;
}
auto TI = Context->getTypeInfo(EnumTR, nullptr);
auto *RecordTI = dyn_cast<EnumTypeInfo>(TI);
assert(RecordTI != nullptr);
if (static_cast<size_t>(*CaseIndex) >= RecordTI->getNumCases()) {
return false;
}
return true;
}
void swift_reflection_dumpTypeRef(swift_typeref_t OpaqueTypeRef) {
auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
if (TR == nullptr) {
fprintf(stdout, "<null type reference>\n");
} else {
TR->dump(stdout);
}
}
void swift_reflection_dumpInfoForTypeRef(SwiftReflectionContextRef ContextRef,
swift_typeref_t OpaqueTypeRef) {
auto Context = ContextRef->nativeContext;
auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
auto TI = Context->getTypeInfo(TR, nullptr);
if (TI == nullptr) {
fprintf(stdout, "<null type info>\n");
} else {
TI->dump(stdout);
Demangle::Demangler Dem;
std::string MangledName = mangleNode(TR->getDemangling(Dem));
fprintf(stdout, "Mangled name: %s%s\n", MANGLING_PREFIX_STR,
MangledName.c_str());
char *DemangledName =
swift_reflection_copyDemangledNameForTypeRef(ContextRef, OpaqueTypeRef);
fprintf(stdout, "Demangled name: %s\n", DemangledName);
free(DemangledName);
#ifndef NDEBUG
assert(mangleNode(TR->getDemangling(Dem)) == MangledName &&
"round-trip diff");
#endif
}
}
void swift_reflection_dumpInfoForMetadata(SwiftReflectionContextRef ContextRef,
uintptr_t Metadata) {
auto Context = ContextRef->nativeContext;
auto TI = Context->getMetadataTypeInfo(Metadata, nullptr);
if (TI == nullptr) {
fprintf(stdout, "<null type info>\n");
} else {
TI->dump(stdout);
}
}
void swift_reflection_dumpInfoForInstance(SwiftReflectionContextRef ContextRef,
uintptr_t Object) {
auto Context = ContextRef->nativeContext;
auto TI = Context->getInstanceTypeInfo(Object, nullptr);
if (TI == nullptr) {
fprintf(stdout, "%s", "<null type info>\n");
} else {
TI->dump(stdout);
}
}
size_t swift_reflection_demangle(const char *MangledName, size_t Length,
char *OutDemangledName, size_t MaxLength) {
if (MangledName == nullptr || Length == 0)
return 0;
std::string Mangled(MangledName, Length);
auto Demangled = Demangle::demangleTypeAsString(Mangled);
strncpy(OutDemangledName, Demangled.c_str(), MaxLength);
return Demangled.size();
}
const char *swift_reflection_iterateConformanceCache(
SwiftReflectionContextRef ContextRef,
void (*Call)(swift_reflection_ptr_t Type,
swift_reflection_ptr_t Proto,
void *ContextPtr),
void *ContextPtr) {
auto Context = ContextRef->nativeContext;
auto Error = Context->iterateConformances([&](auto Type, auto Proto) {
Call(Type, Proto, ContextPtr);
});
return returnableCString(ContextRef, Error);
}
const char *swift_reflection_iterateMetadataAllocations(
SwiftReflectionContextRef ContextRef,
void (*Call)(swift_metadata_allocation_t Allocation,
void *ContextPtr),
void *ContextPtr) {
auto Context = ContextRef->nativeContext;
auto Error = Context->iterateMetadataAllocations([&](auto Allocation) {
swift_metadata_allocation CAllocation;
CAllocation.Tag = Allocation.Tag;
CAllocation.Ptr = Allocation.Ptr;
CAllocation.Size = Allocation.Size;
Call(CAllocation, ContextPtr);
});
return returnableCString(ContextRef, Error);
}
swift_reflection_ptr_t swift_reflection_allocationMetadataPointer(
SwiftReflectionContextRef ContextRef,
swift_metadata_allocation_t Allocation) {
auto Context = ContextRef->nativeContext;
MetadataAllocation<Runtime> NativeAllocation;
NativeAllocation.Tag = Allocation.Tag;
NativeAllocation.Ptr = Allocation.Ptr;
NativeAllocation.Size = Allocation.Size;
return Context->allocationMetadataPointer(NativeAllocation);
}
const char *swift_reflection_metadataAllocationTagName(
SwiftReflectionContextRef ContextRef, swift_metadata_allocation_tag_t Tag) {
auto Context = ContextRef->nativeContext;
auto Result = Context->metadataAllocationTagName(Tag);
return returnableCString(ContextRef, Result);
}
int swift_reflection_metadataAllocationCacheNode(
SwiftReflectionContextRef ContextRef,
swift_metadata_allocation_t Allocation,
swift_metadata_cache_node_t *OutNode) {
auto Context = ContextRef->nativeContext;
MetadataAllocation<Runtime> ConvertedAllocation;
ConvertedAllocation.Tag = Allocation.Tag;
ConvertedAllocation.Ptr = Allocation.Ptr;
ConvertedAllocation.Size = Allocation.Size;
auto Result = Context->metadataAllocationCacheNode(ConvertedAllocation);
if (!Result)
return 0;
OutNode->Left = Result->Left;
OutNode->Right = Result->Right;
return 1;
}
const char *swift_reflection_iterateMetadataAllocationBacktraces(
SwiftReflectionContextRef ContextRef,
swift_metadataAllocationBacktraceIterator Call, void *ContextPtr) {
auto Context = ContextRef->nativeContext;
auto Error = Context->iterateMetadataAllocationBacktraces(
[&](auto AllocationPtr, auto Count, auto Ptrs) {
// Ptrs is an array of StoredPointer, but the callback expects an array
// of swift_reflection_ptr_t. Those may are not always the same type.
// (For example, swift_reflection_ptr_t can be 64-bit on 32-bit systems,
// while StoredPointer is always the pointer size of the target system.)
// Convert the array to an array of swift_reflection_ptr_t.
std::vector<swift_reflection_ptr_t> ConvertedPtrs{&Ptrs[0],
&Ptrs[Count]};
Call(AllocationPtr, Count, ConvertedPtrs.data(), ContextPtr);
});
return returnableCString(ContextRef, Error);
}