2
2
//
3
3
// This source file is part of the Swift.org open source project
4
4
//
5
- // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5
+ // Copyright (c) 2022 Apple Inc. and the Swift project authors
6
6
// Licensed under Apache License v2.0 with Runtime Library Exception
7
7
//
8
8
// See https://swift.org/LICENSE.txt for license information
14
14
//
15
15
// ===----------------------------------------------------------------------===//
16
16
17
+ #include " GenPack.h"
17
18
#include " swift/AST/Decl.h"
19
+ #include " swift/AST/GenericEnvironment.h"
18
20
#include " swift/AST/IRGenOptions.h"
19
21
#include " swift/AST/Types.h"
20
22
#include " swift/SIL/SILModule.h"
24
26
#include " GenType.h"
25
27
#include " IRGenFunction.h"
26
28
#include " IRGenModule.h"
29
+ #include " MetadataRequest.h"
27
30
28
31
using namespace swift ;
29
32
using namespace irgen ;
30
33
31
- llvm::Value *IRGenFunction::emitPackShapeExpression (CanType type) {
34
+ static void accumulateSum (IRGenFunction &IGF, llvm::Value *&result,
35
+ llvm::Value *value) {
36
+ if (result == nullptr ) {
37
+ result = value;
38
+ return ;
39
+ }
32
40
33
- type = type->getReducedShape ()->getCanonicalType ();
41
+ result = IGF.Builder .CreateAdd (result, value);
42
+ }
34
43
35
- auto kind = LocalTypeDataKind::forPackShapeExpression ();
44
+ using PackExplosionCallback = void (CanType eltTy,
45
+ unsigned scalarIndex,
46
+ llvm::Value *dynamicIndex,
47
+ llvm::Value *dynamicLength);
36
48
37
- llvm::Value *result = tryGetLocalTypeData (type, kind);
38
- if (result != nullptr )
39
- return result;
49
+ static std::pair<unsigned , llvm::Value *>
50
+ visitPackExplosion (IRGenFunction &IGF, CanPackType type,
51
+ llvm::function_ref<PackExplosionCallback> callback) {
52
+ llvm::Value *result = nullptr ;
40
53
41
54
// If shape(T) == t and shape(U) == u, the shape expression for a pack
42
55
// {T..., Int, T..., U..., String} becomes 't + t + u + 2'.
43
56
unsigned scalarElements = 0 ;
44
57
45
- auto accumulate = [&](llvm::Value *value) {
46
- if (result == nullptr ) {
47
- result = value;
48
- return ;
49
- }
50
-
51
- result = Builder.CreateAdd (result, value);
52
- };
53
-
54
- auto packType = cast<PackType>(type);
55
- for (auto elt : packType.getElementTypes ()) {
58
+ for (auto elt : type.getElementTypes ()) {
56
59
if (auto expansionType = dyn_cast<PackExpansionType>(elt)) {
57
60
auto reducedShape = expansionType.getCountType ();
58
- accumulate (emitPackShapeExpression (reducedShape));
61
+ auto *eltCount = IGF.emitPackShapeExpression (reducedShape);
62
+ callback (elt, scalarElements, result, eltCount);
63
+ accumulateSum (IGF, result, eltCount);
59
64
continue ;
60
65
}
61
66
67
+ callback (elt, scalarElements, result, nullptr );
62
68
++scalarElements;
63
69
}
64
70
65
- if (scalarElements > 0 ) {
66
- auto *constant = llvm::ConstantInt::get (IGM.SizeTy , scalarElements);
67
- accumulate (constant);
71
+ return std::make_pair (scalarElements, result);
72
+ }
73
+
74
+ llvm::Value *IRGenFunction::emitPackShapeExpression (CanType type) {
75
+
76
+ type = type->getReducedShape ()->getCanonicalType ();
77
+
78
+ auto kind = LocalTypeDataKind::forPackShapeExpression ();
79
+
80
+ llvm::Value *result = tryGetLocalTypeData (type, kind);
81
+ if (result != nullptr )
82
+ return result;
83
+
84
+ auto pair = visitPackExplosion (
85
+ *this , cast<PackType>(type),
86
+ [&](CanType, unsigned , llvm::Value *, llvm::Value *) {});
87
+
88
+ if (pair.first > 0 ) {
89
+ auto *constant = llvm::ConstantInt::get (IGM.SizeTy , pair.first );
90
+ accumulateSum (*this , pair.second , constant);
91
+ }
92
+
93
+ setScopedLocalTypeData (type, kind, pair.second );
94
+ return pair.second ;
95
+ }
96
+
97
+ MetadataResponse
98
+ irgen::emitPackArchetypeMetadataRef (IRGenFunction &IGF,
99
+ CanPackArchetypeType type,
100
+ DynamicMetadataRequest request) {
101
+ if (auto result = IGF.tryGetLocalTypeMetadata (type, request))
102
+ return result;
103
+
104
+ auto packType = type->getSingletonPackType ();
105
+ auto response = emitTypeMetadataPackRef (IGF, packType, request);
106
+
107
+ IGF.setScopedLocalTypeMetadata (type, response);
108
+ return response;
109
+ }
110
+
111
+ static Address emitFixedSizeMetadataPackRef (IRGenFunction &IGF,
112
+ CanPackType packType,
113
+ DynamicMetadataRequest request) {
114
+ assert (!packType->containsPackExpansionType ());
115
+
116
+ unsigned elementCount = packType->getNumElements ();
117
+ auto allocType = llvm::ArrayType::get (
118
+ IGF.IGM .TypeMetadataPtrTy , elementCount);
119
+
120
+ auto pack = IGF.createAlloca (allocType, IGF.IGM .getPointerAlignment ());
121
+ IGF.Builder .CreateLifetimeStart (pack,
122
+ IGF.IGM .getPointerSize () * elementCount);
123
+
124
+ for (unsigned i : indices (packType->getElementTypes ())) {
125
+ Address slot = IGF.Builder .CreateStructGEP (
126
+ pack, i, IGF.IGM .getPointerSize ());
127
+
128
+ auto metadata = IGF.emitTypeMetadataRef (
129
+ packType.getElementType (i), request).getMetadata ();
130
+ IGF.Builder .CreateStore (metadata, slot);
68
131
}
69
132
70
- setScopedLocalTypeData (type, kind, result);
71
- return result;
133
+ pack = IGF.Builder .CreateConstArrayGEP (
134
+ pack, 0 , IGF.IGM .getPointerSize ());
135
+
136
+ IGF.Builder .CreateLifetimeStart (
137
+ pack, Size (IGF.IGM .getPointerSize () * elementCount));
138
+
139
+ return pack;
140
+ }
141
+
142
+ static void emitPackExpansionType (IRGenFunction &IGF,
143
+ Address pack,
144
+ CanPackExpansionType expansionTy,
145
+ llvm::Value *dynamicIndex,
146
+ llvm::Value *dynamicLength,
147
+ DynamicMetadataRequest request) {
148
+ auto *prev = IGF.Builder .GetInsertBlock ();
149
+ auto *check = IGF.createBasicBlock (" pack-expansion-check" );
150
+ auto *loop = IGF.createBasicBlock (" pack-expansion-loop" );
151
+ auto *rest = IGF.createBasicBlock (" pack-expansion-rest" );
152
+
153
+ IGF.Builder .CreateBr (check);
154
+ IGF.Builder .emitBlock (check);
155
+
156
+ // An index into the source metadata pack.
157
+ auto *phi = IGF.Builder .CreatePHI (IGF.IGM .SizeTy , 2 );
158
+ phi->addIncoming (llvm::ConstantInt::get (IGF.IGM .SizeTy , 0 ), prev);
159
+
160
+ // If we reach the end, jump to the continuation block.
161
+ auto *cond = IGF.Builder .CreateICmpULT (phi, dynamicLength);
162
+ IGF.Builder .CreateCondBr (cond, loop, rest);
163
+
164
+ IGF.Builder .emitBlock (loop);
165
+
166
+ auto patternTy = expansionTy.getPatternType ();
167
+
168
+ // Find all the pack archetypes appearing in the pattern type.
169
+ SmallVector<Type, 2 > patternPacks;
170
+ patternTy->getTypeParameterPacks (patternPacks);
171
+
172
+ // Get the outer generic signature and environment.
173
+ auto *genericEnv = cast<PackArchetypeType>(expansionTy.getCountType ())
174
+ ->getGenericEnvironment ();
175
+ auto subMap = genericEnv->getForwardingSubstitutionMap ();
176
+
177
+ auto genericSig = genericEnv->getGenericSignature ().getCanonicalSignature ();
178
+
179
+ // Create an opened element signature and environment.
180
+ auto elementSig = IGF.IGM .Context .getOpenedElementSignature (genericSig);
181
+ auto *elementEnv = GenericEnvironment::forOpenedElement (
182
+ elementSig, UUID::fromTime (), subMap);
183
+
184
+ // Open each pack archetype.
185
+ for (auto patternPackType : patternPacks) {
186
+ // Get the metadata for the pack archetype.
187
+ auto patternPackArchetype = cast<PackArchetypeType>(
188
+ patternPackType->getCanonicalType ());
189
+ auto patternPack = IGF.emitTypeMetadataRef (patternPackArchetype, request)
190
+ .getMetadata ();
191
+
192
+ patternPack = IGF.Builder .CreatePointerCast (
193
+ patternPack, IGF.IGM .TypeMetadataPtrPtrTy );
194
+
195
+ Address patternPackAddress (patternPack, IGF.IGM .TypeMetadataPtrTy ,
196
+ IGF.IGM .getPointerAlignment ());
197
+
198
+ // Load the metadata pack element from the current source index.
199
+ Address fromPtr (
200
+ IGF.Builder .CreateInBoundsGEP (patternPackAddress.getElementType (),
201
+ patternPackAddress.getAddress (),
202
+ phi),
203
+ patternPackAddress.getElementType (),
204
+ patternPackAddress.getAlignment ());
205
+ auto metadata = IGF.Builder .CreateLoad (fromPtr);
206
+
207
+ // Bind the metadata pack element to the element archetype.
208
+ auto elementArchetype =
209
+ elementEnv->mapPackTypeIntoElementContext (
210
+ patternPackArchetype->getInterfaceType ());
211
+
212
+ IGF.setScopedLocalTypeMetadata (
213
+ CanType (elementArchetype),
214
+ MetadataResponse::forComplete (metadata));
215
+ }
216
+
217
+ // Replace pack archetypes with element archetypes in the pattern type.
218
+ auto instantiatedPatternTy = elementEnv->mapPackTypeIntoElementContext (
219
+ patternTy->mapTypeOutOfContext ())->getCanonicalType ();
220
+
221
+ // Emit the element metadata.
222
+ auto element = IGF.emitTypeMetadataRef (instantiatedPatternTy, request)
223
+ .getMetadata ();
224
+
225
+ // Store the element metadata into to the current destination index.
226
+ auto *eltIndex = IGF.Builder .CreateAdd (dynamicIndex, phi);
227
+ Address eltPtr (
228
+ IGF.Builder .CreateInBoundsGEP (pack.getElementType (),
229
+ pack.getAddress (),
230
+ eltIndex),
231
+ pack.getElementType (),
232
+ pack.getAlignment ());
233
+
234
+ IGF.Builder .CreateStore (element, eltPtr);
235
+
236
+ // Increment our counter.
237
+ auto *next = IGF.Builder .CreateAdd (phi,
238
+ llvm::ConstantInt::get (IGF.IGM .SizeTy , 1 ));
239
+
240
+ phi->addIncoming (next, loop);
241
+
242
+ // Repeat the loop.
243
+ IGF.Builder .CreateBr (check);
244
+
245
+ // Fall through.
246
+ IGF.Builder .emitBlock (rest);
247
+ }
248
+
249
+ StackAddress
250
+ irgen::emitTypeMetadataPack (IRGenFunction &IGF,
251
+ CanPackType packType,
252
+ DynamicMetadataRequest request) {
253
+ auto *shape = IGF.emitPackShapeExpression (packType);
254
+
255
+ if (auto *constantInt = dyn_cast<llvm::ConstantInt>(shape)) {
256
+ assert (packType->getNumElements () == constantInt->getValue ());
257
+ return StackAddress (emitFixedSizeMetadataPackRef (IGF, packType, request));
258
+ }
259
+
260
+ assert (packType->containsPackExpansionType ());
261
+ auto pack = IGF.emitDynamicAlloca (IGF.IGM .TypeMetadataPtrTy , shape,
262
+ IGF.IGM .getPointerAlignment (),
263
+ /* allowTaskAlloc=*/ true );
264
+
265
+ auto visitFn =
266
+ [&](CanType eltTy, unsigned staticIndex,
267
+ llvm::Value *dynamicIndex,
268
+ llvm::Value *dynamicLength) {
269
+ if (staticIndex != 0 || dynamicIndex == nullptr ) {
270
+ auto *constant = llvm::ConstantInt::get (IGF.IGM .SizeTy , staticIndex);
271
+ accumulateSum (IGF, dynamicIndex, constant);
272
+ }
273
+
274
+ if (auto expansionTy = dyn_cast<PackExpansionType>(eltTy)) {
275
+ emitPackExpansionType (IGF, pack.getAddress (), expansionTy,
276
+ dynamicIndex, dynamicLength, request);
277
+ } else {
278
+ Address eltPtr (
279
+ IGF.Builder .CreateInBoundsGEP (pack.getAddress ().getElementType (),
280
+ pack.getAddressPointer (),
281
+ dynamicIndex),
282
+ pack.getAddress ().getElementType (),
283
+ pack.getAlignment ());
284
+
285
+ auto metadata = IGF.emitTypeMetadataRef (eltTy, request).getMetadata ();
286
+ IGF.Builder .CreateStore (metadata, eltPtr);
287
+ }
288
+ };
289
+
290
+ visitPackExplosion (IGF, packType, visitFn);
291
+
292
+ return pack;
293
+ }
294
+
295
+ MetadataResponse
296
+ irgen::emitTypeMetadataPackRef (IRGenFunction &IGF,
297
+ CanPackType packType,
298
+ DynamicMetadataRequest request) {
299
+ if (auto result = IGF.tryGetLocalTypeMetadata (packType, request))
300
+ return result;
301
+
302
+ if (packType->getNumElements () == 1 &&
303
+ isa<PackExpansionType>(packType.getElementType (0 ))) {
304
+ if (auto packArchetypeType = dyn_cast<PackArchetypeType>(
305
+ cast<PackExpansionType>(packType.getElementType (0 ))
306
+ .getPatternType ())) {
307
+ if (auto result = IGF.tryGetLocalTypeMetadata (packArchetypeType, request))
308
+ return result;
309
+ }
310
+ }
311
+
312
+ auto pack = emitTypeMetadataPack (IGF, packType, request);
313
+ auto *metadata = IGF.Builder .CreateConstArrayGEP (
314
+ pack.getAddress (), 0 , IGF.IGM .getPointerSize ()).getAddress ();
315
+
316
+ auto response = MetadataResponse::forComplete (metadata);
317
+ IGF.setScopedLocalTypeMetadata (packType, response);
318
+
319
+ return response;
320
+ }
321
+
322
+ void irgen::cleanupTypeMetadataPack (IRGenFunction &IGF,
323
+ StackAddress pack,
324
+ Optional<unsigned > elementCount) {
325
+ if (pack.getExtraInfo ()) {
326
+ IGF.emitDeallocateDynamicAlloca (pack);
327
+ } else {
328
+ IGF.Builder .CreateLifetimeEnd (pack.getAddress (),
329
+ IGF.IGM .getPointerSize () * (*elementCount));
330
+ }
72
331
}
0 commit comments