Skip to content

Commit da5b5c1

Browse files
committed
[IRGen] Lowered de/alloc_pack.
1 parent 58954ab commit da5b5c1

File tree

4 files changed

+82
-4
lines changed

4 files changed

+82
-4
lines changed

lib/IRGen/GenPack.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,3 +882,42 @@ Size irgen::getPackElementSize(IRGenModule &IGM, CanSILPackType ty) {
882882
assert(ty->isElementAddress() && "not implemented for direct packs");
883883
return IGM.getPointerSize();
884884
}
885+
886+
StackAddress irgen::allocatePack(IRGenFunction &IGF, CanSILPackType packType) {
887+
auto *shape = IGF.emitPackShapeExpression(packType);
888+
889+
auto elementSize = getPackElementSize(IGF.IGM, packType);
890+
891+
if (auto *constantInt = dyn_cast<llvm::ConstantInt>(shape)) {
892+
assert(packType->getNumElements() == constantInt->getValue());
893+
(void)constantInt;
894+
assert(!packType->containsPackExpansionType());
895+
unsigned elementCount = packType->getNumElements();
896+
auto allocType = llvm::ArrayType::get(
897+
IGF.IGM.OpaquePtrTy, elementCount);
898+
899+
auto addr = IGF.createAlloca(allocType, IGF.IGM.getPointerAlignment());
900+
IGF.Builder.CreateLifetimeStart(addr,
901+
elementSize * elementCount);
902+
return addr;
903+
}
904+
905+
assert(packType->containsPackExpansionType());
906+
auto addr = IGF.emitDynamicAlloca(IGF.IGM.OpaquePtrTy, shape,
907+
IGF.IGM.getPointerAlignment(),
908+
/*allowTaskAlloc=*/true);
909+
910+
return addr;
911+
}
912+
913+
void irgen::deallocatePack(IRGenFunction &IGF, StackAddress addr, CanSILPackType packType) {
914+
if (packType->containsPackExpansionType()) {
915+
IGF.emitDeallocateDynamicAlloca(addr);
916+
return;
917+
}
918+
919+
auto elementSize = getPackElementSize(IGF.IGM, packType);
920+
auto elementCount = packType->getNumElements();
921+
IGF.Builder.CreateLifetimeEnd(addr.getAddress(),
922+
elementSize * elementCount);
923+
}

lib/IRGen/GenPack.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ Address emitStorageAddressOfPackElement(IRGenFunction &IGF, Address pack,
9191

9292
Size getPackElementSize(IRGenModule &, CanSILPackType ty);
9393

94+
StackAddress allocatePack(IRGenFunction &IGF, CanSILPackType packType);
95+
96+
void deallocatePack(IRGenFunction &IGF, StackAddress addr, CanSILPackType packType);
97+
9498
} // end namespace irgen
9599
} // end namespace swift
96100

lib/IRGen/IRGenSIL.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5502,7 +5502,8 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
55025502
}
55035503

55045504
void IRGenSILFunction::visitAllocPackInst(swift::AllocPackInst *i) {
5505-
IGM.unimplemented(i->getLoc().getSourceLoc(), "alloc_pack");
5505+
auto addr = allocatePack(*this, i->getPackType());
5506+
setLoweredStackAddress(i, addr);
55065507
}
55075508

55085509
static void
@@ -5605,7 +5606,9 @@ void IRGenSILFunction::visitDeallocStackRefInst(DeallocStackRefInst *i) {
56055606
}
56065607

56075608
void IRGenSILFunction::visitDeallocPackInst(swift::DeallocPackInst *i) {
5608-
IGM.unimplemented(i->getLoc().getSourceLoc(), "dealloc_pack");
5609+
auto allocatedType = cast<SILPackType>(i->getOperand()->getType().getASTType());
5610+
StackAddress stackAddr = getLoweredStackAddress(i->getOperand());
5611+
deallocatePack(*this, stackAddr, allocatedType);
56095612
}
56105613

56115614
void IRGenSILFunction::visitDeallocRefInst(swift::DeallocRefInst *i) {

test/IRGen/variadic_generics.sil

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ bb0(%pack : $*Pack{Int, repeat each T, Int}):
8888
%elementAddr = pack_element_get %index of %pack : $*Pack{Int, repeat each T, Int} as $*Int
8989
%value = load %elementAddr : $*Int
9090
return %value : $Int
91-
}
92-
91+
}
92+
9393
// CHECK-LABEL: define{{.*}} @test_pack_element_set_1(
9494
// CHECK: [[INDEX:%.*]] = add [[INT]] %2, 1
9595
// CHECK: [[ELT_STORAGE:%.*]] = getelementptr inbounds %swift.opaque*, %swift.opaque** %0, [[INT]] [[INDEX]]
@@ -103,6 +103,38 @@ bb0(%pack : $*Pack{Int, repeat each T, Int}, %value : $Int):
103103
%index = scalar_pack_index 2 of $Pack{Int, repeat each T, Int}
104104
%elementAddr = pack_element_get %index of %pack : $*Pack{Int, repeat each T, Int} as $*Int
105105
store %value to %elementAddr : $*Int
106+
%ret = tuple ()
107+
return %ret : $()
108+
}
109+
110+
// CHECK-LABEL: define {{.*}}@test_pack_alloc_1_dynamic(
111+
// CHECK-SAME: i{{(32|64)}} [[PACK_SIZE:%[^,]+]]
112+
// CHECK: [[SIZE:%[^,]+]] = add i64 [[PACK_SIZE]], [[PACK_SIZE]]
113+
// CHECK: [[SP_SAVE:%[^,]+]] = call i8* @llvm.stacksave()
114+
// CHECK: alloca %swift.opaque*, i{{(32|64)}} [[SIZE]]
115+
// CHECK: call void @llvm.stackrestore(i8* [[SP_SAVE]])
116+
sil @test_pack_alloc_1_dynamic : $<T...> () -> () {
117+
// Control flow so that stack saving/restoring is emitted
118+
entry:
119+
cond_br undef, left, right
120+
left:
121+
br exit
122+
right:
123+
br exit
124+
exit:
125+
%addr = alloc_pack $Pack{repeat each T, repeat each T}
126+
dealloc_pack %addr : $*Pack{repeat each T, repeat each T}
127+
%ret = tuple ()
128+
return %ret : $()
129+
}
130+
131+
// CHECK-LABEL: define {{.*}}@test_pack_alloc_2_static
132+
// CHECK: [[STACK:%[^,]+]] = alloca [2 x %swift.opaque*]
133+
// CHECK: call void @llvm.lifetime.start.p0i8
134+
// CHECK: call void @llvm.lifetime.end.p0i8
135+
sil @test_pack_alloc_2_static : $<T...> () -> () {
136+
%addr = alloc_pack $Pack{Int, Int}
137+
dealloc_pack %addr : $*Pack{Int, Int}
106138
%ret = tuple ()
107139
return %ret : $()
108140
}

0 commit comments

Comments
 (0)