Skip to content

Commit a0ed29d

Browse files
technicatedToma91
authored andcommitted
🎄 Improved tuple key path support in SIL ~ Merry Christmas 🎄
Using an anonymous union in KeyPathPatternComponent instead of the weird void * in SetterAndIdKind Added TupleElement kind to KeyPathComponentKindEncoding Written basic SIL keypath serialization tests Deleted or edited some old Swift-level tuple key path tests
1 parent bf5943f commit a0ed29d

File tree

9 files changed

+73
-69
lines changed

9 files changed

+73
-69
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,8 @@ ERROR(expected_sil_value_ownership_kind,none,
485485
"expected value ownership kind in SIL code", ())
486486
ERROR(expected_sil_colon,none,
487487
"expected ':' before %0", (StringRef))
488+
ERROR(expected_sil_tuple_index,none,
489+
"expected tuple element index", ())
488490

489491
// SIL Values
490492
ERROR(sil_value_redefinition,none,

include/swift/SIL/SILInstruction.h

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2439,12 +2439,17 @@ class KeyPathPatternComponent {
24392439
// Value is the VarDecl* for StoredProperty, the SILFunction* of the
24402440
// Getter for computed properties, or the Kind for other kinds
24412441
llvm::PointerIntPair<void *, KindPackingBits, unsigned> ValueAndKind;
2442-
2443-
// Setter is the SILFunction* of the Setter for computed properties, or the
2444-
// tuple index for tuple elements
2445-
llvm::PointerIntPair<void *, 2,
2442+
llvm::PointerIntPair<SILFunction *, 2,
24462443
ComputedPropertyId::KindType> SetterAndIdKind;
2447-
ComputedPropertyId::ValueType IdValue;
2444+
2445+
// If this component refers to a tuple element then TupleIndex is the
2446+
// 1-based index of the element in the tuple, in order to allow the
2447+
// discrimination of the TupleElement Kind from the StoredProperty Kind
2448+
union {
2449+
unsigned TupleIndex = 0;
2450+
ComputedPropertyId::ValueType IdValue;
2451+
};
2452+
24482453
ArrayRef<Index> Indices;
24492454
struct {
24502455
SILFunction *Equal;
@@ -2492,10 +2497,9 @@ class KeyPathPatternComponent {
24922497
/// Constructor for tuple element.
24932498
KeyPathPatternComponent(unsigned tupleIndex, CanType componentType)
24942499
: ValueAndKind((void*)((uintptr_t)Kind::TupleElement << KindPackingBits), PackedStored),
2495-
SetterAndIdKind((void*)((uintptr_t)tupleIndex << 2), (ComputedPropertyId::KindType)0),
2500+
TupleIndex(tupleIndex + 1),
24962501
ComponentType(componentType)
24972502
{
2498-
// fixme: [technicated] magic << 2 shift
24992503
}
25002504

25012505
public:
@@ -2509,7 +2513,7 @@ class KeyPathPatternComponent {
25092513
auto packedKind = ValueAndKind.getInt();
25102514
switch ((PackedKind)packedKind) {
25112515
case PackedStored:
2512-
return SetterAndIdKind.getPointer()
2516+
return TupleIndex
25132517
? Kind::TupleElement : Kind::StoredProperty;
25142518
case PackedComputed:
25152519
return SetterAndIdKind.getPointer()
@@ -2580,7 +2584,7 @@ class KeyPathPatternComponent {
25802584
case Kind::TupleElement:
25812585
llvm_unreachable("not a settable computed property");
25822586
case Kind::SettableProperty:
2583-
return static_cast<SILFunction*>(SetterAndIdKind.getPointer());
2587+
return SetterAndIdKind.getPointer();
25842588
}
25852589
llvm_unreachable("unhandled kind");
25862590
}
@@ -2676,8 +2680,7 @@ class KeyPathPatternComponent {
26762680
case Kind::SettableProperty:
26772681
llvm_unreachable("not a tuple element");
26782682
case Kind::TupleElement:
2679-
// fixme: [technicated] magic >> 2 shift
2680-
return (uintptr_t)SetterAndIdKind.getPointer() >> 2;
2683+
return TupleIndex - 1;
26812684
}
26822685
llvm_unreachable("unhandled kind");
26832686
}

lib/ParseSIL/ParseSIL.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2261,6 +2261,19 @@ SILParser::parseKeyPathPatternComponent(KeyPathPatternComponent &component,
22612261

22622262
component = KeyPathPatternComponent::forOptional(kind, ty);
22632263
return false;
2264+
} else if (componentKind.str() == "tuple_element") {
2265+
unsigned tupleIndex;
2266+
CanType ty;
2267+
2268+
if (P.parseToken(tok::pound, diag::expected_sil_constant)
2269+
|| parseInteger(tupleIndex, diag::expected_sil_tuple_index)
2270+
|| P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":")
2271+
|| P.parseToken(tok::sil_dollar, diag::expected_tok_in_sil_instr, "$")
2272+
|| parseASTType(ty, patternEnv))
2273+
return true;
2274+
2275+
component = KeyPathPatternComponent::forTupleElement(tupleIndex, ty);
2276+
return false;
22642277
} else {
22652278
P.diagnose(componentLoc, diag::sil_keypath_unknown_component_kind,
22662279
componentKind);

lib/Serialization/DeserializeSIL.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,9 @@ SILDeserializer::readKeyPathComponent(ArrayRef<uint64_t> ListOfValues,
936936
case KeyPathComponentKindEncoding::OptionalWrap:
937937
return KeyPathPatternComponent::forOptional(
938938
KeyPathPatternComponent::Kind::OptionalWrap, type);
939+
case KeyPathComponentKindEncoding::TupleElement:
940+
return KeyPathPatternComponent::forTupleElement(
941+
ListOfValues[nextValue++], type);
939942
case KeyPathComponentKindEncoding::Trivial:
940943
llvm_unreachable("handled above");
941944
}

lib/Serialization/SILFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ enum CastConsumptionKindEncoding : uint8_t {
8181

8282
enum class KeyPathComponentKindEncoding : uint8_t {
8383
StoredProperty,
84+
TupleElement,
8485
GettableProperty,
8586
SettableProperty,
8687
OptionalChain,

lib/Serialization/SerializeSIL.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,8 @@ SILSerializer::writeKeyPathPatternComponent(
685685
handleComponentCommon(KeyPathComponentKindEncoding::OptionalWrap);
686686
break;
687687
case KeyPathPatternComponent::Kind::TupleElement:
688-
llvm_unreachable("[technicated]");
688+
handleComponentCommon(KeyPathComponentKindEncoding::TupleElement);
689+
ListOfValues.push_back((unsigned)component.getTupleIndex());
689690
break;
690691
}
691692
}

test/SIL/Serialization/keypath.sil

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ public struct External<T> {
4949
init()
5050
}
5151

52+
struct T {
53+
var x: (Int, Int)
54+
var y: (a: Int, b: Int, c: Int)
55+
let z: (Int, Int)
56+
let w: (Int, C)
57+
}
58+
5259
// CHECK-LABEL: sil shared [serialized] [ossa] @stored_properties
5360
sil shared [serialized] [ossa] @stored_properties : $@convention(thin) () -> () {
5461
entry:
@@ -75,6 +82,17 @@ entry:
7582
return undef : $()
7683
}
7784

85+
// CHECK-LABEL: sil shared [serialized] [ossa] @tuple_elements
86+
sil shared [serialized] [ossa] @tuple_elements : $@convention(thin) () -> () {
87+
entry:
88+
// CHECK: keypath $WritableKeyPath<T, Int>, (root $T; stored_property #T.x : $(Int, Int); tuple_element #0 : $Int)
89+
%a = keypath $WritableKeyPath<T, Int>, (root $T; stored_property #T.x : $(Int, Int); tuple_element #0 : $Int)
90+
// CHECK: keypath $WritableKeyPath<T, Int>, (root $T; stored_property #T.y : $(a: Int, b: Int, c: Int); tuple_element #2 : $Int)
91+
%b = keypath $WritableKeyPath<T, Int>, (root $T; stored_property #T.y : $(a: Int, b: Int, c: Int); tuple_element #2 : $Int)
92+
93+
return undef : $()
94+
}
95+
7896
sil @id_a : $@convention(thin) () -> ()
7997
sil @get_s_int : $@convention(thin) (@in_guaranteed S) -> @out Int
8098
sil @set_s_int : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S) -> ()
@@ -160,12 +178,13 @@ entry:
160178
sil [serialized] [ossa] @serialize_all : $@convention(thin) () -> () {
161179
entry:
162180
%0 = function_ref @stored_properties : $@convention(thin) () -> ()
163-
%1 = function_ref @stored_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> ()
164-
%2 = function_ref @computed_properties : $@convention(thin) () -> ()
165-
%3 = function_ref @computed_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> ()
166-
%4 = function_ref @optional : $@convention(thin) () -> ()
167-
%5 = function_ref @indexes : $@convention(thin) (S, C) -> ()
168-
%6 = function_ref @external : $@convention(thin) <D: P, E: Q, F: R> () -> ()
181+
%1 = function_ref @tuple_elements : $@convention(thin) () -> ()
182+
%2 = function_ref @stored_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> ()
183+
%3 = function_ref @computed_properties : $@convention(thin) () -> ()
184+
%4 = function_ref @computed_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> ()
185+
%5 = function_ref @optional : $@convention(thin) () -> ()
186+
%6 = function_ref @indexes : $@convention(thin) (S, C) -> ()
187+
%7 = function_ref @external : $@convention(thin) <D: P, E: Q, F: R> () -> ()
169188

170189
unreachable
171190
}

test/expr/unary/keypath/keypath-unimplemented.swift

Lines changed: 0 additions & 35 deletions
This file was deleted.

test/expr/unary/keypath/keypath.swift

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,6 @@ func testKeyPathInGenericContext<H: Hashable, X>(hashable: H, anything: X) {
220220
func testDisembodiedStringInterpolation(x: Int) {
221221
\(x) // expected-error{{string interpolation}} expected-error{{}}
222222
\(x, radix: 16) // expected-error{{string interpolation}} expected-error{{}}
223-
224-
_ = \(Int, Int).0 // expected-error{{cannot reference tuple elements}}
225223
}
226224

227225
func testNoComponents() {
@@ -235,20 +233,19 @@ struct TupleStruct {
235233
}
236234

237235
func tupleComponent() {
238-
// TODO: Customized diagnostic
239-
let _ = \(Int, String).0 // expected-error{{}}
240-
let _ = \(Int, String).1 // expected-error{{}}
241-
let _ = \TupleStruct.unlabeled.0 // expected-error{{}}
242-
let _ = \TupleStruct.unlabeled.1 // expected-error{{}}
243-
244-
let _ = \(foo: Int, bar: String).0 // expected-error{{}}
245-
let _ = \(foo: Int, bar: String).1 // expected-error{{}}
246-
let _ = \(foo: Int, bar: String).foo // expected-error{{}}
247-
let _ = \(foo: Int, bar: String).bar // expected-error{{}}
248-
let _ = \TupleStruct.labeled.0 // expected-error{{}}
249-
let _ = \TupleStruct.labeled.1 // expected-error{{}}
250-
let _ = \TupleStruct.labeled.foo // expected-error{{}}
251-
let _ = \TupleStruct.labeled.bar // expected-error{{}}
236+
let _ = \(Int, String).0
237+
let _ = \(Int, String).1
238+
let _ = \TupleStruct.unlabeled.0
239+
let _ = \TupleStruct.unlabeled.1
240+
241+
let _ = \(foo: Int, bar: String).0
242+
let _ = \(foo: Int, bar: String).1
243+
let _ = \(foo: Int, bar: String).foo
244+
let _ = \(foo: Int, bar: String).bar
245+
let _ = \TupleStruct.labeled.0
246+
let _ = \TupleStruct.labeled.1
247+
let _ = \TupleStruct.labeled.foo
248+
let _ = \TupleStruct.labeled.bar
252249
}
253250

254251
struct Z { }

0 commit comments

Comments
 (0)