<html dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" id="owaParaStyle"></style>
</head>
<body fpstyle="1" ocsi="0">
<div style="direction: ltr;font-family: Tahoma;color: #000000;font-size: 10pt;">Hi,
<div><br>
</div>
<div>I'm implementing __builtin_setjmp and __builtin_longjmp for Sparc 32 bit processors (64 bit later, time allowing).</div>
<div><br>
</div>
<div>I'm basing the code on the PowerPC version, which itself is based on the X86 version.</div>
<div><br>
</div>
<div>This code is very nearly working, and I've had it working for -O0 optimisation (with a slightly different version to that below), so I know it's close.</div>
<div><br>
</div>
<div>However, the PowerPC code uses a trick to ensure that optimisations retain the jump targets required, using a Pseudo instruction "EH_SjLj_Setup" that expands simply to an IR comment, but makes the compiler think it needs to preserve the jump target address
 - which it does, to ensure that the jump target remains valid after any optimisations. Some of the comments at this URL relating to the PowerPC version help with understanding this: http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20130325/169366.html<a href="http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20130325/169366.html" target="_blank" style="font-size: 10pt;">http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20130325/169366.html</a></div>
<div><br>
</div>
<div>However, when compiling for Sparc, I get a "Not supported instr" for the instruction EH_SjLj_Setup. Of course, it doesn't exist in reality, but neither does it for PowerPC, so I can't understand why there's a difference between how it's handled for the
 two targets.</div>
<div><br>
</div>
<div>I've included a full diff for the setjmp/longjmp change I'm making, but you'll find the most pertinent lines if you search for the text "EH_SjLj_Setup". You'll find very similar code in the PowerPC backend.</div>
<div><br>
</div>
<div>If anyone spots any other mistakes or has comments, I'd be glad to know about them at this stage too. Note: I'll comment as best I can how this works within the code when I get it working.</div>
<div><br>
</div>
<div>
<div>Index: SparcISelLowering.cpp</div>
<div>===================================================================</div>
<div>*** SparcISelLowering.cpp<span class="Apple-tab-span" style="white-space:pre">
</span>(revision 267677)</div>
<div>--- SparcISelLowering.cpp<span class="Apple-tab-span" style="white-space:pre">
</span>(working copy)</div>
<div>***************</div>
<div>*** 1586,1591 ****</div>
<div>--- 1586,1594 ----</div>
<div>    setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);</div>
<div>    setOperationAction(ISD::SELECT_CC, MVT::f128, Custom);</div>
<div>  </div>
<div>+   setOperationAction(ISD::EH_SJLJ_SETJMP, MVT::i32, Custom);</div>
<div>+   setOperationAction(ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom);</div>
<div>+ </div>
<div>    if (Subtarget->is64Bit()) {</div>
<div>      setOperationAction(ISD::ADDC, MVT::i64, Custom);</div>
<div>      setOperationAction(ISD::ADDE, MVT::i64, Custom);</div>
<div>***************</div>
<div>*** 1808,1835 ****</div>
<div>  </div>
<div>  const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {</div>
<div>    switch ((SPISD::NodeType)Opcode) {</div>
<div>!   case SPISD::FIRST_NUMBER: break;</div>
<div>!   case SPISD::CMPICC:     return "SPISD::CMPICC";</div>
<div>!   case SPISD::CMPFCC:     return "SPISD::CMPFCC";</div>
<div>!   case SPISD::BRICC:      return "SPISD::BRICC";</div>
<div>!   case SPISD::BRXCC:      return "SPISD::BRXCC";</div>
<div>!   case SPISD::BRFCC:      return "SPISD::BRFCC";</div>
<div>!   case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC";</div>
<div>!   case SPISD::SELECT_XCC: return "SPISD::SELECT_XCC";</div>
<div>!   case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC";</div>
<div>!   case SPISD::Hi:         return "SPISD::Hi";</div>
<div>!   case SPISD::Lo:         return "SPISD::Lo";</div>
<div>!   case SPISD::FTOI:       return "SPISD::FTOI";</div>
<div>!   case SPISD::ITOF:       return "SPISD::ITOF";</div>
<div>!   case SPISD::FTOX:       return "SPISD::FTOX";</div>
<div>!   case SPISD::XTOF:       return "SPISD::XTOF";</div>
<div>!   case SPISD::CALL:       return "SPISD::CALL";</div>
<div>!   case SPISD::RET_FLAG:   return "SPISD::RET_FLAG";</div>
<div>    case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG";</div>
<div>!   case SPISD::FLUSHW:     return "SPISD::FLUSHW";</div>
<div>!   case SPISD::TLS_ADD:    return "SPISD::TLS_ADD";</div>
<div>!   case SPISD::TLS_LD:     return "SPISD::TLS_LD";</div>
<div>!   case SPISD::TLS_CALL:   return "SPISD::TLS_CALL";</div>
<div>    }</div>
<div>    return nullptr;</div>
<div>  }</div>
<div>--- 1811,1840 ----</div>
<div>  </div>
<div>  const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {</div>
<div>    switch ((SPISD::NodeType)Opcode) {</div>
<div>!   case SPISD::FIRST_NUMBER:    break;</div>
<div>!   case SPISD::CMPICC:          return "SPISD::CMPICC";</div>
<div>!   case SPISD::CMPFCC:          return "SPISD::CMPFCC";</div>
<div>!   case SPISD::BRICC:           return "SPISD::BRICC";</div>
<div>!   case SPISD::BRXCC:           return "SPISD::BRXCC";</div>
<div>!   case SPISD::BRFCC:           return "SPISD::BRFCC";</div>
<div>!   case SPISD::SELECT_ICC:      return "SPISD::SELECT_ICC";</div>
<div>!   case SPISD::SELECT_XCC:      return "SPISD::SELECT_XCC";</div>
<div>!   case SPISD::SELECT_FCC:      return "SPISD::SELECT_FCC";</div>
<div>!   case SPISD::EH_SJLJ_SETJMP:  return "SPISD::EH_SJLJ_SETJMP";</div>
<div>!   case SPISD::EH_SJLJ_LONGJMP: return "SPISD::EH_SJLJ_LONGJMP";</div>
<div>!   case SPISD::Hi:              return "SPISD::Hi";</div>
<div>!   case SPISD::Lo:              return "SPISD::Lo";</div>
<div>!   case SPISD::FTOI:            return "SPISD::FTOI";</div>
<div>!   case SPISD::ITOF:            return "SPISD::ITOF";</div>
<div>!   case SPISD::FTOX:            return "SPISD::FTOX";</div>
<div>!   case SPISD::XTOF:            return "SPISD::XTOF";</div>
<div>!   case SPISD::CALL:            return "SPISD::CALL";</div>
<div>!   case SPISD::RET_FLAG:        return "SPISD::RET_FLAG";</div>
<div>    case SPISD::GLOBAL_BASE_REG: return "SPISD::GLOBAL_BASE_REG";</div>
<div>!   case SPISD::FLUSHW:          return "SPISD::FLUSHW";</div>
<div>!   case SPISD::TLS_ADD:         return "SPISD::TLS_ADD";</div>
<div>!   case SPISD::TLS_LD:          return "SPISD::TLS_LD";</div>
<div>!   case SPISD::TLS_CALL:        return "SPISD::TLS_CALL";</div>
<div>    }</div>
<div>    return nullptr;</div>
<div>  }</div>
<div>***************</div>
<div>*** 2492,2497 ****</div>
<div>--- 2497,2516 ----</div>
<div>                       DAG.getConstant(SPCC, dl, MVT::i32), CompareFlag);</div>
<div>  }</div>
<div>  </div>
<div>+ SDValue SparcTargetLowering::LowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG,</div>
<div>+     const SparcTargetLowering &TLI) const {</div>
<div>+   SDLoc DL(Op);</div>
<div>+   return DAG.getNode(SPISD::EH_SJLJ_SETJMP, DL,</div>
<div>+       DAG.getVTList(MVT::i32, MVT::Other), Op.getOperand(0), Op.getOperand(1));</div>
<div>+ </div>
<div>+ }</div>
<div>+ </div>
<div>+ SDValue SparcTargetLowering::LowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG,</div>
<div>+     const SparcTargetLowering &TLI) const {</div>
<div>+   SDLoc DL(Op);</div>
<div>+   return DAG.getNode(SPISD::EH_SJLJ_LONGJMP, DL, MVT::Other, Op.getOperand(0), Op.getOperand(1));</div>
<div>+ }</div>
<div>+ </div>
<div>  static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG,</div>
<div>                              const SparcTargetLowering &TLI) {</div>
<div>    MachineFunction &MF = DAG.getMachineFunction();</div>
<div>***************</div>
<div>*** 3004,3009 ****</div>
<div>--- 3023,3030 ----</div>
<div>                                                    hasHardQuad);</div>
<div>    case ISD::SELECT_CC:          return LowerSELECT_CC(Op, DAG, *this,</div>
<div>                                                        hasHardQuad);</div>
<div>+   case ISD::EH_SJLJ_SETJMP:     return LowerEH_SJLJ_SETJMP(Op, DAG, *this);</div>
<div>+   case ISD::EH_SJLJ_LONGJMP:    return LowerEH_SJLJ_LONGJMP(Op, DAG, *this);</div>
<div>    case ISD::VASTART:            return LowerVASTART(Op, DAG, *this);</div>
<div>    case ISD::VAARG:              return LowerVAARG(Op, DAG);</div>
<div>    case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG,</div>
<div>***************</div>
<div>*** 3052,3057 ****</div>
<div>--- 3073,3085 ----</div>
<div>    case SP::SELECT_CC_DFP_FCC:</div>
<div>    case SP::SELECT_CC_QFP_FCC:</div>
<div>      return expandSelectCC(MI, BB, SP::FBCOND);</div>
<div>+   case SP::EH_SJLJ_SETJMP32ri:</div>
<div>+   case SP::EH_SJLJ_SETJMP32rr:</div>
<div>+     return emitEHSjLjSetJmp(MI, BB);</div>
<div>+   case SP::EH_SJLJ_LONGJMP32rr:</div>
<div>+   case SP::EH_SJLJ_LONGJMP32ri:</div>
<div>+     return emitEHSjLjLongJmp(MI, BB);</div>
<div>+ </div>
<div>    }</div>
<div>  }</div>
<div>  </div>
<div>***************</div>
<div>*** 3114,3119 ****</div>
<div>--- 3142,3352 ----</div>
<div>    return BB;</div>
<div>  }</div>
<div>  </div>
<div>+ MachineBasicBlock* SparcTargetLowering::</div>
<div>+ emitEHSjLjLongJmp(MachineInstr *MI,</div>
<div>+                   MachineBasicBlock *MBB) const</div>
<div>+ {</div>
<div>+   DebugLoc DL = MI->getDebugLoc();</div>
<div>+   const TargetInstrInfo *TII = Subtarget->getInstrInfo();</div>
<div>+ </div>
<div>+   MachineFunction *MF = MBB->getParent();</div>
<div>+   MachineRegisterInfo &MRI = MF->getRegInfo();</div>
<div>+   MachineInstrBuilder MIB;</div>
<div>+ </div>
<div>+   // Memory Reference</div>
<div>+   MachineInstr::mmo_iterator MMOBegin = MI->memoperands_begin();</div>
<div>+   MachineInstr::mmo_iterator MMOEnd = MI->memoperands_end();</div>
<div>+ </div>
<div>+   MVT PVT = getPointerTy(MF->getDataLayout());</div>
<div>+   unsigned PtrSize = PVT.getStoreSize();</div>
<div>+   assert(PVT == MVT::i32 && "Invalid Pointer Size!");</div>
<div>+ </div>
<div>+   unsigned Buf = MI->getOperand(0).getReg();</div>
<div>+   unsigned JmpLoc = MRI.createVirtualRegister(&SP::IntRegsRegClass);</div>
<div>+ </div>
<div>+   // Instruction to load jmp location</div>
<div>+   MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri))</div>
<div>+             .addReg(JmpLoc, RegState::Define)</div>
<div>+             .addReg(Buf)</div>
<div>+             .addImm(PtrSize);</div>
<div>+   MIB.setMemRefs(MMOBegin, MMOEnd);</div>
<div>+ </div>
<div>+   // TO DO: If we do 64-bit handling, this perhaps should be FLUSHW, not TA 3</div>
<div>+   const long int TRAP_COND_ALWAYS = 0x08;</div>
<div>+   MIB = BuildMI(*MBB, MI, DL, TII->get(SP::TRAPri), SP::G0).addImm(3).addImm(TRAP_COND_ALWAYS);</div>
<div>+ </div>
<div>+   // Instruction to restore FP</div>
<div>+   const unsigned FP  = SP::I6;</div>
<div>+   MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri))</div>
<div>+             .addReg(FP)</div>
<div>+             .addReg(Buf)</div>
<div>+             .addImm(0);</div>
<div>+   MIB.setMemRefs(MMOBegin, MMOEnd);</div>
<div>+ </div>
<div>+   // Instruction to restore SP</div>
<div>+   const unsigned SP  = SP::O6;</div>
<div>+   MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri))</div>
<div>+             .addReg(SP)</div>
<div>+             .addReg(Buf)</div>
<div>+             .addImm(2 * PtrSize);</div>
<div>+   MIB.setMemRefs(MMOBegin, MMOEnd);</div>
<div>+ </div>
<div>+   // Instruction to restore I7</div>
<div>+   MIB = BuildMI(*MBB, MI, DL, TII->get(SP::LDri))</div>
<div>+             .addReg(SP::I7)</div>
<div>+             .addReg(Buf, RegState::Kill)</div>
<div>+             .addImm(3 * PtrSize);</div>
<div>+   MIB.setMemRefs(MMOBegin, MMOEnd);</div>
<div>+ </div>
<div>+   // Jump to JmpLoc</div>
<div>+   BuildMI(*MBB, MI, DL, TII->get(SP::JMPLrr)).addReg(SP::G0).addReg(JmpLoc, RegState::Kill).addReg(SP::G0);</div>
<div>+ </div>
<div>+   MI->eraseFromParent();</div>
<div>+   return MBB;</div>
<div>+ }</div>
<div>+ </div>
<div>+ MachineBasicBlock* SparcTargetLowering::</div>
<div>+ emitEHSjLjSetJmp(MachineInstr *MI,</div>
<div>+                  MachineBasicBlock *MBB) const</div>
<div>+ {</div>
<div>+   DebugLoc DL = MI->getDebugLoc();</div>
<div>+   const TargetInstrInfo *TII = Subtarget->getInstrInfo();</div>
<div>+ </div>
<div>+   MachineFunction *MF = MBB->getParent();</div>
<div>+   MachineRegisterInfo &MRI = MF->getRegInfo();</div>
<div>+ </div>
<div>+   // Memory Reference</div>
<div>+   MachineInstr::mmo_iterator MMOBegin = MI->memoperands_begin();</div>
<div>+   MachineInstr::mmo_iterator MMOEnd = MI->memoperands_end();</div>
<div>+ </div>
<div>+   MVT PVT = getPointerTy(MF->getDataLayout());</div>
<div>+   unsigned PtrSize = PVT.getStoreSize();</div>
<div>+   assert(PVT == MVT::i32 && "Invalid Pointer Size!");</div>
<div>+ </div>
<div>+   // Need to "fix-up" this value later.</div>
<div>+   unsigned DstReg = MI->getOperand(0).getReg();</div>
<div>+   const TargetRegisterClass *RC = MRI.getRegClass(DstReg);</div>
<div>+   assert(RC->hasType(MVT::i32) && "Invalid destination!");</div>
<div>+   unsigned mainDstReg = MRI.createVirtualRegister(RC);</div>
<div>+   unsigned restoreDstReg = MRI.createVirtualRegister(RC);</div>
<div>+ </div>
<div>+   // For v = setjmp(buf), we generate</div>
<div>+   //</div>
<div>+   // thisMBB:</div>
<div>+   //  SjLjSetup mainMBB</div>
<div>+   //  bl mainMBB</div>
<div>+   //  v_restore = 1</div>
<div>+   //  b sinkMBB</div>
<div>+   //</div>
<div>+   // mainMBB:</div>
<div>+   //  buf[LabelOffset] = restoreMBB <-- takes address of restoreMBB</div>
<div>+   //  v_main = 0</div>
<div>+   //</div>
<div>+   // sinkMBB:</div>
<div>+   //  v = phi(main, restore)</div>
<div>+ </div>
<div>+ </div>
<div>+   const BasicBlock *BB = MBB->getBasicBlock();</div>
<div>+   MachineFunction::iterator It = ++MBB->getIterator();</div>
<div>+   MachineBasicBlock *thisMBB = MBB;</div>
<div>+   const BasicBlock* mainBB = BasicBlock::Create(BB->getContext(), "setjmp.main");</div>
<div>+   MachineBasicBlock *mainMBB = MF->CreateMachineBasicBlock(mainBB);</div>
<div>+   mainMBB->setHasAddressTaken();</div>
<div>+   const BasicBlock* sinkBB = BasicBlock::Create(BB->getContext(), "setjmp.sink");</div>
<div>+   MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(sinkBB);</div>
<div>+   sinkMBB->setHasAddressTaken();</div>
<div>+ </div>
<div>+   MF->insert(It, mainMBB);</div>
<div>+   MF->insert(It, sinkMBB);</div>
<div>+ </div>
<div>+   // Transfer the remainder of BB and its successor edges to sinkMBB.</div>
<div>+   sinkMBB->splice(sinkMBB->begin(), MBB,</div>
<div>+                   std::next(MachineBasicBlock::iterator(MI)),</div>
<div>+                   MBB->end());</div>
<div>+   sinkMBB->transferSuccessorsAndUpdatePHIs(MBB);</div>
<div>+ </div>
<div>+   MachineInstrBuilder MIB;</div>
<div>+ </div>
<div>+   unsigned LabelReg = MRI.createVirtualRegister(&SP::IntRegsRegClass);</div>
<div>+   unsigned BufReg = MI->getOperand(1).getReg();</div>
<div>+ </div>
<div>+   MIB = BuildMI(*thisMBB, MI, DL, TII->get(SP::SETHIi))</div>
<div>+             .addReg(LabelReg, RegState::Define)</div>
<div>+             .addMBB(sinkMBB, SparcMCExpr::VK_Sparc_HI);</div>
<div>+   MIB.setMemRefs(MMOBegin, MMOEnd);</div>
<div>+ </div>
<div>+   MIB = BuildMI(*thisMBB, MI, DL, TII->get(SP::ADDri))</div>
<div>+             .addReg(LabelReg)</div>
<div>+             .addReg(LabelReg)</div>
<div>+             .addMBB(sinkMBB, SparcMCExpr::VK_Sparc_LO);</div>
<div>+   MIB.setMemRefs(MMOBegin, MMOEnd);</div>
<div>+ </div>
<div>+   // Instruction to store FP</div>
<div>+   const unsigned FP  = SP::I6;</div>
<div>+   MIB = BuildMI(*thisMBB, MI, DL, TII->get(SP::STri))</div>
<div>+             .addReg(BufReg)</div>
<div>+             .addImm(0)</div>
<div>+             .addReg(FP);</div>
<div>+   MIB.setMemRefs(MMOBegin, MMOEnd);</div>
<div>+ </div>
<div>+   // Instruction to store jmp location</div>
<div>+   MIB = BuildMI(*thisMBB, MI, DL, TII->get(SP::STri))</div>
<div>+             .addReg(BufReg)</div>
<div>+             .addImm(PtrSize)</div>
<div>+             .addReg(LabelReg, RegState::Kill);</div>
<div>+   MIB.setMemRefs(MMOBegin, MMOEnd);</div>
<div>+ </div>
<div>+   // Instruction to store SP</div>
<div>+   const unsigned SP  = SP::O6;</div>
<div>+   MIB = BuildMI(*thisMBB, MI, DL, TII->get(SP::STri))</div>
<div>+             .addReg(BufReg)</div>
<div>+             .addImm(2 * PtrSize)</div>
<div>+             .addReg(SP);</div>
<div>+   MIB.setMemRefs(MMOBegin, MMOEnd);</div>
<div>+ </div>
<div>+   // Instruction to store I7</div>
<div>+   MIB = BuildMI(*thisMBB, MI, DL, TII->get(SP::STri))</div>
<div>+             .addReg(BufReg)</div>
<div>+             .addImm(3 * PtrSize)</div>
<div>+             .addReg(SP::I7);</div>
<div>+   MIB.setMemRefs(MMOBegin, MMOEnd);</div>
<div>+ </div>
<div>+ </div>
<div>+   // Setup</div>
<div>+   MIB = BuildMI(*thisMBB, MI, DL, TII->get(SP::BCOND)).addMBB(mainMBB).addImm(SPCC::ICC_A);</div>
<div>+   const SparcRegisterInfo* TRI = Subtarget->getRegisterInfo();</div>
<div>+   MIB.addRegMask(TRI->getNoPreservedMask());</div>
<div>+ </div>
<div>+   BuildMI(thisMBB, DL, TII->get(SP::LDri))</div>
<div>+               .addReg(restoreDstReg, RegState::Define)</div>
<div>+               .addImm(1)</div>
<div>+               .addReg(SP::G0);</div>
<div>+ </div>
<div>+   MIB = BuildMI(*thisMBB, MI, DL, TII->get(SP::EH_SjLj_Setup)).addMBB(mainMBB);</div>
<div>+   MIB = BuildMI(*thisMBB, MI, DL, TII->get(SP::BCOND)).addMBB(sinkMBB).addImm(SPCC::ICC_A);</div>
<div>+ </div>
<div>+   thisMBB->addSuccessor(mainMBB, BranchProbability::getZero());</div>
<div>+   thisMBB->addSuccessor(sinkMBB, BranchProbability::getOne());</div>
<div>+ </div>
<div>+ </div>
<div>+   // mainMBB:</div>
<div>+   BuildMI(mainMBB, DL, TII->get(SP::ORrr))</div>
<div>+              .addReg(mainDstReg, RegState::Define)</div>
<div>+              .addReg(SP::G0)</div>
<div>+              .addReg(SP::G0);</div>
<div>+   mainMBB->addSuccessor(sinkMBB);</div>
<div>+ </div>
<div>+ </div>
<div>+   // sinkMBB:</div>
<div>+   BuildMI(*sinkMBB, sinkMBB->begin(), DL,</div>
<div>+           TII->get(SP::PHI), DstReg)</div>
<div>+     .addReg(mainDstReg).addMBB(mainMBB)</div>
<div>+     .addReg(restoreDstReg).addMBB(thisMBB);</div>
<div>+ </div>
<div>+   MI->eraseFromParent();</div>
<div>+   return sinkMBB;</div>
<div>+ }</div>
<div>+ </div>
<div>  //===----------------------------------------------------------------------===//</div>
<div>  //                         Sparc Inline Assembly Support</div>
<div>  //===----------------------------------------------------------------------===//</div>
<div>Index: SparcISelLowering.h</div>
<div>===================================================================</div>
<div>*** SparcISelLowering.h<span class="Apple-tab-span" style="white-space:pre">
</span>(revision 267677)</div>
<div>--- SparcISelLowering.h<span class="Apple-tab-span" style="white-space:pre">
</span>(working copy)</div>
<div>***************</div>
<div>*** 33,38 ****</div>
<div>--- 33,41 ----</div>
<div>        SELECT_XCC,  // Select between two values using the current XCC flags.</div>
<div>        SELECT_FCC,  // Select between two values using the current FCC flags.</div>
<div>  </div>
<div>+       EH_SJLJ_SETJMP,  // builtin setjmp operation</div>
<div>+       EH_SJLJ_LONGJMP, // builtin longjmp operation</div>
<div>+ </div>
<div>        Hi, Lo,      // Hi/Lo operations, typically on a global address.</div>
<div>  </div>
<div>        FTOI,        // FP to Int within a FP register.</div>
<div>***************</div>
<div>*** 161,166 ****</div>
<div>--- 164,174 ----</div>
<div>      SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;</div>
<div>      SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;</div>
<div>  </div>
<div>+     SDValue LowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG,</div>
<div>+                                 const SparcTargetLowering &TLI) const ;</div>
<div>+     SDValue LowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG,</div>
<div>+                                  const SparcTargetLowering &TLI) const ;</div>
<div>+ </div>
<div>      unsigned getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const;</div>
<div>      SDValue withTargetFlags(SDValue Op, unsigned TF, SelectionDAG &DAG) const;</div>
<div>      SDValue makeHiLoPair(SDValue Op, unsigned HiTF, unsigned LoTF,</div>
<div>***************</div>
<div>*** 205,210 ****</div>
<div>--- 213,222 ----</div>
<div>                                         MachineBasicBlock *BB,</div>
<div>                                         unsigned Opcode,</div>
<div>                                         unsigned CondCode = 0) const;</div>
<div>+     MachineBasicBlock *emitEHSjLjSetJmp(MachineInstr *MI,</div>
<div>+                                         MachineBasicBlock *MBB) const;</div>
<div>+     MachineBasicBlock *emitEHSjLjLongJmp(MachineInstr *MI,</div>
<div>+                                          MachineBasicBlock *MBB) const;</div>
<div>    };</div>
<div>  } // end namespace llvm</div>
<div>  </div>
<div>Index: SparcInstrInfo.td</div>
<div>===================================================================</div>
<div>*** SparcInstrInfo.td<span class="Apple-tab-span" style="white-space:pre"> </span>
(revision 267677)</div>
<div>--- SparcInstrInfo.td<span class="Apple-tab-span" style="white-space:pre"> </span>
(working copy)</div>
<div>***************</div>
<div>*** 154,159 ****</div>
<div>--- 154,162 ----</div>
<div>  def SDTSPtlsld :</div>
<div>  SDTypeProfile<1, 2, [SDTCisPtrTy<0>, SDTCisPtrTy<1>]>;</div>
<div>  </div>
<div>+ def SDTSPeh_sjlj_setjmp : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisPtrTy<1>]>;</div>
<div>+ def SDTSPeh_sjlj_longjmp: SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;</div>
<div>+ </div>
<div>  def SPcmpicc : SDNode<"SPISD::CMPICC", SDTSPcmpicc, [SDNPOutGlue]>;</div>
<div>  def SPcmpfcc : SDNode<"SPISD::CMPFCC", SDTSPcmpfcc, [SDNPOutGlue]>;</div>
<div>  def SPbricc : SDNode<"SPISD::BRICC", SDTSPbrcc, [SDNPHasChain, SDNPInGlue]>;</div>
<div>***************</div>
<div>*** 172,177 ****</div>
<div>--- 175,187 ----</div>
<div>  def SPselectxcc : SDNode<"SPISD::SELECT_XCC", SDTSPselectcc, [SDNPInGlue]>;</div>
<div>  def SPselectfcc : SDNode<"SPISD::SELECT_FCC", SDTSPselectcc, [SDNPInGlue]>;</div>
<div>  </div>
<div>+ def SPsjlj_setjmp: SDNode<"SPISD::EH_SJLJ_SETJMP",</div>
<div>+                           SDTSPeh_sjlj_setjmp,</div>
<div>+                           [SDNPHasChain, SDNPSideEffect]>;</div>
<div>+ def SPsjlj_longjmp: SDNode<"SPISD::EH_SJLJ_LONGJMP",</div>
<div>+                            SDTSPeh_sjlj_longjmp,</div>
<div>+                            [SDNPHasChain, SDNPSideEffect]>;</div>
<div>+ </div>
<div>  //  These are target-independent nodes, but have target-specific formats.</div>
<div>  def SDT_SPCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>;</div>
<div>  def SDT_SPCallSeqEnd   : SDCallSeqEnd<[ SDTCisVT<0, i32>,</div>
<div>***************</div>
<div>*** 447,452 ****</div>
<div>--- 457,489 ----</div>
<div>              [(set f128:$dst, (SPselectfcc f128:$T, f128:$F, imm:$Cond))]>;</div>
<div>  }</div>
<div>  </div>
<div>+ let hasSideEffects = 1, isBarrier = 1, usesCustomInserter = 1 in {</div>
<div>+   let Defs = [WIM] in</div>
<div>+   def EH_SJLJ_SETJMP32ri  : Pseudo<(outs IntRegs:$dst), (ins MEMri:$buf),</div>
<div>+                             "#EH_SJLJ_SETJMP32",</div>
<div>+                             [(set i32:$dst, (SPsjlj_setjmp ADDRri:$buf))]>,</div>
<div>+                             Requires<[Is32Bit]>;</div>
<div>+   def EH_SJLJ_SETJMP32rr  : Pseudo<(outs IntRegs:$dst), (ins MEMrr:$buf),</div>
<div>+                             "#EH_SJLJ_SETJMP32",</div>
<div>+                             [(set i32:$dst, (SPsjlj_setjmp ADDRrr:$buf))]>,</div>
<div>+                             Requires<[Is32Bit]>;</div>
<div>+   let isTerminator = 1 in</div>
<div>+   def EH_SJLJ_LONGJMP32ri : Pseudo<(outs), (ins MEMri:$buf),</div>
<div>+                             "#EH_SJLJ_LONGJMP32",</div>
<div>+                             [(SPsjlj_longjmp ADDRri:$buf)]>,</div>
<div>+                             Requires<[Is32Bit]>;</div>
<div>+   def EH_SJLJ_LONGJMP32rr : Pseudo<(outs), (ins MEMrr:$buf),</div>
<div>+                             "#EH_SJLJ_LONGJMP32",</div>
<div>+                             [(SPsjlj_longjmp ADDRrr:$buf)]>,</div>
<div>+                             Requires<[Is32Bit]>;</div>
<div>+ }</div>
<div>+ </div>
<div>+ let isBranch = 1, isTerminator = 1 in {</div>
<div>+   def EH_SjLj_Setup : Pseudo<(outs), (ins brtarget:$ptr),</div>
<div>+                         "#EH_SjLj_Setup\t$ptr", []>,</div>
<div>+                         Requires<[Is32Bit]>;</div>
<div>+ }</div>
<div>+ </div>
<div>  // Section B.1 - Load Integer Instructions, p. 90</div>
<div>  let DecoderMethod = "DecodeLoadInt" in {</div>
<div>    defm LDSB : LoadA<"ldsb", 0b001001, 0b011001, sextloadi8,  IntRegs, i32>;</div>
</div>
<div><br>
</div>
<div><br>
</div>
</div>
</body>
</html>