Location list created for the following test case is incomplete for parameter
"p1":

cc1 -v -dD fs.c -dA -m64 -mcmodel=small -gdwarf-2 -O2 -fno-omit-frame-pointer
-quiet

typedef struct s2 {
   unsigned short f1;
   unsigned short length;
   char data[64];
} s2;

int func(s2 *p1, const char *p2)
{
   if (((_LogEffectiveLevel(57)) >= (3))) {
     _Log("abc",
        (__FUNCTION__+((__FUNCTION__[(sizeof("FSS") - 1)] == '_') ?
(sizeof("FSS") - 1) + 1 : (sizeof("FSS") - 1))),
        237 ,
        (p1)->f1,
        (p1)->length,
        *((unsigned int *)(&(p1)->data[0])),
        *((unsigned int *)(&(p1)->data[4])),
        *((unsigned int *)(&(p1)->data[8])),
        *((unsigned int *)(&(p1)->data[12])),
        *((unsigned int *)(&(p1)->data[16])),
        *((unsigned int *)(&(p1)->data[20])),
        *((unsigned int *)(&(p1)->data[24])),
        *((unsigned int *)(&(p1)->data[28])),
        *((unsigned long *)(&(p1)->data[32])),
        *((unsigned long *)(&(p1)->data[40])),
        *((unsigned long *)(&(p1)->data[48])),
        *((unsigned long *)(&(p1)->data[56])), p2);
   }
   return 0;
}

The generated assembly shows the following:
  .uleb128 0xb    # (DIE (0xb2) DW_TAG_formal_parameter)
  .ascii "p1\0"   # DW_AT_name
  .byte   0x1     # DW_AT_decl_file (fs.c)
  .byte   0x8     # DW_AT_decl_line
  .long   0xea    # DW_AT_type
  .long   .LLST1  # DW_AT_location

.LLST1:
  .quad   .LVL0-.Ltext0   # Location list begin address (*.LLST1)
  .quad   .LVL1-.Ltext0   # Location list end address (*.LLST1)
  .value  0x1             # Location expression size
  .byte   0x55            # DW_OP_reg5
  .quad   .LVL1-.Ltext0   # Location list begin address (*.LLST1)
  .quad   .LVL2-.Ltext0   # Location list end address (*.LLST1)
  .value  0x1             # Location expression size
  .byte   0x5b            # DW_OP_reg11
  .quad   .LVL4-.Ltext0   # Location list begin address (*.LLST1)
  .quad   .LVL5-.Ltext0   # Location list end address (*.LLST1)
  .value  0x1             # Location expression size
  .byte   0x5b            # DW_OP_reg11
  .quad   0x0             # Location list terminator begin (*.LLST1)
  .quad   0x0             # Location list terminator end (*.LLST1)

This does not cover instructions between .LVL2 and .LVL4.
Looking at the assembly, you see that R11 is being saved to the stack across
the call to _LogEffectiveLevel() and then reloaded *before* .LVL4:

        # fs.c:10
.LM4:
        movq    %r11, -48(%rbp)
.LVL2:
        call    _LogEffectiveLevel
.LVL3:
        cmpl    $2, %eax
        movq    -48(%rbp), %r11
        jle     .L2
        # basic block 3
        # fs.c:11
.LM5:
        movl    28(%r11), %ecx
.LVL4:
        movq    60(%r11), %rax
        movq    52(%r11), %rdx

So when gdb is stopped at line fs.c:11 it reports that p1's <value is optimized
out>.

I debugged var-tracking.c, and it does not look like it is tracking duplicate
locations, such as when a register is saved and restored from the stack.
It's also possible that one of the previous passes does not give enough
information to var-tracking.c about the variable being saved/restored.
I can see the following in the var tracking output:

(insn:TI 7 102 107 2 fs.c:10 (set (reg:SI 5 di)
        (const_int 57 [0x39])) 47 {*movsi_1} (nil))

(note 107 7 83 2 ( p1 (expr_list:REG_DEP_TRUE (reg/v/f:DI 40 r11 [orig:75 p1 ]
[75])
    (const_int 0 [0x0]))) NOTE_INSN_VAR_LOCATION)
....
(insn 78 90 108 2 fs.c:10 (set (mem/c:DI (plus:DI (reg/f:DI 6 bp)
                (const_int -48 [0xffffffffffffffd0])) [10 S8 A8])
        (reg:DI 40 r11)) 89 {*movdi_1_rex64} (expr_list:REG_DEAD (reg:DI 40
r11)
        (nil)))

(note 108 78 9 2 ( p1 (nil)) NOTE_INSN_VAR_LOCATION)
....
(insn 79 11 12 2 fs.c:10 (set (reg:DI 40 r11)
        (mem/c:DI (plus:DI (reg/f:DI 6 bp)
                (const_int -48 [0xffffffffffffffd0])) [10 S8 A8])) 89
{*movdi_1_rex64} (nil))

It seems that when r11 is saved in insn 78 and reloaded in insn 79 it is not
marked as containing "p1".
Unfortunately I don't have enough knowledge to continue debugging gcc to be
sure it's var-tracking.c or someone else's fault.

This happens with gcc 4.2.3 and gcc 4.3.0.
It does not happen with -O1, or if I remove even a single parameter from the
call to _LogEffectiveLevel().
However we observe a lot of <value optimized out> messages in other parts of
our code, and most of the time I tracked it to incomplete info in the location
list.

I hope this is enough information. Let me know if you need more.
Thanks,
Giampiero Caprino


-- 
           Summary: location list incomplete for spilled registers
           Product: gcc
           Version: 4.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: gcaprino at gmail dot com
  GCC host triplet: host-i686-pc-linux-gnu
GCC target triplet: x86_64-linux


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36303

Reply via email to