[llvm-commits] [llvm] r165989 - in /llvm/trunk: lib/Target/X86/X86ISelDAGToDAG.cpp lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86ISelLowering.h lib/Target/X86/X86InstrCompiler.td lib/Target/X86/X86InstrInfo.td lib/Target/X86/X86RegisterInf
Rafael EspĂndola
rafael.espindola at gmail.com
Wed Oct 17 11:51:39 PDT 2012
This fixed http://llvm.org/pr4899?
On 15 October 2012 18:39, Michael Liao <michael.liao at intel.com> wrote:
> Author: hliao
> Date: Mon Oct 15 17:39:43 2012
> New Revision: 165989
>
> URL: http://llvm.org/viewvc/llvm-project?rev=165989&view=rev
> Log:
> Add __builtin_setjmp/_longjmp supprt in X86 backend
>
> - Besides used in SjLj exception handling, __builtin_setjmp/__longjmp is also
> used as a light-weight replacement of setjmp/longjmp which are used to
> implementation continuation, user-level threading, and etc. The support added
> in this patch ONLY addresses this usage and is NOT intended to support SjLj
> exception handling as zero-cost DWARF exception handling is used by default
> in X86.
>
>
> Added:
> llvm/trunk/test/CodeGen/X86/sjlj.ll
> Modified:
> llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
> llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> llvm/trunk/lib/Target/X86/X86ISelLowering.h
> llvm/trunk/lib/Target/X86/X86InstrCompiler.td
> llvm/trunk/lib/Target/X86/X86InstrInfo.td
> llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp
> llvm/trunk/lib/Target/X86/X86RegisterInfo.h
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=165989&r1=165988&r2=165989&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Mon Oct 15 17:39:43 2012
> @@ -1302,7 +1302,9 @@
> // that are not a MemSDNode, and thus don't have proper addrspace info.
> Parent->getOpcode() != ISD::INTRINSIC_W_CHAIN && // unaligned loads, fixme
> Parent->getOpcode() != ISD::INTRINSIC_VOID && // nontemporal stores
> - Parent->getOpcode() != X86ISD::TLSCALL) { // Fixme
> + Parent->getOpcode() != X86ISD::TLSCALL && // Fixme
> + Parent->getOpcode() != X86ISD::EH_SJLJ_SETJMP && // setjmp
> + Parent->getOpcode() != X86ISD::EH_SJLJ_LONGJMP) { // longjmp
> unsigned AddrSpace =
> cast<MemSDNode>(Parent)->getPointerInfo().getAddrSpace();
> // AddrSpace 256 -> GS, 257 -> FS.
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=165989&r1=165988&r2=165989&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Mon Oct 15 17:39:43 2012
> @@ -457,6 +457,14 @@
> setOperationAction(ISD::SETCC , MVT::i64 , Custom);
> }
> setOperationAction(ISD::EH_RETURN , MVT::Other, Custom);
> + // NOTE: EH_SJLJ_SETJMP/_LONGJMP supported here is NOT intened to support
> + // SjLj exception handling but a light-weight setjmp/longjmp replacement to
> + // support continuation, user-level threading, and etc.. As a result, not
> + // other SjLj exception interfaces are implemented and please don't build
> + // your own exception handling based on them.
> + // LLVM/Clang supports zero-cost DWARF exception handling.
> + setOperationAction(ISD::EH_SJLJ_SETJMP, MVT::i32, Custom);
> + setOperationAction(ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom);
>
> // Darwin ABI issue.
> setOperationAction(ISD::ConstantPool , MVT::i32 , Custom);
> @@ -10351,6 +10359,21 @@
> Chain, DAG.getRegister(StoreAddrReg, getPointerTy()));
> }
>
> +SDValue X86TargetLowering::lowerEH_SJLJ_SETJMP(SDValue Op,
> + SelectionDAG &DAG) const {
> + DebugLoc DL = Op.getDebugLoc();
> + return DAG.getNode(X86ISD::EH_SJLJ_SETJMP, DL,
> + DAG.getVTList(MVT::i32, MVT::Other),
> + Op.getOperand(0), Op.getOperand(1));
> +}
> +
> +SDValue X86TargetLowering::lowerEH_SJLJ_LONGJMP(SDValue Op,
> + SelectionDAG &DAG) const {
> + DebugLoc DL = Op.getDebugLoc();
> + return DAG.getNode(X86ISD::EH_SJLJ_LONGJMP, DL, MVT::Other,
> + Op.getOperand(0), Op.getOperand(1));
> +}
> +
> static SDValue LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) {
> return Op.getOperand(0);
> }
> @@ -11375,6 +11398,8 @@
> return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
> case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
> case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG);
> + case ISD::EH_SJLJ_SETJMP: return lowerEH_SJLJ_SETJMP(Op, DAG);
> + case ISD::EH_SJLJ_LONGJMP: return lowerEH_SJLJ_LONGJMP(Op, DAG);
> case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG);
> case ISD::ADJUST_TRAMPOLINE: return LowerADJUST_TRAMPOLINE(Op, DAG);
> case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG);
> @@ -11667,6 +11692,8 @@
> case X86ISD::TLSADDR: return "X86ISD::TLSADDR";
> case X86ISD::TLSBASEADDR: return "X86ISD::TLSBASEADDR";
> case X86ISD::TLSCALL: return "X86ISD::TLSCALL";
> + case X86ISD::EH_SJLJ_SETJMP: return "X86ISD::EH_SJLJ_SETJMP";
> + case X86ISD::EH_SJLJ_LONGJMP: return "X86ISD::EH_SJLJ_LONGJMP";
> case X86ISD::EH_RETURN: return "X86ISD::EH_RETURN";
> case X86ISD::TC_RETURN: return "X86ISD::TC_RETURN";
> case X86ISD::FNSTCW16m: return "X86ISD::FNSTCW16m";
> @@ -13213,6 +13240,173 @@
> }
>
> MachineBasicBlock *
> +X86TargetLowering::emitEHSjLjSetJmp(MachineInstr *MI,
> + MachineBasicBlock *MBB) const {
> + DebugLoc DL = MI->getDebugLoc();
> + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
> +
> + MachineFunction *MF = MBB->getParent();
> + MachineRegisterInfo &MRI = MF->getRegInfo();
> +
> + const BasicBlock *BB = MBB->getBasicBlock();
> + MachineFunction::iterator I = MBB;
> + ++I;
> +
> + // Memory Reference
> + MachineInstr::mmo_iterator MMOBegin = MI->memoperands_begin();
> + MachineInstr::mmo_iterator MMOEnd = MI->memoperands_end();
> +
> + unsigned DstReg;
> + unsigned MemOpndSlot = 0;
> +
> + unsigned CurOp = 0;
> +
> + DstReg = MI->getOperand(CurOp++).getReg();
> + const TargetRegisterClass *RC = MRI.getRegClass(DstReg);
> + assert(RC->hasType(MVT::i32) && "Invalid destination!");
> + unsigned mainDstReg = MRI.createVirtualRegister(RC);
> + unsigned restoreDstReg = MRI.createVirtualRegister(RC);
> +
> + MemOpndSlot = CurOp;
> +
> + MVT PVT = getPointerTy();
> + assert((PVT == MVT::i64 || PVT == MVT::i32) &&
> + "Invalid Pointer Size!");
> +
> + // For v = setjmp(buf), we generate
> + //
> + // thisMBB:
> + // buf[Label_Offset] = ljMBB
> + // SjLjSetup restoreMBB
> + //
> + // mainMBB:
> + // v_main = 0
> + //
> + // sinkMBB:
> + // v = phi(main, restore)
> + //
> + // restoreMBB:
> + // v_restore = 1
> +
> + 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);
> +
> + MachineInstrBuilder MIB;
> +
> + // Transfer the remainder of BB and its successor edges to sinkMBB.
> + sinkMBB->splice(sinkMBB->begin(), MBB,
> + llvm::next(MachineBasicBlock::iterator(MI)), MBB->end());
> + sinkMBB->transferSuccessorsAndUpdatePHIs(MBB);
> +
> + // thisMBB:
> + unsigned PtrImmStoreOpc = (PVT == MVT::i64) ? X86::MOV64mi32 : X86::MOV32mi;
> + const int64_t Label_Offset = 1 * PVT.getStoreSize();
> +
> + // Store IP
> + MIB = BuildMI(*thisMBB, MI, DL, TII->get(PtrImmStoreOpc));
> + for (unsigned i = 0; i < X86::AddrNumOperands; ++i) {
> + if (i == X86::AddrDisp)
> + MIB.addDisp(MI->getOperand(MemOpndSlot + i), Label_Offset);
> + else
> + MIB.addOperand(MI->getOperand(MemOpndSlot + i));
> + }
> + MIB.addMBB(restoreMBB);
> + MIB.setMemRefs(MMOBegin, MMOEnd);
> + // Setup
> + MIB = BuildMI(*thisMBB, MI, DL, TII->get(X86::EH_SjLj_Setup))
> + .addMBB(restoreMBB);
> + MIB.addRegMask(RegInfo->getNoPreservedMask());
> + thisMBB->addSuccessor(mainMBB);
> + thisMBB->addSuccessor(restoreMBB);
> +
> + // mainMBB:
> + // EAX = 0
> + BuildMI(mainMBB, DL, TII->get(X86::MOV32r0), mainDstReg);
> + mainMBB->addSuccessor(sinkMBB);
> +
> + // sinkMBB:
> + BuildMI(*sinkMBB, sinkMBB->begin(), DL,
> + TII->get(X86::PHI), DstReg)
> + .addReg(mainDstReg).addMBB(mainMBB)
> + .addReg(restoreDstReg).addMBB(restoreMBB);
> +
> + // restoreMBB:
> + BuildMI(restoreMBB, DL, TII->get(X86::MOV32ri), restoreDstReg).addImm(1);
> + BuildMI(restoreMBB, DL, TII->get(X86::JMP_4)).addMBB(sinkMBB);
> + restoreMBB->addSuccessor(sinkMBB);
> +
> + MI->eraseFromParent();
> + return sinkMBB;
> +}
> +
> +MachineBasicBlock *
> +X86TargetLowering::emitEHSjLjLongJmp(MachineInstr *MI,
> + MachineBasicBlock *MBB) const {
> + DebugLoc DL = MI->getDebugLoc();
> + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
> +
> + MachineFunction *MF = MBB->getParent();
> + MachineRegisterInfo &MRI = MF->getRegInfo();
> +
> + // Memory Reference
> + MachineInstr::mmo_iterator MMOBegin = MI->memoperands_begin();
> + MachineInstr::mmo_iterator MMOEnd = MI->memoperands_end();
> +
> + MVT PVT = getPointerTy();
> + assert((PVT == MVT::i64 || PVT == MVT::i32) &&
> + "Invalid Pointer Size!");
> +
> + const TargetRegisterClass *RC =
> + (PVT == MVT::i64) ? &X86::GR64RegClass : &X86::GR32RegClass;
> + unsigned Tmp = MRI.createVirtualRegister(RC);
> + // Since FP is only updated here but NOT referenced, it's treated as GPR.
> + unsigned FP = (PVT == MVT::i64) ? X86::RBP : X86::EBP;
> + unsigned SP = RegInfo->getStackRegister();
> +
> + MachineInstrBuilder MIB;
> +
> + const int64_t Label_Offset = 1 * PVT.getStoreSize();
> + const int64_t SP_Offset = 2 * PVT.getStoreSize();
> +
> + unsigned PtrLoadOpc = (PVT == MVT::i64) ? X86::MOV64rm : X86::MOV32rm;
> + unsigned IJmpOpc = (PVT == MVT::i64) ? X86::JMP64r : X86::JMP32r;
> +
> + // Reload FP
> + MIB = BuildMI(*MBB, MI, DL, TII->get(PtrLoadOpc), FP);
> + for (unsigned i = 0; i < X86::AddrNumOperands; ++i)
> + MIB.addOperand(MI->getOperand(i));
> + MIB.setMemRefs(MMOBegin, MMOEnd);
> + // Reload IP
> + MIB = BuildMI(*MBB, MI, DL, TII->get(PtrLoadOpc), Tmp);
> + for (unsigned i = 0; i < X86::AddrNumOperands; ++i) {
> + if (i == X86::AddrDisp)
> + MIB.addDisp(MI->getOperand(i), Label_Offset);
> + else
> + MIB.addOperand(MI->getOperand(i));
> + }
> + MIB.setMemRefs(MMOBegin, MMOEnd);
> + // Reload SP
> + MIB = BuildMI(*MBB, MI, DL, TII->get(PtrLoadOpc), SP);
> + for (unsigned i = 0; i < X86::AddrNumOperands; ++i) {
> + if (i == X86::AddrDisp)
> + MIB.addDisp(MI->getOperand(i), SP_Offset);
> + else
> + MIB.addOperand(MI->getOperand(i));
> + }
> + MIB.setMemRefs(MMOBegin, MMOEnd);
> + // Jump
> + BuildMI(*MBB, MI, DL, TII->get(IJmpOpc)).addReg(Tmp);
> +
> + MI->eraseFromParent();
> + return MBB;
> +}
> +
> +MachineBasicBlock *
> X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
> MachineBasicBlock *BB) const {
> switch (MI->getOpcode()) {
> @@ -13427,6 +13621,14 @@
>
> case X86::VAARG_64:
> return EmitVAARG64WithCustomInserter(MI, BB);
> +
> + case X86::EH_SjLj_SetJmp32:
> + case X86::EH_SjLj_SetJmp64:
> + return emitEHSjLjSetJmp(MI, BB);
> +
> + case X86::EH_SjLj_LongJmp32:
> + case X86::EH_SjLj_LongJmp64:
> + return emitEHSjLjLongJmp(MI, BB);
> }
> }
>
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.h?rev=165989&r1=165988&r2=165989&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Mon Oct 15 17:39:43 2012
> @@ -217,6 +217,12 @@
> // EH_RETURN - Exception Handling helpers.
> EH_RETURN,
>
> + // EH_SJLJ_SETJMP - SjLj exception handling setjmp.
> + EH_SJLJ_SETJMP,
> +
> + // EH_SJLJ_LONGJMP - SjLj exception handling longjmp.
> + EH_SJLJ_LONGJMP,
> +
> /// TC_RETURN - Tail call return.
> /// operand #0 chain
> /// operand #1 callee (register or absolute)
> @@ -810,6 +816,8 @@
> SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
> SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const;
> SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;
> + SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const;
> + SDValue lowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const;
> SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
> SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG) const;
> SDValue LowerShift(SDValue Op, SelectionDAG &DAG) const;
> @@ -906,6 +914,12 @@
> MachineBasicBlock *emitLoweredTLSAddr(MachineInstr *MI,
> MachineBasicBlock *BB) const;
>
> + MachineBasicBlock *emitEHSjLjSetJmp(MachineInstr *MI,
> + MachineBasicBlock *MBB) const;
> +
> + MachineBasicBlock *emitEHSjLjLongJmp(MachineInstr *MI,
> + MachineBasicBlock *MBB) const;
> +
> /// Emit nodes that will be selected as "test Op0,Op0", or something
> /// equivalent, for use with the given x86 condition code.
> SDValue EmitTest(SDValue Op0, unsigned X86CC, SelectionDAG &DAG) const;
>
> Modified: llvm/trunk/lib/Target/X86/X86InstrCompiler.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrCompiler.td?rev=165989&r1=165988&r2=165989&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86InstrCompiler.td (original)
> +++ llvm/trunk/lib/Target/X86/X86InstrCompiler.td Mon Oct 15 17:39:43 2012
> @@ -165,6 +165,33 @@
>
> }
>
> +let hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1,
> + usesCustomInserter = 1 in {
> + def EH_SjLj_SetJmp32 : I<0, Pseudo, (outs GR32:$dst), (ins i32mem:$buf),
> + "#EH_SJLJ_SETJMP32",
> + [(set GR32:$dst, (X86eh_sjlj_setjmp addr:$buf))]>,
> + Requires<[In32BitMode]>;
> + def EH_SjLj_SetJmp64 : I<0, Pseudo, (outs GR32:$dst), (ins i64mem:$buf),
> + "#EH_SJLJ_SETJMP64",
> + [(set GR32:$dst, (X86eh_sjlj_setjmp addr:$buf))]>,
> + Requires<[In64BitMode]>;
> + let isTerminator = 1 in {
> + def EH_SjLj_LongJmp32 : I<0, Pseudo, (outs), (ins i32mem:$buf),
> + "#EH_SJLJ_LONGJMP32",
> + [(X86eh_sjlj_longjmp addr:$buf)]>,
> + Requires<[In32BitMode]>;
> + def EH_SjLj_LongJmp64 : I<0, Pseudo, (outs), (ins i64mem:$buf),
> + "#EH_SJLJ_LONGJMP64",
> + [(X86eh_sjlj_longjmp addr:$buf)]>,
> + Requires<[In64BitMode]>;
> + }
> +}
> +
> +let isBranch = 1, isTerminator = 1, isCodeGenOnly = 1 in {
> + def EH_SjLj_Setup : I<0, Pseudo, (outs), (ins brtarget:$dst),
> + "#EH_SjLj_Setup\t$dst", []>;
> +}
> +
> //===----------------------------------------------------------------------===//
> // Pseudo instructions used by segmented stacks.
> //
>
> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=165989&r1=165988&r2=165989&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original)
> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Mon Oct 15 17:39:43 2012
> @@ -216,6 +216,14 @@
> def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET,
> [SDNPHasChain]>;
>
> +def X86eh_sjlj_setjmp : SDNode<"X86ISD::EH_SJLJ_SETJMP",
> + SDTypeProfile<1, 1, [SDTCisInt<0>,
> + SDTCisPtrTy<1>]>,
> + [SDNPHasChain, SDNPSideEffect]>;
> +def X86eh_sjlj_longjmp : SDNode<"X86ISD::EH_SJLJ_LONGJMP",
> + SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>,
> + [SDNPHasChain, SDNPSideEffect]>;
> +
> def X86tcret : SDNode<"X86ISD::TC_RETURN", SDT_X86TCRET,
> [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
>
>
> Modified: llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp?rev=165989&r1=165988&r2=165989&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp Mon Oct 15 17:39:43 2012
> @@ -261,6 +261,11 @@
> return CSR_64_RegMask;
> }
>
> +const uint32_t*
> +X86RegisterInfo::getNoPreservedMask() const {
> + return CSR_NoRegs_RegMask;
> +}
> +
> BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
> BitVector Reserved(getNumRegs());
> const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
>
> Modified: llvm/trunk/lib/Target/X86/X86RegisterInfo.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86RegisterInfo.h?rev=165989&r1=165988&r2=165989&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86RegisterInfo.h (original)
> +++ llvm/trunk/lib/Target/X86/X86RegisterInfo.h Mon Oct 15 17:39:43 2012
> @@ -100,6 +100,7 @@
> /// callee-save registers on this target.
> const uint16_t *getCalleeSavedRegs(const MachineFunction* MF = 0) const;
> const uint32_t *getCallPreservedMask(CallingConv::ID) const;
> + const uint32_t *getNoPreservedMask() const;
>
> /// getReservedRegs - Returns a bitset indexed by physical register number
> /// indicating if a register is a special register that has particular uses and
>
> Added: llvm/trunk/test/CodeGen/X86/sjlj.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/sjlj.ll?rev=165989&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/sjlj.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/sjlj.ll Mon Oct 15 17:39:43 2012
> @@ -0,0 +1,46 @@
> +; RUN: llc < %s -mtriple=i386-pc-linux -mcpu=corei7 -relocation-model=static | FileCheck --check-prefix=X86 %s
> +; RUN: llc < %s -mtriple=x86_64-pc-linux -mcpu=corei7 | FileCheck --check-prefix=X64 %s
> +
> + at buf = internal global [5 x i8*] zeroinitializer
> +
> +declare i8* @llvm.frameaddress(i32) nounwind readnone
> +
> +declare i8* @llvm.stacksave() nounwind
> +
> +declare i32 @llvm.eh.sjlj.setjmp(i8*) nounwind
> +
> +declare void @llvm.eh.sjlj.longjmp(i8*) nounwind
> +
> +define i32 @sj0() nounwind {
> + %fp = tail call i8* @llvm.frameaddress(i32 0)
> + store i8* %fp, i8** getelementptr inbounds ([5 x i8*]* @buf, i64 0, i64 0), align 16
> + %sp = tail call i8* @llvm.stacksave()
> + store i8* %sp, i8** getelementptr inbounds ([5 x i8*]* @buf, i64 0, i64 2), align 16
> + %r = tail call i32 @llvm.eh.sjlj.setjmp(i8* bitcast ([5 x i8*]* @buf to i8*))
> + ret i32 %r
> +; X86: sj0
> +; x86: movl %ebp, buf
> +; x86: movl ${{.*LBB.*}}, buf+4
> +; X86: movl %esp, buf+8
> +; X86: ret
> +; X64: sj0
> +; x64: movq %rbp, buf(%rip)
> +; x64: movq ${{.*LBB.*}}, buf+8(%rip)
> +; X64: movq %rsp, buf+16(%rip)
> +; X64: ret
> +}
> +
> +define void @lj0() nounwind {
> + tail call void @llvm.eh.sjlj.longjmp(i8* bitcast ([5 x i8*]* @buf to i8*))
> + unreachable
> +; X86: lj0
> +; X86: movl buf, %ebp
> +; X86: movl buf+4, %[[REG32:.*]]
> +; X86: movl buf+8, %esp
> +; X86: jmpl *%[[REG32]]
> +; X64: lj0
> +; X64: movq buf(%rip), %rbp
> +; X64: movq buf+8(%rip), %[[REG64:.*]]
> +; X64: movq buf+16(%rip), %rsp
> +; X64: jmpq *%[[REG64]]
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list