SetupEntryBlockForSjLj(MI, BB, DispatchBB, FI);
// Create the jump table and associated information
- MachineJumpTableInfo *JTI =
- MF->getOrCreateJumpTableInfo(getJumpTableEncoding());
+ unsigned JTE = getJumpTableEncoding();
+ MachineJumpTableInfo *JTI = MF->getOrCreateJumpTableInfo(JTE);
unsigned MJTI = JTI->createJumpTableIndex(LPadList);
const X86RegisterInfo &RI = TII->getRegisterInfo();
.addRegMask(RI.getNoPreservedMask());
}
- unsigned IReg = MRI->createVirtualRegister(&X86::GR32RegClass);
+ // IReg is used as an index in a memory operand and therefore can't be SP
+ unsigned IReg = MRI->createVirtualRegister(&X86::GR32_NOSPRegClass);
addFrameReference(BuildMI(DispatchBB, DL, TII->get(X86::MOV32rm), IReg), FI,
Subtarget.is64Bit() ? 8 : 4);
BuildMI(DispatchBB, DL, TII->get(X86::CMP32ri))
.addImm(LPadList.size());
BuildMI(DispatchBB, DL, TII->get(X86::JAE_1)).addMBB(TrapBB);
- BuildMI(DispContBB, DL,
- TII->get(Subtarget.is64Bit() ? X86::JMP64m : X86::JMP32m))
- .addReg(0)
- .addImm(Subtarget.is64Bit() ? 8 : 4)
- .addReg(IReg)
- .addJumpTableIndex(MJTI)
- .addReg(0);
+ if (Subtarget.is64Bit()) {
+ unsigned BReg = MRI->createVirtualRegister(&X86::GR64RegClass);
+ unsigned IReg64 = MRI->createVirtualRegister(&X86::GR64_NOSPRegClass);
+
+ // leaq .LJTI0_0(%rip), BReg
+ BuildMI(DispContBB, DL, TII->get(X86::LEA64r), BReg)
+ .addReg(X86::RIP)
+ .addImm(1)
+ .addReg(0)
+ .addJumpTableIndex(MJTI)
+ .addReg(0);
+ // movzx IReg64, IReg
+ BuildMI(DispContBB, DL, TII->get(TargetOpcode::SUBREG_TO_REG), IReg64)
+ .addImm(0)
+ .addReg(IReg)
+ .addImm(X86::sub_32bit);
+
+ switch (JTE) {
+ case MachineJumpTableInfo::EK_BlockAddress:
+ // jmpq *(BReg,IReg64,8)
+ BuildMI(DispContBB, DL, TII->get(X86::JMP64m))
+ .addReg(BReg)
+ .addImm(8)
+ .addReg(IReg64)
+ .addImm(0)
+ .addReg(0);
+ break;
+ case MachineJumpTableInfo::EK_LabelDifference32: {
+ unsigned OReg = MRI->createVirtualRegister(&X86::GR32RegClass);
+ unsigned OReg64 = MRI->createVirtualRegister(&X86::GR64RegClass);
+ unsigned TReg = MRI->createVirtualRegister(&X86::GR64RegClass);
+
+ // movl (BReg,IReg64,4), OReg
+ BuildMI(DispContBB, DL, TII->get(X86::MOV32rm), OReg)
+ .addReg(BReg)
+ .addImm(4)
+ .addReg(IReg64)
+ .addImm(0)
+ .addReg(0);
+ // movsx OReg64, OReg
+ BuildMI(DispContBB, DL, TII->get(X86::MOVSX64rr32), OReg64).addReg(OReg);
+ // addq BReg, OReg64, TReg
+ BuildMI(DispContBB, DL, TII->get(X86::ADD64rr), TReg)
+ .addReg(OReg64)
+ .addReg(BReg);
+ // jmpq *TReg
+ BuildMI(DispContBB, DL, TII->get(X86::JMP64r)).addReg(TReg);
+ break;
+ }
+ default:
+ llvm_unreachable("Unexpected jump table encoding");
+ }
+ } else {
+ // jmpl *.LJTI0_0(,IReg,4)
+ BuildMI(DispContBB, DL, TII->get(X86::JMP32m))
+ .addReg(0)
+ .addImm(4)
+ .addReg(IReg)
+ .addJumpTableIndex(MJTI)
+ .addReg(0);
+ }
// Add the jump table entries as successors to the MBB.
SmallPtrSet<MachineBasicBlock *, 8> SeenMBBs;
; RUN: llc -mtriple i386-windows-gnu -exception-model sjlj -filetype asm -o - %s | FileCheck %s
; RUN: llc -mtriple x86_64-windows-gnu -exception-model sjlj -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-X64
+; RUN: llc -mtriple x86_64-linux -exception-model sjlj -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-X64-LINUX
declare void @_Z20function_that_throwsv()
declare i32 @__gxx_personality_sj0(...)
; CHECK-X64: ud2
; CHECK-X64: [[CONT]]:
; *Handlers[UFC.__callsite]
-; CHECK-X64: jmpq *.LJTI
+; CHECK-X64: leaq .[[TABLE:LJTI[0-9]+_[0-9]+]](%rip), %rcx
+; CHECK-X64: movl (%rcx,%rax,4), %eax
+; CHECK-X64: cltq
+; CHECK-X64: addq %rcx, %rax
+; CHECK-X64: jmpq *%rax
+
+; CHECK-X64-LINUX: .[[RESUME:LBB[0-9]+_[0-9]+]]:
+; assert(UFC.__callsite < 1);
+; CHECK-X64-LINUX: movl -120(%rbp), %eax
+; CHECK-X64-LINUX: cmpl $1, %eax
+; CHECK-X64-LINUX: jb .[[CONT:LBB[0-9]+_[0-9]+]]
+; CHECK-X64-LINUX: ud2
+; CHECK-X64-LINUX: [[CONT]]:
+; *Handlers[UFC.__callsite]
+; CHECK-X64-LINUX: leaq .[[TABLE:LJTI[0-9]+_[0-9]+]](%rip), %rcx
+; CHECK-X64-LINUX: jmpq *(%rcx,%rax,8)