ahatanak updated this revision to Diff 45910.
ahatanak added a comment.

Address review comments from Hans and Manman.


http://reviews.llvm.org/D15599

Files:
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/CGStmt.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenFunction.h
  test/CodeGen/attr-naked.c
  test/CodeGenCXX/attr-naked.cpp
  test/CodeGenCXX/ms-inline-asm-return.cpp

Index: test/CodeGenCXX/ms-inline-asm-return.cpp
===================================================================
--- test/CodeGenCXX/ms-inline-asm-return.cpp
+++ test/CodeGenCXX/ms-inline-asm-return.cpp
@@ -1,5 +1,5 @@
 // REQUIRES: x86-registered-target
-// RUN: %clang_cc1 %s -triple i686-pc-windows-msvc -emit-llvm -o - -fasm-blocks | FileCheck %s
+// RUN: %clang_cc1 %s -triple i686-pc-windows-msvc -emit-llvm -o - -fasm-blocks -fms-compatibility | FileCheck %s
 
 // Check that we take EAX or EAX:EDX and return it from these functions for MSVC
 // compatibility.
@@ -98,3 +98,17 @@
 // CHECK-LABEL: define i32 @main()
 // CHECK: %[[r:[^ ]*]] = call i32 asm sideeffect inteldialect "xor eax, eax", "={eax},{{.*}}"
 // CHECK: ret i32 %[[r]]
+
+// Don't set the return value if the function is marked as naked. 
+__declspec(naked) int nakedFunc(int a, int b)
+{
+  __asm {
+    ret
+  }
+}
+
+// CHECK: define i32 @{{.*}}nakedFunc
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void asm sideeffect inteldialect "ret
+// CHECK-NEXT: unreachable
+// CHECK-NEXT: }
Index: test/CodeGenCXX/attr-naked.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/attr-naked.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -triple=x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s
+
+class Class1 {
+public:
+  void __attribute__((naked)) m1() { __asm__ volatile("retq"); }
+  int __attribute__((naked)) m2() { __asm__ volatile("retq"); }
+};
+
+int foo1(int a, Class1 *c1) {
+  auto Fn = []() __attribute__((naked))->int {
+    __asm__ volatile("retq");
+  };
+
+  if (a < 0)
+    return Fn();
+
+  if (a > 0)
+    return c1->m2();
+  
+  c1->m1();
+  return 1;
+}
+
+// Check for the absence of llvm.trap.
+int __attribute__((naked)) foo2(int a) {
+  __asm__ volatile("retq");
+}
+
+// CHECK: define internal i32 @"_ZZ4foo1iP6Class1ENK3$_0clEv"(%class.anon* %this) [[ATTR1:#[0-9]]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void asm sideeffect "retq
+// CHECK-NEXT: unreachable
+// CHECK-NEXT: }
+
+
+// CHECK: define linkonce_odr i32 @_ZN6Class12m2Ev(%class.Class1* %this) [[ATTR2:#[0-9]]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void asm sideeffect "retq
+// CHECK-NEXT: unreachable
+// CHECK-NEXT: }
+
+// CHECK: define linkonce_odr void @_ZN6Class12m1Ev(%class.Class1* %this) [[ATTR2]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void asm sideeffect "retq
+// CHECK-NEXT: unreachable
+// CHECK-NEXT: }
+
+// CHECK: define i32 @_Z4foo2i(i32 %a) [[ATTR2]]
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void asm sideeffect "retq
+// CHECK-NEXT: unreachable
+// CHECK-NEXT: }
+
+// CHECK: attributes [[ATTR1]] = { {{.*}}naked{{.*}} }
+// CHECK: attributes [[ATTR2]] = { {{.*}}naked{{.*}} }
Index: test/CodeGen/attr-naked.c
===================================================================
--- test/CodeGen/attr-naked.c
+++ test/CodeGen/attr-naked.c
@@ -17,7 +17,7 @@
 
 // Make sure not to generate prolog or epilog for naked functions.
 __attribute((naked)) void t3(int x) {
-// CHECK: define void @t3(i32)
+// CHECK: define void @t3(i32 %x)
 // CHECK-NOT: alloca
 // CHECK-NOT: store
 // CHECK: unreachable
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -3096,6 +3096,13 @@
   llvm::Value *emitBuiltinObjectSize(const Expr *E, unsigned Type,
                                      llvm::IntegerType *ResType);
 
+  /// Return true if CurCodeDecl has attribute Naked.
+  bool isNakedFunction() const;
+
+  /// Clean up naked functions removing allocas and their users and all blocks
+  /// except the entry.
+  void cleanupNakedFunction();
+
 public:
 #ifndef NDEBUG
   // Determine whether the given argument is an Objective-C method
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -355,6 +355,9 @@
     CGBuilderTy(*this, AllocaInsertPt).CreateCall(FrameEscapeFn, EscapeArgs);
   }
 
+  if (isNakedFunction())
+    cleanupNakedFunction();
+
   // Remove the AllocaInsertPt instruction, which is just a convenience for us.
   llvm::Instruction *Ptr = AllocaInsertPt;
   AllocaInsertPt = nullptr;
@@ -1009,7 +1012,8 @@
   //   If the '}' that terminates a function is reached, and the value of the
   //   function call is used by the caller, the behavior is undefined.
   if (getLangOpts().CPlusPlus && !FD->hasImplicitReturnZero() && !SawAsmBlock &&
-      !FD->getReturnType()->isVoidType() && Builder.GetInsertBlock()) {
+      !FD->getReturnType()->isVoidType() && Builder.GetInsertBlock() &&
+      !isNakedFunction()) {
     if (SanOpts.has(SanitizerKind::Return)) {
       SanitizerScope SanScope(this);
       llvm::Value *IsFalse = Builder.getFalse();
@@ -1957,6 +1961,47 @@
   }
 }
 
+bool CodeGenFunction::isNakedFunction() const {
+  return CurCodeDecl && CurCodeDecl->hasAttr<NakedAttr>();
+}
+
+void CodeGenFunction::cleanupNakedFunction() {
+  llvm::SmallPtrSet<llvm::Instruction *, 8> InstrsToRemove;
+  llvm::BasicBlock *EntryBB = AllocaInsertPt->getParent();
+
+  // Erase all allocas and their users.
+  for (auto I = EntryBB->begin(); &*I != &*AllocaInsertPt; ++I)
+    if (auto Alloca = dyn_cast<llvm::AllocaInst>(&*I))
+      InstrsToRemove.insert(Alloca);
+
+  while (!InstrsToRemove.empty()) {
+    auto *I = *InstrsToRemove.begin();
+
+    for (auto *U : I->users())
+      InstrsToRemove.insert(cast<llvm::Instruction>(U));
+
+    I->replaceAllUsesWith(llvm::UndefValue::get(I->getType()));
+    I->eraseFromParent();
+    InstrsToRemove.erase(I);
+  }
+
+  // Erase all blocks except the entry.
+  for (auto BB = CurFn->begin(); BB != CurFn->end();) {
+    if (&*BB == EntryBB)
+      ++BB;
+    else
+      BB++->eraseFromParent();
+  }
+
+  // Erase terminator of the entry block.
+  if (auto *T = EntryBB->getTerminator())
+    T->eraseFromParent();
+
+  // Insert an unreachable at the end of the entry block.
+  Builder.SetInsertPoint(EntryBB, EntryBB->end());
+  Builder.CreateUnreachable();
+}
+
 void CodeGenFunction::EmitSanitizerStatReport(llvm::SanitizerStatKind SSK) {
   if (!CGM.getCodeGenOpts().SanitizeStats)
     return;
Index: lib/CodeGen/CGStmt.cpp
===================================================================
--- lib/CodeGen/CGStmt.cpp
+++ lib/CodeGen/CGStmt.cpp
@@ -1881,9 +1881,10 @@
     }
   }
 
-  // If this is a Microsoft-style asm blob, store the return registers (EAX:EDX)
-  // to the return value slot. Only do this when returning in registers.
-  if (isa<MSAsmStmt>(&S)) {
+  // If this is a Microsoft-style asm blob that is not naked, store the return
+  // registers (EAX:EDX) to the return value slot. Only do this when returning
+  // in registers.
+  if (isa<MSAsmStmt>(&S) && !isNakedFunction()) {
     const ABIArgInfo &RetAI = CurFnInfo->getReturnInfo();
     if (RetAI.isDirect() || RetAI.isExtend()) {
       // Make a fake lvalue for the return value slot.
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -1813,10 +1813,6 @@
 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
@@ -2363,12 +2359,6 @@
 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.isValid()) {
     Builder.CreateRetVoid();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to