1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[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
This commit is contained in:
Sourabh Singh Tomar 2021-03-24 17:54:05 +05:30
parent 6f2c43f053
commit 8252baa8c1
9 changed files with 122 additions and 29 deletions

View File

@ -2582,11 +2582,10 @@ public:
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;

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
};

View File

@ -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 {
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;
// 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;
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,

View File

@ -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}

View File

@ -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}

View File

@ -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}

View File

@ -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)