[llvm] f13f050 - [DebugInfo] Support for signed constants inside DIExpression

Sourabh Singh Tomar via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 30 10:50:50 PDT 2021


Author: Sourabh Singh Tomar
Date: 2021-03-30T23:20:38+05:30
New Revision: f13f0505515dcb1d256673c5224cc3ca55569122

URL: https://github.com/llvm/llvm-project/commit/f13f0505515dcb1d256673c5224cc3ca55569122
DIFF: https://github.com/llvm/llvm-project/commit/f13f0505515dcb1d256673c5224cc3ca55569122.diff

LOG: [DebugInfo] Support for signed constants inside DIExpression

Negative numbers are represented using DW_OP_consts along with signed representation
of the number as the argument.

Test case IR is generated using Fortran front-end.

Reviewed By: aprantl

Differential Revision: https://reviews.llvm.org/D99273

Added: 
    llvm/test/DebugInfo/X86/global-constants.ll
    llvm/test/DebugInfo/X86/invalid-global-constants.ll

Modified: 
    llvm/include/llvm/IR/DebugInfoMetadata.h
    llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
    llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
    llvm/lib/IR/AsmWriter.cpp
    llvm/lib/IR/DebugInfoMetadata.cpp
    llvm/test/DebugInfo/X86/stack-value-dwarf4.ll
    llvm/test/Transforms/StripSymbols/strip-dead-debug-info.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index cdadc68164ce1..0df22a9d95dc7 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<SignedOrUnsignedConstant> isConstant() const;
 
   using element_iterator = ArrayRef<uint64_t>::iterator;
 

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 002687b9375a3..ac7a316398441 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 90484f1f60658..7a28bcb08ba42 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<DIExpression *>()) {
-      if (BE->isSignedConstant()) {
+      if (BE->isConstant() &&
+          DIExpression::SignedOrUnsignedConstant::SignedConstant ==
+              *BE->isConstant()) {
         if (Attr != dwarf::DW_AT_lower_bound || DefaultLowerBound == -1 ||
             static_cast<int64_t>(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 d5f8f3bdc1da3..174fed27671af 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<DIExpression>(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 f003ec9557c73..1299acdc4723d 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -1458,25 +1458,31 @@ Optional<DIExpression *> 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::SignedOrUnsignedConstant>
+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 0000000000000..bf23beccc7318
--- /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 0000000000000..9b9961568174d
--- /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 479625b6df8fe..b1cfd3284f9be 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: "<stdin>", 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 d9b21d4a60fd5..cfb4e6c348b01 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)


        


More information about the llvm-commits mailing list