@@ -1136,13 +1136,7 @@ MetadataAccessStrategy irgen::getTypeMetadataAccessStrategy(CanType type) {
11361136
11371137// / Emit a string encoding the labels in the given tuple type.
11381138static llvm::Constant *getTupleLabelsString (IRGenModule &IGM,
1139- CanTupleType type,
1140- bool useLabels) {
1141- // If we were asked to ignore the labels, do so.
1142- if (!useLabels) {
1143- return llvm::ConstantPointerNull::get (IGM.Int8PtrTy );
1144- }
1145-
1139+ CanTupleType type) {
11461140 bool hasLabels = false ;
11471141 llvm::SmallString<128 > buffer;
11481142 for (auto &elt : type->getElements ()) {
@@ -1175,21 +1169,55 @@ static llvm::Constant *emitEmptyTupleTypeMetadataRef(IRGenModule &IGM) {
11751169 IGM.FullTypeMetadataStructTy , fullMetadata, indices);
11761170}
11771171
1178- using GetElementMetadataFn =
1179- llvm::function_ref<MetadataResponse(CanType eltType,
1180- DynamicMetadataRequest eltRequest)>;
1172+ static MetadataResponse emitDynamicTupleTypeMetadataRef (IRGenFunction &IGF,
1173+ CanTupleType type,
1174+ DynamicMetadataRequest request) {
1175+ SmallVector<Type, 2 > types;
1176+ types.append (type.getElementTypes ().begin (),
1177+ type.getElementTypes ().end ());
1178+
1179+ CanPackType packType = CanPackType (PackType::get (IGF.IGM .Context , types));
1180+
1181+ auto *shapeExpression = IGF.emitPackShapeExpression (packType);
1182+ auto addr = emitTypeMetadataPack (IGF, packType, MetadataState::Abstract);
1183+
1184+ auto *pointerToFirst = IGF.Builder .CreatePointerCast (
1185+ addr.getAddressPointer (), IGF.IGM .TypeMetadataPtrPtrTy );
1186+
1187+ llvm::Value *args[] = {
1188+ request.get (IGF),
1189+ shapeExpression,
1190+ pointerToFirst,
1191+ getTupleLabelsString (IGF.IGM , type),
1192+ llvm::ConstantPointerNull::get (IGF.IGM .WitnessTablePtrTy ) // proposed
1193+ };
1194+
1195+ auto call = IGF.Builder .CreateCall (
1196+ IGF.IGM .getGetTupleMetadataFunctionPointer (), args);
1197+ call->setCallingConv (IGF.IGM .SwiftCC );
1198+ call->setDoesNotThrow ();
1199+
1200+ Optional<unsigned > elementCount = 0 ;
1201+ if (auto *constant = dyn_cast<llvm::ConstantInt>(shapeExpression))
1202+ elementCount = constant->getValue ().getZExtValue ();
1203+
1204+ cleanupTypeMetadataPack (IGF, addr, elementCount);
1205+
1206+ return MetadataResponse::handle (IGF, request, call);
1207+ }
11811208
11821209static MetadataResponse emitTupleTypeMetadataRef (IRGenFunction &IGF,
11831210 CanTupleType type,
1184- DynamicMetadataRequest request,
1185- bool useLabels,
1186- GetElementMetadataFn getMetadataRecursive) {
1211+ DynamicMetadataRequest request) {
1212+ if (type->containsPackExpansionType ())
1213+ return emitDynamicTupleTypeMetadataRef (IGF, type, request);
1214+
11871215 auto getElementMetadata = [&](CanType type) {
11881216 // Just request the elements to be abstract so that we can always build
11891217 // the metadata.
11901218 // TODO: if we have a collector, or if this is a blocking request, maybe
11911219 // we should build a stronger request?
1192- return getMetadataRecursive (type, MetadataState::Abstract).getMetadata ();
1220+ return IGF. emitTypeMetadataRef (type, MetadataState::Abstract).getMetadata ();
11931221 };
11941222
11951223 switch (type->getNumElements ()) {
@@ -1200,7 +1228,7 @@ static MetadataResponse emitTupleTypeMetadataRef(IRGenFunction &IGF,
12001228 case 1 :
12011229 // For metadata purposes, we consider a singleton tuple to be
12021230 // isomorphic to its element type. ???
1203- return getMetadataRecursive (type.getElementType (0 ), request);
1231+ return IGF. emitTypeMetadataRef (type.getElementType (0 ), request);
12041232
12051233 case 2 : {
12061234 auto elt0Metadata = getElementMetadata (type.getElementType (0 ));
@@ -1209,7 +1237,7 @@ static MetadataResponse emitTupleTypeMetadataRef(IRGenFunction &IGF,
12091237 llvm::Value *args[] = {
12101238 request.get (IGF),
12111239 elt0Metadata, elt1Metadata,
1212- getTupleLabelsString (IGF.IGM , type, useLabels ),
1240+ getTupleLabelsString (IGF.IGM , type),
12131241 llvm::ConstantPointerNull::get (IGF.IGM .WitnessTablePtrTy ) // proposed
12141242 };
12151243
@@ -1229,7 +1257,7 @@ static MetadataResponse emitTupleTypeMetadataRef(IRGenFunction &IGF,
12291257 llvm::Value *args[] = {
12301258 request.get (IGF),
12311259 elt0Metadata, elt1Metadata, elt2Metadata,
1232- getTupleLabelsString (IGF.IGM , type, useLabels ),
1260+ getTupleLabelsString (IGF.IGM , type),
12331261 llvm::ConstantPointerNull::get (IGF.IGM .WitnessTablePtrTy ) // proposed
12341262 };
12351263
@@ -1241,50 +1269,7 @@ static MetadataResponse emitTupleTypeMetadataRef(IRGenFunction &IGF,
12411269 return MetadataResponse::handle (IGF, request, call);
12421270 }
12431271 default :
1244- // TODO: use a caching entrypoint (with all information
1245- // out-of-line) for non-dependent tuples.
1246-
1247- llvm::Value *pointerToFirst = nullptr ; // appease -Wuninitialized
1248-
1249- auto elements = type.getElementTypes ();
1250- auto arrayTy = llvm::ArrayType::get (IGF.IGM .TypeMetadataPtrTy ,
1251- elements.size ());
1252- Address buffer = IGF.createAlloca (arrayTy,IGF.IGM .getPointerAlignment (),
1253- " tuple-elements" );
1254- IGF.Builder .CreateLifetimeStart (buffer,
1255- IGF.IGM .getPointerSize () * elements.size ());
1256- for (auto i : indices (elements)) {
1257- // Find the metadata pointer for this element.
1258- llvm::Value *eltMetadata = getElementMetadata (elements[i]);
1259-
1260- // GEP to the appropriate element and store.
1261- Address eltPtr = IGF.Builder .CreateStructGEP (buffer, i,
1262- IGF.IGM .getPointerSize ());
1263- IGF.Builder .CreateStore (eltMetadata, eltPtr);
1264-
1265- // Remember the GEP to the first element.
1266- if (i == 0 ) pointerToFirst = eltPtr.getAddress ();
1267- }
1268-
1269- TupleTypeFlags flags =
1270- TupleTypeFlags ().withNumElements (elements.size ());
1271- llvm::Value *args[] = {
1272- request.get (IGF),
1273- llvm::ConstantInt::get (IGF.IGM .SizeTy , flags.getIntValue ()),
1274- pointerToFirst,
1275- getTupleLabelsString (IGF.IGM , type, useLabels),
1276- llvm::ConstantPointerNull::get (IGF.IGM .WitnessTablePtrTy ) // proposed
1277- };
1278-
1279- auto call = IGF.Builder .CreateCall (
1280- IGF.IGM .getGetTupleMetadataFunctionPointer (), args);
1281- call->setCallingConv (IGF.IGM .SwiftCC );
1282- call->setDoesNotThrow ();
1283-
1284- IGF.Builder .CreateLifetimeEnd (buffer,
1285- IGF.IGM .getPointerSize () * elements.size ());
1286-
1287- return MetadataResponse::handle (IGF, request, call);
1272+ return emitDynamicTupleTypeMetadataRef (IGF, type, request);
12881273 }
12891274}
12901275
@@ -1442,11 +1427,7 @@ namespace {
14421427 if (auto cached = tryGetLocal (type, request))
14431428 return cached;
14441429
1445- auto response = emitTupleTypeMetadataRef (IGF, type, request,
1446- /* labels*/ true ,
1447- [&](CanType eltType, DynamicMetadataRequest eltRequest) {
1448- return IGF.emitTypeMetadataRef (eltType, eltRequest);
1449- });
1430+ auto response = emitTupleTypeMetadataRef (IGF, type, request);
14501431
14511432 return setLocal (type, response);
14521433 }
0 commit comments