alok created this revision.
alok added reviewers: aprantl, probinson, dblaikie, jmorse, jini.susan.george,
SouraVX, awpandey.
alok added projects: LLVM, debug-info.
Herald added a reviewer: bollu.
Herald added subscribers: llvm-commits, lldb-commits, jdoerfert, asbirlea,
george.burgess.iv, hiraditya.
Herald added a project: LLDB.
alok added a child revision: D69999: [DebugInfo] Support for
DW_OP_implicit_pointer (IR Verifier and Bitcode).
alok added a parent revision: D70643: [DebugInfo] Support for
DW_OP_implicit_pointer (DW_OP_LLVM_implicit_pointer).
This patch (3/N) stems from D69787 as suggested by
This is suggested by @jmorse.
New intrinsic llvm.dbg.derefval is introduced.
Summary:
Since dbg.value currently represents (VAR=VALUE), the new intrinsic
dbg.derefval will represent de-referenced value (*VAR = VAL)
- Below represents ptr=null
call void @llvm.dbg.value(metadata i32* null, metadata !21, metadata
!DIExpression())
- And below represents *ptr=var
call void @llvm.dbg.derefval(metadata !16, metadata !21, metadata
!DIExpression(DW_OP_LLVM_implicit_pointer, DW_OP_LLVM_arg0, 0))
- And below represents *ptr=arr[1]
call void @llvm.dbg.derefval(metadata !16, metadata !21, metadata
!DIExpression(DW_OP_LLVM_implicit_pointer, DW_OP_LLVM_arg0, 4))
- We should be able to represent the case when a variable points to
temporary (initialized by constant) and temporary is optimized out.
tmp=[CONST]; ptr=&tmp;
call void @llvm.dbg.derefval(metadata [CONST], metadata !21, metadata
!DIExpression(DW_OP_LLVM_arg0))
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D70644
Files:
lldb/source/Expression/IRInterpreter.cpp
llvm/docs/SourceLevelDebugging.rst
llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
llvm/include/llvm/CodeGen/MachineInstrBuilder.h
llvm/include/llvm/IR/DIBuilder.h
llvm/include/llvm/IR/InstVisitor.h
llvm/include/llvm/IR/IntrinsicInst.h
llvm/include/llvm/IR/Intrinsics.td
llvm/lib/Analysis/MemorySSA.cpp
llvm/lib/Analysis/ObjCARCInstKind.cpp
llvm/lib/Analysis/ValueTracking.cpp
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
llvm/lib/CodeGen/LiveDebugValues.cpp
llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
llvm/lib/IR/DIBuilder.cpp
llvm/lib/IR/IntrinsicInst.cpp
llvm/lib/IR/Verifier.cpp
llvm/lib/Transforms/Utils/Local.cpp
llvm/lib/Transforms/Utils/SimplifyCFG.cpp
polly/lib/Support/ScopHelper.cpp
Index: polly/lib/Support/ScopHelper.cpp
===================================================================
--- polly/lib/Support/ScopHelper.cpp
+++ polly/lib/Support/ScopHelper.cpp
@@ -624,6 +624,7 @@
case llvm::Intrinsic::assume:
// Some debug info intrinsics are supported/ignored.
case llvm::Intrinsic::dbg_value:
+ case llvm::Intrinsic::dbg_derefval:
case llvm::Intrinsic::dbg_declare:
return true;
default:
Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp
===================================================================
--- llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -4010,6 +4010,7 @@
switch (IntrinsicID) {
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
+ case Intrinsic::dbg_derefval:
case Intrinsic::dbg_label:
case Intrinsic::lifetime_end:
break;
Index: llvm/lib/Transforms/Utils/Local.cpp
===================================================================
--- llvm/lib/Transforms/Utils/Local.cpp
+++ llvm/lib/Transforms/Utils/Local.cpp
@@ -385,6 +385,11 @@
return false;
return true;
}
+ if (DbgDerefValueInst *DVI = dyn_cast<DbgDerefValueInst>(I)) {
+ if (DVI->getDerefVariable())
+ return false;
+ return true;
+ }
if (DbgLabelInst *DLI = dyn_cast<DbgLabelInst>(I)) {
if (DLI->getLabel())
return false;
Index: llvm/lib/IR/Verifier.cpp
===================================================================
--- llvm/lib/IR/Verifier.cpp
+++ llvm/lib/IR/Verifier.cpp
@@ -4314,6 +4314,9 @@
case Intrinsic::dbg_value: // llvm.dbg.value
visitDbgIntrinsic("value", cast<DbgVariableIntrinsic>(Call));
break;
+ case Intrinsic::dbg_derefval: // llvm.dbg.derefval
+ visitDbgIntrinsic("derefval", cast<DbgVariableIntrinsic>(Call));
+ break;
case Intrinsic::dbg_label: // llvm.dbg.label
visitDbgLabelIntrinsic("label", cast<DbgLabelInst>(Call));
break;
@@ -4836,8 +4839,9 @@
void Verifier::visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII) {
auto *MD = cast<MetadataAsValue>(DII.getArgOperand(0))->getMetadata();
AssertDI(isa<ValueAsMetadata>(MD) ||
- (isa<MDNode>(MD) && !cast<MDNode>(MD)->getNumOperands()),
- "invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD);
+ (isa<MDNode>(MD) && !cast<MDNode>(MD)->getNumOperands()) ||
+ isa<DbgDerefValueInst>(DII),
+ "invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD);
AssertDI(isa<DILocalVariable>(DII.getRawVariable()),
"invalid llvm.dbg." + Kind + " intrinsic variable", &DII,
DII.getRawVariable());
Index: llvm/lib/IR/IntrinsicInst.cpp
===================================================================
--- llvm/lib/IR/IntrinsicInst.cpp
+++ llvm/lib/IR/IntrinsicInst.cpp
@@ -50,6 +50,14 @@
return nullptr;
}
+Value *DbgVariableIntrinsic::getDerefVariable(bool AllowNullOp) const {
+ Value *Op = getArgOperand(0);
+ if (AllowNullOp && !Op)
+ return nullptr;
+
+ return Op;
+}
+
Optional<uint64_t> DbgVariableIntrinsic::getFragmentSizeInBits() const {
if (auto Fragment = getExpression()->getFragmentInfo())
return Fragment->SizeInBits;
Index: llvm/lib/IR/DIBuilder.cpp
===================================================================
--- llvm/lib/IR/DIBuilder.cpp
+++ llvm/lib/IR/DIBuilder.cpp
@@ -885,6 +885,14 @@
InsertBefore);
}
+Instruction *DIBuilder::insertDbgDerefValueIntrinsic(
+ Value *V, DILocalVariable *VarInfo, DIExpression *Expr,
+ const DILocation *DL, Instruction *InsertBefore) {
+ return insertDbgDerefValueIntrinsic(
+ V, VarInfo, Expr, DL, InsertBefore ? InsertBefore->getParent() : nullptr,
+ InsertBefore);
+}
+
Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V,
DILocalVariable *VarInfo,
DIExpression *Expr,
@@ -960,6 +968,27 @@
return B.CreateCall(ValueFn, Args);
}
+Instruction *DIBuilder::insertDbgDerefValueIntrinsic(
+ Value *V, DILocalVariable *VarInfo, DIExpression *Expr,
+ const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore) {
+ assert(V && "no value passed to dbg.value");
+ assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.value");
+ assert(DL && "Expected debug loc");
+ assert(DL->getScope()->getSubprogram() ==
+ VarInfo->getScope()->getSubprogram() &&
+ "Expected matching subprograms");
+ if (!ValueFn)
+ ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_derefval);
+
+ trackIfUnresolved(VarInfo);
+ trackIfUnresolved(Expr);
+ Value *Args[] = {V, MetadataAsValue::get(VMContext, VarInfo),
+ MetadataAsValue::get(VMContext, Expr)};
+
+ IRBuilder<> B = getIRBForDbgInsertion(DL, InsertBB, InsertBefore);
+ return B.CreateCall(ValueFn, Args);
+}
+
Instruction *DIBuilder::insertLabel(
DILabel *LabelInfo, const DILocation *DL,
BasicBlock *InsertBB, Instruction *InsertBefore) {
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -105,16 +105,17 @@
/// Helper type for DanglingDebugInfoMap.
class DanglingDebugInfo {
- const DbgValueInst* DI = nullptr;
+ const DbgVariableIntrinsic *DI = nullptr;
DebugLoc dl;
unsigned SDNodeOrder = 0;
public:
DanglingDebugInfo() = default;
- DanglingDebugInfo(const DbgValueInst *di, DebugLoc DL, unsigned SDNO)
+ DanglingDebugInfo(const DbgVariableIntrinsic *di, DebugLoc DL,
+ unsigned SDNO)
: DI(di), dl(std::move(DL)), SDNodeOrder(SDNO) {}
- const DbgValueInst* getDI() { return DI; }
+ const DbgVariableIntrinsic *getDI() { return DI; }
DebugLoc getdl() { return dl; }
unsigned getSDNodeOrder() { return SDNodeOrder; }
};
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1133,7 +1133,7 @@
void SelectionDAGBuilder::dropDanglingDebugInfo(const DILocalVariable *Variable,
const DIExpression *Expr) {
auto isMatchingDbgValue = [&](DanglingDebugInfo &DDI) {
- const DbgValueInst *DI = DDI.getDI();
+ const DbgVariableIntrinsic *DI = DDI.getDI();
DIVariable *DanglingVariable = DI->getVariable();
DIExpression *DanglingExpr = DI->getExpression();
if (DanglingVariable == Variable && Expr->fragmentsOverlap(DanglingExpr)) {
@@ -1166,7 +1166,7 @@
DanglingDebugInfoVector &DDIV = DanglingDbgInfoIt->second;
for (auto &DDI : DDIV) {
- const DbgValueInst *DI = DDI.getDI();
+ const DbgVariableIntrinsic *DI = DDI.getDI();
assert(DI && "Ill-formed DanglingDebugInfo");
DebugLoc dl = DDI.getdl();
unsigned ValSDNodeOrder = Val.getNode()->getIROrder();
@@ -1213,16 +1213,21 @@
}
void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {
- Value *V = DDI.getDI()->getValue();
+ const DbgVariableIntrinsic *DVI = DDI.getDI();
+
+ // Currently we consider only dbg.value intrinsics -- we tell the salvager
+ // that DW_OP_stack_value is desired.
+ assert(isa<DbgValueInst>(DVI) || isa<DbgDerefValueInst>(DVI));
+
+ Value *V = isa<DbgValueInst>(DVI) ? cast<DbgValueInst>(DVI)->getValue()
+ : cast<DbgDerefValueInst>(DVI)->getValue();
+
DILocalVariable *Var = DDI.getDI()->getVariable();
DIExpression *Expr = DDI.getDI()->getExpression();
DebugLoc DL = DDI.getdl();
DebugLoc InstDL = DDI.getDI()->getDebugLoc();
unsigned SDOrder = DDI.getSDNodeOrder();
- // Currently we consider only dbg.value intrinsics -- we tell the salvager
- // that DW_OP_stack_value is desired.
- assert(isa<DbgValueInst>(DDI.getDI()));
bool StackValue = true;
// Can this Value can be encoded without any further work?
@@ -5943,6 +5948,29 @@
DanglingDebugInfoMap[V].emplace_back(&DI, dl, SDNodeOrder);
return;
}
+ case Intrinsic::dbg_derefval: {
+ const DbgDerefValueInst &DI = cast<DbgDerefValueInst>(I);
+ assert(DI.getVariable() && "Missing variable");
+
+ DILocalVariable *Variable = DI.getVariable();
+ DIExpression *Expression = DI.getExpression();
+ dropDanglingDebugInfo(Variable, Expression);
+ const Value *V = DI.getValue();
+ if (!V)
+ return;
+
+ if (handleDebugValue(V, Variable, Expression, dl, DI.getDebugLoc(),
+ SDNodeOrder))
+ return;
+
+ // TODO: Dangling debug info will eventually either be resolved or produce
+ // an Undef DBG_VALUE. However in the resolution case, a gap may appear
+ // between the original dbg.value location and its resolved DBG_VALUE, which
+ // we should ideally fill with an extra Undef DBG_VALUE.
+
+ DanglingDebugInfoMap[V].emplace_back(&DI, dl, SDNodeOrder);
+ return;
+ }
case Intrinsic::eh_typeid_for: {
// Find the type id for the given typeinfo.
Index: llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -1444,6 +1444,52 @@
}
return true;
}
+ case Intrinsic::dbg_derefval: {
+ // This form of DBG_VALUE is target-independent.
+ const DbgDerefValueInst *DI = cast<DbgDerefValueInst>(II);
+ const MCInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE);
+ const Value *V = DI->getValue();
+ assert(DI->getVariable()->isValidLocationForIntrinsic(DbgLoc) &&
+ "Expected inlined-at fields to agree");
+ if (!V) {
+ // Currently the optimizer can produce this; insert an undef to
+ // help debugging. Probably the optimizer should not do this.
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, false, 0U,
+ DI->getVariable(), DI->getExpression());
+ } else if (const auto *MDV = dyn_cast<llvm::MetadataAsValue>(V)) {
+ if (const auto *LDV = dyn_cast<llvm::DIVariable>(MDV->getMetadata())) {
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
+ .addMetadata(LDV, true)
+ .addReg(0U)
+ .addMetadata(DI->getVariable())
+ .addMetadata(DI->getExpression());
+ }
+ } else if (const auto *CI = dyn_cast<ConstantInt>(V)) {
+ if (CI->getBitWidth() > 64)
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
+ .addCImm(CI)
+ .addReg(0U)
+ .addMetadata(DI->getVariable())
+ .addMetadata(DI->getExpression());
+ else
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
+ .addImm(CI->getZExtValue())
+ .addReg(0U)
+ .addMetadata(DI->getVariable())
+ .addMetadata(DI->getExpression());
+ } else if (const auto *CF = dyn_cast<ConstantFP>(V)) {
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II)
+ .addFPImm(CF)
+ .addReg(0U)
+ .addMetadata(DI->getVariable())
+ .addMetadata(DI->getExpression());
+ } else {
+ // We can't yet handle anything else here because it would require
+ // generating code, thus altering codegen because of debug info.
+ LLVM_DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n");
+ }
+ return true;
+ }
case Intrinsic::dbg_label: {
const DbgLabelInst *DI = cast<DbgLabelInst>(II);
assert(DI->getLabel() && "Missing label");
Index: llvm/lib/CodeGen/LiveDebugValues.cpp
===================================================================
--- llvm/lib/CodeGen/LiveDebugValues.cpp
+++ llvm/lib/CodeGen/LiveDebugValues.cpp
@@ -714,7 +714,8 @@
// Add the VarLoc to OpenRanges from this DBG_VALUE.
unsigned ID;
if (isDbgValueDescribedByReg(MI) || MI.getOperand(0).isImm() ||
- MI.getOperand(0).isFPImm() || MI.getOperand(0).isCImm()) {
+ MI.getOperand(0).isFPImm() || MI.getOperand(0).isCImm() ||
+ MI.getOperand(0).isMetadata()) {
// Use normal VarLoc constructor for registers and immediates.
VarLoc VL(MI, LS);
ID = VarLocIDs.insert(VL);
Index: llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
===================================================================
--- llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -159,6 +159,34 @@
return MIB.addReg(0).addMetadata(Variable).addMetadata(Expr);
}
+MachineInstrBuilder MachineIRBuilder::buildDerefDbgValue(const Value *Derefval,
+ const MDNode *Variable,
+ const MDNode *Expr) {
+ assert(isa<DILocalVariable>(Variable) && "not a variable");
+ assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
+ assert(
+ cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
+ "Expected inlined-at fields to agree");
+ auto MIB = buildInstr(TargetOpcode::DBG_VALUE);
+ if (const auto *MDV = dyn_cast<llvm::MetadataAsValue>(Derefval)) {
+ if (const auto *LDV = dyn_cast<llvm::DIVariable>(MDV->getMetadata())) {
+ MIB.addMetadata(LDV, true);
+ }
+ } else if (auto *CI = dyn_cast<ConstantInt>(Derefval)) {
+ if (CI->getBitWidth() > 64)
+ MIB.addCImm(CI);
+ else
+ MIB.addImm(CI->getZExtValue());
+ } else if (auto *CFP = dyn_cast<ConstantFP>(Derefval)) {
+ MIB.addFPImm(CFP);
+ } else {
+ // Insert %noreg if we didn't find a usable constant and had to drop it.
+ MIB.addReg(0U);
+ }
+
+ return MIB.addReg(0).addMetadata(Variable).addMetadata(Expr);
+}
+
MachineInstrBuilder MachineIRBuilder::buildDbgLabel(const MDNode *Label) {
assert(isa<DILabel>(Label) && "not a label");
assert(cast<DILabel>(Label)->isValidLocationForIntrinsic(State.DL) &&
Index: llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
===================================================================
--- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -1397,6 +1397,22 @@
}
return true;
}
+ case Intrinsic::dbg_derefval: {
+ // This form of DBG_VALUE is target-independent.
+ const DbgDerefValueInst &DI = cast<DbgDerefValueInst>(CI);
+ const Value *V = DI.getValue();
+ assert(DI.getVariable()->isValidLocationForIntrinsic(
+ MIRBuilder.getDebugLoc()) &&
+ "Expected inlined-at fields to agree");
+ if (!V) {
+ // Currently the optimizer can produce this; insert an undef to
+ // help debugging. Probably the optimizer should not do this.
+ MIRBuilder.buildDirectDbgValue(0, DI.getVariable(), DI.getExpression());
+ } else {
+ MIRBuilder.buildDerefDbgValue(V, DI.getVariable(), DI.getExpression());
+ }
+ return true;
+ }
case Intrinsic::uadd_with_overflow:
return translateOverflowIntrinsic(CI, TargetOpcode::G_UADDO, MIRBuilder);
case Intrinsic::sadd_with_overflow:
Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
===================================================================
--- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -874,6 +874,8 @@
OS << MI->getOperand(0).getImm();
} else if (MI->getOperand(0).isCImm()) {
MI->getOperand(0).getCImm()->getValue().print(OS, false /*isSigned*/);
+ } else if (MI->getOperand(0).isMetadata()) {
+ OS << MI->getOperand(0).getMetadata();
} else {
unsigned Reg;
if (MI->getOperand(0).isReg()) {
Index: llvm/lib/Analysis/ValueTracking.cpp
===================================================================
--- llvm/lib/Analysis/ValueTracking.cpp
+++ llvm/lib/Analysis/ValueTracking.cpp
@@ -508,6 +508,7 @@
case Intrinsic::sideeffect:
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
+ case Intrinsic::dbg_derefval:
case Intrinsic::dbg_label:
case Intrinsic::invariant_start:
case Intrinsic::invariant_end:
Index: llvm/lib/Analysis/ObjCARCInstKind.cpp
===================================================================
--- llvm/lib/Analysis/ObjCARCInstKind.cpp
+++ llvm/lib/Analysis/ObjCARCInstKind.cpp
@@ -184,6 +184,7 @@
// Don't let dbg info affect our results.
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
+ case Intrinsic::dbg_derefval:
case Intrinsic::dbg_label:
// Short cut: Some intrinsics obviously don't use ObjC pointers.
return true;
Index: llvm/lib/Analysis/MemorySSA.cpp
===================================================================
--- llvm/lib/Analysis/MemorySSA.cpp
+++ llvm/lib/Analysis/MemorySSA.cpp
@@ -290,6 +290,7 @@
case Intrinsic::dbg_declare:
case Intrinsic::dbg_label:
case Intrinsic::dbg_value:
+ case Intrinsic::dbg_derefval:
llvm_unreachable("debuginfo shouldn't have associated defs!");
default:
break;
Index: llvm/include/llvm/IR/Intrinsics.td
===================================================================
--- llvm/include/llvm/IR/Intrinsics.td
+++ llvm/include/llvm/IR/Intrinsics.td
@@ -787,6 +787,10 @@
[llvm_metadata_ty,
llvm_metadata_ty,
llvm_metadata_ty]>;
+ def int_dbg_derefval : Intrinsic<[],
+ [llvm_metadata_ty,
+ llvm_metadata_ty,
+ llvm_metadata_ty]>;
def int_dbg_addr : Intrinsic<[],
[llvm_metadata_ty,
llvm_metadata_ty,
Index: llvm/include/llvm/IR/IntrinsicInst.h
===================================================================
--- llvm/include/llvm/IR/IntrinsicInst.h
+++ llvm/include/llvm/IR/IntrinsicInst.h
@@ -72,6 +72,7 @@
switch (I->getIntrinsicID()) {
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
+ case Intrinsic::dbg_derefval:
case Intrinsic::dbg_addr:
case Intrinsic::dbg_label:
return true;
@@ -92,10 +93,13 @@
/// variable's value or its address.
Value *getVariableLocation(bool AllowNullOp = true) const;
+ Value *getDerefVariable(bool AllowNullOp = true) const;
+
/// Does this describe the address of a local variable. True for dbg.addr
/// and dbg.declare, but not dbg.value, which describes its value.
bool isAddressOfVariable() const {
- return getIntrinsicID() != Intrinsic::dbg_value;
+ return getIntrinsicID() == Intrinsic::dbg_declare ||
+ getIntrinsicID() == Intrinsic::dbg_addr;
}
DILocalVariable *getVariable() const {
@@ -124,6 +128,7 @@
switch (I->getIntrinsicID()) {
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
+ case Intrinsic::dbg_derefval:
case Intrinsic::dbg_addr:
return true;
default: return false;
@@ -184,6 +189,24 @@
/// @}
};
+ /// This represents the llvm.dbg.deref.value instruction.
+ class DbgDerefValueInst : public DbgVariableIntrinsic {
+ public:
+ Value *getValue() const {
+ return getDerefVariable(/* AllowNullOp = */ false);
+ }
+
+ /// \name Casting methods
+ /// @{
+ static bool classof(const IntrinsicInst *I) {
+ return I->getIntrinsicID() == Intrinsic::dbg_derefval;
+ }
+ static bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+ /// @}
+ };
+
/// This represents the llvm.dbg.label instruction.
class DbgLabelInst : public DbgInfoIntrinsic {
public:
Index: llvm/include/llvm/IR/InstVisitor.h
===================================================================
--- llvm/include/llvm/IR/InstVisitor.h
+++ llvm/include/llvm/IR/InstVisitor.h
@@ -204,6 +204,9 @@
// Handle the special instrinsic instruction classes.
RetTy visitDbgDeclareInst(DbgDeclareInst &I) { DELEGATE(DbgVariableIntrinsic);}
RetTy visitDbgValueInst(DbgValueInst &I) { DELEGATE(DbgVariableIntrinsic);}
+ RetTy visitDbgDerefValueInst(DbgDerefValueInst &I) {
+ DELEGATE(DbgVariableIntrinsic);
+ }
RetTy visitDbgVariableIntrinsic(DbgVariableIntrinsic &I)
{ DELEGATE(DbgInfoIntrinsic);}
RetTy visitDbgLabelInst(DbgLabelInst &I) { DELEGATE(DbgInfoIntrinsic);}
@@ -306,6 +309,8 @@
default: DELEGATE(IntrinsicInst);
case Intrinsic::dbg_declare: DELEGATE(DbgDeclareInst);
case Intrinsic::dbg_value: DELEGATE(DbgValueInst);
+ case Intrinsic::dbg_derefval:
+ DELEGATE(DbgDerefValueInst);
case Intrinsic::dbg_label: DELEGATE(DbgLabelInst);
case Intrinsic::memcpy: DELEGATE(MemCpyInst);
case Intrinsic::memmove: DELEGATE(MemMoveInst);
Index: llvm/include/llvm/IR/DIBuilder.h
===================================================================
--- llvm/include/llvm/IR/DIBuilder.h
+++ llvm/include/llvm/IR/DIBuilder.h
@@ -92,6 +92,11 @@
DIExpression *Expr, const DILocation *DL,
BasicBlock *InsertBB, Instruction *InsertBefore);
+ /// Internal helper for insertDbgDerefValueIntrinsic.
+ Instruction *insertDbgDerefValueIntrinsic(
+ llvm::Value *Val, DILocalVariable *VarInfo, DIExpression *Expr,
+ const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore);
+
public:
/// Construct a builder for a module.
///
@@ -849,6 +854,18 @@
const DILocation *DL,
Instruction *InsertBefore);
+ /// Insert a new llvm.dbg.derefval intrinsic call.
+ /// \param Val dereferenced value of the variable
+ /// \param VarInfo Variable's debug info descriptor.
+ /// \param Expr A complex location expression.
+ /// \param DL Debug info location.
+ /// \param InsertBefore Location for the new intrinsic.
+ Instruction *insertDbgDerefValueIntrinsic(llvm::Value *Val,
+ DILocalVariable *VarInfo,
+ DIExpression *Expr,
+ const DILocation *DL,
+ Instruction *InsertBefore);
+
/// Replace the vtable holder in the given type.
///
/// If this creates a self reference, it may orphan some unresolved cycles
Index: llvm/include/llvm/CodeGen/MachineInstrBuilder.h
===================================================================
--- llvm/include/llvm/CodeGen/MachineInstrBuilder.h
+++ llvm/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -224,10 +224,12 @@
return *this;
}
- const MachineInstrBuilder &addMetadata(const MDNode *MD) const {
+ const MachineInstrBuilder &addMetadata(const MDNode *MD,
+ bool IsImplicitPointer = false) const {
MI->addOperand(*MF, MachineOperand::CreateMetadata(MD));
- assert((MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable())
- : true) &&
+ assert(((MI->isDebugValue() && !IsImplicitPointer)
+ ? static_cast<bool>(MI->getDebugVariable())
+ : true) &&
"first MDNode argument of a DBG_VALUE not a variable");
assert((MI->isDebugLabel() ? static_cast<bool>(MI->getDebugLabel())
: true) &&
Index: llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
===================================================================
--- llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -366,6 +366,11 @@
const MDNode *Variable,
const MDNode *Expr);
+ /// Build and insert a DBG_VALUE instructions specifying that dereferenced
+ /// value of \p Variable is given by \p V (suitably modified by \p Expr).
+ MachineInstrBuilder buildDerefDbgValue(const Value *V, const MDNode *Variable,
+ const MDNode *Expr);
+
/// Build and insert a DBG_LABEL instructions specifying that \p Label is
/// given. Convert "llvm.dbg.label Label" to "DBG_LABEL Label".
MachineInstrBuilder buildDbgLabel(const MDNode *Label);
Index: llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
===================================================================
--- llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -814,6 +814,7 @@
case Intrinsic::sideeffect:
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
+ case Intrinsic::dbg_derefval:
case Intrinsic::dbg_label:
case Intrinsic::invariant_start:
case Intrinsic::invariant_end:
Index: llvm/docs/SourceLevelDebugging.rst
===================================================================
--- llvm/docs/SourceLevelDebugging.rst
+++ llvm/docs/SourceLevelDebugging.rst
@@ -250,6 +250,38 @@
be indirect (i.e, a pointer to the source variable), provided that interpreting
the complex expression derives the direct value.
+``llvm.dbg.derefval``
+^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: llvm
+
+ void @llvm.dbg.derefval(metadata, metadata, metadata)
+
+This intrinsic is identical to `llvm.dbg.value`, except that it is used to
+describe dereferenced value of pointer variable. The first argument is metadata.
+The second argument is a `local variable <LangRef.html#dilocalvariable>`_
+containing a description of the variable. The third argument is a
+`complex expression <LangRef.html#diexpression>`_. The first argument can be
+interpreted based on the third argument. If the third argument represents
+DW_OP_LLVM_implicit_pointer, the first argument is
+ `local variable <LangRef.html#dilocalvariable>`_ , otherwise it is the value
+(wrapped as metadata).
+
+An `llvm.dbg.derefval` intrinsic is usefull when location which the variable
+points to is optimized out, but the dereferenced value is known.
+
+.. code-block:: text
+
+ call void @llvm.dbg.derefval(metadata !1, metadata !2,
+ metadata !DIExpression(DW_OP_LLVM_implicit_pointer,
+ DW_OP_LLVM_arg0, 0))
+ !1 = !DILocalVariable(name: "arr", ...) ; int arr[5]
+ !2 = !DILocalVariable(name: "ptr", ...) ; int *ptr; ptr=arr;
+ ...
+ call void @llvm.dbg.derefval(metadata i32 1, metadata !1,
+ metadata !DIExpression(DW_OP_LLVM_arg0))
+ !1 = !DILocalVariable(name: "ptr", ...) ; int *ptr;tmp=1;ptr=&tmp;
+
Object lifetimes and scoping
============================
Index: lldb/source/Expression/IRInterpreter.cpp
===================================================================
--- lldb/source/Expression/IRInterpreter.cpp
+++ lldb/source/Expression/IRInterpreter.cpp
@@ -81,6 +81,7 @@
break;
case llvm::Intrinsic::dbg_declare:
case llvm::Intrinsic::dbg_value:
+ case llvm::Intrinsic::dbg_derefval:
return true;
}
}
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits