[llvm] f13f050 - [DebugInfo] Support for signed constants inside DIExpression
Sourabh Singh Tomar via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 12 02:55:57 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