diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h index 9738363bb2e74..cca5d409bb214 100644 --- a/include/swift/SIL/SILInstruction.h +++ b/include/swift/SIL/SILInstruction.h @@ -4706,6 +4706,12 @@ class DebugValueInst final *getTrailingObjects() = NewDS; } + /// Whether the SSA value associated with the current debug_value + /// instruction has an address type. + bool hasAddrVal() const { + return getOperand()->getType().isAddress(); + } + /// True if all references within this debug value will be overwritten with a /// poison sentinel at this point in the program. This is used in debug builds /// when shortening non-trivial value lifetimes to ensure the debugger cannot diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index b2ef131188099..43e05cd63d815 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -2411,6 +2411,9 @@ bool IRGenDebugInfoImpl::buildDebugInfoExpression( if (!handleFragmentDIExpr(ExprOperand, Operands)) return false; break; + case SILDIExprOperator::Dereference: + Operands.push_back(llvm::dwarf::DW_OP_deref); + break; default: llvm_unreachable("Unrecognized operator"); } diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index 2eaea7349f480..4935951d01e25 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -1638,7 +1638,7 @@ void LoweredValue::getExplosion(IRGenFunction &IGF, SILType type, case Kind::DynamicallyEnforcedAddress: case Kind::CoroutineState: llvm_unreachable("not a value"); - + case Kind::ExplosionVector: ex.add(Storage.get(kind)); return; @@ -4714,7 +4714,11 @@ static bool InCoroContext(SILFunction &f, SILInstruction &i) { } void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) { + auto SILVal = i->getOperand(); + bool IsAddrVal = SILVal->getType().isAddress(); if (i->poisonRefs()) { + assert(!IsAddrVal && + "SIL values with address type should not have poison"); emitPoisonDebugValueInst(i); return; } @@ -4723,16 +4727,17 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) { auto VarInfo = i->getVarInfo(); assert(VarInfo && "debug_value without debug info"); - auto SILVal = i->getOperand(); if (isa(SILVal)) { // We cannot track the location of inlined error arguments because it has no // representation in SIL. - if (!i->getDebugScope()->InlinedCallSite && VarInfo->Name == "$error") { + if (!IsAddrVal && + !i->getDebugScope()->InlinedCallSite && VarInfo->Name == "$error") { auto funcTy = CurSILFn->getLoweredFunctionType(); emitErrorResultVar(funcTy, funcTy->getErrorResult(), i); } return; } + bool IsInCoro = InCoroContext(*CurSILFn, *i); bool IsAnonymous = false; VarInfo->Name = getVarName(i, IsAnonymous); @@ -4743,27 +4748,50 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) { SILTy = *MaybeSILTy; else SILTy = SILVal->getType(); + auto RealTy = SILTy.getASTType(); + if (IsAddrVal && IsInCoro) + if (auto *PBI = dyn_cast(i->getOperand())) { + // Usually debug info only ever describes the *result* of a projectBox + // call. To allow the debugger to display a boxed parameter of an async + // continuation object, however, the debug info can only describe the box + // itself and thus also needs to emit a box type for it so the debugger + // knows to call into Remote Mirrors to unbox the value. + RealTy = PBI->getOperand()->getType().getASTType(); + assert(isa(RealTy)); + } + + // Figure out the debug variable type if (VarDecl *Decl = i->getDecl()) { DbgTy = DebugTypeInfo::getLocalVariable( Decl, RealTy, getTypeInfo(SILVal->getType())); } else if (!SILTy.hasArchetype() && !VarInfo->Name.empty()) { - // Preliminary support for .sil debug information. + // Handle the cases that read from a SIL file DbgTy = DebugTypeInfo::getFromTypeInfo(RealTy, getTypeInfo(SILTy)); } else return; + // Calculate the indirection + IndirectionKind Indirection = DirectValue; + if (IsInCoro) + Indirection = IsAddrVal ? CoroIndirectValue : CoroDirectValue; + else if (IsAddrVal && !isa(SILVal)) + Indirection = IndirectValue; + // Put the value into a stack slot at -Onone. llvm::SmallVector Copy; - emitShadowCopyIfNeeded(SILVal, i->getDebugScope(), *VarInfo, IsAnonymous, - Copy); + if (IsAddrVal) + Copy.emplace_back( + emitShadowCopyIfNeeded(getLoweredAddress(SILVal).getAddress(), + i->getDebugScope(), *VarInfo, IsAnonymous)); + else + emitShadowCopyIfNeeded(SILVal, i->getDebugScope(), *VarInfo, IsAnonymous, + Copy); + bindArchetypes(DbgTy.getType()); if (!IGM.DebugInfo) return; - IndirectionKind Indirection = - InCoroContext(*CurSILFn, *i) ? CoroDirectValue : DirectValue; - emitDebugVariableDeclaration(Copy, DbgTy, SILTy, i->getDebugScope(), i->getLoc(), *VarInfo, Indirection); } diff --git a/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index fe6f39362955a..f9f7fd1d4f899 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -1179,31 +1179,37 @@ class SILPrinter : public SILInstructionVisitor { void printDebugVar(Optional Var, const SourceManager *SM = nullptr) { - if (!Var || Var->Name.empty()) + if (!Var) return; - if (Var->Constant) - *this << ", let"; - else - *this << ", var"; - - if ((Var->Loc || Var->Scope) && SM) { - *this << ", (name \"" << Var->Name << '"'; - if (Var->Loc) - printDebugLocRef(*Var->Loc, *SM); - if (Var->Scope) - printDebugScopeRef(Var->Scope, *SM); - *this << ")"; - } else - *this << ", name \"" << Var->Name << '"'; - if (Var->ArgNo) - *this << ", argno " << Var->ArgNo; - if (Var->Implicit) - *this << ", implicit"; - if (Var->Type) { - *this << ", type "; - Var->Type->print(PrintState.OS, PrintState.ASTOptions); + if (!Var->Name.empty()) { + if (Var->Constant) + *this << ", let"; + else + *this << ", var"; + + if ((Var->Loc || Var->Scope) && SM) { + *this << ", (name \"" << Var->Name << '"'; + if (Var->Loc) + printDebugLocRef(*Var->Loc, *SM); + if (Var->Scope) + printDebugScopeRef(Var->Scope, *SM); + *this << ")"; + } else + *this << ", name \"" << Var->Name << '"'; + + if (Var->ArgNo) + *this << ", argno " << Var->ArgNo; + if (Var->Implicit) + *this << ", implicit"; + if (Var->Type) { + *this << ", type "; + Var->Type->print(PrintState.OS, PrintState.ASTOptions); + } } + // Although it's rare in real-world use cases, but during testing, + // sometimes we want to print out di-expression, even the debug + // variable name is empty. if (Var->DIExpr) printDebugInfoExpression(Var->DIExpr); } diff --git a/lib/SIL/Parser/ParseSIL.cpp b/lib/SIL/Parser/ParseSIL.cpp index 0a25b682048cc..bf712b8f5a3f9 100644 --- a/lib/SIL/Parser/ParseSIL.cpp +++ b/lib/SIL/Parser/ParseSIL.cpp @@ -1649,7 +1649,10 @@ bool SILParser::parseSILDebugInfoExpression(SILDebugInfoExpression &DIExpr) { return true; // All operators that we currently support - static const SILDIExprOperator AllOps[] = {SILDIExprOperator::Fragment}; + static const SILDIExprOperator AllOps[] = { + SILDIExprOperator::Dereference, + SILDIExprOperator::Fragment + }; do { P.consumeToken();