<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </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 - __attribute__((no_caller_saved_registers)) ignored for struct members and typedefs"
   href="https://bugs.llvm.org/show_bug.cgi?id=50121">50121</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>__attribute__((no_caller_saved_registers)) ignored for struct members and typedefs
          </td>
        </tr>

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

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

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

        <tr>
          <th>OS</th>
          <td>All
          </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>jhaberman@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>htmldeveloper@gmail.com, llvm-bugs@lists.llvm.org, neeilans@live.com, richard-llvm@metafoo.co.uk
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Take the following program that uses no_caller_saved_registers:

__attribute__((no_caller_saved_registers)) void g();

int f(int x) {
  g();
  return x;
}

This produces the expected output, edi is preserved across the call:

0000000000000000 <f>:
   0:   50                      push   rax
   1:   31 c0                   xor    eax,eax
   3:   e8 00 00 00 00          call   8 <f+0x8>
                        4: R_X86_64_PLT32       g-0x4
   8:   89 f8                   mov    eax,edi
   a:   59                      pop    rcx
   b:   c3                      ret

However the following program does not generate the same output:

struct {
  __attribute__((no_caller_saved_registers)) void (*g)();
} st;

int f(int x) {
  st.g();
  return x;
}

In this case the attribute is ignored, and edi is spilled to a normal
callee-save register:

0000000000000000 <f>:
   0:   53                      push   rbx
   1:   89 fb                   mov    ebx,edi
   3:   31 c0                   xor    eax,eax
   5:   ff 15 00 00 00 00       call   QWORD PTR [rip+0x0]        # b <f+0xb>
                        7: R_X86_64_PC32        st-0x4
   b:   89 d8                   mov    eax,ebx
   d:   5b                      pop    rbx
   e:   c3                      ret

If we copy into a local variable with the attribute, it works:

struct {
  __attribute__((no_caller_saved_registers)) void (*g)();
} st;

int f(int x) {
  __attribute__((no_caller_saved_registers)) void (*local)() = st.g;
  local();
  return x;
}

However it does not work if the attribute is on a typedef:

typedef __attribute__((no_caller_saved_registers)) void g_type();
g_type *g;

int f(int x) {
  g();
  return x;
}

This bug appears to be similar to <a class="bz_bug_link 
          bz_status_RESOLVED  bz_closed"
   title="RESOLVED FIXED - __attribute__((__format__(printf ignored for function pointer members of struct"
   href="show_bug.cgi?id=21082">https://bugs.llvm.org/show_bug.cgi?id=21082</a></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>