Index: llvm/include/llvm/Transforms/Utils/Local.h =================================================================== --- llvm/include/llvm/Transforms/Utils/Local.h +++ llvm/include/llvm/Transforms/Utils/Local.h @@ -283,6 +283,9 @@ /// dbg.addr. TinyPtrVector FindDbgDeclareUses(Value *V); +/// Finds an entry value for the variable. +Value *findEntryValue(DIVariable *Var); + /// Finds the llvm.dbg.value intrinsics describing a value. void findDbgValues(SmallVectorImpl &DbgValues, Value *V); Index: llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -287,7 +287,8 @@ // a call site parameter expression and if that expression is just a register // location, emit it with addBReg and offset 0, because we should emit a DWARF // expression representing a value, rather than a location. - if (!isMemoryLocation() && !HasComplexExpression && + // FIXME: Simplify the statements regarding entry values. + if (!isMemoryLocation() && (!HasComplexExpression || isEntryValue()) && (!isParameterValue() || isEntryValue())) { for (auto &Reg : DwarfRegs) { if (Reg.DwarfRegNo >= 0) @@ -299,7 +300,7 @@ finalizeEntryValue(); if (isEntryValue() && !isIndirect() && !isParameterValue() && - DwarfVersion >= 4) + DwarfVersion >= 4 && !HasComplexExpression) emitOp(dwarf::DW_OP_stack_value); DwarfRegs.clear(); @@ -509,7 +510,7 @@ return; } case dwarf::DW_OP_plus_uconst: - assert(!isRegisterLocation()); + assert(!isRegisterLocation() || isEntryValue()); emitOp(dwarf::DW_OP_plus_uconst); emitUnsigned(Op->getArg(0)); break; Index: llvm/lib/IR/DebugInfoMetadata.cpp =================================================================== --- llvm/lib/IR/DebugInfoMetadata.cpp +++ llvm/lib/IR/DebugInfoMetadata.cpp @@ -1029,8 +1029,7 @@ // entry values of a simple register location. One reason for this is that // we currently can't calculate the size of the resulting DWARF block for // other expressions. - return I->get() == expr_op_begin()->get() && I->getArg(0) == 1 && - getNumElements() == 2; + return I->get() == expr_op_begin()->get() && I->getArg(0) == 1; } case dwarf::DW_OP_LLVM_convert: case dwarf::DW_OP_LLVM_tag_offset: @@ -1195,8 +1194,9 @@ if (EntryValue) { Ops.push_back(dwarf::DW_OP_LLVM_entry_value); // Add size info needed for entry value expression. - // Add plus one for target register operand. - Ops.push_back(Expr->getNumElements() + 1); + // It is always of size 1 at the moment, since we support + // simple register locations only. + Ops.push_back(1); } // If there are no ops to prepend, do not even add the DW_OP_stack_value. Index: llvm/lib/Transforms/Utils/Local.cpp =================================================================== --- llvm/lib/Transforms/Utils/Local.cpp +++ llvm/lib/Transforms/Utils/Local.cpp @@ -1593,6 +1593,30 @@ return DDIs; } +Value *llvm::findEntryValue(DIVariable *Var) { + // TODO: Find an entry value for local variables, + // if the local variable value can be expressed + // in terms of an entry value (of a parameter). + if (!cast(Var)->isParameter()) + return nullptr; + + LLVM_DEBUG(llvm::dbgs() << "Finding entry value for variable: "; + Var->dump();); + + if (auto *MDV = MetadataAsValue::get(Var->getContext(), Var)) { + LLVM_DEBUG(llvm::dbgs() << " mdv : "; MDV->dump();); + for (User *U : MDV->users()) { + LLVM_DEBUG(llvm::dbgs() << " user : "; U->dump();); + if (DbgValueInst *DVI = dyn_cast(U)) { + LLVM_DEBUG(llvm::dbgs() << " dbg.val: "; DVI->dump();); + return DVI->getValue(); + } + } + } + + return nullptr; +} + void llvm::findDbgValues(SmallVectorImpl &DbgValues, Value *V) { // This function is hot. Check whether the value has any metadata to avoid a // DenseMap lookup. Index: llvm/test/Verifier/diexpression-valid-entry-value.ll =================================================================== --- llvm/test/Verifier/diexpression-valid-entry-value.ll +++ llvm/test/Verifier/diexpression-valid-entry-value.ll @@ -1,5 +1,6 @@ ; RUN: opt -S < %s 2>&1 | FileCheck %s -!named = !{!0} +!named = !{!0, !1} ; CHECK-NOT: invalid expression !0 = !DIExpression(DW_OP_LLVM_entry_value, 1) +!1 = !DIExpression(DW_OP_LLVM_entry_value, 1, DW_OP_plus_uconst, 3, DW_OP_stack_value) Index: llvm/unittests/Transforms/Utils/LocalTest.cpp =================================================================== --- llvm/unittests/Transforms/Utils/LocalTest.cpp +++ llvm/unittests/Transforms/Utils/LocalTest.cpp @@ -582,6 +582,41 @@ verifyDebugValuesAreSalvaged(); } +TEST(Local, FindEntryValue) { + LLVMContext Ctx; + + std::unique_ptr M = parseIR(Ctx, + R"( + define internal void @foo(i32 %i) !dbg !4 { + entry: + call void @llvm.dbg.value(metadata i32 %i, metadata !8, metadata !DIExpression()), !dbg !6 + ret void, !dbg !6 + } + + ; Function Attrs: nounwind readnone speculatable willreturn + declare void @llvm.dbg.value(metadata, metadata, metadata) + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!3} + + !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) + !1 = !DIFile(filename: "test.ll", directory: "/") + !2 = !{} + !3 = !{i32 2, !"Debug Info Version", i32 3} + !4 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !5, isLocal: true, isDefinition: true, scopeLine: 1, isOptimized: true, unit: !0, retainedNodes: !7) + !5 = !DISubroutineType(types: !2) + !6 = !DILocation(line: 1, column: 1, scope: !4) + !7 = !{!8} + !8 = !DILocalVariable(name: "i", arg: 1, scope: !4, file: !1, line: 2) + )"); + + auto &F = *cast(M->getNamedValue("foo")); + auto SP = F.getSubprogram(); + auto Var = SP->getRetainedNodes()[0]; + auto EntryValue = findEntryValue(cast(Var)); + ASSERT_TRUE(EntryValue != nullptr); +} + TEST(Local, ChangeToUnreachable) { LLVMContext Ctx;