[llvm] [RFC][BPF] Support Jump Table (PR #133856)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 10 08:57:11 PDT 2025
https://github.com/yonghong-song updated https://github.com/llvm/llvm-project/pull/133856
>From 0be4d463e41bcfb487f2379611d75a4cddd458ea Mon Sep 17 00:00:00 2001
From: Yonghong Song <yonghong.song at linux.dev>
Date: Mon, 31 Mar 2025 21:25:26 -0700
Subject: [PATCH] [RFC][BPF] Support Jump Table
NOTE: We probably need cpu v5 or other flags to enable this feature.
We can add it later when necessary.
- Generate all jump tables in a single section named .jumptables.
- Represent each jump table as a symbol:
- value points to an offset within .jumptables;
- size encodes jump table size in bytes.
- Indirect jump is a gotox instruction:
- dst register is an index within the table;
- accompanied by a R_BPF_64_64 relocation pointing to a jump table
symbol.
clang -S:
.LJTI0_0:
.reloc 0, FK_SecRel_8, .BPF.JT.0.0
gotox r1
goto LBB0_2
LBB0_4:
...
.section .jumptables,"", at progbits
.L0_0_set_4 = ((LBB0_4-.LBPF.JX.0.0)>>3)-1
.L0_0_set_2 = ((LBB0_2-.LBPF.JX.0.0)>>3)-1
...
.BPF.JT.0.0:
.long .L0_0_set_4
.long .L0_0_set_2
...
llvm-readelf -r --sections --symbols:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
...
[ 4] .jumptables PROGBITS 0000000000000000 000118 000100 00 0 0 1
...
Relocation section '.rel.text' at offset 0x2a8 contains 2 entries:
Offset Info Type Symbol's Value Symbol's Name
0000000000000010 0000000300000001 R_BPF_64_64 0000000000000000 .BPF.JT.0.0
...
Symbol table '.symtab' contains 6 entries:
Num: Value Size Type Bind Vis Ndx Name
...
2: 0000000000000000 112 FUNC GLOBAL DEFAULT 2 foo
3: 0000000000000000 128 NOTYPE GLOBAL DEFAULT 4 .BPF.JT.0.0
...
llvm-objdump -Sdr:
0000000000000000 <foo>:
...
2: gotox r1
0000000000000010: R_BPF_64_64 .BPF.JT.0.0
An option -bpf-min-jump-table-entries is implemented to control the minimum
number of entries to use a jump table on BPF. The default value 4, but it
can be changed with the following clang option
clang ... -mllvm -bpf-min-jump-table-entries=6
where the number of jump table cases needs to be >= 6 in order to
use jump table.
---
llvm/include/llvm/CodeGen/AsmPrinter.h | 4 +-
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 2 +-
.../lib/Target/BPF/AsmParser/BPFAsmParser.cpp | 1 +
llvm/lib/Target/BPF/BPFAsmPrinter.cpp | 76 +++++++++++++++++++
llvm/lib/Target/BPF/BPFISelLowering.cpp | 43 ++++++++++-
llvm/lib/Target/BPF/BPFISelLowering.h | 29 ++++++-
llvm/lib/Target/BPF/BPFInstrInfo.cpp | 12 +++
llvm/lib/Target/BPF/BPFInstrInfo.h | 3 +
llvm/lib/Target/BPF/BPFInstrInfo.td | 30 ++++++++
llvm/lib/Target/BPF/BPFMCInstLower.cpp | 28 +++++++
llvm/lib/Target/BPF/BPFMCInstLower.h | 1 +
.../BPF/BPFTargetLoweringObjectFile.cpp | 20 +++++
.../Target/BPF/BPFTargetLoweringObjectFile.h | 25 ++++++
llvm/lib/Target/BPF/BPFTargetMachine.cpp | 3 +-
llvm/lib/Target/BPF/CMakeLists.txt | 1 +
.../Target/BPF/MCTargetDesc/BPFAsmBackend.cpp | 13 ++++
16 files changed, 285 insertions(+), 6 deletions(-)
create mode 100644 llvm/lib/Target/BPF/BPFTargetLoweringObjectFile.cpp
create mode 100644 llvm/lib/Target/BPF/BPFTargetLoweringObjectFile.h
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index faab2503ced50..c4c6a7d0a6065 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -26,6 +26,7 @@
#include "llvm/CodeGen/StackMaps.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/IR/InlineAsm.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <cstdint>
@@ -34,6 +35,7 @@
#include <vector>
namespace llvm {
+extern cl::opt<bool> EmitJumpTableSizesSection;
class AddrLabelMap;
class AsmPrinterHandler;
@@ -663,7 +665,7 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
MCSymbol *GetExternalSymbolSymbol(const Twine &Sym) const;
/// Return the symbol for the specified jump table entry.
- MCSymbol *GetJTISymbol(unsigned JTID, bool isLinkerPrivate = false) const;
+ virtual MCSymbol *GetJTISymbol(unsigned JTID, bool isLinkerPrivate = false) const;
/// Return the symbol for the specified jump table .set
/// FIXME: privatize to AsmPrinter.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 76a1d8c931605..7d01ff372bc33 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -168,7 +168,7 @@ static cl::opt<bool> BBAddrMapSkipEmitBBEntries(
"unnecessary for some PGOAnalysisMap features."),
cl::Hidden, cl::init(false));
-static cl::opt<bool> EmitJumpTableSizesSection(
+cl::opt<bool> llvm::EmitJumpTableSizesSection(
"emit-jump-table-sizes-section",
cl::desc("Emit a section containing jump table addresses and sizes"),
cl::Hidden, cl::init(false));
diff --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
index a347794a9a30c..d96f403d2f814 100644
--- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
+++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
@@ -234,6 +234,7 @@ struct BPFOperand : public MCParsedAsmOperand {
.Case("callx", true)
.Case("goto", true)
.Case("gotol", true)
+ .Case("gotox", true)
.Case("may_goto", true)
.Case("*", true)
.Case("exit", true)
diff --git a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp
index e3843e0e112e2..3a6fd608db87a 100644
--- a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp
+++ b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp
@@ -20,7 +20,13 @@
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCSymbolELF.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInst.h"
@@ -49,6 +55,8 @@ class BPFAsmPrinter : public AsmPrinter {
const char *ExtraCode, raw_ostream &O) override;
void emitInstruction(const MachineInstr *MI) override;
+ virtual MCSymbol *GetJTISymbol(unsigned JTID, bool isLinkerPrivate = false) const override;
+ virtual void emitJumpTableInfo() override;
static char ID;
@@ -150,6 +158,74 @@ void BPFAsmPrinter::emitInstruction(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, TmpInst);
}
+MCSymbol *BPFAsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const {
+ SmallString<60> Name;
+ raw_svector_ostream(Name)
+ << "BPF.JT." << MF->getFunctionNumber() << '.' << JTID;
+ MCSymbol *S = OutContext.getOrCreateSymbol(Name);
+ if (auto *ES = dyn_cast<MCSymbolELF>(S))
+ ES->setBinding(ELF::STB_GLOBAL);
+ return S;
+}
+
+void BPFAsmPrinter::emitJumpTableInfo() {
+ const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
+ if (!MJTI) return;
+
+ const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
+ if (JT.empty()) return;
+
+ const TargetLoweringObjectFile &TLOF = getObjFileLowering();
+ const Function &F = MF->getFunction();
+ MCSection *JTS = TLOF.getSectionForJumpTable(F, TM);
+ assert(MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32);
+ unsigned EntrySize = MJTI->getEntrySize(getDataLayout());
+ OutStreamer->switchSection(JTS);
+ for (unsigned JTI = 0; JTI < JT.size(); JTI++) {
+ ArrayRef<MachineBasicBlock *> JTBBs = JT[JTI].MBBs;
+ if (JTBBs.empty())
+ continue;
+
+ SmallPtrSet<const MachineBasicBlock *, 16> EmittedSets;
+ const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
+ const MCExpr *Base =
+ TLI->getPICJumpTableRelocBaseExpr(MF, JTI, OutContext);
+ for (const MachineBasicBlock *MBB : JTBBs) {
+ if (!EmittedSets.insert(MBB).second)
+ continue;
+
+ // Offset from gotox to target basic block expressed in number
+ // of instructions, e.g.:
+ //
+ // .L0_0_set_4 = ((LBB0_4 - .LBPF.JX.0.0) >> 3) - 1
+ const MCExpr *LHS = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
+ OutStreamer->emitAssignment(
+ GetJTSetSymbol(JTI, MBB->getNumber()),
+ MCBinaryExpr::createSub(
+ MCBinaryExpr::createAShr(
+ MCBinaryExpr::createSub(LHS, Base, OutContext),
+ MCConstantExpr::create(3, OutContext),
+ OutContext),
+ MCConstantExpr::create(1, OutContext),
+ OutContext));
+ }
+ // BPF.JT.0.0:
+ // .long .L0_0_set_4
+ // .long .L0_0_set_2
+ // ...
+ // .size BPF.JT.0.0, 128
+ MCSymbol *JTStart = GetJTISymbol(JTI);
+ OutStreamer->emitLabel(JTStart);
+ for (const MachineBasicBlock *MBB : JTBBs) {
+ MCSymbol *SetSymbol = GetJTSetSymbol(JTI, MBB->getNumber());
+ const MCExpr *V = MCSymbolRefExpr::create(SetSymbol, OutContext);
+ OutStreamer->emitValue(V, EntrySize);
+ }
+ const MCExpr *JTSize = MCConstantExpr::create(JTBBs.size() * 4, OutContext);
+ OutStreamer->emitELFSize(JTStart, JTSize);
+ }
+}
+
char BPFAsmPrinter::ID = 0;
INITIALIZE_PASS(BPFAsmPrinter, "bpf-asm-printer", "BPF Assembly Printer", false,
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.cpp b/llvm/lib/Target/BPF/BPFISelLowering.cpp
index f4f414d192df0..56ed05131688a 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.cpp
+++ b/llvm/lib/Target/BPF/BPFISelLowering.cpp
@@ -18,6 +18,7 @@
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/CodeGen/ValueTypes.h"
@@ -25,6 +26,7 @@
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Module.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
@@ -38,6 +40,10 @@ static cl::opt<bool> BPFExpandMemcpyInOrder("bpf-expand-memcpy-in-order",
cl::Hidden, cl::init(false),
cl::desc("Expand memcpy into load/store pairs in order"));
+static cl::opt<unsigned> BPFMinimumJumpTableEntries(
+ "bpf-min-jump-table-entries", cl::init(4), cl::Hidden,
+ cl::desc("Set minimum number of entries to use a jump table on BPF"));
+
static void fail(const SDLoc &DL, SelectionDAG &DAG, const Twine &Msg,
SDValue Val = {}) {
std::string Str;
@@ -66,8 +72,7 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM,
setStackPointerRegisterToSaveRestore(BPF::R11);
setOperationAction(ISD::BR_CC, MVT::i64, Custom);
- setOperationAction(ISD::BR_JT, MVT::Other, Expand);
- setOperationAction(ISD::BRIND, MVT::Other, Expand);
+ setOperationAction(ISD::BR_JT, MVT::Other, Custom);
setOperationAction(ISD::BRCOND, MVT::Other, Expand);
setOperationAction(ISD::TRAP, MVT::Other, Custom);
@@ -159,6 +164,7 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM,
setBooleanContents(ZeroOrOneBooleanContent);
setMaxAtomicSizeInBitsSupported(64);
+ setMinimumJumpTableEntries(BPFMinimumJumpTableEntries);
// Function alignments
setMinFunctionAlignment(Align(8));
@@ -332,6 +338,8 @@ SDValue BPFTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
return LowerATOMIC_LOAD_STORE(Op, DAG);
case ISD::TRAP:
return LowerTRAP(Op, DAG);
+ case ISD::BR_JT:
+ return LowerBR_JT(Op, DAG);
}
}
@@ -780,6 +788,16 @@ SDValue BPFTargetLowering::LowerTRAP(SDValue Op, SelectionDAG &DAG) const {
return LowerCall(CLI, InVals);
}
+SDValue BPFTargetLowering::LowerBR_JT(SDValue Op, SelectionDAG &DAG) const {
+ SDValue Chain = Op->getOperand(0);
+ SDValue Table = Op->getOperand(1);
+ SDValue Index = Op->getOperand(2);
+ JumpTableSDNode *JT = cast<JumpTableSDNode>(Table);
+ SDLoc DL(Op);
+ SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);
+ return DAG.getNode(BPFISD::BPF_BR_JT, DL, MVT::Other, Chain, TargetJT, Index);
+}
+
const char *BPFTargetLowering::getTargetNodeName(unsigned Opcode) const {
switch ((BPFISD::NodeType)Opcode) {
case BPFISD::FIRST_NUMBER:
@@ -796,6 +814,8 @@ const char *BPFTargetLowering::getTargetNodeName(unsigned Opcode) const {
return "BPFISD::Wrapper";
case BPFISD::MEMCPY:
return "BPFISD::MEMCPY";
+ case BPFISD::BPF_BR_JT:
+ return "BPFISD::BPF_BR_JT";
}
return nullptr;
}
@@ -1069,3 +1089,22 @@ bool BPFTargetLowering::isLegalAddressingMode(const DataLayout &DL,
return true;
}
+
+MCSymbol *BPFTargetLowering::getJXAnchorSymbol(const MachineFunction *MF, unsigned JTI) {
+ const MCAsmInfo *MAI = MF->getContext().getAsmInfo();
+ SmallString<60> Name;
+ raw_svector_ostream(Name)
+ << MAI->getPrivateGlobalPrefix()
+ << "BPF.JX." << MF->getFunctionNumber() << '.' << JTI;
+ return MF->getContext().getOrCreateSymbol(Name);
+}
+
+unsigned BPFTargetLowering::getJumpTableEncoding() const {
+ return MachineJumpTableInfo::EK_LabelDifference32;
+}
+
+const MCExpr *
+BPFTargetLowering::getPICJumpTableRelocBaseExpr(const MachineFunction *MF,
+ unsigned JTI, MCContext &Ctx) const {
+ return MCSymbolRefExpr::create(getJXAnchorSymbol(MF, JTI), Ctx);
+}
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.h b/llvm/lib/Target/BPF/BPFISelLowering.h
index 8f60261c10e9e..ce6edea83d4e4 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.h
+++ b/llvm/lib/Target/BPF/BPFISelLowering.h
@@ -28,7 +28,8 @@ enum NodeType : unsigned {
SELECT_CC,
BR_CC,
Wrapper,
- MEMCPY
+ MEMCPY,
+ BPF_BR_JT,
};
}
@@ -66,6 +67,31 @@ class BPFTargetLowering : public TargetLowering {
MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override;
+ // Always emit EK_LabelDifference32, computed as difference between
+ // JX instruction location and target basic block label.
+ virtual unsigned getJumpTableEncoding() const override;
+
+ // This is a label for JX instructions, used for jump table offsets
+ // computation, e.g.:
+ //
+ // .LBPF.JX.0.0: <------- this is the anchor
+ // .reloc 0, FK_SecRel_8, BPF.JT.0.0
+ // gotox r1
+ // ...
+ // .section .jumptables,"", at progbits
+ // .L0_0_set_7 = ((LBB0_7-.LBPF.JX.0.0)>>3)-1
+ // ...
+ // BPF.JT.0.0: <------- JT definition
+ // .long .L0_0_set_7
+ // ...
+ static MCSymbol *getJXAnchorSymbol(const MachineFunction *MF, unsigned JTI);
+
+ // Refers to a symbol returned by getJXAnchorSymbol(), used by
+ // AsmPrinter::emitJumpTableInfo() to define the .L0_0_set_7 etc above.
+ virtual const MCExpr *
+ getPICJumpTableRelocBaseExpr(const MachineFunction *MF,
+ unsigned JTI, MCContext &Ctx) const override;
+
private:
// Control Instruction Selection Features
bool HasAlu32;
@@ -81,6 +107,7 @@ class BPFTargetLowering : public TargetLowering {
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerTRAP(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const;
template <class NodeTy>
SDValue getAddr(NodeTy *N, SelectionDAG &DAG, unsigned Flags = 0) const;
diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.cpp b/llvm/lib/Target/BPF/BPFInstrInfo.cpp
index 70bc163615f61..e9f65b0517f95 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.cpp
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.cpp
@@ -181,6 +181,10 @@ bool BPFInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
if (!isUnpredicatedTerminator(*I))
break;
+ // If a JX insn, we're done.
+ if (I->getOpcode() == BPF::JX)
+ break;
+
// A terminator that isn't a branch can't easily be handled
// by this analysis.
if (!I->isBranch())
@@ -259,3 +263,11 @@ unsigned BPFInstrInfo::removeBranch(MachineBasicBlock &MBB,
return Count;
}
+
+int BPFInstrInfo::getJumpTableIndex(const MachineInstr &MI) const {
+ if (MI.getOpcode() != BPF::JX)
+ return -1;
+ const MachineOperand &MO = MI.getOperand(1);
+ assert(MO.isJTI() && "JX operand #0 should be isJTI");
+ return MO.getIndex();
+}
diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.h b/llvm/lib/Target/BPF/BPFInstrInfo.h
index d8bbad44e314e..d88e37975980a 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.h
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.h
@@ -58,6 +58,9 @@ class BPFInstrInfo : public BPFGenInstrInfo {
MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
const DebugLoc &DL,
int *BytesAdded = nullptr) const override;
+
+ int getJumpTableIndex(const MachineInstr &MI) const override;
+
private:
void expandMEMCPY(MachineBasicBlock::iterator) const;
diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td
index b21f1a0eee3b0..581e49419c37f 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.td
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.td
@@ -31,6 +31,8 @@ def SDT_BPFMEMCPY : SDTypeProfile<0, 4, [SDTCisVT<0, i64>,
SDTCisVT<1, i64>,
SDTCisVT<2, i64>,
SDTCisVT<3, i64>]>;
+def SDT_BPFBrJt : SDTypeProfile<0, 2, [SDTCisVT<0, i32>, // jump table
+ SDTCisVT<1, i64>]>; // index
def BPFcall : SDNode<"BPFISD::CALL", SDT_BPFCall,
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
@@ -49,6 +51,9 @@ def BPFWrapper : SDNode<"BPFISD::Wrapper", SDT_BPFWrapper>;
def BPFmemcpy : SDNode<"BPFISD::MEMCPY", SDT_BPFMEMCPY,
[SDNPHasChain, SDNPInGlue, SDNPOutGlue,
SDNPMayStore, SDNPMayLoad]>;
+def BPFBrJt : SDNode<"BPFISD::BPF_BR_JT", SDT_BPFBrJt,
+ [SDNPHasChain]>;
+
def BPFIsLittleEndian : Predicate<"Subtarget->isLittleEndian()">;
def BPFIsBigEndian : Predicate<"!Subtarget->isLittleEndian()">;
def BPFHasALU32 : Predicate<"Subtarget->getHasAlu32()">;
@@ -183,6 +188,15 @@ class TYPE_LD_ST<bits<3> mode, bits<2> size,
let Inst{60-59} = size;
}
+// For indirect jump
+class TYPE_IND_JMP<bits<4> op, bits<1> srctype,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : InstBPF<outs, ins, asmstr, pattern> {
+
+ let Inst{63-60} = op;
+ let Inst{59} = srctype;
+}
+
// jump instructions
class JMP_RR<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond>
: TYPE_ALU_JMP<Opc.Value, BPF_X.Value,
@@ -216,6 +230,18 @@ class JMP_RI<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond>
let BPFClass = BPF_JMP;
}
+class JMP_IND<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
+ : TYPE_ALU_JMP<Opc.Value, BPF_X.Value,
+ (outs),
+ (ins GPR:$dst, i32imm:$jt),
+ !strconcat(OpcodeStr, " $dst"),
+ Pattern> {
+ bits<4> dst;
+
+ let Inst{51-48} = dst;
+ let BPFClass = BPF_JMP;
+}
+
class JMP_JCOND<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
: TYPE_ALU_JMP<Opc.Value, BPF_K.Value,
(outs),
@@ -281,6 +307,10 @@ defm JSLT : J<BPF_JSLT, "s<", BPF_CC_LT, BPF_CC_LT_32>;
defm JSLE : J<BPF_JSLE, "s<=", BPF_CC_LE, BPF_CC_LE_32>;
defm JSET : J<BPF_JSET, "&", NoCond, NoCond>;
def JCOND : JMP_JCOND<BPF_JCOND, "may_goto", []>;
+
+let isIndirectBranch = 1 in {
+ def JX : JMP_IND<BPF_JA, "gotox", [(BPFBrJt tjumptable:$jt, i64:$dst)]>;
+}
}
// ALU instructions
diff --git a/llvm/lib/Target/BPF/BPFMCInstLower.cpp b/llvm/lib/Target/BPF/BPFMCInstLower.cpp
index 040a1fb750702..5e22f6c226796 100644
--- a/llvm/lib/Target/BPF/BPFMCInstLower.cpp
+++ b/llvm/lib/Target/BPF/BPFMCInstLower.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "BPFMCInstLower.h"
+#include "BPFISelLowering.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstr.h"
@@ -19,6 +20,7 @@
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -44,6 +46,29 @@ MCOperand BPFMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
return MCOperand::createExpr(Expr);
}
+MCOperand BPFMCInstLower::LowerJTIOperand(const MachineInstr &MI, const MachineOperand &MO, int JTI) const {
+ // Emit relocation entry referencing jump table symbol plus a label
+ // for JX anchor, e.g.:
+ //
+ // .LBPF.JX.0.0:
+ // .reloc 0, FK_SecRel_8, BPF.JT.0.0
+ // gotox r1
+ assert((MI.getOpcode() == BPF::JX) &&
+ "Jump Table Index operands are expected only for JX instructions");
+ const MachineFunction *MF = MI.getMF();
+ Printer.OutStreamer->emitLabel(BPFTargetLowering::getJXAnchorSymbol(MF, JTI));
+ MCSymbol *JT = Printer.GetJTISymbol(JTI);
+ const MCExpr *Zero = MCConstantExpr::create(0, Ctx);
+ Printer.OutStreamer->emitRelocDirective(*Zero,
+ "FK_SecRel_8",
+ MCSymbolRefExpr::create(JT, Ctx),
+ {},
+ *Ctx.getSubtargetInfo());
+ // JTI parameter is used only to emit relocation and is not a part
+ // of JX instruction encoding, so this operand is not really used.
+ return MCOperand::createImm(JTI);
+}
+
void BPFMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
OutMI.setOpcode(MI->getOpcode());
@@ -77,6 +102,9 @@ void BPFMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
case MachineOperand::MO_ConstantPoolIndex:
MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
break;
+ case MachineOperand::MO_JumpTableIndex:
+ MCOp = LowerJTIOperand(*MI, MO, MO.getIndex());
+ break;
}
OutMI.addOperand(MCOp);
diff --git a/llvm/lib/Target/BPF/BPFMCInstLower.h b/llvm/lib/Target/BPF/BPFMCInstLower.h
index 4bd0f1f0bf1cf..7036f7e7a0e7a 100644
--- a/llvm/lib/Target/BPF/BPFMCInstLower.h
+++ b/llvm/lib/Target/BPF/BPFMCInstLower.h
@@ -32,6 +32,7 @@ class LLVM_LIBRARY_VISIBILITY BPFMCInstLower {
void Lower(const MachineInstr *MI, MCInst &OutMI) const;
MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const;
+ MCOperand LowerJTIOperand(const MachineInstr &MI, const MachineOperand &MO, int JTI) const;
MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const;
MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const;
diff --git a/llvm/lib/Target/BPF/BPFTargetLoweringObjectFile.cpp b/llvm/lib/Target/BPF/BPFTargetLoweringObjectFile.cpp
new file mode 100644
index 0000000000000..ccd316d678024
--- /dev/null
+++ b/llvm/lib/Target/BPF/BPFTargetLoweringObjectFile.cpp
@@ -0,0 +1,20 @@
+//===------------------ BPFTargetLoweringObjectFile.cpp -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "BPFTargetLoweringObjectFile.h"
+
+using namespace llvm;
+
+MCSection *
+BPFTargetLoweringObjectFileELF::getSectionForJumpTable(const Function &F,
+ const TargetMachine &TM,
+ const MachineJumpTableEntry *JTE) const {
+ return getContext().getELFSection(".jumptables", ELF::SHT_PROGBITS, 0);
+}
diff --git a/llvm/lib/Target/BPF/BPFTargetLoweringObjectFile.h b/llvm/lib/Target/BPF/BPFTargetLoweringObjectFile.h
new file mode 100644
index 0000000000000..3684b15925022
--- /dev/null
+++ b/llvm/lib/Target/BPF/BPFTargetLoweringObjectFile.h
@@ -0,0 +1,25 @@
+//===============- BPFTargetLoweringObjectFile.h -*- C++ -*-================//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_BPF_BPFTARGETLOWERINGOBJECTFILE
+#define LLVM_LIB_TARGET_BPF_BPFTARGETLOWERINGOBJECTFILE
+
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
+
+namespace llvm {
+class BPFTargetLoweringObjectFileELF : public TargetLoweringObjectFileELF {
+
+public:
+ virtual MCSection *
+ getSectionForJumpTable(const Function &F, const TargetMachine &TM,
+ const MachineJumpTableEntry *JTE) const override;
+};
+}
+
+#endif // LLVM_LIB_TARGET_BPF_BPFTARGETLOWERINGOBJECTFILE
diff --git a/llvm/lib/Target/BPF/BPFTargetMachine.cpp b/llvm/lib/Target/BPF/BPFTargetMachine.cpp
index 527a480354571..ba800f484d791 100644
--- a/llvm/lib/Target/BPF/BPFTargetMachine.cpp
+++ b/llvm/lib/Target/BPF/BPFTargetMachine.cpp
@@ -13,6 +13,7 @@
#include "BPFTargetMachine.h"
#include "BPF.h"
#include "BPFTargetTransformInfo.h"
+#include "BPFTargetLoweringObjectFile.h"
#include "MCTargetDesc/BPFMCAsmInfo.h"
#include "TargetInfo/BPFTargetInfo.h"
#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
@@ -80,7 +81,7 @@ BPFTargetMachine::BPFTargetMachine(const Target &T, const Triple &TT,
: CodeGenTargetMachineImpl(T, computeDataLayout(TT), TT, CPU, FS, Options,
getEffectiveRelocModel(RM),
getEffectiveCodeModel(CM, CodeModel::Small), OL),
- TLOF(std::make_unique<TargetLoweringObjectFileELF>()),
+ TLOF(std::make_unique<BPFTargetLoweringObjectFileELF>()),
Subtarget(TT, std::string(CPU), std::string(FS), *this) {
if (!DisableCheckUnreachable) {
this->Options.TrapUnreachable = true;
diff --git a/llvm/lib/Target/BPF/CMakeLists.txt b/llvm/lib/Target/BPF/CMakeLists.txt
index eade4cacb7100..3678f1335ca36 100644
--- a/llvm/lib/Target/BPF/CMakeLists.txt
+++ b/llvm/lib/Target/BPF/CMakeLists.txt
@@ -37,6 +37,7 @@ add_llvm_target(BPFCodeGen
BPFRegisterInfo.cpp
BPFSelectionDAGInfo.cpp
BPFSubtarget.cpp
+ BPFTargetLoweringObjectFile.cpp
BPFTargetMachine.cpp
BPFMIPeephole.cpp
BPFMIChecking.cpp
diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
index 958790d49d087..7165a88fb17e7 100644
--- a/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
+++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
@@ -34,6 +34,7 @@ class BPFAsmBackend : public MCAsmBackend {
createObjectTargetWriter() const override;
MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;
+ std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;
bool writeNopData(raw_ostream &OS, uint64_t Count,
const MCSubtargetInfo *STI) const override;
@@ -54,6 +55,18 @@ MCFixupKindInfo BPFAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
return Infos[Kind - FirstTargetFixupKind];
}
+std::optional<MCFixupKind> BPFAsmBackend::getFixupKind(StringRef Name) const {
+ if (Name == "FK_SecRel_8")
+ return FK_SecRel_8;
+ if (Name == "FK_BPF_PCRel_4")
+ return BPF::FK_BPF_PCRel_4;
+ if (Name == "FK_Data_8")
+ return FK_Data_8;
+ if (Name == "FK_Data_4")
+ return FK_Data_4;
+ return std::nullopt;
+}
+
bool BPFAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
const MCSubtargetInfo *STI) const {
if ((Count % 8) != 0)
More information about the llvm-commits
mailing list