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 @@ -24,19 +24,22 @@ enum NodeType : unsigned { FIRST_NUMBER = ISD::BUILTIN_OP_END, - CALL, // A call instruction. - GETFUNPLT, // Load function address through %plt insturction. - GETTLSADDR, // Load address for TLS access. - GETSTACKTOP, // Retrieve address of stack top (first address of - // locals and temporaries). - GLOBAL_BASE_REG, // Global base reg for PIC. - Hi, // Hi/Lo operations, typically on a global address. - Lo, // Hi/Lo operations, typically on a global address. - MEMBARRIER, // Compiler barrier only; generate a no-op. - RET_FLAG, // Return with a flag operand. - TS1AM, // A TS1AM instruction used for 1/2 bytes swap. - VEC_BROADCAST, // A vector broadcast instruction. - // 0: scalar value, 1: VL + CALL, // A call instruction. + EH_SJLJ_LONGJMP, // SjLj exception handling longjmp. + EH_SJLJ_SETJMP, // SjLj exception handling setjmp. + EH_SJLJ_SETUP_DISPATCH, // SjLj exception handling setup_dispatch. + GETFUNPLT, // Load function address through %plt insturction. + GETTLSADDR, // Load address for TLS access. + GETSTACKTOP, // Retrieve address of stack top (first address of + // locals and temporaries). + GLOBAL_BASE_REG, // Global base reg for PIC. + Hi, // Hi/Lo operations, typically on a global address. + Lo, // Hi/Lo operations, typically on a global address. + MEMBARRIER, // Compiler barrier only; generate a no-op. + RET_FLAG, // Return with a flag operand. + TS1AM, // A TS1AM instruction used for 1/2 bytes swap. + VEC_BROADCAST, // A vector broadcast instruction. + // 0: scalar value, 1: VL // VVP_* nodes. #define ADD_VVP_OP(VVP_NAME, ...) VVP_NAME, @@ -113,6 +116,9 @@ SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const; SDValue lowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerEH_SJLJ_SETUP_DISPATCH(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; @@ -132,6 +138,29 @@ void ReplaceNodeResults(SDNode *N, SmallVectorImpl &Results, SelectionDAG &DAG) const override; + /// Custom Inserter { + MachineBasicBlock * + EmitInstrWithCustomInserter(MachineInstr &MI, + MachineBasicBlock *MBB) const override; + MachineBasicBlock *emitEHSjLjLongJmp(MachineInstr &MI, + MachineBasicBlock *MBB) const; + MachineBasicBlock *emitEHSjLjSetJmp(MachineInstr &MI, + MachineBasicBlock *MBB) const; + MachineBasicBlock *emitSjLjDispatchBlock(MachineInstr &MI, + MachineBasicBlock *BB) const; + + void setupEntryBlockForSjLj(MachineInstr &MI, MachineBasicBlock *MBB, + MachineBasicBlock *DispatchBB, int FI, + int Offset) const; + // Setup basic block address in a given label regiseter. + Register prepareMBB(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + MachineBasicBlock *TargetBB, const DebugLoc &DL) const; + // Prepare function/variable address in a given label regiseter. + Register prepareSymbol(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + StringRef Symbol, const DebugLoc &DL, bool IsLocal, + bool IsCall) const; + /// } Custom Inserter + /// VVP Lowering { SDValue lowerToVVP(SDValue Op, SelectionDAG &DAG) const; /// } VVPLowering 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 @@ -13,6 +13,7 @@ #include "VEISelLowering.h" #include "MCTargetDesc/VEMCExpr.h" +#include "VEInstrBuilder.h" #include "VEMachineFunctionInfo.h" #include "VERegisterInfo.h" #include "VETargetMachine.h" @@ -276,6 +277,14 @@ /// } Atomic instructions + /// SJLJ instructions { + setOperationAction(ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom); + setOperationAction(ISD::EH_SJLJ_SETJMP, MVT::i32, Custom); + setOperationAction(ISD::EH_SJLJ_SETUP_DISPATCH, MVT::Other, Custom); + if (TM.Options.ExceptionModel == ExceptionHandling::SjLj) + setLibcallName(RTLIB::UNWIND_RESUME, "_Unwind_SjLj_Resume"); + /// } SJLJ instructions + // Intrinsic instructions setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); } @@ -864,6 +873,9 @@ case VEISD::FIRST_NUMBER: break; TARGET_NODE_CASE(CALL) + TARGET_NODE_CASE(EH_SJLJ_LONGJMP) + TARGET_NODE_CASE(EH_SJLJ_SETJMP) + TARGET_NODE_CASE(EH_SJLJ_SETUP_DISPATCH) TARGET_NODE_CASE(GETFUNPLT) TARGET_NODE_CASE(GETSTACKTOP) TARGET_NODE_CASE(GETTLSADDR) @@ -1487,6 +1499,28 @@ return DAG.getMergeValues(Ops, DL); } +SDValue VETargetLowering::lowerEH_SJLJ_LONGJMP(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + return DAG.getNode(VEISD::EH_SJLJ_LONGJMP, DL, MVT::Other, Op.getOperand(0), + Op.getOperand(1)); +} + +SDValue VETargetLowering::lowerEH_SJLJ_SETJMP(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + return DAG.getNode(VEISD::EH_SJLJ_SETJMP, DL, + DAG.getVTList(MVT::i32, MVT::Other), Op.getOperand(0), + Op.getOperand(1)); +} + +SDValue VETargetLowering::lowerEH_SJLJ_SETUP_DISPATCH(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + return DAG.getNode(VEISD::EH_SJLJ_SETUP_DISPATCH, DL, MVT::Other, + Op.getOperand(0)); +} + static SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG, const VETargetLowering &TLI, const VESubtarget *Subtarget) { @@ -1599,6 +1633,12 @@ return lowerConstantPool(Op, DAG); case ISD::DYNAMIC_STACKALLOC: return lowerDYNAMIC_STACKALLOC(Op, DAG); + case ISD::EH_SJLJ_LONGJMP: + return lowerEH_SJLJ_LONGJMP(Op, DAG); + case ISD::EH_SJLJ_SETJMP: + return lowerEH_SJLJ_SETJMP(Op, DAG); + case ISD::EH_SJLJ_SETUP_DISPATCH: + return lowerEH_SJLJ_SETUP_DISPATCH(Op, DAG); case ISD::FRAMEADDR: return lowerFRAMEADDR(Op, DAG, *this, Subtarget); case ISD::GlobalAddress: @@ -1699,6 +1739,677 @@ return DAG.getNode(ISD::ADD, DL, PtrTy, GlobalBase, HiLo); } +Register VETargetLowering::prepareMBB(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + MachineBasicBlock *TargetBB, + const DebugLoc &DL) const { + MachineFunction *MF = MBB.getParent(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + const VEInstrInfo *TII = Subtarget->getInstrInfo(); + + const TargetRegisterClass *RC = &VE::I64RegClass; + Register Tmp1 = MRI.createVirtualRegister(RC); + Register Tmp2 = MRI.createVirtualRegister(RC); + Register Result = MRI.createVirtualRegister(RC); + + if (isPositionIndependent()) { + // Create following instructions for local linkage PIC code. + // lea %Tmp1, TargetBB@gotoff_lo + // and %Tmp2, %Tmp1, (32)0 + // lea.sl %Result, TargetBB@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT + BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1) + .addImm(0) + .addImm(0) + .addMBB(TargetBB, VEMCExpr::VK_VE_GOTOFF_LO32); + BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2) + .addReg(Tmp1, getKillRegState(true)) + .addImm(M0(32)); + BuildMI(MBB, I, DL, TII->get(VE::LEASLrri), Result) + .addReg(VE::SX15) + .addReg(Tmp2, getKillRegState(true)) + .addMBB(TargetBB, VEMCExpr::VK_VE_GOTOFF_HI32); + } else { + // Create following instructions for non-PIC code. + // lea %Tmp1, TargetBB@lo + // and %Tmp2, %Tmp1, (32)0 + // lea.sl %Result, TargetBB@hi(%Tmp2) + BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1) + .addImm(0) + .addImm(0) + .addMBB(TargetBB, VEMCExpr::VK_VE_LO32); + BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2) + .addReg(Tmp1, getKillRegState(true)) + .addImm(M0(32)); + BuildMI(MBB, I, DL, TII->get(VE::LEASLrii), Result) + .addReg(Tmp2, getKillRegState(true)) + .addImm(0) + .addMBB(TargetBB, VEMCExpr::VK_VE_HI32); + } + return Result; +} + +Register VETargetLowering::prepareSymbol(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + StringRef Symbol, const DebugLoc &DL, + bool IsLocal = false, + bool IsCall = false) const { + MachineFunction *MF = MBB.getParent(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + const VEInstrInfo *TII = Subtarget->getInstrInfo(); + + const TargetRegisterClass *RC = &VE::I64RegClass; + Register Result = MRI.createVirtualRegister(RC); + + if (isPositionIndependent()) { + if (IsCall && !IsLocal) { + // Create following instructions for non-local linkage PIC code function + // calls. These instructions uses IC and magic number -24, so we expand + // them in VEAsmPrinter.cpp from GETFUNPLT pseudo instruction. + // lea %Reg, Symbol@plt_lo(-24) + // and %Reg, %Reg, (32)0 + // sic %s16 + // lea.sl %Result, Symbol@plt_hi(%Reg, %s16) ; %s16 is PLT + BuildMI(MBB, I, DL, TII->get(VE::GETFUNPLT), Result) + .addExternalSymbol("abort"); + } else if (IsLocal) { + Register Tmp1 = MRI.createVirtualRegister(RC); + Register Tmp2 = MRI.createVirtualRegister(RC); + // Create following instructions for local linkage PIC code. + // lea %Tmp1, Symbol@gotoff_lo + // and %Tmp2, %Tmp1, (32)0 + // lea.sl %Result, Symbol@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT + BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1) + .addImm(0) + .addImm(0) + .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_GOTOFF_LO32); + BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2) + .addReg(Tmp1, getKillRegState(true)) + .addImm(M0(32)); + BuildMI(MBB, I, DL, TII->get(VE::LEASLrri), Result) + .addReg(VE::SX15) + .addReg(Tmp2, getKillRegState(true)) + .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_GOTOFF_HI32); + } else { + Register Tmp1 = MRI.createVirtualRegister(RC); + Register Tmp2 = MRI.createVirtualRegister(RC); + // Create following instructions for not local linkage PIC code. + // lea %Tmp1, Symbol@got_lo + // and %Tmp2, %Tmp1, (32)0 + // lea.sl %Tmp3, Symbol@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT + // ld %Result, 0(%Tmp3) + Register Tmp3 = MRI.createVirtualRegister(RC); + BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1) + .addImm(0) + .addImm(0) + .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_GOT_LO32); + BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2) + .addReg(Tmp1, getKillRegState(true)) + .addImm(M0(32)); + BuildMI(MBB, I, DL, TII->get(VE::LEASLrri), Tmp3) + .addReg(VE::SX15) + .addReg(Tmp2, getKillRegState(true)) + .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_GOT_HI32); + BuildMI(MBB, I, DL, TII->get(VE::LDrii), Result) + .addReg(Tmp3, getKillRegState(true)) + .addImm(0) + .addImm(0); + } + } else { + Register Tmp1 = MRI.createVirtualRegister(RC); + Register Tmp2 = MRI.createVirtualRegister(RC); + // Create following instructions for non-PIC code. + // lea %Tmp1, Symbol@lo + // and %Tmp2, %Tmp1, (32)0 + // lea.sl %Result, Symbol@hi(%Tmp2) + BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1) + .addImm(0) + .addImm(0) + .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_LO32); + BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2) + .addReg(Tmp1, getKillRegState(true)) + .addImm(M0(32)); + BuildMI(MBB, I, DL, TII->get(VE::LEASLrii), Result) + .addReg(Tmp2, getKillRegState(true)) + .addImm(0) + .addExternalSymbol(Symbol.data(), VEMCExpr::VK_VE_HI32); + } + return Result; +} + +void VETargetLowering::setupEntryBlockForSjLj(MachineInstr &MI, + MachineBasicBlock *MBB, + MachineBasicBlock *DispatchBB, + int FI, int Offset) const { + DebugLoc DL = MI.getDebugLoc(); + const VEInstrInfo *TII = Subtarget->getInstrInfo(); + + Register LabelReg = + prepareMBB(*MBB, MachineBasicBlock::iterator(MI), DispatchBB, DL); + + // Store an address of DispatchBB to a given jmpbuf[1] where has next IC + // referenced by longjmp (throw) later. + MachineInstrBuilder MIB = BuildMI(*MBB, MI, DL, TII->get(VE::STrii)); + addFrameReference(MIB, FI, Offset); // jmpbuf[1] + MIB.addReg(LabelReg, getKillRegState(true)); +} + +MachineBasicBlock * +VETargetLowering::emitEHSjLjSetJmp(MachineInstr &MI, + MachineBasicBlock *MBB) const { + DebugLoc DL = MI.getDebugLoc(); + MachineFunction *MF = MBB->getParent(); + const TargetInstrInfo *TII = Subtarget->getInstrInfo(); + const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + + const BasicBlock *BB = MBB->getBasicBlock(); + MachineFunction::iterator I = ++MBB->getIterator(); + + // Memory Reference. + SmallVector MMOs(MI.memoperands_begin(), + MI.memoperands_end()); + Register BufReg = MI.getOperand(1).getReg(); + + Register DstReg; + + DstReg = MI.getOperand(0).getReg(); + const TargetRegisterClass *RC = MRI.getRegClass(DstReg); + assert(TRI->isTypeLegalForClass(*RC, MVT::i32) && "Invalid destination!"); + (void)TRI; + Register MainDestReg = MRI.createVirtualRegister(RC); + Register RestoreDestReg = MRI.createVirtualRegister(RC); + + // For `v = call @llvm.eh.sjlj.setjmp(buf)`, we generate following + // instructions. SP/FP must be saved in jmpbuf before `llvm.eh.sjlj.setjmp`. + // + // ThisMBB: + // buf[3] = %s17 iff %s17 is used as BP + // buf[1] = RestoreMBB as IC after longjmp + // # SjLjSetup RestoreMBB + // + // MainMBB: + // v_main = 0 + // + // SinkMBB: + // v = phi(v_main, MainMBB, v_restore, RestoreMBB) + // ... + // + // RestoreMBB: + // %s17 = buf[3] = iff %s17 is used as BP + // v_restore = 1 + // goto SinkMBB + + MachineBasicBlock *ThisMBB = MBB; + MachineBasicBlock *MainMBB = MF->CreateMachineBasicBlock(BB); + MachineBasicBlock *SinkMBB = MF->CreateMachineBasicBlock(BB); + MachineBasicBlock *RestoreMBB = MF->CreateMachineBasicBlock(BB); + MF->insert(I, MainMBB); + MF->insert(I, SinkMBB); + MF->push_back(RestoreMBB); + RestoreMBB->setHasAddressTaken(); + + // Transfer the remainder of BB and its successor edges to SinkMBB. + SinkMBB->splice(SinkMBB->begin(), MBB, + std::next(MachineBasicBlock::iterator(MI)), MBB->end()); + SinkMBB->transferSuccessorsAndUpdatePHIs(MBB); + + // ThisMBB: + Register LabelReg = + prepareMBB(*MBB, MachineBasicBlock::iterator(MI), RestoreMBB, DL); + + // Store BP in buf[3] iff this function is using BP. + const VEFrameLowering *TFI = Subtarget->getFrameLowering(); + if (TFI->hasBP(*MF)) { + MachineInstrBuilder MIB = BuildMI(*MBB, MI, DL, TII->get(VE::STrii)); + MIB.addReg(BufReg); + MIB.addImm(0); + MIB.addImm(24); + MIB.addReg(VE::SX17); + MIB.setMemRefs(MMOs); + } + + // Store IP in buf[1]. + MachineInstrBuilder MIB = BuildMI(*MBB, MI, DL, TII->get(VE::STrii)); + MIB.add(MI.getOperand(1)); // we can preserve the kill flags here. + MIB.addImm(0); + MIB.addImm(8); + MIB.addReg(LabelReg, getKillRegState(true)); + MIB.setMemRefs(MMOs); + + // SP/FP are already stored in jmpbuf before `llvm.eh.sjlj.setjmp`. + + // Insert setup. + MIB = + BuildMI(*ThisMBB, MI, DL, TII->get(VE::EH_SjLj_Setup)).addMBB(RestoreMBB); + + const VERegisterInfo *RegInfo = Subtarget->getRegisterInfo(); + MIB.addRegMask(RegInfo->getNoPreservedMask()); + ThisMBB->addSuccessor(MainMBB); + ThisMBB->addSuccessor(RestoreMBB); + + // MainMBB: + BuildMI(MainMBB, DL, TII->get(VE::LEAzii), MainDestReg) + .addImm(0) + .addImm(0) + .addImm(0); + MainMBB->addSuccessor(SinkMBB); + + // SinkMBB: + BuildMI(*SinkMBB, SinkMBB->begin(), DL, TII->get(VE::PHI), DstReg) + .addReg(MainDestReg) + .addMBB(MainMBB) + .addReg(RestoreDestReg) + .addMBB(RestoreMBB); + + // RestoreMBB: + // Restore BP from buf[3] iff this function is using BP. The address of + // buf is in SX10. + // FIXME: Better to not use SX10 here + if (TFI->hasBP(*MF)) { + MachineInstrBuilder MIB = + BuildMI(RestoreMBB, DL, TII->get(VE::LDrii), VE::SX17); + MIB.addReg(VE::SX10); + MIB.addImm(0); + MIB.addImm(24); + MIB.setMemRefs(MMOs); + } + BuildMI(RestoreMBB, DL, TII->get(VE::LEAzii), RestoreDestReg) + .addImm(0) + .addImm(0) + .addImm(1); + BuildMI(RestoreMBB, DL, TII->get(VE::BRCFLa_t)).addMBB(SinkMBB); + RestoreMBB->addSuccessor(SinkMBB); + + MI.eraseFromParent(); + return SinkMBB; +} + +MachineBasicBlock * +VETargetLowering::emitEHSjLjLongJmp(MachineInstr &MI, + MachineBasicBlock *MBB) const { + DebugLoc DL = MI.getDebugLoc(); + MachineFunction *MF = MBB->getParent(); + const TargetInstrInfo *TII = Subtarget->getInstrInfo(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + + // Memory Reference. + SmallVector MMOs(MI.memoperands_begin(), + MI.memoperands_end()); + Register BufReg = MI.getOperand(0).getReg(); + + Register Tmp = MRI.createVirtualRegister(&VE::I64RegClass); + // Since FP is only updated here but NOT referenced, it's treated as GPR. + Register FP = VE::SX9; + Register SP = VE::SX11; + + MachineInstrBuilder MIB; + + MachineBasicBlock *ThisMBB = MBB; + + // For `call @llvm.eh.sjlj.longjmp(buf)`, we generate following instructions. + // + // ThisMBB: + // %fp = load buf[0] + // %jmp = load buf[1] + // %s10 = buf ; Store an address of buf to SX10 for RestoreMBB + // %sp = load buf[2] ; generated by llvm.eh.sjlj.setjmp. + // jmp %jmp + + // Reload FP. + MIB = BuildMI(*ThisMBB, MI, DL, TII->get(VE::LDrii), FP); + MIB.addReg(BufReg); + MIB.addImm(0); + MIB.addImm(0); + MIB.setMemRefs(MMOs); + + // Reload IP. + MIB = BuildMI(*ThisMBB, MI, DL, TII->get(VE::LDrii), Tmp); + MIB.addReg(BufReg); + MIB.addImm(0); + MIB.addImm(8); + MIB.setMemRefs(MMOs); + + // Copy BufReg to SX10 for later use in setjmp. + // FIXME: Better to not use SX10 here + BuildMI(*ThisMBB, MI, DL, TII->get(VE::ORri), VE::SX10) + .addReg(BufReg) + .addImm(0); + + // Reload SP. + MIB = BuildMI(*ThisMBB, MI, DL, TII->get(VE::LDrii), SP); + MIB.add(MI.getOperand(0)); // we can preserve the kill flags here. + MIB.addImm(0); + MIB.addImm(16); + MIB.setMemRefs(MMOs); + + // Jump. + BuildMI(*ThisMBB, MI, DL, TII->get(VE::BCFLari_t)) + .addReg(Tmp, getKillRegState(true)) + .addImm(0); + + MI.eraseFromParent(); + return ThisMBB; +} + +MachineBasicBlock * +VETargetLowering::emitSjLjDispatchBlock(MachineInstr &MI, + MachineBasicBlock *BB) const { + DebugLoc DL = MI.getDebugLoc(); + MachineFunction *MF = BB->getParent(); + MachineFrameInfo &MFI = MF->getFrameInfo(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + const VEInstrInfo *TII = Subtarget->getInstrInfo(); + int FI = MFI.getFunctionContextIndex(); + + // Get a mapping of the call site numbers to all of the landing pads they're + // associated with. + DenseMap> CallSiteNumToLPad; + unsigned MaxCSNum = 0; + for (auto &MBB : *MF) { + if (!MBB.isEHPad()) + continue; + + MCSymbol *Sym = nullptr; + for (const auto &MI : MBB) { + if (MI.isDebugInstr()) + continue; + + assert(MI.isEHLabel() && "expected EH_LABEL"); + Sym = MI.getOperand(0).getMCSymbol(); + break; + } + + if (!MF->hasCallSiteLandingPad(Sym)) + continue; + + for (unsigned CSI : MF->getCallSiteLandingPad(Sym)) { + CallSiteNumToLPad[CSI].push_back(&MBB); + MaxCSNum = std::max(MaxCSNum, CSI); + } + } + + // Get an ordered list of the machine basic blocks for the jump table. + std::vector LPadList; + SmallPtrSet InvokeBBs; + LPadList.reserve(CallSiteNumToLPad.size()); + + for (unsigned CSI = 1; CSI <= MaxCSNum; ++CSI) { + for (auto &LP : CallSiteNumToLPad[CSI]) { + LPadList.push_back(LP); + InvokeBBs.insert(LP->pred_begin(), LP->pred_end()); + } + } + + assert(!LPadList.empty() && + "No landing pad destinations for the dispatch jump table!"); + + // The %fn_context is allocated like below (from --print-after=sjljehprepare): + // %fn_context = alloca { i8*, i64, [4 x i64], i8*, i8*, [5 x i8*] } + // + // This `[5 x i8*]` is jmpbuf, so jmpbuf[1] is FI+72. + // First `i64` is callsite, so callsite is FI+8. + static const int OffsetIC = 72; + static const int OffsetCS = 8; + + // Create the MBBs for the dispatch code like following: + // + // ThisMBB: + // Prepare DispatchBB address and store it to buf[1]. + // ... + // + // DispatchBB: + // %s15 = GETGOT iff isPositionIndependent + // %callsite = load callsite + // brgt.l.t #size of callsites, %callsite, DispContBB + // + // TrapBB: + // Call abort. + // + // DispContBB: + // %breg = address of jump table + // %pc = load and calculate next pc from %breg and %callsite + // jmp %pc + + // Shove the dispatch's address into the return slot in the function context. + MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock(); + DispatchBB->setIsEHPad(true); + + // Trap BB will causes trap like `assert(0)`. + MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock(); + DispatchBB->addSuccessor(TrapBB); + + MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock(); + DispatchBB->addSuccessor(DispContBB); + + // Insert MBBs. + MF->push_back(DispatchBB); + MF->push_back(DispContBB); + MF->push_back(TrapBB); + + // Insert code to call abort in the TrapBB. + Register Abort = prepareSymbol(*TrapBB, TrapBB->end(), "abort", DL, + /* Local */ false, /* Call */ true); + BuildMI(TrapBB, DL, TII->get(VE::BSICrii), VE::SX10) + .addReg(Abort, getKillRegState(true)) + .addImm(0) + .addImm(0); + + // Insert code into the entry block that creates and registers the function + // context. + setupEntryBlockForSjLj(MI, BB, DispatchBB, FI, OffsetIC); + + // Create the jump table and associated information + unsigned JTE = getJumpTableEncoding(); + MachineJumpTableInfo *JTI = MF->getOrCreateJumpTableInfo(JTE); + unsigned MJTI = JTI->createJumpTableIndex(LPadList); + + const VERegisterInfo &RI = TII->getRegisterInfo(); + // Add a register mask with no preserved registers. This results in all + // registers being marked as clobbered. + BuildMI(DispatchBB, DL, TII->get(VE::NOP)) + .addRegMask(RI.getNoPreservedMask()); + + if (isPositionIndependent()) { + // Force to generate GETGOT, since current implementation doesn't store GOT + // register. + BuildMI(DispatchBB, DL, TII->get(VE::GETGOT), VE::SX15); + } + + // IReg is used as an index in a memory operand and therefore can't be SP + const TargetRegisterClass *RC = &VE::I64RegClass; + Register IReg = MRI.createVirtualRegister(RC); + addFrameReference(BuildMI(DispatchBB, DL, TII->get(VE::LDLZXrii), IReg), FI, + OffsetCS); + if (LPadList.size() < 64) { + BuildMI(DispatchBB, DL, TII->get(VE::BRCFLir_t)) + .addImm(VECC::CC_ILE) + .addImm(LPadList.size()) + .addReg(IReg) + .addMBB(TrapBB); + } else { + assert(LPadList.size() <= 0x7FFFFFFF && "Too large Landing Pad!"); + Register TmpReg = MRI.createVirtualRegister(RC); + BuildMI(DispatchBB, DL, TII->get(VE::LEAzii), TmpReg) + .addImm(0) + .addImm(0) + .addImm(LPadList.size()); + BuildMI(DispatchBB, DL, TII->get(VE::BRCFLrr_t)) + .addImm(VECC::CC_ILE) + .addReg(TmpReg, getKillRegState(true)) + .addReg(IReg) + .addMBB(TrapBB); + } + + Register BReg = MRI.createVirtualRegister(RC); + Register Tmp1 = MRI.createVirtualRegister(RC); + Register Tmp2 = MRI.createVirtualRegister(RC); + + if (isPositionIndependent()) { + // Create following instructions for local linkage PIC code. + // lea %Tmp1, .LJTI0_0@gotoff_lo + // and %Tmp2, %Tmp1, (32)0 + // lea.sl %BReg, .LJTI0_0@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT + BuildMI(DispContBB, DL, TII->get(VE::LEAzii), Tmp1) + .addImm(0) + .addImm(0) + .addJumpTableIndex(MJTI, VEMCExpr::VK_VE_GOTOFF_LO32); + BuildMI(DispContBB, DL, TII->get(VE::ANDrm), Tmp2) + .addReg(Tmp1, getKillRegState(true)) + .addImm(M0(32)); + BuildMI(DispContBB, DL, TII->get(VE::LEASLrri), BReg) + .addReg(VE::SX15) + .addReg(Tmp2, getKillRegState(true)) + .addJumpTableIndex(MJTI, VEMCExpr::VK_VE_GOTOFF_HI32); + } else { + // Create following instructions for non-PIC code. + // lea %Tmp1, .LJTI0_0@lo + // and %Tmp2, %Tmp1, (32)0 + // lea.sl %BReg, .LJTI0_0@hi(%Tmp2) + BuildMI(DispContBB, DL, TII->get(VE::LEAzii), Tmp1) + .addImm(0) + .addImm(0) + .addJumpTableIndex(MJTI, VEMCExpr::VK_VE_LO32); + BuildMI(DispContBB, DL, TII->get(VE::ANDrm), Tmp2) + .addReg(Tmp1, getKillRegState(true)) + .addImm(M0(32)); + BuildMI(DispContBB, DL, TII->get(VE::LEASLrii), BReg) + .addReg(Tmp2, getKillRegState(true)) + .addImm(0) + .addJumpTableIndex(MJTI, VEMCExpr::VK_VE_HI32); + } + + switch (JTE) { + case MachineJumpTableInfo::EK_BlockAddress: { + // Generate simple block address code for no-PIC model. + // sll %Tmp1, %IReg, 3 + // lds %TReg, 0(%Tmp1, %BReg) + // bcfla %TReg + + Register TReg = MRI.createVirtualRegister(RC); + Register Tmp1 = MRI.createVirtualRegister(RC); + + BuildMI(DispContBB, DL, TII->get(VE::SLLri), Tmp1) + .addReg(IReg, getKillRegState(true)) + .addImm(3); + BuildMI(DispContBB, DL, TII->get(VE::LDrri), TReg) + .addReg(BReg, getKillRegState(true)) + .addReg(Tmp1, getKillRegState(true)) + .addImm(0); + BuildMI(DispContBB, DL, TII->get(VE::BCFLari_t)) + .addReg(TReg, getKillRegState(true)) + .addImm(0); + break; + } + case MachineJumpTableInfo::EK_Custom32: { + // Generate block address code using differences from the function pointer + // for PIC model. + // sll %Tmp1, %IReg, 2 + // ldl.zx %OReg, 0(%Tmp1, %BReg) + // Prepare function address in BReg2. + // adds.l %TReg, %BReg2, %OReg + // bcfla %TReg + + assert(isPositionIndependent()); + Register OReg = MRI.createVirtualRegister(RC); + Register TReg = MRI.createVirtualRegister(RC); + Register Tmp1 = MRI.createVirtualRegister(RC); + + BuildMI(DispContBB, DL, TII->get(VE::SLLri), Tmp1) + .addReg(IReg, getKillRegState(true)) + .addImm(2); + BuildMI(DispContBB, DL, TII->get(VE::LDLZXrri), OReg) + .addReg(BReg, getKillRegState(true)) + .addReg(Tmp1, getKillRegState(true)) + .addImm(0); + Register BReg2 = + prepareSymbol(*DispContBB, DispContBB->end(), + DispContBB->getParent()->getName(), DL, /* Local */ true); + BuildMI(DispContBB, DL, TII->get(VE::ADDSLrr), TReg) + .addReg(OReg, getKillRegState(true)) + .addReg(BReg2, getKillRegState(true)); + BuildMI(DispContBB, DL, TII->get(VE::BCFLari_t)) + .addReg(TReg, getKillRegState(true)) + .addImm(0); + break; + } + default: + llvm_unreachable("Unexpected jump table encoding"); + } + + // Add the jump table entries as successors to the MBB. + SmallPtrSet SeenMBBs; + for (auto &LP : LPadList) + if (SeenMBBs.insert(LP).second) + DispContBB->addSuccessor(LP); + + // N.B. the order the invoke BBs are processed in doesn't matter here. + SmallVector MBBLPads; + const MCPhysReg *SavedRegs = MF->getRegInfo().getCalleeSavedRegs(); + for (MachineBasicBlock *MBB : InvokeBBs) { + // Remove the landing pad successor from the invoke block and replace it + // with the new dispatch block. + // Keep a copy of Successors since it's modified inside the loop. + SmallVector Successors(MBB->succ_rbegin(), + MBB->succ_rend()); + // FIXME: Avoid quadratic complexity. + for (auto MBBS : Successors) { + if (MBBS->isEHPad()) { + MBB->removeSuccessor(MBBS); + MBBLPads.push_back(MBBS); + } + } + + MBB->addSuccessor(DispatchBB); + + // Find the invoke call and mark all of the callee-saved registers as + // 'implicit defined' so that they're spilled. This prevents code from + // moving instructions to before the EH block, where they will never be + // executed. + for (auto &II : reverse(*MBB)) { + if (!II.isCall()) + continue; + + DenseMap DefRegs; + for (auto &MOp : II.operands()) + if (MOp.isReg()) + DefRegs[MOp.getReg()] = true; + + MachineInstrBuilder MIB(*MF, &II); + for (unsigned RI = 0; SavedRegs[RI]; ++RI) { + Register Reg = SavedRegs[RI]; + if (!DefRegs[Reg]) + MIB.addReg(Reg, RegState::ImplicitDefine | RegState::Dead); + } + + break; + } + } + + // Mark all former landing pads as non-landing pads. The dispatch is the only + // landing pad now. + for (auto &LP : MBBLPads) + LP->setIsEHPad(false); + + // The instruction is gone now. + MI.eraseFromParent(); + return BB; +} + +MachineBasicBlock * +VETargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, + MachineBasicBlock *BB) const { + switch (MI.getOpcode()) { + default: + llvm_unreachable("Unknown Custom Instruction!"); + case VE::EH_SjLj_LongJmp: + return emitEHSjLjLongJmp(MI, BB); + case VE::EH_SjLj_SetJmp: + return emitEHSjLjSetJmp(MI, BB); + case VE::EH_SjLj_Setup_Dispatch: + return emitSjLjDispatchBlock(MI, BB); + } +} + static bool isI32Insn(const SDNode *User, const SDNode *N) { switch (User->getOpcode()) { default: diff --git a/llvm/lib/Target/VE/VEInstrBuilder.h b/llvm/lib/Target/VE/VEInstrBuilder.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/VE/VEInstrBuilder.h @@ -0,0 +1,41 @@ +//===-- VEInstrBuilder.h - Aides for building VE insts ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file exposes functions that may be used with BuildMI from the +// MachineInstrBuilder.h file to simplify generating frame and constant pool +// references. +// +// For reference, the order of operands for memory references is: +// (Operand), Dest Reg, Base Reg, and either Reg Index or Immediate +// Displacement. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_VE_VEINSTRBUILDER_H +#define LLVM_LIB_TARGET_VE_VEINSTRBUILDER_H + +#include "llvm/CodeGen/MachineInstrBuilder.h" + +namespace llvm { + +/// addFrameReference - This function is used to add a reference to the base of +/// an abstract object on the stack frame of the current function. This +/// reference has base register as the FrameIndex offset until it is resolved. +/// This allows a constant offset to be specified as well... +/// +static inline const MachineInstrBuilder & +addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0, + bool ThreeOp = true) { + if (ThreeOp) + return MIB.addFrameIndex(FI).addImm(0).addImm(Offset); + return MIB.addFrameIndex(FI).addImm(Offset); +} + +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/VE/VEInstrInfo.td b/llvm/lib/Target/VE/VEInstrInfo.td --- a/llvm/lib/Target/VE/VEInstrInfo.td +++ b/llvm/lib/Target/VE/VEInstrInfo.td @@ -446,6 +446,17 @@ def getGOT : Operand; +def VEeh_sjlj_setjmp: SDNode<"VEISD::EH_SJLJ_SETJMP", + SDTypeProfile<1, 1, [SDTCisInt<0>, + SDTCisPtrTy<1>]>, + [SDNPHasChain, SDNPSideEffect]>; +def VEeh_sjlj_longjmp: SDNode<"VEISD::EH_SJLJ_LONGJMP", + SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>, + [SDNPHasChain, SDNPSideEffect]>; +def VEeh_sjlj_setup_dispatch: SDNode<"VEISD::EH_SJLJ_SETUP_DISPATCH", + SDTypeProfile<0, 0, []>, + [SDNPHasChain, SDNPSideEffect]>; + // GETFUNPLT for PIC def GetFunPLT : SDNode<"VEISD::GETFUNPLT", SDTIntUnaryOp>; @@ -1878,6 +1889,33 @@ def : Pat<(i64 (atomic_swap_64 ADDRri:$src, i64:$new)), (TS1AMLrir MEMriRRM:$src, (LEAzii 0, 0, 255), i64:$new)>; +//===----------------------------------------------------------------------===// +// SJLJ Exception handling patterns +//===----------------------------------------------------------------------===// + +let hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1, + usesCustomInserter = 1 in { + let isTerminator = 1 in + def EH_SjLj_LongJmp : Pseudo<(outs), (ins I64:$buf), + "# EH_SJLJ_LONGJMP", + [(VEeh_sjlj_longjmp I64:$buf)]>; + + def EH_SjLj_SetJmp : Pseudo<(outs I32:$dst), (ins I64:$buf), + "# EH_SJLJ_SETJMP", + [(set I32:$dst, (VEeh_sjlj_setjmp I64:$buf))]>; + + def EH_SjLj_Setup_Dispatch : Pseudo<(outs), (ins), "# EH_SJLJ_SETUP_DISPATCH", + [(VEeh_sjlj_setup_dispatch)]>; +} + +let isTerminator = 1, isBranch = 1, isCodeGenOnly = 1 in + def EH_SjLj_Setup : Pseudo<(outs), (ins brtarget32:$dst), + "# EH_SJlJ_SETUP $dst">; + +//===----------------------------------------------------------------------===// +// Branch related patterns +//===----------------------------------------------------------------------===// + // Branches def : Pat<(br bb:$addr), (BRCFLa bb:$addr)>; diff --git a/llvm/test/CodeGen/VE/Scalar/builtin_sjlj.ll b/llvm/test/CodeGen/VE/Scalar/builtin_sjlj.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/VE/Scalar/builtin_sjlj.ll @@ -0,0 +1,213 @@ +; RUN: llc < %s -mtriple=ve | FileCheck %s +; RUN: llc < %s -mtriple=ve -relocation-model=pic | \ +; RUN: FileCheck %s -check-prefix=PIC + +%struct.__jmp_buf_tag = type { [25 x i64], i64, [16 x i64] } + +@buf = common global [1 x %struct.__jmp_buf_tag] zeroinitializer, align 8 + +; Function Attrs: noinline nounwind optnone +define signext i32 @t_setjmp() { +; CHECK-LABEL: t_setjmp: +; CHECK: .LBB{{[0-9]+}}_5: +; CHECK-NEXT: st %s18, 48(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s19, 56(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s20, 64(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s21, 72(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s22, 80(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s23, 88(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s24, 96(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s25, 104(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s26, 112(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s27, 120(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s28, 128(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s29, 136(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s30, 144(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s31, 152(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s32, 160(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s33, 168(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: lea %s0, buf@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s0, buf@hi(, %s0) +; CHECK-NEXT: st %s9, (, %s0) +; CHECK-NEXT: st %s11, 16(, %s0) +; CHECK-NEXT: lea %s1, .LBB{{[0-9]+}}_3@lo +; CHECK-NEXT: and %s1, %s1, (32)0 +; CHECK-NEXT: lea.sl %s1, .LBB{{[0-9]+}}_3@hi(, %s1) +; CHECK-NEXT: st %s1, 8(, %s0) +; CHECK-NEXT: # EH_SJlJ_SETUP .LBB{{[0-9]+}}_3 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lea %s0, 0 +; CHECK-NEXT: br.l.t .LBB{{[0-9]+}}_2 +; CHECK-NEXT: .LBB{{[0-9]+}}_3: # Block address taken +; CHECK-NEXT: lea %s0, 1 +; CHECK-NEXT: .LBB{{[0-9]+}}_2: +; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1 +; CHECK-NEXT: ld %s33, 168(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s32, 160(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s31, 152(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s30, 144(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s29, 136(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s28, 128(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s27, 120(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s26, 112(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s25, 104(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s24, 96(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s23, 88(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s22, 80(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s21, 72(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s20, 64(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s19, 56(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s18, 48(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: or %s11, 0, %s9 +; +; PIC-LABEL: t_setjmp: +; PIC: # %bb.0: +; PIC-NEXT: st %s9, (, %s11) +; PIC-NEXT: st %s10, 8(, %s11) +; PIC-NEXT: st %s15, 24(, %s11) +; PIC-NEXT: st %s16, 32(, %s11) +; PIC-NEXT: or %s9, 0, %s11 +; PIC-NEXT: lea %s11, -176(, %s11) +; PIC-NEXT: brge.l %s11, %s8, .LBB0_5 +; PIC-NEXT: # %bb.4: +; PIC-NEXT: ld %s61, 24(, %s14) +; PIC-NEXT: or %s62, 0, %s0 +; PIC-NEXT: lea %s63, 315 +; PIC-NEXT: shm.l %s63, (%s61) +; PIC-NEXT: shm.l %s8, 8(%s61) +; PIC-NEXT: shm.l %s11, 16(%s61) +; PIC-NEXT: monc +; PIC-NEXT: or %s0, 0, %s62 +; PIC-NEXT: .LBB0_5: +; PIC-NEXT: st %s18, 48(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s19, 56(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s20, 64(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s21, 72(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s22, 80(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s23, 88(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s24, 96(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s25, 104(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s26, 112(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s27, 120(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s28, 128(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s29, 136(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s30, 144(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s31, 152(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s32, 160(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s33, 168(, %s9) # 8-byte Folded Spill +; PIC-NEXT: lea %s15, _GLOBAL_OFFSET_TABLE_@pc_lo(-24) +; PIC-NEXT: and %s15, %s15, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s15, _GLOBAL_OFFSET_TABLE_@pc_hi(%s16, %s15) +; PIC-NEXT: lea %s0, buf@got_lo +; PIC-NEXT: and %s0, %s0, (32)0 +; PIC-NEXT: lea.sl %s0, buf@got_hi(, %s0) +; PIC-NEXT: ld %s0, (%s0, %s15) +; PIC-NEXT: st %s9, (, %s0) +; PIC-NEXT: st %s11, 16(, %s0) +; PIC-NEXT: lea %s1, .LBB0_3@gotoff_lo +; PIC-NEXT: and %s1, %s1, (32)0 +; PIC-NEXT: lea.sl %s1, .LBB0_3@gotoff_hi(%s1, %s15) +; PIC-NEXT: st %s1, 8(, %s0) +; PIC-NEXT: # EH_SJlJ_SETUP .LBB0_3 +; PIC-NEXT: # %bb.1: +; PIC-NEXT: lea %s0, 0 +; PIC-NEXT: br.l.t .LBB0_2 +; PIC-NEXT: .LBB0_3: # Block address taken +; PIC-NEXT: lea %s0, 1 +; PIC-NEXT: .LBB0_2: +; PIC-NEXT: adds.w.sx %s0, %s0, (0)1 +; PIC-NEXT: ld %s33, 168(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s32, 160(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s31, 152(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s30, 144(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s29, 136(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s28, 128(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s27, 120(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s26, 112(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s25, 104(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s24, 96(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s23, 88(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s22, 80(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s21, 72(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s20, 64(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s19, 56(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s18, 48(, %s9) # 8-byte Folded Reload +; PIC-NEXT: or %s11, 0, %s9 +; PIC-NEXT: ld %s16, 32(, %s11) +; PIC-NEXT: ld %s15, 24(, %s11) +; PIC-NEXT: ld %s10, 8(, %s11) +; PIC-NEXT: ld %s9, (, %s11) +; PIC-NEXT: b.l.t (, %s10) + %1 = call i8* @llvm.frameaddress(i32 0) + store i8* %1, i8** bitcast ([1 x %struct.__jmp_buf_tag]* @buf to i8**), align 8 + %2 = call i8* @llvm.stacksave() + store i8* %2, i8** getelementptr inbounds (i8*, i8** bitcast ([1 x %struct.__jmp_buf_tag]* @buf to i8**), i64 2), align 8 + %3 = call i32 @llvm.eh.sjlj.setjmp(i8* bitcast ([1 x %struct.__jmp_buf_tag]* @buf to i8*)) + ret i32 %3 +} + +; Function Attrs: nounwind readnone +declare i8* @llvm.frameaddress(i32) + +; Function Attrs: nounwind +declare i8* @llvm.stacksave() + +; Function Attrs: nounwind +declare i32 @llvm.eh.sjlj.setjmp(i8*) + +; Function Attrs: noinline nounwind optnone +define void @t_longjmp() { +; CHECK-LABEL: t_longjmp: +; CHECK: .LBB{{[0-9]+}}_2: +; CHECK-NEXT: lea %s0, buf@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s0, buf@hi(, %s0) +; CHECK-NEXT: ld %s9, (, %s0) +; CHECK-NEXT: ld %s1, 8(, %s0) +; CHECK-NEXT: or %s10, 0, %s0 +; CHECK-NEXT: ld %s11, 16(, %s0) +; CHECK-NEXT: b.l.t (, %s1) +; +; PIC-LABEL: t_longjmp: +; PIC: # %bb.0: +; PIC-NEXT: st %s9, (, %s11) +; PIC-NEXT: st %s10, 8(, %s11) +; PIC-NEXT: st %s15, 24(, %s11) +; PIC-NEXT: st %s16, 32(, %s11) +; PIC-NEXT: or %s9, 0, %s11 +; PIC-NEXT: lea %s11, -176(, %s11) +; PIC-NEXT: brge.l.t %s11, %s8, .LBB1_2 +; PIC-NEXT: # %bb.1: +; PIC-NEXT: ld %s61, 24(, %s14) +; PIC-NEXT: or %s62, 0, %s0 +; PIC-NEXT: lea %s63, 315 +; PIC-NEXT: shm.l %s63, (%s61) +; PIC-NEXT: shm.l %s8, 8(%s61) +; PIC-NEXT: shm.l %s11, 16(%s61) +; PIC-NEXT: monc +; PIC-NEXT: or %s0, 0, %s62 +; PIC-NEXT: .LBB1_2: +; PIC-NEXT: lea %s15, _GLOBAL_OFFSET_TABLE_@pc_lo(-24) +; PIC-NEXT: and %s15, %s15, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s15, _GLOBAL_OFFSET_TABLE_@pc_hi(%s16, %s15) +; PIC-NEXT: lea %s0, buf@got_lo +; PIC-NEXT: and %s0, %s0, (32)0 +; PIC-NEXT: lea.sl %s0, buf@got_hi(, %s0) +; PIC-NEXT: ld %s0, (%s0, %s15) +; PIC-NEXT: ld %s9, (, %s0) +; PIC-NEXT: ld %s1, 8(, %s0) +; PIC-NEXT: or %s10, 0, %s0 +; PIC-NEXT: ld %s11, 16(, %s0) +; PIC-NEXT: b.l.t (, %s1) + call void @llvm.eh.sjlj.longjmp(i8* bitcast ([1 x %struct.__jmp_buf_tag]* @buf to i8*)) + unreachable + ; No predecessors! + ret void +} + +; Function Attrs: noreturn nounwind +declare void @llvm.eh.sjlj.longjmp(i8*) + diff --git a/llvm/test/CodeGen/VE/Scalar/builtin_sjlj_bp.ll b/llvm/test/CodeGen/VE/Scalar/builtin_sjlj_bp.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/VE/Scalar/builtin_sjlj_bp.ll @@ -0,0 +1,87 @@ +; RUN: llc < %s -mtriple=ve | FileCheck %s + +%Foo = type { [125 x i8] } +declare void @whatever(i64, %Foo*, i8**, i8*, i8*, i32) #0 +declare i32 @llvm.eh.sjlj.setjmp(i8*) nounwind + +; Function Attrs: noinline nounwind optnone +define i32 @t_setjmp(i64 %n, %Foo* byval(%Foo) nocapture readnone align 8 %f) { +; CHECK-LABEL: t_setjmp: +; CHECK: .LBB{{[0-9]+}}_5: +; CHECK-NEXT: st %s18, 48(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s19, 56(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s20, 64(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s21, 72(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s22, 80(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s23, 88(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s24, 96(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s25, 104(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s26, 112(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s27, 120(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s28, 128(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s29, 136(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s30, 144(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s31, 152(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s32, 160(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s33, 168(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s1, 312(, %s17) # 8-byte Folded Spill +; CHECK-NEXT: st %s0, 304(, %s17) # 8-byte Folded Spill +; CHECK-NEXT: lea %s0, 15(, %s0) +; CHECK-NEXT: and %s0, -16, %s0 +; CHECK-NEXT: lea %s1, __ve_grow_stack@lo +; CHECK-NEXT: and %s1, %s1, (32)0 +; CHECK-NEXT: lea.sl %s12, __ve_grow_stack@hi(, %s1) +; CHECK-NEXT: bsic %s10, (, %s12) +; CHECK-NEXT: lea %s1, 240(, %s11) +; CHECK-NEXT: st %s1, 328(, %s17) +; CHECK-NEXT: lea %s0, .LBB{{[0-9]+}}_3@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s0, .LBB{{[0-9]+}}_3@hi(, %s0) +; CHECK-NEXT: st %s17, 24(, %s1) +; CHECK-NEXT: st %s1, 296(, %s17) # 8-byte Folded Spill +; CHECK-NEXT: st %s0, 8(, %s1) +; CHECK-NEXT: # EH_SJlJ_SETUP .LBB{{[0-9]+}}_3 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lea %s5, 0 +; CHECK-NEXT: br.l.t .LBB{{[0-9]+}}_2 +; CHECK-NEXT: .LBB{{[0-9]+}}_3: # Block address taken +; CHECK-NEXT: ld %s17, 24(, %s10) +; CHECK-NEXT: lea %s5, 1 +; CHECK-NEXT: .LBB{{[0-9]+}}_2: +; CHECK-NEXT: lea %s0, whatever@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s12, whatever@hi(, %s0) +; CHECK-NEXT: lea %s2, 328(, %s17) +; CHECK-NEXT: lea %s3, 320(, %s17) +; CHECK-NEXT: ld %s0, 304(, %s17) # 8-byte Folded Reload +; CHECK-NEXT: ld %s1, 312(, %s17) # 8-byte Folded Reload +; CHECK-NEXT: ld %s4, 296(, %s17) # 8-byte Folded Reload +; CHECK-NEXT: bsic %s10, (, %s12) +; CHECK-NEXT: or %s0, 0, (0)1 +; CHECK-NEXT: ld %s33, 168(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s32, 160(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s31, 152(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s30, 144(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s29, 136(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s28, 128(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s27, 120(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s26, 112(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s25, 104(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s24, 96(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s23, 88(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s22, 80(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s21, 72(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s20, 64(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s19, 56(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s18, 48(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: or %s11, 0, %s9 + %buf = alloca [5 x i8*], align 16 + %p = alloca i8*, align 8 + %q = alloca i8, align 64 + %r = bitcast [5 x i8*]* %buf to i8* + %s = alloca i8, i64 %n, align 1 + store i8* %s, i8** %p, align 8 + %t = call i32 @llvm.eh.sjlj.setjmp(i8* %s) + call void @whatever(i64 %n, %Foo* %f, i8** %p, i8* %q, i8* %s, i32 %t) #1 + ret i32 0 +} diff --git a/llvm/test/CodeGen/VE/Scalar/builtin_sjlj_callsite.ll b/llvm/test/CodeGen/VE/Scalar/builtin_sjlj_callsite.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/VE/Scalar/builtin_sjlj_callsite.ll @@ -0,0 +1,282 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=ve -exception-model sjlj | FileCheck %s +; RUN: llc < %s -mtriple=ve -exception-model sjlj -relocation-model pic | \ +; RUN: FileCheck %s -check-prefix=PIC + +; Function Attrs: noinline nounwind optnone +define void @test_callsite() personality i32 (...)* @__gxx_personality_sj0 { +; CHECK-LABEL: test_callsite: +; CHECK: # %bb.0: +; CHECK-NEXT: st %s9, (, %s11) +; CHECK-NEXT: st %s10, 8(, %s11) +; CHECK-NEXT: or %s9, 0, %s11 +; CHECK-NEXT: lea %s11, -432(, %s11) +; CHECK-NEXT: brge.l %s11, %s8, .LBB0_7 +; CHECK-NEXT: # %bb.6: +; CHECK-NEXT: ld %s61, 24(, %s14) +; CHECK-NEXT: or %s62, 0, %s0 +; CHECK-NEXT: lea %s63, 315 +; CHECK-NEXT: shm.l %s63, (%s61) +; CHECK-NEXT: shm.l %s8, 8(%s61) +; CHECK-NEXT: shm.l %s11, 16(%s61) +; CHECK-NEXT: monc +; CHECK-NEXT: or %s0, 0, %s62 +; CHECK-NEXT: .LBB0_7: +; CHECK-NEXT: st %s18, 48(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s19, 56(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s20, 64(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s21, 72(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s22, 80(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s23, 88(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s24, 96(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s25, 104(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s26, 112(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s27, 120(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s28, 128(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s29, 136(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s30, 144(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s31, 152(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s32, 160(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s33, 168(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: lea %s0, __gxx_personality_sj0@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s0, __gxx_personality_sj0@hi(, %s0) +; CHECK-NEXT: st %s0, -56(, %s9) +; 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: st %s0, -48(, %s9) +; CHECK-NEXT: st %s9, -40(, %s9) +; CHECK-NEXT: st %s11, -24(, %s9) +; CHECK-NEXT: lea %s0, .LBB0_3@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s0, .LBB0_3@hi(, %s0) +; CHECK-NEXT: st %s0, -32(, %s9) +; CHECK-NEXT: or %s0, 1, (0)1 +; CHECK-NEXT: st %s0, -96(, %s9) +; CHECK-NEXT: lea %s0, _Unwind_SjLj_Register@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s12, _Unwind_SjLj_Register@hi(, %s0) +; CHECK-NEXT: lea %s0, -104(, %s9) +; CHECK-NEXT: bsic %s10, (, %s12) +; CHECK-NEXT: .Ltmp0: +; CHECK-NEXT: lea %s0, f@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s12, f@hi(, %s0) +; CHECK-NEXT: bsic %s10, (, %s12) +; CHECK-NEXT: .Ltmp1: +; CHECK-NEXT: .LBB0_2: # %try.cont +; CHECK-NEXT: or %s0, -1, (0)1 +; CHECK-NEXT: st %s0, -96(, %s9) +; CHECK-NEXT: lea %s0, _Unwind_SjLj_Unregister@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s18, _Unwind_SjLj_Unregister@hi(, %s0) +; CHECK-NEXT: lea %s0, -192(, %s9) +; CHECK-NEXT: or %s12, 0, %s18 +; CHECK-NEXT: bsic %s10, (, %s12) +; CHECK-NEXT: lea %s0, -104(, %s9) +; CHECK-NEXT: or %s12, 0, %s18 +; CHECK-NEXT: bsic %s10, (, %s12) +; CHECK-NEXT: ld %s33, 168(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s32, 160(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s31, 152(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s30, 144(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s29, 136(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s28, 128(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s27, 120(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s26, 112(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s25, 104(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s24, 96(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s23, 88(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s22, 80(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s21, 72(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s20, 64(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s19, 56(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s18, 48(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: or %s11, 0, %s9 +; CHECK-NEXT: ld %s10, 8(, %s11) +; CHECK-NEXT: ld %s9, (, %s11) +; CHECK-NEXT: b.l.t (, %s10) +; CHECK-NEXT: .LBB0_3: +; CHECK-NEXT: ldl.zx %s0, -96(, %s9) +; CHECK-NEXT: brgt.l 1, %s0, .LBB0_4 +; CHECK-NEXT: # %bb.5: +; CHECK-NEXT: lea %s0, abort@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s0, abort@hi(, %s0) +; CHECK-NEXT: bsic %s10, (, %s0) +; CHECK-NEXT: .LBB0_4: +; CHECK-NEXT: lea %s1, .LJTI0_0@lo +; CHECK-NEXT: and %s1, %s1, (32)0 +; CHECK-NEXT: lea.sl %s1, .LJTI0_0@hi(, %s1) +; CHECK-NEXT: sll %s0, %s0, 3 +; CHECK-NEXT: ld %s0, (%s0, %s1) +; CHECK-NEXT: b.l.t (, %s0) +; CHECK-NEXT: .LBB0_1: # %lpad +; CHECK-NEXT: .Ltmp2: +; CHECK-NEXT: ld %s0, -88(, %s9) +; CHECK-NEXT: ld %s0, -80(, %s9) +; CHECK-NEXT: br.l.t .LBB0_2 +; +; PIC-LABEL: test_callsite: +; PIC: # %bb.0: +; PIC-NEXT: st %s9, (, %s11) +; PIC-NEXT: st %s10, 8(, %s11) +; PIC-NEXT: st %s15, 24(, %s11) +; PIC-NEXT: st %s16, 32(, %s11) +; PIC-NEXT: or %s9, 0, %s11 +; PIC-NEXT: lea %s11, -432(, %s11) +; PIC-NEXT: brge.l %s11, %s8, .LBB0_7 +; PIC-NEXT: # %bb.6: +; PIC-NEXT: ld %s61, 24(, %s14) +; PIC-NEXT: or %s62, 0, %s0 +; PIC-NEXT: lea %s63, 315 +; PIC-NEXT: shm.l %s63, (%s61) +; PIC-NEXT: shm.l %s8, 8(%s61) +; PIC-NEXT: shm.l %s11, 16(%s61) +; PIC-NEXT: monc +; PIC-NEXT: or %s0, 0, %s62 +; PIC-NEXT: .LBB0_7: +; PIC-NEXT: st %s18, 48(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s19, 56(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s20, 64(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s21, 72(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s22, 80(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s23, 88(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s24, 96(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s25, 104(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s26, 112(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s27, 120(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s28, 128(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s29, 136(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s30, 144(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s31, 152(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s32, 160(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s33, 168(, %s9) # 8-byte Folded Spill +; PIC-NEXT: lea %s15, _GLOBAL_OFFSET_TABLE_@pc_lo(-24) +; PIC-NEXT: and %s15, %s15, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s15, _GLOBAL_OFFSET_TABLE_@pc_hi(%s16, %s15) +; PIC-NEXT: lea %s0, __gxx_personality_sj0@got_lo +; PIC-NEXT: and %s0, %s0, (32)0 +; PIC-NEXT: lea.sl %s0, __gxx_personality_sj0@got_hi(, %s0) +; PIC-NEXT: ld %s0, (%s0, %s15) +; PIC-NEXT: st %s0, -56(, %s9) +; PIC-NEXT: lea %s0, GCC_except_table0@gotoff_lo +; PIC-NEXT: and %s0, %s0, (32)0 +; PIC-NEXT: lea.sl %s0, GCC_except_table0@gotoff_hi(%s0, %s15) +; PIC-NEXT: st %s0, -48(, %s9) +; PIC-NEXT: st %s9, -40(, %s9) +; PIC-NEXT: st %s11, -24(, %s9) +; PIC-NEXT: lea %s0, .LBB0_3@gotoff_lo +; PIC-NEXT: and %s0, %s0, (32)0 +; PIC-NEXT: lea.sl %s0, .LBB0_3@gotoff_hi(%s0, %s15) +; PIC-NEXT: st %s0, -32(, %s9) +; PIC-NEXT: or %s0, 1, (0)1 +; PIC-NEXT: st %s0, -96(, %s9) +; PIC-NEXT: lea %s12, _Unwind_SjLj_Register@plt_lo(-24) +; PIC-NEXT: and %s12, %s12, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s12, _Unwind_SjLj_Register@plt_hi(%s16, %s12) +; PIC-NEXT: lea %s0, -104(, %s9) +; PIC-NEXT: bsic %s10, (, %s12) +; PIC-NEXT: .Ltmp0: +; PIC-NEXT: lea %s12, f@plt_lo(-24) +; PIC-NEXT: and %s12, %s12, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s12, f@plt_hi(%s16, %s12) +; PIC-NEXT: bsic %s10, (, %s12) +; PIC-NEXT: .Ltmp1: +; PIC-NEXT: .LBB0_2: # %try.cont +; PIC-NEXT: or %s0, -1, (0)1 +; PIC-NEXT: st %s0, -96(, %s9) +; PIC-NEXT: lea %s18, _Unwind_SjLj_Unregister@plt_lo(-24) +; PIC-NEXT: and %s18, %s18, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s18, _Unwind_SjLj_Unregister@plt_hi(%s16, %s18) +; PIC-NEXT: lea %s0, -192(, %s9) +; PIC-NEXT: or %s12, 0, %s18 +; PIC-NEXT: bsic %s10, (, %s12) +; PIC-NEXT: lea %s0, -104(, %s9) +; PIC-NEXT: or %s12, 0, %s18 +; PIC-NEXT: bsic %s10, (, %s12) +; PIC-NEXT: ld %s33, 168(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s32, 160(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s31, 152(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s30, 144(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s29, 136(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s28, 128(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s27, 120(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s26, 112(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s25, 104(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s24, 96(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s23, 88(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s22, 80(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s21, 72(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s20, 64(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s19, 56(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s18, 48(, %s9) # 8-byte Folded Reload +; PIC-NEXT: or %s11, 0, %s9 +; PIC-NEXT: ld %s16, 32(, %s11) +; PIC-NEXT: ld %s15, 24(, %s11) +; PIC-NEXT: ld %s10, 8(, %s11) +; PIC-NEXT: ld %s9, (, %s11) +; PIC-NEXT: b.l.t (, %s10) +; PIC-NEXT: .LBB0_3: +; PIC-NEXT: ldl.zx %s0, -96(, %s9) +; PIC-NEXT: lea %s15, _GLOBAL_OFFSET_TABLE_@pc_lo(-24) +; PIC-NEXT: and %s15, %s15, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s15, _GLOBAL_OFFSET_TABLE_@pc_hi(%s16, %s15) +; PIC-NEXT: brgt.l 1, %s0, .LBB0_4 +; PIC-NEXT: # %bb.5: +; PIC-NEXT: lea %s0, abort@plt_lo(-24) +; PIC-NEXT: and %s0, %s0, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s0, abort@plt_hi(%s16, %s0) +; PIC-NEXT: bsic %s10, (, %s0) +; PIC-NEXT: .LBB0_4: +; PIC-NEXT: lea %s1, .LJTI0_0@gotoff_lo +; PIC-NEXT: and %s1, %s1, (32)0 +; PIC-NEXT: lea.sl %s1, .LJTI0_0@gotoff_hi(%s1, %s15) +; PIC-NEXT: sll %s0, %s0, 2 +; PIC-NEXT: ldl.zx %s0, (%s0, %s1) +; PIC-NEXT: lea %s1, test_callsite@gotoff_lo +; PIC-NEXT: and %s1, %s1, (32)0 +; PIC-NEXT: lea.sl %s1, test_callsite@gotoff_hi(%s1, %s15) +; PIC-NEXT: adds.l %s0, %s0, %s1 +; PIC-NEXT: b.l.t (, %s0) +; PIC-NEXT: .LBB0_1: # %lpad +; PIC-NEXT: .Ltmp2: +; PIC-NEXT: ld %s0, -88(, %s9) +; PIC-NEXT: ld %s0, -80(, %s9) +; PIC-NEXT: br.l.t .LBB0_2 + %fn_context = alloca { i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }, align 4 + call void @llvm.eh.sjlj.callsite(i32 0) + invoke void @f() + to label %try.cont unwind label %lpad + +lpad: ; preds = %entry + %1 = landingpad { i8*, i32 } + cleanup +;; %__data = getelementptr { i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }, { i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }* %fn_context, i32 0, i32 2 +;; %exception_gep = getelementptr [4 x i32], [4 x i32]* %__data, i32 0, i32 0 +;; %exn_val = load volatile i32, i32* %exception_gep, align 4 +;; %2 = inttoptr i32 %exn_val to i8* +;; %exn_selector_gep = getelementptr [4 x i32], [4 x i32]* %__data, i32 0, i32 1 +;; %exn_selector_val = load volatile i32, i32* %exn_selector_gep, align 4 + br label %try.cont + +try.cont: ; preds = %lpad, %entry + call void @_Unwind_SjLj_Unregister({ i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }* %fn_context) + ret void +} + +declare void @f() + +declare i32 @__gxx_personality_sj0(...) + +declare void @_Unwind_SjLj_Unregister({ i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }*) + +; Function Attrs: nounwind readnone +declare void @llvm.eh.sjlj.callsite(i32) diff --git a/llvm/test/CodeGen/VE/Scalar/builtin_sjlj_landingpad.ll b/llvm/test/CodeGen/VE/Scalar/builtin_sjlj_landingpad.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/VE/Scalar/builtin_sjlj_landingpad.ll @@ -0,0 +1,303 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=ve -exception-model=sjlj < %s | FileCheck %s +; RUN: llc -mtriple=ve -exception-model=sjlj -relocation-model=pic < %s | \ +; RUN: FileCheck --check-prefix=PIC %s + +@SomeGlobal = external dso_local global i8 + +define dso_local i32 @foo(i32 %arg) local_unnamed_addr personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) { +; CHECK-LABEL: foo: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: st %s9, (, %s11) +; CHECK-NEXT: st %s10, 8(, %s11) +; CHECK-NEXT: or %s9, 0, %s11 +; CHECK-NEXT: lea %s11, -352(, %s11) +; CHECK-NEXT: brge.l %s11, %s8, .LBB0_8 +; CHECK-NEXT: # %bb.7: # %entry +; CHECK-NEXT: ld %s61, 24(, %s14) +; CHECK-NEXT: or %s62, 0, %s0 +; CHECK-NEXT: lea %s63, 315 +; CHECK-NEXT: shm.l %s63, (%s61) +; CHECK-NEXT: shm.l %s8, 8(%s61) +; CHECK-NEXT: shm.l %s11, 16(%s61) +; CHECK-NEXT: monc +; CHECK-NEXT: or %s0, 0, %s62 +; CHECK-NEXT: .LBB0_8: # %entry +; CHECK-NEXT: st %s18, 48(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s19, 56(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s20, 64(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s21, 72(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s22, 80(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s23, 88(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s24, 96(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s25, 104(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s26, 112(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s27, 120(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s28, 128(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s29, 136(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s30, 144(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s31, 152(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s32, 160(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: st %s33, 168(, %s9) # 8-byte Folded Spill +; CHECK-NEXT: lea %s0, __gxx_personality_sj0@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s0, __gxx_personality_sj0@hi(, %s0) +; CHECK-NEXT: st %s0, -56(, %s9) +; 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: st %s0, -48(, %s9) +; CHECK-NEXT: st %s9, -40(, %s9) +; CHECK-NEXT: st %s11, -24(, %s9) +; CHECK-NEXT: lea %s0, .LBB0_3@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s0, .LBB0_3@hi(, %s0) +; CHECK-NEXT: st %s0, -32(, %s9) +; CHECK-NEXT: or %s0, 1, (0)1 +; CHECK-NEXT: st %s0, -96(, %s9) +; CHECK-NEXT: lea %s0, _Unwind_SjLj_Register@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s12, _Unwind_SjLj_Register@hi(, %s0) +; CHECK-NEXT: lea %s0, -104(, %s9) +; CHECK-NEXT: bsic %s10, (, %s12) +; CHECK-NEXT: .Ltmp0: +; CHECK-NEXT: lea %s0, errorbar@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s12, errorbar@hi(, %s0) +; CHECK-NEXT: bsic %s10, (, %s12) +; CHECK-NEXT: .Ltmp1: +; CHECK-NEXT: # %bb.1: # %exit +; CHECK-NEXT: lea %s0, _Unwind_SjLj_Unregister@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s12, _Unwind_SjLj_Unregister@hi(, %s0) +; CHECK-NEXT: lea %s0, -104(, %s9) +; CHECK-NEXT: bsic %s10, (, %s12) +; CHECK-NEXT: or %s0, 0, (0)1 +; CHECK-NEXT: .LBB0_2: # %exit +; CHECK-NEXT: ld %s33, 168(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s32, 160(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s31, 152(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s30, 144(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s29, 136(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s28, 128(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s27, 120(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s26, 112(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s25, 104(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s24, 96(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s23, 88(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s22, 80(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s21, 72(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s20, 64(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s19, 56(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: ld %s18, 48(, %s9) # 8-byte Folded Reload +; CHECK-NEXT: or %s11, 0, %s9 +; CHECK-NEXT: ld %s10, 8(, %s11) +; CHECK-NEXT: ld %s9, (, %s11) +; CHECK-NEXT: b.l.t (, %s10) +; CHECK-NEXT: .LBB0_3: +; CHECK-NEXT: ldl.zx %s0, -96(, %s9) +; CHECK-NEXT: brgt.l 1, %s0, .LBB0_4 +; CHECK-NEXT: # %bb.5: +; CHECK-NEXT: lea %s0, abort@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s0, abort@hi(, %s0) +; CHECK-NEXT: bsic %s10, (, %s0) +; CHECK-NEXT: .LBB0_4: +; CHECK-NEXT: lea %s1, .LJTI0_0@lo +; CHECK-NEXT: and %s1, %s1, (32)0 +; CHECK-NEXT: lea.sl %s1, .LJTI0_0@hi(, %s1) +; CHECK-NEXT: sll %s0, %s0, 3 +; CHECK-NEXT: ld %s0, (%s0, %s1) +; CHECK-NEXT: b.l.t (, %s0) +; CHECK-NEXT: .LBB0_6: # %handle +; CHECK-NEXT: .Ltmp2: +; CHECK-NEXT: ld %s0, -88(, %s9) +; CHECK-NEXT: ld %s0, -80(, %s9) +; CHECK-NEXT: lea %s0, _Unwind_SjLj_Unregister@lo +; CHECK-NEXT: and %s0, %s0, (32)0 +; CHECK-NEXT: lea.sl %s12, _Unwind_SjLj_Unregister@hi(, %s0) +; CHECK-NEXT: lea %s0, -104(, %s9) +; CHECK-NEXT: bsic %s10, (, %s12) +; CHECK-NEXT: or %s0, 1, (0)1 +; CHECK-NEXT: br.l.t .LBB0_2 +; +; PIC-LABEL: foo: +; PIC: # %bb.0: # %entry +; PIC-NEXT: st %s9, (, %s11) +; PIC-NEXT: st %s10, 8(, %s11) +; PIC-NEXT: st %s15, 24(, %s11) +; PIC-NEXT: st %s16, 32(, %s11) +; PIC-NEXT: or %s9, 0, %s11 +; PIC-NEXT: lea %s11, -352(, %s11) +; PIC-NEXT: brge.l %s11, %s8, .LBB0_8 +; PIC-NEXT: # %bb.7: # %entry +; PIC-NEXT: ld %s61, 24(, %s14) +; PIC-NEXT: or %s62, 0, %s0 +; PIC-NEXT: lea %s63, 315 +; PIC-NEXT: shm.l %s63, (%s61) +; PIC-NEXT: shm.l %s8, 8(%s61) +; PIC-NEXT: shm.l %s11, 16(%s61) +; PIC-NEXT: monc +; PIC-NEXT: or %s0, 0, %s62 +; PIC-NEXT: .LBB0_8: # %entry +; PIC-NEXT: st %s18, 48(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s19, 56(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s20, 64(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s21, 72(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s22, 80(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s23, 88(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s24, 96(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s25, 104(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s26, 112(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s27, 120(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s28, 128(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s29, 136(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s30, 144(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s31, 152(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s32, 160(, %s9) # 8-byte Folded Spill +; PIC-NEXT: st %s33, 168(, %s9) # 8-byte Folded Spill +; PIC-NEXT: lea %s15, _GLOBAL_OFFSET_TABLE_@pc_lo(-24) +; PIC-NEXT: and %s15, %s15, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s15, _GLOBAL_OFFSET_TABLE_@pc_hi(%s16, %s15) +; PIC-NEXT: lea %s0, __gxx_personality_sj0@got_lo +; PIC-NEXT: and %s0, %s0, (32)0 +; PIC-NEXT: lea.sl %s0, __gxx_personality_sj0@got_hi(, %s0) +; PIC-NEXT: ld %s0, (%s0, %s15) +; PIC-NEXT: st %s0, -56(, %s9) +; PIC-NEXT: lea %s0, GCC_except_table0@gotoff_lo +; PIC-NEXT: and %s0, %s0, (32)0 +; PIC-NEXT: lea.sl %s0, GCC_except_table0@gotoff_hi(%s0, %s15) +; PIC-NEXT: st %s0, -48(, %s9) +; PIC-NEXT: st %s9, -40(, %s9) +; PIC-NEXT: st %s11, -24(, %s9) +; PIC-NEXT: lea %s0, .LBB0_3@gotoff_lo +; PIC-NEXT: and %s0, %s0, (32)0 +; PIC-NEXT: lea.sl %s0, .LBB0_3@gotoff_hi(%s0, %s15) +; PIC-NEXT: st %s0, -32(, %s9) +; PIC-NEXT: or %s0, 1, (0)1 +; PIC-NEXT: st %s0, -96(, %s9) +; PIC-NEXT: lea %s12, _Unwind_SjLj_Register@plt_lo(-24) +; PIC-NEXT: and %s12, %s12, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s12, _Unwind_SjLj_Register@plt_hi(%s16, %s12) +; PIC-NEXT: lea %s0, -104(, %s9) +; PIC-NEXT: bsic %s10, (, %s12) +; PIC-NEXT: .Ltmp0: +; PIC-NEXT: lea %s12, errorbar@plt_lo(-24) +; PIC-NEXT: and %s12, %s12, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s12, errorbar@plt_hi(%s16, %s12) +; PIC-NEXT: bsic %s10, (, %s12) +; PIC-NEXT: .Ltmp1: +; PIC-NEXT: # %bb.1: # %exit +; PIC-NEXT: lea %s12, _Unwind_SjLj_Unregister@plt_lo(-24) +; PIC-NEXT: and %s12, %s12, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s12, _Unwind_SjLj_Unregister@plt_hi(%s16, %s12) +; PIC-NEXT: lea %s0, -104(, %s9) +; PIC-NEXT: bsic %s10, (, %s12) +; PIC-NEXT: or %s0, 0, (0)1 +; PIC-NEXT: .LBB0_2: # %exit +; PIC-NEXT: ld %s33, 168(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s32, 160(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s31, 152(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s30, 144(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s29, 136(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s28, 128(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s27, 120(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s26, 112(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s25, 104(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s24, 96(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s23, 88(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s22, 80(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s21, 72(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s20, 64(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s19, 56(, %s9) # 8-byte Folded Reload +; PIC-NEXT: ld %s18, 48(, %s9) # 8-byte Folded Reload +; PIC-NEXT: or %s11, 0, %s9 +; PIC-NEXT: ld %s16, 32(, %s11) +; PIC-NEXT: ld %s15, 24(, %s11) +; PIC-NEXT: ld %s10, 8(, %s11) +; PIC-NEXT: ld %s9, (, %s11) +; PIC-NEXT: b.l.t (, %s10) +; PIC-NEXT: .LBB0_3: +; PIC-NEXT: ldl.zx %s0, -96(, %s9) +; PIC-NEXT: lea %s15, _GLOBAL_OFFSET_TABLE_@pc_lo(-24) +; PIC-NEXT: and %s15, %s15, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s15, _GLOBAL_OFFSET_TABLE_@pc_hi(%s16, %s15) +; PIC-NEXT: brgt.l 1, %s0, .LBB0_4 +; PIC-NEXT: # %bb.5: +; PIC-NEXT: lea %s0, abort@plt_lo(-24) +; PIC-NEXT: and %s0, %s0, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s0, abort@plt_hi(%s16, %s0) +; PIC-NEXT: bsic %s10, (, %s0) +; PIC-NEXT: .LBB0_4: +; PIC-NEXT: lea %s1, .LJTI0_0@gotoff_lo +; PIC-NEXT: and %s1, %s1, (32)0 +; PIC-NEXT: lea.sl %s1, .LJTI0_0@gotoff_hi(%s1, %s15) +; PIC-NEXT: sll %s0, %s0, 2 +; PIC-NEXT: ldl.zx %s0, (%s0, %s1) +; PIC-NEXT: lea %s1, foo@gotoff_lo +; PIC-NEXT: and %s1, %s1, (32)0 +; PIC-NEXT: lea.sl %s1, foo@gotoff_hi(%s1, %s15) +; PIC-NEXT: adds.l %s0, %s0, %s1 +; PIC-NEXT: b.l.t (, %s0) +; PIC-NEXT: .LBB0_6: # %handle +; PIC-NEXT: .Ltmp2: +; PIC-NEXT: ld %s0, -88(, %s9) +; PIC-NEXT: ld %s0, -80(, %s9) +; PIC-NEXT: lea %s12, _Unwind_SjLj_Unregister@plt_lo(-24) +; PIC-NEXT: and %s12, %s12, (32)0 +; PIC-NEXT: sic %s16 +; PIC-NEXT: lea.sl %s12, _Unwind_SjLj_Unregister@plt_hi(%s16, %s12) +; PIC-NEXT: lea %s0, -104(, %s9) +; PIC-NEXT: bsic %s10, (, %s12) +; PIC-NEXT: or %s0, 1, (0)1 +; PIC-NEXT: br.l.t .LBB0_2 +; PIC-NEXT: .Lfunc_end0: +; PIC-NEXT: .size foo, .Lfunc_end0-foo +; PIC-NEXT: .section .rodata,"a",@progbits +; PIC-NEXT: .p2align 2 +; PIC-NEXT: .LJTI0_0: +; PIC-NEXT: .4byte .LBB0_6-foo +; PIC-NEXT: .section .gcc_except_table,"a",@progbits +; PIC-NEXT: .p2align 2 +; PIC-NEXT: GCC_except_table0: +; PIC-NEXT: .Lexception0: +; PIC-NEXT: .byte 255 # @LPStart Encoding = omit +; PIC-NEXT: .byte 0 # @TType Encoding = absptr +; PIC-NEXT: .uleb128 .Lttbase0-.Lttbaseref0 +; PIC-NEXT: .Lttbaseref0: +; PIC-NEXT: .byte 3 # Call site Encoding = udata4 +; PIC-NEXT: .uleb128 .Lcst_end0-.Lcst_begin0 +; PIC-NEXT: .Lcst_begin0: +; PIC-NEXT: .byte 0 # >> Call Site 0 << +; PIC-NEXT: # On exception at call site 0 +; PIC-NEXT: .byte 1 # Action: 1 +; PIC-NEXT: .Lcst_end0: +; PIC-NEXT: .byte 1 # >> Action Record 1 << +; PIC-NEXT: # Catch TypeInfo 1 +; PIC-NEXT: .byte 0 # No further actions +; PIC-NEXT: .p2align 2 +; PIC-NEXT: # >> Catch TypeInfos << +; PIC-NEXT: .8byte SomeGlobal # TypeInfo 1 +; PIC-NEXT: .Lttbase0: +; PIC-NEXT: .p2align 2 +; PIC-NEXT: # -- End function +entry: + invoke void @errorbar() to label %exit unwind label %handle + +handle: + %error = landingpad { i8*, i32 } catch i8* @SomeGlobal + ret i32 1 + +exit: + ret i32 0 +} + +declare dso_local void @errorbar() local_unnamed_addr + +declare dso_local i32 @__gxx_personality_sj0(...) diff --git a/llvm/test/CodeGen/VE/Scalar/sjlj_except.ll b/llvm/test/CodeGen/VE/Scalar/sjlj_except.ll deleted file mode 100644 --- a/llvm/test/CodeGen/VE/Scalar/sjlj_except.ll +++ /dev/null @@ -1,32 +0,0 @@ -; RUN: llc -mtriple=x86_64-unknown-unknown --exception-model=sjlj --print-after=sjljehprepare < %s 2>&1 | FileCheck --check-prefix=CHECK-X86 %s -; RUN: (llc -mtriple=ve-unknown-unknown --exception-model=sjlj --print-after=sjljehprepare < %s || true) 2>&1 | FileCheck --check-prefix=CHECK-VE %s - -@SomeGlobal = external dso_local global i8 - -define dso_local i32 @foo(i32 %arg) local_unnamed_addr personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) { -; CHECK-VE: *** IR Dump After SJLJ Exception Handling preparation *** -; CHECK-VE-NEXT: define dso_local i32 @foo(i32 %arg) local_unnamed_addr personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) { -; CHECK-VE-NEXT: entry: -; CHECK-VE-NEXT: %fn_context = alloca { i8*, i64, [4 x i64], i8*, i8*, [5 x i8*] }, align 8 -; CHECK-VE-NEXT: %arg.tmp = select i1 true, i32 %arg, i32 undef -; CHECK-VE-NEXT: %pers_fn_gep = getelementptr { i8*, i64, [4 x i64], i8*, i8*, [5 x i8*] }, { i8*, i64, [4 x i64], i8*, i8*, [5 x i8*] }* %fn_context, i32 0, i32 3 -; CHECK-X86: *** IR Dump After SJLJ Exception Handling preparation *** -; CHECK-X86-NEXT: define dso_local i32 @foo(i32 %arg) local_unnamed_addr personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) { -; CHECK-X86-NEXT: entry: -; CHECK-X86-NEXT: %fn_context = alloca { i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }, align 8 -; CHECK-X86-NEXT: %arg.tmp = select i1 true, i32 %arg, i32 undef -; CHECK-X86-NEXT: %pers_fn_gep = getelementptr { i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }, { i8*, i32, [4 x i32], i8*, i8*, [5 x i8*] }* %fn_context, i32 0, i32 3 -entry: - invoke void @errorbar() to label %exit unwind label %handle - -handle: - %error = landingpad { i8*, i32 } catch i8* @SomeGlobal - ret i32 1 - -exit: - ret i32 0 -} - -declare dso_local void @errorbar() local_unnamed_addr - -declare dso_local i32 @__gxx_personality_sj0(...)