[llvm] r239380 - [DWARF] Fix a few corner cases in expression emission

David Blaikie dblaikie at gmail.com
Thu Jun 25 14:26:12 PDT 2015


On Wed, Jun 10, 2015 at 8:16 PM, Keno Fischer <kfischer at college.harvard.edu>
wrote:

> Well, I found what the problem is, but I'm not really sure how to fix it
> properly.
>
> Basically, the code for that function ends up looking like
>
> DBG_VALUE %RDI, %noreg, !"d", <<0x3cd2840>>; line no:59
> DBG_VALUE %EDI, %noreg, !"d", <<0x3cd2840>>; line no:59
> MOV32mr %RIP, 1, %noreg, <ga:@values>, %noreg, %EDI, %RDI<imp-use,kill>;
> mem:ST4[getelementptr inbounds ([50 x %struct.some_struct], [50 x
> %struct.some_struct]* @values, i64 0, i64 0, i32
> 0)](align=16)(tbaa=<0x3cdd0b8>) dbg:break1.c:59:43
> RETQ; dbg:break1.c:59:48
>
> so when we emit DWARF information we used to first emit an empty range for
> RDI and then have EDI cover the rest of the function. I see why the second
> DBG_VALUE was inserted by LLVM (the 32bit subregister could be a different
> one, so having that information could increase debug info coverage). I
> think the best way to fix this would be to implement the ability to
> represent values that are simultaneously in multiple places ( I want this
> for other reasons too, but it seems to me that that would fix this
> situation quite elegantly ). Basically what I had in mind is separating the
> notion of a value being present somewhere and having been given a new
> value. Right now DBG_VALUE is doing both, which is causing the current
> situation. If instead the code generator knew that `d` is present in both
> RDI and EDI, it could figure out the most optimal debug information for
> this function, which is that `d` is in RDI for the entire function. Anyway,
> I would like to discuss this and will bring it up in the llvmdev thread
> that Adrian was intending to start. For now, I'll put this change on ice
> until a proper solution is found.
>

So how did these two DBG_VALUEs produce a failure in the test case? I
assume the live range ended prematurely at the end of a basic block when it
was live over multiple basic blocks (this is the common limitation with our
debug variable location tracking)? Even if it was just one DBG_VALUE, this
issue would still be a problem.

I'm not sure why DBG_VALUE %RDI, DBG_VALUE %EDI would produce a worse
experience than DBG_VALUE %RDI, I guess?


>
> On Tue, Jun 9, 2015 at 2:06 PM, David Blaikie <dblaikie at gmail.com> wrote:
>
>>
>>
>> On Mon, Jun 8, 2015 at 9:05 PM, David Blaikie <dblaikie at gmail.com> wrote:
>>
>>> Looks like this might've caused:
>>>
>>> http://lab.llvm.org:8011/builders/clang-x86_64-ubuntu-gdb-75/builds/22562
>>>
>>
>> Reverted in r239420 to hopefully get the buildbot back to green.
>>
>>
>>>
>>>
>>> On Mon, Jun 8, 2015 at 6:54 PM, Keno Fischer <
>>> kfischer at college.harvard.edu> wrote:
>>>
>>>> Author: kfischer
>>>> Date: Mon Jun  8 20:53:59 2015
>>>> New Revision: 239380
>>>>
>>>> URL: http://llvm.org/viewvc/llvm-project?rev=239380&view=rev
>>>> Log:
>>>> [DWARF] Fix a few corner cases in expression emission
>>>>
>>>> Summary: I noticed an object file with `DW_OP_reg4 DW_OP_breg4 0` as a
>>>> DWARF expression,
>>>> which I traced to a missing break (and `++I`) in this code snippet.
>>>> While I was at it, I also added support for a few other corner cases
>>>> along the same lines that I could think of.
>>>>
>>>> Test Plan: Hand-crafted test case to exercises these cases is included.
>>>>
>>>> Reviewers: echristo, dblaikie, aprantl
>>>>
>>>> Reviewed By: aprantl
>>>>
>>>> Subscribers: llvm-commits
>>>>
>>>> Differential Revision: http://reviews.llvm.org/D10302
>>>>
>>>> Added:
>>>>     llvm/trunk/test/DebugInfo/expressions.ll
>>>> Modified:
>>>>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
>>>>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
>>>>     llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h
>>>>
>>>> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=239380&r1=239379&r2=239380&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original)
>>>> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Mon Jun  8
>>>> 20:53:59 2015
>>>> @@ -1562,6 +1562,8 @@ void DwarfDebug::emitDebugLoc() {
>>>>      Asm->OutStreamer->EmitLabel(List.Label);
>>>>      const DwarfCompileUnit *CU = List.CU;
>>>>      for (const auto &Entry : DebugLocs.getEntries(List)) {
>>>> +       if (Entry.BeginSym == Entry.EndSym)
>>>> +        continue;
>>>>        // Set up the range. This range is relative to the entry point
>>>> of the
>>>>        // compile unit. This is a hard coded 0 for low_pc when we're
>>>> emitting
>>>>        // ranges, or the DW_AT_low_pc on the compile unit otherwise.
>>>>
>>>> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp?rev=239380&r1=239379&r2=239380&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp (original)
>>>> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp Mon Jun  8
>>>> 20:53:59 2015
>>>> @@ -65,6 +65,11 @@ void DwarfExpression::AddShr(unsigned Sh
>>>>    EmitOp(dwarf::DW_OP_shr);
>>>>  }
>>>>
>>>> +void DwarfExpression::AddOpStackValue() {
>>>> +  if (DwarfVersion >= 4)
>>>> +    EmitOp(dwarf::DW_OP_stack_value);
>>>> +}
>>>> +
>>>>  bool DwarfExpression::AddMachineRegIndirect(unsigned MachineReg, int
>>>> Offset) {
>>>>    if (isFrameRegister(MachineReg)) {
>>>>      // If variable offset is based in frame register then use fbreg.
>>>> @@ -172,16 +177,14 @@ void DwarfExpression::AddSignedConstant(
>>>>    // value, so the producers and consumers started to rely on
>>>> heuristics
>>>>    // to disambiguate the value vs. location status of the expression.
>>>>    // See PR21176 for more details.
>>>> -  if (DwarfVersion >= 4)
>>>> -    EmitOp(dwarf::DW_OP_stack_value);
>>>> +  AddOpStackValue();
>>>>  }
>>>>
>>>>  void DwarfExpression::AddUnsignedConstant(unsigned Value) {
>>>>    EmitOp(dwarf::DW_OP_constu);
>>>>    EmitUnsigned(Value);
>>>>    // cf. comment in DwarfExpression::AddSignedConstant().
>>>> -  if (DwarfVersion >= 4)
>>>> -    EmitOp(dwarf::DW_OP_stack_value);
>>>> +  AddOpStackValue();
>>>>  }
>>>>
>>>>  static unsigned getOffsetOrZero(unsigned OffsetInBits,
>>>> @@ -212,15 +215,30 @@ bool DwarfExpression::AddMachineRegExpre
>>>>                 getOffsetOrZero(OffsetInBits, PieceOffsetInBits));
>>>>    }
>>>>    case dwarf::DW_OP_plus: {
>>>> -    // [DW_OP_reg,Offset,DW_OP_plus,DW_OP_deref] -->
>>>> [DW_OP_breg,Offset].
>>>>      auto N = I.getNext();
>>>> +    unsigned Offset = I->getArg(0);
>>>> +    // First combine all DW_OP_plus until we hit either a DW_OP_deref
>>>> or a
>>>> +    // DW_OP_bit_piece
>>>> +    while (N != E && N->getOp() == dwarf::DW_OP_plus) {
>>>> +      Offset += N->getArg(0);
>>>> +      ++I;
>>>> +      N = I.getNext();
>>>> +    }
>>>>      if (N != E && N->getOp() == dwarf::DW_OP_deref) {
>>>> -      unsigned Offset = I->getArg(0);
>>>> +      // [DW_OP_reg,Offset,DW_OP_plus,DW_OP_deref] -->
>>>> [DW_OP_breg,Offset].
>>>>        ValidReg = AddMachineRegIndirect(MachineReg, Offset);
>>>>        std::advance(I, 2);
>>>> -      break;
>>>> -    } else
>>>> -      ValidReg = AddMachineRegPiece(MachineReg);
>>>> +    } else {
>>>> +      assert ((N == E) || (N->getOp() == dwarf::DW_OP_bit_piece));
>>>> +      if (Offset == 0) {
>>>> +        ValidReg = AddMachineRegPiece(MachineReg);
>>>> +      } else {
>>>> +        ValidReg = AddMachineRegIndirect(MachineReg, Offset);
>>>> +        AddOpStackValue();
>>>> +      }
>>>> +      ++I;
>>>> +    }
>>>> +    break;
>>>>    }
>>>>    case dwarf::DW_OP_deref: {
>>>>        // [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg].
>>>> @@ -237,6 +255,7 @@ bool DwarfExpression::AddMachineRegExpre
>>>>
>>>>    // Emit remaining elements of the expression.
>>>>    AddExpression(I, E, PieceOffsetInBits);
>>>> +
>>>>    return true;
>>>>  }
>>>>
>>>>
>>>> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h?rev=239380&r1=239379&r2=239380&view=diff
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h (original)
>>>> +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h Mon Jun  8
>>>> 20:53:59 2015
>>>> @@ -83,6 +83,9 @@ public:
>>>>    bool AddMachineRegPiece(unsigned MachineReg, unsigned
>>>> PieceSizeInBits = 0,
>>>>                            unsigned PieceOffsetInBits = 0);
>>>>
>>>> +  /// Emit a DW_OP_stack_value
>>>> +  void AddOpStackValue();
>>>> +
>>>>    /// Emit a signed constant.
>>>>    void AddSignedConstant(int Value);
>>>>    /// Emit an unsigned constant.
>>>>
>>>> Added: llvm/trunk/test/DebugInfo/expressions.ll
>>>> URL:
>>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/expressions.ll?rev=239380&view=auto
>>>>
>>>> ==============================================================================
>>>> --- llvm/trunk/test/DebugInfo/expressions.ll (added)
>>>> +++ llvm/trunk/test/DebugInfo/expressions.ll Mon Jun  8 20:53:59 2015
>>>> @@ -0,0 +1,110 @@
>>>> +; REQUIRES: object-emission
>>>> +; RUN: %llc_dwarf -mtriple x86_64-apple-darwin14.0.0-elf -filetype=obj
>>>> %s -o %t
>>>> +; RUN: %llc_dwarf -mtriple x86_64-apple-darwin14.0.0-elf -O0
>>>> -filetype=obj %s -o %t0
>>>> +; RUN: llvm-dwarfdump -debug-dump=loc %t | FileCheck %s
>>>> +; RUN: llvm-dwarfdump -debug-dump=loc %t0 | FileCheck -check-prefix
>>>> CHECK-O0 %s
>>>> +
>>>> +; CHECK: 0x00000000: Beginning address offset: 0x0000000000000000
>>>> +; CHECK:                Ending address offset: 0x[[END:[0-9a-f]+]]
>>>> +; CHECK:                 Location description:
>>>> +; CHECK-NOT:                                   75 00 55
>>>> +; CHECK-SAME:                                  55
>>>> +; CHECK: 0x00000023: Beginning address offset: 0x0000000000000000
>>>> +; CHECK:                Ending address offset: 0x{{.*}}[[END]]
>>>> +; CHECK:                 Location description: 75 08 9f
>>>> +; CHECK: 0x00000048: Beginning address offset: 0x0000000000000000
>>>> +; CHECK:                Ending address offset: 0x{{.*}}[[END]]
>>>> +; CHECK:                 Location description: 75 10 9f
>>>> +; CHECK: 0x0000006d: Beginning address offset: 0x0000000000000000
>>>> +; CHECK:                Ending address offset: 0x{{.*}}[[END]]
>>>> +; CHECK:                 Location description: 75 18
>>>> +
>>>> +
>>>> +; CHECK-O0: 0x00000000: Beginning address offset: 0x0000000000000000
>>>> +; CHECK-O0:                Ending address offset: 0x000000000000001b
>>>> +; CHECK-O0:                 Location description: 55
>>>> +; CHECK-O0:             Beginning address offset: 0x000000000000001b
>>>> +; CHECK-O0:                Ending address offset: 0x0000000000000024
>>>> +; CHECK-O0:                 Location description: 54
>>>> +; CHECK-O0:             Beginning address offset: 0x0000000000000024
>>>> +; CHECK-O0:                Ending address offset: 0x0000000000000025
>>>> +; CHECK-O0:                 Location description: 77 78 23 00
>>>> +; CHECK-O0: 0x0000004c: Beginning address offset: 0x0000000000000000
>>>> +; CHECK-O0:                Ending address offset: 0x000000000000001b
>>>> +; CHECK-O0:                 Location description: 75 08 9f
>>>> +; CHECK-O0:             Beginning address offset: 0x000000000000001b
>>>> +; CHECK-O0:                Ending address offset: 0x0000000000000024
>>>> +; CHECK-O0:                 Location description: 74 08 9f
>>>> +; CHECK-O0:             Beginning address offset: 0x0000000000000024
>>>> +; CHECK-O0:                Ending address offset: 0x0000000000000025
>>>> +; CHECK-O0:                 Location description: 77 78 23 08
>>>> +; CHECK-O0: 0x0000009c: Beginning address offset: 0x0000000000000000
>>>> +; CHECK-O0:                Ending address offset: 0x000000000000001b
>>>> +; CHECK-O0:                 Location description: 75 10 9f
>>>> +; CHECK-O0:             Beginning address offset: 0x000000000000001b
>>>> +; CHECK-O0:                Ending address offset: 0x0000000000000024
>>>> +; CHECK-O0:                 Location description: 74 10 9f
>>>> +; CHECK-O0:             Beginning address offset: 0x0000000000000024
>>>> +; CHECK-O0:                Ending address offset: 0x0000000000000025
>>>> +; CHECK-O0:                 Location description: 77 78 23 08 23 08
>>>> +; CHECK-O0: 0x000000ee: Beginning address offset: 0x0000000000000000
>>>> +; CHECK-O0:                Ending address offset: 0x000000000000001b
>>>> +; CHECK-O0:                 Location description: 75 18
>>>> +; CHECK-O0:             Beginning address offset: 0x000000000000001b
>>>> +; CHECK-O0:                Ending address offset: 0x0000000000000024
>>>> +; CHECK-O0:                 Location description: 74 18
>>>> +; CHECK-O0:             Beginning address offset: 0x0000000000000024
>>>> +; CHECK-O0:                Ending address offset: 0x0000000000000025
>>>> +; CHECK-O0:                 Location description: 77 78 23 10 23 08 06
>>>> +
>>>> +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #0
>>>> +
>>>> +define float @foo(float* %args, float *%args2)
>>>> +{
>>>> +    call void @llvm.dbg.value(metadata float* %args, i64 0, metadata
>>>> !11, metadata !12), !dbg !19
>>>> +    call void @llvm.dbg.value(metadata float* %args, i64 0, metadata
>>>> !13, metadata !14), !dbg !19
>>>> +    call void @llvm.dbg.value(metadata float* %args, i64 0, metadata
>>>> !15, metadata !16), !dbg !19
>>>> +    call void @llvm.dbg.value(metadata float* %args, i64 0, metadata
>>>> !17, metadata !18), !dbg !19
>>>> +    %a = load float, float* %args, !dbg !19
>>>> +    %bptr = getelementptr float, float* %args, i32 1, !dbg !19
>>>> +    %b = load float, float* %bptr, !dbg !19
>>>> +    %cptr = getelementptr float, float* %args, i32 2, !dbg !19
>>>> +    %c = load float, float* %cptr, !dbg !19
>>>> +    %dptr = getelementptr float, float* %args, i32 3, !dbg !19
>>>> +    %d = load float, float* %dptr, !dbg !19
>>>> +    %ret1 = fadd float %a, %b, !dbg !19
>>>> +    %ret2 = fadd float %c, %d, !dbg !19
>>>> +    call void @llvm.dbg.value(metadata float* %args2, i64 0, metadata
>>>> !11, metadata !12), !dbg !19
>>>> +    call void @llvm.dbg.value(metadata float* %args2, i64 0, metadata
>>>> !13, metadata !14), !dbg !19
>>>> +    call void @llvm.dbg.value(metadata float* %args2, i64 0, metadata
>>>> !15, metadata !16), !dbg !19
>>>> +    call void @llvm.dbg.value(metadata float* %args2, i64 0, metadata
>>>> !17, metadata !18), !dbg !19
>>>> +    %ret  = fsub float %ret1, %ret2, !dbg !19
>>>> +    ret float %ret, !dbg !19
>>>> +}
>>>> +
>>>> +attributes #0 = { nounwind readnone }
>>>> +
>>>> +!llvm.module.flags = !{!0, !1}
>>>> +!llvm.dbg.cu = !{!2}
>>>> +
>>>> +!0 = !{i32 2, !"Dwarf Version", i32 4}
>>>> +!1 = !{i32 1, !"Debug Info Version", i32 3}
>>>> +
>>>> +!2 = !DICompileUnit(language: DW_LANG_C89, file: !3, producer:
>>>> "byHand", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !4,
>>>> retainedTypes: !4, subprograms: !5, globals: !4, imports: !4)
>>>> +!3 = !DIFile(filename: "expressions", directory: ".")
>>>> +!4 = !{}
>>>> +!5 = !{!6}
>>>> +!6 = !DISubprogram(name: "foo", linkageName: "foo", scope: null, file:
>>>> !3, type: !7, isLocal: false, isDefinition: true, isOptimized: true,
>>>> function: float (float*, float*)* @foo, variables: !4)
>>>> +!7 = !DISubroutineType(types: !8)
>>>> +!8 = !{!10, !10}
>>>> +!9 = !DIBasicType(name: "float", size: 4, align: 4, encoding:
>>>> DW_ATE_float)
>>>> +!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64,
>>>> align: 64)
>>>> +!11 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "a", arg: 1,
>>>> scope: !6, file: !3, line: 1, type: !10)
>>>> +!12 = !DIExpression(DW_OP_plus, 0)
>>>> +!13 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "b", arg: 2,
>>>> scope: !6, file: !3, line: 1, type: !10)
>>>> +!14 = !DIExpression(DW_OP_plus, 8)
>>>> +!15 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "c", arg: 3,
>>>> scope: !6, file: !3, line: 1, type: !10)
>>>> +!16 = !DIExpression(DW_OP_plus, 8, DW_OP_plus, 8)
>>>> +!17 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "d", arg: 4,
>>>> scope: !6, file: !3, line: 1, type: !9)
>>>> +!18 = !DIExpression(DW_OP_plus, 16, DW_OP_plus, 8, DW_OP_deref)
>>>> +!19 = !DILocation(line: 1, scope: !6)
>>>>
>>>>
>>>> _______________________________________________
>>>> llvm-commits mailing list
>>>> llvm-commits at cs.uiuc.edu
>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>>>
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150625/02428d8b/attachment.html>


More information about the llvm-commits mailing list