26
26
#include " swift/SIL/SILType.h"
27
27
#include " llvm/IR/DerivedTypes.h"
28
28
29
+ #include " GenTuple.h"
29
30
#include " GenType.h"
30
31
#include " IRGenFunction.h"
31
32
#include " IRGenModule.h"
@@ -1184,3 +1185,227 @@ void irgen::deallocatePack(IRGenFunction &IGF, StackAddress addr, CanSILPackType
1184
1185
IGF.Builder .CreateLifetimeEnd (addr.getAddress (),
1185
1186
elementSize * elementCount);
1186
1187
}
1188
+
1189
+ static unsigned getConstantLabelsLength (CanTupleType type) {
1190
+ unsigned total = 0 ;
1191
+
1192
+ for (auto elt : type->getElements ()) {
1193
+ if (elt.getType ()->is <PackExpansionType>()) {
1194
+ assert (!elt.hasName ());
1195
+ continue ;
1196
+ }
1197
+
1198
+ if (elt.hasName ()) {
1199
+ assert (!elt.getType ()->is <PackExpansionType>());
1200
+ total += elt.getName ().getLength ();
1201
+ }
1202
+
1203
+ ++total;
1204
+ }
1205
+
1206
+ return total;
1207
+ }
1208
+
1209
+ // / Emit the dynamic label string for a tuple type containing pack
1210
+ // / expansions.
1211
+ // /
1212
+ // / The basic idea is that the static label string is "stretched out".
1213
+ // / Pack expansion elements are unlabeled, so they appear as a single
1214
+ // / blank space in the static label string. We replace this with the
1215
+ // / appropriate number of blank spaces, given the dynamic length of
1216
+ // / the pack.
1217
+ llvm::Optional<StackAddress>
1218
+ irgen::emitDynamicTupleTypeLabels (IRGenFunction &IGF,
1219
+ CanTupleType type,
1220
+ CanPackType packType,
1221
+ llvm::Value *shapeExpression) {
1222
+ bool hasLabels = false ;
1223
+ for (auto elt : type->getElements ()) {
1224
+ hasLabels |= elt.hasName ();
1225
+ }
1226
+
1227
+ if (!hasLabels)
1228
+ return llvm::None;
1229
+
1230
+ // Elements of pack expansion type are unlabeled, so the length of
1231
+ // the label string is the number of elements in the pack, plus the
1232
+ // sum of the lengths of the labels.
1233
+ llvm::Value *labelLength = llvm::ConstantInt::get (
1234
+ IGF.IGM .SizeTy , getConstantLabelsLength (type));
1235
+ labelLength = IGF.Builder .CreateAdd (shapeExpression, labelLength);
1236
+
1237
+ // Leave root for a null byte at the end.
1238
+ labelLength = IGF.Builder .CreateAdd (labelLength,
1239
+ llvm::ConstantInt::get (IGF.IGM .SizeTy , 1 ));
1240
+
1241
+ // Allocate space for the label string; we fill it in below.
1242
+ StackAddress labelString = IGF.emitDynamicAlloca (
1243
+ IGF.IGM .Int8Ty , labelLength,
1244
+ IGF.IGM .getPointerAlignment (),
1245
+ /* allowTaskAlloc=*/ true );
1246
+
1247
+ // Get the static label string, where each pack expansion is one element.
1248
+ auto *staticLabelString = getTupleLabelsString (IGF.IGM , type);
1249
+
1250
+ // The position in the static label string for to the current element.
1251
+ unsigned staticPosition = 0 ;
1252
+
1253
+ // The position in the dynamic label string for to the current element.
1254
+ llvm::Value *dynamicPosition = llvm::ConstantInt::get (IGF.IGM .SizeTy , 0 );
1255
+
1256
+ // Number of expansions we've seen so far.
1257
+ unsigned numExpansions = 0 ;
1258
+
1259
+ // Was there at least one label?
1260
+ bool sawLabel = false ;
1261
+
1262
+ auto visitFn = [&](CanType eltTy,
1263
+ unsigned scalarIndex,
1264
+ llvm::Value *dynamicIndex,
1265
+ llvm::Value *dynamicLength) {
1266
+ auto elt = type->getElements ()[scalarIndex + numExpansions];
1267
+ assert (eltTy == CanType (elt.getType ()));
1268
+
1269
+ // The destination address, where we put the current element's label.
1270
+ auto eltAddr = IGF.Builder .CreateArrayGEP (labelString.getAddress (),
1271
+ dynamicPosition, Size (1 ));
1272
+
1273
+ // If we're looking at a pack expansion, insert the appropriate
1274
+ // number of blank spaces in the dynamic label string.
1275
+ if (isa<PackExpansionType>(eltTy)) {
1276
+ assert (!elt.hasName () && " Pack expansions cannot have labels" );
1277
+ // Fill the dynamic label string with a blank label for each
1278
+ // dynamic element.
1279
+ IGF.Builder .CreateMemSet (
1280
+ eltAddr, llvm::ConstantInt::get (IGF.IGM .Int8Ty , ' ' ),
1281
+ dynamicLength);
1282
+
1283
+ // We consumed one static label.
1284
+ staticPosition += 1 ;
1285
+
1286
+ // We produced some number of dynamic labels.
1287
+ dynamicPosition = IGF.Builder .CreateAdd (dynamicPosition, dynamicLength);
1288
+
1289
+ // We consumed an expansion.
1290
+ numExpansions += 1 ;
1291
+
1292
+ return ;
1293
+ }
1294
+
1295
+ // Otherwise, we have a single scalar element, which deposits a single
1296
+ // label in the dynamic label string.
1297
+ unsigned length = 0 ;
1298
+
1299
+ // Scalar elements may have labels.
1300
+ if (elt.hasName ()) {
1301
+ // Index into the static label string.
1302
+ llvm::Constant *indices[] = {
1303
+ llvm::ConstantInt::get (IGF.IGM .SizeTy , staticPosition)
1304
+ };
1305
+
1306
+ // The source address in the static label string.
1307
+ Address srcAddr (
1308
+ llvm::ConstantExpr::getInBoundsGetElementPtr (
1309
+ IGF.IGM .Int8Ty , staticLabelString,
1310
+ indices),
1311
+ IGF.IGM .Int8Ty , Alignment (1 ));
1312
+
1313
+ // The number of bytes to copy; add one for the space at the end.
1314
+ length = elt.getName ().getLength () + 1 ;
1315
+
1316
+ // Desposit the label for this element in the dynamic label string.
1317
+ IGF.Builder .CreateMemCpy (eltAddr, srcAddr, Size (length));
1318
+
1319
+ sawLabel = true ;
1320
+ } else {
1321
+ length = 1 ;
1322
+
1323
+ // There is no label. The static label string stores a blank space,
1324
+ // and we need to update the dynamic string for the same.
1325
+ IGF.Builder .CreateStore (
1326
+ llvm::ConstantInt::get (IGF.IGM .Int8Ty , ' ' ),
1327
+ eltAddr);
1328
+ }
1329
+
1330
+ // We consumed one static label.
1331
+ staticPosition += length;
1332
+
1333
+ // We produced one dynamic label.
1334
+ auto *constant = llvm::ConstantInt::get (IGF.IGM .SizeTy , length);
1335
+ accumulateSum (IGF, dynamicPosition, constant);
1336
+ };
1337
+
1338
+ (void ) visitPackExplosion (IGF, packType, visitFn);
1339
+
1340
+ // Null-terminate the dynamic label string.
1341
+ auto eltAddr = IGF.Builder .CreateArrayGEP (labelString.getAddress (),
1342
+ dynamicPosition, Size (1 ));
1343
+ IGF.Builder .CreateStore (
1344
+ llvm::ConstantInt::get (IGF.IGM .Int8Ty , ' \0 ' ),
1345
+ eltAddr);
1346
+
1347
+ assert (sawLabel);
1348
+ (void ) sawLabel;
1349
+
1350
+ return labelString;
1351
+ }
1352
+
1353
+ StackAddress
1354
+ irgen::emitDynamicFunctionParameterFlags (IRGenFunction &IGF,
1355
+ AnyFunctionType::CanParamArrayRef params,
1356
+ CanPackType packType,
1357
+ llvm::Value *shapeExpression) {
1358
+ auto array =
1359
+ IGF.emitDynamicAlloca (IGF.IGM .Int32Ty , shapeExpression,
1360
+ Alignment (4 ), /* allowTaskAlloc=*/ true );
1361
+
1362
+ unsigned numExpansions = 0 ;
1363
+
1364
+ auto visitFn = [&](CanType eltTy,
1365
+ unsigned scalarIndex,
1366
+ llvm::Value *dynamicIndex,
1367
+ llvm::Value *dynamicLength) {
1368
+ if (scalarIndex != 0 || dynamicIndex == nullptr ) {
1369
+ auto *constant = llvm::ConstantInt::get (IGF.IGM .SizeTy , scalarIndex);
1370
+ accumulateSum (IGF, dynamicIndex, constant);
1371
+ }
1372
+
1373
+ auto elt = params[scalarIndex + numExpansions];
1374
+ auto flags = getABIParameterFlags (elt.getParameterFlags ());
1375
+ auto flagsVal = llvm::ConstantInt::get (
1376
+ IGF.IGM .Int32Ty , flags.getIntValue ());
1377
+
1378
+ assert (eltTy == elt.getPlainType ());
1379
+
1380
+ // If we're looking at a pack expansion, insert the appropriate
1381
+ // number of flags fields.
1382
+ if (auto expansionTy = dyn_cast<PackExpansionType>(eltTy)) {
1383
+ emitPackExpansionPack (IGF, array.getAddress (), expansionTy,
1384
+ dynamicIndex, dynamicLength,
1385
+ [&](llvm::Value *) -> llvm::Value * {
1386
+ return flagsVal;
1387
+ });
1388
+
1389
+ // We consumed an expansion.
1390
+ numExpansions += 1 ;
1391
+
1392
+ return ;
1393
+ }
1394
+
1395
+ // The destination address, where we put the current element's flags field.
1396
+ Address eltAddr (
1397
+ IGF.Builder .CreateInBoundsGEP (array.getAddress ().getElementType (),
1398
+ array.getAddressPointer (),
1399
+ dynamicIndex),
1400
+ array.getAddress ().getElementType (),
1401
+ array.getAlignment ());
1402
+
1403
+ // Otherwise, we have a single scalar element, which deposits a single
1404
+ // flags field.
1405
+ IGF.Builder .CreateStore (flagsVal, eltAddr);
1406
+ };
1407
+
1408
+ (void ) visitPackExplosion (IGF, packType, visitFn);
1409
+
1410
+ return array;
1411
+ }
0 commit comments