Skip to content

Commit 5b92814

Browse files
committed
Debug Info: Add missing debug info propagation to SILCloner.
While tightening the requirements of the debug info generator in IRGenSIL I noticed that SILCloner didn't correctly transfer variable debug info on alloc_box and alloc_stack instructions. In order to make these mistakes easier to find I added an assertion to SILBuilder and fixed all issues uncovered by that assertion, too. The result is a moderate increase in debug info coverage in optimized code. On stdlib/public/core/OSX/x86_64/Swift.o "variables with location" increases from 60134 to 60299.
1 parent 439b911 commit 5b92814

File tree

14 files changed

+85
-36
lines changed

14 files changed

+85
-36
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,8 @@ class SILBuilder {
403403
Optional<SILDebugVariable> Var = None,
404404
bool hasDynamicLifetime = false) {
405405
Loc.markAsPrologue();
406+
assert((!dyn_cast_or_null<VarDecl>(Loc.getAsASTNode<Decl>()) || Var) &&
407+
"location is a VarDecl, but SILDebugVariable is empty");
406408
return insert(AllocStackInst::create(getSILDebugLocation(Loc), elementType,
407409
getFunction(), C.OpenedArchetypes,
408410
Var, hasDynamicLifetime));
@@ -443,6 +445,8 @@ class SILBuilder {
443445
Optional<SILDebugVariable> Var = None,
444446
bool hasDynamicLifetime = false) {
445447
Loc.markAsPrologue();
448+
assert((!dyn_cast_or_null<VarDecl>(Loc.getAsASTNode<Decl>()) || Var) &&
449+
"location is a VarDecl, but SILDebugVariable is empty");
446450
return insert(AllocBoxInst::create(getSILDebugLocation(Loc), BoxType, *F,
447451
C.OpenedArchetypes, Var,
448452
hasDynamicLifetime));

include/swift/SIL/SILCloner.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -784,9 +784,16 @@ template<typename ImplClass>
784784
void
785785
SILCloner<ImplClass>::visitAllocStackInst(AllocStackInst *Inst) {
786786
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
787-
recordClonedInstruction(
788-
Inst, getBuilder().createAllocStack(getOpLocation(Inst->getLoc()),
789-
getOpType(Inst->getElementType())));
787+
// Drop the debug info from mandatory-inlined instructions. It's the law!
788+
SILLocation Loc = getOpLocation(Inst->getLoc());
789+
Optional<SILDebugVariable> VarInfo = Inst->getVarInfo();
790+
if (Loc.getKind() == SILLocation::MandatoryInlinedKind) {
791+
Loc = MandatoryInlinedLocation::getAutoGeneratedLocation();
792+
VarInfo = None;
793+
}
794+
recordClonedInstruction(Inst,
795+
getBuilder().createAllocStack(
796+
Loc, getOpType(Inst->getElementType()), VarInfo));
790797
}
791798

792799
template<typename ImplClass>
@@ -829,11 +836,19 @@ template<typename ImplClass>
829836
void
830837
SILCloner<ImplClass>::visitAllocBoxInst(AllocBoxInst *Inst) {
831838
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
839+
// Drop the debug info from mandatory-inlined instructions.
840+
SILLocation Loc = getOpLocation(Inst->getLoc());
841+
Optional<SILDebugVariable> VarInfo = Inst->getVarInfo();
842+
if (Loc.getKind() == SILLocation::MandatoryInlinedKind) {
843+
Loc = MandatoryInlinedLocation::getAutoGeneratedLocation();
844+
VarInfo = None;
845+
}
846+
832847
recordClonedInstruction(
833848
Inst,
834849
getBuilder().createAllocBox(
835-
getOpLocation(Inst->getLoc()),
836-
this->getOpType(Inst->getType()).template castTo<SILBoxType>()));
850+
Loc, this->getOpType(Inst->getType()).template castTo<SILBoxType>(),
851+
VarInfo));
837852
}
838853

839854
template<typename ImplClass>

include/swift/SIL/SILInstruction.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,14 +1315,18 @@ class UnaryInstructionWithTypeDependentOperandsBase
13151315
/// arguments that are needed by DebugValueInst, DebugValueAddrInst,
13161316
/// AllocStackInst, and AllocBoxInst.
13171317
struct SILDebugVariable {
1318+
StringRef Name;
1319+
unsigned ArgNo : 16;
1320+
unsigned Constant : 1;
1321+
13181322
SILDebugVariable() : ArgNo(0), Constant(false) {}
13191323
SILDebugVariable(bool Constant, uint16_t ArgNo)
13201324
: ArgNo(ArgNo), Constant(Constant) {}
13211325
SILDebugVariable(StringRef Name, bool Constant, unsigned ArgNo)
13221326
: Name(Name), ArgNo(ArgNo), Constant(Constant) {}
1323-
StringRef Name;
1324-
unsigned ArgNo : 16;
1325-
unsigned Constant : 1;
1327+
bool operator==(const SILDebugVariable &V) {
1328+
return ArgNo == V.ArgNo && Constant == V.Constant && Name == V.Name;
1329+
}
13261330
};
13271331

13281332
/// A DebugVariable where storage for the strings has been

include/swift/SIL/SILLocation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ class MandatoryInlinedLocation : public SILLocation {
662662
: SILLocation(L, MandatoryInlinedKind) {}
663663

664664
static MandatoryInlinedLocation getMandatoryInlinedLocation(SILLocation L);
665+
static MandatoryInlinedLocation getAutoGeneratedLocation();
665666

666667
static MandatoryInlinedLocation getModuleLocation(unsigned Flags) {
667668
auto L = MandatoryInlinedLocation();

lib/IRGen/IRGenSIL.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4055,6 +4055,8 @@ void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
40554055
if (!Decl)
40564056
return;
40574057

4058+
assert(i->getVarInfo() && "alloc_stack without debug info");
4059+
40584060
Type Desugared = Decl->getType()->getDesugaredType();
40594061
if (Desugared->getClassOrBoundGenericClass() ||
40604062
Desugared->getStructOrBoundGenericStruct())
@@ -4214,6 +4216,9 @@ void IRGenSILFunction::visitAllocBoxInst(swift::AllocBoxInst *i) {
42144216

42154217
if (!Decl)
42164218
return;
4219+
4220+
assert(i->getVarInfo() && "alloc_box without debug info");
4221+
42174222
// FIXME: This is a workaround to not produce local variables for
42184223
// capture list arguments like "[weak self]". The better solution
42194224
// would be to require all variables to be described with a

lib/IRGen/LoadableByAddress.cpp

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,18 +1040,23 @@ class LoadableStorageAllocation {
10401040
};
10411041
} // end anonymous namespace
10421042

1043-
static AllocStackInst *allocate(StructLoweringState &pass,
1044-
SILLocation loc, SILType type) {
1043+
static AllocStackInst *allocate(StructLoweringState &pass, SILType type) {
10451044
assert(type.isObject());
10461045

10471046
// Insert an alloc_stack at the beginning of the function.
10481047
SILBuilderWithScope allocBuilder(&*pass.F->begin());
1049-
AllocStackInst *alloc = allocBuilder.createAllocStack(loc, type);
1048+
// Don't put any variable debug info into the alloc_stack, there will be a
1049+
// debug_value_addr insterted later. TODO: It may be more elegant to insert
1050+
// the variable info into the alloc_stack instead of additionally generating a
1051+
// debug_value_addr.
1052+
AllocStackInst *alloc = allocBuilder.createAllocStack(
1053+
RegularLocation::getAutoGeneratedLocation(), type);
10501054

10511055
// Insert dealloc_stack at the end(s) of the function.
10521056
for (TermInst *termInst : pass.returnInsts) {
10531057
SILBuilderWithScope deallocBuilder(termInst);
1054-
deallocBuilder.createDeallocStack(loc, alloc);
1058+
deallocBuilder.createDeallocStack(
1059+
RegularLocation::getAutoGeneratedLocation(), alloc);
10551060
}
10561061

10571062
return alloc;
@@ -1091,8 +1096,7 @@ void LoadableStorageAllocation::replaceLoadWithCopyAddr(
10911096
LoadInst *optimizableLoad) {
10921097
SILValue value = optimizableLoad->getOperand();
10931098

1094-
auto allocInstr = allocate(pass, value.getLoc(),
1095-
value->getType().getObjectType());
1099+
auto allocInstr = allocate(pass, value->getType().getObjectType());
10961100

10971101
SILBuilderWithScope outlinedBuilder(optimizableLoad);
10981102
createOutlinedCopyCall(outlinedBuilder, value, allocInstr, pass);
@@ -1214,8 +1218,7 @@ void LoadableStorageAllocation::replaceLoadWithCopyAddrForModifiable(
12141218
}
12151219
SILValue value = unoptimizableLoad->getOperand();
12161220

1217-
AllocStackInst *alloc = allocate(pass, value.getLoc(),
1218-
value->getType().getObjectType());
1221+
AllocStackInst *alloc = allocate(pass, value->getType().getObjectType());
12191222

12201223
SILBuilderWithScope outlinedBuilder(unoptimizableLoad);
12211224
createOutlinedCopyCall(outlinedBuilder, value, alloc, pass);
@@ -1577,8 +1580,8 @@ void LoadableStorageAllocation::allocateForArg(SILValue value) {
15771580
SILBuilderWithScope allocBuilder(&*pass.F->begin()->begin(),
15781581
FirstNonAllocStack);
15791582

1580-
AllocStackInst *allocInstr =
1581-
allocBuilder.createAllocStack(value.getLoc(), value->getType());
1583+
AllocStackInst *allocInstr = allocBuilder.createAllocStack(
1584+
RegularLocation::getAutoGeneratedLocation(), value->getType());
15821585

15831586
LoadInst *loadCopy = nullptr;
15841587
auto *applyOutlinedCopy =
@@ -1604,7 +1607,12 @@ AllocStackInst *
16041607
LoadableStorageAllocation::allocateForApply(SILInstruction *apply,
16051608
SILType type) {
16061609
SILBuilderWithScope allocBuilder(&*pass.F->begin());
1607-
auto *allocInstr = allocBuilder.createAllocStack(apply->getLoc(), type);
1610+
SILLocation Loc = apply->getLoc();
1611+
if (dyn_cast_or_null<VarDecl>(Loc.getAsASTNode<Decl>()))
1612+
// FIXME: Remove this. This is likely indicative of a bug earlier in the
1613+
// pipeline. An apply instruction should not have a VarDecl as location.
1614+
Loc = RegularLocation::getAutoGeneratedLocation();
1615+
auto *allocInstr = allocBuilder.createAllocStack(Loc, type);
16081616

16091617
pass.largeLoadableArgs.push_back(allocInstr);
16101618
pass.allocToApplyRetMap[allocInstr] = apply;
@@ -1713,7 +1721,7 @@ static void rewriteUsesOfSscalar(StructLoweringState &pass,
17131721
static void allocateAndSetForInstResult(StructLoweringState &pass,
17141722
SILValue instResult,
17151723
SILInstruction *inst) {
1716-
auto alloc = allocate(pass, inst->getLoc(), instResult->getType());
1724+
auto alloc = allocate(pass, instResult->getType());
17171725

17181726
auto II = inst->getIterator();
17191727
++II;
@@ -1726,7 +1734,7 @@ static void allocateAndSetForInstResult(StructLoweringState &pass,
17261734
static void allocateAndSetForArgument(StructLoweringState &pass,
17271735
SILArgument *value,
17281736
SILInstruction *user) {
1729-
AllocStackInst *alloc = allocate(pass, user->getLoc(), value->getType());
1737+
AllocStackInst *alloc = allocate(pass, value->getType());
17301738

17311739
SILLocation loc = user->getLoc();
17321740
loc.markAutoGenerated();
@@ -1871,12 +1879,12 @@ static SILValue createCopyOfEnum(StructLoweringState &pass,
18711879
auto type = value->getType();
18721880
if (type.isObject()) {
18731881
// support for non-address operands / enums
1874-
auto *alloc = allocate(pass, orig->getLoc(), type);
1882+
auto *alloc = allocate(pass, type);
18751883
createStoreInit(pass, orig->getIterator(), orig->getLoc(), value, alloc);
18761884
return alloc;
18771885
}
18781886

1879-
auto alloc = allocate(pass, value.getLoc(), type.getObjectType());
1887+
auto alloc = allocate(pass, type.getObjectType());
18801888

18811889
SILBuilderWithScope copyBuilder(orig);
18821890
createOutlinedCopyCall(copyBuilder, value, alloc, pass);

lib/SIL/SILLocation.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,11 @@ MandatoryInlinedLocation::getMandatoryInlinedLocation(SILLocation L) {
223223
llvm_unreachable("Cannot construct Inlined loc from the given location.");
224224
}
225225

226+
MandatoryInlinedLocation MandatoryInlinedLocation::getAutoGeneratedLocation() {
227+
return getMandatoryInlinedLocation(
228+
RegularLocation::getAutoGeneratedLocation());
229+
}
230+
226231
CleanupLocation CleanupLocation::get(SILLocation L) {
227232
if (Expr *E = L.getAsASTNode<Expr>())
228233
return CleanupLocation(E, L.getSpecialFlags());

lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ void ExistentialSpecializerCloner::cloneArguments(
134134
// SILBuilderContext.
135135
SILBuilder NewFBuilder(ClonedEntryBB, DebugScope,
136136
getBuilder().getBuilderContext());
137-
auto InsertLoc = OrigF->begin()->begin()->getLoc();
137+
auto InsertLoc = RegularLocation::getAutoGeneratedLocation();
138138

139139
auto NewFTy = NewF.getLoweredFunctionType();
140140
SmallVector<SILParameterInfo, 4> params;

lib/SILOptimizer/Transforms/SILMem2Reg.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,9 +299,15 @@ promoteDebugValueAddr(DebugValueAddrInst *DVAI, SILValue Value, SILBuilder &B) {
299299
assert(DVAI->getOperand()->getType().isLoadable(*DVAI->getFunction()) &&
300300
"Unexpected promotion of address-only type!");
301301
assert(Value && "Expected valid value");
302+
// Avoid inserting the same debug_value twice.
303+
for (Operand *Use : Value->getUses())
304+
if (auto *DVI = dyn_cast<DebugValueInst>(Use->getUser()))
305+
if (*DVI->getVarInfo() == *DVAI->getVarInfo())
306+
return;
302307
B.setInsertionPoint(DVAI);
303308
B.setCurrentDebugScope(DVAI->getDebugScope());
304309
B.createDebugValue(DVAI->getLoc(), Value, *DVAI->getVarInfo());
310+
305311
DVAI->eraseFromParent();
306312
}
307313

lib/SILOptimizer/Transforms/SILSROA.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,19 +215,21 @@ SROAMemoryUseAnalyzer::
215215
createAllocas(llvm::SmallVector<AllocStackInst *, 4> &NewAllocations) {
216216
SILBuilderWithScope B(AI);
217217
SILType Type = AI->getType().getObjectType();
218-
218+
// Intentionally dropping the debug info.
219+
// FIXME: VarInfo needs to be extended with fragment info to support this.
220+
SILLocation Loc = RegularLocation::getAutoGeneratedLocation();
219221
if (TT) {
220222
for (unsigned EltNo : indices(TT->getElementTypes())) {
221223
SILType EltTy = Type.getTupleElementType(EltNo);
222-
NewAllocations.push_back(B.createAllocStack(AI->getLoc(), EltTy));
224+
NewAllocations.push_back(B.createAllocStack(Loc, EltTy, {}));
223225
}
224226
} else {
225227
assert(SD && "SD should not be null since either it or TT must be set at "
226228
"this point.");
227229
SILModule &M = AI->getModule();
228230
for (auto *D : SD->getStoredProperties())
229-
NewAllocations.push_back(B.createAllocStack(AI->getLoc(),
230-
Type.getFieldType(D, M)));
231+
NewAllocations.push_back(
232+
B.createAllocStack(Loc, Type.getFieldType(D, M), {}));
231233
}
232234
}
233235

lib/SILOptimizer/Utils/GenericCloner.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ void GenericCloner::populateCloned() {
8181
// We need an alloc_stack as a replacement for the indirect parameter.
8282
assert(mappedType.isAddress());
8383
mappedType = mappedType.getObjectType();
84-
ASI = getBuilder().createAllocStack(Loc, mappedType);
84+
auto AllocStackLoc = RegularLocation::getAutoGeneratedLocation();
85+
ASI = getBuilder().createAllocStack(AllocStackLoc, mappedType);
8586
AllocStacks.push_back(ASI);
8687
};
8788
auto handleConversion = [&]() {

test/DebugInfo/inlined-generics-basic.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,15 @@ public class C<R> {
6767
// IR: call {{.*}}3use
6868
#sourceLocation(file: "f.swift", line: 4)
6969
g((r, s))
70-
// IR: dbg.value
71-
// IR: dbg.value({{.*}}, metadata ![[GI_T:[0-9]+]]
70+
// Note to maintainers: the relative order of the constant dbg.values here
71+
// seem to flip back and forth.
7272
// IR: dbg.value({{.*}}, metadata ![[GI_U:[0-9]+]]
73+
// IR: dbg.value({{.*}}, metadata ![[GI_T:[0-9]+]]
7374
// IR: call {{.*}}3use
7475
#sourceLocation(file: "f.swift", line: 5)
7576
g(Int(0))
76-
// IR: dbg.value
77-
// IR: dbg.value({{.*}}, metadata ![[GB_T:[0-9]+]]
7877
// IR: dbg.value({{.*}}, metadata ![[GB_U:[0-9]+]]
78+
// IR: dbg.value({{.*}}, metadata ![[GB_T:[0-9]+]]
7979
// IR: call {{.*}}3use
8080
#sourceLocation(file: "f.swift", line: 6)
8181
g(false)

test/SILOptimizer/sil_locations.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ bb0(%0 : $Int64):
4949
// CHECK-LABEL: sil @inline_test_add : $@convention(thin) (Int64) -> Int64 {
5050
// CHECK: [[VAL9:%.*]] = apply {{.*}} line:38:9:sil
5151
// CHECK: [[VAL10:%.*]] = apply {{.*}} line:39:9:sil
52-
// CHECK: [[VAL11:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <Int64>, {{.*}} line:40:9:minlined
52+
// CHECK: [[VAL11:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <Int64>, {{.*}}compiler-generated
5353
// CHECK: [[PB11:%.*]] = project_box [[VAL11]] {{.*}} line:40:9:minlined
5454
// CHECK: store [[VAL10]] to [[PB11]] {{.*}} line:40:9:minlined
5555
// CHECK: [[VAL13:%.*]] = function_ref @plus {{.*}} line:40:9:minlined

test/SILOptimizer/specialize_unconditional_checked_cast.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ ArchetypeToConcreteConvertUInt8(t: f)
100100
// CHECK-LABEL: sil shared [noinline] @$s37specialize_unconditional_checked_cast31ArchetypeToConcreteConvertUInt8{{[_0-9a-zA-Z]*}}3Not{{.*}}Tg5 : $@convention(thin) (NotUInt8) -> NotUInt8 {
101101
// CHECK: bb0
102102
// CHECK-NEXT: debug_value %0
103-
// CHECK-NEXT: debug_value %0
104103
// CHECK-NEXT: return %0
105104

106105
// x -> y where y is a class but x is not.
@@ -121,7 +120,6 @@ ArchetypeToConcreteConvertUInt8(t: f)
121120
// CHECK-LABEL: sil shared [noinline] @$s37specialize_unconditional_checked_cast27ArchetypeToConcreteConvertC{{[_0-9a-zA-Z]*}}Tg5 : $@convention(thin) (@guaranteed C) -> @owned C {
122121
// CHECK: bb0([[ARG:%.*]] : $C)
123122
// CHECK-NEXT: debug_value [[ARG]]
124-
// CHECK-NEXT: debug_value [[ARG]]
125123
// CHECK-NEXT: strong_retain [[ARG]]
126124
// CHECK-NEXT: return [[ARG]]
127125

0 commit comments

Comments
 (0)