diff --git a/llvm/lib/Target/VE/VEISelLowering.h b/llvm/lib/Target/VE/VEISelLowering.h --- a/llvm/lib/Target/VE/VEISelLowering.h +++ b/llvm/lib/Target/VE/VEISelLowering.h @@ -115,6 +115,7 @@ SDValue lowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const; SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const; diff --git a/llvm/lib/Target/VE/VEISelLowering.cpp b/llvm/lib/Target/VE/VEISelLowering.cpp --- a/llvm/lib/Target/VE/VEISelLowering.cpp +++ b/llvm/lib/Target/VE/VEISelLowering.cpp @@ -275,6 +275,9 @@ } /// } Atomic isntructions + + // Intrinsic instructions + setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); } void VETargetLowering::initVPUActions() { @@ -1525,6 +1528,37 @@ MachinePointerInfo()); } +SDValue VETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + unsigned IntNo = cast(Op.getOperand(0))->getZExtValue(); + switch (IntNo) { + default: // Don't custom lower most intrinsics. + return SDValue(); + case Intrinsic::eh_sjlj_lsda: { + MachineFunction &MF = DAG.getMachineFunction(); + MVT VT = Op.getSimpleValueType(); + const VETargetMachine *TM = + static_cast(&DAG.getTarget()); + + // Create GCC_except_tableXX string. The real symbol for that will be + // generated in EHStreamer::emitExceptionTable() later. So, we just + // borrow it's name here. + TM->getStrList()->push_back(std::string( + (Twine("GCC_except_table") + Twine(MF.getFunctionNumber())).str())); + SDValue Addr = + DAG.getTargetExternalSymbol(TM->getStrList()->back().c_str(), VT, 0); + if (isPositionIndependent()) { + Addr = makeHiLoPair(Addr, VEMCExpr::VK_VE_GOTOFF_HI32, + VEMCExpr::VK_VE_GOTOFF_LO32, DAG); + SDValue GlobalBase = DAG.getNode(VEISD::GLOBAL_BASE_REG, DL, VT); + return DAG.getNode(ISD::ADD, DL, VT, GlobalBase, Addr); + } + return makeHiLoPair(Addr, VEMCExpr::VK_VE_HI32, VEMCExpr::VK_VE_LO32, DAG); + } + } +} + static SDValue getSplatValue(SDNode *N) { if (auto *BuildVec = dyn_cast(N)) { return BuildVec->getSplatValue(); @@ -1571,6 +1605,8 @@ return lowerGlobalAddress(Op, DAG); case ISD::GlobalTLSAddress: return lowerGlobalTLSAddress(Op, DAG); + case ISD::INTRINSIC_WO_CHAIN: + return lowerINTRINSIC_WO_CHAIN(Op, DAG); case ISD::JumpTable: return lowerJumpTable(Op, DAG); case ISD::LOAD: diff --git a/llvm/test/CodeGen/VE/Scalar/builtin_sjlj_lsda.ll b/llvm/test/CodeGen/VE/Scalar/builtin_sjlj_lsda.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/VE/Scalar/builtin_sjlj_lsda.ll @@ -0,0 +1,16 @@ +; RUN: llc < %s -mtriple=ve -exception-model sjlj | FileCheck %s + +; Function Attrs: noinline nounwind optnone +define i8* @test_lsda() { +; CHECK-LABEL: test_lsda: +; CHECK: # %bb.0: +; CHECK-NEXT: lea %s0, GCC_except_table0@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s0, GCC_except_table0@hi(, %s0) +; CHECK-NEXT: b.l.t (, %s10) + %ret = call i8* @llvm.eh.sjlj.lsda() + ret i8* %ret +} + +; Function Attrs: nounwind +declare i8* @llvm.eh.sjlj.lsda()