mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Add a callback to swift::reflection::MemoryReader that allows LLDB to provide
swift::reflection::TypeInfo for (Clang-)imported non-Objective-C types. This is needed to reflect on the size mixed Swift / Clang types, when no type metadata is available for the C types. This is a necessary ingredient for the TypeRef-based Swift context in LLDB. Because we do not have reflection metadata for pure C types in Swift, reflection cannot compute TypeInfo for NominalTypeRefs for those types. By providing this callback, LLDB can supply this information for DWARF, and reflection can compute TypeInfos for mixed Swift/C types.
This commit is contained in:
@@ -328,9 +328,8 @@ class TypeDecoder {
|
||||
|
||||
BuilderType &Builder;
|
||||
|
||||
public:
|
||||
explicit TypeDecoder(BuilderType &Builder)
|
||||
: Builder(Builder) {}
|
||||
public:
|
||||
explicit TypeDecoder(BuilderType &Builder) : Builder(Builder) {}
|
||||
|
||||
/// Given a demangle tree, attempt to turn it into a type.
|
||||
BuiltType decodeMangledType(NodePointer Node) {
|
||||
|
||||
@@ -680,7 +680,9 @@ public:
|
||||
|
||||
/// Return a description of the layout of a class instance with the given
|
||||
/// metadata as its isa pointer.
|
||||
const TypeInfo *getMetadataTypeInfo(StoredPointer MetadataAddress) {
|
||||
const TypeInfo *
|
||||
getMetadataTypeInfo(StoredPointer MetadataAddress,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
// See if we cached the layout already
|
||||
auto found = Cache.find(MetadataAddress);
|
||||
if (found != Cache.end())
|
||||
@@ -702,7 +704,7 @@ public:
|
||||
|
||||
// Perform layout
|
||||
if (start)
|
||||
TI = TC.getClassInstanceTypeInfo(TR, *start);
|
||||
TI = TC.getClassInstanceTypeInfo(TR, *start, ExternalTypeInfo);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -718,7 +720,9 @@ public:
|
||||
|
||||
/// Return a description of the layout of a class instance with the given
|
||||
/// metadata as its isa pointer.
|
||||
const TypeInfo *getInstanceTypeInfo(StoredPointer ObjectAddress) {
|
||||
const TypeInfo *
|
||||
getInstanceTypeInfo(StoredPointer ObjectAddress,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
auto MetadataAddress = readMetadataFromInstance(ObjectAddress);
|
||||
if (!MetadataAddress)
|
||||
return nullptr;
|
||||
@@ -729,7 +733,7 @@ public:
|
||||
|
||||
switch (*kind) {
|
||||
case MetadataKind::Class:
|
||||
return getMetadataTypeInfo(*MetadataAddress);
|
||||
return getMetadataTypeInfo(*MetadataAddress, ExternalTypeInfo);
|
||||
|
||||
case MetadataKind::HeapLocalVariable: {
|
||||
auto CDAddr = this->readCaptureDescriptorFromMetadata(*MetadataAddress);
|
||||
@@ -751,7 +755,7 @@ public:
|
||||
|
||||
auto Info = getBuilder().getClosureContextInfo(CD);
|
||||
|
||||
return getClosureContextInfo(ObjectAddress, Info);
|
||||
return getClosureContextInfo(ObjectAddress, Info, ExternalTypeInfo);
|
||||
}
|
||||
|
||||
case MetadataKind::HeapGenericLocalVariable: {
|
||||
@@ -760,7 +764,8 @@ public:
|
||||
if (auto Meta = readMetadata(*MetadataAddress)) {
|
||||
auto GenericHeapMeta =
|
||||
cast<TargetGenericBoxHeapMetadata<Runtime>>(Meta.getLocalBuffer());
|
||||
return getMetadataTypeInfo(GenericHeapMeta->BoxedType);
|
||||
return getMetadataTypeInfo(GenericHeapMeta->BoxedType,
|
||||
ExternalTypeInfo);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -774,15 +779,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
projectExistential(RemoteAddress ExistentialAddress,
|
||||
const TypeRef *ExistentialTR,
|
||||
const TypeRef **OutInstanceTR,
|
||||
RemoteAddress *OutInstanceAddress) {
|
||||
bool projectExistential(RemoteAddress ExistentialAddress,
|
||||
const TypeRef *ExistentialTR,
|
||||
const TypeRef **OutInstanceTR,
|
||||
RemoteAddress *OutInstanceAddress,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
if (ExistentialTR == nullptr)
|
||||
return false;
|
||||
|
||||
auto ExistentialTI = getTypeInfo(ExistentialTR);
|
||||
auto ExistentialTI = getTypeInfo(ExistentialTR, ExternalTypeInfo);
|
||||
if (ExistentialTI == nullptr)
|
||||
return false;
|
||||
|
||||
@@ -846,14 +851,14 @@ public:
|
||||
/// Returns true if the enum case could be successfully determined. In
|
||||
/// particular, note that this code may return false for valid in-memory data
|
||||
/// if the compiler used a strategy we do not yet understand.
|
||||
bool projectEnumValue(RemoteAddress EnumAddress,
|
||||
const TypeRef *EnumTR,
|
||||
int *CaseIndex) {
|
||||
bool projectEnumValue(RemoteAddress EnumAddress, const TypeRef *EnumTR,
|
||||
int *CaseIndex,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
// Get the TypeInfo and sanity-check it
|
||||
if (EnumTR == nullptr) {
|
||||
return false;
|
||||
}
|
||||
auto TI = getTypeInfo(EnumTR);
|
||||
auto TI = getTypeInfo(EnumTR, ExternalTypeInfo);
|
||||
if (TI == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -865,11 +870,12 @@ public:
|
||||
}
|
||||
|
||||
/// Return a description of the layout of a value with the given type.
|
||||
const TypeInfo *getTypeInfo(const TypeRef *TR) {
|
||||
const TypeInfo *getTypeInfo(const TypeRef *TR,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
if (TR == nullptr) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return getBuilder().getTypeConverter().getTypeInfo(TR);
|
||||
return getBuilder().getTypeConverter().getTypeInfo(TR, ExternalTypeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1160,8 +1166,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
const TypeInfo *getClosureContextInfo(StoredPointer Context,
|
||||
const ClosureContextInfo &Info) {
|
||||
const TypeInfo *
|
||||
getClosureContextInfo(StoredPointer Context, const ClosureContextInfo &Info,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
RecordTypeInfoBuilder Builder(getBuilder().getTypeConverter(),
|
||||
RecordKind::ClosureContext);
|
||||
|
||||
@@ -1219,7 +1226,7 @@ private:
|
||||
SubstCaptureTR = OrigCaptureTR;
|
||||
|
||||
if (SubstCaptureTR != nullptr) {
|
||||
Builder.addField("", SubstCaptureTR);
|
||||
Builder.addField("", SubstCaptureTR, ExternalTypeInfo);
|
||||
if (Builder.isInvalid())
|
||||
return nullptr;
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "swift/Remote/MetadataReader.h"
|
||||
#include "swift/Remote/TypeInfoProvider.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -347,14 +348,16 @@ public:
|
||||
///
|
||||
/// The type must either be concrete, or at least fixed-size, as
|
||||
/// determined by the isFixedSize() predicate.
|
||||
const TypeInfo *getTypeInfo(const TypeRef *TR);
|
||||
const TypeInfo *getTypeInfo(const TypeRef *TR,
|
||||
remote::TypeInfoProvider *externalInfo);
|
||||
|
||||
/// Returns layout information for an instance of the given
|
||||
/// class.
|
||||
///
|
||||
/// Not cached.
|
||||
const TypeInfo *getClassInstanceTypeInfo(const TypeRef *TR,
|
||||
unsigned start);
|
||||
const TypeInfo *
|
||||
getClassInstanceTypeInfo(const TypeRef *TR, unsigned start,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo);
|
||||
|
||||
private:
|
||||
friend class swift::reflection::LowerType;
|
||||
@@ -415,7 +418,8 @@ public:
|
||||
bool bitwiseTakable);
|
||||
|
||||
// Add a field of a record type, such as a struct.
|
||||
void addField(const std::string &Name, const TypeRef *TR);
|
||||
void addField(const std::string &Name, const TypeRef *TR,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo);
|
||||
|
||||
const RecordTypeInfo *build();
|
||||
|
||||
|
||||
@@ -156,8 +156,8 @@ public:
|
||||
bool isConcrete() const;
|
||||
bool isConcreteAfterSubstitutions(const GenericArgumentMap &Subs) const;
|
||||
|
||||
const TypeRef *
|
||||
subst(TypeRefBuilder &Builder, const GenericArgumentMap &Subs) const;
|
||||
const TypeRef *subst(TypeRefBuilder &Builder,
|
||||
const GenericArgumentMap &Subs) const;
|
||||
|
||||
llvm::Optional<GenericArgumentMap> getSubstMap() const;
|
||||
|
||||
|
||||
@@ -634,16 +634,14 @@ public:
|
||||
const std::string &Member,
|
||||
StringRef Protocol);
|
||||
|
||||
const TypeRef *
|
||||
lookupSuperclass(const TypeRef *TR);
|
||||
const TypeRef *lookupSuperclass(const TypeRef *TR);
|
||||
|
||||
/// Load unsubstituted field types for a nominal type.
|
||||
RemoteRef<FieldDescriptor>
|
||||
getFieldTypeInfo(const TypeRef *TR);
|
||||
RemoteRef<FieldDescriptor> getFieldTypeInfo(const TypeRef *TR);
|
||||
|
||||
/// Get the parsed and substituted field types for a nominal type.
|
||||
bool getFieldTypeRefs(const TypeRef *TR,
|
||||
RemoteRef<FieldDescriptor> FD,
|
||||
bool getFieldTypeRefs(const TypeRef *TR, RemoteRef<FieldDescriptor> FD,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo,
|
||||
std::vector<FieldTypeInfo> &Fields);
|
||||
|
||||
/// Get the primitive type lowering for a builtin type.
|
||||
|
||||
@@ -37,7 +37,8 @@ namespace remote {
|
||||
class MemoryReader {
|
||||
public:
|
||||
/// A convenient name for the return type from readBytes.
|
||||
using ReadBytesResult = std::unique_ptr<const void, std::function<void(const void *)>>;
|
||||
using ReadBytesResult =
|
||||
std::unique_ptr<const void, std::function<void(const void *)>>;
|
||||
|
||||
virtual bool queryDataLayout(DataLayoutQueryType type, void *inBuffer,
|
||||
void *outBuffer) = 0;
|
||||
@@ -152,9 +153,8 @@ public:
|
||||
|
||||
return resolvePointer(address, pointerData);
|
||||
}
|
||||
|
||||
|
||||
// Parse extra inhabitants stored in a pointer.
|
||||
// Parse extra inhabitants stored in a pointer.
|
||||
// Sets *extraInhabitant to -1 if the pointer at this address
|
||||
// is actually a valid pointer.
|
||||
// Otherwise, it sets *extraInhabitant to the inhabitant
|
||||
|
||||
39
include/swift/Remote/TypeInfoProvider.h
Normal file
39
include/swift/Remote/TypeInfoProvider.h
Normal file
@@ -0,0 +1,39 @@
|
||||
//===--- TypeInfoProvider.h - Abstract access to type info ------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares an abstract interface for reading type layout info.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_REMOTE_TYPEINFOPROVIDER_H
|
||||
#define SWIFT_REMOTE_TYPEINFOPROVIDER_H
|
||||
|
||||
namespace swift {
|
||||
namespace reflection {
|
||||
class TypeInfo;
|
||||
}
|
||||
namespace remote {
|
||||
|
||||
/// An abstract interface for providing external type layout information.
|
||||
struct TypeInfoProvider {
|
||||
virtual ~TypeInfoProvider() = default;
|
||||
|
||||
/// Attempt to read type information about (Clang)imported types that are not
|
||||
/// represented in the metadata. LLDB can read this information from debug
|
||||
/// info, for example.
|
||||
virtual const reflection::TypeInfo *
|
||||
getTypeInfo(llvm::StringRef mangledName) = 0;
|
||||
};
|
||||
|
||||
} // namespace remote
|
||||
} // namespace swift
|
||||
#endif
|
||||
@@ -1034,7 +1034,10 @@ class ExistentialTypeInfoBuilder {
|
||||
++WitnessTableCount;
|
||||
|
||||
if (auto *Superclass = TC.getBuilder().lookupSuperclass(P)) {
|
||||
auto *SuperclassTI = TC.getTypeInfo(Superclass);
|
||||
// ObjC class info should be available in the metadata, so it's safe
|
||||
// to not pass an external provider here. This helps preserving the
|
||||
// layering.
|
||||
auto *SuperclassTI = TC.getTypeInfo(Superclass, nullptr);
|
||||
if (SuperclassTI == nullptr) {
|
||||
DEBUG_LOG(fprintf(stderr, "No TypeInfo for superclass: ");
|
||||
Superclass->dump());
|
||||
@@ -1140,7 +1143,7 @@ public:
|
||||
Invalid = true;
|
||||
}
|
||||
|
||||
const TypeInfo *build() {
|
||||
const TypeInfo *build(remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
examineProtocols();
|
||||
|
||||
if (Invalid)
|
||||
@@ -1176,12 +1179,14 @@ public:
|
||||
// Class existentials consist of a single retainable pointer
|
||||
// followed by witness tables.
|
||||
if (Refcounting == ReferenceCounting::Unknown)
|
||||
builder.addField("object", TC.getUnknownObjectTypeRef());
|
||||
builder.addField("object", TC.getUnknownObjectTypeRef(),
|
||||
ExternalTypeInfo);
|
||||
else
|
||||
builder.addField("object", TC.getNativeObjectTypeRef());
|
||||
builder.addField("object", TC.getNativeObjectTypeRef(),
|
||||
ExternalTypeInfo);
|
||||
break;
|
||||
case ExistentialTypeRepresentation::Opaque: {
|
||||
auto *TI = TC.getTypeInfo(TC.getRawPointerTypeRef());
|
||||
auto *TI = TC.getTypeInfo(TC.getRawPointerTypeRef(), ExternalTypeInfo);
|
||||
if (TI == nullptr) {
|
||||
DEBUG_LOG(fprintf(stderr, "No TypeInfo for RawPointer\n"));
|
||||
return nullptr;
|
||||
@@ -1195,21 +1200,21 @@ public:
|
||||
TI->getAlignment(),
|
||||
/*numExtraInhabitants=*/0,
|
||||
/*bitwiseTakable=*/true);
|
||||
builder.addField("metadata", TC.getAnyMetatypeTypeRef());
|
||||
builder.addField("metadata", TC.getAnyMetatypeTypeRef(), ExternalTypeInfo);
|
||||
break;
|
||||
}
|
||||
case ExistentialTypeRepresentation::Error:
|
||||
builder.addField("error", TC.getUnknownObjectTypeRef());
|
||||
builder.addField("error", TC.getUnknownObjectTypeRef(), ExternalTypeInfo);
|
||||
break;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < WitnessTableCount; ++i)
|
||||
builder.addField("wtable", TC.getRawPointerTypeRef());
|
||||
builder.addField("wtable", TC.getRawPointerTypeRef(), ExternalTypeInfo);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
const TypeInfo *buildMetatype() {
|
||||
const TypeInfo *buildMetatype(remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
examineProtocols();
|
||||
|
||||
if (Invalid)
|
||||
@@ -1226,9 +1231,9 @@ public:
|
||||
|
||||
RecordTypeInfoBuilder builder(TC, RecordKind::ExistentialMetatype);
|
||||
|
||||
builder.addField("metadata", TC.getAnyMetatypeTypeRef());
|
||||
builder.addField("metadata", TC.getAnyMetatypeTypeRef(), ExternalTypeInfo);
|
||||
for (unsigned i = 0; i < WitnessTableCount; ++i)
|
||||
builder.addField("wtable", TC.getRawPointerTypeRef());
|
||||
builder.addField("wtable", TC.getRawPointerTypeRef(), ExternalTypeInfo);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
@@ -1285,9 +1290,10 @@ unsigned RecordTypeInfoBuilder::addField(unsigned fieldSize,
|
||||
return offset;
|
||||
}
|
||||
|
||||
void RecordTypeInfoBuilder::addField(const std::string &Name,
|
||||
const TypeRef *TR) {
|
||||
const TypeInfo *TI = TC.getTypeInfo(TR);
|
||||
void RecordTypeInfoBuilder::addField(
|
||||
const std::string &Name, const TypeRef *TR,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
const TypeInfo *TI = TC.getTypeInfo(TR, ExternalTypeInfo);
|
||||
if (TI == nullptr) {
|
||||
DEBUG_LOG(fprintf(stderr, "No TypeInfo for field type: "); TR->dump());
|
||||
Invalid = true;
|
||||
@@ -1394,14 +1400,13 @@ TypeConverter::getThinFunctionTypeInfo() {
|
||||
/// Thick functions consist of a function pointer and nullable retainable
|
||||
/// context pointer. The context is modeled exactly like a native Swift
|
||||
/// class reference.
|
||||
const TypeInfo *
|
||||
TypeConverter::getThickFunctionTypeInfo() {
|
||||
const TypeInfo *TypeConverter::getThickFunctionTypeInfo() {
|
||||
if (ThickFunctionTI != nullptr)
|
||||
return ThickFunctionTI;
|
||||
|
||||
RecordTypeInfoBuilder builder(*this, RecordKind::ThickFunction);
|
||||
builder.addField("function", getThinFunctionTypeRef());
|
||||
builder.addField("context", getNativeObjectTypeRef());
|
||||
builder.addField("function", getThinFunctionTypeRef(), nullptr);
|
||||
builder.addField("context", getNativeObjectTypeRef(), nullptr);
|
||||
ThickFunctionTI = builder.build();
|
||||
|
||||
return ThickFunctionTI;
|
||||
@@ -1758,14 +1763,14 @@ public:
|
||||
: TC(TC), Size(0), Alignment(1), NumExtraInhabitants(0),
|
||||
BitwiseTakable(true), Invalid(false) {}
|
||||
|
||||
const TypeInfo *
|
||||
build(const TypeRef *TR, RemoteRef<FieldDescriptor> FD) {
|
||||
const TypeInfo *build(const TypeRef *TR, RemoteRef<FieldDescriptor> FD,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
// Sort enum into payload and no-payload cases.
|
||||
unsigned NoPayloadCases = 0;
|
||||
std::vector<FieldTypeInfo> PayloadCases;
|
||||
|
||||
std::vector<FieldTypeInfo> Fields;
|
||||
if (!TC.getBuilder().getFieldTypeRefs(TR, FD, Fields)) {
|
||||
if (!TC.getBuilder().getFieldTypeRefs(TR, FD, ExternalTypeInfo, Fields)) {
|
||||
Invalid = true;
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1777,7 +1782,7 @@ public:
|
||||
} else {
|
||||
PayloadCases.push_back(Case);
|
||||
auto *CaseTR = getCaseTypeRef(Case);
|
||||
auto *CaseTI = TC.getTypeInfo(CaseTR);
|
||||
auto *CaseTI = TC.getTypeInfo(CaseTR, ExternalTypeInfo);
|
||||
addCase(Case.Name, CaseTR, CaseTI);
|
||||
}
|
||||
}
|
||||
@@ -1810,7 +1815,7 @@ public:
|
||||
} else if (PayloadCases.size() == 1) {
|
||||
// SinglePayloadEnumImplStrategy
|
||||
auto *CaseTR = getCaseTypeRef(PayloadCases[0]);
|
||||
auto *CaseTI = TC.getTypeInfo(CaseTR);
|
||||
auto *CaseTI = TC.getTypeInfo(CaseTR, ExternalTypeInfo);
|
||||
if (CaseTR == nullptr || CaseTI == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1910,11 +1915,13 @@ public:
|
||||
class LowerType
|
||||
: public TypeRefVisitor<LowerType, const TypeInfo *> {
|
||||
TypeConverter &TC;
|
||||
remote::TypeInfoProvider *ExternalTypeInfo;
|
||||
|
||||
public:
|
||||
using TypeRefVisitor<LowerType, const TypeInfo *>::visit;
|
||||
|
||||
LowerType(TypeConverter &TC) : TC(TC) {}
|
||||
LowerType(TypeConverter &TC, remote::TypeInfoProvider *ExternalTypeInfo)
|
||||
: TC(TC), ExternalTypeInfo(ExternalTypeInfo) {}
|
||||
|
||||
const TypeInfo *visitBuiltinTypeRef(const BuiltinTypeRef *B) {
|
||||
/// The context field of a thick function is a Builtin.NativeObject.
|
||||
@@ -1950,6 +1957,18 @@ public:
|
||||
|
||||
// Otherwise, we're out of luck.
|
||||
if (FD == nullptr) {
|
||||
if (ExternalTypeInfo) {
|
||||
// Ask the ExternalTypeInfo. It may be a Clang-imported type.
|
||||
std::string MangledName;
|
||||
if (auto N = dyn_cast<NominalTypeRef>(TR))
|
||||
MangledName = N->getMangledName();
|
||||
else if (auto BG = dyn_cast<BoundGenericTypeRef>(TR))
|
||||
MangledName = BG->getMangledName();
|
||||
if (!MangledName.empty())
|
||||
if (auto *imported = ExternalTypeInfo->getTypeInfo(MangledName))
|
||||
return imported;
|
||||
}
|
||||
|
||||
DEBUG_LOG(fprintf(stderr, "No TypeInfo for nominal type: "); TR->dump());
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1966,17 +1985,17 @@ public:
|
||||
RecordTypeInfoBuilder builder(TC, RecordKind::Struct);
|
||||
|
||||
std::vector<FieldTypeInfo> Fields;
|
||||
if (!TC.getBuilder().getFieldTypeRefs(TR, FD, Fields))
|
||||
if (!TC.getBuilder().getFieldTypeRefs(TR, FD, ExternalTypeInfo, Fields))
|
||||
return nullptr;
|
||||
|
||||
for (auto Field : Fields)
|
||||
builder.addField(Field.Name, Field.TR);
|
||||
builder.addField(Field.Name, Field.TR, ExternalTypeInfo);
|
||||
return builder.build();
|
||||
}
|
||||
case FieldDescriptorKind::Enum:
|
||||
case FieldDescriptorKind::MultiPayloadEnum: {
|
||||
EnumTypeInfoBuilder builder(TC);
|
||||
return builder.build(TR, FD);
|
||||
return builder.build(TR, FD, ExternalTypeInfo);
|
||||
}
|
||||
case FieldDescriptorKind::ObjCClass:
|
||||
return TC.getReferenceTypeInfo(ReferenceKind::Strong,
|
||||
@@ -2002,7 +2021,7 @@ public:
|
||||
const TypeInfo *visitTupleTypeRef(const TupleTypeRef *T) {
|
||||
RecordTypeInfoBuilder builder(TC, RecordKind::Tuple);
|
||||
for (auto Element : T->getElements())
|
||||
builder.addField("", Element);
|
||||
builder.addField("", Element, ExternalTypeInfo);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@@ -2016,7 +2035,7 @@ public:
|
||||
ReferenceCounting::Unknown);
|
||||
case FunctionMetadataConvention::Thin:
|
||||
case FunctionMetadataConvention::CFunctionPointer:
|
||||
return TC.getTypeInfo(TC.getThinFunctionTypeRef());
|
||||
return TC.getTypeInfo(TC.getThinFunctionTypeRef(), ExternalTypeInfo);
|
||||
}
|
||||
|
||||
swift_runtime_unreachable("Unhandled FunctionMetadataConvention in switch.");
|
||||
@@ -2026,7 +2045,7 @@ public:
|
||||
visitProtocolCompositionTypeRef(const ProtocolCompositionTypeRef *PC) {
|
||||
ExistentialTypeInfoBuilder builder(TC);
|
||||
builder.addProtocolComposition(PC);
|
||||
return builder.build();
|
||||
return builder.build(ExternalTypeInfo);
|
||||
}
|
||||
|
||||
const TypeInfo *visitMetatypeTypeRef(const MetatypeTypeRef *M) {
|
||||
@@ -2037,7 +2056,7 @@ public:
|
||||
case MetatypeRepresentation::Thin:
|
||||
return TC.getEmptyTypeInfo();
|
||||
case MetatypeRepresentation::Thick:
|
||||
return TC.getTypeInfo(TC.getAnyMetatypeTypeRef());
|
||||
return TC.getTypeInfo(TC.getAnyMetatypeTypeRef(), ExternalTypeInfo);
|
||||
}
|
||||
|
||||
swift_runtime_unreachable("Unhandled MetatypeRepresentation in switch.");
|
||||
@@ -2055,7 +2074,7 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return builder.buildMetatype();
|
||||
return builder.buildMetatype(ExternalTypeInfo);
|
||||
}
|
||||
|
||||
const TypeInfo *
|
||||
@@ -2102,7 +2121,7 @@ public:
|
||||
|
||||
if (auto *EnumTI = dyn_cast<EnumTypeInfo>(TI)) {
|
||||
if (EnumTI->isOptional() && Kind == ReferenceKind::Weak) {
|
||||
auto *TI = TC.getTypeInfo(EnumTI->getCases()[0].TR);
|
||||
auto *TI = TC.getTypeInfo(EnumTI->getCases()[0].TR, ExternalTypeInfo);
|
||||
return rebuildStorageTypeInfo(TI, Kind);
|
||||
}
|
||||
}
|
||||
@@ -2142,7 +2161,7 @@ public:
|
||||
|
||||
const TypeInfo *
|
||||
visitAnyStorageTypeRef(const TypeRef *TR, ReferenceKind Kind) {
|
||||
return rebuildStorageTypeInfo(TC.getTypeInfo(TR), Kind);
|
||||
return rebuildStorageTypeInfo(TC.getTypeInfo(TR, ExternalTypeInfo), Kind);
|
||||
}
|
||||
|
||||
#define REF_STORAGE(Name, name, ...) \
|
||||
@@ -2170,7 +2189,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
const TypeInfo *TypeConverter::getTypeInfo(const TypeRef *TR) {
|
||||
const TypeInfo *
|
||||
TypeConverter::getTypeInfo(const TypeRef *TR,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
// See if we already computed the result
|
||||
auto found = Cache.find(TR);
|
||||
if (found != Cache.end())
|
||||
@@ -2184,7 +2205,7 @@ const TypeInfo *TypeConverter::getTypeInfo(const TypeRef *TR) {
|
||||
}
|
||||
|
||||
// Compute the result and cache it
|
||||
auto *TI = LowerType(*this).visit(TR);
|
||||
auto *TI = LowerType(*this, ExternalTypeInfo).visit(TR);
|
||||
Cache[TR] = TI;
|
||||
|
||||
RecursionCheck.erase(TR);
|
||||
@@ -2192,8 +2213,9 @@ const TypeInfo *TypeConverter::getTypeInfo(const TypeRef *TR) {
|
||||
return TI;
|
||||
}
|
||||
|
||||
const TypeInfo *TypeConverter::getClassInstanceTypeInfo(const TypeRef *TR,
|
||||
unsigned start) {
|
||||
const TypeInfo *TypeConverter::getClassInstanceTypeInfo(
|
||||
const TypeRef *TR, unsigned start,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo) {
|
||||
auto FD = getBuilder().getFieldTypeInfo(TR);
|
||||
if (FD == nullptr) {
|
||||
DEBUG_LOG(fprintf(stderr, "No field descriptor: "); TR->dump());
|
||||
@@ -2208,7 +2230,7 @@ const TypeInfo *TypeConverter::getClassInstanceTypeInfo(const TypeRef *TR,
|
||||
RecordTypeInfoBuilder builder(*this, RecordKind::ClassInstance);
|
||||
|
||||
std::vector<FieldTypeInfo> Fields;
|
||||
if (!getBuilder().getFieldTypeRefs(TR, FD, Fields))
|
||||
if (!getBuilder().getFieldTypeRefs(TR, FD, ExternalTypeInfo, Fields))
|
||||
return nullptr;
|
||||
|
||||
// Start layout from the given instance start offset. This should
|
||||
@@ -2219,7 +2241,7 @@ const TypeInfo *TypeConverter::getClassInstanceTypeInfo(const TypeRef *TR,
|
||||
/*bitwiseTakable=*/true);
|
||||
|
||||
for (auto Field : Fields)
|
||||
builder.addField(Field.Name, Field.TR);
|
||||
builder.addField(Field.Name, Field.TR, ExternalTypeInfo);
|
||||
return builder.build();
|
||||
}
|
||||
case FieldDescriptorKind::Struct:
|
||||
|
||||
@@ -901,7 +901,7 @@ public:
|
||||
using TypeRefVisitor<TypeRefSubstitution, const TypeRef *>::visit;
|
||||
|
||||
TypeRefSubstitution(TypeRefBuilder &Builder, GenericArgumentMap Substitutions)
|
||||
: Builder(Builder), Substitutions(Substitutions) {}
|
||||
: Builder(Builder), Substitutions(Substitutions) {}
|
||||
|
||||
const TypeRef *visitBuiltinTypeRef(const BuiltinTypeRef *B) {
|
||||
return B;
|
||||
@@ -1081,8 +1081,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
const TypeRef *
|
||||
TypeRef::subst(TypeRefBuilder &Builder, const GenericArgumentMap &Subs) const {
|
||||
const TypeRef *TypeRef::subst(TypeRefBuilder &Builder,
|
||||
const GenericArgumentMap &Subs) const {
|
||||
return TypeRefSubstitution(Builder, Subs).visit(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -145,8 +145,7 @@ lookupTypeWitness(const std::string &MangledTypeName,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const TypeRef * TypeRefBuilder::
|
||||
lookupSuperclass(const TypeRef *TR) {
|
||||
const TypeRef *TypeRefBuilder::lookupSuperclass(const TypeRef *TR) {
|
||||
const auto &FD = getFieldTypeInfo(TR);
|
||||
if (FD == nullptr)
|
||||
return nullptr;
|
||||
@@ -202,8 +201,8 @@ TypeRefBuilder::getFieldTypeInfo(const TypeRef *TR) {
|
||||
}
|
||||
|
||||
bool TypeRefBuilder::getFieldTypeRefs(
|
||||
const TypeRef *TR,
|
||||
RemoteRef<FieldDescriptor> FD,
|
||||
const TypeRef *TR, RemoteRef<FieldDescriptor> FD,
|
||||
remote::TypeInfoProvider *ExternalTypeInfo,
|
||||
std::vector<FieldTypeInfo> &Fields) {
|
||||
if (FD == nullptr)
|
||||
return false;
|
||||
|
||||
@@ -471,7 +471,7 @@ 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);
|
||||
auto TI = Context->getTypeInfo(TR, nullptr);
|
||||
return convertTypeInfo(TI);
|
||||
}
|
||||
|
||||
@@ -481,7 +481,7 @@ swift_reflection_childOfTypeRef(SwiftReflectionContextRef ContextRef,
|
||||
unsigned Index) {
|
||||
auto Context = ContextRef->nativeContext;
|
||||
auto TR = reinterpret_cast<const TypeRef *>(OpaqueTypeRef);
|
||||
auto *TI = Context->getTypeInfo(TR);
|
||||
auto *TI = Context->getTypeInfo(TR, nullptr);
|
||||
return convertChild(TI, Index);
|
||||
}
|
||||
|
||||
@@ -489,7 +489,7 @@ swift_typeinfo_t
|
||||
swift_reflection_infoForMetadata(SwiftReflectionContextRef ContextRef,
|
||||
uintptr_t Metadata) {
|
||||
auto Context = ContextRef->nativeContext;
|
||||
auto *TI = Context->getMetadataTypeInfo(Metadata);
|
||||
auto *TI = Context->getMetadataTypeInfo(Metadata, nullptr);
|
||||
return convertTypeInfo(TI);
|
||||
}
|
||||
|
||||
@@ -498,7 +498,7 @@ swift_reflection_childOfMetadata(SwiftReflectionContextRef ContextRef,
|
||||
uintptr_t Metadata,
|
||||
unsigned Index) {
|
||||
auto Context = ContextRef->nativeContext;
|
||||
auto *TI = Context->getMetadataTypeInfo(Metadata);
|
||||
auto *TI = Context->getMetadataTypeInfo(Metadata, nullptr);
|
||||
return convertChild(TI, Index);
|
||||
}
|
||||
|
||||
@@ -506,7 +506,7 @@ swift_typeinfo_t
|
||||
swift_reflection_infoForInstance(SwiftReflectionContextRef ContextRef,
|
||||
uintptr_t Object) {
|
||||
auto Context = ContextRef->nativeContext;
|
||||
auto *TI = Context->getInstanceTypeInfo(Object);
|
||||
auto *TI = Context->getInstanceTypeInfo(Object, nullptr);
|
||||
return convertTypeInfo(TI);
|
||||
}
|
||||
|
||||
@@ -515,7 +515,7 @@ swift_reflection_childOfInstance(SwiftReflectionContextRef ContextRef,
|
||||
uintptr_t Object,
|
||||
unsigned Index) {
|
||||
auto Context = ContextRef->nativeContext;
|
||||
auto *TI = Context->getInstanceTypeInfo(Object);
|
||||
auto *TI = Context->getInstanceTypeInfo(Object, nullptr);
|
||||
return convertChild(TI, Index);
|
||||
}
|
||||
|
||||
@@ -529,10 +529,9 @@ int swift_reflection_projectExistential(SwiftReflectionContextRef ContextRef,
|
||||
auto RemoteExistentialAddress = RemoteAddress(ExistentialAddress);
|
||||
const TypeRef *InstanceTR = nullptr;
|
||||
RemoteAddress RemoteStartOfInstanceData(nullptr);
|
||||
auto Success = Context->projectExistential(RemoteExistentialAddress,
|
||||
ExistentialTR,
|
||||
&InstanceTR,
|
||||
&RemoteStartOfInstanceData);
|
||||
auto Success = Context->projectExistential(
|
||||
RemoteExistentialAddress, ExistentialTR, &InstanceTR,
|
||||
&RemoteStartOfInstanceData, nullptr);
|
||||
|
||||
if (Success) {
|
||||
*InstanceTypeRef = reinterpret_cast<swift_typeref_t>(InstanceTR);
|
||||
@@ -549,10 +548,11 @@ int swift_reflection_projectEnumValue(SwiftReflectionContextRef ContextRef,
|
||||
auto Context = ContextRef->nativeContext;
|
||||
auto EnumTR = reinterpret_cast<const TypeRef *>(EnumTypeRef);
|
||||
auto RemoteEnumAddress = RemoteAddress(EnumAddress);
|
||||
if (!Context->projectEnumValue(RemoteEnumAddress, EnumTR, CaseIndex)) {
|
||||
if (!Context->projectEnumValue(RemoteEnumAddress, EnumTR, CaseIndex,
|
||||
nullptr)) {
|
||||
return false;
|
||||
}
|
||||
auto TI = Context->getTypeInfo(EnumTR);
|
||||
auto TI = Context->getTypeInfo(EnumTR, nullptr);
|
||||
auto *RecordTI = dyn_cast<EnumTypeInfo>(TI);
|
||||
assert(RecordTI != nullptr);
|
||||
if (static_cast<size_t>(*CaseIndex) >= RecordTI->getNumCases()) {
|
||||
@@ -574,7 +574,7 @@ 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);
|
||||
auto TI = Context->getTypeInfo(TR, nullptr);
|
||||
if (TI == nullptr) {
|
||||
fprintf(stdout, "<null type info>\n");
|
||||
} else {
|
||||
@@ -599,7 +599,7 @@ void swift_reflection_dumpInfoForTypeRef(SwiftReflectionContextRef ContextRef,
|
||||
void swift_reflection_dumpInfoForMetadata(SwiftReflectionContextRef ContextRef,
|
||||
uintptr_t Metadata) {
|
||||
auto Context = ContextRef->nativeContext;
|
||||
auto TI = Context->getMetadataTypeInfo(Metadata);
|
||||
auto TI = Context->getMetadataTypeInfo(Metadata, nullptr);
|
||||
if (TI == nullptr) {
|
||||
fprintf(stdout, "<null type info>\n");
|
||||
} else {
|
||||
@@ -610,7 +610,7 @@ void swift_reflection_dumpInfoForMetadata(SwiftReflectionContextRef ContextRef,
|
||||
void swift_reflection_dumpInfoForInstance(SwiftReflectionContextRef ContextRef,
|
||||
uintptr_t Object) {
|
||||
auto Context = ContextRef->nativeContext;
|
||||
auto TI = Context->getInstanceTypeInfo(Object);
|
||||
auto TI = Context->getInstanceTypeInfo(Object, nullptr);
|
||||
if (TI == nullptr) {
|
||||
fprintf(stdout, "%s", "<null type info>\n");
|
||||
} else {
|
||||
|
||||
@@ -583,25 +583,28 @@ public:
|
||||
using ReflectionContextOwner
|
||||
= std::unique_ptr<void, void (*)(void*)>;
|
||||
|
||||
template<typename Runtime>
|
||||
static std::pair<ReflectionContextOwner, TypeRefBuilder &>
|
||||
makeReflectionContextForMetadataReader(
|
||||
std::shared_ptr<ObjectMemoryReader> reader) {
|
||||
struct ReflectionContextHolder {
|
||||
ReflectionContextOwner Owner;
|
||||
TypeRefBuilder &Builder;
|
||||
ObjectMemoryReader &Reader;
|
||||
};
|
||||
|
||||
template <typename Runtime>
|
||||
static ReflectionContextHolder makeReflectionContextForMetadataReader(
|
||||
std::shared_ptr<ObjectMemoryReader> reader) {
|
||||
using ReflectionContext = ReflectionContext<Runtime>;
|
||||
auto context = new ReflectionContext(reader);
|
||||
auto &builder = context->getBuilder();
|
||||
for (unsigned i = 0, e = reader->getImages().size(); i < e; ++i) {
|
||||
context->addImage(reader->getImageStartAddress(i));
|
||||
}
|
||||
return {ReflectionContextOwner(context,
|
||||
[](void *x){ delete (ReflectionContext*)x; }),
|
||||
builder};
|
||||
return {ReflectionContextOwner(
|
||||
context, [](void *x) { delete (ReflectionContext *)x; }),
|
||||
builder, *reader};
|
||||
}
|
||||
|
||||
|
||||
static std::pair<ReflectionContextOwner, TypeRefBuilder &>
|
||||
makeReflectionContextForObjectFiles(
|
||||
const std::vector<const ObjectFile *> &objectFiles) {
|
||||
static ReflectionContextHolder makeReflectionContextForObjectFiles(
|
||||
const std::vector<const ObjectFile *> &objectFiles) {
|
||||
auto Reader = std::make_shared<ObjectMemoryReader>(objectFiles);
|
||||
|
||||
uint8_t pointerSize;
|
||||
@@ -651,7 +654,7 @@ static int doDumpReflectionSections(ArrayRef<std::string> BinaryFilenames,
|
||||
}
|
||||
|
||||
auto context = makeReflectionContextForObjectFiles(ObjectFiles);
|
||||
auto &builder = context.second;
|
||||
auto &builder = context.Builder;
|
||||
|
||||
switch (Action) {
|
||||
case ActionType::DumpReflectionSections:
|
||||
@@ -676,7 +679,7 @@ static int doDumpReflectionSections(ArrayRef<std::string> BinaryFilenames,
|
||||
}
|
||||
|
||||
TypeRef->dump(file);
|
||||
auto *TypeInfo = builder.getTypeConverter().getTypeInfo(TypeRef);
|
||||
auto *TypeInfo = builder.getTypeConverter().getTypeInfo(TypeRef, nullptr);
|
||||
if (TypeInfo == nullptr) {
|
||||
fprintf(file, "Invalid lowering\n");
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user