llvm.org GIT mirror llvm / 39789f8
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235768 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 5 years ago
8 changed file(s) with 114 addition(s) and 39 deletion(s). Raw diff Collapse all Expand all
220220 int getArgumentFrameIndex(const Argument *A);
221221
222222 private:
223 void addSEHHandlersForLPads();
223 void addSEHHandlersForLPads(ArrayRef LPads);
224224
225225 /// LiveOutRegInfo - Information about live out vregs.
226226 IndexedMap LiveOutRegInfo;
420420 // Represents the list of actions to take when an exception is thrown.
421421 def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>;
422422
423 def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], []>;
424
423425 // __builtin_unwind_init is an undocumented GCC intrinsic that causes all
424426 // callee-saved registers to be saved and restored (regardless of whether they
425427 // are used) in the calling function. It is used by libgcc_eh.
270270 }
271271
272272 // Mark landing pad blocks.
273 const LandingPadInst *LP = nullptr;
273 SmallVector LPads;
274274 for (BB = Fn->begin(); BB != EB; ++BB) {
275275 if (const auto *Invoke = dyn_cast(BB->getTerminator()))
276276 MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad();
277277 if (BB->isLandingPad())
278 LP = BB->getLandingPadInst();
279 }
280
281 // Calculate EH numbers for MSVC C++ EH and save SEH handlers if necessary.
278 LPads.push_back(BB->getLandingPadInst());
279 }
280
281 // If this is an MSVC EH personality, we need to do a bit more work.
282282 EHPersonality Personality = EHPersonality::Unknown;
283 if (LP)
284 Personality = classifyEHPersonality(LP->getPersonalityFn());
283 if (!LPads.empty())
284 Personality = classifyEHPersonality(LPads.back()->getPersonalityFn());
285 if (!isMSVCEHPersonality(Personality))
286 return;
287
288 WinEHFuncInfo *EHInfo = nullptr;
285289 if (Personality == EHPersonality::MSVC_Win64SEH) {
286 addSEHHandlersForLPads();
290 addSEHHandlersForLPads(LPads);
287291 } else if (Personality == EHPersonality::MSVC_CXX) {
288292 const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
289 WinEHFuncInfo &FI = MMI.getWinEHFuncInfo(WinEHParentFn);
290 if (FI.LandingPadStateMap.empty()) {
291 WinEHNumbering Num(FI);
293 EHInfo = &MMI.getWinEHFuncInfo(WinEHParentFn);
294 if (EHInfo->LandingPadStateMap.empty()) {
295 WinEHNumbering Num(*EHInfo);
292296 Num.calculateStateNumbers(*WinEHParentFn);
293297 // Pop everything on the handler stack.
294298 Num.processCallSite(None, ImmutableCallSite());
295299 }
296 }
297 }
298
299 void FunctionLoweringInfo::addSEHHandlersForLPads() {
300
301 // Copy the state numbers to LandingPadInfo for the current function, which
302 // could be a handler or the parent.
303 for (const LandingPadInst *LP : LPads) {
304 MachineBasicBlock *LPadMBB = MBBMap[LP->getParent()];
305 MMI.addWinEHState(LPadMBB, EHInfo->LandingPadStateMap[LP]);
306 }
307 }
308 }
309
310 void FunctionLoweringInfo::addSEHHandlersForLPads(
311 ArrayRef LPads) {
300312 MachineModuleInfo &MMI = MF->getMMI();
301313
302314 // Iterate over all landing pads with llvm.eh.actions calls.
303 for (const BasicBlock &BB : *Fn) {
304 const LandingPadInst *LP = BB.getLandingPadInst();
305 if (!LP)
306 continue;
315 for (const LandingPadInst *LP : LPads) {
307316 const IntrinsicInst *ActionsCall =
308317 dyn_cast(LP->getNextNode());
309318 if (!ActionsCall ||
48164816 case Intrinsic::eh_begincatch:
48174817 case Intrinsic::eh_endcatch:
48184818 llvm_unreachable("begin/end catch intrinsics not lowered in codegen");
4819 case Intrinsic::eh_exceptioncode: {
4820 unsigned Reg = TLI.getExceptionPointerRegister();
4821 assert(Reg && "cannot get exception code on this platform");
4822 MVT PtrVT = TLI.getPointerTy();
4823 const TargetRegisterClass *PtrRC = TLI.getRegClassFor(PtrVT);
4824 unsigned VReg = FuncInfo.MBB->addLiveIn(Reg, PtrRC);
4825 SDValue N =
4826 DAG.getCopyFromReg(DAG.getEntryNode(), getCurSDLoc(), VReg, PtrVT);
4827 N = DAG.getZExtOrTrunc(N, getCurSDLoc(), MVT::i32);
4828 setValue(&I, N);
4829 return nullptr;
4830 }
48194831 }
48204832 }
48214833
959959 // Remove the edge from the invoke to the lpad.
960960 for (MachineBasicBlock *InvokeBB : InvokeBBs)
961961 InvokeBB->removeSuccessor(MBB);
962
963 // Transfer EH state number assigned to the IR block to the MBB.
964 if (Personality == EHPersonality::MSVC_CXX) {
965 WinEHFuncInfo &FI = MF->getMMI().getWinEHFuncInfo(MF->getFunction());
966 MF->getMMI().addWinEHState(MBB, FI.LandingPadStateMap[LPadInst]);
967 }
968962
969963 // Don't select instructions for the landingpad.
970964 return false;
7070 public:
7171 static char ID; // Pass identification, replacement for typeid.
7272 WinEHPrepare(const TargetMachine *TM = nullptr)
73 : FunctionPass(ID), DT(nullptr) {}
73 : FunctionPass(ID), DT(nullptr), SEHExceptionCodeSlot(nullptr) {}
7474
7575 bool runOnFunction(Function &Fn) override;
7676
132132 // outlined into a handler. This is done after all handlers have been
133133 // outlined but before the outlined code is pruned from the parent function.
134134 DenseMap LPadTargetBlocks;
135
136 AllocaInst *SEHExceptionCodeSlot;
135137 };
136138
137139 class WinEHFrameVariableMaterializer : public ValueMaterializer {
627629 Type *Int32Type = Type::getInt32Ty(Context);
628630 Function *ActionIntrin = Intrinsic::getDeclaration(M, Intrinsic::eh_actions);
629631
632 if (isAsynchronousEHPersonality(Personality)) {
633 // FIXME: Switch the ehptr type to i32 and then switch this.
634 SEHExceptionCodeSlot =
635 new AllocaInst(Int8PtrType, nullptr, "seh_exception_code",
636 F.getEntryBlock().getFirstInsertionPt());
637 }
638
630639 for (LandingPadInst *LPad : LPads) {
631640 // Look for evidence that this landingpad has already been processed.
632641 bool LPadHasActionList = false;
679688
680689 // Replace all extracted values with undef and ultimately replace the
681690 // landingpad with undef.
682 // FIXME: This doesn't handle SEH GetExceptionCode(). For now, we just give
683 // out undef until we figure out the codegen support.
684 SmallVector Extracts;
691 SmallVector SEHCodeUses;
692 SmallVector EHUndefs;
685693 for (User *U : LPad->users()) {
686694 auto *E = dyn_cast(U);
687695 if (!E)
688696 continue;
689697 assert(E->getNumIndices() == 1 &&
690698 "Unexpected operation: extracting both landing pad values");
691 Extracts.push_back(E);
692 }
693 for (Instruction *E : Extracts) {
699 unsigned Idx = *E->idx_begin();
700 assert((Idx == 0 || Idx == 1) && "unexpected index");
701 if (Idx == 0 && isAsynchronousEHPersonality(Personality))
702 SEHCodeUses.push_back(E);
703 else
704 EHUndefs.push_back(E);
705 }
706 for (Instruction *E : EHUndefs) {
694707 E->replaceAllUsesWith(UndefValue::get(E->getType()));
695708 E->eraseFromParent();
696709 }
697710 LPad->replaceAllUsesWith(UndefValue::get(LPad->getType()));
711
712 // Rewrite uses of the exception pointer to loads of an alloca.
713 for (Instruction *E : SEHCodeUses) {
714 SmallVector Uses;
715 for (Use &U : E->uses())
716 Uses.push_back(&U);
717 for (Use *U : Uses) {
718 auto *I = cast(U->getUser());
719 if (isa(I))
720 continue;
721 LoadInst *LI;
722 if (auto *Phi = dyn_cast(I))
723 LI = new LoadInst(SEHExceptionCodeSlot, "sehcode", false,
724 Phi->getIncomingBlock(*U));
725 else
726 LI = new LoadInst(SEHExceptionCodeSlot, "sehcode", false, I);
727 U->set(LI);
728 }
729 E->replaceAllUsesWith(UndefValue::get(E->getType()));
730 E->eraseFromParent();
731 }
698732
699733 // Add a call to describe the actions for this landing pad.
700734 std::vector ActionArgs;
818852 // block.
819853 Builder.SetInsertPoint(&F.getEntryBlock().back());
820854 Builder.CreateCall(FrameEscapeFn, AllocasToEscape);
855
856 if (SEHExceptionCodeSlot) {
857 if (SEHExceptionCodeSlot->hasNUses(0))
858 SEHExceptionCodeSlot->eraseFromParent();
859 else
860 PromoteMemToReg(SEHExceptionCodeSlot, *DT);
861 }
821862
822863 // Clean up the handler action maps we created for this function
823864 DeleteContainerSeconds(CatchHandlerMap);
11921233 /// target.
11931234 void WinEHPrepare::processSEHCatchHandler(CatchHandler *CatchAction,
11941235 BasicBlock *StartBB) {
1236 LLVMContext &Context = StartBB->getContext();
11951237 BasicBlock *HandlerBB;
11961238 BasicBlock *NextBB;
11971239 Constant *Selector;
12091251 HandlerBB =
12101252 StartBB->splitBasicBlock(StartBB->getFirstInsertionPt(), "catch.all");
12111253 }
1254 IRBuilder<> Builder(HandlerBB->getFirstInsertionPt());
1255 Function *EHCodeFn = Intrinsic::getDeclaration(
1256 StartBB->getParent()->getParent(), Intrinsic::eh_exceptioncode);
1257 Value *Code = Builder.CreateCall(EHCodeFn, "sehcode");
1258 Code = Builder.CreateIntToPtr(Code, SEHExceptionCodeSlot->getAllocatedType());
1259 Builder.CreateStore(Code, SEHExceptionCodeSlot);
12121260 CatchAction->setHandlerBlockOrFunc(BlockAddress::get(HandlerBB));
12131261 TinyPtrVector Targets(HandlerBB);
12141262 CatchAction->setReturnTargets(Targets);
5454 ; CHECK-NEXT: indirectbr {{.*}} [label %__except]
5555 ;
5656 ; CHECK: __except:
57 ; FIXME: This should not be undef, it should be the new landingpad value, which
58 ; should ultimately lower down to eax.
59 ; CHECK: invoke void @might_crash(i8* undef)
57 ; CHECK: call i32 @llvm.eh.exceptioncode()
58 ; CHECK: invoke void @might_crash(i8* %{{.*}})
6059 ; CHECK: landingpad { i8*, i32 }
6160 ; CHECK-NEXT: cleanup
6261 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void (i8*, i8*)* @resume_phi.cleanup)
0 ; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s
11
2 @str = internal unnamed_addr constant [10 x i8] c"recovered\00", align 1
2 @str = linkonce_odr unnamed_addr constant [27 x i8] c"GetExceptionCode(): 0x%lx\0A\00", align 1
33
44 declare i32 @__C_specific_handler(...)
55 declare void @crash()
6 declare i32 @puts(i8*)
6 declare i32 @printf(i8* nocapture readonly, ...) nounwind
77
88 define i32 @main() {
99 entry:
1313 lpad:
1414 %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
1515 catch i8* null
16 call i32 @puts(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @str, i64 0, i64 0))
16 %1 = extractvalue { i8*, i32 } %0, 0
17 %2 = ptrtoint i8* %1 to i64
18 %3 = trunc i64 %2 to i32
19 call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i64 0, i64 0), i32 %3)
1720 br label %__try.cont
1821
1922 __try.cont:
2326 resume { i8*, i32 } %0
2427 }
2528
29 ; Check that we can get the exception code from eax to the printf.
30
2631 ; CHECK-LABEL: main:
32 ; CHECK: retq
33 ; CHECK: # Block address taken
34 ; CHECK: leaq str(%rip), %rcx
35 ; CHECK: movl %eax, %edx
36 ; CHECK: callq printf
37
2738 ; CHECK: .seh_handlerdata
2839 ; CHECK-NEXT: .long 1
2940 ; CHECK-NEXT: .Ltmp{{[0-9]+}}@IMGREL