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
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to