diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -789,7 +789,7 @@ const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo(); auto AddEntry = [&](const DbgValueLocEntry &Entry, - DIExpressionCursor &Cursor) { + DIExpressionCursor &Cursor) { if (Entry.isLocation()) { if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Entry.getLoc().getReg())) @@ -798,11 +798,19 @@ // If there is an expression, emit raw unsigned bytes. DwarfExpr.addUnsignedConstant(Entry.getInt()); } else if (Entry.isConstantFP()) { + // DwarfExpression does not support arguments wider than 64 bits + // (see PR52584). + // TODO: Consider chunking expressions containing overly wide + // arguments into separate pointer-sized fragment expressions. APInt RawBytes = Entry.getConstantFP()->getValueAPF().bitcastToAPInt(); - DwarfExpr.addUnsignedConstant(RawBytes); + if (RawBytes.getBitWidth() > 64) + return false; + DwarfExpr.addUnsignedConstant(RawBytes.getZExtValue()); } else if (Entry.isConstantInt()) { APInt RawBytes = Entry.getConstantInt()->getValue(); - DwarfExpr.addUnsignedConstant(RawBytes); + if (RawBytes.getBitWidth() > 64) + return false; + DwarfExpr.addUnsignedConstant(RawBytes.getZExtValue()); } else if (Entry.isTargetIndexLocation()) { TargetIndexLocation Loc = Entry.getTargetIndexLocation(); // TODO TargetIndexLocation is a target-independent. Currently only the @@ -815,11 +823,12 @@ return true; }; - DwarfExpr.addExpression( - std::move(Cursor), - [&](unsigned Idx, DIExpressionCursor &Cursor) -> bool { - return AddEntry(DVal->getLocEntries()[Idx], Cursor); - }); + if (!DwarfExpr.addExpression( + std::move(Cursor), + [&](unsigned Idx, DIExpressionCursor &Cursor) -> bool { + return AddEntry(DVal->getLocEntries()[Idx], Cursor); + })) + return VariableDie; // Now attach the location information to the DIE. addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize()); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -340,16 +340,17 @@ /// create one if necessary. unsigned getOrCreateBaseType(unsigned BitSize, dwarf::TypeKind Encoding); + /// Emit all remaining operations in the DIExpressionCursor. The + /// cursor must not contain any DW_OP_LLVM_arg operations. + void addExpression(DIExpressionCursor &&Expr); + /// Emit all remaining operations in the DIExpressionCursor. - /// - /// \param FragmentOffsetInBits If this is one fragment out of multiple - /// locations, this is the offset of the - /// fragment inside the entire variable. - void addExpression(DIExpressionCursor &&Expr, - unsigned FragmentOffsetInBits = 0); - void - addExpression(DIExpressionCursor &&Expr, - llvm::function_ref InsertArg); + /// DW_OP_LLVM_arg operations are resolved by calling (\p InsertArg). + // + /// \return false if any call to (\p InsertArg) returns false. + bool addExpression( + DIExpressionCursor &&Expr, + llvm::function_ref InsertArg); /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to /// the fragment described by \c Expr. diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -463,15 +463,14 @@ return true; } -void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, - unsigned FragmentOffsetInBits) { +void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor) { addExpression(std::move(ExprCursor), [](unsigned Idx, DIExpressionCursor &Cursor) -> bool { llvm_unreachable("unhandled opcode found in expression"); }); } -void DwarfExpression::addExpression( +bool DwarfExpression::addExpression( DIExpressionCursor &&ExprCursor, llvm::function_ref InsertArg) { // Entry values can currently only cover the initial register location, @@ -496,7 +495,7 @@ case dwarf::DW_OP_LLVM_arg: if (!InsertArg(Op->getArg(0), ExprCursor)) { LocationKind = Unknown; - return; + return false; } break; case dwarf::DW_OP_LLVM_fragment: { @@ -527,7 +526,7 @@ setSubRegisterPiece(0, 0); // Reset the location description kind. LocationKind = Unknown; - return; + return true; } case dwarf::DW_OP_plus_uconst: assert(!isRegisterLocation()); @@ -630,6 +629,8 @@ if (isImplicitLocation() && !isParameterValue()) // Turn this into an implicit location description. addStackValue(); + + return true; } /// add masking operations to stencil out a subregister. diff --git a/llvm/test/DebugInfo/X86/pr52584.ll b/llvm/test/DebugInfo/X86/pr52584.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/X86/pr52584.ll @@ -0,0 +1,33 @@ +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o - %s \ +; RUN: | llvm-dwarfdump - \ +; RUN: | FileCheck %s + +; CHECK: DW_TAG_variable +; CHECK-NOT: DW_AT_location +; CHECK-NEXT: DW_AT_name ("arr") +; CHECK-NOT: DW_AT_location +; CHECK: DW_TAG +define dso_local void @test() !dbg !4 { +entry: + call void @llvm.dbg.value(metadata !DIArgList(i128 0), metadata !7, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 127)), !dbg !12 + ret void, !dbg !12 +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "") +!2 = !{i32 7, !"Dwarf Version", i32 4} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 1, type: !5, unit: !0) +!5 = !DISubroutineType(types: !6) +!6 = !{null} +!7 = !DILocalVariable(name: "arr", scope: !4, file: !1, line: 1, type: !8) +!8 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 128, elements: !10) +!9 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!10 = !{!11} +!11 = !DISubrange(count: 16) +!12 = !DILocation(line: 1, column: 1, scope: !4)