Skip to content

Commit e63632f

Browse files
committed
[DebugInfo][SIL] Introduce the 'implicit' attribute for debug variable
Debug variables that are marked 'implicit' on its `debug_value` instruction mean that they were generated by compiler. Optimizers are free to remove them (if it becomes a dead code, for instance) even in -Onone. Since they are barely used by users and keeping them might lead to incorrect IRGen results.
1 parent 2bb6498 commit e63632f

File tree

7 files changed

+61
-19
lines changed

7 files changed

+61
-19
lines changed

docs/SIL.rst

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3505,6 +3505,7 @@ The operand must have loadable type.
35053505
debug-var-attr ::= 'let'
35063506
debug-var-attr ::= 'name' string-literal
35073507
debug-var-attr ::= 'argno' integer-literal
3508+
debug-var-attr ::= 'implicit'
35083509

35093510
::
35103511

@@ -3520,12 +3521,13 @@ The operand must have loadable type.
35203521
There are a number of attributes that provide details about the source
35213522
variable that is being described, including the name of the
35223523
variable. For function and closure arguments ``argno`` is the number
3523-
of the function argument starting with 1. The advanced debug variable
3524-
attributes represent source locations and type of the source variable
3525-
when it was originally declared. It is useful when we're indirectly
3526-
associating the SSA value with the source variable (via di-expression,
3527-
for example) in which case SSA value's type is different from that of
3528-
source variable.
3524+
of the function argument starting with 1. A compiler-generated source
3525+
variable will be marked ``implicit`` and optimizers are free to remove
3526+
it even in -Onone. The advanced debug variable attributes represent source
3527+
locations and type of the source variable when it was originally declared.
3528+
It is useful when we're indirectly associating the SSA value with the
3529+
source variable (via di-expression, for example) in which case SSA value's
3530+
type is different from that of source variable.
35293531

35303532
If the '[poison]' flag is set, then all references within this debug
35313533
value will be overwritten with a sentinel at this point in the

include/swift/SIL/SILInstruction.h

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1726,27 +1726,31 @@ struct SILDebugVariable {
17261726
StringRef Name;
17271727
unsigned ArgNo : 16;
17281728
unsigned Constant : 1;
1729+
unsigned Implicit : 1;
17291730
Optional<SILType> Type;
17301731
Optional<SILLocation> Loc;
17311732
const SILDebugScope *Scope;
17321733
SILDebugInfoExpression DIExpr;
17331734

1734-
SILDebugVariable() : ArgNo(0), Constant(false), Scope(nullptr) {}
1735+
SILDebugVariable()
1736+
: ArgNo(0), Constant(false), Implicit(false), Scope(nullptr) {}
17351737
SILDebugVariable(bool Constant, uint16_t ArgNo)
1736-
: ArgNo(ArgNo), Constant(Constant), Scope(nullptr) {}
1738+
: ArgNo(ArgNo), Constant(Constant), Implicit(false), Scope(nullptr) {}
17371739
SILDebugVariable(StringRef Name, bool Constant, unsigned ArgNo,
1738-
Optional<SILType> AuxType = {},
1740+
bool IsImplicit = false, Optional<SILType> AuxType = {},
17391741
Optional<SILLocation> DeclLoc = {},
17401742
const SILDebugScope *DeclScope = nullptr,
17411743
llvm::ArrayRef<SILDIExprElement> ExprElements = {})
1742-
: Name(Name), ArgNo(ArgNo), Constant(Constant), Type(AuxType),
1743-
Loc(DeclLoc), Scope(DeclScope), DIExpr(ExprElements) {}
1744+
: Name(Name), ArgNo(ArgNo), Constant(Constant), Implicit(IsImplicit),
1745+
Type(AuxType), Loc(DeclLoc), Scope(DeclScope), DIExpr(ExprElements) {}
1746+
17441747
// We're not comparing DIExpr here because strictly speaking,
17451748
// DIExpr is not part of the debug variable. We simply piggyback
17461749
// it in this class so that's it's easier to carry DIExpr around.
17471750
bool operator==(const SILDebugVariable &V) {
17481751
return ArgNo == V.ArgNo && Constant == V.Constant && Name == V.Name &&
1749-
Type == V.Type && Loc == V.Loc && Scope == V.Scope;
1752+
Implicit == V.Implicit && Type == V.Type && Loc == V.Loc &&
1753+
Scope == V.Scope;
17501754
}
17511755
};
17521756

@@ -1761,10 +1765,12 @@ class TailAllocatedDebugVariable {
17611765
int_type HasValue : 1;
17621766
/// True if this is a let-binding.
17631767
int_type Constant : 1;
1768+
/// True if this variable is created by compiler
1769+
int_type Implicit : 1;
17641770
/// When this is nonzero there is a tail-allocated string storing
17651771
/// variable name present. This typically only happens for
17661772
/// instructions that were created from parsing SIL assembler.
1767-
int_type NameLength : 14;
1773+
int_type NameLength : 13;
17681774
/// The source function argument position from left to right
17691775
/// starting with 1 or 0 if this is a local variable.
17701776
int_type ArgNo : 16;
@@ -1786,6 +1792,9 @@ class TailAllocatedDebugVariable {
17861792
StringRef getName(const char *buf) const;
17871793
bool isLet() const { return Bits.Data.Constant; }
17881794

1795+
bool isImplicit() const { return Bits.Data.Implicit; }
1796+
void setImplicit(bool V = true) { Bits.Data.Implicit = V; }
1797+
17891798
Optional<SILDebugVariable>
17901799
get(VarDecl *VD, const char *buf, Optional<SILType> AuxVarType = {},
17911800
Optional<SILLocation> DeclLoc = {},
@@ -1796,11 +1805,11 @@ class TailAllocatedDebugVariable {
17961805

17971806
if (VD)
17981807
return SILDebugVariable(VD->getName().empty() ? "" : VD->getName().str(),
1799-
VD->isLet(), getArgNo(), AuxVarType, DeclLoc,
1800-
DeclScope, DIExprElements);
1801-
else
1802-
return SILDebugVariable(getName(buf), isLet(), getArgNo(), AuxVarType,
1808+
VD->isLet(), getArgNo(), isImplicit(), AuxVarType,
18031809
DeclLoc, DeclScope, DIExprElements);
1810+
else
1811+
return SILDebugVariable(getName(buf), isLet(), getArgNo(), isImplicit(),
1812+
AuxVarType, DeclLoc, DeclScope, DIExprElements);
18041813
}
18051814
};
18061815
static_assert(sizeof(TailAllocatedDebugVariable) == 4,

lib/SIL/IR/SILInstructions.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ TailAllocatedDebugVariable::TailAllocatedDebugVariable(
138138
Bits.Data.HasValue = true;
139139
Bits.Data.Constant = Var->Constant;
140140
Bits.Data.ArgNo = Var->ArgNo;
141+
Bits.Data.Implicit = Var->Implicit;
141142
Bits.Data.NameLength = Var->Name.size();
142143
assert(Bits.Data.ArgNo == Var->ArgNo && "Truncation");
143144
assert(Bits.Data.NameLength == Var->Name.size() && "Truncation");
@@ -181,6 +182,11 @@ AllocStackInst::AllocStackInst(SILDebugLocation Loc, SILType elementType,
181182
getTrailingObjects<const SILDebugScope *>(),
182183
getTrailingObjects<SILDIExprElement>())
183184
.getRawValue();
185+
if (auto *VD = Loc.getLocation().getAsASTNode<VarDecl>()) {
186+
TailAllocatedDebugVariable DbgVar(SILNode::Bits.AllocStackInst.VarInfo);
187+
DbgVar.setImplicit(VD->isImplicit() || DbgVar.isImplicit());
188+
SILNode::Bits.AllocStackInst.VarInfo = DbgVar.getRawValue();
189+
}
184190
TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this,
185191
TypeDependentOperands);
186192
}
@@ -312,6 +318,8 @@ DebugValueInst::DebugValueInst(SILDebugLocation DebugLoc, SILValue Operand,
312318
getTrailingObjects<SILLocation>(),
313319
getTrailingObjects<const SILDebugScope *>(),
314320
getTrailingObjects<SILDIExprElement>()) {
321+
if (auto *VD = DebugLoc.getLocation().getAsASTNode<VarDecl>())
322+
VarInfo.setImplicit(VD->isImplicit() || VarInfo.isImplicit());
315323
setPoisonRefs(poisonRefs);
316324
}
317325

@@ -331,7 +339,10 @@ DebugValueAddrInst::DebugValueAddrInst(SILDebugLocation DebugLoc,
331339
VarInfo(Var, getTrailingObjects<char>(), getTrailingObjects<SILType>(),
332340
getTrailingObjects<SILLocation>(),
333341
getTrailingObjects<const SILDebugScope *>(),
334-
getTrailingObjects<SILDIExprElement>()) {}
342+
getTrailingObjects<SILDIExprElement>()) {
343+
if (auto *VD = DebugLoc.getLocation().getAsASTNode<VarDecl>())
344+
VarInfo.setImplicit(VD->isImplicit() || VarInfo.isImplicit());
345+
}
335346

336347
DebugValueAddrInst *DebugValueAddrInst::create(SILDebugLocation DebugLoc,
337348
SILValue Operand, SILModule &M,

lib/SIL/IR/SILPrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,8 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
11981198

11991199
if (Var->ArgNo)
12001200
*this << ", argno " << Var->ArgNo;
1201+
if (Var->Implicit)
1202+
*this << ", implicit";
12011203
if (Var->Type) {
12021204
*this << ", type ";
12031205
Var->Type->print(PrintState.OS, PrintState.ASTOptions);

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1752,6 +1752,8 @@ bool SILParser::parseSILDebugVar(SILDebugVariable &Var) {
17521752
Var.Constant = false;
17531753
} else if (Key == "loc") {
17541754
Var.Constant = false;
1755+
} else if (Key == "implicit") {
1756+
Var.Implicit = true;
17551757
} else {
17561758
P.diagnose(P.Tok, diag::sil_dbg_unknown_key, Key);
17571759
return true;

lib/SILOptimizer/Utils/InstOptUtils.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,11 @@ bool swift::hasOnlyEndOfScopeOrDestroyUses(SILInstruction *inst) {
222222
// Include debug uses only in Onone mode.
223223
if (isDebugUser && inst->getFunction()->getEffectiveOptimizationMode() <=
224224
OptimizationMode::NoOptimization)
225-
return false;
225+
if (auto DbgVarInst = DebugVarCarryingInst(user)) {
226+
auto VarInfo = DbgVarInst.getVarInfo();
227+
if (VarInfo && !VarInfo->Implicit)
228+
return false;
229+
}
226230
}
227231
}
228232
return true;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %target-swift-frontend -emit-sil -g %s -o %t.sil
2+
// RUN: %FileCheck %s --input-file=%t.sil
3+
// Test the SILParser / SILPrinter
4+
// RUN: %target-swift-frontend -module-name ImplicitVar -emit-sil -g %t.sil | %FileCheck %s
5+
6+
struct MyStruct {
7+
// Check if the 'implicit' directive for `self` is properly generated (and parsed)
8+
// CHECK: sil {{.*}} @{{.*}}MyStructV5hello
9+
// CHECK: debug_value %0 : $MyStruct
10+
// CHECK-SAME: let, name "self", argno 1, implicit, loc
11+
func hello() {}
12+
}

0 commit comments

Comments
 (0)