Skip to content

Commit 7fb678c

Browse files
committed
IRGen: Fix out-of-order task_dealloc with parameter pack metadata
We deallocate an instruction's packs at points where no further control flow path uses the value. In the case of an alloc_stack, this will be right after the dealloc_stack. Thus, if alloc_stack allocates some packs to build type metadata for a tuple type that contains a pack, and then proceeds to allocate a value large enough to hold the tuple, we will free the second allocation first, before we free the pack, as expected. However, after stack allocating the value, alloc_stack does some further work to emit debug info. This could result in emission of additional metadata packs. Split up the debug info emission into two parts; the first we do before we perform the stack allocation, the rest we do after. - Fixes #67702. - Fixes rdar://problem/141363236.
1 parent 245514c commit 7fb678c

File tree

3 files changed

+105
-36
lines changed

3 files changed

+105
-36
lines changed

lib/IRGen/IRGenSIL.cpp

Lines changed: 63 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,12 +1158,10 @@ class IRGenSILFunction :
11581158
}
11591159

11601160
emitTypeMetadataRef(archetype);
1161-
} else if (auto packArchetype = dyn_cast<PackArchetypeType>(t)) {
1162-
emitTypeMetadataRef(packArchetype);
1163-
} else if (auto packtype = dyn_cast<SILPackType>(t)) {
1161+
} else if (auto packType = dyn_cast<SILPackType>(t)) {
11641162
llvm::Value *Shape = emitPackShapeExpression(t);
11651163
emitPackCountDebugVariable(Shape);
1166-
} else if (auto packtype = dyn_cast<PackType>(t)) {
1164+
} else if (auto packType = dyn_cast<PackType>(t)) {
11671165
llvm::Value *Shape = emitPackShapeExpression(t);
11681166
emitPackCountDebugVariable(Shape);
11691167
}
@@ -1212,8 +1210,13 @@ class IRGenSILFunction :
12121210
SILResultInfo ErrorInfo,
12131211
DebugValueInst *DbgValue);
12141212
void emitPoisonDebugValueInst(DebugValueInst *i);
1215-
void emitDebugInfoForAllocStack(AllocStackInst *i, const TypeInfo &type,
1216-
llvm::Value *addr);
1213+
void emitDebugInfoBeforeAllocStack(AllocStackInst *i,
1214+
const TypeInfo &type,
1215+
DebugTypeInfo &DbgTy);
1216+
void emitDebugInfoAfterAllocStack(AllocStackInst *i,
1217+
const TypeInfo &type,
1218+
const DebugTypeInfo &DbgTy,
1219+
llvm::Value *addr);
12171220
void visitAllocStackInst(AllocStackInst *i);
12181221
void visitAllocPackInst(AllocPackInst *i);
12191222
void visitAllocPackMetadataInst(AllocPackMetadataInst *i);
@@ -6401,14 +6404,52 @@ void IRGenSILFunction::visitDestroyNotEscapedClosureInst(
64016404
setLoweredExplosion(i, out);
64026405
}
64036406

6404-
void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
6405-
const TypeInfo &type,
6406-
llvm::Value *addr) {
6407+
void IRGenSILFunction::emitDebugInfoBeforeAllocStack(AllocStackInst *i,
6408+
const TypeInfo &type,
6409+
DebugTypeInfo &DbgTy) {
64076410
auto VarInfo = i->getVarInfo();
6408-
if (!VarInfo)
6411+
if (!VarInfo ||
6412+
!i->getDebugScope() ||
6413+
i->getDebugScope()->getInlinedFunction()->isTransparent())
6414+
return;
6415+
6416+
VarDecl *Decl = i->getDecl();
6417+
6418+
SILType SILTy;
6419+
if (auto MaybeSILTy = VarInfo->Type) {
6420+
// If there is auxiliary type info, use it
6421+
SILTy = *MaybeSILTy;
6422+
} else {
6423+
SILTy = i->getType();
6424+
}
6425+
auto RealType = SILTy.getASTType();
6426+
if (Decl) {
6427+
DbgTy = DebugTypeInfo::getLocalVariable(Decl, RealType, type, IGM);
6428+
} else if (i->getFunction()->isBare() && !SILTy.hasArchetype() &&
6429+
!VarInfo->Name.empty()) {
6430+
DbgTy = DebugTypeInfo::getFromTypeInfo(RealType, getTypeInfo(SILTy), IGM);
6431+
} else
6432+
return;
6433+
6434+
bindArchetypes(DbgTy.getType());
6435+
}
6436+
6437+
/// Do not instantiate type metadata in here, since this may allocate on-stack
6438+
/// packs which will then be cleaned up in the wrong order with respect to the
6439+
/// value stack allocation.
6440+
void IRGenSILFunction::emitDebugInfoAfterAllocStack(AllocStackInst *i,
6441+
const TypeInfo &type,
6442+
const DebugTypeInfo &DbgTy,
6443+
llvm::Value *addr) {
6444+
auto VarInfo = i->getVarInfo();
6445+
if (!VarInfo ||
6446+
!i->getDebugScope() ||
6447+
i->getDebugScope()->getInlinedFunction()->isTransparent())
64096448
return;
64106449

64116450
VarDecl *Decl = i->getDecl();
6451+
auto *DS = i->getDebugScope();
6452+
64126453
// Describe the underlying alloca. This way an llvm.dbg.declare intrinsic
64136454
// is used, which is valid for the entire lifetime of the alloca.
64146455
if (auto *BitCast = dyn_cast<llvm::BitCastInst>(addr)) {
@@ -6425,13 +6466,6 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
64256466
(void)isTaskAlloc;
64266467
}
64276468
}
6428-
6429-
auto DS = i->getDebugScope();
6430-
if (!DS)
6431-
return;
6432-
6433-
if (i->getDebugScope()->getInlinedFunction()->isTransparent())
6434-
return;
64356469

64366470
bool IsAnonymous = false;
64376471
VarInfo->Name = getVarName(i, IsAnonymous);
@@ -6466,25 +6500,15 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
64666500
}
64676501
}
64686502

6469-
SILType SILTy;
6470-
if (auto MaybeSILTy = VarInfo->Type) {
6471-
// If there is auxiliary type info, use it
6472-
SILTy = *MaybeSILTy;
6473-
} else {
6474-
SILTy = i->getType();
6475-
}
6476-
auto RealType = SILTy.getASTType();
6477-
DebugTypeInfo DbgTy;
6478-
if (Decl) {
6479-
DbgTy = DebugTypeInfo::getLocalVariable(Decl, RealType, type, IGM);
6480-
} else if (i->getFunction()->isBare() && !SILTy.hasArchetype() &&
6481-
!VarInfo->Name.empty()) {
6482-
DbgTy = DebugTypeInfo::getFromTypeInfo(RealType, getTypeInfo(SILTy), IGM);
6483-
} else
6484-
return;
6503+
if (DbgTy.getType() && IGM.DebugInfo) {
6504+
SILType SILTy;
6505+
if (auto MaybeSILTy = VarInfo->Type) {
6506+
// If there is auxiliary type info, use it
6507+
SILTy = *MaybeSILTy;
6508+
} else {
6509+
SILTy = i->getType();
6510+
}
64856511

6486-
bindArchetypes(DbgTy.getType());
6487-
if (IGM.DebugInfo) {
64886512
emitDebugVariableDeclaration(
64896513
addr, DbgTy, SILTy, DS, i->getLoc(), *VarInfo, Indirection,
64906514
AddrDbgInstrKind(i->usesMoveableValueDebugInfo()));
@@ -6502,6 +6526,9 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
65026526
dbgname = getVarName(i, IsAnonymous);
65036527
# endif
65046528

6529+
DebugTypeInfo DbgTy;
6530+
emitDebugInfoBeforeAllocStack(i, type, DbgTy);
6531+
65056532
auto stackAddr = type.allocateStack(*this, i->getElementType(), dbgname);
65066533
setLoweredStackAddress(i, stackAddr);
65076534
Address addr = stackAddr.getAddress();
@@ -6516,7 +6543,7 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
65166543
Ty->getStructOrBoundGenericStruct())
65176544
zeroInit(dyn_cast<llvm::AllocaInst>(addr.getAddress()));
65186545
}
6519-
emitDebugInfoForAllocStack(i, type, addr.getAddress());
6546+
emitDebugInfoAfterAllocStack(i, type, DbgTy, addr.getAddress());
65206547
}
65216548

65226549
void IRGenSILFunction::visitAllocPackInst(swift::AllocPackInst *i) {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-run-simple-swift( -target %target-swift-5.9-abi-triple)
2+
// REQUIRES: executable_test
3+
// REQUIRES: concurrency
4+
5+
protocol P {
6+
associatedtype A
7+
var a: A { get }
8+
}
9+
10+
func f<each T: P>(_ t: repeat each T) async -> (repeat (each T).A) {
11+
let x = (repeat (each t).a)
12+
return x
13+
}
14+
15+
struct S: P {
16+
var a: String { "" }
17+
}
18+
19+
_ = await f()
20+
_ = await f(S())
21+
_ = await f(S(), S())
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s
2+
3+
protocol P {
4+
associatedtype A
5+
var a: A { get }
6+
}
7+
8+
func f<each T: P>(_ t: repeat each T) -> (repeat (each T).A) {
9+
let data = (repeat (each t).a)
10+
return data
11+
}
12+
13+
// CHECK-LABEL: define hidden swiftcc void @"$s21pack_metadata_dealloc1fy1AQzxQp_txxQpRvzAA1PRzlF"(ptr noalias sret(%swift.opaque) %0, ptr noalias %1, i64 %2, ptr %"each T", ptr %"each T.P") #0 {
14+
// CHECK: [[SPSAVE:%.*]] = call ptr @llvm.stacksave.p0()
15+
// CHECK: call void @llvm.stackrestore.p0(ptr [[SPSAVE]])
16+
// CHECK: [[SPSAVE1:%.*]] = call ptr @llvm.stacksave.p0()
17+
// CHECK: [[SPSAVE2:%.*]] = call ptr @llvm.stacksave.p0()
18+
// CHECK-NOT: call ptr llvm.stacksave.p0()
19+
// CHECK: call void @llvm.stackrestore.p0(ptr [[SPSAVE2]])
20+
// CHECK: call void @llvm.stackrestore.p0(ptr [[SPSAVE1]])
21+
// CHECK: ret void

0 commit comments

Comments
 (0)