From ffb8cef8cfc53b54c8007b52e75cae492c014bb4 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 11 Feb 2015 21:40:48 +0000 Subject: [PATCH] Add the 'noinline' attribute to call sites within __try bodies LLVM doesn't support non-call exceptions, so inlining makes it harder to catch such asynchronous exceptions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@228876 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCall.cpp | 6 ++++++ lib/CodeGen/CGException.cpp | 7 ++++++- lib/CodeGen/CodeGenFunction.cpp | 2 +- lib/CodeGen/CodeGenFunction.h | 3 +++ test/CodeGen/exceptions-seh.c | 8 +++++--- test/CodeGenCXX/exceptions-seh.cpp | 5 ++++- 6 files changed, 25 insertions(+), 6 deletions(-) diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 0574a1a34d..60ab2effbe 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -3325,6 +3325,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex, llvm::Attribute::AlwaysInline); + // Disable inlining inside SEH __try blocks. + if (IsSEHTryScope) + Attrs = + Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex, + llvm::Attribute::NoInline); + CS.setAttributes(Attrs); CS.setCallingConv(static_cast(CallingConv)); diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index 9df4f97731..b8ce205ff1 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -21,6 +21,7 @@ #include "clang/AST/StmtObjC.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/Support/SaveAndRestore.h" using namespace clang; using namespace CodeGen; @@ -1703,7 +1704,11 @@ void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) { SEHFinallyInfo FI; EnterSEHTryStmt(S, FI); - EmitStmt(S.getTryBlock()); + { + // Disable inlining inside SEH __try scopes. + SaveAndRestore Saver(IsSEHTryScope, true); + EmitStmt(S.getTryBlock()); + } ExitSEHTryStmt(S, FI); } diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 79425d4c21..43dd7a05de 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -40,7 +40,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) CurFn(nullptr), CapturedStmtInfo(nullptr), SanOpts(CGM.getLangOpts().Sanitize), IsSanitizerScope(false), CurFuncIsThunk(false), AutoreleaseResult(false), SawAsmBlock(false), - BlockInfo(nullptr), BlockPointer(nullptr), + IsSEHTryScope(false), BlockInfo(nullptr), BlockPointer(nullptr), LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr), NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr), EHSelectorSlot(nullptr), diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 998e0676cd..6011333c9d 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -263,6 +263,9 @@ public: /// potentially set the return value. bool SawAsmBlock; + /// Codegen is currently inside an SEH try block. + bool IsSEHTryScope; + const CodeGen::CGBlockInfo *BlockInfo; llvm::Value *BlockPointer; diff --git a/test/CodeGen/exceptions-seh.c b/test/CodeGen/exceptions-seh.c index 98b9de5d59..ebe97bedd2 100644 --- a/test/CodeGen/exceptions-seh.c +++ b/test/CodeGen/exceptions-seh.c @@ -21,7 +21,7 @@ int safe_div(int numerator, int denominator, int *res) { return success; } // CHECK-LABEL: define i32 @safe_div(i32 %numerator, i32 %denominator, i32* %res) -// CHECK: invoke void @try_body(i32 %{{.*}}, i32 %{{.*}}, i32* %{{.*}}) +// CHECK: invoke void @try_body(i32 %{{.*}}, i32 %{{.*}}, i32* %{{.*}}) #[[NOINLINE:[0-9]+]] // CHECK: to label %{{.*}} unwind label %[[lpad:[^ ]*]] // // CHECK: [[lpad]] @@ -51,7 +51,7 @@ int filter_expr_capture(void) { // CHECK-LABEL: define i32 @filter_expr_capture() // FIXMECHECK: %[[captures]] = call i8* @llvm.frameallocate(i32 4) // CHECK: store i32 42, i32* %[[r:[^ ,]*]] -// CHECK: invoke void @j() +// CHECK: invoke void @j() #[[NOINLINE]] // // CHECK: landingpad // CHECK-NEXT: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@filter_expr_capture@@" to i8*) @@ -81,7 +81,7 @@ int nested_try(void) { } // CHECK-LABEL: define i32 @nested_try() // CHECK: store i32 42, i32* %[[r:[^ ,]*]] -// CHECK: invoke void @j() +// CHECK: invoke void @j() #[[NOINLINE]] // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[cont]] @@ -179,3 +179,5 @@ int except_return(void) { // CHECK: [[retbb]] // CHECK: %[[r:[^ ]*]] = load i32* %[[rv]] // CHECK: ret i32 %[[r]] + +// CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} } diff --git a/test/CodeGenCXX/exceptions-seh.cpp b/test/CodeGenCXX/exceptions-seh.cpp index 38d176b829..5f93cb1be3 100644 --- a/test/CodeGenCXX/exceptions-seh.cpp +++ b/test/CodeGenCXX/exceptions-seh.cpp @@ -58,7 +58,7 @@ extern "C" void use_seh() { // Make sure we use __C_specific_handler for SEH. // CHECK-LABEL: define void @use_seh() -// CHECK: invoke void @might_throw() +// CHECK: invoke void @might_throw() #[[NOINLINE:[0-9]+]] // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[cont]] @@ -92,4 +92,7 @@ void use_seh_in_lambda() { // NOCXX: ret void // CHECK-LABEL: define internal void @"\01??R@?use_seh_in_lambda@@YAXXZ@QEBAXXZ"(%class.anon* %this) +// CHECK: invoke void @might_throw() #[[NOINLINE]] // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) + +// CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} } -- 2.40.0