r234306 - Revert "[SEH] Implement filter capturing in CodeGen"
Daniel Jasper
djasper at google.com
Tue Apr 7 03:07:48 PDT 2015
Author: djasper
Date: Tue Apr 7 05:07:47 2015
New Revision: 234306
URL: http://llvm.org/viewvc/llvm-project?rev=234306&view=rev
Log:
Revert "[SEH] Implement filter capturing in CodeGen"
Test fails:
http://lab.llvm.org:8080/green/job/clang-stage2-configure-Rlto_check/3182/
Removed:
cfe/trunk/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
Modified:
cfe/trunk/lib/CodeGen/CGException.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
Modified: cfe/trunk/lib/CodeGen/CGException.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=234306&r1=234305&r2=234306&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGException.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGException.cpp Tue Apr 7 05:07:47 2015
@@ -19,10 +19,8 @@
#include "clang/AST/Mangle.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
-#include "clang/AST/StmtVisitor.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Intrinsics.h"
-#include "llvm/IR/IntrinsicInst.h"
using namespace clang;
using namespace CodeGen;
@@ -1341,110 +1339,6 @@ struct PerformSEHFinally : EHScopeStack:
};
}
-namespace {
-/// Find all local variable captures in the statement.
-struct CaptureFinder : ConstStmtVisitor<CaptureFinder> {
- CodeGenFunction &ParentCGF;
- const VarDecl *ParentThis;
- SmallVector<const VarDecl *, 4> Captures;
- CaptureFinder(CodeGenFunction &ParentCGF, const VarDecl *ParentThis)
- : ParentCGF(ParentCGF), ParentThis(ParentThis) {}
-
- void Visit(const Stmt *S) {
- // See if this is a capture, then recurse.
- ConstStmtVisitor<CaptureFinder>::Visit(S);
- for (const Stmt *Child : S->children())
- Visit(Child);
- }
-
- void VisitDeclRefExpr(const DeclRefExpr *E) {
- // If this is already a capture, just make sure we capture 'this'.
- if (E->refersToEnclosingVariableOrCapture()) {
- Captures.push_back(ParentThis);
- return;
- }
-
- const auto *D = dyn_cast<VarDecl>(E->getDecl());
- if (D && D->isLocalVarDeclOrParm() && D->hasLocalStorage())
- Captures.push_back(D);
- }
-
- void VisitCXXThisExpr(const CXXThisExpr *E) {
- Captures.push_back(ParentThis);
- }
-};
-}
-
-void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
- const Stmt *OutlinedStmt,
- llvm::Value *ParentFP) {
- // Find all captures in the Stmt.
- CaptureFinder Finder(ParentCGF, ParentCGF.CXXABIThisDecl);
- Finder.Visit(OutlinedStmt);
-
- // Typically there are no captures and we can exit early.
- if (Finder.Captures.empty())
- return;
-
- // Prepare the first two arguments to llvm.framerecover.
- llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
- &CGM.getModule(), llvm::Intrinsic::framerecover);
- llvm::Constant *ParentI8Fn =
- llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
-
- // Create llvm.framerecover calls for all captures.
- for (const VarDecl *VD : Finder.Captures) {
- if (isa<ImplicitParamDecl>(VD)) {
- CGM.ErrorUnsupported(VD, "'this' captured by SEH");
- CXXThisValue = llvm::UndefValue::get(ConvertTypeForMem(VD->getType()));
- continue;
- }
- if (VD->getType()->isVariablyModifiedType()) {
- CGM.ErrorUnsupported(VD, "VLA captured by SEH");
- continue;
- }
-
- assert((isa<ImplicitParamDecl>(VD) || VD->isLocalVarDeclOrParm()) &&
- "captured non-local variable");
-
- llvm::Value *ParentVar = ParentCGF.LocalDeclMap[VD];
- assert(ParentVar && "capture was not a local decl");
- llvm::CallInst *RecoverCall = nullptr;
- CGBuilderTy Builder(AllocaInsertPt);
- if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) {
- // Mark the variable escaped if nobody else referenced it and compute the
- // frameescape index.
- auto InsertPair =
- ParentCGF.EscapedLocals.insert(std::make_pair(ParentAlloca, -1));
- if (InsertPair.second)
- InsertPair.first->second = ParentCGF.EscapedLocals.size() - 1;
- int FrameEscapeIdx = InsertPair.first->second;
- // call i8* @llvm.framerecover(i8* bitcast(@parentFn), i8* %fp, i32 N)
- RecoverCall =
- Builder.CreateCall3(FrameRecoverFn, ParentI8Fn, ParentFP,
- llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx));
-
- } else {
- // If the parent didn't have an alloca, we're doing some nested outlining.
- // Just clone the existing framerecover call, but tweak the FP argument to
- // use our FP value. All other arguments are constants.
- auto *ParentRecover =
- cast<llvm::IntrinsicInst>(ParentVar->stripPointerCasts());
- assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::framerecover &&
- "expected alloca or framerecover in parent LocalDeclMap");
- RecoverCall = cast<llvm::CallInst>(ParentRecover->clone());
- RecoverCall->setArgOperand(1, ParentFP);
- RecoverCall->insertBefore(AllocaInsertPt);
- }
-
- // Bitcast the variable, rename it, and insert it in the local decl map.
- llvm::Value *ChildVar =
- Builder.CreateBitCast(RecoverCall, ParentVar->getType());
- ChildVar->setName(ParentVar->getName());
- LocalDeclMap[VD] = ChildVar;
- }
-}
-
/// Create a stub filter function that will ultimately hold the code of the
/// filter expression. The EH preparation passes in LLVM will outline the code
/// from the main function body into this stub.
@@ -1498,9 +1392,15 @@ CodeGenFunction::GenerateSEHFilterFuncti
EmitSEHExceptionCodeSave();
- auto AI = Fn->arg_begin();
- ++AI;
- EmitCapturedLocals(ParentCGF, FilterExpr, &*AI);
+ // Insert dummy allocas for every local variable in scope. We'll initialize
+ // them and prune the unused ones after we find out which ones were
+ // referenced.
+ for (const auto &DeclPtrs : ParentCGF.LocalDeclMap) {
+ const Decl *VD = DeclPtrs.first;
+ llvm::Value *Ptr = DeclPtrs.second;
+ auto *ValTy = cast<llvm::PointerType>(Ptr->getType())->getElementType();
+ LocalDeclMap[VD] = CreateTempAlloca(ValTy, Ptr->getName() + ".filt");
+ }
// Emit the original filter expression, convert to i32, and return.
llvm::Value *R = EmitScalarExpr(FilterExpr);
@@ -1510,6 +1410,17 @@ CodeGenFunction::GenerateSEHFilterFuncti
FinishFunction(FilterExpr->getLocEnd());
+ for (const auto &DeclPtrs : ParentCGF.LocalDeclMap) {
+ const Decl *VD = DeclPtrs.first;
+ auto *Alloca = cast<llvm::AllocaInst>(LocalDeclMap[VD]);
+ if (Alloca->hasNUses(0)) {
+ Alloca->eraseFromParent();
+ continue;
+ }
+ ErrorUnsupported(FilterExpr,
+ "SEH filter expression local variable capture");
+ }
+
return Fn;
}
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=234306&r1=234305&r2=234306&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Tue Apr 7 05:07:47 2015
@@ -279,20 +279,6 @@ void CodeGenFunction::FinishFunction(Sou
Builder.ClearInsertionPoint();
}
- // If some of our locals escaped, insert a call to llvm.frameescape in the
- // entry block.
- if (!EscapedLocals.empty()) {
- // Invert the map from local to index into a simple vector. There should be
- // no holes.
- SmallVector<llvm::Value *, 4> EscapeArgs;
- EscapeArgs.resize(EscapedLocals.size());
- for (auto &Pair : EscapedLocals)
- EscapeArgs[Pair.second] = Pair.first;
- llvm::Function *FrameEscapeFn = llvm::Intrinsic::getDeclaration(
- &CGM.getModule(), llvm::Intrinsic::frameescape);
- CGBuilderTy(AllocaInsertPt).CreateCall(FrameEscapeFn, EscapeArgs);
- }
-
// Remove the AllocaInsertPt instruction, which is just a convenience for us.
llvm::Instruction *Ptr = AllocaInsertPt;
AllocaInsertPt = nullptr;
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=234306&r1=234305&r2=234306&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Apr 7 05:07:47 2015
@@ -877,10 +877,6 @@ private:
typedef llvm::DenseMap<const Decl*, llvm::Value*> DeclMapTy;
DeclMapTy LocalDeclMap;
- /// Track escaped local variables with auto storage. Used during SEH
- /// outlining to produce a call to llvm.frameescape.
- llvm::DenseMap<llvm::AllocaInst *, int> EscapedLocals;
-
/// LabelMap - This keeps track of the LLVM basic block for each C label.
llvm::DenseMap<const LabelDecl*, JumpDest> LabelMap;
@@ -2011,12 +2007,6 @@ public:
llvm::Value *EmitSEHExceptionInfo();
llvm::Value *EmitSEHAbnormalTermination();
- /// Scan the outlined statement for captures from the parent function. For
- /// each capture, mark the capture as escaped and emit a call to
- /// llvm.framerecover. Insert the framerecover result into the LocalDeclMap.
- void EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt *OutlinedStmt,
- llvm::Value *ParentFP);
-
void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
ArrayRef<const Attr *> Attrs = None);
Removed: cfe/trunk/test/CodeGenCXX/exceptions-seh-filter-captures.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/exceptions-seh-filter-captures.cpp?rev=234305&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/exceptions-seh-filter-captures.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/exceptions-seh-filter-captures.cpp (removed)
@@ -1,81 +0,0 @@
-// RUN: %clang_cc1 -std=c++11 -fblocks -fms-extensions %s -triple=x86_64-windows-msvc -emit-llvm \
-// RUN: -o - -mconstructor-aliases -fcxx-exceptions -fexceptions | \
-// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CXXEH
-
-extern "C" int basic_filter(int v, ...);
-extern "C" void might_crash();
-
-extern "C" void test_freefunc(int p1) {
- int l1 = 13;
- static int s1 = 42;
- __try {
- might_crash();
- } __except(basic_filter(p1, l1, s1)) {
- }
-}
-
-// CHECK-LABEL: define void @test_freefunc(i32 %p1)
-// CHECK: @llvm.frameescape(i32* %[[p1_ptr:[^, ]*]], i32* %[[l1_ptr:[^, ]*]])
-// CHECK: store i32 %p1, i32* %[[p1_ptr]], align 4
-// CHECK: store i32 13, i32* %[[l1_ptr]], align 4
-// CHECK: invoke void @might_crash()
-
-// CHECK-LABEL: define internal i32 @"\01?filt$0 at 0@test_freefunc@@"(i8* %exception_pointers, i8* %frame_pointer)
-// CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.framerecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer, i32 0)
-// CHECK: %[[p1_ptr:[^ ]*]] = bitcast i8* %[[p1_i8]] to i32*
-// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.framerecover(i8* bitcast (void (i32)* @test_freefunc to i8*), i8* %frame_pointer, i32 1)
-// CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
-// CHECK: %[[s1:[^ ]*]] = load i32, i32* @"\01?s1@?1??test_freefunc@@9 at 4HA", align 4
-// CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
-// CHECK: %[[p1:[^ ]*]] = load i32, i32* %[[p1_ptr]]
-// CHECK: call i32 (i32, ...)* @basic_filter(i32 %[[p1]], i32 %[[l1]], i32 %[[s1]])
-
-struct S {
- int m1;
- void test_method(void);
-};
-
-void S::test_method() {
- int l1 = 13;
- __try {
- might_crash();
- } __except(basic_filter(l1)) {
- // FIXME: Test capturing 'this' and 'm1'.
- }
-}
-
-// CHECK-LABEL: define void @"\01?test_method at S@@QEAAXXZ"(%struct.S* %this)
-// CHECK: @llvm.frameescape(i32* %[[l1_addr:[^, ]*]])
-// CHECK: store i32 13, i32* %[[l1_addr]], align 4
-// CHECK: invoke void @might_crash()
-
-// CHECK-LABEL: define internal i32 @"\01?filt$0 at 0@test_method at S@@"(i8* %exception_pointers, i8* %frame_pointer)
-// CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.framerecover(i8* bitcast (void (%struct.S*)* @"\01?test_method at S@@QEAAXXZ" to i8*), i8* %frame_pointer, i32 0)
-// CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
-// CHECK: %[[l1:[^ ]]] = load i32, i32* %[[l1_ptr]]
-// CHECK: call i32 (i32, ...)* @basic_filter(i32 %[[l1]])
-
-void test_lambda() {
- int l1 = 13;
- auto lambda = [&]() {
- int l2 = 42;
- __try {
- might_crash();
- } __except(basic_filter(l2)) {
- // FIXME: Test 'l1' when we can capture the lambda's 'this' decl.
- }
- };
- lambda();
-}
-
-// CHECK-LABEL: define internal void @"\01??R<lambda_0>@?test_lambda@@YAXXZ at QEBAXXZ"(%class.anon* %this)
-// CHECK: @llvm.frameescape(i32* %[[l2_addr:[^, ]*]])
-// CHECK: store i32 42, i32* %[[l2_addr]], align 4
-// CHECK: invoke void @might_crash()
-
-// CHECK-LABEL: define internal i32 @"\01?filt$0 at 0@?R<lambda_0>@?test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* %frame_pointer)
-// CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.framerecover(i8* bitcast (void (%class.anon*)* @"\01??R<lambda_0>@?test_lambda@@YAXXZ at QEBAXXZ" to i8*), i8* %frame_pointer, i32 0)
-// CHECK: %[[l2_ptr:[^ ]*]] = bitcast i8* %[[l2_i8]] to i32*
-// CHECK: %[[l2:[^ ]]] = load i32, i32* %[[l2_ptr]]
-// CHECK: call i32 (i32, ...)* @basic_filter(i32 %[[l2]])
-
More information about the cfe-commits
mailing list