diff --git a/include/swift/AST/TypeTransform.h b/include/swift/AST/TypeTransform.h index 8348506c836a8..a45be7aa16d0c 100644 --- a/include/swift/AST/TypeTransform.h +++ b/include/swift/AST/TypeTransform.h @@ -1176,6 +1176,12 @@ case TypeKind::Id: if (transformedPack.getPointer() == element->getPackType().getPointer()) return element; + if (!transformedPack->isParameterPack() && + !transformedPack->is() && + !transformedPack->isTypeVariableOrMember()) { + return transformedPack; + } + return PackElementType::get(transformedPack, element->getLevel()); } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 36db45bf4a9de..3a1fc4f977f02 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -3879,7 +3879,7 @@ PackElementType::PackElementType(Type packType, unsigned level, packType(packType), level(level) { assert(packType->isParameterPack() || packType->is() || - packType->is()); + packType->isTypeVariableOrMember()); assert(level > 0); } diff --git a/lib/AST/ParameterPack.cpp b/lib/AST/ParameterPack.cpp index 0384104c5d35d..cd1f00f9e1e93 100644 --- a/lib/AST/ParameterPack.cpp +++ b/lib/AST/ParameterPack.cpp @@ -307,8 +307,6 @@ static CanPackType getReducedShapeOfPack(const ASTContext &ctx, } // Use () as a placeholder for scalar shape. - assert(!elt->template is() && - "Pack archetype outside of a pack expansion"); elts.push_back(ctx.TheEmptyTupleType); } diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index 5592f971e83ff..0ef5c1616f234 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -1158,12 +1158,10 @@ class IRGenSILFunction : } emitTypeMetadataRef(archetype); - } else if (auto packArchetype = dyn_cast(t)) { - emitTypeMetadataRef(packArchetype); - } else if (auto packtype = dyn_cast(t)) { + } else if (auto packType = dyn_cast(t)) { llvm::Value *Shape = emitPackShapeExpression(t); emitPackCountDebugVariable(Shape); - } else if (auto packtype = dyn_cast(t)) { + } else if (auto packType = dyn_cast(t)) { llvm::Value *Shape = emitPackShapeExpression(t); emitPackCountDebugVariable(Shape); } @@ -1212,8 +1210,13 @@ class IRGenSILFunction : SILResultInfo ErrorInfo, DebugValueInst *DbgValue); void emitPoisonDebugValueInst(DebugValueInst *i); - void emitDebugInfoForAllocStack(AllocStackInst *i, const TypeInfo &type, - llvm::Value *addr); + void emitDebugInfoBeforeAllocStack(AllocStackInst *i, + const TypeInfo &type, + DebugTypeInfo &DbgTy); + void emitDebugInfoAfterAllocStack(AllocStackInst *i, + const TypeInfo &type, + const DebugTypeInfo &DbgTy, + llvm::Value *addr); void visitAllocStackInst(AllocStackInst *i); void visitAllocPackInst(AllocPackInst *i); void visitAllocPackMetadataInst(AllocPackMetadataInst *i); @@ -6410,14 +6413,52 @@ void IRGenSILFunction::visitDestroyNotEscapedClosureInst( setLoweredExplosion(i, out); } -void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i, - const TypeInfo &type, - llvm::Value *addr) { +void IRGenSILFunction::emitDebugInfoBeforeAllocStack(AllocStackInst *i, + const TypeInfo &type, + DebugTypeInfo &DbgTy) { auto VarInfo = i->getVarInfo(); - if (!VarInfo) + if (!VarInfo || + !i->getDebugScope() || + i->getDebugScope()->getInlinedFunction()->isTransparent()) + return; + + VarDecl *Decl = i->getDecl(); + + SILType SILTy; + if (auto MaybeSILTy = VarInfo->Type) { + // If there is auxiliary type info, use it + SILTy = *MaybeSILTy; + } else { + SILTy = i->getType(); + } + auto RealType = SILTy.getASTType(); + if (Decl) { + DbgTy = DebugTypeInfo::getLocalVariable(Decl, RealType, type, IGM); + } else if (i->getFunction()->isBare() && !SILTy.hasArchetype() && + !VarInfo->Name.empty()) { + DbgTy = DebugTypeInfo::getFromTypeInfo(RealType, getTypeInfo(SILTy), IGM); + } else + return; + + bindArchetypes(DbgTy.getType()); +} + +/// Do not instantiate type metadata in here, since this may allocate on-stack +/// packs which will then be cleaned up in the wrong order with respect to the +/// value stack allocation. +void IRGenSILFunction::emitDebugInfoAfterAllocStack(AllocStackInst *i, + const TypeInfo &type, + const DebugTypeInfo &DbgTy, + llvm::Value *addr) { + auto VarInfo = i->getVarInfo(); + if (!VarInfo || + !i->getDebugScope() || + i->getDebugScope()->getInlinedFunction()->isTransparent()) return; VarDecl *Decl = i->getDecl(); + auto *DS = i->getDebugScope(); + // Describe the underlying alloca. This way an llvm.dbg.declare intrinsic // is used, which is valid for the entire lifetime of the alloca. if (auto *BitCast = dyn_cast(addr)) { @@ -6434,13 +6475,6 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i, (void)isTaskAlloc; } } - - auto DS = i->getDebugScope(); - if (!DS) - return; - - if (i->getDebugScope()->getInlinedFunction()->isTransparent()) - return; bool IsAnonymous = false; VarInfo->Name = getVarName(i, IsAnonymous); @@ -6475,25 +6509,15 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i, } } - SILType SILTy; - if (auto MaybeSILTy = VarInfo->Type) { - // If there is auxiliary type info, use it - SILTy = *MaybeSILTy; - } else { - SILTy = i->getType(); - } - auto RealType = SILTy.getASTType(); - DebugTypeInfo DbgTy; - if (Decl) { - DbgTy = DebugTypeInfo::getLocalVariable(Decl, RealType, type, IGM); - } else if (i->getFunction()->isBare() && !SILTy.hasArchetype() && - !VarInfo->Name.empty()) { - DbgTy = DebugTypeInfo::getFromTypeInfo(RealType, getTypeInfo(SILTy), IGM); - } else - return; + if (DbgTy.getType() && IGM.DebugInfo) { + SILType SILTy; + if (auto MaybeSILTy = VarInfo->Type) { + // If there is auxiliary type info, use it + SILTy = *MaybeSILTy; + } else { + SILTy = i->getType(); + } - bindArchetypes(DbgTy.getType()); - if (IGM.DebugInfo) { emitDebugVariableDeclaration( addr, DbgTy, SILTy, DS, i->getLoc(), *VarInfo, Indirection, AddrDbgInstrKind(i->usesMoveableValueDebugInfo())); @@ -6511,6 +6535,9 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) { dbgname = getVarName(i, IsAnonymous); # endif + DebugTypeInfo DbgTy; + emitDebugInfoBeforeAllocStack(i, type, DbgTy); + auto stackAddr = type.allocateStack(*this, i->getElementType(), dbgname); setLoweredStackAddress(i, stackAddr); Address addr = stackAddr.getAddress(); @@ -6525,7 +6552,7 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) { Ty->getStructOrBoundGenericStruct()) zeroInit(dyn_cast(addr.getAddress())); } - emitDebugInfoForAllocStack(i, type, addr.getAddress()); + emitDebugInfoAfterAllocStack(i, type, DbgTy, addr.getAddress()); } void IRGenSILFunction::visitAllocPackInst(swift::AllocPackInst *i) { diff --git a/test/Concurrency/Runtime/async_parameter_pack.swift b/test/Concurrency/Runtime/async_parameter_pack.swift new file mode 100644 index 0000000000000..bc6a82776178a --- /dev/null +++ b/test/Concurrency/Runtime/async_parameter_pack.swift @@ -0,0 +1,21 @@ +// RUN: %target-run-simple-swift( -target %target-swift-5.9-abi-triple) +// REQUIRES: executable_test +// REQUIRES: concurrency + +protocol P { + associatedtype A + var a: A { get } +} + +func f(_ t: repeat each T) async -> (repeat (each T).A) { + let x = (repeat (each t).a) + return x +} + +struct S: P { + var a: String { "" } +} + +_ = await f() +_ = await f(S()) +_ = await f(S(), S()) diff --git a/test/IRGen/pack_metadata_dealloc.swift b/test/IRGen/pack_metadata_dealloc.swift new file mode 100644 index 0000000000000..1bdb24a4d3369 --- /dev/null +++ b/test/IRGen/pack_metadata_dealloc.swift @@ -0,0 +1,30 @@ +// RUN: %target-swift-frontend -emit-ir %s -target %target-swift-5.9-abi-triple | %FileCheck %s + +protocol P { + associatedtype A + var a: A { get } +} + +func f(_ t: repeat each T) -> (repeat (each T).A) { + let data = (repeat (each t).a) + return data +} + +// CHECK-LABEL: define {{.*}} void @"$s21pack_metadata_dealloc1fy1AQzxQp_txxQpRvzAA1PRzlF" +// CHECK: [[SPSAVE:%.*]] = call ptr @llvm.stacksave.p0() +// CHECK: call void @llvm.stackrestore.p0(ptr [[SPSAVE]]) +// CHECK: [[SPSAVE1:%.*]] = call ptr @llvm.stacksave.p0() +// CHECK: [[SPSAVE2:%.*]] = call ptr @llvm.stacksave.p0() +// CHECK-NOT: call ptr llvm.stacksave.p0() +// CHECK: call void @llvm.stackrestore.p0(ptr [[SPSAVE2]]) +// CHECK: call void @llvm.stackrestore.p0(ptr [[SPSAVE1]]) +// CHECK: ret void + +struct G { + init(_: repeat each T) {} +} + +func f2(t: repeat each T, u: repeat each U) async -> (repeat G<(each T).A, repeat each U>) { + let x = (repeat G((each t).a, repeat each u)) + return x +} \ No newline at end of file