<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br>Hi,<br><br>I've recently been investigating problems with using naked functions in Clang where portions of the stack are overwritten in debug builds. This happens on all architectures I've tested (x86, x64, ARM) and is evident in the LLVM IR itself. With the svn builds of clang, there's an additional problem where undefined results are being introduced<br><br>First to show what I'm discussing:<br><br>test.cpp:<br><br><font face="Courier">__attribute((noinline, naked)) int NakedTest(int value, int value2)<br>{<br><span class="Apple-tab-span" style="white-space: pre; ">  </span>asm("");<br>}<br></font><br>Example using svn r167616 of clang/llvm:<br><br><br><font face="Courier">clang -S test.cpp<br><br><span class="Apple-tab-span" style="white-space: pre; ">   </span>.section<span class="Apple-tab-span" style="white-space: pre; "> </span>__TEXT,__text,regular,pure_instructions<br><span class="Apple-tab-span" style="white-space: pre; ">        </span>.globl<span class="Apple-tab-span" style="white-space: pre; ">   </span>__Z9NakedTestii<br><span class="Apple-tab-span" style="white-space: pre; ">        </span>.align<span class="Apple-tab-span" style="white-space: pre; ">   </span>4, 0x90<br>__Z9NakedTestii:                        ## @_Z9NakedTestii<br><span class="Apple-tab-span" style="white-space: pre; ">        </span>.cfi_startproc<br>## BB#0:                                ## %entry<br><b><font color="#ff2600"><span class="Apple-tab-span" style="white-space: pre; ">       </span>movl<span class="Apple-tab-span" style="white-space: pre; ">     </span>%edi, -8(%rbp)<br><span class="Apple-tab-span" style="white-space: pre; "> </span>movl<span class="Apple-tab-span" style="white-space: pre; ">     </span>%esi, -12(%rbp)</font><br></b><span class="Apple-tab-span" style="white-space: pre; "> </span>## InlineAsm Start<br><span class="Apple-tab-span" style="white-space: pre; ">     </span>## InlineAsm End<br><b><font color="#ff2600"><span class="Apple-tab-span" style="white-space: pre; ">        </span>ud2<br></font></b><span class="Apple-tab-span" style="white-space: pre; ">     </span>.cfi_endproc<br></font><br><br>The first two highlighted lines are overwriting memory unexpected. The ud2 causes a runtime failure on all naked functions with a return type.<br><br>The same test.cpp compiled with Xcode 4.5.2's version of clang:<br><br><font face="Courier"><span class="Apple-tab-span" style="white-space: pre; ">        </span>.section<span class="Apple-tab-span" style="white-space: pre; "> </span>__TEXT,__text,regular,pure_instructions<br><span class="Apple-tab-span" style="white-space: pre; ">        </span>.globl<span class="Apple-tab-span" style="white-space: pre; ">   </span>__Z9NakedTestii<br><span class="Apple-tab-span" style="white-space: pre; ">        </span>.align<span class="Apple-tab-span" style="white-space: pre; ">   </span>4, 0x90<br>__Z9NakedTestii:                        ## @_Z9NakedTestii<br><span class="Apple-tab-span" style="white-space: pre; ">        </span>.cfi_startproc<br>## BB#0:<br><b><font color="#ff2600"><span class="Apple-tab-span" style="white-space: pre; ">        </span>movl<span class="Apple-tab-span" style="white-space: pre; ">     </span>%edi, -8(%rbp)<br><span class="Apple-tab-span" style="white-space: pre; "> </span>movl<span class="Apple-tab-span" style="white-space: pre; ">     </span>%esi, -12(%rbp)</font></b><br><span class="Apple-tab-span" style="white-space: pre; "> </span>## InlineAsm Start<br><span class="Apple-tab-span" style="white-space: pre; ">     </span>## InlineAsm End<br><b><font color="#ff2600"><span class="Apple-tab-span" style="white-space: pre; ">        </span>movl<span class="Apple-tab-span" style="white-space: pre; ">     </span>-4(%rbp), %eax</font></b><br><span class="Apple-tab-span" style="white-space: pre; ">  </span>ret<br><span class="Apple-tab-span" style="white-space: pre; ">    </span>.cfi_endproc<br></font><br><br>I've developed a patch for clang that fixes these issues; however, upon review from Eli Friedman, one of the changes that I had to make was particularly concerning to him and he suggested that I post to this list for discussion -- it's a change required in VMCore/Verifier.cpp.<br><br>When we have a naked function, I'm <b>always </b>generating a <font face="Courier">ret void</font> instruction in LLVM IR. This is even if the function has a signature that specifies a return type, but I need to do this so that the debug code generators don't insert any extra code to setup the return value. This fails the verifier (which complains that return type of function doesn't match return type instruction found), however, I believe that for naked functions (where all the body of the function would be written in "asm" sections), that this is actually what is necessary.<div><br></div><div>So I have a patch that checks for this (attached):</div><div><br></div><div>The question is: Am I doing anything that is fundamentally wrong? Will this cause any problems with the LLVM optimisers? Note that naked functions are also implicitly "noinline" <br><div>Thanks for your time,</div></div><div><br></div><div>Jeffrey Lim</div><div><br></div><div><div></div></div></body></html>