summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikael Holmen <mikael.holmen@ericsson.com>2018-01-29 12:37:30 +0000
committerMikael Holmen <mikael.holmen@ericsson.com>2018-01-29 12:37:30 +0000
commita9e31537af5d70ad2d71b80a71ea42c89a7f2ba7 (patch)
tree3eb9869ef00c0e45ef8e3012a6c0b21da0363711
parent865de57bde1b3fa0184679c93ebb9127c3f0f1e1 (diff)
downloadbcm5719-llvm-a9e31537af5d70ad2d71b80a71ea42c89a7f2ba7.tar.gz
bcm5719-llvm-a9e31537af5d70ad2d71b80a71ea42c89a7f2ba7.zip
[DebugInfo] Fix fragment offset emission order for symbol locations
Summary: When emitting the location for a global variable with fragmented debug expressions, make sure that the offset pieces, which represent optimized-out parts of the variable, are emitted before their succeeding fragments' expressions. Previously, if the succeeding fragment's location was a symbol, the offset piece was emitted after, rather than before, that symbol's expression. This effectively meant that the symbols were associated with the wrong parts of the variable. This fixes PR36085. Patch by: David Stenberg Reviewers: aprantl, probinson, dblaikie Reviewed By: aprantl Subscribers: JDevlieghere, llvm-commits Tags: #debug-info Differential Revision: https://reviews.llvm.org/D42527 llvm-svn: 323644
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp7
-rw-r--r--llvm/test/DebugInfo/X86/fragment-offset-order.ll62
2 files changed, 66 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index c009adc1e50..3cde5ad38ce 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -191,6 +191,9 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
DwarfExpr = llvm::make_unique<DIEDwarfExpression>(*Asm, *this, *Loc);
}
+ if (Expr)
+ DwarfExpr->addFragmentOffset(Expr);
+
if (Global) {
const MCSymbol *Sym = Asm->getSymbol(Global);
if (Global->isThreadLocal()) {
@@ -226,10 +229,8 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
addOpAddress(*Loc, Sym);
}
}
- if (Expr) {
- DwarfExpr->addFragmentOffset(Expr);
+ if (Expr)
DwarfExpr->addExpression(Expr);
- }
}
if (Loc)
addBlock(*VariableDIE, dwarf::DW_AT_location, DwarfExpr->finalize());
diff --git a/llvm/test/DebugInfo/X86/fragment-offset-order.ll b/llvm/test/DebugInfo/X86/fragment-offset-order.ll
new file mode 100644
index 00000000000..31117f69d22
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/fragment-offset-order.ll
@@ -0,0 +1,62 @@
+; RUN: llc -dwarf-version=4 -filetype=obj -O0 \
+; RUN: -mtriple=x86_64-unknown-linux-gnu < %s \
+; RUN: | llvm-dwarfdump -v - | FileCheck %s
+
+; Verify that the empty DW_OP_piece operations that are created for the
+; optimized-out struct fields `foo' and `baz' are emitted before their
+; succeeding fields' symbol location expressions.
+
+; Test file based on foo.c:
+;
+; struct {
+; long foo;
+; void *bar;
+; long baz;
+; void *qux;
+; } static var;
+;
+; void *ptr;
+;
+; int main() {
+; if (var.foo == 0)
+; var.bar = var.qux = ptr;
+; return 0;
+; }
+;
+; which was built using:
+;
+; clang -O0 -g2 -S -emit-llvm foo.c -o foo.ll
+; opt -S -globalopt foo.ll -o foo.opt.ll
+
+; CHECK: DW_AT_name {{.*}}"var"
+; CHECK: DW_AT_location [DW_FORM_exprloc] (DW_OP_piece 0x8, DW_OP_addr 0x0, DW_OP_piece 0x8, DW_OP_piece 0x8, DW_OP_addr 0x0, DW_OP_piece 0x8)
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@var.1 = internal unnamed_addr global i8* null, align 8, !dbg !0
+@var.3 = internal unnamed_addr global i8* null, align 8, !dbg !15
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!16, !17}
+!llvm.ident = !{!18}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_LLVM_fragment, 64, 64))
+!1 = distinct !DIGlobalVariable(name: "var", scope: !2, file: !3, line: 15, type: !7, isLocal: true, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 7.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5)
+!3 = !DIFile(filename: "foo.c", directory: "/")
+!4 = !{}
+!5 = !{!6}
+!6 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, file: !3, line: 10, size: 256, elements: !8)
+!8 = !{!9, !11, !13, !14}
+!9 = !DIDerivedType(tag: DW_TAG_member, name: "foo", scope: !7, file: !3, line: 11, baseType: !10, size: 64)
+!10 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed)
+!11 = !DIDerivedType(tag: DW_TAG_member, name: "bar", scope: !7, file: !3, line: 12, baseType: !12, size: 64, offset: 64)
+!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!13 = !DIDerivedType(tag: DW_TAG_member, name: "baz", scope: !7, file: !3, line: 13, baseType: !10, size: 64, offset: 128)
+!14 = !DIDerivedType(tag: DW_TAG_member, name: "qux", scope: !7, file: !3, line: 14, baseType: !12, size: 64, offset: 192)
+!15 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_LLVM_fragment, 192, 64))
+!16 = !{i32 2, !"Dwarf Version", i32 4}
+!17 = !{i32 2, !"Debug Info Version", i32 3}
+!18 = !{!"clang version 7.0.0"}
OpenPOWER on IntegriCloud