diff --git a/lib/AST/ParameterPack.cpp b/lib/AST/ParameterPack.cpp index 46689cfa9498a..5955c2dbbeef0 100644 --- a/lib/AST/ParameterPack.cpp +++ b/lib/AST/ParameterPack.cpp @@ -340,6 +340,11 @@ CanType TypeBase::getReducedShape() { if (auto *expansionType = getAs()) return expansionType->getReducedShape(); + if (auto *silPackType = getAs()) { + auto can = cast(silPackType->getCanonicalType()); + return can->getReducedShape(); + } + SmallVector rootParameterPacks; getTypeParameterPacks(rootParameterPacks); diff --git a/lib/IRGen/GenPack.cpp b/lib/IRGen/GenPack.cpp index bc92f6d23117a..5daa102ad8b4c 100644 --- a/lib/IRGen/GenPack.cpp +++ b/lib/IRGen/GenPack.cpp @@ -865,15 +865,59 @@ void irgen::cleanupTypeMetadataPack(IRGenFunction &IGF, } } -Address irgen::emitStorageAddressOfPackElement(IRGenFunction &IGF, - Address pack, +Address irgen::emitStorageAddressOfPackElement(IRGenFunction &IGF, Address pack, llvm::Value *index, - SILType elementType) { + SILType elementType, + CanSILPackType packType) { // When we have an indirect pack, the elements are pointers, so we can // simply index into that flat array. assert(elementType.isAddress() && "direct packs not currently supported"); - auto elementSize = IGF.IGM.getPointerSize(); + auto elementSize = getPackElementSize(IGF.IGM, packType); auto elementAddress = IGF.Builder.CreateArrayGEP(pack, index, elementSize); return IGF.Builder.CreateElementBitCast(elementAddress, IGF.IGM.getStoragePointerType(elementType)); } + +Size irgen::getPackElementSize(IRGenModule &IGM, CanSILPackType ty) { + assert(ty->isElementAddress() && "not implemented for direct packs"); + return IGM.getPointerSize(); +} + +StackAddress irgen::allocatePack(IRGenFunction &IGF, CanSILPackType packType) { + auto *shape = IGF.emitPackShapeExpression(packType); + + auto elementSize = getPackElementSize(IGF.IGM, packType); + + if (auto *constantInt = dyn_cast(shape)) { + assert(packType->getNumElements() == constantInt->getValue()); + (void)constantInt; + assert(!packType->containsPackExpansionType()); + unsigned elementCount = packType->getNumElements(); + auto allocType = llvm::ArrayType::get( + IGF.IGM.OpaquePtrTy, elementCount); + + auto addr = IGF.createAlloca(allocType, IGF.IGM.getPointerAlignment()); + IGF.Builder.CreateLifetimeStart(addr, + elementSize * elementCount); + return addr; + } + + assert(packType->containsPackExpansionType()); + auto addr = IGF.emitDynamicAlloca(IGF.IGM.OpaquePtrTy, shape, + IGF.IGM.getPointerAlignment(), + /*allowTaskAlloc=*/true); + + return addr; +} + +void irgen::deallocatePack(IRGenFunction &IGF, StackAddress addr, CanSILPackType packType) { + if (packType->containsPackExpansionType()) { + IGF.emitDeallocateDynamicAlloca(addr); + return; + } + + auto elementSize = getPackElementSize(IGF.IGM, packType); + auto elementCount = packType->getNumElements(); + IGF.Builder.CreateLifetimeEnd(addr.getAddress(), + elementSize * elementCount); +} diff --git a/lib/IRGen/GenPack.h b/lib/IRGen/GenPack.h index eac4ae24d9422..701f0d2aefb15 100644 --- a/lib/IRGen/GenPack.h +++ b/lib/IRGen/GenPack.h @@ -17,6 +17,7 @@ #ifndef SWIFT_IRGEN_GENPACK_H #define SWIFT_IRGEN_GENPACK_H +#include "IRGen.h" #include "swift/AST/Types.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" @@ -32,6 +33,7 @@ namespace swift { namespace irgen { class Address; class IRGenFunction; +class IRGenModule; class DynamicMetadataRequest; class MetadataResponse; class StackAddress; @@ -83,9 +85,15 @@ llvm::Value *emitIndexOfStructuralPackComponent(IRGenFunction &IGF, /// /// For indirect packs, note that this is the address of the pack /// array element, not the address stored in the pack array element. -Address emitStorageAddressOfPackElement(IRGenFunction &IGF, - Address pack, llvm::Value *index, - SILType elementType); +Address emitStorageAddressOfPackElement(IRGenFunction &IGF, Address pack, + llvm::Value *index, SILType elementType, + CanSILPackType packType); + +Size getPackElementSize(IRGenModule &, CanSILPackType ty); + +StackAddress allocatePack(IRGenFunction &IGF, CanSILPackType packType); + +void deallocatePack(IRGenFunction &IGF, StackAddress addr, CanSILPackType packType); } // end namespace irgen } // end namespace swift diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index 1508c6c551344..bf8ce15cb15de 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -5502,7 +5502,8 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) { } void IRGenSILFunction::visitAllocPackInst(swift::AllocPackInst *i) { - IGM.unimplemented(i->getLoc().getSourceLoc(), "alloc_pack"); + auto addr = allocatePack(*this, i->getPackType()); + setLoweredStackAddress(i, addr); } static void @@ -5605,7 +5606,9 @@ void IRGenSILFunction::visitDeallocStackRefInst(DeallocStackRefInst *i) { } void IRGenSILFunction::visitDeallocPackInst(swift::DeallocPackInst *i) { - IGM.unimplemented(i->getLoc().getSourceLoc(), "dealloc_pack"); + auto allocatedType = cast(i->getOperand()->getType().getASTType()); + StackAddress stackAddr = getLoweredStackAddress(i->getOperand()); + deallocatePack(*this, stackAddr, allocatedType); } void IRGenSILFunction::visitDeallocRefInst(swift::DeallocRefInst *i) { @@ -6897,8 +6900,8 @@ void IRGenSILFunction::visitPackElementGetInst(PackElementGetInst *i) { auto elementType = i->getElementType(); auto &elementTI = getTypeInfo(elementType); - auto elementStorageAddr = - emitStorageAddressOfPackElement(*this, pack, index, elementType); + auto elementStorageAddr = emitStorageAddressOfPackElement( + *this, pack, index, elementType, i->getPackType()); assert(elementType.isAddress() && i->getPackType()->isElementAddress() && @@ -6913,8 +6916,8 @@ void IRGenSILFunction::visitPackElementSetInst(PackElementSetInst *i) { llvm::Value *index = getLoweredSingletonExplosion(i->getIndex()); auto elementType = i->getElementType(); - auto elementStorageAddress = - emitStorageAddressOfPackElement(*this, pack, index, elementType); + auto elementStorageAddress = emitStorageAddressOfPackElement( + *this, pack, index, elementType, i->getPackType()); assert(elementType.isAddress() && i->getPackType()->isElementAddress() && diff --git a/test/IRGen/variadic_generics.sil b/test/IRGen/variadic_generics.sil index ad7f6952b6cf7..c2436dc53a046 100644 --- a/test/IRGen/variadic_generics.sil +++ b/test/IRGen/variadic_generics.sil @@ -88,8 +88,8 @@ bb0(%pack : $*Pack{Int, repeat each T, Int}): %elementAddr = pack_element_get %index of %pack : $*Pack{Int, repeat each T, Int} as $*Int %value = load %elementAddr : $*Int return %value : $Int -} - + } + // CHECK-LABEL: define{{.*}} @test_pack_element_set_1( // CHECK: [[INDEX:%.*]] = add [[INT]] %2, 1 // 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): %index = scalar_pack_index 2 of $Pack{Int, repeat each T, Int} %elementAddr = pack_element_get %index of %pack : $*Pack{Int, repeat each T, Int} as $*Int store %value to %elementAddr : $*Int + %ret = tuple () + return %ret : $() + } + +// CHECK-LABEL: define {{.*}}@test_pack_alloc_1_dynamic( +// CHECK-SAME: i{{(32|64)}} [[PACK_SIZE:%[^,]+]] +// CHECK: [[SIZE:%[^,]+]] = add i64 [[PACK_SIZE]], [[PACK_SIZE]] +// CHECK: [[SP_SAVE:%[^,]+]] = call i8* @llvm.stacksave() +// CHECK: alloca %swift.opaque*, i{{(32|64)}} [[SIZE]] +// CHECK: call void @llvm.stackrestore(i8* [[SP_SAVE]]) +sil @test_pack_alloc_1_dynamic : $ () -> () { +// Control flow so that stack saving/restoring is emitted +entry: + cond_br undef, left, right +left: + br exit +right: + br exit +exit: + %addr = alloc_pack $Pack{repeat each T, repeat each T} + dealloc_pack %addr : $*Pack{repeat each T, repeat each T} + %ret = tuple () + return %ret : $() +} + +// CHECK-LABEL: define {{.*}}@test_pack_alloc_2_static +// CHECK: [[STACK:%[^,]+]] = alloca [2 x %swift.opaque*] +// CHECK: call void @llvm.lifetime.start.p0i8 +// CHECK: call void @llvm.lifetime.end.p0i8 +sil @test_pack_alloc_2_static : $ () -> () { + %addr = alloc_pack $Pack{Int, Int} + dealloc_pack %addr : $*Pack{Int, Int} %ret = tuple () return %ret : $() }