<html>
    <head>
      <base href="http://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - Naked attribute: clang emits extraneous, stack-altering code for naked functions that have a parameter."
   href="http://llvm.org/bugs/show_bug.cgi?id=18791">18791</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Naked attribute: clang emits extraneous, stack-altering code for naked functions that have a parameter.
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>3.4
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Windows NT
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>-New Bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>carl.william@wittenstein.co.uk
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>clang/LLVM emits extra register- and stack-altering code before and after body
of "naked" function, when the function is declared with a parameter. 

It also emits extra code when the function is declared with a return value, and
in all cases emits a return after the function body (the return is usually
harmless, though, likewise the extra code in the return value case.) 

It looks as if part of the normal function stack frame setup/take-down is being
generated, but the code produced in the function-having-a-parameter case is
problematic as it overwrites part of the in-use stack (without first advancing
the stack pointer). 

I made some attempt to elicit different behaviour with different syntax and
different command line parameters (e.g. turning off debug with -g0) but
couldn't get rid of the erroneous object code. 

It appears to do the same with other targets, e.g. ARM7 and x86.

For comparison, a recent arm-none-eabi-gcc appears to emit nothing but the body
of the __asm, in all cases without a return value, and a single register copy
after the body of the __asm in the cases that do have a return value.

The only truly problematic bit of extra code is the stack write before the
__asm body; everything after the __asm body is usually just dead code because
the body of a naked function may be expected to do its own return. The register
write before the body is unexpected, but there are few circumstances with the
ARM ABI at any rate, where a write to R1 is an issue.

With many parameters, however, especially beyond the four params that will
typically be passed in simple registers, the degree of stack and register
corruption is much worse. See extra example, below.

Work-around:
------------

Code parametrized naked functions in assembly or using inline __asm() semantics
directly in macros.



Example code that illustrates the issue:
---------------------------------------

naked_test.c
------------
__attribute__((naked)) void void_foo( void )
{
    __asm volatile ( "   nop   " );
}

__attribute__((naked)) int retval_foo( void )
{
    __asm volatile ( "   nop   " );
}

__attribute__((naked)) void param_foo( int bar )
{
    __asm volatile ( "   nop   " );
}

__attribute__((naked)) int retval_param_foo( int bar )
{
    __asm volatile ( "   nop   " );
}


Compiled with
-------------
clang -mcpu=cortex-m3 --target=thumbv7m--none-eabi -mthumb -S naked_test.c -o
naked_test.s


Code generated (with comments added)
------------------------------------
        .syntax unified
        .cpu    cortex-m3
        .eabi_attribute 6, 10
        .eabi_attribute 7, 77
        .eabi_attribute 8, 0
        .eabi_attribute 9, 2
        .eabi_attribute 20, 1
        .eabi_attribute 21, 1
        .eabi_attribute 23, 3
        .eabi_attribute 24, 1
        .eabi_attribute 25, 1
        .eabi_attribute 44, 2
        .file   "naked_test.c"
        .text
        .globl  void_foo
        .align  2
        .type   void_foo,%function
        .code   16
        .thumb_func
void_foo:                  /* Naked except extraneous/harmless bx lr */        
        @APP
           nop
        @NO_APP
        bx      lr
.Ltmp0:
        .size   void_foo, .Ltmp0-void_foo

        .globl  retval_foo
        .align  2
        .type   retval_foo,%function
        .code   16
        .thumb_func
retval_foo:                
        @APP
           nop
        @NO_APP
        ldr     r0, [sp]    /* extra ldr will clobber return val */
        bx      lr          /* if __asm code doesn't return, but */
.Ltmp1:                     /* this is mostly harmless */ 
        .size   retval_foo, .Ltmp1-retval_foo

        .globl  param_foo
        .align  2
        .type   param_foo,%function
        .code   16
        .thumb_func
param_foo:
        mov     r1, r0       /* clobbers R1 with R0 param */
        str     r0, [sp, #4] /* Bad: clobbering in-use stack */
        @APP
           nop
        @NO_APP
        str     r1, [sp]     /* clobbering stack some more if __asm */
        bx      lr           /* doesn't do its own return. */
.Ltmp2:
        .size   param_foo, .Ltmp2-param_foo

        .globl  retval_param_foo
        .align  2
        .type   retval_param_foo,%function
        .code   16
        .thumb_func
retval_param_foo:            /* combines retval and param cases */
        mov     r1, r0
        str     r0, [sp, #4]
        @APP
           nop
        @NO_APP
        ldr     r0, [sp, #8]
        str     r1, [sp]
        bx      lr
.Ltmp3:
        .size   retval_param_foo, .Ltmp3-retval_param_foo


        .ident  "clang version 3.4 (198054)"



Extra example illustrating case with many parameters
----------------------------------------------------

__attribute__((naked)) void many_param_foo( int bar1, int bar2, int bar3, int
bar4, int bar5 )
{
    __asm volatile ( "   nop   " );
}



    .globl  many_param_foo
    .align  2
    .type   many_param_foo,%function
    .code   16
    .thumb_func
many_param_foo:
    ldr.w   r12, [sp, #36]
    mov lr, r3
    mov r4, r2
    mov r5, r1
    mov r6, r0
    str r0, [sp, #32]
    str r1, [sp, #28]
    str r2, [sp, #24]
    str r3, [sp, #20]
    str.w   r12, [sp, #16]
    @APP
       nop
    @NO_APP
    str.w   lr, [sp, #12]
    str r4, [sp, #8]
    str r5, [sp, #4]
    str r6, [sp]
    bx  lr
.Ltmp4:
    .size   many_param_foo, .Ltmp4-many_param_foo


    .ident  "clang version 3.4 (198054)"</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>