AVR C calling convention not matching spec

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

AVR C calling convention not matching spec

Dylan McKay
Hey all,

I'm working on the AVR backend for LLVM.

I'm looking into an issue where the current LLVM implementation of the AVR C calling convention is not matching the assembly of what GCC is generating.

On top of that, when I run through the argument algorithm described on the Wiki (https://gcc.gnu.org/wiki/avr-gcc), GCC output doesn't seem to match up, whereas LLVM does.

The shortest and most inaccurate version of it is: GCC only stores up to 8 bytes of arguments in registers, and every argument after that is located on the stack. The Wiki says that registers between r8-r25 are used, which doesn't seem to match up.

Example: Given a function which takes two 64-bit integers (i64 %a, i64 %b)
* Start with Rn = 26
* Begin processing %a
  * Rn -= 8 = 18
  * Rn >= 8, therefore this argument will be stored in registers r18-r25
* Begin processing %b
  * Rn -= 8 = 10
  * Rn >= 8, therefore this argument will be stored in registers r10-r17

This indicates that both arguments should be located in registers, but AVR-GCC stores the first argument in registers, and the second argument on the stack.

Which is correct? Am I misunderstanding the algorithm?

Where in GCC can I find the implementation of this calling convention?

I've got an issue on the LLVM bug tracker here (https://llvm.org/bugs/show_bug.cgi?id=31347).

Cheers,
Dylan

_______________________________________________
AVR-GCC-list mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: AVR C calling convention not matching spec

Pitchumani Sivanupandi-2
On Sunday 11 December 2016 07:13 AM, Dylan McKay wrote:

> Hey all,
>
> I'm working on the AVR backend for LLVM.
>
> I'm looking into an issue where the current LLVM implementation of the
> AVR C calling convention is not matching the assembly of what GCC is
> generating.
>
> On top of that, when I run through the argument algorithm described on
> the Wiki (https://gcc.gnu.org/wiki/avr-gcc), GCC output doesn't seem
> to match up, whereas LLVM does.
>
> The shortest and most inaccurate version of it is: GCC only stores up
> to 8 bytes of arguments in registers, and every argument after that is
> located on the stack. The Wiki says that registers between r8-r25 are
> used, which doesn't seem to match up.
>
> Example: Given a function which takes two 64-bit integers (i64 %a, i64 %b)
> * Start with Rn = 26 * Begin processing %a * Rn -= 8 = 18 * Rn >= 8,
> therefore this argument will be stored in registers r18-r25 * Begin
> processing %b * Rn -= 8 = 10 * Rn >= 8, therefore this argument will
> be stored in registers r10-r17
> This indicates that both arguments should be located in registers, but
> AVR-GCC stores the first argument in registers, and the second
> argument on the stack.
>
> Which is correct? Am I misunderstanding the algorithm?
>
> Where in GCC can I find the implementation of this calling convention?
>
> I've got an issue on the LLVM bug tracker here
> (https://llvm.org/bugs/show_bug.cgi?id=31347).

I guess you misunderstood the assembly generated.
(snip)
.global thing
     .type   thing, @function
thing:
     push r10                             <--------------
     push r11
     push r12
     push r13                             save call-used registers
     push r14
     push r15
     push r16
     push r17                             -------------->
/* prologue: function */
/* frame size = 0 */
/* stack size = 8 */
.L__stack_usage = 8
     ldi r30,lo8(4)            ;
     ldi r31,0                 ; load address 4 to Z register
     st Z,r10                     <-----
     std Z+1,r11
     std Z+2,r12
     std Z+3,r13
     std Z+4,r14                  store argument b (which is in r10-r17)
     std Z+5,r15                  into memory starts at 4 (4-11)
     std Z+6,r16
     std Z+7,r17                  ----->
/* epilogue start */
     pop r17                              <----------------
     pop r16
     pop r15
     pop r14
     pop r13                              restore call-used registers
     pop r12
     pop r11
     pop r10                              ----------------->
     ret
     .size   thing, .-thing
(snip)

Regards,
Pitchumani

_______________________________________________
AVR-GCC-list mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: AVR C calling convention not matching spec

Dylan McKay
I think you're correct.

When I use the on-chip test tool, linking LLVM generated code to GCC generated code, everything works fine, even when I have multiple 64-bit arguments being passed.

Thanks for the help Pitchumani!

On Tue, Dec 20, 2016 at 5:54 AM, Pitchumani Sivanupandi <[hidden email]> wrote:
On Sunday 11 December 2016 07:13 AM, Dylan McKay wrote:
Hey all,

I'm working on the AVR backend for LLVM.

I'm looking into an issue where the current LLVM implementation of the AVR C calling convention is not matching the assembly of what GCC is generating.

On top of that, when I run through the argument algorithm described on the Wiki (https://gcc.gnu.org/wiki/avr-gcc), GCC output doesn't seem to match up, whereas LLVM does.

The shortest and most inaccurate version of it is: GCC only stores up to 8 bytes of arguments in registers, and every argument after that is located on the stack. The Wiki says that registers between r8-r25 are used, which doesn't seem to match up.

Example: Given a function which takes two 64-bit integers (i64 %a, i64 %b)
* Start with Rn = 26 * Begin processing %a * Rn -= 8 = 18 * Rn >= 8, therefore this argument will be stored in registers r18-r25 * Begin processing %b * Rn -= 8 = 10 * Rn >= 8, therefore this argument will be stored in registers r10-r17
This indicates that both arguments should be located in registers, but AVR-GCC stores the first argument in registers, and the second argument on the stack.

Which is correct? Am I misunderstanding the algorithm?

Where in GCC can I find the implementation of this calling convention?

I've got an issue on the LLVM bug tracker here (https://llvm.org/bugs/show_bug.cgi?id=31347).

I guess you misunderstood the assembly generated.
(snip)
.global thing
    .type   thing, @function
thing:
    push r10                             <--------------
    push r11
    push r12
    push r13                             save call-used registers
    push r14
    push r15
    push r16
    push r17                             -------------->
/* prologue: function */
/* frame size = 0 */
/* stack size = 8 */
.L__stack_usage = 8
    ldi r30,lo8(4)            ;
    ldi r31,0                 ; load address 4 to Z register
    st Z,r10                     <-----
    std Z+1,r11
    std Z+2,r12
    std Z+3,r13
    std Z+4,r14                  store argument b (which is in r10-r17)
    std Z+5,r15                  into memory starts at 4 (4-11)
    std Z+6,r16
    std Z+7,r17                  ----->
/* epilogue start */
    pop r17                              <----------------
    pop r16
    pop r15
    pop r14
    pop r13                              restore call-used registers
    pop r12
    pop r11
    pop r10                              ----------------->
    ret
    .size   thing, .-thing
(snip)

Regards,
Pitchumani


_______________________________________________
AVR-GCC-list mailing list
[hidden email]
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list
Loading...