[llvm] r235768 - [SEH] Implement GetExceptionCode in __except blocks

Aditya Nandakumar aditya_nandakumar at apple.com
Fri Apr 24 16:53:19 PDT 2015


Hi Reid,

You have an unused variable Context in processSEHCatchHandler and this is breaking our Werror builders.

Could you please fix that.

Thanks
Aditya
> On Apr 24, 2015, at 1:25 PM, Reid Kleckner <reid at kleckner.net> wrote:
> 
> Author: rnk
> Date: Fri Apr 24 15:25:05 2015
> New Revision: 235768
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=235768&view=rev
> Log:
> [SEH] Implement GetExceptionCode in __except blocks
> 
> This introduces an intrinsic called llvm.eh.exceptioncode. It is lowered
> by copying the EAX value live into whatever basic block it is called
> from. Obviously, this only works if you insert it late during codegen,
> because otherwise mid-level passes might reschedule it.
> 
> Modified:
>    llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h
>    llvm/trunk/include/llvm/IR/Intrinsics.td
>    llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
>    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
>    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
>    llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
>    llvm/trunk/test/CodeGen/WinEH/seh-resume-phi.ll
>    llvm/trunk/test/CodeGen/X86/seh-catch-all.ll
> 
> Modified: llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h?rev=235768&r1=235767&r2=235768&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h Fri Apr 24 15:25:05 2015
> @@ -221,7 +221,7 @@ public:
>   int getArgumentFrameIndex(const Argument *A);
> 
> private:
> -  void addSEHHandlersForLPads();
> +  void addSEHHandlersForLPads(ArrayRef<const LandingPadInst *> LPads);
> 
>   /// LiveOutRegInfo - Information about live out vregs.
>   IndexedMap<LiveOutInfo, VirtReg2IndexFunctor> LiveOutRegInfo;
> 
> Modified: llvm/trunk/include/llvm/IR/Intrinsics.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Intrinsics.td?rev=235768&r1=235767&r2=235768&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/Intrinsics.td (original)
> +++ llvm/trunk/include/llvm/IR/Intrinsics.td Fri Apr 24 15:25:05 2015
> @@ -421,6 +421,8 @@ def int_eh_endcatch : Intrinsic<[], []>;
> // Represents the list of actions to take when an exception is thrown.
> def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>;
> 
> +def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], []>;
> +
> // __builtin_unwind_init is an undocumented GCC intrinsic that causes all
> // callee-saved registers to be saved and restored (regardless of whether they
> // are used) in the calling function. It is used by libgcc_eh.
> 
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp?rev=235768&r1=235767&r2=235768&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp Fri Apr 24 15:25:05 2015
> @@ -271,40 +271,49 @@ void FunctionLoweringInfo::set(const Fun
>   }
> 
>   // Mark landing pad blocks.
> -  const LandingPadInst *LP = nullptr;
> +  SmallVector<const LandingPadInst *, 4> LPads;
>   for (BB = Fn->begin(); BB != EB; ++BB) {
>     if (const auto *Invoke = dyn_cast<InvokeInst>(BB->getTerminator()))
>       MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad();
>     if (BB->isLandingPad())
> -      LP = BB->getLandingPadInst();
> +      LPads.push_back(BB->getLandingPadInst());
>   }
> 
> -  // Calculate EH numbers for MSVC C++ EH and save SEH handlers if necessary.
> +  // If this is an MSVC EH personality, we need to do a bit more work.
>   EHPersonality Personality = EHPersonality::Unknown;
> -  if (LP)
> -    Personality = classifyEHPersonality(LP->getPersonalityFn());
> +  if (!LPads.empty())
> +    Personality = classifyEHPersonality(LPads.back()->getPersonalityFn());
> +  if (!isMSVCEHPersonality(Personality))
> +    return;
> +
> +  WinEHFuncInfo *EHInfo = nullptr;
>   if (Personality == EHPersonality::MSVC_Win64SEH) {
> -    addSEHHandlersForLPads();
> +    addSEHHandlersForLPads(LPads);
>   } else if (Personality == EHPersonality::MSVC_CXX) {
>     const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
> -    WinEHFuncInfo &FI = MMI.getWinEHFuncInfo(WinEHParentFn);
> -    if (FI.LandingPadStateMap.empty()) {
> -      WinEHNumbering Num(FI);
> +    EHInfo = &MMI.getWinEHFuncInfo(WinEHParentFn);
> +    if (EHInfo->LandingPadStateMap.empty()) {
> +      WinEHNumbering Num(*EHInfo);
>       Num.calculateStateNumbers(*WinEHParentFn);
>       // Pop everything on the handler stack.
>       Num.processCallSite(None, ImmutableCallSite());
>     }
> +
> +    // Copy the state numbers to LandingPadInfo for the current function, which
> +    // could be a handler or the parent.
> +    for (const LandingPadInst *LP : LPads) {
> +      MachineBasicBlock *LPadMBB = MBBMap[LP->getParent()];
> +      MMI.addWinEHState(LPadMBB, EHInfo->LandingPadStateMap[LP]);
> +    }
>   }
> }
> 
> -void FunctionLoweringInfo::addSEHHandlersForLPads() {
> +void FunctionLoweringInfo::addSEHHandlersForLPads(
> +    ArrayRef<const LandingPadInst *> LPads) {
>   MachineModuleInfo &MMI = MF->getMMI();
> 
>   // Iterate over all landing pads with llvm.eh.actions calls.
> -  for (const BasicBlock &BB : *Fn) {
> -    const LandingPadInst *LP = BB.getLandingPadInst();
> -    if (!LP)
> -      continue;
> +  for (const LandingPadInst *LP : LPads) {
>     const IntrinsicInst *ActionsCall =
>         dyn_cast<IntrinsicInst>(LP->getNextNode());
>     if (!ActionsCall ||
> 
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=235768&r1=235767&r2=235768&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Fri Apr 24 15:25:05 2015
> @@ -4817,6 +4817,18 @@ SelectionDAGBuilder::visitIntrinsicCall(
>   case Intrinsic::eh_begincatch:
>   case Intrinsic::eh_endcatch:
>     llvm_unreachable("begin/end catch intrinsics not lowered in codegen");
> +  case Intrinsic::eh_exceptioncode: {
> +    unsigned Reg = TLI.getExceptionPointerRegister();
> +    assert(Reg && "cannot get exception code on this platform");
> +    MVT PtrVT = TLI.getPointerTy();
> +    const TargetRegisterClass *PtrRC = TLI.getRegClassFor(PtrVT);
> +    unsigned VReg = FuncInfo.MBB->addLiveIn(Reg, PtrRC);
> +    SDValue N =
> +        DAG.getCopyFromReg(DAG.getEntryNode(), getCurSDLoc(), VReg, PtrVT);
> +    N = DAG.getZExtOrTrunc(N, getCurSDLoc(), MVT::i32);
> +    setValue(&I, N);
> +    return nullptr;
> +  }
>   }
> }
> 
> 
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=235768&r1=235767&r2=235768&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Fri Apr 24 15:25:05 2015
> @@ -961,12 +961,6 @@ bool SelectionDAGISel::PrepareEHLandingP
>     for (MachineBasicBlock *InvokeBB : InvokeBBs)
>       InvokeBB->removeSuccessor(MBB);
> 
> -    // Transfer EH state number assigned to the IR block to the MBB.
> -    if (Personality == EHPersonality::MSVC_CXX) {
> -      WinEHFuncInfo &FI = MF->getMMI().getWinEHFuncInfo(MF->getFunction());
> -      MF->getMMI().addWinEHState(MBB, FI.LandingPadStateMap[LPadInst]);
> -    }
> -
>     // Don't select instructions for the landingpad.
>     return false;
>   }
> 
> Modified: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=235768&r1=235767&r2=235768&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (original)
> +++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Fri Apr 24 15:25:05 2015
> @@ -71,7 +71,7 @@ class WinEHPrepare : public FunctionPass
> public:
>   static char ID; // Pass identification, replacement for typeid.
>   WinEHPrepare(const TargetMachine *TM = nullptr)
> -      : FunctionPass(ID), DT(nullptr) {}
> +      : FunctionPass(ID), DT(nullptr), SEHExceptionCodeSlot(nullptr) {}
> 
>   bool runOnFunction(Function &Fn) override;
> 
> @@ -133,6 +133,8 @@ private:
>   // outlined into a handler.  This is done after all handlers have been
>   // outlined but before the outlined code is pruned from the parent function.
>   DenseMap<const BasicBlock *, BasicBlock *> LPadTargetBlocks;
> +
> +  AllocaInst *SEHExceptionCodeSlot;
> };
> 
> class WinEHFrameVariableMaterializer : public ValueMaterializer {
> @@ -628,6 +630,13 @@ bool WinEHPrepare::prepareExceptionHandl
>   Type *Int32Type = Type::getInt32Ty(Context);
>   Function *ActionIntrin = Intrinsic::getDeclaration(M, Intrinsic::eh_actions);
> 
> +  if (isAsynchronousEHPersonality(Personality)) {
> +    // FIXME: Switch the ehptr type to i32 and then switch this.
> +    SEHExceptionCodeSlot =
> +        new AllocaInst(Int8PtrType, nullptr, "seh_exception_code",
> +                       F.getEntryBlock().getFirstInsertionPt());
> +  }
> +
>   for (LandingPadInst *LPad : LPads) {
>     // Look for evidence that this landingpad has already been processed.
>     bool LPadHasActionList = false;
> @@ -680,23 +689,48 @@ bool WinEHPrepare::prepareExceptionHandl
> 
>     // Replace all extracted values with undef and ultimately replace the
>     // landingpad with undef.
> -    // FIXME: This doesn't handle SEH GetExceptionCode(). For now, we just give
> -    // out undef until we figure out the codegen support.
> -    SmallVector<Instruction *, 4> Extracts;
> +    SmallVector<Instruction *, 4> SEHCodeUses;
> +    SmallVector<Instruction *, 4> EHUndefs;
>     for (User *U : LPad->users()) {
>       auto *E = dyn_cast<ExtractValueInst>(U);
>       if (!E)
>         continue;
>       assert(E->getNumIndices() == 1 &&
>              "Unexpected operation: extracting both landing pad values");
> -      Extracts.push_back(E);
> +      unsigned Idx = *E->idx_begin();
> +      assert((Idx == 0 || Idx == 1) && "unexpected index");
> +      if (Idx == 0 && isAsynchronousEHPersonality(Personality))
> +        SEHCodeUses.push_back(E);
> +      else
> +        EHUndefs.push_back(E);
>     }
> -    for (Instruction *E : Extracts) {
> +    for (Instruction *E : EHUndefs) {
>       E->replaceAllUsesWith(UndefValue::get(E->getType()));
>       E->eraseFromParent();
>     }
>     LPad->replaceAllUsesWith(UndefValue::get(LPad->getType()));
> 
> +    // Rewrite uses of the exception pointer to loads of an alloca.
> +    for (Instruction *E : SEHCodeUses) {
> +      SmallVector<Use *, 4> Uses;
> +      for (Use &U : E->uses())
> +        Uses.push_back(&U);
> +      for (Use *U : Uses) {
> +        auto *I = cast<Instruction>(U->getUser());
> +        if (isa<ResumeInst>(I))
> +          continue;
> +        LoadInst *LI;
> +        if (auto *Phi = dyn_cast<PHINode>(I))
> +          LI = new LoadInst(SEHExceptionCodeSlot, "sehcode", false,
> +                            Phi->getIncomingBlock(*U));
> +        else
> +          LI = new LoadInst(SEHExceptionCodeSlot, "sehcode", false, I);
> +        U->set(LI);
> +      }
> +      E->replaceAllUsesWith(UndefValue::get(E->getType()));
> +      E->eraseFromParent();
> +    }
> +
>     // Add a call to describe the actions for this landing pad.
>     std::vector<Value *> ActionArgs;
>     for (ActionHandler *Action : Actions) {
> @@ -820,6 +854,13 @@ bool WinEHPrepare::prepareExceptionHandl
>   Builder.SetInsertPoint(&F.getEntryBlock().back());
>   Builder.CreateCall(FrameEscapeFn, AllocasToEscape);
> 
> +  if (SEHExceptionCodeSlot) {
> +    if (SEHExceptionCodeSlot->hasNUses(0))
> +      SEHExceptionCodeSlot->eraseFromParent();
> +    else
> +      PromoteMemToReg(SEHExceptionCodeSlot, *DT);
> +  }
> +
>   // Clean up the handler action maps we created for this function
>   DeleteContainerSeconds(CatchHandlerMap);
>   CatchHandlerMap.clear();
> @@ -1193,6 +1234,7 @@ bool WinEHPrepare::outlineHandler(Action
> /// target.
> void WinEHPrepare::processSEHCatchHandler(CatchHandler *CatchAction,
>                                           BasicBlock *StartBB) {
> +  LLVMContext &Context = StartBB->getContext();
>   BasicBlock *HandlerBB;
>   BasicBlock *NextBB;
>   Constant *Selector;
> @@ -1210,6 +1252,12 @@ void WinEHPrepare::processSEHCatchHandle
>     HandlerBB =
>         StartBB->splitBasicBlock(StartBB->getFirstInsertionPt(), "catch.all");
>   }
> +  IRBuilder<> Builder(HandlerBB->getFirstInsertionPt());
> +  Function *EHCodeFn = Intrinsic::getDeclaration(
> +      StartBB->getParent()->getParent(), Intrinsic::eh_exceptioncode);
> +  Value *Code = Builder.CreateCall(EHCodeFn, "sehcode");
> +  Code = Builder.CreateIntToPtr(Code, SEHExceptionCodeSlot->getAllocatedType());
> +  Builder.CreateStore(Code, SEHExceptionCodeSlot);
>   CatchAction->setHandlerBlockOrFunc(BlockAddress::get(HandlerBB));
>   TinyPtrVector<BasicBlock *> Targets(HandlerBB);
>   CatchAction->setReturnTargets(Targets);
> 
> Modified: llvm/trunk/test/CodeGen/WinEH/seh-resume-phi.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/seh-resume-phi.ll?rev=235768&r1=235767&r2=235768&view=diff
> ==============================================================================
> --- llvm/trunk/test/CodeGen/WinEH/seh-resume-phi.ll (original)
> +++ llvm/trunk/test/CodeGen/WinEH/seh-resume-phi.ll Fri Apr 24 15:25:05 2015
> @@ -55,9 +55,8 @@ eh.resume:
> ; CHECK-NEXT: indirectbr {{.*}} [label %__except]
> ;
> ; CHECK: __except:
> -;      FIXME: This should not be undef, it should be the new landingpad value, which
> -;      should ultimately lower down to eax.
> -; CHECK: invoke void @might_crash(i8* undef)
> +; CHECK: call i32 @llvm.eh.exceptioncode()
> +; CHECK: invoke void @might_crash(i8* %{{.*}})
> ; CHECK: landingpad { i8*, i32 }
> ; CHECK-NEXT: cleanup
> ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void (i8*, i8*)* @resume_phi.cleanup)
> 
> Modified: llvm/trunk/test/CodeGen/X86/seh-catch-all.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/seh-catch-all.ll?rev=235768&r1=235767&r2=235768&view=diff
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/seh-catch-all.ll (original)
> +++ llvm/trunk/test/CodeGen/X86/seh-catch-all.ll Fri Apr 24 15:25:05 2015
> @@ -1,10 +1,10 @@
> ; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s
> 
> - at str = internal unnamed_addr constant [10 x i8] c"recovered\00", align 1
> + at str = linkonce_odr unnamed_addr constant [27 x i8] c"GetExceptionCode(): 0x%lx\0A\00", align 1
> 
> declare i32 @__C_specific_handler(...)
> declare void @crash()
> -declare i32 @puts(i8*)
> +declare i32 @printf(i8* nocapture readonly, ...) nounwind
> 
> define i32 @main() {
> entry:
> @@ -14,7 +14,10 @@ entry:
> lpad:
>   %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
>           catch i8* null
> -  call i32 @puts(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @str, i64 0, i64 0))
> +  %1 = extractvalue { i8*, i32 } %0, 0
> +  %2 = ptrtoint i8* %1 to i64
> +  %3 = trunc i64 %2 to i32
> +  call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i64 0, i64 0), i32 %3)
>   br label %__try.cont
> 
> __try.cont:
> @@ -24,7 +27,15 @@ eh.resume:
>   resume { i8*, i32 } %0
> }
> 
> +; Check that we can get the exception code from eax to the printf.
> +
> ; CHECK-LABEL: main:
> +; CHECK: retq
> +; CHECK: # Block address taken
> +; CHECK: leaq str(%rip), %rcx
> +; CHECK: movl %eax, %edx
> +; CHECK: callq printf
> +
> ; CHECK: .seh_handlerdata
> ; CHECK-NEXT: .long 1
> ; CHECK-NEXT: .Ltmp{{[0-9]+}}@IMGREL
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits





More information about the llvm-commits mailing list