Skip to content

Commit 18dd471

Browse files
committed
[IRGen] Lowered de/alloc_pack.
1 parent a3f2406 commit 18dd471

File tree

4 files changed

+75
-30
lines changed

4 files changed

+75
-30
lines changed

lib/IRGen/GenPack.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,3 +604,42 @@ Size irgen::getPackElementSize(IRGenModule &IGM, CanSILPackType ty) {
604604
assert(ty->isElementAddress() && "not implemented for direct packs");
605605
return IGM.getPointerSize();
606606
}
607+
608+
StackAddress irgen::allocatePack(IRGenFunction &IGF, CanSILPackType packType) {
609+
auto *shape = IGF.emitPackShapeExpression(packType);
610+
611+
auto elementSize = getPackElementSize(IGF.IGM, packType);
612+
613+
if (auto *constantInt = dyn_cast<llvm::ConstantInt>(shape)) {
614+
assert(packType->getNumElements() == constantInt->getValue());
615+
assert(!packType->containsPackExpansionType());
616+
unsigned elementCount = packType->getNumElements();
617+
auto allocType = llvm::ArrayType::get(
618+
IGF.IGM.OpaquePtrTy, elementCount);
619+
620+
auto addr = IGF.createAlloca(allocType, IGF.IGM.getPointerAlignment());
621+
IGF.Builder.CreateLifetimeStart(addr,
622+
elementSize * elementCount);
623+
return addr;
624+
}
625+
626+
assert(packType->containsPackExpansionType());
627+
auto addr = IGF.emitDynamicAlloca(IGF.IGM.OpaquePtrTy, shape,
628+
IGF.IGM.getPointerAlignment(),
629+
/*allowTaskAlloc=*/true);
630+
631+
return addr;
632+
}
633+
634+
void irgen::deallocatePack(IRGenFunction &IGF, StackAddress addr, CanSILPackType packType) {
635+
if (packType->containsPackExpansionType()) {
636+
IGF.emitDeallocateDynamicAlloca(addr);
637+
return;
638+
}
639+
640+
assert(!packType->containsPackExpansionType());
641+
auto elementSize = getPackElementSize(IGF.IGM, packType);
642+
auto elementCount = packType->getNumElements();
643+
IGF.Builder.CreateLifetimeEnd(addr.getAddress(),
644+
elementSize * elementCount);
645+
}

lib/IRGen/GenPack.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,11 @@ Address emitStorageAddressOfPackElement(IRGenFunction &IGF, Address pack,
7979

8080
Size getPackElementSize(IRGenModule &, CanSILPackType ty);
8181

82+
StackAddress allocatePack(IRGenFunction &IGF, CanSILPackType packType);
83+
84+
void deallocatePack(IRGenFunction &IGF, StackAddress addr, CanSILPackType packType);
85+
8286
} // end namespace irgen
8387
} // end namespace swift
8488

85-
#endif
89+
#endif

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: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -74,35 +74,34 @@ bb0:
7474
return %index : $Builtin.PackIndex
7575
}
7676

77-
// CHECK-LABEL: define{{.*}} @test_pack_element_get_1(
78-
// CHECK: [[INDEX:%.*]] = add [[INT]] %1, 1
79-
// CHECK: [[ELT_STORAGE:%.*]] = getelementptr inbounds %swift.opaque*, %swift.opaque** %0, [[INT]] [[INDEX]]
80-
// CHECK: [[BITCAST_STORAGE:%.*]] = bitcast %swift.opaque** [[ELT_STORAGE]] to %TSi**
81-
// CHECK: [[ELT_ADDR:%.*]] = load %TSi*, %TSi** [[BITCAST_STORAGE]], align
82-
// CHECK: [[VALUE_ADDR:%.*]] = getelementptr inbounds %TSi, %TSi* [[ELT_ADDR]], i32 0, i32 0
83-
// CHECK: [[RET:%.*]] = load [[INT]], [[INT]]* [[VALUE_ADDR]], align
84-
// CHECK: ret [[INT]] [[RET]]
85-
sil @test_pack_element_get_1 : $<T...> (@pack_owned Pack{Int, repeat each T, Int}) -> Int {
86-
bb0(%pack : $*Pack{Int, repeat each T, Int}):
87-
%index = scalar_pack_index 2 of $Pack{Int, repeat each T, Int}
88-
%elementAddr = pack_element_get %index of %pack : $*Pack{Int, repeat each T, Int} as $*Int
89-
%value = load %elementAddr : $*Int
90-
return %value : $Int
77+
// CHECK-LABEL: define {{.*}}@test_pack_alloc_1_dynamic(
78+
// CHECK-SAME: i{{(32|64)}} [[PACK_SIZE:%[^,]+]]
79+
// CHECK: [[SIZE:%[^,]+]] = add i64 [[PACK_SIZE]], [[PACK_SIZE]]
80+
// CHECK: [[SP_SAVE:%[^,]+]] = call i8* @llvm.stacksave()
81+
// CHECK: alloca %swift.opaque*, i{{(32|64)}} [[SIZE]]
82+
// CHECK: call void @llvm.stackrestore(i8* [[SP_SAVE]])
83+
sil @test_pack_alloc_1_dynamic : $<T...> () -> () {
84+
// Control flow so that stack saving/restoring is emitted
85+
entry:
86+
cond_br undef, left, right
87+
left:
88+
br exit
89+
right:
90+
br exit
91+
exit:
92+
%addr = alloc_pack $Pack{repeat each T, repeat each T}
93+
dealloc_pack %addr : $*Pack{repeat each T, repeat each T}
94+
%ret = tuple ()
95+
return %ret : $()
9196
}
9297

93-
// CHECK-LABEL: define{{.*}} @test_pack_element_set_1(
94-
// CHECK: [[INDEX:%.*]] = add [[INT]] %2, 1
95-
// CHECK: [[ELT_STORAGE:%.*]] = getelementptr inbounds %swift.opaque*, %swift.opaque** %0, [[INT]] [[INDEX]]
96-
// CHECK: [[BITCAST_STORAGE:%.*]] = bitcast %swift.opaque** [[ELT_STORAGE]] to %TSi**
97-
// CHECK: [[ELT_ADDR:%.*]] = load %TSi*, %TSi** [[BITCAST_STORAGE]], align
98-
// CHECK: [[VALUE_ADDR:%.*]] = getelementptr inbounds %TSi, %TSi* [[ELT_ADDR]], i32 0, i32 0
99-
// CHECK: store [[INT]] %1, [[INT]]* [[VALUE_ADDR]], align
100-
// CHECK: ret void
101-
sil @test_pack_element_set_1 : $<T...> (@pack_owned Pack{Int, repeat each T, Int}, Int) -> () {
102-
bb0(%pack : $*Pack{Int, repeat each T, Int}, %value : $Int):
103-
%index = scalar_pack_index 2 of $Pack{Int, repeat each T, Int}
104-
%elementAddr = pack_element_get %index of %pack : $*Pack{Int, repeat each T, Int} as $*Int
105-
store %value to %elementAddr : $*Int
98+
// CHECK-LABEL: define {{.*}}@test_pack_alloc_2_static
99+
// CHECK: [[STACK:%[^,]+]] = alloca [2 x %swift.opaque*]
100+
// CHECK: call void @llvm.lifetime.start.p0i8
101+
// CHECK: call void @llvm.lifetime.end.p0i8
102+
sil @test_pack_alloc_2_static : $<T...> () -> () {
103+
%addr = alloc_pack $Pack{Int, Int}
104+
dealloc_pack %addr : $*Pack{Int, Int}
106105
%ret = tuple ()
107106
return %ret : $()
108107
}

0 commit comments

Comments
 (0)