22//
33// This source file is part of the Swift.org open source project
44//
5- // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+ // Copyright (c) 2022 Apple Inc. and the Swift project authors
66// Licensed under Apache License v2.0 with Runtime Library Exception
77//
88// See https://swift.org/LICENSE.txt for license information
1414//
1515// ===----------------------------------------------------------------------===//
1616
17+ #include " GenPack.h"
1718#include " swift/AST/Decl.h"
19+ #include " swift/AST/GenericEnvironment.h"
1820#include " swift/AST/IRGenOptions.h"
1921#include " swift/AST/Types.h"
2022#include " swift/SIL/SILModule.h"
2426#include " GenType.h"
2527#include " IRGenFunction.h"
2628#include " IRGenModule.h"
29+ #include " MetadataRequest.h"
2730
2831using namespace swift ;
2932using namespace irgen ;
3033
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+ }
3240
33- type = type->getReducedShape ()->getCanonicalType ();
41+ result = IGF.Builder .CreateAdd (result, value);
42+ }
3443
35- auto kind = LocalTypeDataKind::forPackShapeExpression ();
44+ using PackExplosionCallback = void (CanType eltTy,
45+ unsigned scalarIndex,
46+ llvm::Value *dynamicIndex,
47+ llvm::Value *dynamicLength);
3648
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 ;
4053
4154 // If shape(T) == t and shape(U) == u, the shape expression for a pack
4255 // {T..., Int, T..., U..., String} becomes 't + t + u + 2'.
4356 unsigned scalarElements = 0 ;
4457
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 ()) {
5659 if (auto expansionType = dyn_cast<PackExpansionType>(elt)) {
5760 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);
5964 continue ;
6065 }
6166
67+ callback (elt, scalarElements, result, nullptr );
6268 ++scalarElements;
6369 }
6470
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);
68131 }
69132
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+ }
72331}
0 commit comments