Skip to content

Commit 0e72564

Browse files
committed
IRGen: Support for tuple metadata involving pack expansions
1 parent 9bc0f25 commit 0e72564

File tree

4 files changed

+73
-72
lines changed

4 files changed

+73
-72
lines changed

lib/IRGen/GenPack.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,6 @@ static Address emitFixedSizeMetadataPackRef(IRGenFunction &IGF,
133133
pack = IGF.Builder.CreateConstArrayGEP(
134134
pack, 0, IGF.IGM.getPointerSize());
135135

136-
IGF.Builder.CreateLifetimeStart(
137-
pack, Size(IGF.IGM.getPointerSize() * elementCount));
138-
139136
return pack;
140137
}
141138

lib/IRGen/MetadataRequest.cpp

Lines changed: 47 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,13 +1136,7 @@ MetadataAccessStrategy irgen::getTypeMetadataAccessStrategy(CanType type) {
11361136

11371137
/// Emit a string encoding the labels in the given tuple type.
11381138
static 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

11821209
static 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
}

test/IRGen/variadic_generic_types.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,21 @@ struct G<T...> {
1616
func caller() {
1717
callee()
1818
}
19+
20+
func makeTuple1() -> (T...).Type {
21+
return (T...).self
22+
}
23+
24+
func makeTuple2() -> ((Array<T>)...).Type {
25+
return ((Array<T>)...).self
26+
}
1927
}
2028

2129
func blackHole<T>(_: T) {}
2230

2331
blackHole(G< >.self)
2432
blackHole(G<Int, String>.self)
2533

26-
func genericMetadata<T...>(_: T...) {
27-
blackHole(G<T... >.self)
28-
}
34+
let g = G<Int, String, Float>()
35+
blackHole(g.makeTuple1())
36+
blackHole(g.makeTuple2())
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-run-simple-swift(-enable-experimental-feature VariadicGenerics) | %FileCheck %s
2+
3+
// REQUIRES: executable_test
4+
5+
// Because of -enable-experimental-feature VariadicGenerics
6+
// REQUIRES: asserts
7+
8+
struct G<T...> {
9+
func makeTuple() {
10+
print(((Array<T>)...).self)
11+
}
12+
}
13+
14+
// CHECK: (Array<Int>, Array<String>, Array<Float>)
15+
G<Int, String, Float>().makeTuple()

0 commit comments

Comments
 (0)