]> granicus.if.org Git - clang/commitdiff
Don't emit prologues or epilogues for naked functions (PR18791, PR20028)
authorHans Wennborg <hans@hanshq.net>
Thu, 4 Sep 2014 22:16:33 +0000 (22:16 +0000)
committerHans Wennborg <hans@hanshq.net>
Thu, 4 Sep 2014 22:16:33 +0000 (22:16 +0000)
For naked functions with parameters, Clang would still emit stores in the prologue
that would clobber the stack, because LLVM doesn't set up a stack frame. (This
shows up in -O0 compiles, because the stores are optimized away otherwise.)

For example:

  __attribute__((naked)) int f(int x) {
    asm("movl $42, %eax");
    asm("retl");
  }

Would result in:

  _Z1fi:
  movl    12(%esp), %eax
  movl    %eax, (%esp)    <--- Oops.
  movl    $42, %eax
  retl

Differential Revision: http://reviews.llvm.org/D5183

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@217198 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCall.cpp
test/CodeGen/attr-naked.c

index ce16d3bd64c4659250ea6eba3484a8b7fd14f2a8..f0eeba06f9cbb5845d9b650416e3f162a3911dbf 100644 (file)
@@ -1462,6 +1462,10 @@ static bool shouldAddNonNullAttr(const Decl *FD, const ParmVarDecl *PVD) {
 void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
                                          llvm::Function *Fn,
                                          const FunctionArgList &Args) {
+  if (CurCodeDecl && CurCodeDecl->hasAttr<NakedAttr>())
+    // Naked functions don't have prologues.
+    return;
+
   // If this is an implicit-return-zero function, go ahead and
   // initialize the return value.  TODO: it might be nice to have
   // a more general mechanism for this that didn't require synthesized
@@ -1985,6 +1989,12 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) {
 void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
                                          bool EmitRetDbgLoc,
                                          SourceLocation EndLoc) {
+  if (CurCodeDecl && CurCodeDecl->hasAttr<NakedAttr>()) {
+    // Naked functions don't have epilogues.
+    Builder.CreateUnreachable();
+    return;
+  }
+
   // Functions with no result always return void.
   if (!ReturnValue) {
     Builder.CreateRetVoid();
index c07dd8d3732a4126485fc0facab7513bd4095ced..270fc7959f4437ef76de339d489bbcf5cfbc7ee1 100644 (file)
@@ -12,7 +12,15 @@ void t1()
 // Make sure this doesn't explode in the verifier.
 // (It doesn't really make sense, but it isn't invalid.)
 // CHECK: define void @t2() [[NAKED]] {
-__attribute((naked, always_inline)) void t2()  {
+__attribute((naked, always_inline)) void t2() {
+}
+
+// Make sure not to generate prolog or epilog for naked functions.
+__attribute((naked)) void t3(int x) {
+// CHECK: define void @t3(i32)
+// CHECK-NOT: alloca
+// CHECK-NOT: store
+// CHECK: unreachable
 }
 
 // CHECK: attributes [[NAKED]] = { naked noinline nounwind{{.*}} }