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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits