Skip to content

Commit 33ec01a

Browse files
committed
[SIL][DebugInfo] PATCH 1/3: Add support for expr op_deref
This new SIL di-expression represents the dereference on the SSA value. Similar to DW_OP_deref in DWARF. It is also going to replace the existing `debug_value_addr`. Namely, replacing the following instruction: ``` debug_value_addr %a : $*T, name "my_var" ``` with this one: ``` debug_value %a : $*T, name "my_var", expr op_deref ```
1 parent d844d0b commit 33ec01a

File tree

5 files changed

+78
-32
lines changed

5 files changed

+78
-32
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4706,6 +4706,12 @@ class DebugValueInst final
47064706
*getTrailingObjects<const SILDebugScope *>() = NewDS;
47074707
}
47084708

4709+
/// Whether the SSA value associated with the current debug_value
4710+
/// instruction has an address type.
4711+
bool hasAddrVal() const {
4712+
return getOperand()->getType().isAddress();
4713+
}
4714+
47094715
/// True if all references within this debug value will be overwritten with a
47104716
/// poison sentinel at this point in the program. This is used in debug builds
47114717
/// when shortening non-trivial value lifetimes to ensure the debugger cannot

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2410,6 +2410,9 @@ bool IRGenDebugInfoImpl::buildDebugInfoExpression(
24102410
if (!handleFragmentDIExpr(ExprOperand, Operands))
24112411
return false;
24122412
break;
2413+
case SILDIExprOperator::Dereference:
2414+
Operands.push_back(llvm::dwarf::DW_OP_deref);
2415+
break;
24132416
default:
24142417
llvm_unreachable("Unrecognized operator");
24152418
}

lib/IRGen/IRGenSIL.cpp

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,7 +1637,7 @@ void LoweredValue::getExplosion(IRGenFunction &IGF, SILType type,
16371637
case Kind::DynamicallyEnforcedAddress:
16381638
case Kind::CoroutineState:
16391639
llvm_unreachable("not a value");
1640-
1640+
16411641
case Kind::ExplosionVector:
16421642
ex.add(Storage.get<ExplosionVector>(kind));
16431643
return;
@@ -4713,7 +4713,11 @@ static bool InCoroContext(SILFunction &f, SILInstruction &i) {
47134713
}
47144714

47154715
void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
4716+
auto SILVal = i->getOperand();
4717+
bool IsAddrVal = SILVal->getType().isAddress();
47164718
if (i->poisonRefs()) {
4719+
assert(!IsAddrVal &&
4720+
"SIL values with address type should not have poison");
47174721
emitPoisonDebugValueInst(i);
47184722
return;
47194723
}
@@ -4722,16 +4726,17 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
47224726

47234727
auto VarInfo = i->getVarInfo();
47244728
assert(VarInfo && "debug_value without debug info");
4725-
auto SILVal = i->getOperand();
47264729
if (isa<SILUndef>(SILVal)) {
47274730
// We cannot track the location of inlined error arguments because it has no
47284731
// representation in SIL.
4729-
if (!i->getDebugScope()->InlinedCallSite && VarInfo->Name == "$error") {
4732+
if (!IsAddrVal &&
4733+
!i->getDebugScope()->InlinedCallSite && VarInfo->Name == "$error") {
47304734
auto funcTy = CurSILFn->getLoweredFunctionType();
47314735
emitErrorResultVar(funcTy, funcTy->getErrorResult(), i);
47324736
}
47334737
return;
47344738
}
4739+
bool IsInCoro = InCoroContext(*CurSILFn, *i);
47354740

47364741
bool IsAnonymous = false;
47374742
VarInfo->Name = getVarName(i, IsAnonymous);
@@ -4742,27 +4747,50 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
47424747
SILTy = *MaybeSILTy;
47434748
else
47444749
SILTy = SILVal->getType();
4750+
47454751
auto RealTy = SILTy.getASTType();
4752+
if (IsAddrVal && IsInCoro)
4753+
if (auto *PBI = dyn_cast<ProjectBoxInst>(i->getOperand())) {
4754+
// Usually debug info only ever describes the *result* of a projectBox
4755+
// call. To allow the debugger to display a boxed parameter of an async
4756+
// continuation object, however, the debug info can only describe the box
4757+
// itself and thus also needs to emit a box type for it so the debugger
4758+
// knows to call into Remote Mirrors to unbox the value.
4759+
RealTy = PBI->getOperand()->getType().getASTType();
4760+
assert(isa<SILBoxType>(RealTy));
4761+
}
4762+
4763+
// Figure out the debug variable type
47464764
if (VarDecl *Decl = i->getDecl()) {
47474765
DbgTy = DebugTypeInfo::getLocalVariable(
47484766
Decl, RealTy, getTypeInfo(SILVal->getType()));
47494767
} else if (!SILTy.hasArchetype() && !VarInfo->Name.empty()) {
4750-
// Preliminary support for .sil debug information.
4768+
// Handle the cases that read from a SIL file
47514769
DbgTy = DebugTypeInfo::getFromTypeInfo(RealTy, getTypeInfo(SILTy));
47524770
} else
47534771
return;
47544772

4773+
// Calculate the indirection
4774+
IndirectionKind Indirection = DirectValue;
4775+
if (IsInCoro)
4776+
Indirection = IsAddrVal ? CoroIndirectValue : CoroDirectValue;
4777+
else if (IsAddrVal && !isa<AllocStackInst>(SILVal))
4778+
Indirection = IndirectValue;
4779+
47554780
// Put the value into a stack slot at -Onone.
47564781
llvm::SmallVector<llvm::Value *, 8> Copy;
4757-
emitShadowCopyIfNeeded(SILVal, i->getDebugScope(), *VarInfo, IsAnonymous,
4758-
Copy);
4782+
if (IsAddrVal)
4783+
Copy.emplace_back(
4784+
emitShadowCopyIfNeeded(getLoweredAddress(SILVal).getAddress(),
4785+
i->getDebugScope(), *VarInfo, IsAnonymous));
4786+
else
4787+
emitShadowCopyIfNeeded(SILVal, i->getDebugScope(), *VarInfo, IsAnonymous,
4788+
Copy);
4789+
47594790
bindArchetypes(DbgTy.getType());
47604791
if (!IGM.DebugInfo)
47614792
return;
47624793

4763-
IndirectionKind Indirection =
4764-
InCoroContext(*CurSILFn, *i) ? CoroDirectValue : DirectValue;
4765-
47664794
emitDebugVariableDeclaration(Copy, DbgTy, SILTy, i->getDebugScope(),
47674795
i->getLoc(), *VarInfo, Indirection);
47684796
}

lib/SIL/IR/SILPrinter.cpp

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,31 +1179,37 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
11791179

11801180
void printDebugVar(Optional<SILDebugVariable> Var,
11811181
const SourceManager *SM = nullptr) {
1182-
if (!Var || Var->Name.empty())
1182+
if (!Var)
11831183
return;
1184-
if (Var->Constant)
1185-
*this << ", let";
1186-
else
1187-
*this << ", var";
1188-
1189-
if ((Var->Loc || Var->Scope) && SM) {
1190-
*this << ", (name \"" << Var->Name << '"';
1191-
if (Var->Loc)
1192-
printDebugLocRef(*Var->Loc, *SM);
1193-
if (Var->Scope)
1194-
printDebugScopeRef(Var->Scope, *SM);
1195-
*this << ")";
1196-
} else
1197-
*this << ", name \"" << Var->Name << '"';
11981184

1199-
if (Var->ArgNo)
1200-
*this << ", argno " << Var->ArgNo;
1201-
if (Var->Implicit)
1202-
*this << ", implicit";
1203-
if (Var->Type) {
1204-
*this << ", type ";
1205-
Var->Type->print(PrintState.OS, PrintState.ASTOptions);
1185+
if (!Var->Name.empty()) {
1186+
if (Var->Constant)
1187+
*this << ", let";
1188+
else
1189+
*this << ", var";
1190+
1191+
if ((Var->Loc || Var->Scope) && SM) {
1192+
*this << ", (name \"" << Var->Name << '"';
1193+
if (Var->Loc)
1194+
printDebugLocRef(*Var->Loc, *SM);
1195+
if (Var->Scope)
1196+
printDebugScopeRef(Var->Scope, *SM);
1197+
*this << ")";
1198+
} else
1199+
*this << ", name \"" << Var->Name << '"';
1200+
1201+
if (Var->ArgNo)
1202+
*this << ", argno " << Var->ArgNo;
1203+
if (Var->Implicit)
1204+
*this << ", implicit";
1205+
if (Var->Type) {
1206+
*this << ", type ";
1207+
Var->Type->print(PrintState.OS, PrintState.ASTOptions);
1208+
}
12061209
}
1210+
// Although it's rare in real-world use cases, but during testing,
1211+
// sometimes we want to print out di-expression, even the debug
1212+
// variable name is empty.
12071213
if (Var->DIExpr)
12081214
printDebugInfoExpression(Var->DIExpr);
12091215
}

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1649,7 +1649,10 @@ bool SILParser::parseSILDebugInfoExpression(SILDebugInfoExpression &DIExpr) {
16491649
return true;
16501650

16511651
// All operators that we currently support
1652-
static const SILDIExprOperator AllOps[] = {SILDIExprOperator::Fragment};
1652+
static const SILDIExprOperator AllOps[] = {
1653+
SILDIExprOperator::Dereference,
1654+
SILDIExprOperator::Fragment
1655+
};
16531656

16541657
do {
16551658
P.consumeToken();

0 commit comments

Comments
 (0)