Skip to content

Commit e717cd0

Browse files
committed
COFF imgrel32 jump tables
1 parent 55e1e9c commit e717cd0

File tree

13 files changed

+131
-27
lines changed

13 files changed

+131
-27
lines changed

llvm/include/llvm/CodeGen/MIRYamlMapping.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ template <> struct ScalarEnumerationTraits<MachineJumpTableInfo::JTEntryKind> {
141141
MachineJumpTableInfo::EK_LabelDifference64);
142142
IO.enumCase(EntryKind, "inline", MachineJumpTableInfo::EK_Inline);
143143
IO.enumCase(EntryKind, "custom32", MachineJumpTableInfo::EK_Custom32);
144+
IO.enumCase(EntryKind, "coff-imgrel32",
145+
MachineJumpTableInfo::EK_CoffImgRel32);
144146
}
145147
};
146148

llvm/include/llvm/CodeGen/MachineJumpTableInfo.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,12 @@ class MachineJumpTableInfo {
8585

8686
/// EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the
8787
/// TargetLowering::LowerCustomJumpTableEntry hook.
88-
EK_Custom32
88+
EK_Custom32,
89+
90+
// EK_CoffImgRel32 - In PE/COFF (Windows) images, each entry is a 32-bit
91+
// unsigned offset that is added to the image base.
92+
// .word LBB123@IMGREL
93+
EK_CoffImgRel32,
8994
};
9095

9196
private:
@@ -100,6 +105,9 @@ class MachineJumpTableInfo {
100105
LLVM_ABI unsigned getEntrySize(const DataLayout &TD) const;
101106
/// getEntryAlignment - Return the alignment of each entry in the jump table.
102107
LLVM_ABI unsigned getEntryAlignment(const DataLayout &TD) const;
108+
/// getEntryIsSigned - Return true if the load for the jump table index
109+
/// should use signed extension, false if zero extension (unsigned)
110+
LLVM_ABI bool getEntryIsSigned() const;
103111

104112
/// createJumpTableIndex - Create a new jump table.
105113
///

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3136,6 +3136,14 @@ void AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo &MJTI,
31363136
Value = MCBinaryExpr::createSub(Value, Base, OutContext);
31373137
break;
31383138
}
3139+
3140+
case MachineJumpTableInfo::EK_CoffImgRel32: {
3141+
// This generates an unsigned 32-bit offset, which is MBB's address minus
3142+
// the COFF image base.
3143+
Value = MCSymbolRefExpr::create(
3144+
MBB->getSymbol(), MCSymbolRefExpr::VK_COFF_IMGREL32, OutContext);
3145+
break;
3146+
}
31393147
}
31403148

31413149
assert(Value && "Unknown entry kind!");

llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3564,6 +3564,10 @@ void CodeViewDebug::collectDebugInfoForJumpTables(const MachineFunction *MF,
35643564
std::tie(Base, BaseOffset, Branch, EntrySize) =
35653565
Asm->getCodeViewJumpTableInfo(JumpTableIndex, &BranchMI, Branch);
35663566
break;
3567+
case MachineJumpTableInfo::EK_CoffImgRel32:
3568+
EntrySize = JumpTableEntrySize::UInt32;
3569+
Base = nullptr;
3570+
break;
35673571
}
35683572

35693573
const MachineJumpTableEntry &JTE = JTI.getJumpTables()[JumpTableIndex];

llvm/lib/CodeGen/MachineFunction.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,6 +1328,7 @@ unsigned MachineJumpTableInfo::getEntrySize(const DataLayout &TD) const {
13281328
case MachineJumpTableInfo::EK_GPRel32BlockAddress:
13291329
case MachineJumpTableInfo::EK_LabelDifference32:
13301330
case MachineJumpTableInfo::EK_Custom32:
1331+
case MachineJumpTableInfo::EK_CoffImgRel32:
13311332
return 4;
13321333
case MachineJumpTableInfo::EK_Inline:
13331334
return 0;
@@ -1348,6 +1349,7 @@ unsigned MachineJumpTableInfo::getEntryAlignment(const DataLayout &TD) const {
13481349
return TD.getABIIntegerTypeAlignment(64).value();
13491350
case MachineJumpTableInfo::EK_GPRel32BlockAddress:
13501351
case MachineJumpTableInfo::EK_LabelDifference32:
1352+
case MachineJumpTableInfo::EK_CoffImgRel32:
13511353
case MachineJumpTableInfo::EK_Custom32:
13521354
return TD.getABIIntegerTypeAlignment(32).value();
13531355
case MachineJumpTableInfo::EK_Inline:
@@ -1356,6 +1358,25 @@ unsigned MachineJumpTableInfo::getEntryAlignment(const DataLayout &TD) const {
13561358
llvm_unreachable("Unknown jump table encoding!");
13571359
}
13581360

1361+
/// getEntryIsSigned - Return true if the load for the jump table index
1362+
/// should use signed extension, false if zero extension (unsigned)
1363+
bool MachineJumpTableInfo::getEntryIsSigned() const {
1364+
switch (getEntryKind()) {
1365+
case MachineJumpTableInfo::EK_BlockAddress:
1366+
case MachineJumpTableInfo::EK_GPRel64BlockAddress:
1367+
case MachineJumpTableInfo::EK_GPRel32BlockAddress:
1368+
case MachineJumpTableInfo::EK_LabelDifference32:
1369+
case MachineJumpTableInfo::EK_LabelDifference64:
1370+
case MachineJumpTableInfo::EK_Inline:
1371+
case MachineJumpTableInfo::EK_Custom32:
1372+
return true;
1373+
1374+
case MachineJumpTableInfo::EK_CoffImgRel32:
1375+
return false;
1376+
}
1377+
llvm_unreachable("Unknown jump table encoding!");
1378+
}
1379+
13591380
/// Create a new jump table entry in the jump table info.
13601381
unsigned MachineJumpTableInfo::createJumpTableIndex(
13611382
const std::vector<MachineBasicBlock*> &DestBBs) {

llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4133,8 +4133,8 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
41334133
const DataLayout &TD = DAG.getDataLayout();
41344134
EVT PTy = TLI.getPointerTy(TD);
41354135

4136-
unsigned EntrySize =
4137-
DAG.getMachineFunction().getJumpTableInfo()->getEntrySize(TD);
4136+
MachineJumpTableInfo *MJTI = DAG.getMachineFunction().getJumpTableInfo();
4137+
unsigned EntrySize = MJTI->getEntrySize(TD);
41384138

41394139
// For power-of-two jumptable entry sizes convert multiplication to a shift.
41404140
// This transformation needs to be done here since otherwise the MIPS
@@ -4151,10 +4151,15 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
41514151

41524152
EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), EntrySize * 8);
41534153
SDValue LD = DAG.getExtLoad(
4154-
ISD::SEXTLOAD, dl, PTy, Chain, Addr,
4155-
MachinePointerInfo::getJumpTable(DAG.getMachineFunction()), MemVT);
4154+
MJTI->getEntryIsSigned() ? ISD::SEXTLOAD : ISD::ZEXTLOAD, dl, PTy,
4155+
Chain, Addr, MachinePointerInfo::getJumpTable(DAG.getMachineFunction()),
4156+
MemVT);
41564157
Addr = LD;
4157-
if (TLI.isJumpTableRelative()) {
4158+
if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_CoffImgRel32) {
4159+
SDValue ImageBase = DAG.getExternalSymbol(
4160+
"__ImageBase", TLI.getPointerTy(DAG.getDataLayout()));
4161+
Addr = DAG.getMemBasePlusOffset(ImageBase, Addr, dl);
4162+
} else if (TLI.isJumpTableRelative()) {
41584163
// For PIC, the sequence is:
41594164
// BRIND(RelocBase + load(Jumptable + index))
41604165
// RelocBase can be JumpTable, GOT or some sort of global base.

llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,9 @@ enum TOF {
486486
/// reference is actually to the ".refptr.FOO" symbol. This is used for
487487
/// stub symbols on windows.
488488
MO_COFFSTUB,
489+
/// MO_COFF_IMGREL32: Indicates that the operand value is unsigned 32-bit
490+
/// offset from ImageBase to a symbol (basically .imgrel32).
491+
MO_COFF_IMGREL32,
489492
};
490493

491494
enum : uint64_t {

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37617,6 +37617,37 @@ X86TargetLowering::EmitSjLjDispatchBlock(MachineInstr &MI,
3761737617
BuildMI(DispContBB, MIMD, TII->get(X86::JMP64r)).addReg(TReg);
3761837618
break;
3761937619
}
37620+
case MachineJumpTableInfo::EK_CoffImgRel32: {
37621+
Register ImageBaseReg = MRI->createVirtualRegister(&X86::GR64RegClass);
37622+
Register OReg64 = MRI->createVirtualRegister(&X86::GR64RegClass);
37623+
Register TReg = MRI->createVirtualRegister(&X86::GR64RegClass);
37624+
37625+
// movl (BReg,IReg64,4), OReg
37626+
// This implicitly zero-extends from uint32 to uint64.
37627+
BuildMI(DispContBB, MIMD, TII->get(X86::MOV32rm), OReg64)
37628+
.addReg(BReg)
37629+
.addImm(4)
37630+
.addReg(IReg64)
37631+
.addImm(0)
37632+
.addReg(0);
37633+
37634+
// leaq (__ImageBase,OReg64), ImageBaseReg
37635+
BuildMI(DispContBB, MIMD, TII->get(X86::LEA64r), ImageBaseReg)
37636+
.addReg(X86::RIP)
37637+
.addImm(0)
37638+
.addReg(0)
37639+
.addExternalSymbol("__ImageBase", X86II::MO_COFF_IMGREL32)
37640+
.addReg(0);
37641+
37642+
// addq ImageBaseReg, OReg64
37643+
BuildMI(DispContBB, MIMD, TII->get(X86::ADD64rr), TReg)
37644+
.addReg(ImageBaseReg)
37645+
.addReg(OReg64);
37646+
37647+
// jmpq *TReg
37648+
BuildMI(DispContBB, MIMD, TII->get(X86::JMP64r)).addReg(TReg);
37649+
break;
37650+
}
3762037651
default:
3762137652
llvm_unreachable("Unexpected jump table encoding");
3762237653
}

llvm/lib/Target/X86/X86ISelLoweringCall.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,11 @@ bool X86TargetLowering::allowsMemoryAccess(LLVMContext &Context,
420420
/// current function. The returned value is a member of the
421421
/// MachineJumpTableInfo::JTEntryKind enum.
422422
unsigned X86TargetLowering::getJumpTableEncoding() const {
423+
// Always use EK_CoffImgRel32 for 64-bit Windows targets.
424+
if (Subtarget.isTargetWin64()) {
425+
return MachineJumpTableInfo::EK_CoffImgRel32;
426+
}
427+
423428
// In GOT pic mode, each entry in the jump table is emitted as a @GOTOFF
424429
// symbol.
425430
if (isPositionIndependent() && Subtarget.isPICStyleGOT())

llvm/lib/Target/X86/X86MCInstLower.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,9 @@ MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
320320
Expr = MCSymbolRefExpr::create(Label, Ctx);
321321
}
322322
break;
323+
case X86II::MO_COFF_IMGREL32:
324+
Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_COFF_IMGREL32, Ctx);
325+
break;
323326
}
324327

325328
if (!Expr)

0 commit comments

Comments
 (0)