It looks like this causes linker errors when building 32-bit Windows apps ( crbug.com/482292). I reverted this in r236082.
On Tue, Apr 28, 2015 at 3:19 PM, Reid Kleckner <[email protected]> wrote: > Author: rnk > Date: Tue Apr 28 17:19:32 2015 > New Revision: 236052 > > URL: http://llvm.org/viewvc/llvm-project?rev=236052&view=rev > Log: > [SEH] Add 32-bit lowering code for __try > > This is just the clang-side of 32-bit SEH. LLVM still needs work, and it > will determinstically fail to compile until it's feature complete. > > On x86, all outlined handlers have no parameters, but they do implicitly > take the EBP value passed in and use it to address locals of the parent > frame. We model this with llvm.frameaddress(1). > > This works (mostly), but __finally block inlining can break it. For now, > we apply the 'noinline' attribute. If we really want to inline __finally > blocks on 32-bit x86, we should teach the inliner how to untangle > frameescape and framerecover. > > Promote the error diagnostic from codegen to sema. It now rejects SEH on > non-Windows platforms. LLVM doesn't implement SEH on non-x86 Windows > platforms, but there's nothing preventing it. > > 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.c > > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=236052&r1=236051&r2=236052&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Apr 28 > 17:19:32 2015 > @@ -5535,6 +5535,8 @@ 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=236052&r1=236051&r2=236052&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/Basic/TargetInfo.h (original) > +++ cfe/trunk/include/clang/Basic/TargetInfo.h Tue Apr 28 17:19:32 2015 > @@ -807,6 +807,11 @@ 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=236052&r1=236051&r2=236052&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGException.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGException.cpp Tue Apr 28 17:19:32 2015 > @@ -20,6 +20,7 @@ > #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" > @@ -1271,14 +1272,6 @@ 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"); > @@ -1303,25 +1296,39 @@ struct PerformSEHFinally : EHScopeStack: > > void Emit(CodeGenFunction &CGF, Flags F) override { > ASTContext &Context = CGF.getContext(); > - QualType ArgTys[2] = {Context.UnsignedCharTy, Context.VoidPtrTy}; > - FunctionProtoType::ExtProtoInfo EPI; > - const auto *FTP = cast<FunctionType>( > - Context.getFunctionType(Context.VoidTy, ArgTys, EPI)); > + CodeGenModule &CGM = CGF.CGM; > > + // In 64-bit, we call the child function with arguments. In 32-bit, > we store > + // zero in the parent frame and use framerecover to check the value. > + const CGFunctionInfo *FnInfo; > CallArgList Args; > - llvm::Value *IsForEH = > - llvm::ConstantInt::get(CGF.ConvertType(ArgTys[0]), > F.isForEHCleanup()); > - Args.add(RValue::get(IsForEH), ArgTys[0]); > + if (CGF.getTarget().getTriple().getArch() == llvm::Triple::x86_64) { > + // 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]); > + 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)); > + FnInfo = &CGM.getTypes().arrangeFreeFunctionCall(Args, FPT, > + > /*chainCall=*/false); > + } else { > + // Emit the zero store if this is normal control flow. There are no > + // explicit arguments. > + if (F.isForNormalCleanup() && CGF.ChildAbnormalTerminationSlot) > + CGF.Builder.CreateStore(CGF.Builder.getInt32(0), > + CGF.ChildAbnormalTerminationSlot); > + FnInfo = &CGM.getTypes().arrangeNullaryFunction(); > + } > > - 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); > + CGF.EmitCall(*FnInfo, OutlinedFinally, ReturnValueSlot(), Args); > } > }; > } > @@ -1332,6 +1339,7 @@ struct CaptureFinder : ConstStmtVisitor< > CodeGenFunction &ParentCGF; > const VarDecl *ParentThis; > SmallVector<const VarDecl *, 4> Captures; > + llvm::Value *AbnormalTermination = nullptr; > CaptureFinder(CodeGenFunction &ParentCGF, const VarDecl *ParentThis) > : ParentCGF(ParentCGF), ParentThis(ParentThis) {} > > @@ -1358,25 +1366,93 @@ 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__abnormal_termination: > + case Builtin::BI_abnormal_termination: > + // 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 (!AbnormalTermination) > + AbnormalTermination = ParentCGF.CreateMemTemp( > + ParentCGF.getContext().IntTy, "abnormal_termination"); > + 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.CreateCall3(FrameRecoverFn, ParentI8Fn, ParentFP, > + llvm::ConstantInt::get(Int32Ty, > FrameEscapeIdx)); > + > + } else { > + // If the parent didn't have an alloca, we're doing some nested > outlining. > + // Just clone the existing framerecover call, but tweak the FP > argument to > + // use our FP value. All other arguments are constants. > + auto *ParentRecover = > + cast<llvm::IntrinsicInst>(ParentVar->stripPointerCasts()); > + assert(ParentRecover->getIntrinsicID() == > llvm::Intrinsic::framerecover && > + "expected alloca or framerecover in parent LocalDeclMap"); > + RecoverCall = cast<llvm::CallInst>(ParentRecover->clone()); > + RecoverCall->setArgOperand(1, ParentFP); > + RecoverCall->insertBefore(AllocaInsertPt); > + } > + > + // Bitcast the variable, rename it, and insert it in the local decl map. > + llvm::Value *ChildVar = > + Builder.CreateBitCast(RecoverCall, ParentVar->getType()); > + ChildVar->setName(ParentVar->getName()); > + return ChildVar; > +} > + > void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, > - const Stmt *OutlinedStmt, > - llvm::Value *ParentFP) { > + const Stmt *OutlinedStmt) { > // Find all captures in the Stmt. > CaptureFinder Finder(ParentCGF, ParentCGF.CXXABIThisDecl); > Finder.Visit(OutlinedStmt); > > // Typically there are no captures and we can exit early. > - if (Finder.Captures.empty()) > + if (Finder.Captures.empty() && !Finder.AbnormalTermination) > return; > > - // Prepare the first two arguments to llvm.framerecover. > - llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration( > - &CGM.getModule(), llvm::Intrinsic::framerecover); > - llvm::Constant *ParentI8Fn = > - llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy); > + // The parent FP is passed in as EBP on x86 and the second argument on > x64. > + llvm::Value *ParentFP; > + if (CGM.getTarget().getTriple().getArch() == llvm::Triple::x86_64) { > + auto AI = CurFn->arg_begin(); > + ++AI; > + ParentFP = AI; > + } else { > + CGBuilderTy Builder(AllocaInsertPt); > + ParentFP = Builder.CreateCall( > + CGM.getIntrinsic(llvm::Intrinsic::frameaddress), > Builder.getInt32(1)); > + > + // Inlining will break llvm.frameaddress(1), so disable it. > + // FIXME: We could teach the inliner about the special meaning of > + // frameaddress, framerecover, and frameescape to remove this > limitation. > + CurFn->addFnAttr(llvm::Attribute::NoInline); > + } > > // Create llvm.framerecover calls for all captures. > for (const VarDecl *VD : Finder.Captures) { > @@ -1399,39 +1475,16 @@ void CodeGenFunction::EmitCapturedLocals > continue; > llvm::Value *ParentVar = I->second; > > - llvm::CallInst *RecoverCall = nullptr; > - CGBuilderTy Builder(AllocaInsertPt); > - if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) { > - // Mark the variable escaped if nobody else referenced it and > compute the > - // frameescape index. > - auto InsertPair = > - ParentCGF.EscapedLocals.insert(std::make_pair(ParentAlloca, > -1)); > - if (InsertPair.second) > - InsertPair.first->second = ParentCGF.EscapedLocals.size() - 1; > - int FrameEscapeIdx = InsertPair.first->second; > - // call i8* @llvm.framerecover(i8* bitcast(@parentFn), i8* %fp, i32 > N) > - RecoverCall = > - Builder.CreateCall3(FrameRecoverFn, ParentI8Fn, ParentFP, > - llvm::ConstantInt::get(Int32Ty, > FrameEscapeIdx)); > + LocalDeclMap[VD] = > + recoverAddrOfEscapedLocal(ParentCGF, ParentVar, 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; > + // AbnormalTermination is just another capture, but it has no Decl. > + if (Finder.AbnormalTermination) { > + AbnormalTerminationSlot = recoverAddrOfEscapedLocal( > + ParentCGF, Finder.AbnormalTermination, ParentFP); > + // Save the slot on the parent so it can store 1 and 0 to it. > + ParentCGF.ChildAbnormalTerminationSlot = Finder.AbnormalTermination; > } > } > > @@ -1466,10 +1519,7 @@ void CodeGenFunction::startOutlinedSEHHe > OutlinedStmt->getLocStart(), OutlinedStmt->getLocStart()); > > CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn); > - > - auto AI = Fn->arg_begin(); > - ++AI; > - EmitCapturedLocals(ParentCGF, OutlinedStmt, &*AI); > + EmitCapturedLocals(ParentCGF, OutlinedStmt); > } > > /// Create a stub filter function that will ultimately hold the code of > the > @@ -1481,14 +1531,16 @@ CodeGenFunction::GenerateSEHFilterFuncti > 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)); > + if (CGM.getTarget().getTriple().getArch() == llvm::Triple::x86_64) { > + SEHPointersDecl = ImplicitParamDecl::Create( > + getContext(), nullptr, StartLoc, > + &getContext().Idents.get("exception_pointers"), > getContext().VoidPtrTy); > + 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; > @@ -1529,13 +1581,15 @@ CodeGenFunction::GenerateSEHFinallyFunct > SourceLocation StartLoc = FinallyBlock->getLocStart(); > > 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)); > + if (CGM.getTarget().getTriple().getArch() == llvm::Triple::x86_64) { > + 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; > @@ -1567,7 +1621,7 @@ void CodeGenFunction::EmitSEHExceptionCo > // }; > // void *exn.slot = > // (void > *)(uintptr_t)exception_pointers->ExceptionRecord->ExceptionCode; > - llvm::Value *Ptrs = > Builder.CreateLoad(GetAddrOfLocalVar(SEHPointersDecl)); > + llvm::Value *Ptrs = EmitSEHExceptionInfo(); > llvm::Type *RecordTy = CGM.Int32Ty->getPointerTo(); > llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy, > nullptr); > Ptrs = Builder.CreateBitCast(Ptrs, PtrsTy->getPointerTo()); > @@ -1582,6 +1636,9 @@ void CodeGenFunction::EmitSEHExceptionCo > } > > llvm::Value *CodeGenFunction::EmitSEHExceptionInfo() { > + if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86_64) > + return Builder.CreateCall( > + CGM.getIntrinsic(llvm::Intrinsic::eh_exceptioninfo)); > // Sema should diagnose calling this builtin outside of a filter > context, but > // don't crash if we screw up. > if (!SEHPointersDecl) > @@ -1599,6 +1656,8 @@ llvm::Value *CodeGenFunction::EmitSEHExc > } > > llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() { > + if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86_64) > + return Builder.CreateLoad(AbnormalTerminationSlot); > // Abnormal termination is just the first parameter to the outlined > finally > // helper. > auto AI = CurFn->arg_begin(); > @@ -1608,9 +1667,15 @@ llvm::Value *CodeGenFunction::EmitSEHAbn > void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) { > CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true); > if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) { > - // Push a cleanup for __finally blocks. > + // Outline the finally block. > llvm::Function *FinallyFunc = > HelperCGF.GenerateSEHFinallyFunction(*this, *Finally); > + > + // Store 1 to indicate abnormal termination if an exception is thrown. > + if (ChildAbnormalTerminationSlot) > + Builder.CreateStore(Builder.getInt32(1), > ChildAbnormalTerminationSlot); > + > + // Push a cleanup for __finally blocks. > EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, > FinallyFunc); > return; > } > @@ -1642,6 +1707,7 @@ void CodeGenFunction::ExitSEHTryStmt(con > // Just pop the cleanup if it's a __finally block. > if (S.getFinallyHandler()) { > PopCleanupBlock(); > + ChildAbnormalTerminationSlot = nullptr; > return; > } > > > Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=236052&r1=236051&r2=236052&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original) > +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Tue Apr 28 17:19:32 2015 > @@ -45,12 +45,13 @@ CodeGenFunction::CodeGenFunction(CodeGen > LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr), > NextCleanupDestIndex(1), FirstBlockInfo(nullptr), > EHResumeBlock(nullptr), > ExceptionSlot(nullptr), EHSelectorSlot(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), > + ChildAbnormalTerminationSlot(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=236052&r1=236051&r2=236052&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) > +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Apr 28 17:19:32 2015 > @@ -310,7 +310,13 @@ public: > /// write the current selector value into this alloca. > llvm::AllocaInst *EHSelectorSlot; > > - llvm::AllocaInst *AbnormalTerminationSlot; > + /// Entering and leaving an SEH __try / __finally scope causes stores > to this > + /// slot. > + llvm::Value *ChildAbnormalTerminationSlot; > + > + /// The SEH __abnormal_termination() intrinsic lowers down to loads > from this > + /// slot from a parent function. > + llvm::Value *AbnormalTerminationSlot; > > /// The implicit parameter to SEH filter functions of type > /// 'EXCEPTION_POINTERS*'. > @@ -2033,8 +2039,16 @@ public: > /// Scan the outlined statement for captures from the parent function. > For > /// each capture, mark the capture as escaped and emit a call to > /// llvm.framerecover. Insert the framerecover result into the > LocalDeclMap. > - void EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt > *OutlinedStmt, > - llvm::Value *ParentFP); > + void EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt > *OutlinedStmt); > + > + /// 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); > > 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=236052&r1=236051&r2=236052&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaStmt.cpp (original) > +++ cfe/trunk/lib/Sema/SemaStmt.cpp Tue Apr 28 17:19:32 2015 > @@ -25,6 +25,7 @@ > #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" > @@ -3637,6 +3638,10 @@ 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=236052&r1=236051&r2=236052&view=diff > > ============================================================================== > --- cfe/trunk/test/CodeGen/exceptions-seh-finally.c (original) > +++ cfe/trunk/test/CodeGen/exceptions-seh-finally.c Tue Apr 28 17:19:32 > 2015 > @@ -1,4 +1,7 @@ > -// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm > -o - | FileCheck %s > +// 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 > > void abort(void) __attribute__((noreturn)); > void might_crash(void); > @@ -17,18 +20,20 @@ void basic_finally(void) { > // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] > // > // CHECK: [[invoke_cont]] > -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > -// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i8 0, i8* %[[fp]]) > +// X64: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// X64: call void @"\01?fin$0@0@basic_finally@@"(i8 0, i8* %[[fp]]) > +// X86: call void @"\01?fin$0@0@basic_finally@@"() > // 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 1, i8* %[[fp]]) > +// X64: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// X64: call void @"\01?fin$0@0@basic_finally@@"(i8 1, i8* %[[fp]]) > +// X86: call void @"\01?fin$0@0@basic_finally@@"() > // CHECK: resume { i8*, i32 } > > -// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"(i8 > %abnormal_termination, i8* %frame_pointer) > +// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}}) > // CHECK: call void @cleanup() > > // Mostly check that we don't double emit 'r' which would crash. > @@ -57,11 +62,12 @@ l: > // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] > // > // CHECK: [[invoke_cont]] > -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > -// CHECK: call void @"\01?fin$0@0@label_in_finally@@"(i8 0, i8* %[[fp]]) > +// X64: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// X64: call void @"\01?fin$0@0@label_in_finally@@"(i8 0, i8* %[[fp]]) > +// X86: call void @"\01?fin$0@0@label_in_finally@@"() > // CHECK: ret void > > -// CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"(i8 > %abnormal_termination, i8* %frame_pointer) > +// CHECK: define internal void @"\01?fin$0@0@label_in_finally@@"({{.*}}) > // CHECK: br label %[[l:[^ ]*]] > // > // CHECK: [[l]] > @@ -80,23 +86,33 @@ void use_abnormal_termination(void) { > } > > // CHECK-LABEL: define void @use_abnormal_termination() > +// X86: call void (...) @llvm.frameescape(i32* %[[abnormal_termination:[^ > ),]*]]) > +// X86: store i32 1, i32* %[[abnormal_termination]] > // CHECK: invoke void @might_crash() > // CHECK: to label %[[invoke_cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] > // > // CHECK: [[invoke_cont]] > -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > -// CHECK: call void @"\01?fin$0@0@use_abnormal_termination@@"(i8 0, i8* > %[[fp]]) > +// X64: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// X64: call void @"\01?fin$0@0@use_abnormal_termination@@"(i8 0, i8* > %[[fp]]) > +// X86: store i32 0, i32* %[[abnormal_termination]] > +// X86: call void @"\01?fin$0@0@use_abnormal_termination@@"() > // 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 1, i8* > %[[fp]]) > +// X64: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// X64: call void @"\01?fin$0@0@use_abnormal_termination@@"(i8 1, i8* > %[[fp]]) > +// X86: call void @"\01?fin$0@0@use_abnormal_termination@@"() > // CHECK: resume { i8*, 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 > +// X64: define internal void @"\01?fin$0@0@use_abnormal_termination@@"(i8 > %[[abnormal:abnormal_termination]], i8* %frame_pointer) > +// X64: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32 > +// X86: define internal void @"\01?fin$0@0@use_abnormal_termination@@"() > +// X86: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1) > +// X86: %[[abnormal_i8:[^ ]*]] = call i8* @llvm.framerecover(i8* bitcast > (void ()* @use_abnormal_termination to i8*), i8* %[[fp]], i32 0) > +// X86: %[[abnormal:[^ ]*]] = bitcast i8* %[[abnormal_i8]] to i32* > +// X86: %[[abnormal_zext:[^ ]*]] = load i32, i32* %[[abnormal]] > // CHECK: store i32 %[[abnormal_zext]], i32* @crashed > // CHECK-NEXT: ret void > > @@ -109,11 +125,10 @@ void noreturn_noop_finally() { > } > > // CHECK-LABEL: define void @noreturn_noop_finally() > -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > -// CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"(i8 0, i8* > %[[fp]]) > +// CHECK: call void @"\01?fin$0@0@noreturn_noop_finally@@"({{.*}}) > // CHECK: ret void > > -// CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@@"(i8 > %abnormal_termination, i8* %frame_pointer) > +// CHECK: define internal void @"\01?fin$0@0@noreturn_noop_finally@ > @"({{.*}}) > // CHECK: call void @abort() > // CHECK: unreachable > > @@ -130,18 +145,16 @@ void noreturn_finally() { > // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] > // > // CHECK: [[cont]] > -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > -// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i8 0, i8* %[[fp]]) > +// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}}) > // CHECK: ret void > // > // CHECK: [[lpad]] > // CHECK: landingpad > // CHECK-NEXT: cleanup > -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > -// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"(i8 1, i8* %[[fp]]) > +// CHECK: call void @"\01?fin$0@0@noreturn_finally@@"({{.*}}) > // CHECK: resume { i8*, i32 } > > -// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"(i8 > %abnormal_termination, i8* %frame_pointer) > +// CHECK: define internal void @"\01?fin$0@0@noreturn_finally@@"({{.*}}) > // CHECK: call void @abort() > // CHECK: unreachable > > @@ -152,11 +165,10 @@ int finally_with_return() { > } > } > // CHECK-LABEL: define i32 @finally_with_return() > -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > -// CHECK-NEXT: call void @"\01?fin$0@0@finally_with_return@@"(i8 0, i8* > %[[fp]]) > +// CHECK: call void @"\01?fin$0@0@finally_with_return@@"({{.*}}) > // CHECK-NEXT: ret i32 42 > > -// CHECK: define internal void @"\01?fin$0@0@finally_with_return@@"(i8 > %abnormal_termination, i8* %frame_pointer) > +// CHECK: define internal void @"\01?fin$0@0@finally_with_return@ > @"({{.*}}) > // CHECK-NOT: br i1 > // CHECK-NOT: br label > // CHECK: ret void > @@ -174,25 +186,22 @@ int nested___finally___finally() { > } > > // CHECK-LABEL: define i32 @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: invoke void @"\01?fin$1@0@nested___finally___finally@@"({{.*}}) > // 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@@"(i8 > 0, i8* %[[fp]]) > +// CHECK: call void @"\01?fin$0@0@nested___finally___finally@@"({{.*}}) > // CHECK-NEXT: ret i32 0 > // > // 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@@"(i8 > 1, i8* %[[fp]]) > +// CHECK: call 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-LABEL: define internal void @"\01?fin$0@0 > @nested___finally___finally@@"({{.*}}) > // CHECK: ret void > > -// CHECK-LABEL: define internal void @"\01?fin$1@0 > @nested___finally___finally@@"(i8 %abnormal_termination, i8* > %frame_pointer) > +// CHECK-LABEL: define internal void @"\01?fin$1@0 > @nested___finally___finally@@"({{.*}}) > // CHECK: unreachable > > int nested___finally___finally_with_eh_edge() { > @@ -212,31 +221,27 @@ int nested___finally___finally_with_eh_e > // 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@@"(i8 0, i8* %[[fp]]) > +// CHECK: invoke void @"\01?fin$1@0 > @nested___finally___finally_with_eh_edge@@"({{.*}}) > // 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@@"(i8 0, i8* %[[fp]]) > +// CHECK: call void @"\01?fin$0@0 > @nested___finally___finally_with_eh_edge@@"({{.*}}) > // CHECK-NEXT: ret i32 912 > // > // CHECK: [[lpad1]] > // CHECK-NEXT: landingpad > // CHECK-NEXT: cleanup > -// 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: invoke void @"\01?fin$1@0 > @nested___finally___finally_with_eh_edge@@"({{.*}}) > // CHECK: to label %[[outercont:[^ ]*]] unwind label %[[lpad2]] > // > // 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@@"(i8 1, i8* %[[fp]]) > +// CHECK: call void @"\01?fin$0@0 > @nested___finally___finally_with_eh_edge@@"({{.*}}) > // CHECK: resume > > -// CHECK-LABEL: define internal void @"\01?fin$0@0 > @nested___finally___finally_with_eh_edge@@"(i8 %abnormal_termination, i8* > %frame_pointer) > +// CHECK-LABEL: define internal void @"\01?fin$0@0 > @nested___finally___finally_with_eh_edge@@"({{.*}}) > // CHECK: ret void > > -// CHECK-LABEL: define internal void @"\01?fin$1@0 > @nested___finally___finally_with_eh_edge@@"(i8 %abnormal_termination, i8* > %frame_pointer) > +// CHECK-LABEL: define internal void @"\01?fin$1@0 > @nested___finally___finally_with_eh_edge@@"({{.*}}) > // 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=236052&r1=236051&r2=236052&view=diff > > ============================================================================== > --- cfe/trunk/test/CodeGen/exceptions-seh.c (original) > +++ cfe/trunk/test/CodeGen/exceptions-seh.c Tue Apr 28 17:19:32 2015 > @@ -1,4 +1,7 @@ > -// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm > -o - | FileCheck %s > +// 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 > > void try_body(int numerator, int denominator, int *myres) { > *myres = numerator / denominator; > @@ -24,7 +27,8 @@ int safe_div(int numerator, int denomina > // CHECK: to label %{{.*}} unwind label %[[lpad:[^ ]*]] > // > // CHECK: [[lpad]] > -// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* > @__C_specific_handler to i8*) > +// X64: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* > @__C_specific_handler to i8*) > +// X86: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* > @_except_handler3 to i8*) > // CHECK-NEXT: catch i8* null > // CHECK-NOT: br i1 > // CHECK: br label %[[except:[^ ]*]] > @@ -52,14 +56,19 @@ int filter_expr_capture(void) { > // CHECK: invoke void @j() #[[NOINLINE]] > // > // CHECK: landingpad > -// CHECK-NEXT: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0 > @filter_expr_capture@@" to i8*) > +// CHECK-NEXT: catch i8* bitcast (i32 ({{.*}})* @"\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]] > > -// 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) > +// 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: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1) > +// X86: call i8* @llvm.framerecover(i8* bitcast (i32 ()* > @filter_expr_capture to i8*), i8* %[[fp]], i32 0) > +// > // CHECK: store i32 -1, i32* %{{.*}} > // CHECK: ret i32 -1 > > @@ -87,19 +96,20 @@ int nested_try(void) { > // CHECK: br label %[[inner_try_cont:[^ ]*]] > // > // CHECK: [[lpad]] > -// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* > @__C_specific_handler 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*) > +// X64: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* > @__C_specific_handler to i8*) > +// X86: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* > @_except_handler3 to i8*) > +// 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: 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 (i8*, i8*)* > @"\01?filt$1@0@nested_try@@" to i8*)) > +// CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ({{.*}})* > @"\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 (i8*, i8*)* > @"\01?filt$0@0@nested_try@@" to i8*)) > +// CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ({{.*}})* > @"\01?filt$0@0@nested_try@@" to i8*)) > // CHECK: icmp eq i32 > // CHECK: br i1 > // > @@ -115,6 +125,20 @@ 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.eh.exceptioninfo() > +// CHECK: load i32*, i32** > +// CHECK: load i32, i32* > +// CHECK: ptrtoint > +// CHECK: icmp eq i32 %{{.*}}, 456 > +// > +// CHECK-LABEL: define internal i32 @"\01?filt$1@0@nested_try@@"({{.*}}) > +// X86: call i8* @llvm.eh.exceptioninfo() > +// CHECK: load i32*, i32** > +// CHECK: load i32, i32* > +// CHECK: ptrtoint > +// CHECK: icmp eq i32 %{{.*}}, 123 > > static unsigned g = 0; > void basic_finally(void) { > @@ -134,18 +158,21 @@ void basic_finally(void) { > // CHECK: to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]] > // > // CHECK: [[cont]] > -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > -// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i8 0, i8* %[[fp]]) > +// X64: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// X64: call void @"\01?fin$0@0@basic_finally@@"(i8 0, i8* %[[fp]]) > +// X86: call void @"\01?fin$0@0@basic_finally@@"() > // CHECK: ret void > // > // CHECK: [[lpad]] > -// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* > @__C_specific_handler to i8*) > +// X64: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* > @__C_specific_handler to i8*) > +// X86: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* > @_except_handler3 to i8*) > // CHECK-NEXT: cleanup > -// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > -// CHECK: call void @"\01?fin$0@0@basic_finally@@"(i8 1, i8* %[[fp]]) > +// X64: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0) > +// X64: call void @"\01?fin$0@0@basic_finally@@"(i8 1, i8* %[[fp]]) > +// X86: call void @"\01?fin$0@0@basic_finally@@"() > // CHECK: resume > > -// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"(i8 > %abnormal_termination, i8* %frame_pointer) > +// CHECK: define internal void @"\01?fin$0@0@basic_finally@@"({{.*}}) > // CHECK: load i32, i32* @g, align 4 > // CHECK: add i32 %{{.*}}, -1 > // CHECK: store i32 %{{.*}}, i32* @g, align 4 > > > _______________________________________________ > 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
