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:
parent
6f2c43f053
commit
8252baa8c1
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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,
|
||||
|
31
test/DebugInfo/X86/global-constants.ll
Normal file
31
test/DebugInfo/X86/global-constants.ll
Normal 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}
|
17
test/DebugInfo/X86/invalid-global-constants.ll
Normal file
17
test/DebugInfo/X86/invalid-global-constants.ll
Normal 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}
|
@ -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}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user