r234789 - Revert r234613 (and follow-ups 234614, 234616, 234618), it caused PR23216.
Nico Weber
nicolasweber at gmx.de
Mon Apr 13 13:04:23 PDT 2015
Author: nico
Date: Mon Apr 13 15:04:22 2015
New Revision: 234789
URL: http://llvm.org/viewvc/llvm-project?rev=234789&view=rev
Log:
Revert r234613 (and follow-ups 234614, 234616, 234618), it caused PR23216.
Modified:
cfe/trunk/include/clang/AST/Mangle.h
cfe/trunk/lib/AST/ItaniumMangle.cpp
cfe/trunk/lib/AST/MicrosoftMangle.cpp
cfe/trunk/lib/CodeGen/CGException.cpp
cfe/trunk/lib/CodeGen/CGStmt.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/test/CodeGen/exceptions-seh-finally.c
cfe/trunk/test/CodeGen/exceptions-seh-leave.c
cfe/trunk/test/CodeGen/exceptions-seh.c
cfe/trunk/test/CodeGenCXX/exceptions-seh.cpp
Modified: cfe/trunk/include/clang/AST/Mangle.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Mangle.h?rev=234789&r1=234788&r2=234789&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Mangle.h (original)
+++ cfe/trunk/include/clang/AST/Mangle.h Mon Apr 13 15:04:22 2015
@@ -135,9 +135,6 @@ public:
virtual void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
raw_ostream &Out) = 0;
- virtual void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
- raw_ostream &Out) = 0;
-
/// Generates a unique string for an externally visible type for use with TBAA
/// or type uniquing.
/// TODO: Extend this to internal types by generating names that are unique
Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=234789&r1=234788&r2=234789&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Mon Apr 13 15:04:22 2015
@@ -166,8 +166,6 @@ public:
raw_ostream &Out) override;
void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
raw_ostream &Out) override;
- void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
- raw_ostream &Out) override;
void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &) override;
void mangleItaniumThreadLocalWrapper(const VarDecl *D,
raw_ostream &) override;
@@ -3966,16 +3964,6 @@ void ItaniumMangleContextImpl::mangleSEH
if (shouldMangleDeclName(EnclosingDecl))
Mangler.mangle(EnclosingDecl);
else
- Mangler.getStream() << EnclosingDecl->getName();
-}
-
-void ItaniumMangleContextImpl::mangleSEHFinallyBlock(
- const NamedDecl *EnclosingDecl, raw_ostream &Out) {
- CXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "__fin_";
- if (shouldMangleDeclName(EnclosingDecl))
- Mangler.mangle(EnclosingDecl);
- else
Mangler.getStream() << EnclosingDecl->getName();
}
Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=234789&r1=234788&r2=234789&view=diff
==============================================================================
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Mon Apr 13 15:04:22 2015
@@ -94,7 +94,6 @@ class MicrosoftMangleContextImpl : publi
llvm::DenseMap<const NamedDecl *, unsigned> Uniquifier;
llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds;
llvm::DenseMap<const NamedDecl *, unsigned> SEHFilterIds;
- llvm::DenseMap<const NamedDecl *, unsigned> SEHFinallyIds;
public:
MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags)
@@ -152,8 +151,6 @@ public:
raw_ostream &Out) override;
void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
raw_ostream &Out) override;
- void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
- raw_ostream &Out) override;
void mangleStringLiteral(const StringLiteral *SL, raw_ostream &Out) override;
void mangleCXXVTableBitSet(const CXXRecordDecl *RD,
raw_ostream &Out) override;
@@ -2472,17 +2469,6 @@ void MicrosoftMangleContextImpl::mangleS
Mangler.mangleName(EnclosingDecl);
}
-void MicrosoftMangleContextImpl::mangleSEHFinallyBlock(
- const NamedDecl *EnclosingDecl, raw_ostream &Out) {
- MicrosoftCXXNameMangler Mangler(*this, Out);
- // The function body is in the same comdat as the function with the handler,
- // so the numbering here doesn't have to be the same across TUs.
- //
- // <mangled-name> ::= ?fin$ <filter-number> @0
- Mangler.getStream() << "\01?fin$" << SEHFinallyIds[EnclosingDecl]++ << "@0@";
- Mangler.mangleName(EnclosingDecl);
-}
-
void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) {
// This is just a made up unique string for the purposes of tbaa. undname
// does *not* know how to demangle it.
Modified: cfe/trunk/lib/CodeGen/CGException.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=234789&r1=234788&r2=234789&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGException.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGException.cpp Mon Apr 13 15:04:22 2015
@@ -23,7 +23,6 @@
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicInst.h"
-#include "llvm/Support/SaveAndRestore.h"
using namespace clang;
using namespace CodeGen;
@@ -409,6 +408,13 @@ llvm::Value *CodeGenFunction::getSelecto
return Builder.CreateLoad(getEHSelectorSlot(), "sel");
}
+llvm::Value *CodeGenFunction::getAbnormalTerminationSlot() {
+ if (!AbnormalTerminationSlot)
+ AbnormalTerminationSlot =
+ CreateTempAlloca(Int8Ty, "abnormal.termination.slot");
+ return AbnormalTerminationSlot;
+}
+
void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E,
bool KeepInsertionPoint) {
if (const Expr *SubExpr = E->getSubExpr()) {
@@ -1281,7 +1287,8 @@ void CodeGenFunction::EmitSEHTryStmt(con
return;
}
- EnterSEHTryStmt(S);
+ SEHFinallyInfo FI;
+ EnterSEHTryStmt(S, FI);
{
JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave");
@@ -1294,36 +1301,42 @@ void CodeGenFunction::EmitSEHTryStmt(con
else
delete TryExit.getBlock();
}
- ExitSEHTryStmt(S);
+ ExitSEHTryStmt(S, FI);
}
namespace {
-struct PerformSEHFinally : EHScopeStack::Cleanup {
- llvm::Function *OutlinedFinally;
- PerformSEHFinally(llvm::Function *OutlinedFinally)
- : OutlinedFinally(OutlinedFinally) {}
+struct PerformSEHFinally : EHScopeStack::Cleanup {
+ CodeGenFunction::SEHFinallyInfo *FI;
+ PerformSEHFinally(CodeGenFunction::SEHFinallyInfo *FI) : FI(FI) {}
void Emit(CodeGenFunction &CGF, Flags F) override {
- ASTContext &Context = CGF.getContext();
- QualType ArgTys[2] = {Context.BoolTy, Context.VoidPtrTy};
- FunctionProtoType::ExtProtoInfo EPI;
- const auto *FTP = cast<FunctionType>(
- Context.getFunctionType(Context.VoidTy, ArgTys, EPI));
-
- CallArgList Args;
- llvm::Value *IsForEH =
- llvm::ConstantInt::get(CGF.ConvertType(ArgTys[0]), F.isForEHCleanup());
- Args.add(RValue::get(IsForEH), ArgTys[0]);
-
- CodeGenModule &CGM = CGF.CGM;
- llvm::Value *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0);
- llvm::Value *FrameAddr = CGM.getIntrinsic(llvm::Intrinsic::frameaddress);
- llvm::Value *FP = CGF.Builder.CreateCall(FrameAddr, Zero);
- Args.add(RValue::get(FP), ArgTys[1]);
-
- const CGFunctionInfo &FnInfo =
- CGM.getTypes().arrangeFreeFunctionCall(Args, FTP, /*chainCall=*/false);
- CGF.EmitCall(FnInfo, OutlinedFinally, ReturnValueSlot(), Args);
+ // Cleanups are emitted at most twice: once for normal control flow and once
+ // for exception control flow. Branch into the finally block, and remember
+ // the continuation block so we can branch out later.
+ if (!FI->FinallyBB) {
+ FI->FinallyBB = CGF.createBasicBlock("__finally");
+ FI->FinallyBB->insertInto(CGF.CurFn);
+ FI->FinallyBB->moveAfter(CGF.Builder.GetInsertBlock());
+ }
+
+ // Set the termination status and branch in.
+ CGF.Builder.CreateStore(
+ llvm::ConstantInt::get(CGF.Int8Ty, F.isForEHCleanup()),
+ CGF.getAbnormalTerminationSlot());
+ CGF.Builder.CreateBr(FI->FinallyBB);
+
+ // Create a continuation block for normal or exceptional control.
+ if (F.isForEHCleanup()) {
+ assert(!FI->ResumeBB && "double emission for EH");
+ FI->ResumeBB = CGF.createBasicBlock("__finally.resume");
+ CGF.EmitBlock(FI->ResumeBB);
+ } else {
+ assert(F.isForNormalCleanup() && !FI->ContBB && "double normal emission");
+ FI->ContBB = CGF.createBasicBlock("__finally.cont");
+ CGF.EmitBlock(FI->ContBB);
+ // Try to keep source order.
+ FI->ContBB->moveAfter(FI->FinallyBB);
+ }
}
};
}
@@ -1341,8 +1354,7 @@ struct CaptureFinder : ConstStmtVisitor<
// See if this is a capture, then recurse.
ConstStmtVisitor<CaptureFinder>::Visit(S);
for (const Stmt *Child : S->children())
- if (Child)
- Visit(Child);
+ Visit(Child);
}
void VisitDeclRefExpr(const DeclRefExpr *E) {
@@ -1391,16 +1403,12 @@ void CodeGenFunction::EmitCapturedLocals
CGM.ErrorUnsupported(VD, "VLA captured by SEH");
continue;
}
+
assert((isa<ImplicitParamDecl>(VD) || VD->isLocalVarDeclOrParm()) &&
"captured non-local variable");
- // If this decl hasn't been declared yet, it will be declared in the
- // OutlinedStmt.
- auto I = ParentCGF.LocalDeclMap.find(VD);
- if (I == ParentCGF.LocalDeclMap.end())
- continue;
- llvm::Value *ParentVar = I->second;
-
+ 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)) {
@@ -1437,81 +1445,63 @@ void CodeGenFunction::EmitCapturedLocals
}
}
-/// Arrange a function prototype that can be called by Windows exception
-/// handling personalities. On Win64, the prototype looks like:
-/// RetTy func(void *EHPtrs, void *ParentFP);
-void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
- StringRef Name, QualType RetTy,
- FunctionArgList &Args,
- const Stmt *OutlinedStmt) {
- llvm::Function *ParentFn = ParentCGF.CurFn;
- const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionDeclaration(
- RetTy, Args, FunctionType::ExtInfo(), /*isVariadic=*/false);
-
- llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
- llvm::Function *Fn = llvm::Function::Create(
- FnTy, llvm::GlobalValue::InternalLinkage, Name.str(), &CGM.getModule());
- // The filter is either in the same comdat as the function, or it's internal.
- if (llvm::Comdat *C = ParentFn->getComdat()) {
- Fn->setComdat(C);
- } else if (ParentFn->hasWeakLinkage() || ParentFn->hasLinkOnceLinkage()) {
- llvm::Comdat *C = CGM.getModule().getOrInsertComdat(ParentFn->getName());
- ParentFn->setComdat(C);
- Fn->setComdat(C);
- } else {
- Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
- }
-
- IsOutlinedSEHHelper = true;
-
- StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args,
- OutlinedStmt->getLocStart(), OutlinedStmt->getLocStart());
-
- CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn);
-
- auto AI = Fn->arg_begin();
- ++AI;
- EmitCapturedLocals(ParentCGF, OutlinedStmt, &*AI);
-}
-
/// 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.
llvm::Function *
CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
const SEHExceptStmt &Except) {
- const Expr *FilterExpr = Except.getFilterExpr();
- SourceLocation StartLoc = FilterExpr->getLocStart();
+ const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
+ llvm::Function *ParentFn = ParentCGF.CurFn;
- SEHPointersDecl = ImplicitParamDecl::Create(
- getContext(), nullptr, StartLoc,
- &getContext().Idents.get("exception_pointers"), getContext().VoidPtrTy);
- FunctionArgList Args;
- Args.push_back(SEHPointersDecl);
- Args.push_back(ImplicitParamDecl::Create(
- getContext(), nullptr, StartLoc,
- &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
+ Expr *FilterExpr = Except.getFilterExpr();
// Get the mangled function name.
SmallString<128> Name;
{
llvm::raw_svector_ostream OS(Name);
- const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
CGM.getCXXABI().getMangleContext().mangleSEHFilterExpression(Parent, OS);
}
- startOutlinedSEHHelper(ParentCGF, Name, getContext().IntTy, Args, FilterExpr);
+ // Arrange a function with the declaration:
+ // int filt(EXCEPTION_POINTERS *exception_pointers, void *frame_pointer)
+ QualType RetTy = getContext().IntTy;
+ FunctionArgList Args;
+ SEHPointersDecl = ImplicitParamDecl::Create(
+ getContext(), nullptr, FilterExpr->getLocStart(),
+ &getContext().Idents.get("exception_pointers"), getContext().VoidPtrTy);
+ Args.push_back(SEHPointersDecl);
+ Args.push_back(ImplicitParamDecl::Create(
+ getContext(), nullptr, FilterExpr->getLocStart(),
+ &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
+ const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionDeclaration(
+ RetTy, Args, FunctionType::ExtInfo(), /*isVariadic=*/false);
+ llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
+ llvm::Function *Fn = llvm::Function::Create(FnTy, ParentFn->getLinkage(),
+ Name.str(), &CGM.getModule());
+ // The filter is either in the same comdat as the function, or it's internal.
+ if (llvm::Comdat *C = ParentFn->getComdat()) {
+ Fn->setComdat(C);
+ } else if (ParentFn->hasWeakLinkage() || ParentFn->hasLinkOnceLinkage()) {
+ // FIXME: Unreachable with Rafael's changes?
+ llvm::Comdat *C = CGM.getModule().getOrInsertComdat(ParentFn->getName());
+ ParentFn->setComdat(C);
+ Fn->setComdat(C);
+ } else {
+ Fn->setLinkage(llvm::GlobalValue::InternalLinkage);
+ }
- // Mark finally block calls as nounwind and noinline to make LLVM's job a
- // little easier.
- // FIXME: Remove these restrictions in the future.
- CurFn->addFnAttr(llvm::Attribute::NoUnwind);
- CurFn->addFnAttr(llvm::Attribute::NoInline);
+ StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args,
+ FilterExpr->getLocStart(), FilterExpr->getLocStart());
EmitSEHExceptionCodeSave();
+ auto AI = Fn->arg_begin();
+ ++AI;
+ EmitCapturedLocals(ParentCGF, FilterExpr, &*AI);
+
// Emit the original filter expression, convert to i32, and return.
llvm::Value *R = EmitScalarExpr(FilterExpr);
R = Builder.CreateIntCast(R, CGM.IntTy,
@@ -1520,42 +1510,7 @@ CodeGenFunction::GenerateSEHFilterFuncti
FinishFunction(FilterExpr->getLocEnd());
- return CurFn;
-}
-
-llvm::Function *
-CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
- const SEHFinallyStmt &Finally) {
- const Stmt *FinallyBlock = Finally.getBlock();
- SourceLocation StartLoc = FinallyBlock->getLocStart();
-
- FunctionArgList Args;
- Args.push_back(ImplicitParamDecl::Create(
- getContext(), nullptr, StartLoc,
- &getContext().Idents.get("abnormal_termination"), getContext().BoolTy));
- Args.push_back(ImplicitParamDecl::Create(
- getContext(), nullptr, StartLoc,
- &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
-
- // Get the mangled function name.
- SmallString<128> Name;
- {
- llvm::raw_svector_ostream OS(Name);
- const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
- const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
- assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
- CGM.getCXXABI().getMangleContext().mangleSEHFinallyBlock(Parent, OS);
- }
-
- startOutlinedSEHHelper(ParentCGF, Name, getContext().VoidTy, Args,
- FinallyBlock);
-
- // Emit the original filter expression, convert to i32, and return.
- EmitStmt(FinallyBlock);
-
- FinishFunction(FinallyBlock->getLocEnd());
-
- return CurFn;
+ return Fn;
}
void CodeGenFunction::EmitSEHExceptionCodeSave() {
@@ -1599,24 +1554,21 @@ llvm::Value *CodeGenFunction::EmitSEHExc
}
llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() {
- // Abnormal termination is just the first parameter to the outlined finally
- // helper.
- auto AI = CurFn->arg_begin();
- return Builder.CreateZExt(&*AI, Int32Ty);
+ // Load from the abnormal termination slot. It will be uninitialized outside
+ // of __finally blocks, which we should warn or error on.
+ llvm::Value *IsEH = Builder.CreateLoad(getAbnormalTerminationSlot());
+ return Builder.CreateZExt(IsEH, Int32Ty);
}
-void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
- CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
- if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
+void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI) {
+ if (S.getFinallyHandler()) {
// Push a cleanup for __finally blocks.
- llvm::Function *FinallyFunc =
- HelperCGF.GenerateSEHFinallyFunction(*this, *Finally);
- EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc);
+ EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, &FI);
return;
}
// Otherwise, we must have an __except block.
- const SEHExceptStmt *Except = S.getExceptHandler();
+ SEHExceptStmt *Except = S.getExceptHandler();
assert(Except);
EHCatchScope *CatchScope = EHStack.pushCatch(1);
@@ -1631,17 +1583,40 @@ void CodeGenFunction::EnterSEHTryStmt(co
// In general, we have to emit an outlined filter function. Use the function
// in place of the RTTI typeinfo global that C++ EH uses.
+ CodeGenFunction FilterCGF(CGM, /*suppressNewContext=*/true);
llvm::Function *FilterFunc =
- HelperCGF.GenerateSEHFilterFunction(*this, *Except);
+ FilterCGF.GenerateSEHFilterFunction(*this, *Except);
llvm::Constant *OpaqueFunc =
llvm::ConstantExpr::getBitCast(FilterFunc, Int8PtrTy);
CatchScope->setHandler(0, OpaqueFunc, createBasicBlock("__except"));
}
-void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {
+void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI) {
// Just pop the cleanup if it's a __finally block.
- if (S.getFinallyHandler()) {
+ if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
PopCleanupBlock();
+ assert(FI.ContBB && "did not emit normal cleanup");
+
+ // Emit the code into FinallyBB.
+ CGBuilderTy::InsertPoint SavedIP = Builder.saveIP();
+ Builder.SetInsertPoint(FI.FinallyBB);
+ EmitStmt(Finally->getBlock());
+
+ if (HaveInsertPoint()) {
+ if (FI.ResumeBB) {
+ llvm::Value *IsEH = Builder.CreateLoad(getAbnormalTerminationSlot(),
+ "abnormal.termination");
+ IsEH = Builder.CreateICmpEQ(IsEH, llvm::ConstantInt::get(Int8Ty, 0));
+ Builder.CreateCondBr(IsEH, FI.ContBB, FI.ResumeBB);
+ } else {
+ // There was nothing exceptional in the try body, so we only have normal
+ // control flow.
+ Builder.CreateBr(FI.ContBB);
+ }
+ }
+
+ Builder.restoreIP(SavedIP);
+
return;
}
@@ -1691,13 +1666,7 @@ void CodeGenFunction::EmitSEHLeaveStmt(c
if (HaveInsertPoint())
EmitStopPoint(&S);
- // This must be a __leave from a __finally block, which we warn on and is UB.
- // Just emit unreachable.
- if (!isSEHTryScope()) {
- Builder.CreateUnreachable();
- Builder.ClearInsertionPoint();
- return;
- }
-
+ assert(!SEHTryEpilogueStack.empty() &&
+ "sema should have rejected this __leave");
EmitBranchThroughCleanup(*SEHTryEpilogueStack.back());
}
Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=234789&r1=234788&r2=234789&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Mon Apr 13 15:04:22 2015
@@ -1021,12 +1021,6 @@ void CodeGenFunction::EmitReturnOfRValue
/// if the function returns void, or may be missing one if the function returns
/// non-void. Fun stuff :).
void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
- // Returning from an outlined SEH helper is UB, and we already warn on it.
- if (IsOutlinedSEHHelper) {
- Builder.CreateUnreachable();
- Builder.ClearInsertionPoint();
- }
-
// Emit the result value, even if unused, to evalute the side effects.
const Expr *RV = S.getRetValue();
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=234789&r1=234788&r2=234789&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Mon Apr 13 15:04:22 2015
@@ -40,7 +40,7 @@ CodeGenFunction::CodeGenFunction(CodeGen
CurFn(nullptr), CapturedStmtInfo(nullptr),
SanOpts(CGM.getLangOpts().Sanitize), IsSanitizerScope(false),
CurFuncIsThunk(false), AutoreleaseResult(false), SawAsmBlock(false),
- IsOutlinedSEHHelper(false), BlockInfo(nullptr), BlockPointer(nullptr),
+ BlockInfo(nullptr), BlockPointer(nullptr),
LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr),
NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr),
ExceptionSlot(nullptr), EHSelectorSlot(nullptr),
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=234789&r1=234788&r2=234789&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon Apr 13 15:04:22 2015
@@ -263,10 +263,6 @@ public:
/// potentially set the return value.
bool SawAsmBlock;
- /// True if the current function is an outlined SEH helper. This can be a
- /// finally block or filter expression.
- bool IsOutlinedSEHHelper;
-
const CodeGen::CGBlockInfo *BlockInfo;
llvm::Value *BlockPointer;
@@ -355,6 +351,17 @@ public:
void exit(CodeGenFunction &CGF);
};
+ /// Cleanups can be emitted for two reasons: normal control leaving a region
+ /// exceptional control flow leaving a region.
+ struct SEHFinallyInfo {
+ SEHFinallyInfo()
+ : FinallyBB(nullptr), ContBB(nullptr), ResumeBB(nullptr) {}
+
+ llvm::BasicBlock *FinallyBB;
+ llvm::BasicBlock *ContBB;
+ llvm::BasicBlock *ResumeBB;
+ };
+
/// Returns true inside SEH __try blocks.
bool isSEHTryScope() const { return !SEHTryEpilogueStack.empty(); }
@@ -1045,6 +1052,10 @@ public:
llvm::Value *getExceptionSlot();
llvm::Value *getEHSelectorSlot();
+ /// Stack slot that contains whether a __finally block is being executed as an
+ /// EH cleanup or as a normal cleanup.
+ llvm::Value *getAbnormalTerminationSlot();
+
/// Returns the contents of the function's exception object and selector
/// slots.
llvm::Value *getExceptionFromSlot();
@@ -1989,19 +2000,12 @@ public:
void EmitCXXTryStmt(const CXXTryStmt &S);
void EmitSEHTryStmt(const SEHTryStmt &S);
void EmitSEHLeaveStmt(const SEHLeaveStmt &S);
- void EnterSEHTryStmt(const SEHTryStmt &S);
- void ExitSEHTryStmt(const SEHTryStmt &S);
-
- void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, StringRef Name,
- QualType RetTy, FunctionArgList &Args,
- const Stmt *OutlinedStmt);
+ void EnterSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI);
+ void ExitSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI);
llvm::Function *GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
const SEHExceptStmt &Except);
- llvm::Function *GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
- const SEHFinallyStmt &Finally);
-
void EmitSEHExceptionCodeSave();
llvm::Value *EmitSEHExceptionCode();
llvm::Value *EmitSEHExceptionInfo();
Modified: cfe/trunk/test/CodeGen/exceptions-seh-finally.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/exceptions-seh-finally.c?rev=234789&r1=234788&r2=234789&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/exceptions-seh-finally.c (original)
+++ cfe/trunk/test/CodeGen/exceptions-seh-finally.c Mon Apr 13 15:04:22 2015
@@ -17,20 +17,30 @@ void basic_finally(void) {
// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[invoke_cont]]
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@basic_finally@@"(i1 zeroext false, i8* %[[fp]])
+// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]]
+// CHECK: br label %[[finally:[^ ]*]]
+//
+// CHECK: [[finally]]
+// CHECK: call void @cleanup()
+// CHECK: load i8, i8* %[[abnormal]]
+// CHECK: icmp eq
+// CHECK: br i1 %{{.*}}, label %[[finallycont:[^ ]*]], label %[[resumecont:[^ ]*]]
+//
+// CHECK: [[finallycont]]
// CHECK-NEXT: ret void
//
// CHECK: [[lpad]]
// CHECK-NEXT: landingpad
// CHECK-NEXT: cleanup
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@basic_finally@@"(i1 zeroext true, i8* %[[fp]])
+// CHECK: store i8 1, i8* %[[abnormal]]
+// CHECK: br label %[[finally]]
+//
+// CHECK: [[resumecont]]
+// CHECK: br label %[[ehresume:[^ ]*]]
+//
+// CHECK: [[ehresume]]
// CHECK: resume { i8*, i32 }
-// CHECK: define internal void @"\01?fin$0 at 0@basic_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
-// CHECK: call void @cleanup()
-
// Mostly check that we don't double emit 'r' which would crash.
void decl_in_finally(void) {
__try {
@@ -57,11 +67,10 @@ l:
// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[invoke_cont]]
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@label_in_finally@@"(i1 zeroext false, i8* %[[fp]])
-// CHECK: ret void
-
-// CHECK: define internal void @"\01?fin$0 at 0@label_in_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
+// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]]
+// CHECK: br label %[[finally:[^ ]*]]
+//
+// CHECK: [[finally]]
// CHECK: br label %[[l:[^ ]*]]
//
// CHECK: [[l]]
@@ -84,22 +93,32 @@ void use_abnormal_termination(void) {
// CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[invoke_cont]]
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@use_abnormal_termination@@"(i1 zeroext false, i8* %[[fp]])
-// CHECK: ret void
+// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]]
+// CHECK: br label %[[finally:[^ ]*]]
+//
+// CHECK: [[finally]]
+// CHECK: load i8, i8* %[[abnormal]]
+// CHECK: zext i8 %{{.*}} to i32
+// CHECK: store i32 %{{.*}}, i32* @crashed
+// CHECK: load i8, i8* %[[abnormal]]
+// CHECK: icmp eq
+// CHECK: br i1 %{{.*}}, label %[[finallycont:[^ ]*]], label %[[resumecont:[^ ]*]]
+//
+// CHECK: [[finallycont]]
+// CHECK-NEXT: ret void
//
// CHECK: [[lpad]]
// CHECK-NEXT: landingpad
// CHECK-NEXT: cleanup
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@use_abnormal_termination@@"(i1 zeroext true, i8* %[[fp]])
+// CHECK: store i8 1, i8* %[[abnormal]]
+// CHECK: br label %[[finally]]
+//
+// CHECK: [[resumecont]]
+// CHECK: br label %[[ehresume:[^ ]*]]
+//
+// CHECK: [[ehresume]]
// CHECK: resume { i8*, i32 }
-// CHECK: define internal void @"\01?fin$0 at 0@use_abnormal_termination@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
-// CHECK: %[[abnormal_zext:[^ ]*]] = zext i1 %abnormal_termination to i32
-// CHECK: store i32 %[[abnormal_zext]], i32* @crashed
-// CHECK-NEXT: ret void
-
void noreturn_noop_finally() {
__try {
__noop();
@@ -109,13 +128,12 @@ void noreturn_noop_finally() {
}
// CHECK-LABEL: define void @noreturn_noop_finally()
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@noreturn_noop_finally@@"(i1 zeroext false, i8* %[[fp]])
-// CHECK: ret void
-
-// CHECK: define internal void @"\01?fin$0 at 0@noreturn_noop_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
+// CHECK: store i8 0, i8* %
+// CHECK: br label %[[finally:[^ ]*]]
+// CHECK: [[finally]]
// CHECK: call void @abort()
-// CHECK: unreachable
+// CHECK-NEXT: unreachable
+// CHECK-NOT: load
void noreturn_finally() {
__try {
@@ -130,20 +148,18 @@ void noreturn_finally() {
// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[cont]]
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@noreturn_finally@@"(i1 zeroext false, i8* %[[fp]])
-// CHECK: ret void
+// CHECK: store i8 0, i8* %
+// CHECK: br label %[[finally:[^ ]*]]
+//
+// CHECK: [[finally]]
+// CHECK: call void @abort()
+// CHECK-NEXT: unreachable
//
// CHECK: [[lpad]]
// CHECK: landingpad
// CHECK-NEXT: cleanup
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@noreturn_finally@@"(i1 zeroext true, i8* %[[fp]])
-// CHECK: resume { i8*, i32 }
-
-// CHECK: define internal void @"\01?fin$0 at 0@noreturn_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
-// CHECK: call void @abort()
-// CHECK: unreachable
+// CHECK: store i8 1, i8* %
+// CHECK: br label %[[finally]]
int finally_with_return() {
__try {
@@ -152,15 +168,15 @@ int finally_with_return() {
}
}
// CHECK-LABEL: define i32 @finally_with_return()
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: call void @"\01?fin$0 at 0@finally_with_return@@"(i1 zeroext false, i8* %[[fp]])
+// CHECK: store i8 0, i8* %
+// CHECK-NEXT: br label %[[finally:[^ ]*]]
+//
+// CHECK: [[finally]]
+// CHECK-NEXT: br label %[[finallycont:[^ ]*]]
+//
+// CHECK: [[finallycont]]
// CHECK-NEXT: ret i32 42
-// CHECK: define internal void @"\01?fin$0 at 0@finally_with_return@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
-// CHECK-NOT: br i1
-// CHECK-NOT: br label
-// CHECK: ret void
-
int nested___finally___finally() {
__try {
__try {
@@ -172,28 +188,38 @@ int nested___finally___finally() {
}
return 0;
}
-
// CHECK-LABEL: define i32 @nested___finally___finally
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: invoke void @"\01?fin$1 at 0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]])
-// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
-//
-// CHECK: [[outercont]]
-// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: call void @"\01?fin$0 at 0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]])
-// CHECK-NEXT: ret i32 0
+// CHECK: store i8 0, i8* %
+// CHECK-NEXT: br label %[[finally:[^ ]*]]
//
-// CHECK: [[lpad]]
-// CHECK-NEXT: landingpad
-// CHECK-NEXT: cleanup
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: call void @"\01?fin$0 at 0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]])
-
-// CHECK-LABEL: define internal void @"\01?fin$0 at 0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
-// CHECK: ret void
-
-// CHECK-LABEL: define internal void @"\01?fin$1 at 0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
-// CHECK: unreachable
+// CHECK: [[finally]]
+// CHECK-NEXT: store i32 1, i32* %
+// CHECK-NEXT: store i32 1, i32* %
+// CHECK-NEXT: br label %[[cleanup:[^ ]*]]
+//
+// The finally's unreachable continuation block:
+// CHECK: store i32 0, i32* %
+// CHECK-NEXT: br label %[[cleanup]]
+//
+// CHECK: [[cleanup]]
+// CHECK-NEXT: store i8 0, i8* %
+// CHECK-NEXT: br label %[[outerfinally:[^ ]*]]
+//
+// CHECK: [[outerfinally]]
+// CHECK-NEXT: br label %[[finallycont:[^ ]*]]
+//
+// CHECK: [[finallycont]]
+// CHECK-NEXT: %[[dest:[^ ]*]] = load i32, i32* %
+// CHECK-NEXT: switch i32 %[[dest]]
+// CHECK-NEXT: i32 0, label %[[cleanupcont:[^ ]*]]
+//
+// CHECK: [[cleanupcont]]
+// CHECK-NEXT: store i32 0, i32* %
+// CHECK-NEXT: br label %[[return:[^ ]*]]
+//
+// CHECK: [[return]]
+// CHECK-NEXT: %[[reg:[^ ]*]] = load i32, i32* %
+// CHECK-NEXT: ret i32 %[[reg]]
int nested___finally___finally_with_eh_edge() {
__try {
@@ -208,35 +234,58 @@ int nested___finally___finally_with_eh_e
return 912;
}
// CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge
-// CHECK: invoke void @might_crash()
-// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
+// CHECK: invoke void @might_crash() #3
+// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
-// [[invokecont]]
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: invoke void @"\01?fin$1 at 0@nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]])
-// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
-//
-// CHECK: [[outercont]]
-// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: call void @"\01?fin$0 at 0@nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]])
-// CHECK-NEXT: ret i32 912
+// CHECK: [[invokecont]]
+// CHECK-NEXT: store i8 0, i8* %[[abnormal:[^ ]*]]
+// CHECK-NEXT: br label %[[finally:[^ ]*]]
+
+// CHECK: [[finally]]
+// CHECK-NEXT: store i32 899, i32* %
+// CHECK-NEXT: store i32 1, i32* %
+// CHECK-NEXT: br label %[[cleanup:[^ ]*]]
+//
+// The inner finally's unreachable continuation block:
+// CHECK: store i32 0, i32* %
+// CHECK-NEXT: br label %[[cleanup]]
+//
+// CHECK: [[cleanup]]
+// CHECK-NEXT: store i8 0, i8* %
+// CHECK-NEXT: br label %[[outerfinally:[^ ]*]]
+//
+// CHECK: [[outerfinally]]
+// CHECK-NEXT: %[[abnormallocal:[^ ]*]] = load i8, i8* %[[abnormal]]
+// CHECK-NEXT: %[[reg:[^ ]*]] = icmp eq i8 %[[abnormallocal]], 0
+// CHECK-NEXT: br i1 %[[reg]], label %[[finallycont:[^ ]*]], label %[[finallyresume:[^ ]*]]
+//
+// CHECK: [[finallycont]]
+// CHECK-NEXT: %[[dest:[^ ]*]] = load i32, i32* %
+// CHECK-NEXT: switch i32 %[[dest]]
+// CHECK-NEXT: i32 0, label %[[cleanupcont:[^ ]*]]
+//
+// CHECK: [[cleanupcont]]
+// CHECK-NEXT: store i32 912, i32* %
+// CHECK-NEXT: br label %[[return:[^ ]*]]
//
-// CHECK: [[lpad1]]
-// CHECK-NEXT: landingpad
-// CHECK-NEXT: cleanup
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: invoke void @"\01?fin$1 at 0@nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]])
-// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2]]
//
-// CHECK: [[lpad2]]
+// CHECK: [[lpad]]
// CHECK-NEXT: landingpad
// CHECK-NEXT: cleanup
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]])
+// CHECK: store i8 1, i8* %[[abnormal]]
+// CHECK: br label %[[finally]]
+//
+// The inner finally's unreachable resume block:
+// CHECK: store i8 1, i8* %[[abnormal]]
+// CHECK-NEXT: br label %[[outerfinally]]
+//
+// CHECK: [[finallyresume]]
+// CHECK-NEXT: br label %[[ehresume:[^ ]*]]
+//
+// CHECK: [[return]]
+// CHECK-NEXT: %[[reg:[^ ]*]] = load i32, i32* %
+// CHECK-NEXT: ret i32 %[[reg]]
+//
+// The ehresume block, not reachable either.
+// CHECK: [[ehresume]]
// CHECK: resume
-
-// CHECK-LABEL: define internal void @"\01?fin$0 at 0@nested___finally___finally_with_eh_edge@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
-// CHECK: ret void
-
-// CHECK-LABEL: define internal void @"\01?fin$1 at 0@nested___finally___finally_with_eh_edge@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
-// CHECK: unreachable
Modified: cfe/trunk/test/CodeGen/exceptions-seh-leave.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/exceptions-seh-leave.c?rev=234789&r1=234788&r2=234789&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/exceptions-seh-leave.c (original)
+++ cfe/trunk/test/CodeGen/exceptions-seh-leave.c Mon Apr 13 15:04:22 2015
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
-void g(void);
+void g();
//////////////////////////////////////////////////////////////////////////////
// __leave with __except
@@ -38,7 +38,7 @@ int __leave_with___except() {
return 1;
}
// CHECK-LABEL: define i32 @__leave_with___except()
-// CHECK: invoke void @g()
+// CHECK: invoke void bitcast (void (...)* @g to void ()*)()
// CHECK-NEXT: to label %[[cont:.*]] unwind label %{{.*}}
// For __excepts, instead of an explicit __try.__leave label, we could use
// use invoke.cont as __leave jump target instead. However, not doing this
@@ -74,8 +74,8 @@ int __leave_with___finally_simple() {
// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
// CHECK-NOT: store i32 23
// CHECK: [[tryleave]]
-// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: call void @"\01?fin$0 at 0@__leave_with___finally_simple@@"(i1 zeroext false, i8* %[[fp]])
+// CHECK-NEXT: store i8 0, i8* %
+// CHECK-NEXT: br label %
// __finally block doesn't return, __finally.cont doesn't exist.
int __leave_with___finally_noreturn() {
@@ -94,8 +94,8 @@ int __leave_with___finally_noreturn() {
// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
// CHECK-NOT: store i32 23
// CHECK: [[tryleave]]
-// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: call void @"\01?fin$0 at 0@__leave_with___finally_noreturn@@"(i1 zeroext false, i8* %[[fp]])
+// CHECK-NEXT: store i8 0, i8* %
+// CHECK-NEXT: br label %
// The "normal" case.
int __leave_with___finally() {
@@ -110,7 +110,7 @@ int __leave_with___finally() {
return 1;
}
// CHECK-LABEL: define i32 @__leave_with___finally()
-// CHECK: invoke void @g()
+// CHECK: invoke void bitcast (void (...)* @g to void ()*)()
// CHECK-NEXT: to label %[[cont:.*]] unwind label %{{.*}}
// For __finally, there needs to be an explicit __try.__leave, because
// abnormal.termination.slot needs to be set there.
@@ -118,8 +118,8 @@ int __leave_with___finally() {
// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
// CHECK-NOT: store i32 23
// CHECK: [[tryleave]]
-// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: call void @"\01?fin$0 at 0@__leave_with___finally@@"(i1 zeroext false, i8* %[[fp]])
+// CHECK-NEXT: store i8 0, i8* %
+// CHECK-NEXT: br label %
//////////////////////////////////////////////////////////////////////////////
@@ -142,37 +142,45 @@ int nested___except___finally() {
}
return 1;
}
+// The order of basic blocks in the below doesn't matter.
// CHECK-LABEL: define i32 @nested___except___finally()
-// CHECK-LABEL: invoke void @g()
-// CHECK-NEXT: to label %[[g1_cont1:.*]] unwind label %[[g1_lpad:.*]]
+// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)()
+// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
+
+// CHECK: [[g1_cont]]
+// CHECK-NEXT: store i8 0, i8* %[[abnormal:[^ ]*]]
+// CHECK-NEXT: br label %[[finally:[^ ]*]]
-// CHECK: [[g1_cont1]]
-// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: invoke void @"\01?fin$0 at 0@nested___except___finally@@"(i1 zeroext false, i8* %[[fp]])
-// CHECK-NEXT: to label %[[fin_cont:.*]] unwind label %[[g2_lpad:.*]]
+// CHECK: [[finally]]
+// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)()
+// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]]
+
+// CHECK: [[g2_cont]]
+// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
+// CHECK-NOT: store i32 23
-// CHECK: [[fin_cont]]
+// Unused __finally continuation block
// CHECK: store i32 51, i32* %
+// CHECK-NEXT: br label %[[tryleave]]
+
+// CHECK: [[tryleave]]
// CHECK-NEXT: br label %[[trycont:[^ ]*]]
// CHECK: [[g1_lpad]]
-// CHECK-NEXT: landingpad
-// CHECK-NEXT: catch i8* null
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: invoke void @"\01?fin$0 at 0@nested___except___finally@@"(i1 zeroext true, i8* %[[fp]])
-// CHECK-NEXT: to label %[[g1_resume:.*]] unwind label %[[g2_lpad]]
+// CHECK: store i8 1, i8* %
+// CHECK-NEXT: br label %[[finally]]
// CHECK: [[g2_lpad]]
-// CHECK: br label %[[trycont]]
+// CHECK-NOT: %[[abnormal]]
+// CHECK: br label %[[except:[^ ]*]]
+
+// CHECK: [[except]]
+// CHECK-NEXT: br label %[[trycont]]
// CHECK: [[trycont]]
// CHECK-NEXT: ret i32 1
-// CHECK-LABEL: define internal void @"\01?fin$0 at 0@nested___except___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
-// CHECK: call void @g()
-// CHECK: unreachable
-
int nested___except___except() {
int myres = 0;
__try {
@@ -194,7 +202,7 @@ int nested___except___except() {
// The order of basic blocks in the below doesn't matter.
// CHECK-LABEL: define i32 @nested___except___except()
-// CHECK-LABEL: invoke void @g()
+// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)()
// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
// CHECK: [[g1_cont]]
@@ -205,7 +213,7 @@ int nested___except___except() {
// CHECK: br label %[[except:[^ ]*]]
// CHECK: [[except]]
-// CHECK-NEXT: invoke void @g()
+// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)() #3
// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]]
// CHECK: [[g2_cont]]
@@ -248,7 +256,7 @@ int nested___finally___except() {
// The order of basic blocks in the below doesn't matter.
// CHECK-LABEL: define i32 @nested___finally___except()
-// CHECK-LABEL: invoke void @g()
+// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)()
// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
// CHECK: [[g1_cont]]
@@ -258,7 +266,7 @@ int nested___finally___except() {
// CHECK: br label %[[except:[^ ]*]]
// CHECK: [[except]]
-// CHECK-NEXT: invoke void @g()
+// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)()
// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]]
// CHECK: [[g2_cont]]
@@ -266,25 +274,31 @@ int nested___finally___except() {
// CHECK-NOT: 23
// CHECK: [[g2_lpad]]
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: call void @"\01?fin$0 at 0@nested___finally___except@@"(i1 zeroext true, i8* %[[fp]])
-// CHECK-NEXT: br label %[[ehresume:[^ ]*]]
+// CHECK: store i8 1, i8* %[[abnormal:[^ ]*]]
+// CHECK-NEXT: br label %[[finally:[^ ]*]]
// CHECK: [[trycont]]
// CHECK: store i32 51, i32* %
// CHECK-NEXT: br label %[[tryleave]]
// CHECK: [[tryleave]]
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: call void @"\01?fin$0 at 0@nested___finally___except@@"(i1 zeroext false, i8* %[[fp]])
+// CHECK-NEXT: store i8 0, i8* %[[abnormal]]
+// CHECK-NEXT: br label %[[finally:[^ ]*]]
+
+// CHECK: [[finally]]
+// CHECK-NEXT: %[[abnormallocal:[^ ]*]] = load i8, i8* %[[abnormal]]
+// CHECK-NEXT: %[[reg:[^ ]*]] = icmp eq i8 %[[abnormallocal]], 0
+// CHECK-NEXT: br i1 %[[reg]], label %[[finallycont:[^ ]*]], label %[[finallyresume:[^ ]*]]
+
+// CHECK: [[finallycont]]
// CHECK-NEXT: ret i32 1
+// CHECK: [[finallyresume]]
+// CHECK-NEXT: br label %[[ehresume:[^ ]*]]
+
// CHECK: [[ehresume]]
// CHECK: resume
-// CHECK-LABEL: define internal void @"\01?fin$0 at 0@nested___finally___except@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
-// CHECK: ret void
-
int nested___finally___finally() {
int myres = 0;
__try {
@@ -306,44 +320,51 @@ int nested___finally___finally() {
// The order of basic blocks in the below doesn't matter.
// CHECK-LABEL: define i32 @nested___finally___finally()
-// CHECK-LABEL: invoke void @g()
+// CHECK-LABEL: invoke void bitcast (void (...)* @g to void ()*)()
// CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]]
// CHECK: [[g1_cont]]
// CHECK: store i32 16, i32* %[[myres:[^ ]*]],
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: invoke void @"\01?fin$1 at 0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]])
-// CHECK-NEXT: to label %[[finally_cont:.*]] unwind label %[[g2_lpad:.*]]
+// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]]
+// CHECK-NEXT: br label %[[finally:[^ ]*]]
+
+// CHECK: [[finally]]
+// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)() #3
+// CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]]
+
+// CHECK: [[g2_cont]]
+// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
+// CHECK-NOT: store i32 23
-// CHECK: [[finally_cont]]
+// There's an unreachable block for the skipped `myres = 51`.
// CHECK: store i32 51, i32* %[[myres]]
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: call void @"\01?fin$0 at 0@nested___finally___finally@@"(i1 zeroext false, i8* %[[fp]])
+// CHECK-NEXT: br label %[[tryleave]]
+
+// CHECK: [[tryleave]]
+// CHECK-NEXT: store i8 0, i8* %[[abnormal]]
+// CHECK-NEXT: br label %[[outerfinally:[^ ]*]]
+
+// CHECK: [[outerfinally]]
+// CHECK-NEXT: %[[abnormallocal:[^ ]*]] = load i8, i8* %[[abnormal]]
+// CHECK-NEXT: %[[reg:[^ ]*]] = icmp eq i8 %[[abnormallocal]], 0
+// CHECK-NEXT: br i1 %[[reg]], label %[[finallycont:[^ ]*]], label %[[finallyresume:[^ ]*]]
+
+// CHECK: [[finallycont]]
// CHECK-NEXT: ret i32 1
// CHECK: [[g1_lpad]]
-// CHECK-NEXT: landingpad
-// CHECK-NEXT: cleanup
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: invoke void @"\01?fin$1 at 0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]])
-// CHECK-NEXT: to label %[[finally_cont2:.*]] unwind label %[[g2_lpad]]
+// CHECK: store i8 1, i8* %[[abnormal]]
+// CHECK-NEXT: br label %[[finally:[^ ]*]]
// CHECK: [[g2_lpad]]
-// CHECK-NEXT: landingpad
-// CHECK-NEXT: cleanup
-// CHECK: br label %[[ehcleanup:.*]]
-
-// CHECK: [[finally_cont2]]
-// CHECK: br label %[[ehcleanup]]
+// CHECK: br label %[[ehcleanup:[^ ]*]]
// CHECK: [[ehcleanup]]
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK-NEXT: call void @"\01?fin$0 at 0@nested___finally___finally@@"(i1 zeroext true, i8* %[[fp]])
-// CHECK: resume
+// CHECK-NEXT: store i8 1, i8* %[[abnormal]]
+// CHECK-NEXT: br label %[[outerfinally]]
-// CHECK-LABEL: define internal void @"\01?fin$0 at 0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
-// CHECK: ret void
+// CHECK: [[finallyresume]]
+// CHECK-NEXT: br label %[[ehresume:[^ ]*]]
-// CHECK-LABEL: define internal void @"\01?fin$1 at 0@nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
-// CHECK: call void @g()
-// CHECK: unreachable
+// CHECK: [[ehresume]]
+// CHECK: resume
Modified: cfe/trunk/test/CodeGen/exceptions-seh.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/exceptions-seh.c?rev=234789&r1=234788&r2=234789&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/exceptions-seh.c (original)
+++ cfe/trunk/test/CodeGen/exceptions-seh.c Mon Apr 13 15:04:22 2015
@@ -118,6 +118,8 @@ int nested_try(void) {
// CHECK: [[inner_try_cont]]
// CHECK: br label %[[outer_try_cont]]
+// FIXME: This lowering of __finally can't actually work, it will have to
+// change.
static unsigned g = 0;
void basic_finally(void) {
++g;
@@ -136,23 +138,24 @@ void basic_finally(void) {
// CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
//
// CHECK: [[cont]]
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@basic_finally@@"(i1 zeroext false, i8* %[[fp]])
+// CHECK: br label %[[finally:[^ ]*]]
+//
+// CHECK: [[finally]]
+// CHECK: load i32, i32* @g
+// CHECK: add i32 %{{.*}}, -1
+// CHECK: store i32 %{{.*}}, i32* @g
+// CHECK: icmp eq
+// CHECK: br i1 %{{.*}}, label
+//
// CHECK: ret void
//
// CHECK: [[lpad]]
// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
// CHECK-NEXT: cleanup
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@basic_finally@@"(i1 zeroext true, i8* %[[fp]])
+// CHECK: br label %[[finally]]
+//
// CHECK: resume
-// CHECK: define internal void @"\01?fin$0 at 0@basic_finally@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer)
-// CHECK: load i32, i32* @g, align 4
-// CHECK: add i32 %{{.*}}, -1
-// CHECK: store i32 %{{.*}}, i32* @g, align 4
-// CHECK: ret void
-
int returns_int(void);
int except_return(void) {
__try {
Modified: cfe/trunk/test/CodeGenCXX/exceptions-seh.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/exceptions-seh.cpp?rev=234789&r1=234788&r2=234789&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/exceptions-seh.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/exceptions-seh.cpp Mon Apr 13 15:04:22 2015
@@ -5,7 +5,6 @@
// RUN: -o - -mconstructor-aliases -O1 -disable-llvm-optzns | \
// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=NOCXX
-extern "C" unsigned long _exception_code();
extern "C" void might_throw();
struct HasCleanup {
@@ -96,47 +95,4 @@ void use_seh_in_lambda() {
// CHECK: invoke void @might_throw() #[[NOINLINE]]
// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
-static int my_unique_global;
-
-extern "C" inline void use_seh_in_inline_func() {
- __try {
- might_throw();
- } __except(_exception_code() == 424242) {
- }
- __try {
- might_throw();
- } __finally {
- my_unique_global = 1234;
- }
-}
-
-void use_inline() {
- use_seh_in_inline_func();
-}
-
-// CHECK-LABEL: define linkonce_odr void @use_seh_in_inline_func() #{{[0-9]+}} comdat {
-// CHECK: invoke void @might_throw()
-//
-// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
-// CHECK-NEXT: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0 at 0@use_seh_in_inline_func@@" to i8*)
-//
-// CHECK: invoke void @might_throw()
-//
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@use_seh_in_inline_func@@"(i1 zeroext false, i8* %[[fp]])
-// CHECK: ret void
-//
-// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
-// CHECK-NEXT: cleanup
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@use_seh_in_inline_func@@"(i1 zeroext true, i8* %[[fp]])
-
-// CHECK-LABEL: define internal i32 @"\01?filt$0 at 0@use_seh_in_inline_func@@"(i8* %exception_pointers, i8* %frame_pointer) #{{[0-9]+}} comdat($use_seh_in_inline_func)
-// CHECK: icmp eq i32 %{{.*}}, 424242
-// CHECK: zext i1 %{{.*}} to i32
-// CHECK: ret i32
-
-// CHECK-LABEL: define internal void @"\01?fin$0 at 0@use_seh_in_inline_func@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) #{{[0-9]+}} comdat($use_seh_in_inline_func)
-// CHECK: store i32 1234, i32* @my_unique_global
-
// CHECK: attributes #[[NOINLINE]] = { {{.*noinline.*}} }
More information about the cfe-commits
mailing list