From e6797b7d75a4d037e24e94326b2c69e99edafc90 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Wed, 9 Nov 2016 22:39:54 +0000 Subject: [PATCH] GlobalISel: translate invoke and landingpad instructions Pretty bare-bones support for exception handling (no weird MSVC stuff, no SjLj etc), but it should get things going. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286407 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../llvm/CodeGen/GlobalISel/IRTranslator.h | 6 +- lib/CodeGen/GlobalISel/IRTranslator.cpp | 117 +++++++++++++++++- .../AArch64/AArch64InstructionSelector.cpp | 2 +- .../GlobalISel/irtranslator-exceptions.ll | 44 +++++++ 4 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 test/CodeGen/AArch64/GlobalISel/irtranslator-exceptions.ll diff --git a/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/include/llvm/CodeGen/GlobalISel/IRTranslator.h index af7413205e2..ba85b8ec303 100644 --- a/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -132,6 +132,10 @@ private: /// \pre \p U is a call instruction. bool translateCall(const User &U); + bool translateInvoke(const User &U); + + bool translateLandingPad(const User &U); + /// Translate one of LLVM's cast instructions into MachineInstrs, with the /// given generic Opcode. bool translateCast(unsigned Opcode, const User &U); @@ -287,7 +291,6 @@ private: // translation. bool translateSwitch(const User &U) { return false; } bool translateIndirectBr(const User &U) { return false; } - bool translateInvoke(const User &U) { return false; } bool translateResume(const User &U) { return false; } bool translateCleanupRet(const User &U) { return false; } bool translateCatchRet(const User &U) { return false; } @@ -304,7 +307,6 @@ private: bool translateExtractElement(const User &U) { return false; } bool translateInsertElement(const User &U) { return false; } bool translateShuffleVector(const User &U) { return false; } - bool translateLandingPad(const User &U) { return false; } /// @} diff --git a/lib/CodeGen/GlobalISel/IRTranslator.cpp b/lib/CodeGen/GlobalISel/IRTranslator.cpp index 79cce6a6f96..24707c53565 100644 --- a/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -14,8 +14,11 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/GlobalISel/CallLowering.h" +#include "llvm/CodeGen/Analysis.h" +#include "llvm/CodeGen/FunctionLoweringInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/Constant.h" @@ -443,6 +446,13 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, case Intrinsic::smul_with_overflow: Op = TargetOpcode::G_SMULO; break; case Intrinsic::memcpy: return translateMemcpy(CI); + case Intrinsic::eh_typeid_for: { + GlobalValue *GV = ExtractTypeInfo(CI.getArgOperand(0)); + unsigned Reg = getOrCreateVReg(CI); + unsigned TypeID = MIRBuilder.getMF().getMMI().getTypeIDFor(GV); + MIRBuilder.buildConstant(Reg, TypeID); + return true; + } case Intrinsic::objectsize: { // If we don't know by now, we're never going to know. const ConstantInt *Min = cast(CI.getArgOperand(1)); @@ -529,6 +539,111 @@ bool IRTranslator::translateCall(const User &U) { return true; } +bool IRTranslator::translateInvoke(const User &U) { + const InvokeInst &I = cast(U); + MachineFunction &MF = MIRBuilder.getMF(); + MachineModuleInfo &MMI = MF.getMMI(); + + const BasicBlock *ReturnBB = I.getSuccessor(0); + const BasicBlock *EHPadBB = I.getSuccessor(1); + + const Value *Callee(I.getCalledValue()); + const Function *Fn = dyn_cast(Callee); + if (isa(Callee)) + return false; + + // FIXME: support invoking patchpoint and statepoint intrinsics. + if (Fn && Fn->isIntrinsic()) + return false; + + // FIXME: support whatever these are. + if (I.countOperandBundlesOfType(LLVMContext::OB_deopt)) + return false; + + // FIXME: support Windows exception handling. + if (!isa(EHPadBB->front())) + return false; + + + // Emit the actual call, bracketed by EH_LABELs so that the MMI knows about + // the region covered by the try. + MCSymbol *BeginSymbol = MMI.getContext().createTempSymbol(); + MIRBuilder.buildInstr(TargetOpcode::EH_LABEL).addSym(BeginSymbol); + + unsigned Res = I.getType()->isVoidTy() ? 0 : getOrCreateVReg(I); + SmallVector Args; + for (auto &Arg: I.arg_operands()) + Args.emplace_back(getOrCreateVReg(*Arg), Arg->getType()); + + if (!CLI->lowerCall(MIRBuilder, MachineOperand::CreateGA(Fn, 0), + CallLowering::ArgInfo(Res, I.getType()), Args)) + return false; + + MCSymbol *EndSymbol = MMI.getContext().createTempSymbol(); + MIRBuilder.buildInstr(TargetOpcode::EH_LABEL).addSym(EndSymbol); + + // FIXME: track probabilities. + MachineBasicBlock &EHPadMBB = getOrCreateBB(*EHPadBB), + &ReturnMBB = getOrCreateBB(*ReturnBB); + MMI.addInvoke(&EHPadMBB, BeginSymbol, EndSymbol); + MIRBuilder.getMBB().addSuccessor(&ReturnMBB); + MIRBuilder.getMBB().addSuccessor(&EHPadMBB); + + return true; +} + +bool IRTranslator::translateLandingPad(const User &U) { + const LandingPadInst &LP = cast(U); + + MachineBasicBlock &MBB = MIRBuilder.getMBB(); + MachineFunction &MF = MIRBuilder.getMF(); + MachineModuleInfo &MMI = MF.getMMI(); + AddLandingPadInfo(LP, MMI, &MBB); + + MBB.setIsEHPad(); + + // If there aren't registers to copy the values into (e.g., during SjLj + // exceptions), then don't bother. + auto &TLI = *MF.getSubtarget().getTargetLowering(); + const Constant *PersonalityFn = MF.getFunction()->getPersonalityFn(); + if (TLI.getExceptionPointerRegister(PersonalityFn) == 0 && + TLI.getExceptionSelectorRegister(PersonalityFn) == 0) + return true; + + // If landingpad's return type is token type, we don't create DAG nodes + // for its exception pointer and selector value. The extraction of exception + // pointer or selector value from token type landingpads is not currently + // supported. + if (LP.getType()->isTokenTy()) + return true; + + // Add a label to mark the beginning of the landing pad. Deletion of the + // landing pad can thus be detected via the MachineModuleInfo. + MIRBuilder.buildInstr(TargetOpcode::EH_LABEL) + .addSym(MMI.addLandingPad(&MBB)); + + // Mark exception register as live in. + SmallVector Regs; + SmallVector Offsets; + LLT p0 = LLT::pointer(0, DL->getPointerSizeInBits()); + if (unsigned Reg = TLI.getExceptionPointerRegister(PersonalityFn)) { + unsigned VReg = MRI->createGenericVirtualRegister(p0); + MIRBuilder.buildCopy(VReg, Reg); + Regs.push_back(VReg); + Offsets.push_back(0); + } + + if (unsigned Reg = TLI.getExceptionSelectorRegister(PersonalityFn)) { + unsigned VReg = MRI->createGenericVirtualRegister(p0); + MIRBuilder.buildCopy(VReg, Reg); + Regs.push_back(VReg); + Offsets.push_back(p0.getSizeInBits()); + } + + MIRBuilder.buildSequence(getOrCreateVReg(LP), Regs, Offsets); + return true; +} + bool IRTranslator::translateStaticAlloca(const AllocaInst &AI) { if (!TPC->isGlobalISelAbortEnabled() && !AI.isStaticAlloca()) return false; @@ -613,7 +728,6 @@ bool IRTranslator::translate(const Constant &C, unsigned Reg) { return true; } - void IRTranslator::finalizeFunction() { finishPendingPhis(); @@ -665,6 +779,7 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &MF) { // Set the insertion point of all the following translations to // the end of this basic block. MIRBuilder.setMBB(MBB); + for (const Instruction &Inst: BB) { bool Succeeded = translate(Inst); if (!Succeeded) { diff --git a/lib/Target/AArch64/AArch64InstructionSelector.cpp b/lib/Target/AArch64/AArch64InstructionSelector.cpp index ac8323ac624..b156fcd49e8 100644 --- a/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -915,7 +915,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const { .addUse(SrcXReg) .addImm(0) .addImm(SrcTy.getSizeInBits() - 1); - } else if (DstTy == LLT::scalar(32)) { + } else if (DstTy.isScalar() && DstTy.getSizeInBits() <= 32) { const unsigned NewOpc = isSigned ? AArch64::SBFMWri : AArch64::UBFMWri; ExtI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc)) .addDef(DefReg) diff --git a/test/CodeGen/AArch64/GlobalISel/irtranslator-exceptions.ll b/test/CodeGen/AArch64/GlobalISel/irtranslator-exceptions.ll new file mode 100644 index 00000000000..47a085e9845 --- /dev/null +++ b/test/CodeGen/AArch64/GlobalISel/irtranslator-exceptions.ll @@ -0,0 +1,44 @@ +; RUN: llc -O0 -mtriple=aarch64-apple-ios -global-isel -stop-after=irtranslator %s -o - | FileCheck %s + +@_ZTIi = external global i8* + +declare i32 @foo(i32) +declare i32 @__gxx_personality_v0(...) +declare i32 @llvm.eh.typeid.for(i8*) + +; CHECK: name: bar +; CHECK: body: +; CHECK: bb.0: +; CHECK: successors: %bb.2{{.*}}%bb.1 +; CHECK: EH_LABEL +; CHECK: %w0 = COPY +; CHECK: BL @foo, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %w0, implicit-def %w0 +; CHECK: {{%[0-9]+}}(s32) = COPY %w0 +; CHECK: EH_LABEL + +; CHECK: bb.1 +; CHECK: EH_LABEL +; CHECK: [[PTR:%[0-9]+]](p0) = COPY %x0 +; CHECK: [[SEL:%[0-9]+]](p0) = COPY %x1 +; CHECK: [[PTR_SEL:%[0-9]+]](s128) = G_SEQUENCE [[PTR]](p0), 0, [[SEL]](p0), 64 +; CHECK: [[PTR_RET:%[0-9]+]](s64), [[SEL_RET:%[0-9]+]](s32) = G_EXTRACT [[PTR_SEL]](s128), 0, 64 +; CHECK: %x0 = COPY [[PTR_RET]] +; CHECK: %w1 = COPY [[SEL_RET]] + +; CHECK: bb.2: +; CHECK: [[SEL:%[0-9]+]](s32) = G_CONSTANT 1 +; CHECK: {{%[0-9]+}}(s128) = G_INSERT {{%[0-9]+}}(s128), [[SEL]](s32), 64 + +define { i8*, i32 } @bar() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { + %res32 = invoke i32 @foo(i32 42) to label %continue unwind label %broken + + +broken: + %ptr.sel = landingpad { i8*, i32 } catch i8* bitcast(i8** @_ZTIi to i8*) + ret { i8*, i32 } %ptr.sel + +continue: + %sel.int = tail call i32 @llvm.eh.typeid.for(i8* bitcast(i8** @_ZTIi to i8*)) + %res.good = insertvalue { i8*, i32 } undef, i32 %sel.int, 1 + ret { i8*, i32 } %res.good +} -- 2.40.0