Index: llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -156,6 +156,9 @@ MCSection *getSectionForJumpTable(const Function &F, const TargetMachine &TM) const override; + bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, + const Function &F) const override; + /// Emit Obj-C garbage collection and linker options. Only linker option /// emission is implemented for COFF. void emitModuleFlags(MCStreamer &Streamer, Index: llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1055,6 +1055,13 @@ COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID); } +bool TargetLoweringObjectFileCOFF::shouldPutJumpTableInFunctionSection( + bool UsesLabelDifference, const Function &F) const { + // We can always create relative relocations, so use another section + // that can be marked non-executable. + return false; +} + void TargetLoweringObjectFileCOFF::emitModuleFlags( MCStreamer &Streamer, ArrayRef ModuleFlags, const TargetMachine &TM) const { Index: llvm/trunk/lib/Target/X86/X86ISelLowering.h =================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.h +++ llvm/trunk/lib/Target/X86/X86ISelLowering.h @@ -684,6 +684,7 @@ const X86Subtarget &STI); unsigned getJumpTableEncoding() const override; + bool isJumpTableRelative() const override; bool useSoftFloat() const override; MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override { Index: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp @@ -1926,10 +1926,20 @@ if (isPositionIndependent() && Subtarget.isPICStyleGOT()) return MachineJumpTableInfo::EK_Custom32; + // On Win64, we want to use both label differences and a separate section. + if (Subtarget.isTargetWin64()) + return MachineJumpTableInfo::EK_LabelDifference32; + // Otherwise, use the normal jump table encoding heuristics. return TargetLowering::getJumpTableEncoding(); } +bool X86TargetLowering::isJumpTableRelative() const { + if (Subtarget.isTargetWin64()) + return true; + return TargetLowering::isJumpTableRelative(); +} + bool X86TargetLowering::useSoftFloat() const { return Subtarget.useSoftFloat(); } @@ -1948,11 +1958,19 @@ /// Returns relocation base for the given PIC jumptable. SDValue X86TargetLowering::getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const { + // COFF doesn't have relocations to take the difference between two arbitrary + // symbols. The assembler, however, can resolve a fixup between the function + // entry and a basic block label, so use the function entry as the base. + if (Subtarget.isTargetWin64()) + return DAG.getGlobalAddress(DAG.getMachineFunction().getFunction(), SDLoc(), + getPointerTy(DAG.getDataLayout())); + if (!Subtarget.is64Bit()) // This doesn't have SDLoc associated with it, but is not really the // same as a Register. return DAG.getNode(X86ISD::GlobalBaseReg, SDLoc(), getPointerTy(DAG.getDataLayout())); + return Table; } @@ -1961,6 +1979,13 @@ const MCExpr *X86TargetLowering:: getPICJumpTableRelocBaseExpr(const MachineFunction *MF, unsigned JTI, MCContext &Ctx) const { + // COFF doesn't have relocations to take the difference between two arbitrary + // symbols. The assembler, however, can resolve a fixup between the function + // entry and a basic block label, so use the function entry as the base. + if (Subtarget.isTargetWin64()) + return MCSymbolRefExpr::create( + getTargetMachine().getSymbol(MF->getFunction()), Ctx); + // X86-64 uses RIP relative addressing based on the jump table label. if (Subtarget.isPICStyleRIPRel()) return TargetLowering::getPICJumpTableRelocBaseExpr(MF, JTI, Ctx); Index: llvm/trunk/test/CodeGen/X86/win64-jumptable.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/win64-jumptable.ll +++ llvm/trunk/test/CodeGen/X86/win64-jumptable.ll @@ -1,7 +1,5 @@ -; RUN: llc < %s -relocation-model static | FileCheck %s - -; FIXME: Remove '-relocation-model static' when it is no longer necessary to -; trigger the separate .rdata section. +; RUN: llc < %s -relocation-model static | FileCheck %s --check-prefix=CHECK --check-prefix=STATIC +; RUN: llc < %s -relocation-model pic | FileCheck %s --check-prefix=CHECK --check-prefix=PIC target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc19.0.24215" @@ -41,7 +39,17 @@ ; CHECK: .text ; CHECK: f: ; CHECK: .seh_proc f -; CHECK: jmpq *.LJTI0_0 + +; STATIC: movslq .LJTI0_0(,%{{.*}},4), %[[target:[^ ]*]] +; STATIC: leaq f(%[[target]]), %[[target]] +; STATIC: jmpq *%[[target]] + +; PIC: leaq .LJTI0_0(%rip), %[[jt:[^ ]*]] +; PIC: movslq (%[[jt]],%{{.*}},4), %[[offset:[^ ]*]] +; PIC: leaq f(%rip), %[[base:[^ ]*]] +; PIC: addq %[[offset]], %[[base]] +; PIC: jmpq *%[[base]] + ; CHECK: .LBB0_{{.*}}: # %sw.bb ; CHECK: .LBB0_{{.*}}: # %sw.bb1 ; CHECK: .LBB0_{{.*}}: # %sw.bb2 @@ -49,10 +57,10 @@ ; CHECK: callq g ; CHECK: jmp g # TAILCALL ; CHECK: .section .rdata,"dr" -; CHECK: .quad .LBB0_ -; CHECK: .quad .LBB0_ -; CHECK: .quad .LBB0_ -; CHECK: .quad .LBB0_ +; CHECK: .long .LBB0_{{.*}}-f +; CHECK: .long .LBB0_{{.*}}-f +; CHECK: .long .LBB0_{{.*}}-f +; CHECK: .long .LBB0_{{.*}}-f ; CHECK: .seh_handlerdata ; It's important that we switch back to .text here, not .rdata.