Skip to content

Commit 4b9cf31

Browse files
committed
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.
1 parent 45be7f2 commit 4b9cf31

File tree

12 files changed

+185
-114
lines changed

12 files changed

+185
-114
lines changed

include/swift/Demangling/TypeDecoder.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,8 @@ class TypeDecoder {
328328

329329
BuilderType &Builder;
330330

331-
public:
332-
explicit TypeDecoder(BuilderType &Builder)
333-
: Builder(Builder) {}
331+
public:
332+
explicit TypeDecoder(BuilderType &Builder) : Builder(Builder) {}
334333

335334
/// Given a demangle tree, attempt to turn it into a type.
336335
BuiltType decodeMangledType(NodePointer Node) {

include/swift/Reflection/ReflectionContext.h

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,9 @@ class ReflectionContext
680680

681681
/// Return a description of the layout of a class instance with the given
682682
/// metadata as its isa pointer.
683-
const TypeInfo *getMetadataTypeInfo(StoredPointer MetadataAddress) {
683+
const TypeInfo *
684+
getMetadataTypeInfo(StoredPointer MetadataAddress,
685+
remote::TypeInfoProvider *ExternalTypeInfo) {
684686
// See if we cached the layout already
685687
auto found = Cache.find(MetadataAddress);
686688
if (found != Cache.end())
@@ -702,7 +704,7 @@ class ReflectionContext
702704

703705
// Perform layout
704706
if (start)
705-
TI = TC.getClassInstanceTypeInfo(TR, *start);
707+
TI = TC.getClassInstanceTypeInfo(TR, *start, ExternalTypeInfo);
706708

707709
break;
708710
}
@@ -718,7 +720,9 @@ class ReflectionContext
718720

719721
/// Return a description of the layout of a class instance with the given
720722
/// metadata as its isa pointer.
721-
const TypeInfo *getInstanceTypeInfo(StoredPointer ObjectAddress) {
723+
const TypeInfo *
724+
getInstanceTypeInfo(StoredPointer ObjectAddress,
725+
remote::TypeInfoProvider *ExternalTypeInfo) {
722726
auto MetadataAddress = readMetadataFromInstance(ObjectAddress);
723727
if (!MetadataAddress)
724728
return nullptr;
@@ -729,7 +733,7 @@ class ReflectionContext
729733

730734
switch (*kind) {
731735
case MetadataKind::Class:
732-
return getMetadataTypeInfo(*MetadataAddress);
736+
return getMetadataTypeInfo(*MetadataAddress, ExternalTypeInfo);
733737

734738
case MetadataKind::HeapLocalVariable: {
735739
auto CDAddr = this->readCaptureDescriptorFromMetadata(*MetadataAddress);
@@ -751,7 +755,7 @@ class ReflectionContext
751755

752756
auto Info = getBuilder().getClosureContextInfo(CD);
753757

754-
return getClosureContextInfo(ObjectAddress, Info);
758+
return getClosureContextInfo(ObjectAddress, Info, ExternalTypeInfo);
755759
}
756760

757761
case MetadataKind::HeapGenericLocalVariable: {
@@ -760,7 +764,8 @@ class ReflectionContext
760764
if (auto Meta = readMetadata(*MetadataAddress)) {
761765
auto GenericHeapMeta =
762766
cast<TargetGenericBoxHeapMetadata<Runtime>>(Meta.getLocalBuffer());
763-
return getMetadataTypeInfo(GenericHeapMeta->BoxedType);
767+
return getMetadataTypeInfo(GenericHeapMeta->BoxedType,
768+
ExternalTypeInfo);
764769
}
765770
return nullptr;
766771
}
@@ -774,15 +779,15 @@ class ReflectionContext
774779
}
775780
}
776781

777-
bool
778-
projectExistential(RemoteAddress ExistentialAddress,
779-
const TypeRef *ExistentialTR,
780-
const TypeRef **OutInstanceTR,
781-
RemoteAddress *OutInstanceAddress) {
782+
bool projectExistential(RemoteAddress ExistentialAddress,
783+
const TypeRef *ExistentialTR,
784+
const TypeRef **OutInstanceTR,
785+
RemoteAddress *OutInstanceAddress,
786+
remote::TypeInfoProvider *ExternalTypeInfo) {
782787
if (ExistentialTR == nullptr)
783788
return false;
784789

785-
auto ExistentialTI = getTypeInfo(ExistentialTR);
790+
auto ExistentialTI = getTypeInfo(ExistentialTR, ExternalTypeInfo);
786791
if (ExistentialTI == nullptr)
787792
return false;
788793

@@ -846,14 +851,14 @@ class ReflectionContext
846851
/// Returns true if the enum case could be successfully determined. In
847852
/// particular, note that this code may return false for valid in-memory data
848853
/// if the compiler used a strategy we do not yet understand.
849-
bool projectEnumValue(RemoteAddress EnumAddress,
850-
const TypeRef *EnumTR,
851-
int *CaseIndex) {
854+
bool projectEnumValue(RemoteAddress EnumAddress, const TypeRef *EnumTR,
855+
int *CaseIndex,
856+
remote::TypeInfoProvider *ExternalTypeInfo) {
852857
// Get the TypeInfo and sanity-check it
853858
if (EnumTR == nullptr) {
854859
return false;
855860
}
856-
auto TI = getTypeInfo(EnumTR);
861+
auto TI = getTypeInfo(EnumTR, ExternalTypeInfo);
857862
if (TI == nullptr) {
858863
return false;
859864
}
@@ -865,11 +870,12 @@ class ReflectionContext
865870
}
866871

867872
/// Return a description of the layout of a value with the given type.
868-
const TypeInfo *getTypeInfo(const TypeRef *TR) {
873+
const TypeInfo *getTypeInfo(const TypeRef *TR,
874+
remote::TypeInfoProvider *ExternalTypeInfo) {
869875
if (TR == nullptr) {
870876
return nullptr;
871877
} else {
872-
return getBuilder().getTypeConverter().getTypeInfo(TR);
878+
return getBuilder().getTypeConverter().getTypeInfo(TR, ExternalTypeInfo);
873879
}
874880
}
875881

@@ -1160,8 +1166,9 @@ class ReflectionContext
11601166
}
11611167

11621168
private:
1163-
const TypeInfo *getClosureContextInfo(StoredPointer Context,
1164-
const ClosureContextInfo &Info) {
1169+
const TypeInfo *
1170+
getClosureContextInfo(StoredPointer Context, const ClosureContextInfo &Info,
1171+
remote::TypeInfoProvider *ExternalTypeInfo) {
11651172
RecordTypeInfoBuilder Builder(getBuilder().getTypeConverter(),
11661173
RecordKind::ClosureContext);
11671174

@@ -1219,7 +1226,7 @@ class ReflectionContext
12191226
SubstCaptureTR = OrigCaptureTR;
12201227

12211228
if (SubstCaptureTR != nullptr) {
1222-
Builder.addField("", SubstCaptureTR);
1229+
Builder.addField("", SubstCaptureTR, ExternalTypeInfo);
12231230
if (Builder.isInvalid())
12241231
return nullptr;
12251232

include/swift/Reflection/TypeLowering.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/ADT/DenseSet.h"
2323
#include "llvm/Support/Casting.h"
2424
#include "swift/Remote/MetadataReader.h"
25+
#include "swift/Remote/TypeInfoProvider.h"
2526

2627
#include <memory>
2728

@@ -347,14 +348,16 @@ class TypeConverter {
347348
///
348349
/// The type must either be concrete, or at least fixed-size, as
349350
/// determined by the isFixedSize() predicate.
350-
const TypeInfo *getTypeInfo(const TypeRef *TR);
351+
const TypeInfo *getTypeInfo(const TypeRef *TR,
352+
remote::TypeInfoProvider *externalInfo);
351353

352354
/// Returns layout information for an instance of the given
353355
/// class.
354356
///
355357
/// Not cached.
356-
const TypeInfo *getClassInstanceTypeInfo(const TypeRef *TR,
357-
unsigned start);
358+
const TypeInfo *
359+
getClassInstanceTypeInfo(const TypeRef *TR, unsigned start,
360+
remote::TypeInfoProvider *ExternalTypeInfo);
358361

359362
private:
360363
friend class swift::reflection::LowerType;
@@ -415,7 +418,8 @@ class RecordTypeInfoBuilder {
415418
bool bitwiseTakable);
416419

417420
// Add a field of a record type, such as a struct.
418-
void addField(const std::string &Name, const TypeRef *TR);
421+
void addField(const std::string &Name, const TypeRef *TR,
422+
remote::TypeInfoProvider *ExternalTypeInfo);
419423

420424
const RecordTypeInfo *build();
421425

include/swift/Reflection/TypeRef.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ class alignas(void *) TypeRef {
156156
bool isConcrete() const;
157157
bool isConcreteAfterSubstitutions(const GenericArgumentMap &Subs) const;
158158

159-
const TypeRef *
160-
subst(TypeRefBuilder &Builder, const GenericArgumentMap &Subs) const;
159+
const TypeRef *subst(TypeRefBuilder &Builder,
160+
const GenericArgumentMap &Subs) const;
161161

162162
llvm::Optional<GenericArgumentMap> getSubstMap() const;
163163

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -634,16 +634,14 @@ class TypeRefBuilder {
634634
const std::string &Member,
635635
StringRef Protocol);
636636

637-
const TypeRef *
638-
lookupSuperclass(const TypeRef *TR);
637+
const TypeRef *lookupSuperclass(const TypeRef *TR);
639638

640639
/// Load unsubstituted field types for a nominal type.
641-
RemoteRef<FieldDescriptor>
642-
getFieldTypeInfo(const TypeRef *TR);
640+
RemoteRef<FieldDescriptor> getFieldTypeInfo(const TypeRef *TR);
643641

644642
/// Get the parsed and substituted field types for a nominal type.
645-
bool getFieldTypeRefs(const TypeRef *TR,
646-
RemoteRef<FieldDescriptor> FD,
643+
bool getFieldTypeRefs(const TypeRef *TR, RemoteRef<FieldDescriptor> FD,
644+
remote::TypeInfoProvider *ExternalTypeInfo,
647645
std::vector<FieldTypeInfo> &Fields);
648646

649647
/// Get the primitive type lowering for a builtin type.

include/swift/Remote/MemoryReader.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ namespace remote {
3737
class MemoryReader {
3838
public:
3939
/// A convenient name for the return type from readBytes.
40-
using ReadBytesResult = std::unique_ptr<const void, std::function<void(const void *)>>;
40+
using ReadBytesResult =
41+
std::unique_ptr<const void, std::function<void(const void *)>>;
4142

4243
virtual bool queryDataLayout(DataLayoutQueryType type, void *inBuffer,
4344
void *outBuffer) = 0;
@@ -152,9 +153,8 @@ class MemoryReader {
152153

153154
return resolvePointer(address, pointerData);
154155
}
155-
156156

157-
// Parse extra inhabitants stored in a pointer.
157+
// Parse extra inhabitants stored in a pointer.
158158
// Sets *extraInhabitant to -1 if the pointer at this address
159159
// is actually a valid pointer.
160160
// Otherwise, it sets *extraInhabitant to the inhabitant
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===--- TypeInfoProvider.h - Abstract access to type info ------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file declares an abstract interface for reading type layout info.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_REMOTE_TYPEINFOPROVIDER_H
18+
#define SWIFT_REMOTE_TYPEINFOPROVIDER_H
19+
20+
namespace swift {
21+
namespace reflection {
22+
class TypeInfo;
23+
}
24+
namespace remote {
25+
26+
/// An abstract interface for providing external type layout information.
27+
struct TypeInfoProvider {
28+
virtual ~TypeInfoProvider() = default;
29+
30+
/// Attempt to read type information about (Clang)imported types that are not
31+
/// represented in the metadata. LLDB can read this information from debug
32+
/// info, for example.
33+
virtual const reflection::TypeInfo *
34+
getTypeInfo(llvm::StringRef mangledName) = 0;
35+
};
36+
37+
} // namespace remote
38+
} // namespace swift
39+
#endif

0 commit comments

Comments
 (0)