diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -2583,12 +2583,15 @@ return Elements[I]; } - /// Determine whether this represents a standalone constant value. - bool isConstant() const; + /// Determine whether this represents a standalone unsigned constant value. + bool isUnsignedConstant() const; /// Determine whether this represents a standalone signed constant value. bool isSignedConstant() const; + /// Determine whether this represents a constant value. + bool isConstant() const; + using element_iterator = ArrayRef::iterator; element_iterator elements_begin() const { return getElements().begin(); } 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 @@ -209,11 +209,13 @@ const DIExpression *Expr = GE.Expr; // For compatibility with DWARF 3 and earlier, - // DW_AT_location(DW_OP_constu, X, DW_OP_stack_value) becomes + // DW_AT_location(DW_OP_constu, X, DW_OP_stack_value) or + // DW_AT_location(DW_OP_consts, X, DW_OP_stack_value) becomes // DW_AT_const_value(X). if (GlobalExprs.size() == 1 && Expr && Expr->isConstant()) { addToAccelTable = true; - addConstantValue(*VariableDIE, /*Unsigned=*/true, Expr->getElement(1)); + addConstantValue(*VariableDIE, Expr->isUnsignedConstant(), + Expr->getElement(1)); break; } diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -1450,7 +1450,7 @@ return DIExpression::get(Expr->getContext(), Ops); } -bool DIExpression::isConstant() const { +bool DIExpression::isUnsignedConstant() const { // Recognize DW_OP_constu C DW_OP_stack_value (DW_OP_LLVM_fragment Len Ofs)?. if (getNumElements() != 3 && getNumElements() != 6) return false; @@ -1463,14 +1463,22 @@ } bool DIExpression::isSignedConstant() const { - // Recognize DW_OP_consts C - if (getNumElements() != 2) + // Recognize DW_OP_consts C and DW_OP_consts C DW_OP_stack_value. + if (getNumElements() != 2 && getNumElements() != 3 && getNumElements() != 6) + return false; + if ((getNumElements() == 2 && getElement(0) != dwarf::DW_OP_consts) || + (getNumElements() == 3 && getElement(0) != dwarf::DW_OP_consts && + getElement(2) != dwarf::DW_OP_stack_value)) return false; - if (getElement(0) != dwarf::DW_OP_consts) + if (getNumElements() == 6 && getElement(3) != dwarf::DW_OP_LLVM_fragment) return false; return true; } +bool DIExpression::isConstant() const { + return isUnsignedConstant() || isSignedConstant(); +} + DIExpression::ExtOps DIExpression::getExtOps(unsigned FromSize, unsigned ToSize, bool Signed) { dwarf::TypeKind TK = Signed ? dwarf::DW_ATE_signed : dwarf::DW_ATE_unsigned; diff --git a/llvm/test/DebugInfo/X86/global-constants.ll b/llvm/test/DebugInfo/X86/global-constants.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/X86/global-constants.ll @@ -0,0 +1,31 @@ +; RUN: llc %s -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s + +; CHECK-DAG-LABEL: DW_AT_name ("negconstant") +; CHECK: DW_AT_const_value (-1) +; CHECK-DAG-LABEL: DW_AT_name ("negconstant2") +; CHECK: DW_AT_const_value (-2) +; CHECK-DAG-LABEL: DW_AT_name ("posconstant") +; CHECK: DW_AT_const_value (1) +; CHECK-DAG-LABEL: DW_AT_name ("posconstant1") +; CHECK: DW_AT_const_value (2) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!13, !14, !15, !16} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3) +!1 = !DIFile(filename: "globalconst.c", directory: "/") +!2 = !{} +!3 = !{!4, !7, !9, !11} +!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression(DW_OP_consts, 18446744073709551615, DW_OP_stack_value)) +!5 = distinct !DIGlobalVariable(name: "negconstant", scope: !0, file: !1, line: 2, type: !6, isLocal: false, isDefinition: true) +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression(DW_OP_consts, 18446744073709551614, DW_OP_stack_value)) +!8 = distinct !DIGlobalVariable(name: "negconstant2", scope: !0, file: !1, line: 3, type: !6, isLocal: false, isDefinition: true) +!9 = !DIGlobalVariableExpression(var: !10, expr: !DIExpression(DW_OP_consts, 1, DW_OP_stack_value)) +!10 = distinct !DIGlobalVariable(name: "posconstant", scope: !0, file: !1, line: 2, type: !6, isLocal: false, isDefinition: true) +!11 = !DIGlobalVariableExpression(var: !12, expr: !DIExpression(DW_OP_consts, 2, DW_OP_stack_value)) +!12 = distinct !DIGlobalVariable(name: "posconstant2", scope: !0, file: !1, line: 3, type: !6, isLocal: false, isDefinition: true) +!13 = !{i32 2, !"Dwarf Version", i32 4} +!14 = !{i32 2, !"Debug Info Version", i32 3} +!15 = !{i32 1, !"wchar_size", i32 4} +!16 = !{i32 7, !"PIC Level", i32 2} diff --git a/llvm/test/DebugInfo/X86/stack-value-dwarf4.ll b/llvm/test/DebugInfo/X86/stack-value-dwarf4.ll --- a/llvm/test/DebugInfo/X86/stack-value-dwarf4.ll +++ b/llvm/test/DebugInfo/X86/stack-value-dwarf4.ll @@ -13,6 +13,16 @@ ; CHECK-DWARF2-NEXT: .byte 48 ; CHECK-DWARF2-NEXT: .byte 147 ; CHECK-DWARF2-NEXT: .byte 2 +; CHECK-DWARF2: .byte 8 # DW_AT_location +; CHECK-DWARF2-NEXT: .byte 17 +; CHECK-DWARF2-NEXT: .byte 127 +; CHECK-DWARF2-NEXT: .byte 147 +; CHECK-DWARF2-NEXT: .byte 2 +; CHECK-DWARF2-NEXT: .byte 17 +; CHECK-DWARF2-NEXT: .byte 126 +; CHECK-DWARF2-NEXT: .byte 147 +; CHECK-DWARF2-NEXT: .byte 2 +; CHECK-DWARF2-NEXT: .byte 0 # End Of Children Mark ; CHECK-DWARF4: .byte 8 # DW_AT_location ; CHECK-DWARF4-NEXT:.byte 52 @@ -23,9 +33,21 @@ ; CHECK-DWARF4-NEXT:.byte 159 ; CHECK-DWARF4-NEXT:.byte 147 ; CHECK-DWARF4-NEXT:.byte 2 +; CHECK-DWARF4: .byte 10 # DW_AT_location +; CHECK-DWARF4-NEXT: .byte 17 +; CHECK-DWARF4-NEXT: .byte 127 +; CHECK-DWARF4-NEXT: .byte 159 +; CHECK-DWARF4-NEXT: .byte 147 +; CHECK-DWARF4-NEXT: .byte 2 +; CHECK-DWARF4-NEXT: .byte 17 +; CHECK-DWARF4-NEXT: .byte 126 +; CHECK-DWARF4-NEXT: .byte 159 +; CHECK-DWARF4-NEXT: .byte 147 +; CHECK-DWARF4-NEXT: .byte 2 +; CHECK-DWARF4-NEXT: .byte 0 # End Of Children Mark !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang", file: !4, globals: !1, emissionKind: FullDebug) -!1 = !{!2, !10} +!1 = !{!2, !10, !11, !14} !2 = !DIGlobalVariableExpression(var: !8, expr: !3) !3 = !DIExpression(DW_OP_constu, 4, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 16) !4 = !DIFile(filename: "", directory: "/") @@ -35,6 +57,11 @@ !8 = distinct !DIGlobalVariable(name: "a", scope: null, isLocal: false, isDefinition: true, type: !5) !9 = !DIExpression(DW_OP_constu, 0, DW_OP_stack_value, DW_OP_LLVM_fragment, 16, 16) !10 = !DIGlobalVariableExpression(var: !8, expr: !9) +!11 = !DIGlobalVariableExpression(var: !13, expr: !12) +!12 = !DIExpression(DW_OP_consts, 18446744073709551615, DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 16) +!13 = distinct !DIGlobalVariable(name: "b", scope: null, isLocal: false, isDefinition: true, type: !5) +!14 = !DIGlobalVariableExpression(var: !13, expr: !15) +!15 = !DIExpression(DW_OP_consts, 18446744073709551614, DW_OP_stack_value, DW_OP_LLVM_fragment, 16, 16) !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!6, !7} diff --git a/llvm/test/Transforms/StripSymbols/strip-dead-debug-info.ll b/llvm/test/Transforms/StripSymbols/strip-dead-debug-info.ll --- a/llvm/test/Transforms/StripSymbols/strip-dead-debug-info.ll +++ b/llvm/test/Transforms/StripSymbols/strip-dead-debug-info.ll @@ -7,6 +7,7 @@ ; CHECK-NOT: "GCC" ; CHECK: "Globals" ; CHECK: "abcd2" +; CHECK: "abcd3" source_filename = "test/Transforms/StripSymbols/strip-dead-debug-info.ll" @@ -61,9 +62,11 @@ !22 = distinct !DILexicalBlock(scope: !15, file: !2, line: 7) !23 = distinct !DICompileUnit(language: DW_LANG_C89, file: !2, producer: "GCC", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !5) !24 = distinct !DICompileUnit(language: DW_LANG_C89, file: !2, producer: "Globals", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !25) -!25 = !{!26} +!25 = !{!26, !31} !26 = !DIGlobalVariableExpression(var: !27, expr: !DIExpression(DW_OP_constu, 0, DW_OP_stack_value)) !27 = !DIGlobalVariable(name: "abcd2", scope: !2, file: !2, line: 2, type: !3, isLocal: true, isDefinition: true) !28 = distinct !DICompileUnit(language: DW_LANG_C89, file: !2, producer: "InlineTest", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !5) !29 = distinct !DISubprogram(name: "inlinefunc", linkageName: "inlinefunc", scope: null, file: !2, line: 7, type: !16, isLocal: false, isDefinition: true, isOptimized: true, unit: !28) !30 = !DILocation(line: 100, scope: !29, inlinedAt: !21) +!31 = !DIGlobalVariableExpression(var: !32, expr: !DIExpression(DW_OP_consts, 18446744073709551615, DW_OP_stack_value)) +!32 = !DIGlobalVariable(name: "abcd3", scope: !2, file: !2, line: 3, type: !3, isLocal: true, isDefinition: true)