Skip to content

Commit 625258d

Browse files
committed
jump tables
1 parent 626be98 commit 625258d

File tree

14 files changed

+161
-32
lines changed

14 files changed

+161
-32
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-image-base",
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
@@ -3139,6 +3139,14 @@ void AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo &MJTI,
31393139
Value = MCBinaryExpr::createSub(Value, Base, OutContext);
31403140
break;
31413141
}
3142+
3143+
case MachineJumpTableInfo::EK_CoffImgRel32: {
3144+
// This generates an unsigned 32-bit offset, which is MBB's address minus
3145+
// the COFF image base.
3146+
Value = MCSymbolRefExpr::create(
3147+
MBB->getSymbol(), MCSymbolRefExpr::VK_COFF_IMGREL32, OutContext);
3148+
break;
3149+
}
31423150
}
31433151

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

llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3564,17 +3564,44 @@ 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

3569-
CurFn->JumpTables.push_back(
3570-
{EntrySize, Base, BaseOffset, Branch,
3571-
MF->getJTISymbol(JumpTableIndex, MMI->getContext()),
3572-
JTI.getJumpTables()[JumpTableIndex].MBBs.size()});
3573+
const MachineJumpTableEntry &JTE = JTI.getJumpTables()[JumpTableIndex];
3574+
3575+
JumpTableInfo CVJTI{EntrySize,
3576+
Base,
3577+
BaseOffset,
3578+
Branch,
3579+
MF->getJTISymbol(JumpTableIndex, MMI->getContext()),
3580+
JTE.MBBs.size()};
3581+
3582+
for (const auto &MBB : JTE.MBBs) {
3583+
CVJTI.Cases.push_back(MBB->getSymbol());
3584+
}
3585+
3586+
CurFn->JumpTables.push_back(std::move(CVJTI));
35733587
});
35743588
}
35753589

35763590
void CodeViewDebug::emitDebugInfoForJumpTables(const FunctionInfo &FI) {
3577-
for (auto JumpTable : FI.JumpTables) {
3591+
// Emit S_LABEL32 records for each jump target
3592+
for (const auto &JumpTable : FI.JumpTables) {
3593+
for (const auto &CaseSym : JumpTable.Cases) {
3594+
MCSymbol *LabelEnd = beginSymbolRecord(SymbolKind::S_LABEL32);
3595+
OS.AddComment("Offset and segment");
3596+
OS.emitCOFFSecRel32(CaseSym, 0);
3597+
OS.AddComment("Flags");
3598+
OS.emitInt8(0);
3599+
emitNullTerminatedSymbolName(OS, CaseSym->getName());
3600+
endSymbolRecord(LabelEnd);
3601+
}
3602+
}
3603+
3604+
for (const auto &JumpTable : FI.JumpTables) {
35783605
MCSymbol *JumpTableEnd = beginSymbolRecord(SymbolKind::S_ARMSWITCHTABLE);
35793606
if (JumpTable.Base) {
35803607
OS.AddComment("Base offset");

llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
146146
const MCSymbol *Branch;
147147
const MCSymbol *Table;
148148
size_t TableSize;
149+
std::vector<const MCSymbol *> Cases;
149150
};
150151

151152
// For each function, store a vector of labels to its instructions, as well as

llvm/lib/CodeGen/MachineFunction.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,6 +1331,8 @@ unsigned MachineJumpTableInfo::getEntrySize(const DataLayout &TD) const {
13311331
return 4;
13321332
case MachineJumpTableInfo::EK_Inline:
13331333
return 0;
1334+
case MachineJumpTableInfo::EK_CoffImgRel32:
1335+
return 4;
13341336
}
13351337
llvm_unreachable("Unknown jump table encoding!");
13361338
}
@@ -1348,6 +1350,7 @@ unsigned MachineJumpTableInfo::getEntryAlignment(const DataLayout &TD) const {
13481350
return TD.getABIIntegerTypeAlignment(64).value();
13491351
case MachineJumpTableInfo::EK_GPRel32BlockAddress:
13501352
case MachineJumpTableInfo::EK_LabelDifference32:
1353+
case MachineJumpTableInfo::EK_CoffImgRel32:
13511354
case MachineJumpTableInfo::EK_Custom32:
13521355
return TD.getABIIntegerTypeAlignment(32).value();
13531356
case MachineJumpTableInfo::EK_Inline:
@@ -1356,6 +1359,25 @@ unsigned MachineJumpTableInfo::getEntryAlignment(const DataLayout &TD) const {
13561359
llvm_unreachable("Unknown jump table encoding!");
13571360
}
13581361

1362+
/// getEntryIsSigned - Return true if the load for the jump table index
1363+
/// should use signed extension, false if zero extension (unsigned)
1364+
bool MachineJumpTableInfo::getEntryIsSigned() const {
1365+
switch (getEntryKind()) {
1366+
case MachineJumpTableInfo::EK_BlockAddress:
1367+
case MachineJumpTableInfo::EK_GPRel64BlockAddress:
1368+
case MachineJumpTableInfo::EK_GPRel32BlockAddress:
1369+
case MachineJumpTableInfo::EK_LabelDifference32:
1370+
case MachineJumpTableInfo::EK_LabelDifference64:
1371+
case MachineJumpTableInfo::EK_Inline:
1372+
case MachineJumpTableInfo::EK_Custom32:
1373+
return true;
1374+
1375+
case MachineJumpTableInfo::EK_CoffImgRel32:
1376+
return false;
1377+
}
1378+
llvm_unreachable("Unknown jump table encoding!");
1379+
}
1380+
13591381
/// Create a new jump table entry in the jump table info.
13601382
unsigned MachineJumpTableInfo::createJumpTableIndex(
13611383
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
@@ -4107,8 +4107,8 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
41074107
const DataLayout &TD = DAG.getDataLayout();
41084108
EVT PTy = TLI.getPointerTy(TD);
41094109

4110-
unsigned EntrySize =
4111-
DAG.getMachineFunction().getJumpTableInfo()->getEntrySize(TD);
4110+
MachineJumpTableInfo *MJTI = DAG.getMachineFunction().getJumpTableInfo();
4111+
unsigned EntrySize = MJTI->getEntrySize(TD);
41124112

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

41264126
EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), EntrySize * 8);
41274127
SDValue LD = DAG.getExtLoad(
4128-
ISD::SEXTLOAD, dl, PTy, Chain, Addr,
4129-
MachinePointerInfo::getJumpTable(DAG.getMachineFunction()), MemVT);
4128+
MJTI->getEntryIsSigned() ? ISD::SEXTLOAD : ISD::ZEXTLOAD, dl, PTy,
4129+
Chain, Addr, MachinePointerInfo::getJumpTable(DAG.getMachineFunction()),
4130+
MemVT);
41304131
Addr = LD;
4131-
if (TLI.isJumpTableRelative()) {
4132+
if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_CoffImgRel32) {
4133+
SDValue ImageBase = DAG.getExternalSymbol(
4134+
"__ImageBase", TLI.getPointerTy(DAG.getDataLayout()));
4135+
Addr = DAG.getMemBasePlusOffset(ImageBase, Addr, dl);
4136+
} else if (TLI.isJumpTableRelative()) {
41324137
// For PIC, the sequence is:
41334138
// BRIND(RelocBase + load(Jumptable + index))
41344139
// 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
@@ -37618,6 +37618,37 @@ X86TargetLowering::EmitSjLjDispatchBlock(MachineInstr &MI,
3761837618
BuildMI(DispContBB, MIMD, TII->get(X86::JMP64r)).addReg(TReg);
3761937619
break;
3762037620
}
37621+
case MachineJumpTableInfo::EK_CoffImgRel32: {
37622+
Register ImageBaseReg = MRI->createVirtualRegister(&X86::GR64RegClass);
37623+
Register OReg64 = MRI->createVirtualRegister(&X86::GR64RegClass);
37624+
Register TReg = MRI->createVirtualRegister(&X86::GR64RegClass);
37625+
37626+
// movl (BReg,IReg64,4), OReg
37627+
// This implicitly zero-extends from uint32 to uint64.
37628+
BuildMI(DispContBB, MIMD, TII->get(X86::MOV32rm), OReg64)
37629+
.addReg(BReg)
37630+
.addImm(4)
37631+
.addReg(IReg64)
37632+
.addImm(0)
37633+
.addReg(0);
37634+
37635+
// leaq (__ImageBase,OReg64), ImageBaseReg
37636+
BuildMI(DispContBB, MIMD, TII->get(X86::LEA64r), ImageBaseReg)
37637+
.addReg(X86::RIP)
37638+
.addImm(0)
37639+
.addReg(0)
37640+
.addExternalSymbol("__ImageBase", X86II::MO_COFF_IMGREL32)
37641+
.addReg(0);
37642+
37643+
// addq ImageBaseReg, OReg64
37644+
BuildMI(DispContBB, MIMD, TII->get(X86::ADD64rr), TReg)
37645+
.addReg(ImageBaseReg)
37646+
.addReg(OReg64);
37647+
37648+
// jmpq *TReg
37649+
BuildMI(DispContBB, MIMD, TII->get(X86::JMP64r)).addReg(TReg);
37650+
break;
37651+
}
3762137652
default:
3762237653
llvm_unreachable("Unexpected jump table encoding");
3762337654
}

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())

0 commit comments

Comments
 (0)