[Sparc] Load address with SETHI

Hi,

I’m trying to implement __builtin_setjmp / __builtin_longjmp for Sparc processors. I think I’m very close, but I can’t work out how to issue BuildMI-type instructions to load the address of the recovery location (set in setjmp) into a register using the SETHI / OR combination. I can’t see any equivalent code anywhere else in Sparc.

I imagine this is similar if I try to make a CALLRi or CALLrr call, but looking through the code there isn’t yielding any obvious solution to me.

Would anyone be able to point me at a relevant piece of code that can do this, or is already doing it for Sparc?

Best Regards,
Chris Dewhurst / Lero, University of Limerick, Ireland.

SparcAsmParser::expandSET and SparcTargetLowering::makeAddress are the
two variants I can think of immediately.

Joerg

Some more information on what I have so far. I’ll actually focus on the longjmp side, as the problem is probably easier.

I need to get the SETHI / OR combination inserted where the comment “*** Need to use the SETHI / OR combination here. ***” appears in the code below, but I’m not sure that this is done anywhere near this piece of code, so I’ll include all the relevant parts that I can find of my current implementation.

First, some def’s in SparcInstrInfo.td:

def SPsjlj_longjmp: SDNode<“SPISD::EH_SJLJ_LONGJMP”,
SDTSPeh_sjlj_longjmp,
[SDNPHasChain, SDNPSideEffect]>;

let hasSideEffects = 1, isBarrier = 1, usesCustomInserter = 1 in {
let isTerminator = 1 in
def EH_SJLJ_LONGJMP32ri : Pseudo<(outs), (ins MEMri:$buf),
#EH_SJLJ_LONGJMP32”,
[(SPsjlj_longjmp ADDRri:$buf)]>,
Requires<[Is32Bit]>;
def EH_SJLJ_LONGJMP32rr : Pseudo<(outs), (ins MEMrr:$buf),
#EH_SJLJ_LONGJMP32”,
[(SPsjlj_longjmp ADDRrr:$buf)]>,
Requires<[Is32Bit]>;
}

SparcISelLowering.cpp, of course, sets this as setOperationAction(ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom);

I also have these functions in SparcISelLowering.cpp:

SDValue SparcTargetLowering::LowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG,
const SparcTargetLowering &TLI, bool hasHardQuad) const {
SDLoc DL(Op);
return DAG.getNode(SPISD::EH_SJLJ_LONGJMP, DL, MVT::Other, Op.getOperand(0));
}

MachineBasicBlock * SparcTargetLowering::
EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB) const
{
switch (MI->getOpcode()) {
… [ Other code first]
case SP::EH_SJLJ_LONGJMP32rr:
case SP::EH_SJLJ_LONGJMP32ri:
return emitEHSjLjLongJmp(MI, BB);
}
}

MachineBasicBlock* SparcTargetLowering::
emitEHSjLjLongJmp(MachineInstr *MI,
MachineBasicBlock *MBB) const
{
DebugLoc DL = MI->getDebugLoc();
const TargetInstrInfo *TII = Subtarget->getInstrInfo();

MachineFunction *MF = MBB->getParent();
MachineRegisterInfo &MRI = MF->getRegInfo();
MachineInstrBuilder MIB;

// Memory Reference
MachineInstr::mmo_iterator MMOBegin = MI->memoperands_begin();
MachineInstr::mmo_iterator MMOEnd = MI->memoperands_end();

MVT PVT = getPointerTy(MF->getDataLayout());
unsigned PtrSize = PVT.getStoreSize();
assert(PVT == MVT::i32 && “Invalid Pointer Size!”);

unsigned ArgReg = MI->getOperand(0).getReg();
unsigned Buf = MRI.createVirtualRegister(&SP::IntRegsRegClass);
unsigned JmpLoc = MRI.createVirtualRegister(&SP::IntRegsRegClass);

// *** Need to use the SETHI / OR combination here. ***

// MIB = BuildMI(*MBB, MI, DL, TII->get(SP::ORri))
// .addReg(Buf)
// .addReg(ArgReg)
// .addImm(0);
// MIB.setMemRefs(MMOBegin, MMOEnd);

// Instruction to load jmp location
MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri))
.addReg(JmpLoc)
.addReg(Buf)
.addImm(PtrSize);
MIB.setMemRefs(MMOBegin, MMOEnd);

// TO DO: If we do 64-bit handling, this perhaps should be FLUSHW, not TA 3
const long int TRAP_COND_ALWAYS = 0x08;
MIB = BuildMI(*MBB, MI, DL, TII->get(SP::TRAPri), SP::G0).addImm(3).addImm(TRAP_COND_ALWAYS);

// Instruction to restore FP
const unsigned FP = SP::I6;
MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri))
.addReg(FP)
.addReg(Buf)
.addImm(0);
MIB.setMemRefs(MMOBegin, MMOEnd);

// Instruction to restore SP
const unsigned SP = SP::O6;
MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri))
.addReg(SP)
.addReg(Buf)
.addImm(2 * PtrSize);
MIB.setMemRefs(MMOBegin, MMOEnd);

// Instruction to restore I7
MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri))
.addReg(SP::I7)
.addReg(Buf)
.addImm(3 * PtrSize);
MIB.setMemRefs(MMOBegin, MMOEnd);

// Jump to I7
BuildMI(*MBB, MI, DL, TII->get(SP::JMPLrr)).addReg(SP::G0).addReg(JmpLoc).addReg(SP::G0);

MI->eraseFromParent();
return MBB;
}

I don't understand what exactly you want to materialize here. Shouldn't
the address of the buffer already be an operand at this point?

Joerg