1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +01:00

[VE] Support SJLJ exception related instructions

Support EH_SJLJ_LONGJMP, EH_SJLJ_SETJMP, and EH_SJLJ_SETUP_DISPATCH
for SjLj exception handling.  NC++ uses SjLj exception handling, so
implement it first.  Add regression tests also.

Reviewed By: simoll

Differential Revision: https://reviews.llvm.org/D94071
This commit is contained in:
Kazushi (Jam) Marukawa 2020-12-15 21:50:17 +09:00
parent c5a8d5ee85
commit b4ca317c5c
9 changed files with 1717 additions and 45 deletions

View File

@ -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 @@ void VETargetLowering::initSPUActions() {
/// } 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 @@ const char *VETargetLowering::getTargetNodeName(unsigned Opcode) const {
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 @@ SDValue VETargetLowering::lowerDYNAMIC_STACKALLOC(SDValue Op,
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 @@ SDValue VETargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
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 @@ SDValue VETargetLowering::getPICJumpTableRelocBase(SDValue Table,
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<MachineMemOperand *, 2> 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<MachineMemOperand *, 2> 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<unsigned, SmallVector<MachineBasicBlock *, 2>> 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<MachineBasicBlock *> LPadList;
SmallPtrSet<MachineBasicBlock *, 32> 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<MachineBasicBlock *, 8> 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<MachineBasicBlock *, 64> 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<MachineBasicBlock *, 8> 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<Register, bool> 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:

View File

@ -24,19 +24,22 @@ namespace VEISD {
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 @@ public:
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 @@ public:
void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &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.
Register prepareMBB(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
MachineBasicBlock *TargetBB, const DebugLoc &DL) const;
// Prepare function/variable address.
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

View File

@ -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

View File

@ -446,6 +446,17 @@ def retflag : SDNode<"VEISD::RET_FLAG", SDTNone,
def getGOT : Operand<iPTR>;
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<(i32 (atomic_swap_32 ADDRri:$src, i32:$new)),
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)>;

View File

@ -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*)

View File

@ -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
}

View File

@ -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)

View File

@ -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(...)

View File

@ -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(...)