Skip to content

Commit ae65e1c

Browse files
authored
Merge pull request #3269 from slavapestov/single-payload-enum-reflection
Single payload enum reflection
2 parents a663e79 + 3937f4c commit ae65e1c

File tree

17 files changed

+988
-527
lines changed

17 files changed

+988
-527
lines changed

include/swift/Reflection/Records.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,21 @@ namespace reflection {
2727
class FieldRecordFlags {
2828
using int_type = uint32_t;
2929
enum : int_type {
30-
IsObjC = 0x00000001,
30+
// Is this an indirect enum case?
31+
IsIndirectCase = 0x1
3132
};
3233
int_type Data;
34+
3335
public:
34-
bool isObjC() const {
35-
return Data & IsObjC;
36+
bool isIndirectCase() const {
37+
return (Data & IsIndirectCase) == IsIndirectCase;
3638
}
3739

38-
void setIsObjC(bool ObjC) {
39-
if (ObjC)
40-
Data |= IsObjC;
40+
void setIsIndirectCase(bool IndirectCase=true) {
41+
if (IndirectCase)
42+
Data |= IsIndirectCase;
4143
else
42-
Data &= ~IsObjC;
44+
Data &= ~IsIndirectCase;
4345
}
4446

4547
int_type getRawValue() const {
@@ -69,8 +71,8 @@ class FieldRecord {
6971
return "";
7072
}
7173

72-
bool isObjC() const {
73-
return Flags.isObjC();
74+
bool isIndirectCase() const {
75+
return Flags.isIndirectCase();
7476
}
7577
};
7678

include/swift/Reflection/ReflectionContext.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ class ReflectionContext
190190
// Class existentials have trivial layout.
191191
// It is itself the pointer to the instance followed by the witness tables.
192192
case RecordKind::ClassExistential:
193-
*OutInstanceTR = getBuilder().getTypeConverter().getUnknownObjectTypeRef();
193+
// This is just Builtin.UnknownObject
194+
*OutInstanceTR = ExistentialRecordTI->getFields()[0].TR;
194195
*OutInstanceAddress = ExistentialAddress;
195196
return true;
196197

@@ -342,11 +343,13 @@ class ReflectionContext
342343
return nullptr;
343344

344345
// Initialize the builder.
345-
Builder.addField(OffsetToFirstCapture.second, sizeof(StoredPointer));
346+
Builder.addField(OffsetToFirstCapture.second, sizeof(StoredPointer),
347+
/*numExtraInhabitants=*/0);
346348

347349
// Skip the closure's necessary bindings struct, if it's present.
348350
auto SizeOfNecessaryBindings = Info.NumBindings * sizeof(StoredPointer);
349-
Builder.addField(SizeOfNecessaryBindings, sizeof(StoredPointer));
351+
Builder.addField(SizeOfNecessaryBindings, sizeof(StoredPointer),
352+
/*numExtraInhabitants=*/0);
350353

351354
// FIXME: should be unordered_set but I'm too lazy to write a hash
352355
// functor

include/swift/Reflection/TypeLowering.h

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,23 @@ class TypeRef;
3434
class TypeRefBuilder;
3535
class BuiltinTypeDescriptor;
3636

37+
// Defined in TypeLowering.cpp, not public -- they're friends below
38+
class LowerType;
39+
class RecordTypeInfoBuilder;
40+
class ExistentialTypeInfoBuilder;
41+
3742
enum class RecordKind : unsigned {
3843
Tuple,
3944
Struct,
4045

46+
// An enum with no payload cases. The record will have no fields, but
47+
// will have the correct size.
48+
NoPayloadEnum,
49+
50+
// An enum with a single payload case. The record consists of a single
51+
// field, being the enum payload.
52+
SinglePayloadEnum,
53+
4154
// A Swift-native function is always a function pointer followed by a
4255
// retainable, nullable context pointer.
4356
ThickFunction,
@@ -185,10 +198,16 @@ class TypeConverter {
185198
llvm::DenseMap<const TypeRef *, const TypeInfo *> Cache;
186199
llvm::DenseMap<std::pair<unsigned, unsigned>,
187200
const ReferenceTypeInfo *> ReferenceCache;
201+
188202
const TypeRef *RawPointerTR = nullptr;
189203
const TypeRef *NativeObjectTR = nullptr;
190204
const TypeRef *UnknownObjectTR = nullptr;
205+
const TypeRef *ThinFunctionTR = nullptr;
206+
const TypeRef *AnyMetatypeTR = nullptr;
207+
208+
const TypeInfo *ThinFunctionTI = nullptr;
191209
const TypeInfo *ThickFunctionTI = nullptr;
210+
const TypeInfo *AnyMetatypeTI = nullptr;
192211
const TypeInfo *EmptyTI = nullptr;
193212

194213
public:
@@ -216,15 +235,29 @@ class TypeConverter {
216235
unsigned start,
217236
unsigned align);
218237

219-
/* Not really public */
238+
private:
239+
friend class swift::reflection::LowerType;
240+
friend class swift::reflection::RecordTypeInfoBuilder;
241+
friend class swift::reflection::ExistentialTypeInfoBuilder;
242+
220243
const ReferenceTypeInfo *
221244
getReferenceTypeInfo(ReferenceKind Kind,
222245
ReferenceCounting Refcounting);
223246

247+
/// TypeRefs for special types for which we need to know the layout
248+
/// intrinsically in order to layout anything else.
249+
///
250+
/// IRGen emits BuiltinTypeDescriptors for these when compiling the
251+
/// standard library.
224252
const TypeRef *getRawPointerTypeRef();
225253
const TypeRef *getNativeObjectTypeRef();
226254
const TypeRef *getUnknownObjectTypeRef();
255+
const TypeRef *getThinFunctionTypeRef();
256+
const TypeRef *getAnyMetatypeTypeRef();
257+
258+
const TypeInfo *getThinFunctionTypeInfo();
227259
const TypeInfo *getThickFunctionTypeInfo();
260+
const TypeInfo *getAnyMetatypeTypeInfo();
228261
const TypeInfo *getEmptyTypeInfo();
229262

230263
template <typename TypeInfoTy, typename... Args>
@@ -242,18 +275,20 @@ class RecordTypeInfoBuilder {
242275
unsigned Size, Alignment, Stride, NumExtraInhabitants;
243276
RecordKind Kind;
244277
std::vector<FieldInfo> Fields;
278+
bool Empty;
245279
bool Invalid;
246280

247281
public:
248282
RecordTypeInfoBuilder(TypeConverter &TC, RecordKind Kind)
249283
: TC(TC), Size(0), Alignment(1), Stride(0), NumExtraInhabitants(0),
250-
Kind(Kind), Invalid(false) {}
284+
Kind(Kind), Empty(true), Invalid(false) {}
251285

252286
bool isInvalid() const {
253287
return Invalid;
254288
}
255289

256-
unsigned addField(unsigned fieldSize, unsigned fieldAlignment);
290+
unsigned addField(unsigned fieldSize, unsigned fieldAlignment,
291+
unsigned numExtraInhabitants);
257292
void addField(const std::string &Name, const TypeRef *TR);
258293
const RecordTypeInfo *build();
259294

@@ -264,6 +299,13 @@ class RecordTypeInfoBuilder {
264299
unsigned getFieldOffset(unsigned Index) const {
265300
return Fields[Index].Offset;
266301
}
302+
303+
void setNumExtraInhabitants(unsigned numExtraInhabitants) {
304+
// We can only take away extra inhabitants while performing
305+
// record layout, never add new ones.
306+
assert(numExtraInhabitants <= NumExtraInhabitants);
307+
NumExtraInhabitants = numExtraInhabitants;
308+
}
267309
};
268310

269311
}

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,28 @@ struct ClosureContextInfo {
9292
void dump(std::ostream &OS) const;
9393
};
9494

95+
struct FieldTypeInfo {
96+
std::string Name;
97+
const TypeRef *TR;
98+
bool Indirect;
99+
100+
FieldTypeInfo() : Name(""), TR(nullptr), Indirect(false) {}
101+
FieldTypeInfo(const std::string &Name, const TypeRef *TR, bool Indirect)
102+
: Name(Name), TR(TR), Indirect(Indirect) {}
103+
104+
static FieldTypeInfo forEmptyCase(std::string Name) {
105+
return FieldTypeInfo(Name, nullptr, false);
106+
}
107+
108+
static FieldTypeInfo forIndirectCase(std::string Name, const TypeRef *TR) {
109+
return FieldTypeInfo(Name, TR, true);
110+
}
111+
112+
static FieldTypeInfo forField(std::string Name, const TypeRef *TR) {
113+
return FieldTypeInfo(Name, TR, false);
114+
}
115+
};
116+
95117
/// An implementation of MetadataReader's BuilderType concept for
96118
/// building TypeRefs, and parsing field metadata from any images
97119
/// it has been made aware of.
@@ -286,7 +308,7 @@ class TypeRefBuilder {
286308
const FieldDescriptor *getFieldTypeInfo(const TypeRef *TR);
287309

288310
/// Get the parsed and substituted field types for a nominal type.
289-
std::vector<std::pair<std::string, const TypeRef *>>
311+
std::vector<FieldTypeInfo>
290312
getFieldTypeRefs(const TypeRef *TR, const FieldDescriptor *FD);
291313

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

include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,17 @@ typedef enum swift_layout_kind {
6363
// Value types consisting of zero or more fields.
6464
SWIFT_TUPLE,
6565
SWIFT_STRUCT,
66+
67+
// An enum with no payload cases. The record will have no fields, but
68+
// will have the correct size.
69+
SWIFT_NO_PAYLOAD_ENUM,
70+
71+
// An enum with a single payload case. The record consists of a single
72+
// field, being the enum payload.
73+
SWIFT_SINGLE_PAYLOAD_ENUM,
74+
6675
SWIFT_THICK_FUNCTION,
76+
6777
SWIFT_OPAQUE_EXISTENTIAL,
6878
SWIFT_CLASS_EXISTENTIAL,
6979
SWIFT_ERROR_EXISTENTIAL,

0 commit comments

Comments
 (0)