Skip to content

Commit 2bb6498

Browse files
committed
[SIL][DebugInfo] Bring advanced debug info to alloc_stack
The `alloc_stack` instruction now can carry advanced debug info like source-variable-specific SIL location, type, and SIL DIExpression.
1 parent 700b11d commit 2bb6498

File tree

6 files changed

+127
-85
lines changed

6 files changed

+127
-85
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 70 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,6 +1806,50 @@ class TailAllocatedDebugVariable {
18061806
static_assert(sizeof(TailAllocatedDebugVariable) == 4,
18071807
"SILNode inline bitfield needs updating");
18081808

1809+
/// Used for keeping track of advanced / supplement debug variable info
1810+
/// stored in trailing objects space inside debug instructions (e.g.
1811+
/// debug_value)
1812+
class SILDebugVariableSupplement {
1813+
protected:
1814+
enum SourceLocKind : unsigned { SLK_Loc = 0b01, SLK_Scope = 0b10 };
1815+
1816+
unsigned NumDIExprOperands : 8;
1817+
1818+
unsigned HasAuxDebugVariableType : 1;
1819+
1820+
unsigned AuxVariableSourceLoc : 2;
1821+
1822+
SILDebugVariableSupplement(unsigned NumDIExprOps, bool AuxType, bool AuxLoc,
1823+
bool AuxScope)
1824+
: NumDIExprOperands(NumDIExprOps), HasAuxDebugVariableType(AuxType),
1825+
AuxVariableSourceLoc((AuxLoc ? SLK_Loc : 0) |
1826+
(AuxScope ? SLK_Scope : 0)) {}
1827+
};
1828+
1829+
#define SIL_DEBUG_VAR_SUPPLEMENT_TRAILING_OBJS_IMPL() \
1830+
inline bool hasAuxDebugLocation() const { \
1831+
return AuxVariableSourceLoc & SLK_Loc; \
1832+
} \
1833+
inline bool hasAuxDebugScope() const { \
1834+
return AuxVariableSourceLoc & SLK_Scope; \
1835+
} \
1836+
\
1837+
size_t numTrailingObjects(OverloadToken<SILType>) const { \
1838+
return HasAuxDebugVariableType ? 1 : 0; \
1839+
} \
1840+
\
1841+
size_t numTrailingObjects(OverloadToken<SILLocation>) const { \
1842+
return hasAuxDebugLocation() ? 1 : 0; \
1843+
} \
1844+
\
1845+
size_t numTrailingObjects(OverloadToken<const SILDebugScope *>) const { \
1846+
return hasAuxDebugScope() ? 1 : 0; \
1847+
} \
1848+
\
1849+
size_t numTrailingObjects(OverloadToken<SILDIExprElement>) const { \
1850+
return NumDIExprOperands; \
1851+
}
1852+
18091853
//===----------------------------------------------------------------------===//
18101854
// Allocation Instructions
18111855
//===----------------------------------------------------------------------===//
@@ -1833,7 +1877,10 @@ class DeallocStackInst;
18331877
class AllocStackInst final
18341878
: public InstructionBase<SILInstructionKind::AllocStackInst,
18351879
AllocationInst>,
1836-
private llvm::TrailingObjects<AllocStackInst, Operand, char> {
1880+
private SILDebugVariableSupplement,
1881+
private llvm::TrailingObjects<AllocStackInst, SILType, SILLocation,
1882+
const SILDebugScope *, SILDIExprElement,
1883+
Operand, char> {
18371884
friend TrailingObjects;
18381885
friend SILBuilder;
18391886

@@ -1849,6 +1896,8 @@ class AllocStackInst final
18491896
Optional<SILDebugVariable> Var,
18501897
bool hasDynamicLifetime);
18511898

1899+
SIL_DEBUG_VAR_SUPPLEMENT_TRAILING_OBJS_IMPL()
1900+
18521901
size_t numTrailingObjects(OverloadToken<Operand>) const {
18531902
return SILNode::Bits.AllocStackInst.NumOperands;
18541903
}
@@ -1878,9 +1927,24 @@ class AllocStackInst final
18781927

18791928
/// Return the debug variable information attached to this instruction.
18801929
Optional<SILDebugVariable> getVarInfo() const {
1930+
Optional<SILType> AuxVarType;
1931+
Optional<SILLocation> VarDeclLoc;
1932+
const SILDebugScope *VarDeclScope = nullptr;
1933+
if (HasAuxDebugVariableType)
1934+
AuxVarType = *getTrailingObjects<SILType>();
1935+
1936+
if (hasAuxDebugLocation())
1937+
VarDeclLoc = *getTrailingObjects<SILLocation>();
1938+
if (hasAuxDebugScope())
1939+
VarDeclScope = *getTrailingObjects<const SILDebugScope *>();
1940+
1941+
llvm::ArrayRef<SILDIExprElement> DIExprElements(
1942+
getTrailingObjects<SILDIExprElement>(), NumDIExprOperands);
1943+
18811944
auto RawValue = SILNode::Bits.AllocStackInst.VarInfo;
18821945
auto VI = TailAllocatedDebugVariable(RawValue);
1883-
return VI.get(getDecl(), getTrailingObjects<char>());
1946+
return VI.get(getDecl(), getTrailingObjects<char>(), AuxVarType, VarDeclLoc,
1947+
VarDeclScope, DIExprElements);
18841948
};
18851949
void setArgNo(unsigned N) {
18861950
auto RawValue = SILNode::Bits.AllocStackInst.VarInfo;
@@ -4560,29 +4624,18 @@ class MarkFunctionEscapeInst final
45604624
}
45614625
};
45624626

4563-
/// Simple bitmasks that represent whether a SIL instruction
4564-
/// or debug variable has SILLocation, DebugScope, or both of them
4565-
/// attached.
4566-
struct SILSourceLocKind {
4567-
static constexpr unsigned Loc = 0b01;
4568-
static constexpr unsigned Scope = 0b10;
4569-
};
4570-
45714627
/// Define the start or update to a symbolic variable value (for loadable
45724628
/// types).
45734629
class DebugValueInst final
45744630
: public UnaryInstructionBase<SILInstructionKind::DebugValueInst,
45754631
NonValueInstruction>,
4632+
private SILDebugVariableSupplement,
45764633
private llvm::TrailingObjects<DebugValueInst, SILType, SILLocation,
45774634
const SILDebugScope *, SILDIExprElement,
45784635
char> {
45794636
friend TrailingObjects;
45804637
friend SILBuilder;
45814638

4582-
unsigned NumDIExprOperands;
4583-
bool HasAuxDebugVariableType;
4584-
unsigned AuxVariableSourceLoc : 2;
4585-
45864639
TailAllocatedDebugVariable VarInfo;
45874640

45884641
DebugValueInst(SILDebugLocation DebugLoc, SILValue Operand,
@@ -4591,28 +4644,7 @@ class DebugValueInst final
45914644
SILModule &M, SILDebugVariable Var,
45924645
bool poisonRefs);
45934646

4594-
inline bool hasAuxDebugLocation() const {
4595-
return AuxVariableSourceLoc & SILSourceLocKind::Loc;
4596-
}
4597-
inline bool hasAuxDebugScope() const {
4598-
return AuxVariableSourceLoc & SILSourceLocKind::Scope;
4599-
}
4600-
4601-
size_t numTrailingObjects(OverloadToken<SILType>) const {
4602-
return HasAuxDebugVariableType ? 1 : 0;
4603-
}
4604-
4605-
size_t numTrailingObjects(OverloadToken<SILLocation>) const {
4606-
return hasAuxDebugLocation() ? 1 : 0;
4607-
}
4608-
4609-
size_t numTrailingObjects(OverloadToken<const SILDebugScope *>) const {
4610-
return hasAuxDebugScope() ? 1 : 0;
4611-
}
4612-
4613-
size_t numTrailingObjects(OverloadToken<SILDIExprElement>) const {
4614-
return NumDIExprOperands;
4615-
}
4647+
SIL_DEBUG_VAR_SUPPLEMENT_TRAILING_OBJS_IMPL()
46164648

46174649
size_t numTrailingObjects(OverloadToken<char>) const { return 1; }
46184650

@@ -4622,7 +4654,6 @@ class DebugValueInst final
46224654
VarDecl *getDecl() const;
46234655
/// Return the debug variable information attached to this instruction.
46244656
Optional<SILDebugVariable> getVarInfo() const {
4625-
;
46264657
Optional<SILType> AuxVarType;
46274658
Optional<SILLocation> VarDeclLoc;
46284659
const SILDebugScope *VarDeclScope = nullptr;
@@ -4662,16 +4693,13 @@ class DebugValueInst final
46624693
class DebugValueAddrInst final
46634694
: public UnaryInstructionBase<SILInstructionKind::DebugValueAddrInst,
46644695
NonValueInstruction>,
4696+
private SILDebugVariableSupplement,
46654697
private llvm::TrailingObjects<DebugValueAddrInst, SILType, SILLocation,
46664698
const SILDebugScope *, SILDIExprElement,
46674699
char> {
46684700
friend TrailingObjects;
46694701
friend SILBuilder;
46704702

4671-
unsigned NumDIExprOperands;
4672-
bool HasAuxDebugVariableType;
4673-
unsigned AuxVariableSourceLoc : 2;
4674-
46754703
TailAllocatedDebugVariable VarInfo;
46764704

46774705
DebugValueAddrInst(SILDebugLocation DebugLoc, SILValue Operand,
@@ -4680,28 +4708,7 @@ class DebugValueAddrInst final
46804708
SILValue Operand, SILModule &M,
46814709
SILDebugVariable Var);
46824710

4683-
inline bool hasAuxDebugLocation() const {
4684-
return AuxVariableSourceLoc & SILSourceLocKind::Loc;
4685-
}
4686-
inline bool hasAuxDebugScope() const {
4687-
return AuxVariableSourceLoc & SILSourceLocKind::Scope;
4688-
}
4689-
4690-
size_t numTrailingObjects(OverloadToken<SILType>) const {
4691-
return HasAuxDebugVariableType ? 1 : 0;
4692-
}
4693-
4694-
size_t numTrailingObjects(OverloadToken<SILLocation>) const {
4695-
return hasAuxDebugLocation() ? 1 : 0;
4696-
}
4697-
4698-
size_t numTrailingObjects(OverloadToken<const SILDebugScope *>) const {
4699-
return hasAuxDebugScope() ? 1 : 0;
4700-
}
4701-
4702-
size_t numTrailingObjects(OverloadToken<SILDIExprElement>) const {
4703-
return NumDIExprOperands;
4704-
}
4711+
SIL_DEBUG_VAR_SUPPLEMENT_TRAILING_OBJS_IMPL()
47054712

47064713
public:
47074714
/// Return the underlying variable declaration that this denotes,

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2493,13 +2493,13 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
24932493
Operands.push_back(SizeInBits);
24942494
}
24952495
llvm::DIExpression *DIExpr = DBuilder.createExpression(Operands);
2496-
emitDbgIntrinsic(
2497-
Builder, Piece, Var,
2498-
// DW_OP_LLVM_fragment must be the last part of an DIExpr
2499-
// so we can't append more if IsPiece is true.
2500-
Operands.empty() || IsPiece ? DIExpr : appendDIExpression(DIExpr),
2501-
DInstLine, DInstLoc.column, Scope, DS,
2502-
Indirection == CoroDirectValue || Indirection == CoroIndirectValue);
2496+
emitDbgIntrinsic(Builder, Piece, Var,
2497+
// DW_OP_LLVM_fragment must be the last part of an DIExpr
2498+
// so we can't append more if IsPiece is true.
2499+
IsPiece ? DIExpr : appendDIExpression(DIExpr), DInstLine,
2500+
DInstLoc.column, Scope, DS,
2501+
Indirection == CoroDirectValue ||
2502+
Indirection == CoroIndirectValue);
25032503
}
25042504

25052505
// Emit locationless intrinsic for variables that were optimized away.

lib/IRGen/IRGenSIL.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5160,7 +5160,12 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
51605160
}
51615161
}
51625162

5163-
SILType SILTy = i->getType();
5163+
SILType SILTy;
5164+
if (auto MaybeSILTy = VarInfo->Type)
5165+
// If there is auxiliary type info, use it
5166+
SILTy = *MaybeSILTy;
5167+
else
5168+
SILTy = i->getType();
51645169
auto RealType = SILTy.getASTType();
51655170
DebugTypeInfo DbgTy;
51665171
if (Decl) {

lib/SIL/IR/SILInstructions.cpp

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -162,17 +162,25 @@ StringRef TailAllocatedDebugVariable::getName(const char *buf) const {
162162

163163
AllocStackInst::AllocStackInst(SILDebugLocation Loc, SILType elementType,
164164
ArrayRef<SILValue> TypeDependentOperands,
165-
SILFunction &F,
166-
Optional<SILDebugVariable> Var,
165+
SILFunction &F, Optional<SILDebugVariable> Var,
167166
bool hasDynamicLifetime)
168167
: InstructionBase(Loc, elementType.getAddressType()),
169-
dynamicLifetime(hasDynamicLifetime) {
168+
SILDebugVariableSupplement(Var ? Var->DIExpr.getNumElements() : 0,
169+
Var ? Var->Type.hasValue() : false,
170+
Var ? Var->Loc.hasValue() : false,
171+
Var ? Var->Scope != nullptr : false),
172+
dynamicLifetime(hasDynamicLifetime) {
170173
SILNode::Bits.AllocStackInst.NumOperands =
171174
TypeDependentOperands.size();
172175
assert(SILNode::Bits.AllocStackInst.NumOperands ==
173176
TypeDependentOperands.size() && "Truncation");
174177
SILNode::Bits.AllocStackInst.VarInfo =
175-
TailAllocatedDebugVariable(Var, getTrailingObjects<char>()).getRawValue();
178+
TailAllocatedDebugVariable(Var, getTrailingObjects<char>(),
179+
getTrailingObjects<SILType>(),
180+
getTrailingObjects<SILLocation>(),
181+
getTrailingObjects<const SILDebugScope *>(),
182+
getTrailingObjects<SILDIExprElement>())
183+
.getRawValue();
176184
TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this,
177185
TypeDependentOperands);
178186
}
@@ -297,10 +305,9 @@ SILType AllocBoxInst::getAddressType() const {
297305
DebugValueInst::DebugValueInst(SILDebugLocation DebugLoc, SILValue Operand,
298306
SILDebugVariable Var, bool poisonRefs)
299307
: UnaryInstructionBase(DebugLoc, Operand),
300-
NumDIExprOperands(Var.DIExpr.getNumElements()),
301-
HasAuxDebugVariableType(Var.Type.hasValue()),
302-
AuxVariableSourceLoc((Var.Loc.hasValue() ? SILSourceLocKind::Loc : 0) |
303-
(Var.Scope ? SILSourceLocKind::Scope : 0)),
308+
SILDebugVariableSupplement(Var.DIExpr.getNumElements(),
309+
Var.Type.hasValue(), Var.Loc.hasValue(),
310+
Var.Scope),
304311
VarInfo(Var, getTrailingObjects<char>(), getTrailingObjects<SILType>(),
305312
getTrailingObjects<SILLocation>(),
306313
getTrailingObjects<const SILDebugScope *>(),
@@ -318,10 +325,9 @@ DebugValueInst *DebugValueInst::create(SILDebugLocation DebugLoc,
318325
DebugValueAddrInst::DebugValueAddrInst(SILDebugLocation DebugLoc,
319326
SILValue Operand, SILDebugVariable Var)
320327
: UnaryInstructionBase(DebugLoc, Operand),
321-
NumDIExprOperands(Var.DIExpr.getNumElements()),
322-
HasAuxDebugVariableType(Var.Type.hasValue()),
323-
AuxVariableSourceLoc((Var.Loc.hasValue() ? SILSourceLocKind::Loc : 0) |
324-
(Var.Scope ? SILSourceLocKind::Scope : 0)),
328+
SILDebugVariableSupplement(Var.DIExpr.getNumElements(),
329+
Var.Type.hasValue(), Var.Loc.hasValue(),
330+
Var.Scope),
325331
VarInfo(Var, getTrailingObjects<char>(), getTrailingObjects<SILType>(),
326332
getTrailingObjects<SILLocation>(),
327333
getTrailingObjects<const SILDebugScope *>(),

lib/SIL/IR/SILPrinter.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,7 +1210,8 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
12101210
if (AVI->hasDynamicLifetime())
12111211
*this << "[dynamic_lifetime] ";
12121212
*this << AVI->getElementType();
1213-
printDebugVar(AVI->getVarInfo());
1213+
printDebugVar(AVI->getVarInfo(),
1214+
&AVI->getModule().getASTContext().SourceMgr);
12141215
}
12151216

12161217
void printAllocRefInstBase(AllocRefInstBase *ARI) {
@@ -1245,7 +1246,8 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
12451246
if (ABI->hasDynamicLifetime())
12461247
*this << "[dynamic_lifetime] ";
12471248
*this << ABI->getType();
1248-
printDebugVar(ABI->getVarInfo());
1249+
printDebugVar(ABI->getVarInfo(),
1250+
&ABI->getModule().getASTContext().SourceMgr);
12491251
}
12501252

12511253
void printSubstitutions(SubstitutionMap Subs,

test/DebugInfo/debug_info_expression.sil

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ struct MyStruct {
1010

1111
sil_scope 1 { loc "file.swift":7:6 parent @test_fragment : $@convention(thin) () -> () }
1212

13+
// Testing op_fragment w/ debug_value_addr
1314
sil hidden @test_fragment : $@convention(thin) () -> () {
1415
bb0:
1516
%2 = alloc_stack $MyStruct, var, name "my_struct", loc "file.swift":8:9, scope 1
@@ -28,3 +29,24 @@ bb0:
2829
%r = tuple()
2930
return %r : $()
3031
}
32+
33+
sil_scope 2 { loc "file.swift":14:6 parent @test_alloc_stack : $@convention(thin) () -> () }
34+
35+
// Testing di-expression w/ alloc_stack
36+
sil hidden @test_alloc_stack : $@convention(thin) () -> () {
37+
bb0:
38+
%my_struct = alloc_stack $MyStruct, var, name "my_struct", loc "file.swift":15:9, scope 2
39+
// CHECK: %[[MY_STRUCT:.+]] = alloca %{{.*}}MyStruct
40+
// CHECK: llvm.dbg.declare(metadata {{.*}}* %[[MY_STRUCT]], metadata ![[VAR_DECL_MD:[0-9]+]]
41+
// CHECK-SIL: alloc_stack $Int, var
42+
// CHECK-SIL-SAME: (name "my_struct", loc "file.swift":15:9, scope {{[0-9]+}})
43+
// CHECK-SIL-SAME: type $MyStruct, expr op_fragment:#MyStruct.x
44+
%field_x = alloc_stack $Int, var, (name "my_struct", loc "file.swift":15:9, scope 2), type $MyStruct, expr op_fragment:#MyStruct.x, loc "file.swift":16:17, scope 2
45+
// CHECK: %[[FIELD_X:.+]] = alloca %TSi
46+
// CHECK: llvm.dbg.declare(metadata %TSi* %[[FIELD_X]], metadata ![[VAR_DECL_MD]]
47+
// CHECK-SAME: !DIExpression(DW_OP_LLVM_fragment, 0, 64)
48+
dealloc_stack %field_x : $*Int
49+
dealloc_stack %my_struct: $*MyStruct
50+
%r = tuple()
51+
return %r : $()
52+
}

0 commit comments

Comments
 (0)