Skip to content

Commit 352c4c2

Browse files
authored
Merge pull request #61837 from augusto2112/reflect-optional-bool
Implement reading extra inhabitants of integers
2 parents 4a8ce3a + 363b5e4 commit 352c4c2

File tree

2 files changed

+265
-17
lines changed

2 files changed

+265
-17
lines changed

stdlib/public/Reflection/TypeLowering.cpp

Lines changed: 57 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -241,25 +241,65 @@ BuiltinTypeInfo::BuiltinTypeInfo(TypeRefBuilder &builder,
241241
builder.readTypeRef(descriptor, descriptor->TypeName)))
242242
{}
243243

244-
bool
245-
BuiltinTypeInfo::readExtraInhabitantIndex(remote::MemoryReader &reader,
246-
remote::RemoteAddress address,
247-
int *extraInhabitantIndex) const {
248-
if (getNumExtraInhabitants() == 0) {
249-
*extraInhabitantIndex = -1;
250-
return true;
251-
}
252-
// If it has extra inhabitants, it must be a pointer. (The only non-pointer
253-
// data with extra inhabitants is a non-payload enum, which doesn't get here.)
254-
if (Name == "yyXf") {
255-
// But there are two different conventions, one for function pointers:
256-
return reader.readFunctionPointerExtraInhabitantIndex(address, extraInhabitantIndex);
257-
} else {
258-
// And one for pointers to heap-allocated blocks of memory
259-
return reader.readHeapObjectExtraInhabitantIndex(address, extraInhabitantIndex);
260-
}
244+
bool BuiltinTypeInfo::readExtraInhabitantIndex(
245+
remote::MemoryReader &reader, remote::RemoteAddress address,
246+
int *extraInhabitantIndex) const {
247+
if (getNumExtraInhabitants() == 0) {
248+
*extraInhabitantIndex = -1;
249+
return true;
261250
}
251+
// If it has extra inhabitants, it could be an integer type with extra
252+
// inhabitants (a bool) or a pointer.
253+
// Check if it's an integer first. The mangling of an integer type is
254+
// type ::= 'Bi' NATURAL '_'
255+
llvm::StringRef nameRef(Name);
256+
if (nameRef.startswith("Bi") && nameRef.endswith("_")) {
257+
// Drop the front "Bi" and "_" end, check that what we're left with is a
258+
// bool.
259+
llvm::StringRef naturalRef = nameRef.drop_front(2).drop_back();
260+
uint8_t natural;
261+
if (naturalRef.getAsInteger(10, natural))
262+
return false;
263+
264+
assert(natural == 1 &&
265+
"Reading extra inhabitants of integer with more than 1 byte!");
266+
if (natural != 1)
267+
return false;
268+
269+
assert(getSize() == 1 && "Reading extra inhabitants of integer but size of "
270+
"type info is different than 1!");
271+
if (getSize() != 1)
272+
return false;
273+
274+
assert(getNumExtraInhabitants() == 254 &&
275+
"Boolean type info should have 254 extra inhabitants!");
276+
if (getNumExtraInhabitants() != 254)
277+
return false;
278+
279+
uint8_t rawValue;
280+
if (!reader.readInteger(address, &rawValue))
281+
return false;
262282

283+
// The max valid value, for a bool valid values are 0 or 1, so this would
284+
// be 1.
285+
auto maxValidValue = 1;
286+
// If the raw value falls outside the range of valid values, this is an
287+
// extra inhabitant.
288+
if (maxValidValue < rawValue)
289+
*extraInhabitantIndex = rawValue - maxValidValue - 1;
290+
else
291+
*extraInhabitantIndex = -1;
292+
return true;
293+
} else if (Name == "yyXf") {
294+
// But there are two different conventions, one for function pointers:
295+
return reader.readFunctionPointerExtraInhabitantIndex(address,
296+
extraInhabitantIndex);
297+
} else {
298+
// And one for pointers to heap-allocated blocks of memory
299+
return reader.readHeapObjectExtraInhabitantIndex(address,
300+
extraInhabitantIndex);
301+
}
302+
}
263303

264304
bool RecordTypeInfo::readExtraInhabitantIndex(remote::MemoryReader &reader,
265305
remote::RemoteAddress address,
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -g -lswiftSwiftReflectionTest %s -o %t/reflect_Optional_Bool
3+
// RUN: %target-codesign %t/reflect_Optional_Bool
4+
5+
// RUN: %target-run %target-swift-reflection-test %t/reflect_Optional_Bool | %FileCheck %s
6+
7+
8+
// REQUIRES: reflection_test_support
9+
// REQUIRES: executable_test
10+
// UNSUPPORTED: use_os_stdlib
11+
12+
import SwiftReflectionTest
13+
14+
let optFalse: Bool? = false
15+
reflect(enum: optFalse)
16+
17+
// CHECK: Reflecting an enum.
18+
// CHECK: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
19+
// CHECK: Type reference:
20+
// CHECK: (bound_generic_enum Swift.Optional
21+
// CHECK: (struct Swift.Bool))
22+
23+
// CHECK: Type info:
24+
// CHECK: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
25+
// CHECK: (case name=some index=0 offset=0
26+
// CHECK: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
27+
// CHECK: (field name=_value offset=0
28+
// CHECK: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1))))
29+
// CHECK: (case name=none index=1))
30+
31+
// CHECK: Mangled name: $sSbSg
32+
// CHECK: Demangled name: Swift.Optional<Swift.Bool>
33+
34+
// CHECK: Enum value:
35+
// CHECK: (enum_value name=some index=0
36+
// CHECK: (struct Swift.Bool)
37+
// CHECK: )
38+
39+
40+
let optTrue: Bool? = true
41+
reflect(enum: optTrue)
42+
43+
// CHECK: Reflecting an enum.
44+
// CHECK: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
45+
// CHECK: Type reference:
46+
// CHECK: (bound_generic_enum Swift.Optional
47+
// CHECK: (struct Swift.Bool))
48+
49+
// CHECK: Type info:
50+
// CHECK: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
51+
// CHECK: (case name=some index=0 offset=0
52+
// CHECK: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
53+
// CHECK: (field name=_value offset=0
54+
// CHECK: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1))))
55+
// CHECK: (case name=none index=1))
56+
57+
// CHECK: Mangled name: $sSbSg
58+
// CHECK: Demangled name: Swift.Optional<Swift.Bool>
59+
60+
// CHECK: Enum value:
61+
// CHECK: (enum_value name=some index=0
62+
// CHECK: (struct Swift.Bool)
63+
// CHECK: )
64+
65+
let optNil: Bool? = .none
66+
reflect(enum: optNil)
67+
68+
// CHECK: Reflecting an enum.
69+
// CHECK: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
70+
// CHECK: Type reference:
71+
// CHECK: (bound_generic_enum Swift.Optional
72+
// CHECK: (struct Swift.Bool))
73+
74+
// CHECK: Type info:
75+
// CHECK: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
76+
// CHECK: (case name=some index=0 offset=0
77+
// CHECK: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
78+
// CHECK: (field name=_value offset=0
79+
// CHECK: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1))))
80+
// CHECK: (case name=none index=1))
81+
82+
// CHECK: Mangled name: $sSbSg
83+
// CHECK: Demangled name: Swift.Optional<Swift.Bool>
84+
85+
// CHECK: Enum value:
86+
// CHECK: (enum_value name=none index=1)
87+
88+
let optOptFalse: Bool?? = false
89+
reflect(enum: optOptFalse)
90+
91+
// CHECK: Reflecting an enum.
92+
// CHECK: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
93+
// CHECK: Type reference:
94+
// CHECK: (bound_generic_enum Swift.Optional
95+
// CHECK: (bound_generic_enum Swift.Optional
96+
// CHECK: (struct Swift.Bool)))
97+
98+
// CHECK: Type info:
99+
// CHECK: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=252 bitwise_takable=1
100+
// CHECK: (case name=some index=0 offset=0
101+
// CHECK: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
102+
// CHECK: (case name=some index=0 offset=0
103+
// CHECK: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
104+
// CHECK: (field name=_value offset=0
105+
// CHECK: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1))))
106+
// CHECK: (case name=none index=1)))
107+
// CHECK: (case name=none index=1))
108+
109+
// CHECK: Mangled name: $sSbSgSg
110+
// CHECK: Demangled name: Swift.Optional<Swift.Optional<Swift.Bool>>
111+
112+
// CHECK: Enum value:
113+
// CHECK: (enum_value name=some index=0
114+
// CHECK: (bound_generic_enum Swift.Optional
115+
// CHECK: (struct Swift.Bool))
116+
// CHECK: )
117+
118+
let optOptTrue: Bool?? = true
119+
reflect(enum: optOptTrue)
120+
121+
// CHECK: Reflecting an enum.
122+
// CHECK: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
123+
// CHECK: Type reference:
124+
// CHECK: (bound_generic_enum Swift.Optional
125+
// CHECK: (bound_generic_enum Swift.Optional
126+
// CHECK: (struct Swift.Bool)))
127+
128+
// CHECK: Type info:
129+
// CHECK: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=252 bitwise_takable=1
130+
// CHECK: (case name=some index=0 offset=0
131+
// CHECK: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
132+
// CHECK: (case name=some index=0 offset=0
133+
// CHECK: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
134+
// CHECK: (field name=_value offset=0
135+
// CHECK: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1))))
136+
// CHECK: (case name=none index=1)))
137+
// CHECK: (case name=none index=1))
138+
139+
// CHECK: Mangled name: $sSbSgSg
140+
// CHECK: Demangled name: Swift.Optional<Swift.Optional<Swift.Bool>>
141+
142+
// CHECK: Enum value:
143+
// CHECK: (enum_value name=some index=0
144+
// CHECK: (bound_generic_enum Swift.Optional
145+
// CHECK: (struct Swift.Bool))
146+
// CHECK: )
147+
148+
let optOptSomeNil: Bool?? = .some(.none)
149+
reflect(enum: optOptSomeNil)
150+
151+
// CHECK: Reflecting an enum.
152+
// CHECK: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
153+
// CHECK: Type reference:
154+
// CHECK: (bound_generic_enum Swift.Optional
155+
// CHECK: (bound_generic_enum Swift.Optional
156+
// CHECK: (struct Swift.Bool)))
157+
158+
// CHECK: Type info:
159+
// CHECK: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=252 bitwise_takable=1
160+
// CHECK: (case name=some index=0 offset=0
161+
// CHECK: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
162+
// CHECK: (case name=some index=0 offset=0
163+
// CHECK: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
164+
// CHECK: (field name=_value offset=0
165+
// CHECK: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1))))
166+
// CHECK: (case name=none index=1)))
167+
// CHECK: (case name=none index=1))
168+
169+
// CHECK: Mangled name: $sSbSgSg
170+
// CHECK: Demangled name: Swift.Optional<Swift.Optional<Swift.Bool>>
171+
172+
// CHECK: Enum value:
173+
// CHECK: (enum_value name=some index=0
174+
// CHECK: (bound_generic_enum Swift.Optional
175+
// CHECK: (struct Swift.Bool))
176+
// CHECK: )
177+
178+
let optOptNil: Bool?? = .none
179+
reflect(enum: optOptNil)
180+
181+
// CHECK: Reflecting an enum.
182+
// CHECK: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
183+
// CHECK: Type reference:
184+
// CHECK: (bound_generic_enum Swift.Optional
185+
// CHECK: (bound_generic_enum Swift.Optional
186+
// CHECK: (struct Swift.Bool)))
187+
188+
// CHECK: Type info:
189+
// CHECK: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=252 bitwise_takable=1
190+
// CHECK: (case name=some index=0 offset=0
191+
// CHECK: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
192+
// CHECK: (case name=some index=0 offset=0
193+
// CHECK: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
194+
// CHECK: (field name=_value offset=0
195+
// CHECK: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1))))
196+
// CHECK: (case name=none index=1)))
197+
// CHECK: (case name=none index=1))
198+
199+
// CHECK: Mangled name: $sSbSgSg
200+
// CHECK: Demangled name: Swift.Optional<Swift.Optional<Swift.Bool>>
201+
202+
// CHECK: Enum value:
203+
// CHECK: (enum_value name=none index=1)
204+
205+
doneReflecting()
206+
207+
// CHECK-64: Done.
208+

0 commit comments

Comments
 (0)