Skip to content

Commit b2e2b02

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 758ae18 commit b2e2b02

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);
@@ -6410,14 +6413,52 @@ void IRGenSILFunction::visitDestroyNotEscapedClosureInst(
64106413
setLoweredExplosion(i, out);
64116414
}
64126415

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

64206459
VarDecl *Decl = i->getDecl();
6460+
auto *DS = i->getDebugScope();
6461+
64216462
// Describe the underlying alloca. This way an llvm.dbg.declare intrinsic
64226463
// is used, which is valid for the entire lifetime of the alloca.
64236464
if (auto *BitCast = dyn_cast<llvm::BitCastInst>(addr)) {
@@ -6434,13 +6475,6 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
64346475
(void)isTaskAlloc;
64356476
}
64366477
}
6437-
6438-
auto DS = i->getDebugScope();
6439-
if (!DS)
6440-
return;
6441-
6442-
if (i->getDebugScope()->getInlinedFunction()->isTransparent())
6443-
return;
64446478

64456479
bool IsAnonymous = false;
64466480
VarInfo->Name = getVarName(i, IsAnonymous);
@@ -6475,25 +6509,15 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
64756509
}
64766510
}
64776511

6478-
SILType SILTy;
6479-
if (auto MaybeSILTy = VarInfo->Type) {
6480-
// If there is auxiliary type info, use it
6481-
SILTy = *MaybeSILTy;
6482-
} else {
6483-
SILTy = i->getType();
6484-
}
6485-
auto RealType = SILTy.getASTType();
6486-
DebugTypeInfo DbgTy;
6487-
if (Decl) {
6488-
DbgTy = DebugTypeInfo::getLocalVariable(Decl, RealType, type, IGM);
6489-
} else if (i->getFunction()->isBare() && !SILTy.hasArchetype() &&
6490-
!VarInfo->Name.empty()) {
6491-
DbgTy = DebugTypeInfo::getFromTypeInfo(RealType, getTypeInfo(SILTy), IGM);
6492-
} else
6493-
return;
6512+
if (DbgTy.getType() && IGM.DebugInfo) {
6513+
SILType SILTy;
6514+
if (auto MaybeSILTy = VarInfo->Type) {
6515+
// If there is auxiliary type info, use it
6516+
SILTy = *MaybeSILTy;
6517+
} else {
6518+
SILTy = i->getType();
6519+
}
64946520

6495-
bindArchetypes(DbgTy.getType());
6496-
if (IGM.DebugInfo) {
64976521
emitDebugVariableDeclaration(
64986522
addr, DbgTy, SILTy, DS, i->getLoc(), *VarInfo, Indirection,
64996523
AddrDbgInstrKind(i->usesMoveableValueDebugInfo()));
@@ -6511,6 +6535,9 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
65116535
dbgname = getVarName(i, IsAnonymous);
65126536
# endif
65136537

6538+
DebugTypeInfo DbgTy;
6539+
emitDebugInfoBeforeAllocStack(i, type, DbgTy);
6540+
65146541
auto stackAddr = type.allocateStack(*this, i->getElementType(), dbgname);
65156542
setLoweredStackAddress(i, stackAddr);
65166543
Address addr = stackAddr.getAddress();
@@ -6525,7 +6552,7 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
65256552
Ty->getStructOrBoundGenericStruct())
65266553
zeroInit(dyn_cast<llvm::AllocaInst>(addr.getAddress()));
65276554
}
6528-
emitDebugInfoForAllocStack(i, type, addr.getAddress());
6555+
emitDebugInfoAfterAllocStack(i, type, DbgTy, addr.getAddress());
65296556
}
65306557

65316558
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 -target %target-swift-5.9-abi-triple | %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 {{.*}} void @"$s21pack_metadata_dealloc1fy1AQzxQp_txxQpRvzAA1PRzlF"
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)