I re-reverted this (and follow-ups 234614, 234616, 234618) in 234789 as it caused PR23216.
On Fri, Apr 10, 2015 at 10:34 AM, Reid Kleckner <[email protected]> wrote: > Author: rnk > Date: Fri Apr 10 12:34:52 2015 > New Revision: 234613 > > URL: http://llvm.org/viewvc/llvm-project?rev=234613&view=rev > Log: > [SEH] Re-land r234532, but use internal linkage for all SEH helpers > > Even though these symbols are in a comdat group, the Microsoft linker > really wants them to have internal linkage. > > I'm planning to tweak the mangling in a follow-up change. This is a > straight revert with a 1-line fix. > > 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 > > Modified: cfe/trunk/include/clang/AST/Mangle.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Mangle.h?rev=234613&r1=234612&r2=234613&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/AST/Mangle.h (original) > +++ cfe/trunk/include/clang/AST/Mangle.h Fri Apr 10 12:34:52 2015 > @@ -135,6 +135,9 @@ 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=234613&r1=234612&r2=234613&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original) > +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Fri Apr 10 12:34:52 2015 > @@ -166,6 +166,8 @@ 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; > @@ -3964,6 +3966,16 @@ 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=234613&r1=234612&r2=234613&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original) > +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Fri Apr 10 12:34:52 2015 > @@ -94,6 +94,7 @@ 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) > @@ -151,6 +152,8 @@ 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; > @@ -2469,6 +2472,17 @@ 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=234613&r1=234612&r2=234613&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGException.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGException.cpp Fri Apr 10 12:34:52 2015 > @@ -23,6 +23,7 @@ > #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; > @@ -408,13 +409,6 @@ 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()) { > @@ -1287,8 +1281,7 @@ void CodeGenFunction::EmitSEHTryStmt(con > return; > } > > - SEHFinallyInfo FI; > - EnterSEHTryStmt(S, FI); > + EnterSEHTryStmt(S); > { > JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave"); > > @@ -1301,42 +1294,36 @@ void CodeGenFunction::EmitSEHTryStmt(con > else > delete TryExit.getBlock(); > } > - ExitSEHTryStmt(S, FI); > + ExitSEHTryStmt(S); > } > > namespace { > -struct PerformSEHFinally : EHScopeStack::Cleanup { > - CodeGenFunction::SEHFinallyInfo *FI; > - PerformSEHFinally(CodeGenFunction::SEHFinallyInfo *FI) : FI(FI) {} > +struct PerformSEHFinally : EHScopeStack::Cleanup { > + llvm::Function *OutlinedFinally; > + PerformSEHFinally(llvm::Function *OutlinedFinally) > + : OutlinedFinally(OutlinedFinally) {} > > void Emit(CodeGenFunction &CGF, Flags F) override { > - // 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); > - } > + 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); > } > }; > } > @@ -1354,7 +1341,8 @@ struct CaptureFinder : ConstStmtVisitor< > // See if this is a capture, then recurse. > ConstStmtVisitor<CaptureFinder>::Visit(S); > for (const Stmt *Child : S->children()) > - Visit(Child); > + if (Child) > + Visit(Child); > } > > void VisitDeclRefExpr(const DeclRefExpr *E) { > @@ -1403,12 +1391,16 @@ void CodeGenFunction::EmitCapturedLocals > 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"); > + // 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::CallInst *RecoverCall = nullptr; > CGBuilderTy Builder(AllocaInsertPt); > if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) { > @@ -1445,47 +1437,24 @@ void CodeGenFunction::EmitCapturedLocals > } > } > > -/// 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 Decl *ParentCodeDecl = ParentCGF.CurCodeDecl; > +/// 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; > - > - Expr *FilterExpr = Except.getFilterExpr(); > - > - // Get the mangled function name. > - SmallString<128> Name; > - { > - llvm::raw_svector_ostream OS(Name); > - 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); > - } > - > - // 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()); > + 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()) { > - // FIXME: Unreachable with Rafael's changes? > llvm::Comdat *C = > CGM.getModule().getOrInsertComdat(ParentFn->getName()); > ParentFn->setComdat(C); > Fn->setComdat(C); > @@ -1493,14 +1462,55 @@ CodeGenFunction::GenerateSEHFilterFuncti > Fn->setLinkage(llvm::GlobalValue::InternalLinkage); > } > > + IsOutlinedSEHHelper = true; > + > StartFunction(GlobalDecl(), RetTy, Fn, FnInfo, Args, > - FilterExpr->getLocStart(), FilterExpr->getLocStart()); > + OutlinedStmt->getLocStart(), OutlinedStmt->getLocStart()); > > - EmitSEHExceptionCodeSave(); > + CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn); > > auto AI = Fn->arg_begin(); > ++AI; > - EmitCapturedLocals(ParentCGF, FilterExpr, &*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(); > + > + 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)); > + > + // 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); > + > + // 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); > + > + EmitSEHExceptionCodeSave(); > > // Emit the original filter expression, convert to i32, and return. > llvm::Value *R = EmitScalarExpr(FilterExpr); > @@ -1510,7 +1520,42 @@ CodeGenFunction::GenerateSEHFilterFuncti > > FinishFunction(FilterExpr->getLocEnd()); > > - return Fn; > + 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; > } > > void CodeGenFunction::EmitSEHExceptionCodeSave() { > @@ -1554,21 +1599,24 @@ llvm::Value *CodeGenFunction::EmitSEHExc > } > > llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() { > - // 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); > + // Abnormal termination is just the first parameter to the outlined > finally > + // helper. > + auto AI = CurFn->arg_begin(); > + return Builder.CreateZExt(&*AI, Int32Ty); > } > > -void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo > &FI) { > - if (S.getFinallyHandler()) { > +void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) { > + CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true); > + if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) { > // Push a cleanup for __finally blocks. > - EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, &FI); > + llvm::Function *FinallyFunc = > + HelperCGF.GenerateSEHFinallyFunction(*this, *Finally); > + EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, > FinallyFunc); > return; > } > > // Otherwise, we must have an __except block. > - SEHExceptStmt *Except = S.getExceptHandler(); > + const SEHExceptStmt *Except = S.getExceptHandler(); > assert(Except); > EHCatchScope *CatchScope = EHStack.pushCatch(1); > > @@ -1583,40 +1631,17 @@ 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 = > - FilterCGF.GenerateSEHFilterFunction(*this, *Except); > + HelperCGF.GenerateSEHFilterFunction(*this, *Except); > llvm::Constant *OpaqueFunc = > llvm::ConstantExpr::getBitCast(FilterFunc, Int8PtrTy); > CatchScope->setHandler(0, OpaqueFunc, createBasicBlock("__except")); > } > > -void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo > &FI) { > +void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) { > // Just pop the cleanup if it's a __finally block. > - if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) { > + if (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; > } > > @@ -1666,7 +1691,13 @@ void CodeGenFunction::EmitSEHLeaveStmt(c > if (HaveInsertPoint()) > EmitStopPoint(&S); > > - assert(!SEHTryEpilogueStack.empty() && > - "sema should have rejected this __leave"); > + // 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; > + } > + > EmitBranchThroughCleanup(*SEHTryEpilogueStack.back()); > } > > Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=234613&r1=234612&r2=234613&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGStmt.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGStmt.cpp Fri Apr 10 12:34:52 2015 > @@ -1021,6 +1021,12 @@ 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=234613&r1=234612&r2=234613&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original) > +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Fri Apr 10 12:34:52 2015 > @@ -41,7 +41,7 @@ CodeGenFunction::CodeGenFunction(CodeGen > CurFn(nullptr), CapturedStmtInfo(nullptr), > SanOpts(CGM.getLangOpts().Sanitize), IsSanitizerScope(false), > CurFuncIsThunk(false), AutoreleaseResult(false), SawAsmBlock(false), > - BlockInfo(nullptr), BlockPointer(nullptr), > + IsOutlinedSEHHelper(false), 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=234613&r1=234612&r2=234613&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) > +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Apr 10 12:34:52 2015 > @@ -263,6 +263,10 @@ 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; > > @@ -351,17 +355,6 @@ 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(); } > > @@ -1052,10 +1045,6 @@ 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(); > @@ -2003,12 +1992,19 @@ public: > void EmitCXXTryStmt(const CXXTryStmt &S); > void EmitSEHTryStmt(const SEHTryStmt &S); > void EmitSEHLeaveStmt(const SEHLeaveStmt &S); > - void EnterSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI); > - void ExitSEHTryStmt(const SEHTryStmt &S, SEHFinallyInfo &FI); > + void EnterSEHTryStmt(const SEHTryStmt &S); > + void ExitSEHTryStmt(const SEHTryStmt &S); > + > + void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, StringRef Name, > + QualType RetTy, FunctionArgList &Args, > + const Stmt *OutlinedStmt); > > 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=234613&r1=234612&r2=234613&view=diff > > ============================================================================== > --- cfe/trunk/test/CodeGen/exceptions-seh-finally.c (original) > +++ cfe/trunk/test/CodeGen/exceptions-seh-finally.c Fri Apr 10 12:34:52 > 2015 > @@ -17,30 +17,20 @@ void basic_finally(void) { > // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] > // > // CHECK: [[invoke_cont]] > -// 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: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext false, i8* > %[[fp]]) > // CHECK-NEXT: ret void > // > // CHECK: [[lpad]] > // CHECK-NEXT: landingpad > // CHECK-NEXT: cleanup > -// CHECK: store i8 1, i8* %[[abnormal]] > -// CHECK: br label %[[finally]] > -// > -// CHECK: [[resumecont]] > -// CHECK: br label %[[ehresume:[^ ]*]] > -// > -// CHECK: [[ehresume]] > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext true, i8* > %[[fp]]) > // CHECK: resume { i8*, i32 } > > +// CHECK: define internal void @"\01?fin$0@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 { > @@ -67,10 +57,11 @@ l: > // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] > // > // CHECK: [[invoke_cont]] > -// CHECK: store i8 0, i8* %[[abnormal:[^ ]*]] > -// CHECK: br label %[[finally:[^ ]*]] > -// > -// CHECK: [[finally]] > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK: call void @"\01?fin$0@0@label_in_finally@@"(i1 zeroext false, > i8* %[[fp]]) > +// CHECK: ret void > + > +// CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"(i1 > zeroext %abnormal_termination, i8* %frame_pointer) > // CHECK: br label %[[l:[^ ]*]] > // > // CHECK: [[l]] > @@ -93,32 +84,22 @@ void use_abnormal_termination(void) { > // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] > // > // CHECK: [[invoke_cont]] > -// 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: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext > false, i8* %[[fp]]) > +// CHECK: ret void > // > // CHECK: [[lpad]] > // CHECK-NEXT: landingpad > // CHECK-NEXT: cleanup > -// CHECK: store i8 1, i8* %[[abnormal]] > -// CHECK: br label %[[finally]] > -// > -// CHECK: [[resumecont]] > -// CHECK: br label %[[ehresume:[^ ]*]] > -// > -// CHECK: [[ehresume]] > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i1 zeroext > true, i8* %[[fp]]) > // CHECK: resume { i8*, i32 } > > +// CHECK: define internal void @"\01?fin$0@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(); > @@ -128,12 +109,13 @@ void noreturn_noop_finally() { > } > > // CHECK-LABEL: define void @noreturn_noop_finally() > -// CHECK: store i8 0, i8* % > -// CHECK: br label %[[finally:[^ ]*]] > -// CHECK: [[finally]] > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"(i1 zeroext > false, i8* %[[fp]]) > +// CHECK: ret void > + > +// CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"(i1 > zeroext %abnormal_termination, i8* %frame_pointer) > // CHECK: call void @abort() > -// CHECK-NEXT: unreachable > -// CHECK-NOT: load > +// CHECK: unreachable > > void noreturn_finally() { > __try { > @@ -148,18 +130,20 @@ void noreturn_finally() { > // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] > // > // CHECK: [[cont]] > -// CHECK: store i8 0, i8* % > -// CHECK: br label %[[finally:[^ ]*]] > -// > -// CHECK: [[finally]] > -// CHECK: call void @abort() > -// CHECK-NEXT: unreachable > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext false, > i8* %[[fp]]) > +// CHECK: ret void > // > // CHECK: [[lpad]] > // CHECK: landingpad > // CHECK-NEXT: cleanup > -// CHECK: store i8 1, i8* % > -// CHECK: br label %[[finally]] > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i1 zeroext true, > i8* %[[fp]]) > +// CHECK: resume { i8*, i32 } > + > +// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"(i1 > zeroext %abnormal_termination, i8* %frame_pointer) > +// CHECK: call void @abort() > +// CHECK: unreachable > > int finally_with_return() { > __try { > @@ -168,15 +152,17 @@ int finally_with_return() { > } > } > // CHECK-LABEL: define i32 @finally_with_return() > -// CHECK: store i8 0, i8* % > -// CHECK-NEXT: br label %[[finally:[^ ]*]] > -// > -// CHECK: [[finally]] > -// CHECK-NEXT: br label %[[finallycont:[^ ]*]] > -// > -// CHECK: [[finallycont]] > +// CHECK: alloca i32 > +// CHECK-NEXT: store i32 > +// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK-NEXT: call void @"\01?fin$0@0@finally_with_return@@"(i1 zeroext > false, i8* %[[fp]]) > // CHECK-NEXT: ret i32 42 > > +// CHECK: define internal void @"\01?fin$0@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 { > @@ -188,38 +174,28 @@ int nested___finally___finally() { > } > return 0; > } > + > // CHECK-LABEL: define i32 @nested___finally___finally > -// CHECK: store i8 0, i8* % > -// CHECK-NEXT: br label %[[finally:[^ ]*]] > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK: invoke void @"\01?fin$1@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@0@nested___finally___finally@@"(i1 > zeroext false, i8* %[[fp]]) > +// CHECK-NEXT: ret i32 0 > // > -// 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]] > +// CHECK: [[lpad]] > +// CHECK-NEXT: landingpad > +// CHECK-NEXT: cleanup > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 > zeroext true, i8* %[[fp]]) > + > +// CHECK-LABEL: define internal void @"\01?fin$0@0 > @nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* > %frame_pointer) > +// CHECK: ret void > + > +// CHECK-LABEL: define internal void @"\01?fin$1@0 > @nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* > %frame_pointer) > +// CHECK: unreachable > > int nested___finally___finally_with_eh_edge() { > __try { > @@ -234,58 +210,35 @@ int nested___finally___finally_with_eh_e > return 912; > } > // CHECK-LABEL: define i32 @nested___finally___finally_with_eh_edge > -// CHECK: invoke void @might_crash() #3 > -// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad:[^ ]*]] > -// > -// 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: invoke void @might_crash() > +// CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ > ]*]] > // > +// [[invokecont]] > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK: invoke void @"\01?fin$1@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@0 > @nested___finally___finally_with_eh_edge@@"(i1 zeroext false, i8* %[[fp]]) > +// CHECK-NEXT: ret i32 912 > // > -// CHECK: [[lpad]] > +// CHECK: [[lpad1]] > // CHECK-NEXT: landingpad > // CHECK-NEXT: cleanup > -// 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]] > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK: invoke void @"\01?fin$1@0 > @nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]]) > +// CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2]] > // > -// The ehresume block, not reachable either. > -// CHECK: [[ehresume]] > +// CHECK: [[lpad2]] > +// CHECK-NEXT: landingpad > +// CHECK-NEXT: cleanup > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK: call void @"\01?fin$0@0 > @nested___finally___finally_with_eh_edge@@"(i1 zeroext true, i8* %[[fp]]) > // CHECK: resume > + > +// CHECK-LABEL: define internal void @"\01?fin$0@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@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=234613&r1=234612&r2=234613&view=diff > > ============================================================================== > --- cfe/trunk/test/CodeGen/exceptions-seh-leave.c (original) > +++ cfe/trunk/test/CodeGen/exceptions-seh-leave.c Fri Apr 10 12:34:52 2015 > @@ -1,6 +1,6 @@ > // RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm > -o - | FileCheck %s > > -void g(); > +void g(void); > > > > ////////////////////////////////////////////////////////////////////////////// > // __leave with __except > @@ -38,7 +38,7 @@ int __leave_with___except() { > return 1; > } > // CHECK-LABEL: define i32 @__leave_with___except() > -// CHECK: invoke void bitcast (void (...)* @g to void ()*)() > +// CHECK: invoke void @g() > // 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: store i8 0, i8* % > -// CHECK-NEXT: br label % > +// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_simple@@"(i1 > zeroext false, i8* %[[fp]]) > > // __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: store i8 0, i8* % > -// CHECK-NEXT: br label % > +// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally_noreturn@@"(i1 > zeroext false, i8* %[[fp]]) > > // 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 bitcast (void (...)* @g to void ()*)() > +// CHECK: invoke void @g() > // 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: store i8 0, i8* % > -// CHECK-NEXT: br label % > +// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK-NEXT: call void @"\01?fin$0@0@__leave_with___finally@@"(i1 > zeroext false, i8* %[[fp]]) > > > > > ////////////////////////////////////////////////////////////////////////////// > @@ -142,45 +142,37 @@ 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 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-LABEL: invoke void @g() > +// CHECK-NEXT: to label %[[g1_cont1:.*]] unwind label > %[[g1_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: [[g1_cont1]] > +// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i1 > zeroext false, i8* %[[fp]]) > +// CHECK-NEXT: to label %[[fin_cont:.*]] unwind label > %[[g2_lpad:.*]] > > -// Unused __finally continuation block > +// CHECK: [[fin_cont]] > // CHECK: store i32 51, i32* % > -// CHECK-NEXT: br label %[[tryleave]] > - > -// CHECK: [[tryleave]] > // CHECK-NEXT: br label %[[trycont:[^ ]*]] > > // CHECK: [[g1_lpad]] > -// CHECK: store i8 1, i8* % > -// CHECK-NEXT: br label %[[finally]] > +// CHECK-NEXT: landingpad > +// CHECK-NEXT: catch i8* null > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK-NEXT: invoke void @"\01?fin$0@0@nested___except___finally@@"(i1 > zeroext true, i8* %[[fp]]) > +// CHECK-NEXT: to label %[[g1_resume:.*]] unwind label %[[g2_lpad]] > > // CHECK: [[g2_lpad]] > -// CHECK-NOT: %[[abnormal]] > -// CHECK: br label %[[except:[^ ]*]] > - > -// CHECK: [[except]] > -// CHECK-NEXT: br label %[[trycont]] > +// CHECK: br label %[[trycont]] > > // CHECK: [[trycont]] > // CHECK-NEXT: ret i32 1 > > +// CHECK-LABEL: define internal void @"\01?fin$0@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 { > @@ -202,7 +194,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 bitcast (void (...)* @g to void ()*)() > +// CHECK-LABEL: invoke void @g() > // CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] > > // CHECK: [[g1_cont]] > @@ -213,7 +205,7 @@ int nested___except___except() { > // CHECK: br label %[[except:[^ ]*]] > > // CHECK: [[except]] > -// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)() #3 > +// CHECK-NEXT: invoke void @g() > // CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] > > // CHECK: [[g2_cont]] > @@ -256,7 +248,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 bitcast (void (...)* @g to void ()*)() > +// CHECK-LABEL: invoke void @g() > // CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] > > // CHECK: [[g1_cont]] > @@ -266,7 +258,7 @@ int nested___finally___except() { > // CHECK: br label %[[except:[^ ]*]] > > // CHECK: [[except]] > -// CHECK-NEXT: invoke void bitcast (void (...)* @g to void ()*)() > +// CHECK-NEXT: invoke void @g() > // CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] > > // CHECK: [[g2_cont]] > @@ -274,31 +266,25 @@ int nested___finally___except() { > // CHECK-NOT: 23 > > // CHECK: [[g2_lpad]] > -// CHECK: store i8 1, i8* %[[abnormal:[^ ]*]] > -// CHECK-NEXT: br label %[[finally:[^ ]*]] > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i1 > zeroext true, i8* %[[fp]]) > +// CHECK-NEXT: br label %[[ehresume:[^ ]*]] > > // CHECK: [[trycont]] > // CHECK: store i32 51, i32* % > // CHECK-NEXT: br label %[[tryleave]] > > // CHECK: [[tryleave]] > -// 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: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___except@@"(i1 > zeroext false, i8* %[[fp]]) > // CHECK-NEXT: ret i32 1 > > -// CHECK: [[finallyresume]] > -// CHECK-NEXT: br label %[[ehresume:[^ ]*]] > - > // CHECK: [[ehresume]] > // CHECK: resume > > +// CHECK-LABEL: define internal void @"\01?fin$0@0 > @nested___finally___except@@"(i1 zeroext %abnormal_termination, i8* > %frame_pointer) > +// CHECK: ret void > + > int nested___finally___finally() { > int myres = 0; > __try { > @@ -320,51 +306,44 @@ 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 bitcast (void (...)* @g to void ()*)() > +// CHECK-LABEL: invoke void @g() > // CHECK-NEXT: to label %[[g1_cont:.*]] unwind label %[[g1_lpad:.*]] > > // CHECK: [[g1_cont]] > // CHECK: store i32 16, i32* %[[myres:[^ ]*]], > -// 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: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i1 > zeroext false, i8* %[[fp]]) > +// CHECK-NEXT: to label %[[finally_cont:.*]] unwind label > %[[g2_lpad:.*]] > > -// There's an unreachable block for the skipped `myres = 51`. > +// CHECK: [[finally_cont]] > // CHECK: store i32 51, i32* %[[myres]] > -// 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: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 > zeroext false, i8* %[[fp]]) > // CHECK-NEXT: ret i32 1 > > // CHECK: [[g1_lpad]] > -// CHECK: store i8 1, i8* %[[abnormal]] > -// CHECK-NEXT: br label %[[finally:[^ ]*]] > +// CHECK-NEXT: landingpad > +// CHECK-NEXT: cleanup > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK-NEXT: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i1 > zeroext true, i8* %[[fp]]) > +// CHECK-NEXT: to label %[[finally_cont2:.*]] unwind label > %[[g2_lpad]] > > // CHECK: [[g2_lpad]] > -// CHECK: br label %[[ehcleanup:[^ ]*]] > +// CHECK-NEXT: landingpad > +// CHECK-NEXT: cleanup > +// CHECK: br label %[[ehcleanup:.*]] > + > +// CHECK: [[finally_cont2]] > +// CHECK: br label %[[ehcleanup]] > > // CHECK: [[ehcleanup]] > -// CHECK-NEXT: store i8 1, i8* %[[abnormal]] > -// CHECK-NEXT: br label %[[outerfinally]] > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i1 > zeroext true, i8* %[[fp]]) > +// CHECK: resume > > -// CHECK: [[finallyresume]] > -// CHECK-NEXT: br label %[[ehresume:[^ ]*]] > +// CHECK-LABEL: define internal void @"\01?fin$0@0 > @nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* > %frame_pointer) > +// CHECK: ret void > > -// CHECK: [[ehresume]] > -// CHECK: resume > +// CHECK-LABEL: define internal void @"\01?fin$1@0 > @nested___finally___finally@@"(i1 zeroext %abnormal_termination, i8* > %frame_pointer) > +// CHECK: call void @g() > +// CHECK: unreachable > > Modified: cfe/trunk/test/CodeGen/exceptions-seh.c > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/exceptions-seh.c?rev=234613&r1=234612&r2=234613&view=diff > > ============================================================================== > --- cfe/trunk/test/CodeGen/exceptions-seh.c (original) > +++ cfe/trunk/test/CodeGen/exceptions-seh.c Fri Apr 10 12:34:52 2015 > @@ -118,8 +118,6 @@ 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; > @@ -138,24 +136,23 @@ void basic_finally(void) { > // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] > // > // CHECK: [[cont]] > -// 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: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext false, i8* > %[[fp]]) > // CHECK: ret void > // > // CHECK: [[lpad]] > // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* > @__C_specific_handler to i8*) > // CHECK-NEXT: cleanup > -// CHECK: br label %[[finally]] > -// > +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i1 zeroext true, i8* > %[[fp]]) > // CHECK: resume > > +// CHECK: define internal void @"\01?fin$0@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 { > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
