Author: nico Date: Thu Jul 2 01:10:53 2015 New Revision: 241244 URL: http://llvm.org/viewvc/llvm-project?rev=241244&view=rev Log: Revert 241171, 241187, 241199 (32-bit SEH).
It still doesn't produce quite the right code, test binaries built with this enabled fail some tests. Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Basic/TargetInfo.h cfe/trunk/lib/CodeGen/CGException.cpp cfe/trunk/lib/CodeGen/CodeGenFunction.cpp cfe/trunk/lib/CodeGen/CodeGenFunction.h cfe/trunk/lib/Sema/SemaStmt.cpp 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/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=241244&r1=241243&r2=241244&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jul 2 01:10:53 2015 @@ -5576,8 +5576,6 @@ def err_seh_try_outside_functions : Erro "cannot use SEH '__try' in blocks, captured regions, or Obj-C method decls">; def err_mixing_cxx_try_seh_try : Error< "cannot use C++ 'try' in the same function as SEH '__try'">; -def err_seh_try_unsupported : Error< - "SEH '__try' is not supported on this target">; def note_conflicting_try_here : Note< "conflicting %0 here">; def warn_jump_out_of_seh_finally : Warning< Modified: cfe/trunk/include/clang/Basic/TargetInfo.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=241244&r1=241243&r2=241244&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/TargetInfo.h (original) +++ cfe/trunk/include/clang/Basic/TargetInfo.h Thu Jul 2 01:10:53 2015 @@ -809,11 +809,6 @@ public: return TLSSupported; } - /// \brief Whether the target supports SEH __try. - bool isSEHTrySupported() const { - return getTriple().isOSWindows(); - } - /// \brief Return true if {|} are normal characters in the asm string. /// /// If this returns false (the default), then {abc|xyz} is syntax Modified: cfe/trunk/lib/CodeGen/CGException.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=241244&r1=241243&r2=241244&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGException.cpp (original) +++ cfe/trunk/lib/CodeGen/CGException.cpp Thu Jul 2 01:10:53 2015 @@ -20,7 +20,6 @@ #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtVisitor.h" -#include "clang/Basic/TargetBuiltins.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicInst.h" @@ -1280,6 +1279,14 @@ llvm::BasicBlock *CodeGenFunction::getEH } void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) { + // FIXME: Implement SEH on other architectures. + const llvm::Triple &T = CGM.getTarget().getTriple(); + if (T.getArch() != llvm::Triple::x86_64 || + !T.isKnownWindowsMSVCEnvironment()) { + ErrorUnsupported(&S, "__try statement"); + return; + } + EnterSEHTryStmt(S); { JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave"); @@ -1304,28 +1311,24 @@ struct PerformSEHFinally : EHScopeStack: void Emit(CodeGenFunction &CGF, Flags F) override { ASTContext &Context = CGF.getContext(); - CodeGenModule &CGM = CGF.CGM; + QualType ArgTys[2] = {Context.UnsignedCharTy, Context.VoidPtrTy}; + FunctionProtoType::ExtProtoInfo EPI; + const auto *FTP = cast<FunctionType>( + Context.getFunctionType(Context.VoidTy, ArgTys, EPI)); CallArgList Args; - - // Compute the two argument values. - QualType ArgTys[2] = {Context.UnsignedCharTy, Context.VoidPtrTy}; - llvm::Value *FrameAddr = CGM.getIntrinsic(llvm::Intrinsic::frameaddress); - llvm::Value *FP = - CGF.Builder.CreateCall(FrameAddr, {CGF.Builder.getInt32(0)}); 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]); - // Arrange a two-arg function info and type. - FunctionProtoType::ExtProtoInfo EPI; - const auto *FPT = cast<FunctionProtoType>( - Context.getFunctionType(Context.VoidTy, ArgTys, EPI)); const CGFunctionInfo &FnInfo = - CGM.getTypes().arrangeFreeFunctionCall(Args, FPT, - /*chainCall=*/false); - + CGM.getTypes().arrangeFreeFunctionCall(Args, FTP, /*chainCall=*/false); CGF.EmitCall(FnInfo, OutlinedFinally, ReturnValueSlot(), Args); } }; @@ -1337,15 +1340,9 @@ struct CaptureFinder : ConstStmtVisitor< CodeGenFunction &ParentCGF; const VarDecl *ParentThis; SmallVector<const VarDecl *, 4> Captures; - llvm::Value *SEHCodeSlot = nullptr; CaptureFinder(CodeGenFunction &ParentCGF, const VarDecl *ParentThis) : ParentCGF(ParentCGF), ParentThis(ParentThis) {} - // Return true if we need to do any capturing work. - bool foundCaptures() { - return !Captures.empty() || SEHCodeSlot; - } - void Visit(const Stmt *S) { // See if this is a capture, then recurse. ConstStmtVisitor<CaptureFinder>::Visit(S); @@ -1369,104 +1366,25 @@ struct CaptureFinder : ConstStmtVisitor< void VisitCXXThisExpr(const CXXThisExpr *E) { Captures.push_back(ParentThis); } - - void VisitCallExpr(const CallExpr *E) { - // We only need to add parent frame allocations for these builtins in x86. - if (ParentCGF.getTarget().getTriple().getArch() != llvm::Triple::x86) - return; - - unsigned ID = E->getBuiltinCallee(); - switch (ID) { - case Builtin::BI__exception_code: - case Builtin::BI_exception_code: - // This is the simple case where we are the outermost finally. All we - // have to do here is make sure we escape this and recover it in the - // outlined handler. - if (!SEHCodeSlot) - SEHCodeSlot = ParentCGF.SEHCodeSlotStack.back(); - break; - } - } }; } -llvm::Value *CodeGenFunction::recoverAddrOfEscapedLocal( - CodeGenFunction &ParentCGF, llvm::Value *ParentVar, llvm::Value *ParentFP) { - llvm::CallInst *RecoverCall = nullptr; - CGBuilderTy Builder(AllocaInsertPt); - if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) { - // Mark the variable escaped if nobody else referenced it and compute the - // frameescape index. - auto InsertPair = ParentCGF.EscapedLocals.insert( - std::make_pair(ParentAlloca, ParentCGF.EscapedLocals.size())); - int FrameEscapeIdx = InsertPair.first->second; - // call i8* @llvm.framerecover(i8* bitcast(@parentFn), i8* %fp, i32 N) - llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration( - &CGM.getModule(), llvm::Intrinsic::framerecover); - llvm::Constant *ParentI8Fn = - llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy); - RecoverCall = Builder.CreateCall( - FrameRecoverFn, {ParentI8Fn, ParentFP, - llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)}); - - } else { - // If the parent didn't have an alloca, we're doing some nested outlining. - // Just clone the existing framerecover call, but tweak the FP argument to - // use our FP value. All other arguments are constants. - auto *ParentRecover = - cast<llvm::IntrinsicInst>(ParentVar->stripPointerCasts()); - assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::framerecover && - "expected alloca or framerecover in parent LocalDeclMap"); - RecoverCall = cast<llvm::CallInst>(ParentRecover->clone()); - RecoverCall->setArgOperand(1, ParentFP); - RecoverCall->insertBefore(AllocaInsertPt); - } - - // Bitcast the variable, rename it, and insert it in the local decl map. - llvm::Value *ChildVar = - Builder.CreateBitCast(RecoverCall, ParentVar->getType()); - ChildVar->setName(ParentVar->getName()); - return ChildVar; -} - void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt *OutlinedStmt, - bool IsFilter) { + llvm::Value *ParentFP) { // Find all captures in the Stmt. CaptureFinder Finder(ParentCGF, ParentCGF.CXXABIThisDecl); Finder.Visit(OutlinedStmt); - // We can exit early on x86_64 when there are no captures. We just have to - // save the exception code in filters so that __exception_code() works. - if (!Finder.foundCaptures() && - CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) { - if (IsFilter) - EmitSEHExceptionCodeSave(ParentCGF, nullptr, nullptr); + // Typically there are no captures and we can exit early. + if (Finder.Captures.empty()) return; - } - llvm::Value *EntryEBP = nullptr; - llvm::Value *ParentFP; - if (IsFilter && CGM.getTarget().getTriple().getArch() == llvm::Triple::x86) { - // 32-bit SEH filters need to be careful about FP recovery. The end of the - // EH registration is passed in as the EBP physical register. We can - // recover that with llvm.frameaddress(1), and adjust that to recover the - // parent's true frame pointer. - CGBuilderTy Builder(AllocaInsertPt); - EntryEBP = Builder.CreateCall( - CGM.getIntrinsic(llvm::Intrinsic::frameaddress), {Builder.getInt32(1)}); - llvm::Function *RecoverFPIntrin = - CGM.getIntrinsic(llvm::Intrinsic::x86_seh_recoverfp); - llvm::Constant *ParentI8Fn = - llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy); - ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryEBP}); - } else { - // Otherwise, for x64 and 32-bit finally functions, the parent FP is the - // second parameter. - auto AI = CurFn->arg_begin(); - ++AI; - ParentFP = AI; - } + // Prepare the first two arguments to llvm.framerecover. + llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration( + &CGM.getModule(), llvm::Intrinsic::framerecover); + llvm::Constant *ParentI8Fn = + llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy); // Create llvm.framerecover calls for all captures. for (const VarDecl *VD : Finder.Captures) { @@ -1489,63 +1407,49 @@ void CodeGenFunction::EmitCapturedLocals continue; llvm::Value *ParentVar = I->second; - LocalDeclMap[VD] = - recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP); - } + llvm::CallInst *RecoverCall = nullptr; + CGBuilderTy Builder(AllocaInsertPt); + if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) { + // Mark the variable escaped if nobody else referenced it and compute the + // frameescape index. + auto InsertPair = + ParentCGF.EscapedLocals.insert(std::make_pair(ParentAlloca, -1)); + if (InsertPair.second) + InsertPair.first->second = ParentCGF.EscapedLocals.size() - 1; + int FrameEscapeIdx = InsertPair.first->second; + // call i8* @llvm.framerecover(i8* bitcast(@parentFn), i8* %fp, i32 N) + RecoverCall = Builder.CreateCall( + FrameRecoverFn, {ParentI8Fn, ParentFP, + llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)}); - if (Finder.SEHCodeSlot) { - SEHCodeSlotStack.push_back( - recoverAddrOfEscapedLocal(ParentCGF, Finder.SEHCodeSlot, ParentFP)); + } else { + // If the parent didn't have an alloca, we're doing some nested outlining. + // Just clone the existing framerecover call, but tweak the FP argument to + // use our FP value. All other arguments are constants. + auto *ParentRecover = + cast<llvm::IntrinsicInst>(ParentVar->stripPointerCasts()); + assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::framerecover && + "expected alloca or framerecover in parent LocalDeclMap"); + RecoverCall = cast<llvm::CallInst>(ParentRecover->clone()); + RecoverCall->setArgOperand(1, ParentFP); + RecoverCall->insertBefore(AllocaInsertPt); + } + + // Bitcast the variable, rename it, and insert it in the local decl map. + llvm::Value *ChildVar = + Builder.CreateBitCast(RecoverCall, ParentVar->getType()); + ChildVar->setName(ParentVar->getName()); + LocalDeclMap[VD] = ChildVar; } - - if (IsFilter) - EmitSEHExceptionCodeSave(ParentCGF, ParentFP, EntryEBP); } /// 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, - bool IsFilter, + StringRef Name, QualType RetTy, + FunctionArgList &Args, const Stmt *OutlinedStmt) { - SourceLocation StartLoc = OutlinedStmt->getLocStart(); - - // 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"); - MangleContext &Mangler = CGM.getCXXABI().getMangleContext(); - if (IsFilter) - Mangler.mangleSEHFilterExpression(Parent, OS); - else - Mangler.mangleSEHFinallyBlock(Parent, OS); - } - - FunctionArgList Args; - if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 || !IsFilter) { - // All SEH finally functions take two parameters. Win64 filters take two - // parameters. Win32 filters take no parameters. - if (IsFilter) { - Args.push_back(ImplicitParamDecl::Create( - getContext(), nullptr, StartLoc, - &getContext().Idents.get("exception_pointers"), - getContext().VoidPtrTy)); - } else { - Args.push_back(ImplicitParamDecl::Create( - getContext(), nullptr, StartLoc, - &getContext().Idents.get("abnormal_termination"), - getContext().UnsignedCharTy)); - } - Args.push_back(ImplicitParamDecl::Create( - getContext(), nullptr, StartLoc, - &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy)); - } - - QualType RetTy = IsFilter ? getContext().LongTy : getContext().VoidTy; - llvm::Function *ParentFn = ParentCGF.CurFn; const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionDeclaration( RetTy, Args, FunctionType::ExtInfo(), /*isVariadic=*/false); @@ -1570,7 +1474,10 @@ void CodeGenFunction::startOutlinedSEHHe OutlinedStmt->getLocStart(), OutlinedStmt->getLocStart()); CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn); - EmitCapturedLocals(ParentCGF, OutlinedStmt, IsFilter); + + auto AI = Fn->arg_begin(); + ++AI; + EmitCapturedLocals(ParentCGF, OutlinedStmt, &*AI); } /// Create a stub filter function that will ultimately hold the code of the @@ -1580,7 +1487,37 @@ llvm::Function * CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF, const SEHExceptStmt &Except) { const Expr *FilterExpr = Except.getFilterExpr(); - startOutlinedSEHHelper(ParentCGF, true, FilterExpr); + 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().LongTy, 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); @@ -1597,13 +1534,29 @@ llvm::Function * CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF, const SEHFinallyStmt &Finally) { const Stmt *FinallyBlock = Finally.getBlock(); - startOutlinedSEHHelper(ParentCGF, false, FinallyBlock); + SourceLocation StartLoc = FinallyBlock->getLocStart(); - // 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); + FunctionArgList Args; + Args.push_back(ImplicitParamDecl::Create( + getContext(), nullptr, StartLoc, + &getContext().Idents.get("abnormal_termination"), + getContext().UnsignedCharTy)); + 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); @@ -1613,58 +1566,44 @@ CodeGenFunction::GenerateSEHFinallyFunct return CurFn; } -void CodeGenFunction::EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF, - llvm::Value *ParentFP, - llvm::Value *EntryEBP) { - // Get the pointer to the EXCEPTION_POINTERS struct. This is returned by the - // __exception_info intrinsic. - if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) { - // On Win64, the info is passed as the first parameter to the filter. - auto AI = CurFn->arg_begin(); - SEHInfo = AI; - SEHCodeSlotStack.push_back( - CreateMemTemp(getContext().IntTy, "__exception_code")); - } else { - // On Win32, the EBP on entry to the filter points to the end of an - // exception registration object. It contains 6 32-bit fields, and the info - // pointer is stored in the second field. So, GEP 20 bytes backwards and - // load the pointer. - SEHInfo = Builder.CreateConstInBoundsGEP1_32(Int8Ty, EntryEBP, -20); - SEHInfo = Builder.CreateBitCast(SEHInfo, Int8PtrTy->getPointerTo()); - SEHInfo = Builder.CreateLoad(Int8PtrTy, SEHInfo); - SEHCodeSlotStack.push_back(recoverAddrOfEscapedLocal( - ParentCGF, ParentCGF.SEHCodeSlotStack.back(), ParentFP)); - } - +void CodeGenFunction::EmitSEHExceptionCodeSave() { // Save the exception code in the exception slot to unify exception access in // the filter function and the landing pad. // struct EXCEPTION_POINTERS { // EXCEPTION_RECORD *ExceptionRecord; // CONTEXT *ContextRecord; // }; - // int exceptioncode = exception_pointers->ExceptionRecord->ExceptionCode; + // void *exn.slot = + // (void *)(uintptr_t)exception_pointers->ExceptionRecord->ExceptionCode; + llvm::Value *Ptrs = Builder.CreateLoad(GetAddrOfLocalVar(SEHPointersDecl)); llvm::Type *RecordTy = CGM.Int32Ty->getPointerTo(); llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy, nullptr); - llvm::Value *Ptrs = Builder.CreateBitCast(SEHInfo, PtrsTy->getPointerTo()); + Ptrs = Builder.CreateBitCast(Ptrs, PtrsTy->getPointerTo()); llvm::Value *Rec = Builder.CreateStructGEP(PtrsTy, Ptrs, 0); Rec = Builder.CreateLoad(Rec); llvm::Value *Code = Builder.CreateLoad(Rec); - assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except"); - Builder.CreateStore(Code, SEHCodeSlotStack.back()); + Code = Builder.CreateZExt(Code, CGM.IntPtrTy); + // FIXME: Change landing pads to produce {i32, i32} and make the exception + // slot an i32. + Code = Builder.CreateIntToPtr(Code, CGM.VoidPtrTy); + Builder.CreateStore(Code, getExceptionSlot()); } llvm::Value *CodeGenFunction::EmitSEHExceptionInfo() { // Sema should diagnose calling this builtin outside of a filter context, but // don't crash if we screw up. - if (!SEHInfo) + if (!SEHPointersDecl) return llvm::UndefValue::get(Int8PtrTy); - assert(SEHInfo->getType() == Int8PtrTy); - return SEHInfo; + return Builder.CreateLoad(GetAddrOfLocalVar(SEHPointersDecl)); } llvm::Value *CodeGenFunction::EmitSEHExceptionCode() { - assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except"); - return Builder.CreateLoad(Int32Ty, SEHCodeSlotStack.back()); + // If we're in a landing pad or filter function, the exception slot contains + // the code. + assert(ExceptionSlot); + llvm::Value *Code = + Builder.CreatePtrToInt(getExceptionFromSlot(), CGM.IntPtrTy); + return Builder.CreateTrunc(Code, CGM.Int32Ty); } llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() { @@ -1677,11 +1616,9 @@ llvm::Value *CodeGenFunction::EmitSEHAbn void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) { CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true); if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) { - // Outline the finally block. + // Push a cleanup for __finally blocks. llvm::Function *FinallyFunc = HelperCGF.GenerateSEHFinallyFunction(*this, *Finally); - - // Push a cleanup for __finally blocks. EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc); return; } @@ -1690,16 +1627,12 @@ void CodeGenFunction::EnterSEHTryStmt(co const SEHExceptStmt *Except = S.getExceptHandler(); assert(Except); EHCatchScope *CatchScope = EHStack.pushCatch(1); - SEHCodeSlotStack.push_back( - CreateMemTemp(getContext().IntTy, "__exception_code")); - // If the filter is known to evaluate to 1, then we can use the clause - // "catch i8* null". We can't do this on x86 because the filter has to save - // the exception code. + // If the filter is known to evaluate to 1, then we can use the clause "catch + // i8* null". llvm::Constant *C = CGM.EmitConstantExpr(Except->getFilterExpr(), getContext().IntTy, this); - if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 && C && - C->isOneValue()) { + if (C && C->isOneValue()) { CatchScope->setCatchAllHandler(0, createBasicBlock("__except")); return; } @@ -1731,7 +1664,6 @@ void CodeGenFunction::ExitSEHTryStmt(con if (!CatchScope.hasEHBranches()) { CatchScope.clearHandlerBlocks(); EHStack.popCatch(); - SEHCodeSlotStack.pop_back(); return; } @@ -1751,20 +1683,9 @@ void CodeGenFunction::ExitSEHTryStmt(con EmitBlockAfterUses(ExceptBB); - // On Win64, the exception pointer is the exception code. Copy it to the slot. - if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) { - llvm::Value *Code = - Builder.CreatePtrToInt(getExceptionFromSlot(), IntPtrTy); - Code = Builder.CreateTrunc(Code, Int32Ty); - Builder.CreateStore(Code, SEHCodeSlotStack.back()); - } - // Emit the __except body. EmitStmt(Except->getBlock()); - // End the lifetime of the exception code. - SEHCodeSlotStack.pop_back(); - if (HaveInsertPoint()) Builder.CreateBr(ContBB); Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=241244&r1=241243&r2=241244&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original) +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Thu Jul 2 01:10:53 2015 @@ -45,12 +45,12 @@ CodeGenFunction::CodeGenFunction(CodeGen LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr), NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr), EHSelectorSlot(nullptr), - DebugInfo(CGM.getModuleDebugInfo()), - DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(nullptr), - PGO(cgm), SwitchInsn(nullptr), SwitchWeights(nullptr), - CaseRangeBlock(nullptr), UnreachableBlock(nullptr), NumReturnExprs(0), - NumSimpleReturnExprs(0), CXXABIThisDecl(nullptr), - CXXABIThisValue(nullptr), CXXThisValue(nullptr), + AbnormalTerminationSlot(nullptr), SEHPointersDecl(nullptr), + DebugInfo(CGM.getModuleDebugInfo()), DisableDebugInfo(false), + DidCallStackSave(false), IndirectBranch(nullptr), PGO(cgm), + SwitchInsn(nullptr), SwitchWeights(nullptr), CaseRangeBlock(nullptr), + UnreachableBlock(nullptr), NumReturnExprs(0), NumSimpleReturnExprs(0), + CXXABIThisDecl(nullptr), CXXABIThisValue(nullptr), CXXThisValue(nullptr), CXXDefaultInitExprThis(nullptr), CXXStructorImplicitParamDecl(nullptr), CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr), CurLexicalScope(nullptr), TerminateLandingPad(nullptr), Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=241244&r1=241243&r2=241244&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Jul 2 01:10:53 2015 @@ -324,13 +324,11 @@ public: /// write the current selector value into this alloca. llvm::AllocaInst *EHSelectorSlot; - /// A stack of exception code slots. Entering an __except block pushes a slot - /// on the stack and leaving pops one. The __exception_code() intrinsic loads - /// a value from the top of the stack. - SmallVector<llvm::Value *, 1> SEHCodeSlotStack; + llvm::AllocaInst *AbnormalTerminationSlot; - /// Value returned by __exception_info intrinsic. - llvm::Value *SEHInfo = nullptr; + /// The implicit parameter to SEH filter functions of type + /// 'EXCEPTION_POINTERS*'. + ImplicitParamDecl *SEHPointersDecl; /// Emits a landing pad for the current EH stack. llvm::BasicBlock *EmitLandingPad(); @@ -2050,7 +2048,8 @@ public: void EnterSEHTryStmt(const SEHTryStmt &S); void ExitSEHTryStmt(const SEHTryStmt &S); - void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, bool IsFilter, + void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, StringRef Name, + QualType RetTy, FunctionArgList &Args, const Stmt *OutlinedStmt); llvm::Function *GenerateSEHFilterFunction(CodeGenFunction &ParentCGF, @@ -2059,9 +2058,7 @@ public: llvm::Function *GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF, const SEHFinallyStmt &Finally); - void EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF, - llvm::Value *ParentFP, - llvm::Value *EntryEBP); + void EmitSEHExceptionCodeSave(); llvm::Value *EmitSEHExceptionCode(); llvm::Value *EmitSEHExceptionInfo(); llvm::Value *EmitSEHAbnormalTermination(); @@ -2070,16 +2067,7 @@ public: /// each capture, mark the capture as escaped and emit a call to /// llvm.framerecover. Insert the framerecover result into the LocalDeclMap. void EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt *OutlinedStmt, - bool IsFilter); - - /// Recovers the address of a local in a parent function. ParentVar is the - /// address of the variable used in the immediate parent function. It can - /// either be an alloca or a call to llvm.framerecover if there are nested - /// outlined functions. ParentFP is the frame pointer of the outermost parent - /// frame. - llvm::Value *recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, - llvm::Value *ParentVar, - llvm::Value *ParentFP); + llvm::Value *ParentFP); void EmitCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef<const Attr *> Attrs = None); Modified: cfe/trunk/lib/Sema/SemaStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=241244&r1=241243&r2=241244&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaStmt.cpp (original) +++ cfe/trunk/lib/Sema/SemaStmt.cpp Thu Jul 2 01:10:53 2015 @@ -25,7 +25,6 @@ #include "clang/AST/StmtObjC.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" -#include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -3650,10 +3649,6 @@ StmtResult Sema::ActOnSEHTryBlock(bool I else Diag(TryLoc, diag::err_seh_try_outside_functions); - // Reject __try on unsupported targets. - if (!Context.getTargetInfo().isSEHTrySupported()) - Diag(TryLoc, diag::err_seh_try_unsupported); - return SEHTryStmt::Create(Context, IsCXXTry, TryLoc, TryBlock, Handler); } 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=241244&r1=241243&r2=241244&view=diff ============================================================================== --- cfe/trunk/test/CodeGen/exceptions-seh-finally.c (original) +++ cfe/trunk/test/CodeGen/exceptions-seh-finally.c Thu Jul 2 01:10:53 2015 @@ -1,5 +1,4 @@ // RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s void abort(void) __attribute__((noreturn)); void might_crash(void); @@ -19,17 +18,17 @@ void basic_finally(void) { // // CHECK: [[invoke_cont]] // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]]) +// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i8 0, i8* %[[fp]]) // 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@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]]) +// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i8 1, i8* %[[fp]]) // CHECK: resume { i8*, i32 } -// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}}) +// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"(i8 %abnormal_termination, i8* %frame_pointer) // CHECK: call void @cleanup() // Mostly check that we don't double emit 'r' which would crash. @@ -59,10 +58,10 @@ l: // // CHECK: [[invoke_cont]] // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@label_in_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]]) +// CHECK: call void @"\01?fin$0@0@label_in_finally@@"(i8 0, i8* %[[fp]]) // CHECK: ret void -// CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"({{.*}}) +// CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"(i8 %abnormal_termination, i8* %frame_pointer) // CHECK: br label %[[l:[^ ]*]] // // CHECK: [[l]] @@ -86,18 +85,18 @@ void use_abnormal_termination(void) { // // CHECK: [[invoke_cont]] // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 0, i8* %[[fp]]) +// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i8 0, i8* %[[fp]]) // CHECK: ret void // // CHECK: [[lpad]] // CHECK-NEXT: landingpad // CHECK-NEXT: cleanup // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]]) +// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i8 1, i8* %[[fp]]) // CHECK: resume { i8*, i32 } -// CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer) -// CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32 +// CHECK: define internal void @"\01?fin$0@0@use_abnormal_termination@@"(i8 %abnormal_termination, i8* %frame_pointer) +// CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %abnormal_termination to i32 // CHECK: store i32 %[[abnormal_zext]], i32* @crashed // CHECK-NEXT: ret void @@ -110,10 +109,11 @@ void noreturn_noop_finally() { } // CHECK-LABEL: define void @noreturn_noop_finally() -// CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}}) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"(i8 0, i8* %[[fp]]) // CHECK: ret void -// CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}}) +// CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"(i8 %abnormal_termination, i8* %frame_pointer) // CHECK: call void @abort() // CHECK: unreachable @@ -130,16 +130,18 @@ void noreturn_finally() { // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[cont]] -// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}}) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i8 0, i8* %[[fp]]) // CHECK: ret void // // CHECK: [[lpad]] // CHECK: landingpad // CHECK-NEXT: cleanup -// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}}) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i8 1, i8* %[[fp]]) // CHECK: resume { i8*, i32 } -// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"({{.*}}) +// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"(i8 %abnormal_termination, i8* %frame_pointer) // CHECK: call void @abort() // CHECK: unreachable @@ -150,10 +152,11 @@ int finally_with_return() { } } // CHECK-LABEL: define i32 @finally_with_return() -// CHECK: call void @"\01?fin$0@0@finally_with_return@@"({{.*}}) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@finally_with_return@@"(i8 0, i8* %[[fp]]) // CHECK-NEXT: ret i32 42 -// CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"({{.*}}) +// CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"(i8 %abnormal_termination, i8* %frame_pointer) // CHECK-NOT: br i1 // CHECK-NOT: br label // CHECK: ret void @@ -171,22 +174,25 @@ int nested___finally___finally() { } // CHECK-LABEL: define i32 @nested___finally___finally -// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"({{.*}}) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally@@"(i8 0, i8* %[[fp]]) // CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[outercont]] -// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}}) +// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 0, i8* %[[fp]]) // CHECK-NEXT: ret i32 0 // // CHECK: [[lpad]] // CHECK-NEXT: landingpad // CHECK-NEXT: cleanup -// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}}) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally@@"(i8 1, i8* %[[fp]]) -// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"({{.*}}) +// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer) // CHECK: ret void -// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"({{.*}}) +// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer) // CHECK: unreachable int nested___finally___finally_with_eh_edge() { @@ -206,27 +212,31 @@ int nested___finally___finally_with_eh_e // CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]] // // [[invokecont]] -// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}}) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i8 0, i8* %[[fp]]) // CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]] // // CHECK: [[outercont]] -// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}}) +// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK-NEXT: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i8 0, i8* %[[fp]]) // CHECK-NEXT: ret i32 912 // // CHECK: [[lpad1]] // CHECK-NEXT: landingpad // CHECK-NEXT: cleanup -// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}}) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: invoke void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i8 1, i8* %[[fp]]) // CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2]] // // CHECK: [[lpad2]] // CHECK-NEXT: landingpad // CHECK-NEXT: cleanup -// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}}) +// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) +// CHECK: call void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i8 1, i8* %[[fp]]) // CHECK: resume -// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"({{.*}}) +// CHECK-LABEL: define internal void @"\01?fin$0@0@nested___finally___finally_with_eh_edge@@"(i8 %abnormal_termination, i8* %frame_pointer) // CHECK: ret void -// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"({{.*}}) +// CHECK-LABEL: define internal void @"\01?fin$1@0@nested___finally___finally_with_eh_edge@@"(i8 %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=241244&r1=241243&r2=241244&view=diff ============================================================================== --- cfe/trunk/test/CodeGen/exceptions-seh-leave.c (original) +++ cfe/trunk/test/CodeGen/exceptions-seh-leave.c Thu Jul 2 01:10:53 2015 @@ -205,7 +205,7 @@ int nested___except___except() { // CHECK: br label %[[except:[^ ]*]] // CHECK: [[except]] -// CHECK: invoke void @g() +// CHECK-NEXT: invoke void @g() // CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] // CHECK: [[g2_cont]] @@ -216,7 +216,7 @@ int nested___except___except() { // CHECK: br label %[[outerexcept:[^ ]*]] // CHECK: [[outerexcept]] -// CHECK: br label %[[trycont4:[^ ]*]] +// CHECK-NEXT: br label %[[trycont4:[^ ]*]] // CHECK: [[trycont4]] // CHECK-NEXT: ret i32 1 @@ -258,11 +258,11 @@ int nested___finally___except() { // CHECK: br label %[[except:[^ ]*]] // CHECK: [[except]] -// CHECK: invoke void @g() +// CHECK-NEXT: invoke void @g() // CHECK-NEXT: to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]] // CHECK: [[g2_cont]] -// CHECK: br label %[[tryleave:[^ ]*]] +// CHECK-NEXT: br label %[[tryleave:[^ ]*]] // CHECK-NOT: 23 // CHECK: [[g2_lpad]] Modified: cfe/trunk/test/CodeGen/exceptions-seh.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/exceptions-seh.c?rev=241244&r1=241243&r2=241244&view=diff ============================================================================== --- cfe/trunk/test/CodeGen/exceptions-seh.c (original) +++ cfe/trunk/test/CodeGen/exceptions-seh.c Thu Jul 2 01:10:53 2015 @@ -1,7 +1,4 @@ -// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - \ -// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X64 -// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - \ -// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X86 +// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s void try_body(int numerator, int denominator, int *myres) { *myres = numerator / denominator; @@ -22,46 +19,20 @@ int safe_div(int numerator, int denomina *res = myres; return success; } - -// X64-LABEL: define i32 @safe_div(i32 %numerator, i32 %denominator, i32* %res) {{.*}} personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) -// X64: invoke void @try_body(i32 %{{.*}}, i32 %{{.*}}, i32* %{{.*}}) #[[NOINLINE:[0-9]+]] -// X64: to label %{{.*}} unwind label %[[lpad:[^ ]*]] -// -// X64: [[lpad]] -// X64: landingpad { i8*, i32 } -// X64-NEXT: catch i8* null -// X64-NOT: br i1 -// X64: br label %[[except:[^ ]*]] -// X64: [[except]] -// X64: store i32 -42, i32* %[[success:[^ ]*]] -// -// X64: %[[res:[^ ]*]] = load i32, i32* %[[success]] -// X64: ret i32 %[[res]] - -// X86-LABEL: define i32 @safe_div(i32 %numerator, i32 %denominator, i32* %res) {{.*}} personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) -// X86: invoke void @try_body(i32 %{{.*}}, i32 %{{.*}}, i32* %{{.*}}) #[[NOINLINE:[0-9]+]] -// X86: to label %{{.*}} unwind label %[[lpad:[^ ]*]] -// -// X86: [[lpad]] -// X86: landingpad { i8*, i32 } -// X86-NEXT: catch i8* bitcast (i32 ()* @"\01?filt$0@0@safe_div@@" to i8*) -// X86-NOT: br i1 -// X86: br label %[[except:[^ ]*]] -// X86: [[except]] -// X86: store i32 -42, i32* %[[success:[^ ]*]] -// -// X86: %[[res:[^ ]*]] = load i32, i32* %[[success]] -// X86: ret i32 %[[res]] - -// X86-LABEL: define internal i32 @"\01?filt$0@0@safe_div@@"() -// X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1) -// X86: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 (i32, i32, i32*)* @safe_div to i8*), i8* %[[ebp]]) -// X86: call i8* @llvm.framerecover(i8* bitcast (i32 (i32, i32, i32*)* @safe_div to i8*), i8* %[[fp]], i32 0) -// X86: load i8*, i8** -// X86: load i32*, i32** -// X86: load i32, i32* -// X86: store i32 %{{.*}}, i32* -// X86: ret i32 1 +// CHECK-LABEL: define i32 @safe_div(i32 %numerator, i32 %denominator, i32* %res) {{.*}} personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) +// CHECK: invoke void @try_body(i32 %{{.*}}, i32 %{{.*}}, i32* %{{.*}}) #[[NOINLINE:[0-9]+]] +// CHECK: to label %{{.*}} unwind label %[[lpad:[^ ]*]] +// +// CHECK: [[lpad]] +// CHECK: landingpad { i8*, i32 } +// CHECK-NEXT: catch i8* null +// CHECK-NOT: br i1 +// CHECK: br label %[[except:[^ ]*]] +// CHECK: [[except]] +// CHECK-NEXT: store i32 -42, i32* %[[success:[^ ]*]] +// +// CHECK: %[[res:[^ ]*]] = load i32, i32* %[[success]] +// CHECK: ret i32 %[[res]] void j(void); @@ -75,29 +46,20 @@ int filter_expr_capture(void) { return r; } -// CHECK-LABEL: define i32 @filter_expr_capture() -// X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) -// X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) -// X64: call void (...) @llvm.frameescape(i32* %[[r:[^ ,]*]]) -// X86: call void (...) @llvm.frameescape(i32* %[[r:[^ ,]*]], i32* %[[code:[^ ,]*]]) +// CHECK-LABEL: define i32 @filter_expr_capture() {{.*}} personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) +// CHECK: call void (...) @llvm.frameescape(i32* %[[r:[^ ,]*]]) // CHECK: store i32 42, i32* %[[r]] // CHECK: invoke void @j() #[[NOINLINE]] // // CHECK: landingpad -// CHECK-NEXT: catch i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@filter_expr_capture@@" to i8*) +// CHECK-NEXT: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@filter_expr_capture@@" to i8*) // CHECK: store i32 13, i32* %[[r]] // // CHECK: %[[rv:[^ ]*]] = load i32, i32* %[[r]] // CHECK: ret i32 %[[rv]] -// X64-LABEL: define internal i32 @"\01?filt$0@0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer) -// X64: call i8* @llvm.framerecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer, i32 0) -// -// X86-LABEL: define internal i32 @"\01?filt$0@0@filter_expr_capture@@"() -// X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1) -// X86: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[ebp]]) -// X86: call i8* @llvm.framerecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0) -// +// CHECK-LABEL: define internal i32 @"\01?filt$0@0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer) +// CHECK: call i8* @llvm.framerecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer, i32 0) // CHECK: store i32 -1, i32* %{{.*}} // CHECK: ret i32 -1 @@ -115,9 +77,7 @@ int nested_try(void) { } return r; } -// CHECK-LABEL: define i32 @nested_try() -// X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) -// X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) +// CHECK-LABEL: define i32 @nested_try() {{.*}} personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) // CHECK: store i32 42, i32* %[[r:[^ ,]*]] // CHECK: invoke void @j() #[[NOINLINE]] // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] @@ -128,18 +88,18 @@ int nested_try(void) { // // CHECK: [[lpad]] // CHECK: landingpad { i8*, i32 } -// CHECK: catch i8* bitcast (i32 ({{.*}})* @"\01?filt$1@0@nested_try@@" to i8*) -// CHECK: catch i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@nested_try@@" to i8*) +// CHECK: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$1@0@nested_try@@" to i8*) +// CHECK: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@nested_try@@" to i8*) // CHECK: store i8* %{{.*}}, i8** %[[ehptr_slot:[^ ]*]] // CHECK: store i32 %{{.*}}, i32* %[[sel_slot:[^ ]*]] // // CHECK: load i32, i32* %[[sel_slot]] -// CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ({{.*}})* @"\01?filt$1@0@nested_try@@" to i8*)) +// CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @"\01?filt$1@0@nested_try@@" to i8*)) // CHECK: icmp eq i32 // CHECK: br i1 // // CHECK: load i32, i32* %[[sel_slot]] -// CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ({{.*}})* @"\01?filt$0@0@nested_try@@" to i8*)) +// CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@nested_try@@" to i8*)) // CHECK: icmp eq i32 // CHECK: br i1 // @@ -155,55 +115,40 @@ int nested_try(void) { // // CHECK: [[inner_try_cont]] // CHECK: br label %[[outer_try_cont]] -// -// CHECK-LABEL: define internal i32 @"\01?filt$0@0@nested_try@@"({{.*}}) -// X86: call i8* @llvm.x86.seh.recoverfp({{.*}}) -// CHECK: load i32*, i32** -// CHECK: load i32, i32* -// CHECK: icmp eq i32 %{{.*}}, 456 -// -// CHECK-LABEL: define internal i32 @"\01?filt$1@0@nested_try@@"({{.*}}) -// X86: call i8* @llvm.x86.seh.recoverfp({{.*}}) -// CHECK: load i32*, i32** -// CHECK: load i32, i32* -// CHECK: icmp eq i32 %{{.*}}, 123 -int basic_finally(int g) { +static unsigned g = 0; +void basic_finally(void) { + ++g; __try { j(); } __finally { - ++g; + --g; } - return g; } -// CHECK-LABEL: define i32 @basic_finally(i32 %g) -// X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) -// X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) -// CHECK: %[[g_addr:[^ ]*]] = alloca i32, align 4 -// CHECK: call void (...) @llvm.frameescape(i32* %[[g_addr]]) -// CHECK: store i32 %g, i32* %[[g_addr]] +// CHECK-LABEL: define void @basic_finally() {{.*}} personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) +// CHECK: load i32, i32* @g +// CHECK: add i32 %{{.*}}, 1 +// CHECK: store i32 %{{.*}}, i32* @g // // CHECK: invoke void @j() // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] // // CHECK: [[cont]] // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]]) -// CHECK: load i32, i32* %[[g_addr]], align 4 -// CHECK: ret i32 +// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i8 0, i8* %[[fp]]) +// CHECK: ret void // // CHECK: [[lpad]] // CHECK: landingpad { i8*, i32 } // CHECK-NEXT: cleanup // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) -// CHECK: call void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]]) +// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i8 1, i8* %[[fp]]) // CHECK: resume -// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{i8( zeroext)?}} %abnormal_termination, i8* %frame_pointer) -// CHECK: call i8* @llvm.framerecover(i8* bitcast (i32 (i32)* @basic_finally to i8*), i8* %frame_pointer, i32 0) -// CHECK: load i32, i32* %{{.*}}, align 4 -// CHECK: add nsw i32 %{{.*}}, 1 -// CHECK: store i32 %{{.*}}, i32* %{{.*}}, align 4 +// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"(i8 %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); _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits