alok updated this revision to Diff 234356.
alok added a comment.
This version is updated to rebase and to incorporate comments from @jmorse and
@StephenTozer.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D70644/new/
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/MachineInstr.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/MachineInstr.cpp
llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
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
@@ -4322,6 +4322,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;
@@ -4877,8 +4880,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
@@ -887,6 +887,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,
@@ -962,6 +970,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/FastISel.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -1401,11 +1401,13 @@
}
return true;
}
- case Intrinsic::dbg_value: {
+ case Intrinsic::dbg_value:
+ case Intrinsic::dbg_derefval: {
// This form of DBG_VALUE is target-independent.
- const DbgValueInst *DI = cast<DbgValueInst>(II);
+ const DbgVariableIntrinsic *DI = cast<DbgVariableIntrinsic>(II);
const MCInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE);
- const Value *V = DI->getValue();
+ const Value *V = DbgValueInst::classof(DI) ? DI->getVariableLocation(false)
+ : DI->getDerefVariable(false);
assert(DI->getVariable()->isValidLocationForIntrinsic(DbgLoc) &&
"Expected inlined-at fields to agree");
if (!V) {
@@ -1437,6 +1439,15 @@
bool IsIndirect = false;
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, IsIndirect, Reg,
DI->getVariable(), DI->getExpression());
+ } else if (DbgDerefValueInst::classof(DI)) {
+ 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)
+ .addImplicitPtrMetadata(LDV)
+ .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.
Index: llvm/lib/CodeGen/MachineInstr.cpp
===================================================================
--- llvm/lib/CodeGen/MachineInstr.cpp
+++ llvm/lib/CodeGen/MachineInstr.cpp
@@ -818,6 +818,11 @@
return cast<DILocalVariable>(getOperand(2).getMetadata());
}
+const DIVariable *MachineInstr::getDebugImplicitVariable() const {
+ assert(isDebugValue() && "not a DBG_VALUE");
+ return cast<DIVariable>(getOperand(0).getMetadata());
+}
+
const DIExpression *MachineInstr::getDebugExpression() const {
assert(isDebugValue() && "not a DBG_VALUE");
return cast<DIExpression>(getOperand(3).getMetadata());
Index: llvm/lib/CodeGen/LiveDebugValues.cpp
===================================================================
--- llvm/lib/CodeGen/LiveDebugValues.cpp
+++ llvm/lib/CodeGen/LiveDebugValues.cpp
@@ -174,7 +174,8 @@
ImmediateKind,
EntryValueKind,
EntryValueBackupKind,
- EntryValueCopyBackupKind
+ EntryValueCopyBackupKind,
+ ImplicitPtrKind
} Kind = InvalidKind;
/// The value location. Stored separately to avoid repeatedly
@@ -186,6 +187,7 @@
int64_t Immediate;
const ConstantFP *FPImm;
const ConstantInt *CImm;
+ const DIVariable *ImplicitPtr;
} Loc;
VarLoc(const MachineInstr &MI, LexicalScopes &LS)
@@ -208,6 +210,9 @@
} else if (MI.getOperand(0).isCImm()) {
Kind = ImmediateKind;
Loc.CImm = MI.getOperand(0).getCImm();
+ } else if (MI.getOperand(0).isMetadata()) {
+ Kind = ImplicitPtrKind;
+ Loc.ImplicitPtr = MI.getDebugImplicitVariable();
}
// We create the debug entry values from the factory functions rather than
@@ -314,6 +319,10 @@
MachineOperand MO = MI.getOperand(0);
return BuildMI(MF, DbgLoc, IID, Indirect, MO, Var, DIExpr);
}
+ case ImplicitPtrKind: {
+ MachineOperand MO = MI.getOperand(0);
+ return BuildMI(MF, DbgLoc, IID, Indirect, MO, Var, DIExpr);
+ }
case EntryValueBackupKind:
case EntryValueCopyBackupKind:
case InvalidKind:
@@ -377,6 +386,9 @@
case ImmediateKind:
dbgs() << Loc.Immediate;
break;
+ case ImplicitPtrKind:
+ dbgs() << Loc.ImplicitPtr->getName();
+ break;
case InvalidKind:
llvm_unreachable("Invalid VarLoc in dump method");
}
@@ -803,7 +815,8 @@
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);
// End all previous ranges of VL.Var.
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.addImplicitPtrMetadata(LDV);
+ }
+ } 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
@@ -879,6 +879,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
@@ -510,6 +510,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
@@ -807,6 +807,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.
///
@@ -851,6 +856,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
@@ -235,6 +235,18 @@
return *this;
}
+ const MachineInstrBuilder &addImplicitPtrMetadata(const MDNode *MD) const {
+ MI->addOperand(*MF, MachineOperand::CreateMetadata(MD));
+ assert(((MI->isDebugValue())
+ ? static_cast<bool>(MI->getDebugImplicitVariable())
+ : true) &&
+ "first MDNode argument of a DBG_VALUE not a DIVariable");
+ assert((MI->isDebugLabel() ? static_cast<bool>(MI->getDebugLabel())
+ : true) &&
+ "first MDNode argument of a DBG_LABEL not a label");
+ return *this;
+ }
+
const MachineInstrBuilder &addCFIIndex(unsigned CFIIndex) const {
MI->addOperand(*MF, MachineOperand::CreateCFIIndex(CFIIndex));
return *this;
Index: llvm/include/llvm/CodeGen/MachineInstr.h
===================================================================
--- llvm/include/llvm/CodeGen/MachineInstr.h
+++ llvm/include/llvm/CodeGen/MachineInstr.h
@@ -403,6 +403,10 @@
/// this DBG_VALUE instruction.
const DILocalVariable *getDebugVariable() const;
+ /// Return the debug implicit variable referenced by
+ /// this DBG_VALUE instruction.
+ const DIVariable *getDebugImplicitVariable() const;
+
/// Return the complex address expression referenced by
/// this DBG_VALUE instruction.
const DIExpression *getDebugExpression() const;
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 the 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
@@ -815,6 +815,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,37 @@
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 a pointer variable, when the pointer itself is
+no longer available in the program.
+
+The first argument must be a `local variable <LangRef.html#dilocalvariable>`_.
+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>`_.
+
+An `llvm.dbg.derefval` intrinsic is useful 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