diff options
author | Reid Kleckner <reid@kleckner.net> | 2015-06-09 17:49:42 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2015-06-09 17:49:42 +0000 |
commit | 0b9bbbfc13db6ba8c451d34f1a36736f715056fc (patch) | |
tree | 2b202bf4e0c4e9c1c048d891fd2d1c4ec77605ed /clang/lib/CodeGen | |
parent | f8439940eff4e0a65a65248a83d0d7bbeae632c5 (diff) | |
download | bcm5719-llvm-0b9bbbfc13db6ba8c451d34f1a36736f715056fc.tar.gz bcm5719-llvm-0b9bbbfc13db6ba8c451d34f1a36736f715056fc.zip |
Revert "Re-land r236052, "[SEH] Add 32-bit lowering code for __try""
This reverts commit r239415. This was committed accidentally, LLVM isn't
ready for this.
llvm-svn: 239417
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 234 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 13 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 20 |
3 files changed, 93 insertions, 174 deletions
diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 71c548deadc..d9a3f0b252a 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -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" @@ -1275,6 +1274,14 @@ llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) { } 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"); @@ -1299,39 +1306,25 @@ struct PerformSEHFinally : EHScopeStack::Cleanup { 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)); - // 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; - 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(); - } + llvm::Value *IsForEH = + llvm::ConstantInt::get(CGF.ConvertType(ArgTys[0]), F.isForEHCleanup()); + Args.add(RValue::get(IsForEH), ArgTys[0]); - CGF.EmitCall(*FnInfo, OutlinedFinally, ReturnValueSlot(), Args); + 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); } }; } @@ -1342,7 +1335,6 @@ struct CaptureFinder : ConstStmtVisitor<CaptureFinder> { CodeGenFunction &ParentCGF; const VarDecl *ParentThis; SmallVector<const VarDecl *, 4> Captures; - llvm::Value *AbnormalTermination = nullptr; CaptureFinder(CodeGenFunction &ParentCGF, const VarDecl *ParentThis) : ParentCGF(ParentCGF), ParentThis(ParentThis) {} @@ -1369,93 +1361,25 @@ struct CaptureFinder : ConstStmtVisitor<CaptureFinder> { 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.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) { + const Stmt *OutlinedStmt, + llvm::Value *ParentFP) { // Find all captures in the Stmt. CaptureFinder Finder(ParentCGF, ParentCGF.CXXABIThisDecl); Finder.Visit(OutlinedStmt); // Typically there are no captures and we can exit early. - if (Finder.Captures.empty() && !Finder.AbnormalTermination) + if (Finder.Captures.empty()) return; - // 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); - } + // 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) { @@ -1478,16 +1402,39 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, 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)}); + + } 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); + } - // 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; + // 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; } } @@ -1522,7 +1469,10 @@ void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF, OutlinedStmt->getLocStart(), OutlinedStmt->getLocStart()); CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn); - EmitCapturedLocals(ParentCGF, OutlinedStmt); + + auto AI = Fn->arg_begin(); + ++AI; + EmitCapturedLocals(ParentCGF, OutlinedStmt, &*AI); } /// Create a stub filter function that will ultimately hold the code of the @@ -1534,16 +1484,14 @@ CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF, const Expr *FilterExpr = Except.getFilterExpr(); SourceLocation StartLoc = FilterExpr->getLocStart(); + SEHPointersDecl = ImplicitParamDecl::Create( + getContext(), nullptr, StartLoc, + &getContext().Idents.get("exception_pointers"), getContext().VoidPtrTy); FunctionArgList Args; - 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)); - } + 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; @@ -1584,15 +1532,13 @@ CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF, SourceLocation StartLoc = FinallyBlock->getLocStart(); FunctionArgList Args; - 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)); - } + 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; @@ -1624,7 +1570,7 @@ void CodeGenFunction::EmitSEHExceptionCodeSave() { // }; // void *exn.slot = // (void *)(uintptr_t)exception_pointers->ExceptionRecord->ExceptionCode; - llvm::Value *Ptrs = EmitSEHExceptionInfo(); + llvm::Value *Ptrs = Builder.CreateLoad(GetAddrOfLocalVar(SEHPointersDecl)); llvm::Type *RecordTy = CGM.Int32Ty->getPointerTo(); llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy, nullptr); Ptrs = Builder.CreateBitCast(Ptrs, PtrsTy->getPointerTo()); @@ -1639,9 +1585,6 @@ void CodeGenFunction::EmitSEHExceptionCodeSave() { } 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) @@ -1659,8 +1602,6 @@ llvm::Value *CodeGenFunction::EmitSEHExceptionCode() { } 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(); @@ -1670,15 +1611,9 @@ llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() { 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); - - // 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; } @@ -1710,7 +1645,6 @@ void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) { // Just pop the cleanup if it's a __finally block. if (S.getFinallyHandler()) { PopCleanupBlock(); - ChildAbnormalTerminationSlot = nullptr; return; } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 663e6a1a13f..01da7500561 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -45,13 +45,12 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr), NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr), EHSelectorSlot(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), + 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), diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index cb8bfe39c3b..469022dc62e 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -310,13 +310,7 @@ public: /// write the current selector value into this alloca. llvm::AllocaInst *EHSelectorSlot; - /// 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; + llvm::AllocaInst *AbnormalTerminationSlot; /// The implicit parameter to SEH filter functions of type /// 'EXCEPTION_POINTERS*'. @@ -2045,16 +2039,8 @@ 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); - - /// 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 EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt *OutlinedStmt, + llvm::Value *ParentFP); void EmitCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef<const Attr *> Attrs = None); |