Bug List: (This bug is not in your last search results)   Show last search results      Search page      Enter new bug
Bug#: 27192
Product:  
Component:  
Status: NEW
Resolution:
Assigned To: Not yet assigned to anyone <unassigned@gcc.gnu.org>
Host:
Reported against  
Priority:  
Severity:  
Target Milestone:  
 
 
Target:
Reporter: John Regehr <regehr@cs.utah.edu>
Add CC:
CC:
Remove selected CCs
Build:
URL:
Summary:
Keywords:
Known to work:
Known to fail:

Attachment Description Type Created Size Actions
shifty3.i Pre-processed testcase. text/plain 2007-04-04 00:24 219 bytes Edit
shifty3.dis Disassembly of the shifty3.i test case. text/plain 2007-04-04 00:25 879 bytes Edit
Create a New Attachment (proposed patch, testcase, etc.) View All

Bug 27192 depends on: Show dependency tree
Show dependency graph
Bug 27192 blocks:

Additional Comments:





Mark bug as waiting for feedback
Mark bug as suspended




View Bug Activity   |   Format For Printing   |   Clone This Bug


Description:   Last confirmed: 2007-05-30 19:23 Opened: 2006-04-18 05:32
The program below confuses gcc in such a way that it generates code loading the
byte-address of bar() into the Z register, which causes icall to jump off to
neverneverland.  Rather, the double-byte address of bar() should be loaded into
Z before the indirect call.

This bug is also present in gcc 4.0.3 and 3.4.3.

avr-gcc -v gives:

Target: avr
Configured with: ../gcc-4.1.0/configure --prefix=/home/regehr/gcc-4.1.0-avr-bin
--disable-libssp --disable-nls --target=avr
Thread model: single
gcc version 4.1.0

Compile with:

  avr-gcc -Os -Wall shifty.c -o shifty.elf

Program:

struct fseqp_void
{
    void (*p) (void);
    char *e;
};

struct fseqp_void c[2];

void bar (void)
{
}

void foo (void)
{
    int i;
    for (i=0; i<32; i++);
}

int main (void)
{
    c[0].e = (char *)bar + 2;
    c[0].p = bar;
    foo ();
    struct fseqp_void x = c[0];
    void (*start) (void) = x.p;
    (*start)();
    return 0;
}

------- Comment #1 From Eric Weddington 2007-03-30 19:55 -------
Dr. John,

Can you provide additional information:
- What AVR processor was this compiled for? You don't have the required -mmcu=
flag in your command line.

- Can you provide a disassembly listing showing the problem?

I don't necessarily see the problem with my 4.1.1 compiler, -mmcu=atmega128.
Maybe I'm just dense.

Eric

------- Comment #2 From Eric Weddington 2007-04-04 00:24 -------
Created an attachment (id=13324) [edit]
Pre-processed testcase.

------- Comment #3 From Eric Weddington 2007-04-04 00:25 -------
Created an attachment (id=13325) [edit]
Disassembly of the shifty3.i test case.

------- Comment #4 From Eric Weddington 2007-04-04 00:38 -------
Confirmed bug.

shifty3.i is a test case showing the problem. Compiled with avr-gcc 4.1.2,
with:
avr-gcc -Os shifty.c -o shifty.o

shifty3.dis is a disassembly of shifty.o (with avr-objdump -d shifty.o).

The problem is exhibited here:

0000005a <main>:
  5a:   89 e2           ldi     r24, 0x29       ; 41
  5c:   90 e0           ldi     r25, 0x00       ; 0
  5e:   90 93 61 00     sts     0x0061, r25
  62:   80 93 60 00     sts     0x0060, r24
  66:   82 e5           ldi     r24, 0x52       ; 82
  68:   92 e0           ldi     r25, 0x02       ; 2
  6a:   90 93 64 00     sts     0x0064, r25
  6e:   80 93 63 00     sts     0x0063, r24
  72:   e0 91 60 00     lds     r30, 0x0060
  76:   f0 91 61 00     lds     r31, 0x0061
  7a:   09 95           icall
  7c:   e0 91 63 00     lds     r30, 0x0063
  80:   f0 91 64 00     lds     r31, 0x0064
  84:   09 95           icall

The correct word address of the function foo is taken and stored (address 5a to
62), but then the *byte* address of the function foo is taken, and an offset
added, and stored (address 66 to 6e). The following indirect call (address 7c
to 84) is then incorrect. The PC has to be a *word* address.

Adding a fixed offset to a function pointer, and then doing an indirect call,
is valid in an AVR application as it is possible to copy or place functions at
fixed offsets like this.

Please mark this bug as NEW.
Known to fail: 4.1.1, 4.1.2

------- Comment #5 From Eric Weddington 2007-05-30 19:23 -------
Bug still present in 4.2.0, and 4.3-20070525.

To test bug (fixed from last comment):
avr-gcc -Os shifty3.i -o shifty3.o
avr-objdump -d shifty3.o > shifty3.dis
Compare output.

------- Comment #6 From Wouter van Gulik 2008-01-20 19:30 -------
Bug is still present in 4.2.2.

Some more info:

I rewrote the example to (atleast for me) little more clear example.

struct fseqp_void
{
    void (*p) (void);
    char *e;
};

struct fseqp_void c;

void bar (void){}

int main (void)
{
    c.e = (char *)bar + 2;
    c.p = bar;
    c.p();
    return 0;
}

The problem is the re-use after loading bar into the struct:

        ldi r24,lo8(bar+2)          <<Hmm this should need gs() I guess
        ldi r25,hi8(bar+2)
        sts (c+2)+1,r25
        sts c+2,r24
        sbiw r24,2                  <<Sub 2, but we also need a shift!
        sts (c)+1,r25
        sts c,r24

However if comment out the dump the load off the variable e, then all is well

int main (void)
{
    //c.e = (char *)bar + 2;
    c.p = bar;
    c.p();
    return 0;
}

        ldi r24,lo8(gs(bar))
        ldi r25,hi8(gs(bar))
        sts (c)+1,r25
        sts c,r24
        ldi r24,lo8(0)
        ldi r25,hi8(0)

And if the order of assigment is reverted then all is well also

    c.e = (char *)bar + 2;
    c.p = bar;
    c.p();
    return 0;

        ldi r24,lo8(gs(bar))
        ldi r25,hi8(gs(bar))
        sts (c)+1,r25
        sts c,r24
        adiw r24,2
        sts (c+2)+1,r25
        sts c+2,r24
        ldi r24,lo8(0)
        ldi r25,hi8(0)

So the problem is the optimizer, which forget that the 16-bit program address
is different from the data address.

Bug List: (This bug is not in your last search results)   Show last search results      Search page      Enter new bug