Skip to content
Permalink
Browse files

BPF backend

Summary:
V8->V9:
- cleanup tests

V7->V8:
- addressed feedback from David:
- switched to range-based 'for' loops
- fixed formatting of tests

V6->V7:
- rebased and adjusted AsmPrinter args
- CamelCased .td, fixed formatting, cleaned up names, removed unused patterns
- diffstat: 3 files changed, 203 insertions(+), 227 deletions(-)

V5->V6:
- addressed feedback from Chandler:
- reinstated full verbose standard banner in all files
- fixed variables that were not in CamelCase
- fixed names of #ifdef in header files
- removed redundant braces in if/else chains with single statements
- fixed comments
- removed trailing empty line
- dropped debug annotations from tests
- diffstat of these changes:
  46 files changed, 456 insertions(+), 469 deletions(-)

V4->V5:
- fix setLoadExtAction() interface
- clang-formated all where it made sense

V3->V4:
- added CODE_OWNERS entry for BPF backend

V2->V3:
- fix metadata in tests

V1->V2:
- addressed feedback from Tom and Matt
- removed top level change to configure (now everything via 'experimental-backend')
- reworked error reporting via DiagnosticInfo (similar to R600)
- added few more tests
- added cmake build
- added Triple::bpf
- tested on linux and darwin

V1 cover letter:
---------------------
recently linux gained "universal in-kernel virtual machine" which is called
eBPF or extended BPF. The name comes from "Berkeley Packet Filter", since
new instruction set is based on it.
This patch adds a new backend that emits extended BPF instruction set.

The concept and development are covered by the following articles:
http://lwn.net/Articles/599755/
http://lwn.net/Articles/575531/
http://lwn.net/Articles/603983/
http://lwn.net/Articles/606089/
http://lwn.net/Articles/612878/

One of use cases: dtrace/systemtap alternative.

bpf syscall manpage:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=b4fc1a460f3017e958e6a8ea560ea0afd91bf6fe

instruction set description and differences vs classic BPF:
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/networking/filter.txt

Short summary of instruction set:
- 64-bit registers
  R0      - return value from in-kernel function, and exit value for BPF program
  R1 - R5 - arguments from BPF program to in-kernel function
  R6 - R9 - callee saved registers that in-kernel function will preserve
  R10     - read-only frame pointer to access stack
- two-operand instructions like +, -, *, mov, load/store
- implicit prologue/epilogue (invisible stack pointer)
- no floating point, no simd

Short history of extended BPF in kernel:
interpreter in 3.15, x64 JIT in 3.16, arm64 JIT, verifier, bpf syscall in 3.18, more to come in the future.

It's a very small and simple backend.
There is no support for global variables, arbitrary function calls, floating point, varargs,
exceptions, indirect jumps, arbitrary pointer arithmetic, alloca, etc.
From C front-end point of view it's very restricted. It's done on purpose, since kernel
rejects all programs that it cannot prove safe. It rejects programs with loops
and with memory accesses via arbitrary pointers. When kernel accepts the program it is
guaranteed that program will terminate and will not crash the kernel.

This patch implements all 'must have' bits. There are several things on TODO list,
so this is not the end of development.
Most of the code is a boiler plate code, copy-pasted from other backends.
Only odd things are lack or < and <= instructions, specialized load_byte intrinsics
and 'compare and goto' as single instruction.
Current instruction set is fixed, but more instructions can be added in the future.

Signed-off-by: Alexei Starovoitov <alexei.starovoitov@gmail.com>

Subscribers: majnemer, chandlerc, echristo, joerg, pete, rengolin, kristof.beyls, arsenm, t.p.northover, tstellarAMD, aemerson, llvm-commits

Differential Revision: http://reviews.llvm.org/D6494

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227008 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information...
4ast committed Jan 24, 2015
1 parent 211422d commit 4fe85c75482f9d11c5a1f92a1863ce30afad8d0d
Showing with 4,644 additions and 1 deletion.
  1. +4 −0 CODE_OWNERS.TXT
  2. +1 −0 include/llvm/ADT/Triple.h
  3. +1 −0 include/llvm/IR/Intrinsics.td
  4. +22 −0 include/llvm/IR/IntrinsicsBPF.td
  5. +8 −0 lib/Support/Triple.cpp
  6. +22 −0 lib/Target/BPF/BPF.h
  7. +31 −0 lib/Target/BPF/BPF.td
  8. +87 −0 lib/Target/BPF/BPFAsmPrinter.cpp
  9. +29 −0 lib/Target/BPF/BPFCallingConv.td
  10. +39 −0 lib/Target/BPF/BPFFrameLowering.cpp
  11. +41 −0 lib/Target/BPF/BPFFrameLowering.h
  12. +159 −0 lib/Target/BPF/BPFISelDAGToDAG.cpp
  13. +642 −0 lib/Target/BPF/BPFISelLowering.cpp
  14. +89 −0 lib/Target/BPF/BPFISelLowering.h
  15. +33 −0 lib/Target/BPF/BPFInstrFormats.td
  16. +168 −0 lib/Target/BPF/BPFInstrInfo.cpp
  17. +60 −0 lib/Target/BPF/BPFInstrInfo.h
  18. +507 −0 lib/Target/BPF/BPFInstrInfo.td
  19. +77 −0 lib/Target/BPF/BPFMCInstLower.cpp
  20. +43 −0 lib/Target/BPF/BPFMCInstLower.h
  21. +88 −0 lib/Target/BPF/BPFRegisterInfo.cpp
  22. +41 −0 lib/Target/BPF/BPFRegisterInfo.h
  23. +41 −0 lib/Target/BPF/BPFRegisterInfo.td
  24. +31 −0 lib/Target/BPF/BPFSubtarget.cpp
  25. +66 −0 lib/Target/BPF/BPFSubtarget.h
  26. +68 −0 lib/Target/BPF/BPFTargetMachine.cpp
  27. +40 −0 lib/Target/BPF/BPFTargetMachine.h
  28. +27 −0 lib/Target/BPF/CMakeLists.txt
  29. +86 −0 lib/Target/BPF/InstPrinter/BPFInstPrinter.cpp
  30. +41 −0 lib/Target/BPF/InstPrinter/BPFInstPrinter.h
  31. +3 −0 lib/Target/BPF/InstPrinter/CMakeLists.txt
  32. +23 −0 lib/Target/BPF/InstPrinter/LLVMBuild.txt
  33. +16 −0 lib/Target/BPF/InstPrinter/Makefile
  34. +32 −0 lib/Target/BPF/LLVMBuild.txt
  35. +83 −0 lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
  36. +53 −0 lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp
  37. +36 −0 lib/Target/BPF/MCTargetDesc/BPFMCAsmInfo.h
  38. +167 −0 lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp
  39. +111 −0 lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp
  40. +59 −0 lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h
  41. +6 −0 lib/Target/BPF/MCTargetDesc/CMakeLists.txt
  42. +23 −0 lib/Target/BPF/MCTargetDesc/LLVMBuild.txt
  43. +16 −0 lib/Target/BPF/MCTargetDesc/Makefile
  44. +21 −0 lib/Target/BPF/Makefile
  45. +18 −0 lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp
  46. +3 −0 lib/Target/BPF/TargetInfo/CMakeLists.txt
  47. +23 −0 lib/Target/BPF/TargetInfo/LLVMBuild.txt
  48. +16 −0 lib/Target/BPF/TargetInfo/Makefile
  49. +1 −1 lib/Target/LLVMBuild.txt
  50. +46 −0 test/CodeGen/BPF/alu8.ll
  51. +20 −0 test/CodeGen/BPF/atomics.ll
  52. +28 −0 test/CodeGen/BPF/basictest.ll
  53. +27 −0 test/CodeGen/BPF/byval.ll
  54. +96 −0 test/CodeGen/BPF/cc_args.ll
  55. +48 −0 test/CodeGen/BPF/cc_ret.ll
  56. +119 −0 test/CodeGen/BPF/cmp.ll
  57. +46 −0 test/CodeGen/BPF/ex1.ll
  58. +50 −0 test/CodeGen/BPF/intrinsics.ll
  59. +43 −0 test/CodeGen/BPF/load.ll
  60. +111 −0 test/CodeGen/BPF/loops.ll
  61. +12 −0 test/CodeGen/BPF/many_args1.ll
  62. +15 −0 test/CodeGen/BPF/many_args2.ll
  63. +117 −0 test/CodeGen/BPF/sanity.ll
  64. +99 −0 test/CodeGen/BPF/setcc.ll
  65. +101 −0 test/CodeGen/BPF/shifts.ll
  66. +326 −0 test/CodeGen/BPF/sockex2.ll
  67. +17 −0 test/CodeGen/BPF/struct_ret1.ll
  68. +12 −0 test/CodeGen/BPF/struct_ret2.ll
  69. +9 −0 test/CodeGen/BPF/vararg1.ll
@@ -146,6 +146,10 @@ N: Michael Spencer
E: bigcheesegs@gmail.com
D: Windows parts of Support, Object, ar, nm, objdump, ranlib, size

N: Alexei Starovoitov
E: alexei.starovoitov@gmail.com
D: BPF backend

N: Tom Stellard
E: thomas.stellard@amd.com
E: mesa-dev@lists.freedesktop.org
@@ -50,6 +50,7 @@ class Triple {
armeb, // ARM (big endian): armeb
aarch64, // AArch64 (little endian): aarch64
aarch64_be, // AArch64 (big endian): aarch64_be
bpf, // eBPF or extended BPF or 64-bit BPF (little endian)
hexagon, // Hexagon: hexagon
mips, // MIPS: mips, mipsallegrex
mipsel, // MIPSEL: mipsel, mipsallegrexel
@@ -597,3 +597,4 @@ include "llvm/IR/IntrinsicsHexagon.td"
include "llvm/IR/IntrinsicsNVVM.td"
include "llvm/IR/IntrinsicsMips.td"
include "llvm/IR/IntrinsicsR600.td"
include "llvm/IR/IntrinsicsBPF.td"
@@ -0,0 +1,22 @@
//===- IntrinsicsBPF.td - Defines BPF intrinsics -----------*- tablegen -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines all of the BPF-specific intrinsics.
//
//===----------------------------------------------------------------------===//

// Specialized loads from packet
let TargetPrefix = "bpf" in { // All intrinsics start with "llvm.bpf."
def int_bpf_load_byte : GCCBuiltin<"__builtin_bpf_load_byte">,
Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>;
def int_bpf_load_half : GCCBuiltin<"__builtin_bpf_load_half">,
Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>;
def int_bpf_load_word : GCCBuiltin<"__builtin_bpf_load_word">,
Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>;
}
@@ -23,6 +23,7 @@ const char *Triple::getArchTypeName(ArchType Kind) {
case aarch64_be: return "aarch64_be";
case arm: return "arm";
case armeb: return "armeb";
case bpf: return "bpf";
case hexagon: return "hexagon";
case mips: return "mips";
case mipsel: return "mipsel";
@@ -86,6 +87,8 @@ const char *Triple::getArchTypePrefix(ArchType Kind) {
case amdgcn:
case r600: return "amdgpu";

case bpf: return "bpf";

case sparcv9:
case sparc: return "sparc";

@@ -191,6 +194,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
.Case("arm64", aarch64) // "arm64" is an alias for "aarch64"
.Case("arm", arm)
.Case("armeb", armeb)
.Case("bpf", bpf)
.Case("mips", mips)
.Case("mipsel", mipsel)
.Case("mips64", mips64)
@@ -290,6 +294,7 @@ static Triple::ArchType parseArch(StringRef ArchName) {
.Case("mips64el", Triple::mips64el)
.Case("r600", Triple::r600)
.Case("amdgcn", Triple::amdgcn)
.Case("bpf", Triple::bpf)
.Case("hexagon", Triple::hexagon)
.Case("s390x", Triple::systemz)
.Case("sparc", Triple::sparc)
@@ -869,6 +874,7 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
case llvm::Triple::amdgcn:
case llvm::Triple::bpf:
case llvm::Triple::le64:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
@@ -905,6 +911,7 @@ Triple Triple::get32BitArchVariant() const {
case Triple::aarch64:
case Triple::aarch64_be:
case Triple::amdgcn:
case Triple::bpf:
case Triple::msp430:
case Triple::systemz:
case Triple::ppc64le:
@@ -966,6 +973,7 @@ Triple Triple::get64BitArchVariant() const {

case Triple::aarch64:
case Triple::aarch64_be:
case Triple::bpf:
case Triple::le64:
case Triple::amdil64:
case Triple::amdgcn:
@@ -0,0 +1,22 @@
//===-- BPF.h - Top-level interface for BPF representation ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_BPF_BPF_H
#define LLVM_LIB_TARGET_BPF_BPF_H

#include "MCTargetDesc/BPFMCTargetDesc.h"
#include "llvm/Target/TargetMachine.h"

namespace llvm {
class BPFTargetMachine;

FunctionPass *createBPFISelDag(BPFTargetMachine &TM);
}

#endif
@@ -0,0 +1,31 @@
//===-- BPF.td - Describe the BPF Target Machine -----------*- tablegen -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

include "llvm/Target/Target.td"

include "BPFRegisterInfo.td"
include "BPFCallingConv.td"
include "BPFInstrInfo.td"

def BPFInstrInfo : InstrInfo;

class Proc<string Name, list<SubtargetFeature> Features>
: Processor<Name, NoItineraries, Features>;

def : Proc<"generic", []>;

def BPFInstPrinter : AsmWriter {
string AsmWriterClassName = "InstPrinter";
bit isMCAsmWriter = 1;
}

def BPF : Target {
let InstructionSet = BPFInstrInfo;
let AssemblyWriters = [BPFInstPrinter];
}
@@ -0,0 +1,87 @@
//===-- BPFAsmPrinter.cpp - BPF LLVM assembly writer ----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to the BPF assembly language.
//
//===----------------------------------------------------------------------===//

#include "BPF.h"
#include "BPFInstrInfo.h"
#include "BPFMCInstLower.h"
#include "BPFTargetMachine.h"
#include "InstPrinter/BPFInstPrinter.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

#define DEBUG_TYPE "asm-printer"

namespace {
class BPFAsmPrinter : public AsmPrinter {
public:
explicit BPFAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
: AsmPrinter(TM, std::move(Streamer)) {}

const char *getPassName() const override { return "BPF Assembly Printer"; }

void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
const char *Modifier = nullptr);
void EmitInstruction(const MachineInstr *MI) override;
};
}

void BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
raw_ostream &O, const char *Modifier) {
const MachineOperand &MO = MI->getOperand(OpNum);

switch (MO.getType()) {
case MachineOperand::MO_Register:
O << BPFInstPrinter::getRegisterName(MO.getReg());
break;

case MachineOperand::MO_Immediate:
O << MO.getImm();
break;

case MachineOperand::MO_MachineBasicBlock:
O << *MO.getMBB()->getSymbol();
break;

case MachineOperand::MO_GlobalAddress:
O << *getSymbol(MO.getGlobal());
break;

default:
llvm_unreachable("<unknown operand type>");
}
}

void BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) {

BPFMCInstLower MCInstLowering(OutContext, *this);

MCInst TmpInst;
MCInstLowering.Lower(MI, TmpInst);
EmitToStreamer(OutStreamer, TmpInst);
}

// Force static initialization.
extern "C" void LLVMInitializeBPFAsmPrinter() {
RegisterAsmPrinter<BPFAsmPrinter> X(TheBPFTarget);
}
@@ -0,0 +1,29 @@
//===-- BPFCallingConv.td - Calling Conventions BPF --------*- tablegen -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This describes the calling conventions for the BPF architecture.
//
//===----------------------------------------------------------------------===//

// BPF 64-bit C return-value convention.
def RetCC_BPF64 : CallingConv<[CCIfType<[i64], CCAssignToReg<[R0]>>]>;

// BPF 64-bit C Calling convention.
def CC_BPF64 : CallingConv<[
// Promote i8/i16/i32 args to i64
CCIfType<[ i8, i16, i32 ], CCPromoteToType<i64>>,

// All arguments get passed in integer registers if there is space.
CCIfType<[i64], CCAssignToReg<[ R1, R2, R3, R4, R5 ]>>,

// Could be assigned to the stack in 8-byte aligned units, but unsupported
CCAssignToStack<8, 8>
]>;

def CSR : CalleeSavedRegs<(add R6, R7, R8, R9, R10)>;
@@ -0,0 +1,39 @@
//===-- BPFFrameLowering.cpp - BPF Frame Information ----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the BPF implementation of TargetFrameLowering class.
//
//===----------------------------------------------------------------------===//

#include "BPFFrameLowering.h"
#include "BPFInstrInfo.h"
#include "BPFSubtarget.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"

using namespace llvm;

bool BPFFrameLowering::hasFP(const MachineFunction &MF) const { return true; }

void BPFFrameLowering::emitPrologue(MachineFunction &MF) const {}

void BPFFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {}

void BPFFrameLowering::processFunctionBeforeCalleeSavedScan(
MachineFunction &MF, RegScavenger *RS) const {
MachineRegisterInfo &MRI = MF.getRegInfo();

MRI.setPhysRegUnused(BPF::R6);
MRI.setPhysRegUnused(BPF::R7);
MRI.setPhysRegUnused(BPF::R8);
MRI.setPhysRegUnused(BPF::R9);
}
@@ -0,0 +1,41 @@
//===-- BPFFrameLowering.h - Define frame lowering for BPF -----*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class implements BPF-specific bits of TargetFrameLowering class.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_BPF_BPFFRAMELOWERING_H
#define LLVM_LIB_TARGET_BPF_BPFFRAMELOWERING_H

#include "llvm/Target/TargetFrameLowering.h"

namespace llvm {
class BPFSubtarget;

class BPFFrameLowering : public TargetFrameLowering {
public:
explicit BPFFrameLowering(const BPFSubtarget &sti)
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 8, 0) {}

void emitPrologue(MachineFunction &MF) const override;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;

bool hasFP(const MachineFunction &MF) const override;
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
RegScavenger *RS) const override;

void
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI) const override {
MBB.erase(MI);
}
};
}
#endif

0 comments on commit 4fe85c7

Please sign in to comment.
You can’t perform that action at this time.