27
27
namespace swift {
28
28
namespace Lowering {
29
29
30
+ // / A reference to a generator suitable for handling pack inputs.
31
+ // / Has the same basic liveness characteristics as SimpleGeneratorRef.
32
+ class PackGeneratorRef {
33
+ struct VTable {
34
+ ManagedValue (*claimNext)(void *impl);
35
+ void (*finishCurrent)(void *impl, ManagedValue packAddr);
36
+ };
37
+
38
+ template <class Impl >
39
+ struct VTableImpl {
40
+ static constexpr VTable vtable = {
41
+ [](void *impl) {
42
+ return static_cast <Impl*>(impl)->claimNext ();
43
+ },
44
+ [](void *impl, ManagedValue packAddr) {
45
+ static_cast <Impl*>(impl)->finishCurrent (packAddr);
46
+ }
47
+ };
48
+ };
49
+
50
+ void *pointer;
51
+ const VTable *vtable;
52
+ public:
53
+ template <class G >
54
+ PackGeneratorRef (G &generator,
55
+ std::enable_if_t <!std::is_same_v<std::remove_const_t <G>, PackGeneratorRef>,
56
+ bool > = false )
57
+ : pointer(&generator), vtable(&VTableImpl<G>::vtable) {}
58
+
59
+ ManagedValue claimNext () {
60
+ return vtable->claimNext (pointer);
61
+ }
62
+ void finishCurrent (ManagedValue packAddr) {
63
+ vtable->finishCurrent (pointer, packAddr);
64
+ }
65
+ };
66
+
30
67
// / A generator for destructuring a tuple type that is recursively
31
68
// / expanded in some sequence. In SIL, this sort of expansion
32
69
// / happens in both function parameters and function results.
@@ -48,7 +85,7 @@ namespace Lowering {
48
85
// / reaches them.
49
86
class ExpandedTupleInputGenerator {
50
87
const ASTContext &ctx;
51
- SimpleGeneratorRef<ManagedValue> packInputs;
88
+ PackGeneratorRef packInputs;
52
89
TupleElementGenerator origElt;
53
90
54
91
// / If origElt.isPackExpansion(), this is the pack currently
@@ -82,10 +119,22 @@ class ExpandedTupleInputGenerator {
82
119
if (substEltIndex != origElt.getSubstTypes ().size ())
83
120
return ;
84
121
85
- // Otherwise, advance, and ready the next orig element if we
86
- // didn't finish.
122
+ // Otherwise, we need to advance and ready the next orig element.
123
+
124
+ // If the current orig element is a pack expansion, tell the
125
+ // pack generator about the completed pack value.
126
+ if (origElt.isOrigPackExpansion ()) {
127
+ assert (packValue.isValid ());
128
+ packInputs.finishCurrent (packValue);
129
+ }
130
+
131
+ // Advance to the next orig element. If we're out of elements,
132
+ // we're done.
87
133
origElt.advance ();
88
134
if (origElt.isFinished ()) return ;
135
+
136
+ // Ready the next orig element, which may include generating a pack
137
+ // value.
89
138
readyOrigElement ();
90
139
}
91
140
}
@@ -110,12 +159,14 @@ class ExpandedTupleInputGenerator {
110
159
111
160
void updatePackValue (ManagedValue newPackValue) {
112
161
assert (isOrigPackExpansion ());
162
+ assert (packValue.isValid ());
163
+ assert (newPackValue.isValid ());
113
164
packValue = newPackValue;
114
165
}
115
166
116
167
public:
117
168
ExpandedTupleInputGenerator (const ASTContext &ctx,
118
- SimpleGeneratorRef<ManagedValue> inputs,
169
+ PackGeneratorRef inputs,
119
170
AbstractionPattern origTupleType,
120
171
CanType substType)
121
172
: ctx(ctx), packInputs(inputs), origElt(origTupleType, substType) {
0 commit comments