diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp --- a/lldb/source/Expression/IRInterpreter.cpp +++ b/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; } } diff --git a/llvm/docs/SourceLevelDebugging.rst b/llvm/docs/SourceLevelDebugging.rst --- a/llvm/docs/SourceLevelDebugging.rst +++ b/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 `_ +containing a description of the variable. The third argument is a +`complex expression `_. 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 `_ , 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 ============================ diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h --- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/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: diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/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); diff --git a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h --- a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/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(MI->getDebugVariable()) - : true) && + assert(((MI->isDebugValue() && !IsImplicitPointer) + ? static_cast(MI->getDebugVariable()) + : true) && "first MDNode argument of a DBG_VALUE not a variable"); assert((MI->isDebugLabel() ? static_cast(MI->getDebugLabel()) : true) && diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/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 diff --git a/llvm/include/llvm/IR/InstVisitor.h b/llvm/include/llvm/IR/InstVisitor.h --- a/llvm/include/llvm/IR/InstVisitor.h +++ b/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); diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h --- a/llvm/include/llvm/IR/IntrinsicInst.h +++ b/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(V) && classof(cast(V)); + } + /// @} + }; + /// This represents the llvm.dbg.label instruction. class DbgLabelInst : public DbgInfoIntrinsic { public: diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/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, diff --git a/llvm/lib/Analysis/MemorySSA.cpp b/llvm/lib/Analysis/MemorySSA.cpp --- a/llvm/lib/Analysis/MemorySSA.cpp +++ b/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; diff --git a/llvm/lib/Analysis/ObjCARCInstKind.cpp b/llvm/lib/Analysis/ObjCARCInstKind.cpp --- a/llvm/lib/Analysis/ObjCARCInstKind.cpp +++ b/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; diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/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: diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/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()) { diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/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(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: diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp --- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/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(Variable) && "not a variable"); + assert(cast(Expr)->isValid() && "not an expression"); + assert( + cast(Variable)->isValidLocationForIntrinsic(getDL()) && + "Expected inlined-at fields to agree"); + auto MIB = buildInstr(TargetOpcode::DBG_VALUE); + if (const auto *MDV = dyn_cast(Derefval)) { + if (const auto *LDV = dyn_cast(MDV->getMetadata())) { + MIB.addMetadata(LDV, true); + } + } else if (auto *CI = dyn_cast(Derefval)) { + if (CI->getBitWidth() > 64) + MIB.addCImm(CI); + else + MIB.addImm(CI->getZExtValue()); + } else if (auto *CFP = dyn_cast(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(Label) && "not a label"); assert(cast(Label)->isValidLocationForIntrinsic(State.DL) && diff --git a/llvm/lib/CodeGen/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues.cpp --- a/llvm/lib/CodeGen/LiveDebugValues.cpp +++ b/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); diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/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(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(V)) { + if (const auto *LDV = dyn_cast(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(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(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(II); assert(DI->getLabel() && "Missing label"); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/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; } }; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/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(DVI) || isa(DVI)); + + Value *V = isa(DVI) ? cast(DVI)->getValue() + : cast(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(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(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. diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp --- a/llvm/lib/IR/DIBuilder.cpp +++ b/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) { diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp --- a/llvm/lib/IR/IntrinsicInst.cpp +++ b/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 DbgVariableIntrinsic::getFragmentSizeInBits() const { if (auto Fragment = getExpression()->getFragmentInfo()) return Fragment->SizeInBits; diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -4314,6 +4314,9 @@ case Intrinsic::dbg_value: // llvm.dbg.value visitDbgIntrinsic("value", cast(Call)); break; + case Intrinsic::dbg_derefval: // llvm.dbg.derefval + visitDbgIntrinsic("derefval", cast(Call)); + break; case Intrinsic::dbg_label: // llvm.dbg.label visitDbgLabelIntrinsic("label", cast(Call)); break; @@ -4836,8 +4839,9 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII) { auto *MD = cast(DII.getArgOperand(0))->getMetadata(); AssertDI(isa(MD) || - (isa(MD) && !cast(MD)->getNumOperands()), - "invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); + (isa(MD) && !cast(MD)->getNumOperands()) || + isa(DII), + "invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); AssertDI(isa(DII.getRawVariable()), "invalid llvm.dbg." + Kind + " intrinsic variable", &DII, DII.getRawVariable()); diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -385,6 +385,11 @@ return false; return true; } + if (DbgDerefValueInst *DVI = dyn_cast(I)) { + if (DVI->getDerefVariable()) + return false; + return true; + } if (DbgLabelInst *DLI = dyn_cast(I)) { if (DLI->getLabel()) return false; diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/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; diff --git a/polly/lib/Support/ScopHelper.cpp b/polly/lib/Support/ScopHelper.cpp --- a/polly/lib/Support/ScopHelper.cpp +++ b/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: