summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/BPF
diff options
context:
space:
mode:
authorAlexei Starovoitov <alexei.starovoitov@gmail.com>2017-11-19 01:35:00 +0000
committerAlexei Starovoitov <alexei.starovoitov@gmail.com>2017-11-19 01:35:00 +0000
commit9a67245d881f4cf89fd8f897ae2cd0bccec49496 (patch)
treebe1166344599d69ad93901682d2f9d9ecf0f5e76 /llvm/lib/Target/BPF
parent9a94dfc457443b263ded785722bdd085cb05ab22 (diff)
downloadbcm5719-llvm-9a67245d881f4cf89fd8f897ae2cd0bccec49496.tar.gz
bcm5719-llvm-9a67245d881f4cf89fd8f897ae2cd0bccec49496.zip
[bpf] allow direct and indirect calls
kernel verifier is becoming smarter and soon will support direct and indirect function calls. Remove obsolete error from BPF backend. Make call to use PCRel_4 fixup. 'bpf to bpf' calls are distinguished from 'bpf to kernel' calls by insn->src_reg == BPF_PSEUDO_CALL == 1 which is used as relocation indicator similar to ld_imm64->src_reg == BPF_PSEUDO_MAP_FD == 1 The actual 'call' instruction remains the same for both 'bpf to kernel' and 'bpf to bpf' calls. Signed-off-by: Alexei Starovoitov <ast@kernel.org> llvm-svn: 318614
Diffstat (limited to 'llvm/lib/Target/BPF')
-rw-r--r--llvm/lib/Target/BPF/BPFISelLowering.cpp7
-rw-r--r--llvm/lib/Target/BPF/BPFInstrInfo.td14
-rw-r--r--llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp9
-rw-r--r--llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp1
-rw-r--r--llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp2
5 files changed, 25 insertions, 8 deletions
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.cpp b/llvm/lib/Target/BPF/BPFISelLowering.cpp
index 995f206529f..f9078fae028 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.cpp
+++ b/llvm/lib/Target/BPF/BPFISelLowering.cpp
@@ -330,13 +330,6 @@ SDValue BPFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// Likewise ExternalSymbol -> TargetExternalSymbol.
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
auto GV = G->getGlobal();
- fail(CLI.DL, DAG,
- "A call to global function '" + StringRef(GV->getName())
- + "' is not supported. "
- + (GV->isDeclaration() ?
- "Only calls to predefined BPF helpers are allowed." :
- "Please use __attribute__((always_inline) to make sure"
- " this function is inlined."));
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), CLI.DL, PtrVT,
G->getOffset(), 0);
} else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) {
diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td
index 27b26b987fa..126d55fc28d 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.td
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.td
@@ -400,6 +400,18 @@ class CALL<string OpcodeStr>
let BPFClass = BPF_JMP;
}
+class CALLX<string OpcodeStr>
+ : TYPE_ALU_JMP<BPF_CALL.Value, BPF_X.Value,
+ (outs),
+ (ins calltarget:$BrDst),
+ !strconcat(OpcodeStr, " $BrDst"),
+ []> {
+ bits<32> BrDst;
+
+ let Inst{31-0} = BrDst;
+ let BPFClass = BPF_JMP;
+}
+
// Jump always
let isBranch = 1, isTerminator = 1, hasDelaySlot=0, isBarrier = 1 in {
def JMP : BRANCH<BPF_JA, "goto", [(br bb:$BrDst)]>;
@@ -410,6 +422,7 @@ let isCall=1, hasDelaySlot=0, Uses = [R11],
// Potentially clobbered registers
Defs = [R0, R1, R2, R3, R4, R5] in {
def JAL : CALL<"call">;
+ def JALX : CALLX<"callx">;
}
class NOP_I<string OpcodeStr>
@@ -476,6 +489,7 @@ def : Pat<(i64 (and (i64 GPR:$src), 0xffffFFFF)),
def : Pat<(BPFcall tglobaladdr:$dst), (JAL tglobaladdr:$dst)>;
def : Pat<(BPFcall texternalsym:$dst), (JAL texternalsym:$dst)>;
def : Pat<(BPFcall imm:$dst), (JAL imm:$dst)>;
+def : Pat<(BPFcall GPR:$dst), (JALX GPR:$dst)>;
// Loads
def : Pat<(extloadi8 ADDRri:$src), (i64 (LDB ADDRri:$src))>;
diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
index 800700d3dad..e6ea92e0836 100644
--- a/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
+++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
@@ -76,6 +76,15 @@ void BPFAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
unsigned Idx = IsLittleEndian ? i : Size - i - 1;
Data[Fixup.getOffset() + Idx] = uint8_t(Value >> (i * 8));
}
+ } else if (Fixup.getKind() == FK_PCRel_4) {
+ Value = (uint32_t)((Value - 8) / 8);
+ if (IsLittleEndian) {
+ Data[Fixup.getOffset() + 1] = 0x10;
+ support::endian::write32le(&Data[Fixup.getOffset() + 4], Value);
+ } else {
+ Data[Fixup.getOffset() + 1] = 0x1;
+ support::endian::write32be(&Data[Fixup.getOffset() + 4], Value);
+ }
} else {
assert(Fixup.getKind() == FK_PCRel_2);
Value = (uint16_t)((Value - 8) / 8);
diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp
index 144ea2b697d..f7de612dab1 100644
--- a/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp
+++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp
@@ -44,6 +44,7 @@ unsigned BPFELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
llvm_unreachable("invalid fixup kind!");
case FK_SecRel_8:
return ELF::R_BPF_64_64;
+ case FK_PCRel_4:
case FK_SecRel_4:
return ELF::R_BPF_64_32;
case FK_Data_8:
diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp
index e8c97447982..b4ecfdee7bf 100644
--- a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp
+++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp
@@ -100,7 +100,7 @@ unsigned BPFMCCodeEmitter::getMachineOpValue(const MCInst &MI,
if (MI.getOpcode() == BPF::JAL)
// func call name
- Fixups.push_back(MCFixup::create(0, Expr, FK_SecRel_4));
+ Fixups.push_back(MCFixup::create(0, Expr, FK_PCRel_4));
else if (MI.getOpcode() == BPF::LD_imm64)
Fixups.push_back(MCFixup::create(0, Expr, FK_SecRel_8));
else
OpenPOWER on IntegriCloud