Skip to content

Commit ba07393

Browse files
Merge pull request #66281 from nate-chandler/rdar110123679
[GenPack] Always heapify metadata packs.
2 parents ad6caaa + 0b5a233 commit ba07393

File tree

5 files changed

+160
-46
lines changed

5 files changed

+160
-46
lines changed

lib/IRGen/GenPack.cpp

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -445,15 +445,16 @@ static void emitPackExpansionMetadataPack(IRGenFunction &IGF, Address pack,
445445
});
446446
}
447447

448-
StackAddress
449-
irgen::emitTypeMetadataPack(IRGenFunction &IGF,
450-
CanPackType packType,
448+
std::pair<StackAddress, llvm::Value *>
449+
irgen::emitTypeMetadataPack(IRGenFunction &IGF, CanPackType packType,
451450
DynamicMetadataRequest request) {
452451
auto *shape = IGF.emitPackShapeExpression(packType);
453452

454453
if (auto *constantInt = dyn_cast<llvm::ConstantInt>(shape)) {
455454
assert(packType->getNumElements() == constantInt->getValue());
456-
return StackAddress(emitFixedSizeMetadataPackRef(IGF, packType, request));
455+
auto pack =
456+
StackAddress(emitFixedSizeMetadataPackRef(IGF, packType, request));
457+
return {pack, constantInt};
457458
}
458459

459460
assert(packType->containsPackExpansionType());
@@ -488,7 +489,13 @@ irgen::emitTypeMetadataPack(IRGenFunction &IGF,
488489

489490
visitPackExplosion(IGF, packType, visitFn);
490491

491-
return pack;
492+
return {pack, shape};
493+
}
494+
495+
static Optional<unsigned> countForShape(llvm::Value *shape) {
496+
if (auto *constant = dyn_cast<llvm::ConstantInt>(shape))
497+
return constant->getValue().getZExtValue();
498+
return llvm::None;
492499
}
493500

494501
MetadataResponse
@@ -497,11 +504,19 @@ irgen::emitTypeMetadataPackRef(IRGenFunction &IGF, CanPackType packType,
497504
if (auto result = tryGetLocalPackTypeMetadata(IGF, packType, request))
498505
return result;
499506

500-
auto pack = emitTypeMetadataPack(IGF, packType, request);
507+
StackAddress pack;
508+
llvm::Value *shape;
509+
std::tie(pack, shape) = emitTypeMetadataPack(IGF, packType, request);
510+
501511
auto *metadata = pack.getAddress().getAddress();
502512
metadata = IGF.Builder.CreatePointerCast(
503513
metadata, IGF.IGM.TypeMetadataPtrTy->getPointerTo());
504514

515+
metadata = IGF.Builder.CreateCall(
516+
IGF.IGM.getAllocateMetadataPackFunctionPointer(), {metadata, shape});
517+
518+
cleanupTypeMetadataPack(IGF, pack, shape);
519+
505520
auto response = MetadataResponse::forComplete(metadata);
506521
IGF.setScopedLocalTypeMetadata(packType, response);
507522

@@ -573,15 +588,16 @@ static void emitPackExpansionWitnessTablePack(
573588
});
574589
}
575590

576-
StackAddress irgen::emitWitnessTablePack(IRGenFunction &IGF,
577-
CanPackType packType,
578-
PackConformance *packConformance) {
591+
std::pair<StackAddress, llvm::Value *>
592+
irgen::emitWitnessTablePack(IRGenFunction &IGF, CanPackType packType,
593+
PackConformance *packConformance) {
579594
auto *shape = IGF.emitPackShapeExpression(packType);
580595

581596
if (auto *constantInt = dyn_cast<llvm::ConstantInt>(shape)) {
582597
assert(packType->getNumElements() == constantInt->getValue());
583-
return StackAddress(
598+
auto pack = StackAddress(
584599
emitFixedSizeWitnessTablePack(IGF, packType, packConformance));
600+
return {pack, constantInt};
585601
}
586602

587603
assert(packType->containsPackExpansionType());
@@ -618,16 +634,16 @@ StackAddress irgen::emitWitnessTablePack(IRGenFunction &IGF,
618634

619635
visitPackExplosion(IGF, packType, visitFn);
620636

621-
return pack;
637+
return {pack, shape};
622638
}
623639

624640
void irgen::cleanupWitnessTablePack(IRGenFunction &IGF, StackAddress pack,
625-
Optional<unsigned> elementCount) {
641+
llvm::Value *shape) {
626642
if (pack.getExtraInfo()) {
627643
IGF.emitDeallocateDynamicAlloca(pack);
628-
} else {
644+
} else if (auto count = countForShape(shape)) {
629645
IGF.Builder.CreateLifetimeEnd(pack.getAddress(),
630-
IGF.IGM.getPointerSize() * (*elementCount));
646+
IGF.IGM.getPointerSize() * (count.value()));
631647
}
632648
}
633649

@@ -650,12 +666,19 @@ llvm::Value *irgen::emitWitnessTablePackRef(IRGenFunction &IGF,
650666
if (auto *wtable = tryGetLocalPackTypeData(IGF, packType, localDataKind))
651667
return wtable;
652668

653-
auto pack = emitWitnessTablePack(IGF, packType, conformance);
669+
StackAddress pack;
670+
llvm::Value *shape;
671+
std::tie(pack, shape) = emitWitnessTablePack(IGF, packType, conformance);
654672

655673
auto *result = pack.getAddress().getAddress();
656674
result = IGF.Builder.CreatePointerCast(
657675
result, IGF.IGM.WitnessTablePtrTy->getPointerTo());
658676

677+
result = IGF.Builder.CreateCall(
678+
IGF.IGM.getAllocateWitnessTablePackFunctionPointer(), {result, shape});
679+
680+
cleanupWitnessTablePack(IGF, pack, shape);
681+
659682
IGF.setScopedLocalTypeData(packType, localDataKind, result);
660683

661684
return result;
@@ -1018,14 +1041,13 @@ void irgen::bindOpenedElementArchetypesAtIndex(IRGenFunction &IGF,
10181041
}
10191042
}
10201043

1021-
void irgen::cleanupTypeMetadataPack(IRGenFunction &IGF,
1022-
StackAddress pack,
1023-
Optional<unsigned> elementCount) {
1044+
void irgen::cleanupTypeMetadataPack(IRGenFunction &IGF, StackAddress pack,
1045+
llvm::Value *shape) {
10241046
if (pack.getExtraInfo()) {
10251047
IGF.emitDeallocateDynamicAlloca(pack);
1026-
} else {
1048+
} else if (auto count = countForShape(shape)) {
10271049
IGF.Builder.CreateLifetimeEnd(pack.getAddress(),
1028-
IGF.IGM.getPointerSize() * (*elementCount));
1050+
IGF.IGM.getPointerSize() * (*count));
10291051
}
10301052
}
10311053

lib/IRGen/GenPack.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,8 @@ emitPackArchetypeMetadataRef(IRGenFunction &IGF,
4343
CanPackArchetypeType type,
4444
DynamicMetadataRequest request);
4545

46-
StackAddress
47-
emitTypeMetadataPack(IRGenFunction &IGF,
48-
CanPackType packType,
46+
std::pair<StackAddress, llvm::Value *>
47+
emitTypeMetadataPack(IRGenFunction &IGF, CanPackType packType,
4948
DynamicMetadataRequest request);
5049

5150
MetadataResponse
@@ -68,18 +67,18 @@ emitTypeMetadataPackElementRef(IRGenFunction &IGF, CanPackType packType,
6867
DynamicMetadataRequest request,
6968
llvm::SmallVectorImpl<llvm::Value *> &wtables);
7069

71-
void cleanupTypeMetadataPack(IRGenFunction &IGF,
72-
StackAddress pack,
73-
Optional<unsigned> elementCount);
70+
void cleanupTypeMetadataPack(IRGenFunction &IGF, StackAddress pack,
71+
llvm::Value *shape);
7472

75-
StackAddress emitWitnessTablePack(IRGenFunction &IGF, CanPackType packType,
76-
PackConformance *conformance);
73+
std::pair<StackAddress, llvm::Value *>
74+
emitWitnessTablePack(IRGenFunction &IGF, CanPackType packType,
75+
PackConformance *conformance);
7776

7877
llvm::Value *emitWitnessTablePackRef(IRGenFunction &IGF, CanPackType packType,
7978
PackConformance *conformance);
8079

8180
void cleanupWitnessTablePack(IRGenFunction &IGF, StackAddress pack,
82-
Optional<unsigned> elementCount);
81+
llvm::Value *shape);
8382

8483
/// Emit the dynamic index of a particular structural component
8584
/// of the given pack type. If the component is a pack expansion, this

lib/IRGen/MetadataRequest.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,7 +1233,10 @@ static MetadataResponse emitDynamicTupleTypeMetadataRef(IRGenFunction &IGF,
12331233

12341234
// Otherwise, we know that either statically or dynamically, we have more than
12351235
// one element. Emit the pack.
1236-
auto addr = emitTypeMetadataPack(IGF, packType, MetadataState::Abstract);
1236+
llvm::Value *shape;
1237+
StackAddress addr;
1238+
std::tie(addr, shape) =
1239+
emitTypeMetadataPack(IGF, packType, MetadataState::Abstract);
12371240

12381241
auto *pointerToFirst = IGF.Builder.CreatePointerCast(
12391242
addr.getAddressPointer(), IGF.IGM.TypeMetadataPtrPtrTy);
@@ -1252,12 +1255,7 @@ static MetadataResponse emitDynamicTupleTypeMetadataRef(IRGenFunction &IGF,
12521255
call->setCallingConv(IGF.IGM.SwiftCC);
12531256
call->setDoesNotThrow();
12541257

1255-
// Clean up the pack.
1256-
Optional<unsigned> elementCount = 0;
1257-
if (auto *constant = dyn_cast<llvm::ConstantInt>(shapeExpression))
1258-
elementCount = constant->getValue().getZExtValue();
1259-
1260-
cleanupTypeMetadataPack(IGF, addr, elementCount);
1258+
cleanupTypeMetadataPack(IGF, addr, shape);
12611259
}
12621260

12631261
// Control flow join with the one-element case.

test/IRGen/variadic_generic_functions.sil

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@ struct Gen2<Fwd : Q> : Q {}
3232
// CHECK: [[METADATA_ELEMENT_0:%[^,]+]] = getelementptr inbounds [1 x %swift.type*], [1 x %swift.type*]* [[METADATA_PACK]]
3333
// CHECK: store %swift.type* bitcast {{.*}}$s26variadic_generic_functions3S_2VMf{{.*}}, %swift.type** [[METADATA_ELEMENT_0]]
3434
// CHECK: [[METADATA_PACK_PTR:%[^,]+]] = bitcast [1 x %swift.type*]* [[METADATA_PACK]] to %swift.type**
35+
// CHECK: [[HEAPIFIED_METADATA_PACK_PTR:%[^,]+]] = call swiftcc %swift.type** @swift_allocateMetadataPack(%swift.type** [[METADATA_PACK_PTR]], i64 1)
3536
// CHECK: [[WTABLE_ELEMENT_0:%[^,]+]] = getelementptr inbounds [1 x i8**], [1 x i8**]* [[WTABLE_PACK]]
3637
// CHECK: store i8** getelementptr inbounds {{.*}}$s26variadic_generic_functions3S_2VAA1PAAWP{{.*}}, i8*** [[WTABLE_ELEMENT_0]]
37-
// CHECK: [[WTABLE_PACK_ADDR:%[^,]+]] = bitcast [1 x i8**]* [[WTABLE_PACK]] to i8***
38-
// CHECK: call swiftcc void @g([[INT]] 1, %swift.type** [[METADATA_PACK_PTR]], i8*** [[WTABLE_PACK_ADDR]])
38+
// CHECK: [[WTABLE_PACK_PTR:%[^,]+]] = bitcast [1 x i8**]* [[WTABLE_PACK]] to i8***
39+
// CHECK: [[HEAPIFIED_WTABLE_PACK_PTR:%[^%]+]] = call swiftcc i8*** @swift_allocateWitnessTablePack(i8*** [[WTABLE_PACK_PTR]], i64 1)
40+
// CHECK: call swiftcc void @g([[INT]] 1, %swift.type** [[HEAPIFIED_METADATA_PACK_PTR]], i8*** [[HEAPIFIED_WTABLE_PACK_PTR]])
3941
sil @c : $() -> () {
4042
%g = function_ref @g : $@convention(thin) <each T : P> () -> ()
4143
apply %g<Pack{S_2}>() : $@convention(thin) <each T : P> () -> ()
@@ -89,9 +91,10 @@ sil @f1c : $<each T : PA where repeat each T.A : P> () -> () {}
8991
// CHECK-SAME: i8*** %"each T.PA",
9092
// CHECK-SAME: i8*** [[ASSOCIATEDTYPES_CONFORMANCES_TO_Q:%[^,]+]])
9193
// CHECK: [[ASSOCIATEDTYPES:%[^,]+]] = alloca %swift.type*, [[INT]] [[SHAPE]]
94+
// CHECK: [[HEAPIFIED_ASSOCIATEDTYPES:%[^,]+]] = call swiftcc %swift.type** @swift_allocateMetadataPack(%swift.type** [[ASSOCIATEDTYPES]], i64 %0)
9295
// CHECK: call swiftcc void @associatedtype_with_added_conformance_callee(
9396
// CHECK-SAME: [[INT]] [[SHAPE]],
94-
// CHECK-SAME: %swift.type** [[ASSOCIATEDTYPES]],
97+
// CHECK-SAME: %swift.type** [[HEAPIFIED_ASSOCIATEDTYPES]],
9598
// CHECK-SAME: i8*** [[ASSOCIATEDTYPES_CONFORMANCES_TO_Q]])
9699
sil @associatedtype_with_added_conformance : $<each T : PA where repeat each T.A : Q> () -> () {
97100
%callee = function_ref @associatedtype_with_added_conformance_callee : $@convention(thin) <each T : Q> () -> ()
@@ -109,9 +112,10 @@ sil @associatedtype_with_added_conformance_callee : $<each T : Q> () -> () {}
109112
// CHECK-SAME: i8*** %"each T.A.QA",
110113
// CHECK-SAME: i8*** [[ASSOCIATEDTYPES_CONFORMANCES_TO_Q:%[^,]+]])
111114
// CHECK: [[ASSOCIATEDTYPES:%[^,]+]] = alloca %swift.type*, [[INT]] [[SHAPE]]
115+
// CHECK: [[HEAPIFIED_ASSOCIATEDTYPES:%[^,]+]] = call swiftcc %swift.type** @swift_allocateMetadataPack(%swift.type** [[ASSOCIATEDTYPES]], i64 [[SHAPE]])
112116
// CHECK: call swiftcc void @associatedtype_with_added_conformance_2_callee(
113117
// CHECK-SAME: [[INT]] [[SHAPE]],
114-
// CHECK-SAME: %swift.type** [[ASSOCIATEDTYPES]],
118+
// CHECK-SAME: %swift.type** [[HEAPIFIED_ASSOCIATEDTYPES]],
115119
// CHECK-SAME: i8*** [[ASSOCIATEDTYPES_CONFORMANCES_TO_Q]])
116120
sil @associatedtype_with_added_conformance_2 : $<each T : PA where repeat each T.A : QA, repeat each T.A.A : R> () -> () {
117121
%j = function_ref @associatedtype_with_added_conformance_2_callee : $@convention(thin) <each T : R> () -> ()
@@ -127,11 +131,15 @@ sil @associatedtype_with_added_conformance_2_callee : $<each T : R> () -> () {}
127131
// CHECK-SAME: %swift.type** %"each T",
128132
// CHECK-SAME: i8*** %"each T.Q")
129133
// CHECK: [[GEN2_TYPES:%[^,]+]] = alloca %swift.type*, [[INT]] [[SHAPE]]
134+
// CHECK: [[HEAPIFIED_GEN2_TYPES:%[^,]+]] = call swiftcc %swift.type** @swift_allocateMetadataPack(%swift.type** [[GEN2_TYPES]], i64 [[SHAPE]])
135+
// CHECK: [[STORED_STACK_LOC:%[^,]+]] = call i8* @llvm.stacksave()
130136
// CHECK: [[GEN2_CONFORMANCES_TO_Q:%[^,]+]] = alloca i8**, [[INT]] [[SHAPE]]
137+
// CHECK: [[HEAPIFIED_GEN2_CONFORMANCES_TO_Q:%[^%]+]] = call swiftcc i8*** @swift_allocateWitnessTablePack(i8*** [[GEN2_CONFORMANCES_TO_Q]], i64 [[SHAPE]])
138+
// CHECK: call void @llvm.stackrestore(i8* [[STORED_STACK_LOC]])
131139
// CHECK: call swiftcc void @associatedtype_with_forwarded_conformance_1_callee(
132140
// CHECK-SAME: [[INT]] [[SHAPE]],
133-
// CHECK-SAME: %swift.type** [[GEN2_TYPES]],
134-
// CHECK-SAME: i8*** [[GEN2_CONFORMANCES_TO_Q]])
141+
// CHECK-SAME: %swift.type** [[HEAPIFIED_GEN2_TYPES]],
142+
// CHECK-SAME: i8*** [[HEAPIFIED_GEN2_CONFORMANCES_TO_Q]])
135143
sil @associatedtype_with_forwarded_conformance_1 : $<each T : Q> () -> () {
136144
%i = function_ref @associatedtype_with_forwarded_conformance_1_callee : $@convention(thin) <each T : Q> () -> ()
137145
apply %i<Pack{repeat Gen2<each T>}>() : $@convention(thin) <each T : Q> () -> ()
@@ -148,11 +156,15 @@ sil @associatedtype_with_forwarded_conformance_1_callee : $<each T : Q> () -> ()
148156
// CHECK-SAME: i8*** %"each T.PA",
149157
// CHECK-SAME: i8*** %"each T.A.Q")
150158
// CHECK: [[GEN1_TYPES:%[^,]+]] = alloca %swift.type*, [[INT]] [[SHAPE]]
159+
// CHECK: [[HEAPIFIED_GEN1_TYPES:%[^,]+]] = call swiftcc %swift.type** @swift_allocateMetadataPack(%swift.type** [[GEN1_TYPES]], i64 [[SHAPE]])
160+
// CHECK: [[STORED_STACK_LOC:%[^,]+]] = call i8* @llvm.stacksave()
151161
// CHECK: [[GEN1_CONFORMANCES_TO_PA:%[^,]+]] = alloca i8**, [[INT]] [[SHAPE]]
162+
// CHECK: [[HEAPIFIED_GEN1_CONFORMANCES_TO_PA:%[^%]+]] = call swiftcc i8*** @swift_allocateWitnessTablePack(i8*** [[GEN1_CONFORMANCES_TO_PA]], i64 [[SHAPE]])
163+
// CHECK: call void @llvm.stackrestore(i8* [[STORED_STACK_LOC]])
152164
// CHECK: call swiftcc void @generictype_with_forwarded_conformance_2_callee(
153165
// CHECK-SAME: [[INT]] [[SHAPE]],
154-
// CHECK-SAME: %swift.type** [[GEN1_TYPES]],
155-
// CHECK-SAME: i8*** [[GEN1_CONFORMANCES_TO_PA]],
166+
// CHECK-SAME: %swift.type** [[HEAPIFIED_GEN1_TYPES]],
167+
// CHECK-SAME: i8*** [[HEAPIFIED_GEN1_CONFORMANCES_TO_PA]],
156168
// CHECK-SAME: i8*** %"each T.A.Q")
157169
sil @generictype_with_forwarded_conformance_2 : $<each T : PA where repeat each T.A : Q>() -> () {
158170
%callee = function_ref @generictype_with_forwarded_conformance_2_callee : $@convention(thin) <each T : PA where repeat each T.A : Q> () -> ()
@@ -169,11 +181,15 @@ sil @generictype_with_forwarded_conformance_2_callee : $<each T : PA where repea
169181
// CHECK-SAME: i8*** %"each T.PA",
170182
// CHECK-SAME: i8*** %"each T.A.Q")
171183
// CHECK: [[GEN1_GEN1_TYPES:%[^,]+]] = alloca %swift.type*, [[INT]] [[SHAPE]]
184+
// CHECK: [[HEAPIFIED_GEN1_GEN1_TYPES:%[^%]+]] = call swiftcc %swift.type** @swift_allocateMetadataPack(%swift.type** [[GEN1_GEN1_TYPES]], i64 [[SHAPE]])
185+
// CHECK: [[STORED_STACK_LOC:%[^,]+]] = call i8* @llvm.stacksave()
172186
// CHECK: [[GEN1_GEN1_CONFORMANCES_TO_PA:%[^,]+]] = alloca i8**, [[INT]] [[SHAPE]]
187+
// CHECK: [[HEAPIFIED_GEN1_GEN1_CONFORMANCES_TO_PA:%[^%]+]] = call swiftcc i8*** @swift_allocateWitnessTablePack(i8*** [[GEN1_GEN1_CONFORMANCES_TO_PA]], i64 [[SHAPE]])
188+
// CHECK: call void @llvm.stackrestore(i8* [[STORED_STACK_LOC]])
173189
// CHECK: call swiftcc void @generic_with_forwarded_conformance_3_callee(
174190
// CHECK-SAME: [[INT]] [[SHAPE]],
175-
// CHECK-SAME: %swift.type** [[GEN1_GEN1_TYPES]],
176-
// CHECK-SAME: i8*** [[GEN1_GEN1_CONFORMANCES_TO_PA]],
191+
// CHECK-SAME: %swift.type** [[HEAPIFIED_GEN1_GEN1_TYPES]],
192+
// CHECK-SAME: i8*** [[HEAPIFIED_GEN1_GEN1_CONFORMANCES_TO_PA]],
177193
// CHECK-SAME: i8*** %"each T.A.Q")
178194
sil @generic_with_forwarded_conformance_3 : $<each T : PA where repeat each T.A : Q> () -> () {
179195
%callee = function_ref @generic_with_forwarded_conformance_3_callee : $@convention(thin) <each T : PA where repeat each T.A : Q> () -> ()

0 commit comments

Comments
 (0)