mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Add an extra opaque field to AddressSpace, which can be used by clients of RemoteInspection to distinguish between different address spaces. LLDB employs an optimization where it reads memory from files instead of the running process whenever it can to speed up memory reads (these can be slow when debugging something over a network). To do this, it needs to keep track whether an address originated from a process or a file. It currently distinguishes addresses by setting an unused high bit on the address, but because of pointer authentication this is not a reliable solution. In order to keep this optimization working, this patch adds an extra opaque AddressSpace field to RemoteAddress, which LLDB can use on its own implementation of MemoryReader to distinguish between addresses. This patch is NFC for the other RemoteInspection clients, as it adds extra information to RemoteAddress, which is entirely optional and if unused should not change the behavior of the library. Although this patch is quite big the changes are largely mechanical, replacing threading StoredPointer with RemoteAddress. rdar://148361743 (cherry picked from commit58df5534d2) (cherry picked from commit8f3862b5e7)
1113 lines
40 KiB
C++
1113 lines
40 KiB
C++
//===--- 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"
|
|
#include <iostream>
|
|
#include <variant>
|
|
|
|
#define SWIFT_CLASS_IS_SWIFT_MASK swift_reflection_classIsSwiftMask
|
|
extern "C" {
|
|
SWIFT_REMOTE_MIRROR_LINKAGE
|
|
unsigned long long swift_reflection_classIsSwiftMask = 2;
|
|
|
|
SWIFT_REMOTE_MIRROR_LINKAGE uint32_t swift_reflection_libraryVersion = 3;
|
|
}
|
|
|
|
#include "swift/Demangling/Demangler.h"
|
|
#include "swift/RemoteInspection/ReflectionContext.h"
|
|
#include "swift/RemoteInspection/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 RuntimeWithObjCInterop =
|
|
External<WithObjCInterop<RuntimeTarget<sizeof(uintptr_t)>>>;
|
|
using RuntimeNoObjCInterop =
|
|
External<NoObjCInterop<RuntimeTarget<sizeof(uintptr_t)>>>;
|
|
|
|
using ReflectionContextWithObjCInterop =
|
|
swift::reflection::ReflectionContext<RuntimeWithObjCInterop>;
|
|
using ReflectionContextNoObjCInterop =
|
|
swift::reflection::ReflectionContext<RuntimeNoObjCInterop>;
|
|
|
|
struct SwiftReflectionContext {
|
|
using ContextVariant =
|
|
std::variant<std::unique_ptr<ReflectionContextWithObjCInterop>,
|
|
std::unique_ptr<ReflectionContextNoObjCInterop>>;
|
|
|
|
ContextVariant context;
|
|
std::vector<std::function<void()>> freeFuncs;
|
|
std::vector<std::tuple<swift_addr_t, swift_addr_t>> dataSegments;
|
|
|
|
std::function<void(void)> freeTemporaryAllocation = [] {};
|
|
|
|
SwiftReflectionContext(bool objCInteropIsEnabled, MemoryReaderImpl impl) {
|
|
auto Reader = std::make_shared<CMemoryReader>(impl);
|
|
if (objCInteropIsEnabled) {
|
|
context = std::make_unique<ReflectionContextWithObjCInterop>(Reader);
|
|
} else {
|
|
context = std::make_unique<ReflectionContextNoObjCInterop>(Reader);
|
|
}
|
|
}
|
|
|
|
~SwiftReflectionContext() {
|
|
freeTemporaryAllocation();
|
|
for (auto f : freeFuncs)
|
|
f();
|
|
}
|
|
|
|
// Allocate a single temporary object that will stay allocated until the next
|
|
// call to this method, or until the context is destroyed.
|
|
template <typename T>
|
|
T *allocateTemporaryObject() {
|
|
freeTemporaryAllocation();
|
|
T *obj = new T;
|
|
freeTemporaryAllocation = [obj] { delete obj; };
|
|
return obj;
|
|
}
|
|
|
|
// Allocate a single temporary object that will stay allocated until the next
|
|
// call to allocateTemporaryObject, or until the context is destroyed. Does
|
|
// NOT free any existing objects created with allocateTemporaryObject or
|
|
// allocateSubsequentTemporaryObject. Use to allocate additional objects after
|
|
// a call to allocateTemporaryObject when multiple objects are needed
|
|
// simultaneously.
|
|
template <typename T>
|
|
T *allocateSubsequentTemporaryObject() {
|
|
T *obj = new T;
|
|
auto oldFree = freeTemporaryAllocation;
|
|
freeTemporaryAllocation = [obj, oldFree] {
|
|
delete obj;
|
|
oldFree();
|
|
};
|
|
return obj;
|
|
}
|
|
|
|
// Call fn with a pointer to context.
|
|
template <typename T, typename Fn>
|
|
T withContext(const Fn &fn) {
|
|
return std::visit([&](auto &&context) { return fn(context.get()); },
|
|
this->context);
|
|
}
|
|
};
|
|
|
|
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 {
|
|
PointerSize,
|
|
ReaderContext,
|
|
DataLayout,
|
|
Free,
|
|
ReadBytes,
|
|
GetStringLength,
|
|
GetSymbolAddress
|
|
};
|
|
|
|
return new SwiftReflectionContext(SWIFT_OBJC_INTEROP, ReaderImpl);
|
|
}
|
|
|
|
SwiftReflectionContextRef
|
|
swift_reflection_createReflectionContextWithDataLayout(void *ReaderContext,
|
|
QueryDataLayoutFunction DataLayout,
|
|
FreeBytesFunction Free,
|
|
ReadBytesFunction ReadBytes,
|
|
GetStringLengthFunction GetStringLength,
|
|
GetSymbolAddressFunction GetSymbolAddress) {
|
|
uint8_t PointerSize = sizeof(uintptr_t);
|
|
MemoryReaderImpl ReaderImpl {
|
|
PointerSize,
|
|
ReaderContext,
|
|
DataLayout,
|
|
Free,
|
|
ReadBytes,
|
|
GetStringLength,
|
|
GetSymbolAddress
|
|
};
|
|
|
|
// If the client implements DLQ_GetObjCInteropIsEnabled, use that value.
|
|
// If they don't, use this platform's default.
|
|
bool dataLayoutSaysObjCInteropIsEnabled = true;
|
|
if (DataLayout(ReaderContext, DLQ_GetObjCInteropIsEnabled, nullptr,
|
|
(void *)&dataLayoutSaysObjCInteropIsEnabled)) {
|
|
return new SwiftReflectionContext(dataLayoutSaysObjCInteropIsEnabled,
|
|
ReaderImpl);
|
|
} else {
|
|
return new SwiftReflectionContext(SWIFT_OBJC_INTEROP, 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>(
|
|
RemoteAddress(RemoteSectionStart, RemoteAddress::DefaultAddressSpace),
|
|
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>(
|
|
RemoteAddress(RemoteSectionStart, RemoteAddress::DefaultAddressSpace),
|
|
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) {
|
|
ContextRef->withContext<void>([&](auto *Context) {
|
|
// 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) {
|
|
std::cerr << "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),
|
|
ReflectionSection<const void *>(nullptr, 0),
|
|
ReflectionSection<MultiPayloadEnumDescriptorIterator>(0, 0),
|
|
{}};
|
|
|
|
Context->addReflectionInfo(ContextInfo);
|
|
});
|
|
}
|
|
|
|
void swift_reflection_addReflectionMappingInfo(
|
|
SwiftReflectionContextRef ContextRef,
|
|
swift_reflection_mapping_info_t Info) {
|
|
return ContextRef->withContext<void>([&](auto *Context) {
|
|
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),
|
|
ReflectionSection<const void *>(nullptr, 0),
|
|
MultiPayloadEnumSection(0, 0),
|
|
{}};
|
|
|
|
Context->addReflectionInfo(ContextInfo);
|
|
});
|
|
}
|
|
|
|
int
|
|
swift_reflection_addImage(SwiftReflectionContextRef ContextRef,
|
|
swift_addr_t imageStart) {
|
|
return ContextRef->withContext<int>([&](auto *Context) {
|
|
return Context
|
|
->addImage(
|
|
RemoteAddress(imageStart, RemoteAddress::DefaultAddressSpace))
|
|
.has_value();
|
|
});
|
|
}
|
|
|
|
int
|
|
swift_reflection_readIsaMask(SwiftReflectionContextRef ContextRef,
|
|
uintptr_t *outIsaMask) {
|
|
return ContextRef->withContext<int>([&](auto *Context) {
|
|
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) {
|
|
return ContextRef->withContext<swift_typeref_t>([&](auto *Context) {
|
|
auto TR = Context->readTypeFromMetadata(RemoteAddress(Metadata,
|
|
RemoteAddress::DefaultAddressSpace));
|
|
return reinterpret_cast<swift_typeref_t>(TR);
|
|
});
|
|
}
|
|
|
|
int
|
|
swift_reflection_ownsObject(SwiftReflectionContextRef ContextRef, uintptr_t Object) {
|
|
return ContextRef->withContext<int>([&](auto *Context) {
|
|
return Context->ownsObject(
|
|
RemoteAddress(Object, RemoteAddress::DefaultAddressSpace));
|
|
});
|
|
}
|
|
|
|
int
|
|
swift_reflection_ownsAddress(SwiftReflectionContextRef ContextRef, uintptr_t Address) {
|
|
return ContextRef->withContext<int>([&](auto *Context) {
|
|
return Context->ownsAddress(
|
|
RemoteAddress(Address, RemoteAddress::DefaultAddressSpace));
|
|
});
|
|
}
|
|
|
|
int
|
|
swift_reflection_ownsAddressStrict(SwiftReflectionContextRef ContextRef, uintptr_t Address) {
|
|
return ContextRef->withContext<int>([&](auto *Context) {
|
|
return Context->ownsAddress(
|
|
RemoteAddress(Address, RemoteAddress::DefaultAddressSpace), false);
|
|
});
|
|
}
|
|
|
|
uintptr_t
|
|
swift_reflection_metadataForObject(SwiftReflectionContextRef ContextRef,
|
|
uintptr_t Object) {
|
|
return ContextRef->withContext<uintptr_t>([&](auto *Context) -> uintptr_t {
|
|
auto MetadataAddress = Context->readMetadataFromInstance(
|
|
RemoteAddress(Object, RemoteAddress::DefaultAddressSpace));
|
|
if (!MetadataAddress)
|
|
return 0;
|
|
return MetadataAddress->getRawAddress();
|
|
});
|
|
}
|
|
|
|
swift_reflection_ptr_t
|
|
swift_reflection_metadataNominalTypeDescriptor(SwiftReflectionContextRef ContextRef,
|
|
swift_reflection_ptr_t MetadataAddress) {
|
|
return ContextRef->withContext<swift_reflection_ptr_t>([&](auto *Context) {
|
|
return Context
|
|
->nominalTypeDescriptorFromMetadata(
|
|
RemoteAddress(MetadataAddress, RemoteAddress::DefaultAddressSpace))
|
|
.getRawAddress();
|
|
});
|
|
}
|
|
|
|
int swift_reflection_metadataIsActor(SwiftReflectionContextRef ContextRef,
|
|
swift_reflection_ptr_t Metadata) {
|
|
return ContextRef->withContext<int>([&](auto *Context) {
|
|
return Context->metadataIsActor(
|
|
RemoteAddress(Metadata, RemoteAddress::DefaultAddressSpace));
|
|
});
|
|
}
|
|
|
|
swift_typeref_t
|
|
swift_reflection_typeRefForInstance(SwiftReflectionContextRef ContextRef,
|
|
uintptr_t Object) {
|
|
return ContextRef->withContext<swift_typeref_t>(
|
|
[&](auto *Context) -> swift_typeref_t {
|
|
auto MetadataAddress = Context->readMetadataFromInstance(
|
|
RemoteAddress(Object, RemoteAddress::DefaultAddressSpace));
|
|
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) {
|
|
return ContextRef->withContext<swift_typeref_t>([&](auto *Context) {
|
|
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());
|
|
}
|
|
|
|
char *
|
|
swift_reflection_copyNameForTypeRef(SwiftReflectionContextRef ContextRef,
|
|
swift_typeref_t OpaqueTypeRef,
|
|
bool mangled) {
|
|
auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
|
|
|
|
Demangle::Demangler Dem;
|
|
if (mangled) {
|
|
auto Mangling = mangleNode(TR->getDemangling(Dem), Mangle::ManglingFlavor::Default);
|
|
if (Mangling.isSuccess()) {
|
|
return strdup(Mangling.result().c_str());
|
|
}
|
|
}
|
|
else {
|
|
auto Name = nodeToString(TR->getDemangling(Dem));
|
|
return strdup(Name.c_str());
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
SWIFT_REMOTE_MIRROR_LINKAGE
|
|
char *
|
|
swift_reflection_copyDemangledNameForProtocolDescriptor(
|
|
SwiftReflectionContextRef ContextRef, swift_reflection_ptr_t Proto) {
|
|
return ContextRef->withContext<char *>([&](auto *Context) {
|
|
|
|
Demangle::Demangler Dem;
|
|
auto Demangling = Context->readDemanglingForContextDescriptor(
|
|
RemoteAddress(Proto, RemoteAddress::DefaultAddressSpace), 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"
|
|
}
|
|
}
|
|
|
|
case TypeInfoKind::Array: {
|
|
return SWIFT_ARRAY;
|
|
}
|
|
}
|
|
|
|
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 = nullptr;
|
|
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),
|
|
};
|
|
}
|
|
|
|
template <typename ReflectionContext>
|
|
static swift_layout_kind_t convertAllocationChunkKind(
|
|
typename ReflectionContext::AsyncTaskAllocationChunk::ChunkKind Kind) {
|
|
switch (Kind) {
|
|
case ReflectionContext::AsyncTaskAllocationChunk::ChunkKind::Unknown:
|
|
return SWIFT_UNKNOWN;
|
|
case ReflectionContext::AsyncTaskAllocationChunk::ChunkKind::NonPointer:
|
|
return SWIFT_BUILTIN;
|
|
case ReflectionContext::AsyncTaskAllocationChunk::ChunkKind::RawPointer:
|
|
return SWIFT_RAW_POINTER;
|
|
case ReflectionContext::AsyncTaskAllocationChunk::ChunkKind::StrongReference:
|
|
return SWIFT_STRONG_REFERENCE;
|
|
case ReflectionContext::AsyncTaskAllocationChunk::ChunkKind::UnownedReference:
|
|
return SWIFT_UNOWNED_REFERENCE;
|
|
case ReflectionContext::AsyncTaskAllocationChunk::ChunkKind::WeakReference:
|
|
return SWIFT_WEAK_REFERENCE;
|
|
case ReflectionContext::AsyncTaskAllocationChunk::ChunkKind::
|
|
UnmanagedReference:
|
|
return SWIFT_UNMANAGED_REFERENCE;
|
|
}
|
|
}
|
|
|
|
static const char *returnableCString(SwiftReflectionContextRef ContextRef,
|
|
std::optional<std::string> String) {
|
|
if (String) {
|
|
auto *TmpStr = ContextRef->allocateTemporaryObject<std::string>();
|
|
*TmpStr = *String;
|
|
return TmpStr->c_str();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
swift_typeinfo_t
|
|
swift_reflection_infoForTypeRef(SwiftReflectionContextRef ContextRef,
|
|
swift_typeref_t OpaqueTypeRef) {
|
|
return ContextRef->withContext<swift_typeinfo_t>([&](auto *Context) {
|
|
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) {
|
|
return ContextRef->withContext<swift_childinfo_t>([&](auto *Context) {
|
|
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) {
|
|
return ContextRef->withContext<swift_typeinfo_t>([&](auto *Context) {
|
|
auto *TI = Context->getMetadataTypeInfo(
|
|
RemoteAddress(Metadata, RemoteAddress::DefaultAddressSpace), nullptr);
|
|
return convertTypeInfo(TI);
|
|
});
|
|
}
|
|
|
|
swift_childinfo_t
|
|
swift_reflection_childOfMetadata(SwiftReflectionContextRef ContextRef,
|
|
uintptr_t Metadata,
|
|
unsigned Index) {
|
|
return ContextRef->withContext<swift_childinfo_t>([&](auto *Context) {
|
|
auto *TI = Context->getMetadataTypeInfo(
|
|
RemoteAddress(Metadata, RemoteAddress::DefaultAddressSpace), nullptr);
|
|
return convertChild(TI, Index);
|
|
});
|
|
}
|
|
|
|
swift_typeinfo_t
|
|
swift_reflection_infoForInstance(SwiftReflectionContextRef ContextRef,
|
|
uintptr_t Object) {
|
|
return ContextRef->withContext<swift_typeinfo_t>([&](auto *Context) {
|
|
auto *TI = Context->getInstanceTypeInfo(
|
|
RemoteAddress(Object, RemoteAddress::DefaultAddressSpace), nullptr);
|
|
return convertTypeInfo(TI);
|
|
});
|
|
}
|
|
|
|
swift_childinfo_t
|
|
swift_reflection_childOfInstance(SwiftReflectionContextRef ContextRef,
|
|
uintptr_t Object,
|
|
unsigned Index) {
|
|
return ContextRef->withContext<swift_childinfo_t>([&](auto *Context) {
|
|
auto *TI = Context->getInstanceTypeInfo(
|
|
RemoteAddress(Object, RemoteAddress::DefaultAddressSpace), 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) {
|
|
return ContextRef->withContext<int>([&](auto *Context) {
|
|
auto ExistentialTR = reinterpret_cast<const TypeRef *>(ExistentialTypeRef);
|
|
auto RemoteExistentialAddress =
|
|
RemoteAddress(ExistentialAddress, RemoteAddress::DefaultAddressSpace);
|
|
const TypeRef *InstanceTR = nullptr;
|
|
RemoteAddress RemoteStartOfInstanceData;
|
|
auto Success = Context->projectExistential(
|
|
RemoteExistentialAddress, ExistentialTR, &InstanceTR,
|
|
&RemoteStartOfInstanceData, nullptr);
|
|
|
|
if (Success) {
|
|
*InstanceTypeRef = reinterpret_cast<swift_typeref_t>(InstanceTR);
|
|
*StartOfInstanceData = RemoteStartOfInstanceData.getRawAddress();
|
|
}
|
|
|
|
return Success;
|
|
});
|
|
}
|
|
|
|
int swift_reflection_projectExistentialAndUnwrapClass(SwiftReflectionContextRef ContextRef,
|
|
swift_addr_t ExistentialAddress,
|
|
swift_typeref_t ExistentialTypeRef,
|
|
swift_typeref_t *InstanceTypeRef,
|
|
swift_addr_t *StartOfInstanceData) {
|
|
return ContextRef->withContext<int>([&](auto *Context) {
|
|
auto ExistentialTR = reinterpret_cast<const TypeRef *>(ExistentialTypeRef);
|
|
auto RemoteExistentialAddress =
|
|
RemoteAddress(ExistentialAddress, RemoteAddress::DefaultAddressSpace);
|
|
auto Pair = Context->projectExistentialAndUnwrapClass(
|
|
RemoteExistentialAddress, *ExistentialTR);
|
|
if (!Pair.has_value())
|
|
return false;
|
|
*InstanceTypeRef =
|
|
reinterpret_cast<swift_typeref_t>(std::get<const TypeRef *>(*Pair));
|
|
*StartOfInstanceData = std::get<RemoteAddress>(*Pair).getRawAddress();
|
|
|
|
return true;
|
|
});
|
|
}
|
|
|
|
int swift_reflection_projectEnumValue(SwiftReflectionContextRef ContextRef,
|
|
swift_addr_t EnumAddress,
|
|
swift_typeref_t EnumTypeRef,
|
|
int *CaseIndex) {
|
|
return ContextRef->withContext<int>([&](auto *Context) {
|
|
auto EnumTR = reinterpret_cast<const TypeRef *>(EnumTypeRef);
|
|
auto RemoteEnumAddress =
|
|
RemoteAddress(EnumAddress, RemoteAddress::DefaultAddressSpace);
|
|
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) {
|
|
std::cout << "<null type reference>\n";
|
|
} else {
|
|
TR->dump(std::cout);
|
|
}
|
|
}
|
|
|
|
void swift_reflection_dumpInfoForTypeRef(SwiftReflectionContextRef ContextRef,
|
|
swift_typeref_t OpaqueTypeRef) {
|
|
ContextRef->withContext<void>([&](auto *Context) {
|
|
auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
|
|
auto TI = Context->getTypeInfo(TR, nullptr);
|
|
if (TI == nullptr) {
|
|
std::cout << "<null type info>\n";
|
|
} else {
|
|
TI->dump(std::cout);
|
|
Demangle::Demangler Dem;
|
|
auto Mangling = mangleNode(TR->getDemangling(Dem), Mangle::ManglingFlavor::Default);
|
|
std::string MangledName;
|
|
if (Mangling.isSuccess()) {
|
|
MangledName = Mangling.result();
|
|
std::cout << "Mangled name: " << MANGLING_PREFIX_STR << MangledName
|
|
<< "\n";
|
|
} else {
|
|
MangledName = "<failed to mangle name>";
|
|
std::cout
|
|
<< "Failed to get mangled name: Node " << Mangling.error().node
|
|
<< " error " << Mangling.error().code << ":"
|
|
<< Mangling.error().line << "\n";
|
|
}
|
|
|
|
char *DemangledName =
|
|
swift_reflection_copyNameForTypeRef(ContextRef, OpaqueTypeRef, false);
|
|
std::cout << "Demangled name: " << DemangledName << "\n";
|
|
free(DemangledName);
|
|
}
|
|
});
|
|
}
|
|
|
|
void swift_reflection_dumpInfoForMetadata(SwiftReflectionContextRef ContextRef,
|
|
uintptr_t Metadata) {
|
|
ContextRef->withContext<void>([&](auto *Context) {
|
|
auto TI = Context->getMetadataTypeInfo(
|
|
RemoteAddress(Metadata, RemoteAddress::DefaultAddressSpace), nullptr);
|
|
if (TI == nullptr) {
|
|
std::cout << "<null type info>\n";
|
|
} else {
|
|
TI->dump(std::cout);
|
|
}
|
|
});
|
|
}
|
|
|
|
void swift_reflection_dumpInfoForInstance(SwiftReflectionContextRef ContextRef,
|
|
uintptr_t Object) {
|
|
ContextRef->withContext<void>([&](auto *Context) {
|
|
auto TI = Context->getInstanceTypeInfo(
|
|
RemoteAddress(Object, RemoteAddress::DefaultAddressSpace), nullptr);
|
|
if (TI == nullptr) {
|
|
std::cout << "<null type info>\n";
|
|
} else {
|
|
TI->dump(std::cout);
|
|
}
|
|
});
|
|
}
|
|
|
|
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) {
|
|
return ContextRef->withContext<const char *>([&](auto *Context) {
|
|
auto Error = Context->iterateConformances([&](auto Type, auto Proto) {
|
|
Call(Type.getRawAddress(), Proto.getRawAddress(), ContextPtr);
|
|
});
|
|
return returnableCString(ContextRef, Error);
|
|
});
|
|
}
|
|
|
|
const char *swift_reflection_iterateMetadataAllocations(
|
|
SwiftReflectionContextRef ContextRef,
|
|
void (*Call)(swift_metadata_allocation_t Allocation,
|
|
void *ContextPtr),
|
|
void *ContextPtr) {
|
|
return ContextRef->withContext<const char *>([&](auto *Context) {
|
|
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);
|
|
});
|
|
}
|
|
|
|
// Convert Allocation to a MetadataAllocation<Runtime>, where <Runtime> is
|
|
// the same as the <Runtime> template of Context.
|
|
//
|
|
// Accepting the Context parameter is a workaround for templated lambda callers
|
|
// not having direct access to <Runtime>. The Swift project doesn't compile
|
|
// with a new enough C++ version to use explicitly-templated lambdas, so we
|
|
// need some other method of extracting <Runtime>.
|
|
template <typename Runtime>
|
|
static MetadataAllocation<Runtime> convertMetadataAllocation(
|
|
const swift::reflection::ReflectionContext<Runtime> *Context,
|
|
const swift_metadata_allocation_t &Allocation) {
|
|
(void)Context;
|
|
|
|
MetadataAllocation<Runtime> ConvertedAllocation;
|
|
ConvertedAllocation.Tag = Allocation.Tag;
|
|
ConvertedAllocation.Ptr = Allocation.Ptr;
|
|
ConvertedAllocation.Size = Allocation.Size;
|
|
return ConvertedAllocation;
|
|
}
|
|
|
|
swift_reflection_ptr_t swift_reflection_allocationMetadataPointer(
|
|
SwiftReflectionContextRef ContextRef,
|
|
swift_metadata_allocation_t Allocation) {
|
|
return ContextRef->withContext<swift_reflection_ptr_t>([&](auto *Context) {
|
|
auto ConvertedAllocation = convertMetadataAllocation(Context, Allocation);
|
|
return Context->allocationMetadataPointer(ConvertedAllocation);
|
|
});
|
|
}
|
|
|
|
const char *swift_reflection_metadataAllocationTagName(
|
|
SwiftReflectionContextRef ContextRef, swift_metadata_allocation_tag_t Tag) {
|
|
return ContextRef->withContext<const char *>([&](auto *Context) {
|
|
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) {
|
|
return ContextRef->withContext<int>([&](auto *Context) {
|
|
auto ConvertedAllocation = convertMetadataAllocation(Context, Allocation);
|
|
|
|
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) {
|
|
return ContextRef->withContext<const char *>([&](auto *Context) {
|
|
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);
|
|
});
|
|
}
|
|
|
|
swift_async_task_slab_return_t
|
|
swift_reflection_asyncTaskSlabPointer(SwiftReflectionContextRef ContextRef,
|
|
swift_reflection_ptr_t AsyncTaskPtr) {
|
|
return ContextRef->withContext<swift_async_task_slab_return_t>(
|
|
[&](auto *Context) {
|
|
// We only care about the AllocatorSlabPtr field. Disable child task and
|
|
// async backtrace iteration to save wasted work.
|
|
unsigned ChildTaskLimit = 0;
|
|
unsigned AsyncBacktraceLimit = 0;
|
|
|
|
auto [Error, TaskInfo] = Context->asyncTaskInfo(
|
|
RemoteAddress(AsyncTaskPtr, RemoteAddress::DefaultAddressSpace),
|
|
ChildTaskLimit, AsyncBacktraceLimit);
|
|
|
|
swift_async_task_slab_return_t Result = {};
|
|
if (Error) {
|
|
Result.Error = returnableCString(ContextRef, Error);
|
|
}
|
|
Result.SlabPtr = TaskInfo.AllocatorSlabPtr;
|
|
return Result;
|
|
});
|
|
}
|
|
|
|
swift_async_task_slab_allocations_return_t
|
|
swift_reflection_asyncTaskSlabAllocations(SwiftReflectionContextRef ContextRef,
|
|
swift_reflection_ptr_t SlabPtr) {
|
|
return ContextRef->withContext<swift_async_task_slab_allocations_return_t>(
|
|
[&](auto *Context) {
|
|
auto [Error, Info] = Context->asyncTaskSlabAllocations(SlabPtr);
|
|
|
|
swift_async_task_slab_allocations_return_t Result = {};
|
|
if (Result.Error) {
|
|
Result.Error = returnableCString(ContextRef, Error);
|
|
return Result;
|
|
}
|
|
|
|
Result.NextSlab = Info.NextSlab;
|
|
Result.SlabSize = Info.SlabSize;
|
|
|
|
auto *Chunks = ContextRef->allocateTemporaryObject<
|
|
std::vector<swift_async_task_allocation_chunk_t>>();
|
|
Chunks->reserve(Info.Chunks.size());
|
|
for (auto &Chunk : Info.Chunks) {
|
|
swift_async_task_allocation_chunk_t ConvertedChunk;
|
|
ConvertedChunk.Start = Chunk.Start;
|
|
ConvertedChunk.Length = Chunk.Length;
|
|
|
|
// This pedantry is required to properly template over *Context.
|
|
ConvertedChunk.Kind = convertAllocationChunkKind<
|
|
typename std::pointer_traits<decltype(Context)>::element_type>(
|
|
Chunk.Kind);
|
|
|
|
Chunks->push_back(ConvertedChunk);
|
|
}
|
|
|
|
Result.ChunkCount = Chunks->size();
|
|
Result.Chunks = Chunks->data();
|
|
|
|
return Result;
|
|
});
|
|
}
|
|
|
|
swift_async_task_info_t
|
|
swift_reflection_asyncTaskInfo(SwiftReflectionContextRef ContextRef,
|
|
swift_reflection_ptr_t AsyncTaskPtr) {
|
|
return ContextRef->withContext<swift_async_task_info_t>([&](auto *Context) {
|
|
// Limit the child task and async backtrace iteration to semi-reasonable
|
|
// numbers to avoid doing excessive work on bad data.
|
|
unsigned ChildTaskLimit = 1000000;
|
|
unsigned AsyncBacktraceLimit = 1000;
|
|
|
|
auto [Error, TaskInfo] = Context->asyncTaskInfo(
|
|
RemoteAddress(AsyncTaskPtr, RemoteAddress::DefaultAddressSpace),
|
|
ChildTaskLimit, AsyncBacktraceLimit);
|
|
|
|
swift_async_task_info_t Result = {};
|
|
if (Error) {
|
|
Result.Error = returnableCString(ContextRef, Error);
|
|
return Result;
|
|
}
|
|
|
|
Result.Kind = TaskInfo.Kind;
|
|
Result.EnqueuePriority = TaskInfo.EnqueuePriority;
|
|
Result.IsChildTask = TaskInfo.IsChildTask;
|
|
Result.IsFuture = TaskInfo.IsFuture;
|
|
Result.IsGroupChildTask = TaskInfo.IsGroupChildTask;
|
|
Result.IsAsyncLetTask = TaskInfo.IsAsyncLetTask;
|
|
Result.IsSynchronousStartTask = TaskInfo.IsSynchronousStartTask;
|
|
|
|
Result.MaxPriority = TaskInfo.MaxPriority;
|
|
Result.IsCancelled = TaskInfo.IsCancelled;
|
|
Result.IsStatusRecordLocked = TaskInfo.IsStatusRecordLocked;
|
|
Result.IsEscalated = TaskInfo.IsEscalated;
|
|
Result.HasIsRunning = TaskInfo.HasIsRunning;
|
|
Result.IsRunning = TaskInfo.IsRunning;
|
|
Result.IsEnqueued = TaskInfo.IsEnqueued;
|
|
Result.Id = TaskInfo.Id;
|
|
|
|
Result.HasThreadPort = TaskInfo.HasThreadPort;
|
|
Result.ThreadPort = TaskInfo.ThreadPort;
|
|
|
|
Result.RunJob = TaskInfo.RunJob;
|
|
Result.AllocatorSlabPtr = TaskInfo.AllocatorSlabPtr;
|
|
|
|
auto *ChildTasks =
|
|
ContextRef
|
|
->allocateTemporaryObject<std::vector<swift_reflection_ptr_t>>();
|
|
std::copy(TaskInfo.ChildTasks.begin(), TaskInfo.ChildTasks.end(),
|
|
std::back_inserter(*ChildTasks));
|
|
Result.ChildTaskCount = ChildTasks->size();
|
|
Result.ChildTasks = ChildTasks->data();
|
|
|
|
auto *AsyncBacktraceFrames = ContextRef->allocateSubsequentTemporaryObject<
|
|
std::vector<swift_reflection_ptr_t>>();
|
|
std::copy(TaskInfo.AsyncBacktraceFrames.begin(),
|
|
TaskInfo.AsyncBacktraceFrames.end(),
|
|
std::back_inserter(*AsyncBacktraceFrames));
|
|
Result.AsyncBacktraceFramesCount = AsyncBacktraceFrames->size();
|
|
Result.AsyncBacktraceFrames = AsyncBacktraceFrames->data();
|
|
|
|
return Result;
|
|
});
|
|
}
|
|
|
|
swift_actor_info_t
|
|
swift_reflection_actorInfo(SwiftReflectionContextRef ContextRef,
|
|
swift_reflection_ptr_t ActorPtr) {
|
|
return ContextRef->withContext<swift_actor_info_t>([&](auto *Context) {
|
|
auto [Error, ActorInfo] = Context->actorInfo(
|
|
RemoteAddress(ActorPtr, RemoteAddress::DefaultAddressSpace));
|
|
|
|
swift_actor_info_t Result = {};
|
|
Result.Error = returnableCString(ContextRef, Error);
|
|
Result.State = ActorInfo.State;
|
|
Result.IsDistributedRemote = ActorInfo.IsDistributedRemote;
|
|
Result.IsPriorityEscalated = ActorInfo.IsPriorityEscalated;
|
|
Result.MaxPriority = ActorInfo.MaxPriority;
|
|
Result.FirstJob = ActorInfo.FirstJob;
|
|
|
|
Result.HasThreadPort = ActorInfo.HasThreadPort;
|
|
Result.ThreadPort = ActorInfo.ThreadPort;
|
|
|
|
return Result;
|
|
});
|
|
}
|
|
|
|
swift_reflection_ptr_t
|
|
swift_reflection_nextJob(SwiftReflectionContextRef ContextRef,
|
|
swift_reflection_ptr_t JobPtr) {
|
|
return ContextRef->withContext<swift_reflection_ptr_t>([&](auto *Context) {
|
|
return Context->nextJob(
|
|
RemoteAddress(JobPtr, RemoteAddress::DefaultAddressSpace));
|
|
});
|
|
}
|