diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index cdadc68164ce11..0df22a9d95dc7d 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -2582,11 +2582,10 @@ class DIExpression : public MDNode { return Elements[I]; } - /// Determine whether this represents a standalone constant value. - bool isConstant() const; - - /// Determine whether this represents a standalone signed constant value. - bool isSignedConstant() const; + enum SignedOrUnsignedConstant { SignedConstant, UnsignedConstant }; + /// Determine whether this represents a constant value, if so + // return it's sign information. + llvm::Optional isConstant() const; using element_iterator = ArrayRef::iterator; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 002687b9375a31..ac7a3163984412 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -209,11 +209,16 @@ void DwarfCompileUnit::addLocationAttribute( 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, + DIExpression::SignedOrUnsignedConstant::UnsignedConstant == + *Expr->isConstant(), + Expr->getElement(1)); break; } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 90484f1f606587..7a28bcb08ba42f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1359,7 +1359,9 @@ void DwarfUnit::constructGenericSubrangeDIE(DIE &Buffer, if (auto *VarDIE = getDIE(BV)) addDIEEntry(DwGenericSubrange, Attr, *VarDIE); } else if (auto *BE = Bound.dyn_cast()) { - if (BE->isSignedConstant()) { + if (BE->isConstant() && + DIExpression::SignedOrUnsignedConstant::SignedConstant == + *BE->isConstant()) { if (Attr != dwarf::DW_AT_lower_bound || DefaultLowerBound == -1 || static_cast(BE->getElement(1)) != DefaultLowerBound) addSInt(DwGenericSubrange, Attr, dwarf::DW_FORM_sdata, diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index d5f8f3bdc1da39..174fed27671aff 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1935,7 +1935,10 @@ static void writeDIGenericSubrange(raw_ostream &Out, const DIGenericSubrange *N, auto IsConstant = [&](Metadata *Bound) -> bool { if (auto *BE = dyn_cast_or_null(Bound)) { - return BE->isSignedConstant(); + return BE->isConstant() + ? DIExpression::SignedOrUnsignedConstant::SignedConstant == + *BE->isConstant() + : false; } return false; }; diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index f003ec9557c730..1299acdc4723da 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -1458,25 +1458,31 @@ Optional DIExpression::createFragmentExpression( return DIExpression::get(Expr->getContext(), Ops); } -bool DIExpression::isConstant() const { - // Recognize DW_OP_constu C DW_OP_stack_value (DW_OP_LLVM_fragment Len Ofs)?. - if (getNumElements() != 3 && getNumElements() != 6) - return false; - if (getElement(0) != dwarf::DW_OP_constu || - getElement(2) != dwarf::DW_OP_stack_value) - return false; - if (getNumElements() == 6 && getElement(3) != dwarf::DW_OP_LLVM_fragment) - return false; - return true; -} +llvm::Optional +DIExpression::isConstant() const { + + // Recognize signed and unsigned constants. + // An signed constants can be represented as DW_OP_consts C DW_OP_stack_value + // (DW_OP_LLVM_fragment of Len). + // An unsigned constant can be represented as + // DW_OP_constu C DW_OP_stack_value (DW_OP_LLVM_fragment of Len). + + if ((getNumElements() != 2 && getNumElements() != 3 && + getNumElements() != 6) || + (getElement(0) != dwarf::DW_OP_consts && + getElement(0) != dwarf::DW_OP_constu)) + return None; -bool DIExpression::isSignedConstant() const { - // Recognize DW_OP_consts C - if (getNumElements() != 2) - return false; - if (getElement(0) != dwarf::DW_OP_consts) - return false; - return true; + if (getNumElements() == 2 && getElement(0) == dwarf::DW_OP_consts) + return SignedOrUnsignedConstant::SignedConstant; + + if ((getNumElements() == 3 && getElement(2) != dwarf::DW_OP_stack_value) || + (getNumElements() == 6 && (getElement(2) != dwarf::DW_OP_stack_value || + getElement(3) != dwarf::DW_OP_LLVM_fragment))) + return None; + return getElement(0) == dwarf::DW_OP_constu + ? SignedOrUnsignedConstant::UnsignedConstant + : SignedOrUnsignedConstant::SignedConstant; } DIExpression::ExtOps DIExpression::getExtOps(unsigned FromSize, unsigned ToSize, diff --git a/llvm/test/DebugInfo/X86/global-constants.ll b/llvm/test/DebugInfo/X86/global-constants.ll new file mode 100644 index 00000000000000..bf23beccc73180 --- /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/invalid-global-constants.ll b/llvm/test/DebugInfo/X86/invalid-global-constants.ll new file mode 100644 index 00000000000000..9b9961568174da --- /dev/null +++ b/llvm/test/DebugInfo/X86/invalid-global-constants.ll @@ -0,0 +1,17 @@ +; RUN: llc %s -filetype=obj -o - 2>&1 | FileCheck %s --check-prefix=ERROR +; ERROR: invalid expression + +!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: "invalidconst.c", directory: "/") +!2 = !{} +!3 = !{!4} +!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression(DW_OP_consts, 18446744073709551615, DW_OP_stack_value, DW_OP_consts, 18446744073709551615, DW_OP_stack_value)) +!5 = distinct !DIGlobalVariable(name: "constant", scope: !0, file: !1, line: 2, type: !6, isLocal: false, isDefinition: true) +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!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 index 479625b6df8fed..b1cfd3284f9beb 100644 --- a/llvm/test/DebugInfo/X86/stack-value-dwarf4.ll +++ b/llvm/test/DebugInfo/X86/stack-value-dwarf4.ll @@ -13,6 +13,16 @@ target triple = "x86_64-unknown-linux-gnu" ; 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 @@ target triple = "x86_64-unknown-linux-gnu" ; 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 @@ target triple = "x86_64-unknown-linux-gnu" !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 index d9b21d4a60fd5b..cfb4e6c348b017 100644 --- 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 @@ attributes #2 = { nounwind readonly ssp } !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)