Skip to content

Commit 75f7134

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. In the cases I saw, these additional packs were duplicates, that were only emitted because we do not canonicalize a bare PackArchetypeType versus one wrapped in a singleton pack. Add a narrow workaround to debug info to avoid this problem. More generally, we should fix the canonicalization here, and also come up with a more general bookkeeping mechanism for stack allocations if it turns out that alloc_stack cannot be refactored to always emit packs first.
1 parent bc45bc3 commit 75f7134

File tree

2 files changed

+89
-35
lines changed

2 files changed

+89
-35
lines changed

lib/IRGen/IRGenSIL.cpp

Lines changed: 68 additions & 35 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,58 @@ 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();
64176420
if (!VarInfo)
64186421
return;
64196422

6423+
auto DS = i->getDebugScope();
6424+
if (!DS)
6425+
return;
6426+
6427+
if (i->getDebugScope()->getInlinedFunction()->isTransparent())
6428+
return;
6429+
6430+
VarDecl *Decl = i->getDecl();
6431+
6432+
SILType SILTy;
6433+
if (auto MaybeSILTy = VarInfo->Type) {
6434+
// If there is auxiliary type info, use it
6435+
SILTy = *MaybeSILTy;
6436+
} else {
6437+
SILTy = i->getType();
6438+
}
6439+
auto RealType = SILTy.getASTType();
6440+
if (Decl) {
6441+
DbgTy = DebugTypeInfo::getLocalVariable(Decl, RealType, type, IGM);
6442+
} else if (i->getFunction()->isBare() && !SILTy.hasArchetype() &&
6443+
!VarInfo->Name.empty()) {
6444+
DbgTy = DebugTypeInfo::getFromTypeInfo(RealType, getTypeInfo(SILTy), IGM);
6445+
} else
6446+
return;
6447+
6448+
bindArchetypes(DbgTy.getType());
6449+
}
6450+
6451+
void IRGenSILFunction::emitDebugInfoAfterAllocStack(AllocStackInst *i,
6452+
const TypeInfo &type,
6453+
const DebugTypeInfo &DbgTy,
6454+
llvm::Value *addr) {
6455+
auto VarInfo = i->getVarInfo();
6456+
if (!VarInfo)
6457+
return;
6458+
6459+
auto DS = i->getDebugScope();
6460+
if (!DS)
6461+
return;
6462+
6463+
if (i->getDebugScope()->getInlinedFunction()->isTransparent())
6464+
return;
6465+
64206466
VarDecl *Decl = i->getDecl();
6467+
64216468
// Describe the underlying alloca. This way an llvm.dbg.declare intrinsic
64226469
// is used, which is valid for the entire lifetime of the alloca.
64236470
if (auto *BitCast = dyn_cast<llvm::BitCastInst>(addr)) {
@@ -6434,13 +6481,6 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
64346481
(void)isTaskAlloc;
64356482
}
64366483
}
6437-
6438-
auto DS = i->getDebugScope();
6439-
if (!DS)
6440-
return;
6441-
6442-
if (i->getDebugScope()->getInlinedFunction()->isTransparent())
6443-
return;
64446484

64456485
bool IsAnonymous = false;
64466486
VarInfo->Name = getVarName(i, IsAnonymous);
@@ -6475,25 +6515,15 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
64756515
}
64766516
}
64776517

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;
6518+
if (DbgTy.getType() && IGM.DebugInfo) {
6519+
SILType SILTy;
6520+
if (auto MaybeSILTy = VarInfo->Type) {
6521+
// If there is auxiliary type info, use it
6522+
SILTy = *MaybeSILTy;
6523+
} else {
6524+
SILTy = i->getType();
6525+
}
64946526

6495-
bindArchetypes(DbgTy.getType());
6496-
if (IGM.DebugInfo) {
64976527
emitDebugVariableDeclaration(
64986528
addr, DbgTy, SILTy, DS, i->getLoc(), *VarInfo, Indirection,
64996529
AddrDbgInstrKind(i->usesMoveableValueDebugInfo()));
@@ -6511,6 +6541,9 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
65116541
dbgname = getVarName(i, IsAnonymous);
65126542
# endif
65136543

6544+
DebugTypeInfo DbgTy;
6545+
emitDebugInfoBeforeAllocStack(i, type, DbgTy);
6546+
65146547
auto stackAddr = type.allocateStack(*this, i->getElementType(), dbgname);
65156548
setLoweredStackAddress(i, stackAddr);
65166549
Address addr = stackAddr.getAddress();
@@ -6525,7 +6558,7 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
65256558
Ty->getStructOrBoundGenericStruct())
65266559
zeroInit(dyn_cast<llvm::AllocaInst>(addr.getAddress()));
65276560
}
6528-
emitDebugInfoForAllocStack(i, type, addr.getAddress());
6561+
emitDebugInfoAfterAllocStack(i, type, DbgTy, addr.getAddress());
65296562
}
65306563

65316564
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-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: [[SPSAVE1:%.*]] = call ptr @llvm.stacksave.p0()
15+
// CHECK: [[SPSAVE2:%.*]] = call ptr @llvm.stacksave.p0()
16+
// CHECK: [[SPSAVE3:%.*]] = call ptr @llvm.stacksave.p0()
17+
// CHECK-NOT: call ptr llvm.stacksave.p0()
18+
// CHECK: call void @llvm.stackrestore.p0(ptr [[SPSAVE3]])
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)