Skip to content

Commit 839d655

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 8224df3 commit 839d655

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
@@ -2411,6 +2411,9 @@ bool IRGenDebugInfoImpl::buildDebugInfoExpression(
24112411
if (!handleFragmentDIExpr(ExprOperand, Operands))
24122412
return false;
24132413
break;
2414+
case SILDIExprOperator::Dereference:
2415+
Operands.push_back(llvm::dwarf::DW_OP_deref);
2416+
break;
24142417
default:
24152418
llvm_unreachable("Unrecognized operator");
24162419
}

lib/IRGen/IRGenSIL.cpp

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

47164716
void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
4717+
auto SILVal = i->getOperand();
4718+
bool IsAddrVal = SILVal->getType().isAddress();
47174719
if (i->poisonRefs()) {
4720+
assert(!IsAddrVal &&
4721+
"SIL values with address type should not have poison");
47184722
emitPoisonDebugValueInst(i);
47194723
return;
47204724
}
@@ -4723,16 +4727,17 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
47234727

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

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

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

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

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)