Skip to content

Commit fd6ff41

Browse files
committed
IRGen: Fix indexing into on-heap packs from emitTypeMetadataPackElementRef()
1 parent 60ffd84 commit fd6ff41

File tree

4 files changed

+78
-29
lines changed

4 files changed

+78
-29
lines changed

lib/IRGen/GenPack.cpp

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,10 @@ static Address emitFixedSizeMetadataPackRef(IRGenFunction &IGF,
209209
return pack;
210210
}
211211

212-
static llvm::Value *bindMetadataAtIndex(IRGenFunction &IGF,
213-
CanType elementArchetype,
212+
/// Use this to index into packs to correctly handle on-heap packs.
213+
static llvm::Value *loadMetadataAtIndex(IRGenFunction &IGF,
214214
llvm::Value *patternPack,
215-
llvm::Value *index,
216-
DynamicMetadataRequest request) {
217-
if (auto response = IGF.tryGetLocalTypeMetadata(elementArchetype, request))
218-
return response.getMetadata();
219-
215+
llvm::Value *index) {
220216
// If the pack is on the heap, the LSB is set, so mask it off.
221217
patternPack =
222218
IGF.Builder.CreatePtrToInt(patternPack, IGF.IGM.SizeTy);
@@ -233,7 +229,18 @@ static llvm::Value *bindMetadataAtIndex(IRGenFunction &IGF,
233229
IGF.Builder.CreateInBoundsGEP(patternPackAddress.getElementType(),
234230
patternPackAddress.getAddress(), index),
235231
patternPackAddress.getElementType(), patternPackAddress.getAlignment());
236-
llvm::Value *metadata = IGF.Builder.CreateLoad(fromPtr);
232+
return IGF.Builder.CreateLoad(fromPtr);
233+
}
234+
235+
static llvm::Value *bindMetadataAtIndex(IRGenFunction &IGF,
236+
CanType elementArchetype,
237+
llvm::Value *patternPack,
238+
llvm::Value *index,
239+
DynamicMetadataRequest request) {
240+
if (auto response = IGF.tryGetLocalTypeMetadata(elementArchetype, request))
241+
return response.getMetadata();
242+
243+
llvm::Value *metadata = loadMetadataAtIndex(IGF, patternPack, index);
237244

238245
// Bind the metadata pack element to the element archetype.
239246
IGF.setScopedLocalTypeMetadata(elementArchetype,
@@ -242,15 +249,10 @@ static llvm::Value *bindMetadataAtIndex(IRGenFunction &IGF,
242249
return metadata;
243250
}
244251

245-
static llvm::Value *bindWitnessTableAtIndex(IRGenFunction &IGF,
246-
CanType elementArchetype,
247-
ProtocolConformanceRef conf,
252+
/// Use this to index into packs to correctly handle on-heap packs.
253+
static llvm::Value *loadWitnessTableAtIndex(IRGenFunction &IGF,
248254
llvm::Value *wtablePack,
249255
llvm::Value *index) {
250-
auto key = LocalTypeDataKind::forProtocolWitnessTable(conf);
251-
if (auto *wtable = IGF.tryGetLocalTypeData(elementArchetype, key))
252-
return wtable;
253-
254256
// If the pack is on the heap, the LSB is set, so mask it off.
255257
wtablePack =
256258
IGF.Builder.CreatePtrToInt(wtablePack, IGF.IGM.SizeTy);
@@ -267,7 +269,19 @@ static llvm::Value *bindWitnessTableAtIndex(IRGenFunction &IGF,
267269
IGF.Builder.CreateInBoundsGEP(patternPackAddress.getElementType(),
268270
patternPackAddress.getAddress(), index),
269271
patternPackAddress.getElementType(), patternPackAddress.getAlignment());
270-
auto *wtable = IGF.Builder.CreateLoad(fromPtr);
272+
return IGF.Builder.CreateLoad(fromPtr);
273+
}
274+
275+
static llvm::Value *bindWitnessTableAtIndex(IRGenFunction &IGF,
276+
CanType elementArchetype,
277+
ProtocolConformanceRef conf,
278+
llvm::Value *wtablePack,
279+
llvm::Value *index) {
280+
auto key = LocalTypeDataKind::forProtocolWitnessTable(conf);
281+
if (auto *wtable = IGF.tryGetLocalTypeData(elementArchetype, key))
282+
return wtable;
283+
284+
auto *wtable = loadWitnessTableAtIndex(IGF, wtablePack, index);
271285

272286
// Bind the witness table pack element to the element archetype.
273287
IGF.setScopedLocalTypeData(elementArchetype, key, wtable);
@@ -658,18 +672,10 @@ llvm::Value *irgen::emitTypeMetadataPackElementRef(
658672
if (materializedMetadataPack &&
659673
llvm::all_of(materializedWtablePacks,
660674
[](auto *wtablePack) { return wtablePack; })) {
661-
auto *gep = IGF.Builder.CreateInBoundsGEP(
662-
IGF.IGM.TypeMetadataPtrTy, materializedMetadataPack.getMetadata(),
663-
index);
664-
auto addr =
665-
Address(gep, IGF.IGM.TypeMetadataPtrTy, IGF.IGM.getPointerAlignment());
666-
auto *metadata = IGF.Builder.CreateLoad(addr);
675+
auto *metadataPack = materializedMetadataPack.getMetadata();
676+
auto *metadata = loadMetadataAtIndex(IGF, metadataPack, index);
667677
for (auto *wtablePack : materializedWtablePacks) {
668-
auto *gep = IGF.Builder.CreateInBoundsGEP(IGF.IGM.WitnessTablePtrTy,
669-
wtablePack, index);
670-
auto addr = Address(gep, IGF.IGM.WitnessTablePtrTy,
671-
IGF.IGM.getPointerAlignment());
672-
auto *wtable = IGF.Builder.CreateLoad(addr);
678+
auto *wtable = loadWitnessTableAtIndex(IGF, wtablePack, index);
673679
wtables.push_back(wtable);
674680
}
675681
return metadata;

test/IRGen/run_variadic_generics.sil

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,9 @@ entry(%intIndex : $Builtin.Word):
573573

574574
// Verify that we just gep into a parameter pack when that's all that the pack consists of.
575575
// CHECK-LL: define {{.*}}void @direct_access_from_parameter(i{{(32|64)}} [[INDEX:%[^,]+]], i{{(32|64)}} {{%[^,]+}}, %swift.type** [[PACK:%[^,]+]])
576+
// CHECK-LL: [[PACK_ADDR:%.*]] = ptrtoint %swift.type** [[PACK]] to i{{(32|64)}}
577+
// CHECK-LL: [[PACK_ADDR2:%.*]] = and i{{(32|64)}} [[PACK_ADDR]], -2
578+
// CHECK-LL: [[PACK:%.*]] = inttoptr i{{(32|64)}} [[PACK_ADDR2]] to %swift.type**
576579
// CHECK-LL: [[ELEMENT_ADDRESS:%[^,]+]] = getelementptr inbounds %swift.type*, %swift.type** [[PACK]], i{{(32|64)}} [[INDEX]]
577580
// CHECK-LL: [[ELEMENT:%[^,]+]] = load %swift.type*, %swift.type** [[ELEMENT_ADDRESS]]
578581
// CHECK-LL: call swiftcc void @printGenericType(%swift.type* [[ELEMENT]], %swift.type* [[ELEMENT]])
@@ -593,8 +596,14 @@ entry(%intIndex : $Builtin.Word):
593596
// CHECK-LL-SAME: i{{(32|64)}} {{%[^,]+}},
594597
// CHECK-LL-SAME: %swift.type** [[METADATA_PACK:%[^,]+]],
595598
// CHECK-LL-SAME: i8*** [[WTABLE_PACK:%[^,]+]])
596-
// CHECK-LL: [[METADATA_ADDRESS:%[^,]+]] = getelementptr inbounds %swift.type*, %swift.type** [[METADATA_PACK]], i{{(32|64)}} [[INDEX]]
599+
// CHECK-LL: [[PACK_ADDR:%.*]] = ptrtoint %swift.type** [[METADATA_PACK]] to i{{(32|64)}}
600+
// CHECK-LL: [[PACK_ADDR2:%.*]] = and i{{(32|64)}} [[PACK_ADDR]], -2
601+
// CHECK-LL: [[METADATA_PACK:%.*]] = inttoptr i{{(32|64)}} [[PACK_ADDR2]] to %swift.type**
602+
// CHECK-LL: [[METADATA_ADDRESS:%[^,]+]] = getelementptr inbounds %swift.type*, %swift.type** [[METADATA_PACK]], i{{(32|64)}} [[INDEX]]
597603
// CHECK-LL: [[METADATA:%[^,]+]] = load %swift.type*, %swift.type** [[METADATA_ADDRESS]]
604+
// CHECK-LL: [[PACK_ADDR:%.*]] = ptrtoint i8*** [[WTABLE_PACK]] to i{{(32|64)}}
605+
// CHECK-LL: [[PACK_ADDR2:%.*]] = and i{{(32|64)}} [[PACK_ADDR]], -2
606+
// CHECK-LL: [[WTABLE_PACK:%.*]] = inttoptr i{{(32|64)}} [[PACK_ADDR2]] to i8***
598607
// CHECK-LL: [[WTABLE_ADDRESS:%[^,]+]] = getelementptr inbounds i8**, i8*** [[WTABLE_PACK]], i{{(32|64)}} [[INDEX]]
599608
// CHECK-LL: [[WTABLE:%[^,]+]] = load i8**, i8*** [[WTABLE_ADDRESS]], align
600609
// CHECK-LL: call swiftcc void @printGenericType(%swift.type* [[METADATA]], %swift.type* [[METADATA]])
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-swift-frontend -emit-ir %s -enable-experimental-feature VariadicGenerics | %FileCheck %s -DINT=i%target-ptrsize
2+
3+
// Because of -enable-experimental-feature VariadicGenerics
4+
// REQUIRES: asserts
5+
6+
public struct G<T> {}
7+
8+
public struct GG<each T> {
9+
var elements: (repeat G<each T>)
10+
11+
public func doStuff(input: repeat each T) {
12+
_ = (repeat each input)
13+
}
14+
}
15+
16+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s28variadic_generic_fulfillment2GGV7doStuff5inputyxxQp_tF"(%swift.opaque** noalias nocapture %0, %swift.type* %"GG<repeat each T>", %T28variadic_generic_fulfillment2GGV* noalias nocapture swiftself %1)
17+
// CHECK: [[METADATA:%.*]] = bitcast %swift.type* %"GG<repeat each T>" to %swift.type***
18+
// CHECK: [[T_PTR:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[METADATA]]
19+
// CHECK: [[T:%.*]] = load %swift.type**, %swift.type*** [[T_PTR]]
20+
21+
// CHECK: [[INDEX:%.*]] = phi [[INT]] [ 0, %entry ], [ {{%.*}}, {{%.*}} ]
22+
23+
// Make sure we mask off the LSB since we have an on-heap pack here.
24+
25+
// CHECK: [[T_ADDR:%.*]] = ptrtoint %swift.type** [[T]] to [[INT]]
26+
// CHECK-NEXT: [[T_ADDR2:%.*]] = and [[INT]] [[T_ADDR]], -2
27+
// CHECK-NEXT: [[T2:%.*]] = inttoptr [[INT]] [[T_ADDR2]] to %swift.type**
28+
// CHECK-NEXT: [[T_ELT_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T2]], [[INT]] [[INDEX]]
29+
// CHECK-NEXT: [[T_ELT:%.*]] = load %swift.type*, %swift.type** [[T_ELT_PTR]]
30+
31+
// CHECK: ret void

test/IRGen/variadic_generic_outlining.sil

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ struct Wrapper<Value> {
1414
// an opened element type.
1515
//
1616
// CHECK-LABEL: define{{.*}}void @test_outlining
17-
// CHECK: [[T0:%.*]] = getelementptr inbounds %swift.type*, %swift.type** %T, [[INT]]
17+
// CHECK: [[PACK_ADDR:%.*]] = ptrtoint %swift.type** %T to [[INT]]
18+
// CHECK-NEXT: [[PACK_ADDR2:%.*]] = and [[INT]] [[PACK_ADDR]], -2
19+
// CHECK-NEXT: [[PACK:%.*]] = inttoptr [[INT]] [[PACK_ADDR2]] to %swift.type**
20+
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[PACK]], [[INT]]
1821
// CHECK-NEXT: [[ELT_TYPE:%.*]] = load %swift.type*, %swift.type** [[T0]], align
1922
// Test that we do the copy through the VWT for the element type.
2023
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[ELT_TYPE]] to i8***

0 commit comments

Comments
 (0)