aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/BPF
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/BPF')
-rw-r--r--lib/Target/BPF/AsmParser/BPFAsmParser.cpp498
-rw-r--r--lib/Target/BPF/AsmParser/CMakeLists.txt3
-rw-r--r--lib/Target/BPF/AsmParser/LLVMBuild.txt23
-rw-r--r--lib/Target/BPF/BPF.td6
-rw-r--r--lib/Target/BPF/BPFAsmPrinter.cpp77
-rw-r--r--lib/Target/BPF/BPFFrameLowering.h2
-rw-r--r--lib/Target/BPF/BPFISelDAGToDAG.cpp51
-rw-r--r--lib/Target/BPF/BPFISelLowering.cpp55
-rw-r--r--lib/Target/BPF/BPFISelLowering.h11
-rw-r--r--lib/Target/BPF/BPFInstrFormats.td85
-rw-r--r--lib/Target/BPF/BPFInstrInfo.h2
-rw-r--r--lib/Target/BPF/BPFInstrInfo.td544
-rw-r--r--lib/Target/BPF/BPFRegisterInfo.cpp10
-rw-r--r--lib/Target/BPF/BPFRegisterInfo.h2
-rw-r--r--lib/Target/BPF/BPFRegisterInfo.td53
-rw-r--r--lib/Target/BPF/BPFSubtarget.cpp26
-rw-r--r--lib/Target/BPF/BPFSubtarget.h17
-rw-r--r--lib/Target/BPF/BPFTargetMachine.cpp12
-rw-r--r--lib/Target/BPF/BPFTargetMachine.h4
-rw-r--r--lib/Target/BPF/CMakeLists.txt1
-rw-r--r--lib/Target/BPF/Disassembler/BPFDisassembler.cpp18
-rw-r--r--lib/Target/BPF/InstPrinter/BPFInstPrinter.cpp15
-rw-r--r--lib/Target/BPF/InstPrinter/BPFInstPrinter.h1
-rw-r--r--lib/Target/BPF/LLVMBuild.txt2
-rw-r--r--lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp15
-rw-r--r--lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp11
-rw-r--r--lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp2
-rw-r--r--lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp44
-rw-r--r--lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h7
-rw-r--r--lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp9
30 files changed, 1254 insertions, 352 deletions
diff --git a/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
new file mode 100644
index 000000000000..deaa11325809
--- /dev/null
+++ b/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
@@ -0,0 +1,498 @@
+//===-- BPFAsmParser.cpp - Parse BPF assembly to MCInst instructions --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/BPFMCTargetDesc.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+namespace {
+struct BPFOperand;
+
+class BPFAsmParser : public MCTargetAsmParser {
+
+ SMLoc getLoc() const { return getParser().getTok().getLoc(); }
+
+ bool PreMatchCheck(OperandVector &Operands);
+
+ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
+ OperandVector &Operands, MCStreamer &Out,
+ uint64_t &ErrorInfo,
+ bool MatchingInlineAsm) override;
+
+ bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+
+ bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
+ SMLoc NameLoc, OperandVector &Operands) override;
+
+ bool ParseDirective(AsmToken DirectiveID) override;
+
+ // "=" is used as assignment operator for assembly statment, so can't be used
+ // for symbol assignment.
+ bool equalIsAsmAssignment() override { return false; }
+ // "*" is used for dereferencing memory that it will be the start of
+ // statement.
+ bool starIsStartOfStatement() override { return true; }
+
+#define GET_ASSEMBLER_HEADER
+#include "BPFGenAsmMatcher.inc"
+
+ OperandMatchResultTy parseImmediate(OperandVector &Operands);
+ OperandMatchResultTy parseRegister(OperandVector &Operands);
+ OperandMatchResultTy parseOperandAsOperator(OperandVector &Operands);
+
+public:
+ enum BPFMatchResultTy {
+ Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
+#define GET_OPERAND_DIAGNOSTIC_TYPES
+#include "BPFGenAsmMatcher.inc"
+#undef GET_OPERAND_DIAGNOSTIC_TYPES
+ };
+
+ BPFAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
+ const MCInstrInfo &MII, const MCTargetOptions &Options)
+ : MCTargetAsmParser(Options, STI, MII) {
+ setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
+ }
+};
+
+/// BPFOperand - Instances of this class represent a parsed machine
+/// instruction
+struct BPFOperand : public MCParsedAsmOperand {
+
+ enum KindTy {
+ Token,
+ Register,
+ Immediate,
+ } Kind;
+
+ struct RegOp {
+ unsigned RegNum;
+ };
+
+ struct ImmOp {
+ const MCExpr *Val;
+ };
+
+ SMLoc StartLoc, EndLoc;
+ union {
+ StringRef Tok;
+ RegOp Reg;
+ ImmOp Imm;
+ };
+
+ BPFOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
+
+public:
+ BPFOperand(const BPFOperand &o) : MCParsedAsmOperand() {
+ Kind = o.Kind;
+ StartLoc = o.StartLoc;
+ EndLoc = o.EndLoc;
+
+ switch (Kind) {
+ case Register:
+ Reg = o.Reg;
+ break;
+ case Immediate:
+ Imm = o.Imm;
+ break;
+ case Token:
+ Tok = o.Tok;
+ break;
+ }
+ }
+
+ bool isToken() const override { return Kind == Token; }
+ bool isReg() const override { return Kind == Register; }
+ bool isImm() const override { return Kind == Immediate; }
+ bool isMem() const override { return false; }
+
+ bool isConstantImm() const {
+ return isImm() && dyn_cast<MCConstantExpr>(getImm());
+ }
+
+ int64_t getConstantImm() const {
+ const MCExpr *Val = getImm();
+ return static_cast<const MCConstantExpr *>(Val)->getValue();
+ }
+
+ bool isSImm12() const {
+ return (isConstantImm() && isInt<12>(getConstantImm()));
+ }
+
+ /// getStartLoc - Gets location of the first token of this operand
+ SMLoc getStartLoc() const override { return StartLoc; }
+ /// getEndLoc - Gets location of the last token of this operand
+ SMLoc getEndLoc() const override { return EndLoc; }
+
+ unsigned getReg() const override {
+ assert(Kind == Register && "Invalid type access!");
+ return Reg.RegNum;
+ }
+
+ const MCExpr *getImm() const {
+ assert(Kind == Immediate && "Invalid type access!");
+ return Imm.Val;
+ }
+
+ StringRef getToken() const {
+ assert(Kind == Token && "Invalid type access!");
+ return Tok;
+ }
+
+ void print(raw_ostream &OS) const override {
+ switch (Kind) {
+ case Immediate:
+ OS << *getImm();
+ break;
+ case Register:
+ OS << "<register x";
+ OS << getReg() << ">";
+ break;
+ case Token:
+ OS << "'" << getToken() << "'";
+ break;
+ }
+ }
+
+ void addExpr(MCInst &Inst, const MCExpr *Expr) const {
+ assert(Expr && "Expr shouldn't be null!");
+
+ if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
+ Inst.addOperand(MCOperand::createImm(CE->getValue()));
+ else
+ Inst.addOperand(MCOperand::createExpr(Expr));
+ }
+
+ // Used by the TableGen Code
+ void addRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createReg(getReg()));
+ }
+
+ void addImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ addExpr(Inst, getImm());
+ }
+
+ static std::unique_ptr<BPFOperand> createToken(StringRef Str, SMLoc S) {
+ auto Op = make_unique<BPFOperand>(Token);
+ Op->Tok = Str;
+ Op->StartLoc = S;
+ Op->EndLoc = S;
+ return Op;
+ }
+
+ static std::unique_ptr<BPFOperand> createReg(unsigned RegNo, SMLoc S,
+ SMLoc E) {
+ auto Op = make_unique<BPFOperand>(Register);
+ Op->Reg.RegNum = RegNo;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ static std::unique_ptr<BPFOperand> createImm(const MCExpr *Val, SMLoc S,
+ SMLoc E) {
+ auto Op = make_unique<BPFOperand>(Immediate);
+ Op->Imm.Val = Val;
+ Op->StartLoc = S;
+ Op->EndLoc = E;
+ return Op;
+ }
+
+ // Identifiers that can be used at the start of a statment.
+ static bool isValidIdAtStart(StringRef Name) {
+ return StringSwitch<bool>(Name.lower())
+ .Case("if", true)
+ .Case("call", true)
+ .Case("goto", true)
+ .Case("*", true)
+ .Case("exit", true)
+ .Case("lock", true)
+ .Case("ld_pseudo", true)
+ .Default(false);
+ }
+
+ // Identifiers that can be used in the middle of a statment.
+ static bool isValidIdInMiddle(StringRef Name) {
+ return StringSwitch<bool>(Name.lower())
+ .Case("u64", true)
+ .Case("u32", true)
+ .Case("u16", true)
+ .Case("u8", true)
+ .Case("be64", true)
+ .Case("be32", true)
+ .Case("be16", true)
+ .Case("le64", true)
+ .Case("le32", true)
+ .Case("le16", true)
+ .Case("goto", true)
+ .Case("ll", true)
+ .Case("skb", true)
+ .Case("s", true)
+ .Default(false);
+ }
+};
+} // end anonymous namespace.
+
+#define GET_REGISTER_MATCHER
+#define GET_MATCHER_IMPLEMENTATION
+#include "BPFGenAsmMatcher.inc"
+
+bool BPFAsmParser::PreMatchCheck(OperandVector &Operands) {
+
+ if (Operands.size() == 4) {
+ // check "reg1 = -reg2" and "reg1 = be16/be32/be64/le16/le32/le64 reg2",
+ // reg1 must be the same as reg2
+ BPFOperand &Op0 = (BPFOperand &)*Operands[0];
+ BPFOperand &Op1 = (BPFOperand &)*Operands[1];
+ BPFOperand &Op2 = (BPFOperand &)*Operands[2];
+ BPFOperand &Op3 = (BPFOperand &)*Operands[3];
+ if (Op0.isReg() && Op1.isToken() && Op2.isToken() && Op3.isReg()
+ && Op1.getToken() == "="
+ && (Op2.getToken() == "-" || Op2.getToken() == "be16"
+ || Op2.getToken() == "be32" || Op2.getToken() == "be64"
+ || Op2.getToken() == "le16" || Op2.getToken() == "le32"
+ || Op2.getToken() == "le64")
+ && Op0.getReg() != Op3.getReg())
+ return true;
+ }
+
+ return false;
+}
+
+bool BPFAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
+ OperandVector &Operands,
+ MCStreamer &Out, uint64_t &ErrorInfo,
+ bool MatchingInlineAsm) {
+ MCInst Inst;
+ SMLoc ErrorLoc;
+
+ if (PreMatchCheck(Operands))
+ return Error(IDLoc, "additional inst constraint not met");
+
+ switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
+ default:
+ break;
+ case Match_Success:
+ Inst.setLoc(IDLoc);
+ Out.EmitInstruction(Inst, getSTI());
+ return false;
+ case Match_MissingFeature:
+ return Error(IDLoc, "instruction use requires an option to be enabled");
+ case Match_MnemonicFail:
+ return Error(IDLoc, "unrecognized instruction mnemonic");
+ case Match_InvalidOperand:
+ ErrorLoc = IDLoc;
+
+ if (ErrorInfo != ~0U) {
+ if (ErrorInfo >= Operands.size())
+ return Error(ErrorLoc, "too few operands for instruction");
+
+ ErrorLoc = ((BPFOperand &)*Operands[ErrorInfo]).getStartLoc();
+
+ if (ErrorLoc == SMLoc())
+ ErrorLoc = IDLoc;
+ }
+
+ return Error(ErrorLoc, "invalid operand for instruction");
+ }
+
+ llvm_unreachable("Unknown match type detected!");
+}
+
+bool BPFAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+ SMLoc &EndLoc) {
+ const AsmToken &Tok = getParser().getTok();
+ StartLoc = Tok.getLoc();
+ EndLoc = Tok.getEndLoc();
+ RegNo = 0;
+ StringRef Name = getLexer().getTok().getIdentifier();
+
+ if (!MatchRegisterName(Name)) {
+ getParser().Lex(); // Eat identifier token.
+ return false;
+ }
+
+ return Error(StartLoc, "invalid register name");
+}
+
+OperandMatchResultTy
+BPFAsmParser::parseOperandAsOperator(OperandVector &Operands) {
+ SMLoc S = getLoc();
+
+ if (getLexer().getKind() == AsmToken::Identifier) {
+ StringRef Name = getLexer().getTok().getIdentifier();
+
+ if (BPFOperand::isValidIdInMiddle(Name)) {
+ getLexer().Lex();
+ Operands.push_back(BPFOperand::createToken(Name, S));
+ return MatchOperand_Success;
+ }
+
+ return MatchOperand_NoMatch;
+ }
+
+ switch (getLexer().getKind()) {
+ case AsmToken::Minus:
+ case AsmToken::Plus: {
+ if (getLexer().peekTok().is(AsmToken::Integer))
+ return MatchOperand_NoMatch;
+ }
+ // Fall through.
+
+ case AsmToken::Equal:
+ case AsmToken::Greater:
+ case AsmToken::Less:
+ case AsmToken::Pipe:
+ case AsmToken::Star:
+ case AsmToken::LParen:
+ case AsmToken::RParen:
+ case AsmToken::LBrac:
+ case AsmToken::RBrac:
+ case AsmToken::Slash:
+ case AsmToken::Amp:
+ case AsmToken::Percent:
+ case AsmToken::Caret: {
+ StringRef Name = getLexer().getTok().getString();
+ getLexer().Lex();
+ Operands.push_back(BPFOperand::createToken(Name, S));
+
+ return MatchOperand_Success;
+ }
+
+ case AsmToken::EqualEqual:
+ case AsmToken::ExclaimEqual:
+ case AsmToken::GreaterEqual:
+ case AsmToken::GreaterGreater:
+ case AsmToken::LessEqual:
+ case AsmToken::LessLess: {
+ Operands.push_back(BPFOperand::createToken(
+ getLexer().getTok().getString().substr(0, 1), S));
+ Operands.push_back(BPFOperand::createToken(
+ getLexer().getTok().getString().substr(1, 1), S));
+ getLexer().Lex();
+
+ return MatchOperand_Success;
+ }
+
+ default:
+ break;
+ }
+
+ return MatchOperand_NoMatch;
+}
+
+OperandMatchResultTy BPFAsmParser::parseRegister(OperandVector &Operands) {
+ SMLoc S = getLoc();
+ SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+
+ switch (getLexer().getKind()) {
+ default:
+ return MatchOperand_NoMatch;
+ case AsmToken::Identifier:
+ StringRef Name = getLexer().getTok().getIdentifier();
+ unsigned RegNo = MatchRegisterName(Name);
+
+ if (RegNo == 0)
+ return MatchOperand_NoMatch;
+
+ getLexer().Lex();
+ Operands.push_back(BPFOperand::createReg(RegNo, S, E));
+ }
+ return MatchOperand_Success;
+}
+
+OperandMatchResultTy BPFAsmParser::parseImmediate(OperandVector &Operands) {
+ switch (getLexer().getKind()) {
+ default:
+ return MatchOperand_NoMatch;
+ case AsmToken::LParen:
+ case AsmToken::Minus:
+ case AsmToken::Plus:
+ case AsmToken::Integer:
+ case AsmToken::String:
+ case AsmToken::Identifier:
+ break;
+ }
+
+ const MCExpr *IdVal;
+ SMLoc S = getLoc();
+
+ if (getParser().parseExpression(IdVal))
+ return MatchOperand_ParseFail;
+
+ SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+ Operands.push_back(BPFOperand::createImm(IdVal, S, E));
+
+ return MatchOperand_Success;
+}
+
+/// ParseInstruction - Parse an BPF instruction which is in BPF verifier
+/// format.
+bool BPFAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
+ SMLoc NameLoc, OperandVector &Operands) {
+ // The first operand could be either register or actually an operator.
+ unsigned RegNo = MatchRegisterName(Name);
+
+ if (RegNo != 0) {
+ SMLoc E = SMLoc::getFromPointer(NameLoc.getPointer() - 1);
+ Operands.push_back(BPFOperand::createReg(RegNo, NameLoc, E));
+ } else if (BPFOperand::isValidIdAtStart (Name))
+ Operands.push_back(BPFOperand::createToken(Name, NameLoc));
+ else
+ return true;
+
+ while (!getLexer().is(AsmToken::EndOfStatement)) {
+ // Attempt to parse token as operator
+ if (parseOperandAsOperator(Operands) == MatchOperand_Success)
+ continue;
+
+ // Attempt to parse token as register
+ if (parseRegister(Operands) == MatchOperand_Success)
+ continue;
+
+ // Attempt to parse token as an immediate
+ if (parseImmediate(Operands) != MatchOperand_Success)
+ return true;
+ }
+
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ SMLoc Loc = getLexer().getLoc();
+
+ getParser().eatToEndOfStatement();
+
+ return Error(Loc, "unexpected token");
+ }
+
+ // Consume the EndOfStatement.
+ getParser().Lex();
+ return false;
+}
+
+bool BPFAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
+
+extern "C" void LLVMInitializeBPFAsmParser() {
+ RegisterMCAsmParser<BPFAsmParser> X(getTheBPFTarget());
+ RegisterMCAsmParser<BPFAsmParser> Y(getTheBPFleTarget());
+ RegisterMCAsmParser<BPFAsmParser> Z(getTheBPFbeTarget());
+}
diff --git a/lib/Target/BPF/AsmParser/CMakeLists.txt b/lib/Target/BPF/AsmParser/CMakeLists.txt
new file mode 100644
index 000000000000..22fb4f048292
--- /dev/null
+++ b/lib/Target/BPF/AsmParser/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_llvm_library(LLVMBPFAsmParser
+ BPFAsmParser.cpp
+ )
diff --git a/lib/Target/BPF/AsmParser/LLVMBuild.txt b/lib/Target/BPF/AsmParser/LLVMBuild.txt
new file mode 100644
index 000000000000..2733da9d4a02
--- /dev/null
+++ b/lib/Target/BPF/AsmParser/LLVMBuild.txt
@@ -0,0 +1,23 @@
+;===- ./lib/Target/BPF/AsmParser/LLVMBuild.txt ---------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = BPFAsmParser
+parent = BPF
+required_libraries = MC MCParser BPFDesc BPFInfo Support
+add_to_library_groups = BPF
diff --git a/lib/Target/BPF/BPF.td b/lib/Target/BPF/BPF.td
index 11abe520c506..2d0c22a3a516 100644
--- a/lib/Target/BPF/BPF.td
+++ b/lib/Target/BPF/BPF.td
@@ -19,6 +19,12 @@ class Proc<string Name, list<SubtargetFeature> Features>
: Processor<Name, NoItineraries, Features>;
def : Proc<"generic", []>;
+def : Proc<"v1", []>;
+def : Proc<"v2", []>;
+def : Proc<"probe", []>;
+
+def DummyFeature : SubtargetFeature<"dummy", "isDummyMode",
+ "true", "unused feature">;
def BPFInstPrinter : AsmWriter {
string AsmWriterClassName = "InstPrinter";
diff --git a/lib/Target/BPF/BPFAsmPrinter.cpp b/lib/Target/BPF/BPFAsmPrinter.cpp
index 9397c78f3dff..705211b486bf 100644
--- a/lib/Target/BPF/BPFAsmPrinter.cpp
+++ b/lib/Target/BPF/BPFAsmPrinter.cpp
@@ -40,11 +40,88 @@ public:
: AsmPrinter(TM, std::move(Streamer)) {}
StringRef getPassName() const override { return "BPF Assembly Printer"; }
+ void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
+ bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+ unsigned AsmVariant, const char *ExtraCode,
+ raw_ostream &O) override;
+ bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
+ unsigned AsmVariant, const char *ExtraCode,
+ raw_ostream &O) override;
void EmitInstruction(const MachineInstr *MI) override;
};
} // namespace
+void BPFAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
+ raw_ostream &O) {
+ 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;
+
+ case MachineOperand::MO_BlockAddress: {
+ MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
+ O << BA->getName();
+ break;
+ }
+
+ case MachineOperand::MO_ExternalSymbol:
+ O << *GetExternalSymbolSymbol(MO.getSymbolName());
+ break;
+
+ case MachineOperand::MO_JumpTableIndex:
+ case MachineOperand::MO_ConstantPoolIndex:
+ default:
+ llvm_unreachable("<unknown operand type>");
+ }
+}
+
+bool BPFAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+ unsigned /*AsmVariant*/,
+ const char *ExtraCode, raw_ostream &O) {
+ if (ExtraCode && ExtraCode[0])
+ return true; // BPF does not have special modifiers
+
+ printOperand(MI, OpNo, O);
+ return false;
+}
+
+bool BPFAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
+ unsigned OpNum, unsigned AsmVariant,
+ const char *ExtraCode,
+ raw_ostream &O) {
+ assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands");
+ const MachineOperand &BaseMO = MI->getOperand(OpNum);
+ const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1);
+ assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand.");
+ assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand.");
+ int Offset = OffsetMO.getImm();
+
+ if (ExtraCode)
+ return true; // Unknown modifier.
+
+ if (Offset < 0)
+ O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " - " << -Offset << ")";
+ else
+ O << "(" << BPFInstPrinter::getRegisterName(BaseMO.getReg()) << " + " << Offset << ")";
+
+ return false;
+}
+
void BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) {
BPFMCInstLower MCInstLowering(OutContext, *this);
diff --git a/lib/Target/BPF/BPFFrameLowering.h b/lib/Target/BPF/BPFFrameLowering.h
index 5db963f518b1..b4ffa0713fa6 100644
--- a/lib/Target/BPF/BPFFrameLowering.h
+++ b/lib/Target/BPF/BPFFrameLowering.h
@@ -14,7 +14,7 @@
#ifndef LLVM_LIB_TARGET_BPF_BPFFRAMELOWERING_H
#define LLVM_LIB_TARGET_BPF_BPFFRAMELOWERING_H
-#include "llvm/Target/TargetFrameLowering.h"
+#include "llvm/CodeGen/TargetFrameLowering.h"
namespace llvm {
class BPFSubtarget;
diff --git a/lib/Target/BPF/BPFISelDAGToDAG.cpp b/lib/Target/BPF/BPFISelDAGToDAG.cpp
index f48429ee57b0..61b04d1f2a13 100644
--- a/lib/Target/BPF/BPFISelDAGToDAG.cpp
+++ b/lib/Target/BPF/BPFISelDAGToDAG.cpp
@@ -40,7 +40,9 @@ namespace {
class BPFDAGToDAGISel : public SelectionDAGISel {
public:
- explicit BPFDAGToDAGISel(BPFTargetMachine &TM) : SelectionDAGISel(TM) {}
+ explicit BPFDAGToDAGISel(BPFTargetMachine &TM) : SelectionDAGISel(TM) {
+ curr_func_ = nullptr;
+ }
StringRef getPassName() const override {
return "BPF DAG->DAG Pattern Instruction Selection";
@@ -48,6 +50,10 @@ public:
void PreprocessISelDAG() override;
+ bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode,
+ std::vector<SDValue> &OutOps) override;
+
+
private:
// Include the pieces autogenerated from the target description.
#include "BPFGenDAGISel.inc"
@@ -81,6 +87,8 @@ private:
std::map<const void *, val_vec_type> cs_vals_;
// Mapping from vreg to load memory opcode
std::map<unsigned, unsigned> load_to_vreg_;
+ // Current function
+ const Function *curr_func_;
};
} // namespace
@@ -145,6 +153,26 @@ bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base,
return false;
}
+bool BPFDAGToDAGISel::SelectInlineAsmMemoryOperand(
+ const SDValue &Op, unsigned ConstraintCode, std::vector<SDValue> &OutOps) {
+ SDValue Op0, Op1;
+ switch (ConstraintCode) {
+ default:
+ return true;
+ case InlineAsm::Constraint_m: // memory
+ if (!SelectAddr(Op, Op0, Op1))
+ return true;
+ break;
+ }
+
+ SDLoc DL(Op);
+ SDValue AluOp = CurDAG->getTargetConstant(ISD::ADD, DL, MVT::i32);;
+ OutOps.push_back(Op0);
+ OutOps.push_back(Op1);
+ OutOps.push_back(AluOp);
+ return false;
+}
+
void BPFDAGToDAGISel::Select(SDNode *Node) {
unsigned Opcode = Node->getOpcode();
@@ -305,6 +333,16 @@ void BPFDAGToDAGISel::PreprocessISelDAG() {
// are 32-bit registers, but later on, kernel verifier will rewrite
// it with 64-bit value. Therefore, truncating the value after the
// load will result in incorrect code.
+
+ // clear the load_to_vreg_ map so that we have a clean start
+ // for this function.
+ if (!curr_func_) {
+ curr_func_ = FuncInfo->Fn;
+ } else if (curr_func_ != FuncInfo->Fn) {
+ load_to_vreg_.clear();
+ curr_func_ = FuncInfo->Fn;
+ }
+
for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
E = CurDAG->allnodes_end();
I != E;) {
@@ -508,8 +546,7 @@ void BPFDAGToDAGISel::PreprocessTrunc(SDNode *Node,
if (!RegN || !TargetRegisterInfo::isVirtualRegister(RegN->getReg()))
return;
unsigned AndOpReg = RegN->getReg();
- DEBUG(dbgs() << "Examine %vreg" << TargetRegisterInfo::virtReg2Index(AndOpReg)
- << '\n');
+ DEBUG(dbgs() << "Examine " << printReg(AndOpReg) << '\n');
// Examine the PHI insns in the MachineBasicBlock to found out the
// definitions of this virtual register. At this stage (DAG2DAG
@@ -536,10 +573,10 @@ void BPFDAGToDAGISel::PreprocessTrunc(SDNode *Node,
return;
} else {
// The PHI node looks like:
- // %vreg2<def> = PHI %vreg0, <BB#1>, %vreg1, <BB#3>
- // Trace each incoming definition, e.g., (%vreg0, BB#1) and (%vreg1, BB#3)
- // The AND operation can be removed if both %vreg0 in BB#1 and %vreg1 in
- // BB#3 are defined with with a load matching the MaskN.
+ // %2 = PHI %0, <%bb.1>, %1, <%bb.3>
+ // Trace each incoming definition, e.g., (%0, %bb.1) and (%1, %bb.3)
+ // The AND operation can be removed if both %0 in %bb.1 and %1 in
+ // %bb.3 are defined with with a load matching the MaskN.
DEBUG(dbgs() << "Check PHI Insn: "; MII->dump(); dbgs() << '\n');
unsigned PrevReg = -1;
for (unsigned i = 0; i < MII->getNumOperands(); ++i) {
diff --git a/lib/Target/BPF/BPFISelLowering.cpp b/lib/Target/BPF/BPFISelLowering.cpp
index 5740b49f6a0f..3ea96e3148f2 100644
--- a/lib/Target/BPF/BPFISelLowering.cpp
+++ b/lib/Target/BPF/BPFISelLowering.cpp
@@ -36,7 +36,7 @@ using namespace llvm;
static void fail(const SDLoc &DL, SelectionDAG &DAG, const Twine &Msg) {
MachineFunction &MF = DAG.getMachineFunction();
DAG.getContext()->diagnose(
- DiagnosticInfoUnsupported(*MF.getFunction(), Msg, DL.getDebugLoc()));
+ DiagnosticInfoUnsupported(MF.getFunction(), Msg, DL.getDebugLoc()));
}
static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *Msg,
@@ -48,7 +48,7 @@ static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *Msg,
Val->print(OS);
OS.flush();
DAG.getContext()->diagnose(
- DiagnosticInfoUnsupported(*MF.getFunction(), Str, DL.getDebugLoc()));
+ DiagnosticInfoUnsupported(MF.getFunction(), Str, DL.getDebugLoc()));
}
BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM,
@@ -130,12 +130,31 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM,
MaxStoresPerMemset = MaxStoresPerMemsetOptSize = 128;
MaxStoresPerMemcpy = MaxStoresPerMemcpyOptSize = 128;
MaxStoresPerMemmove = MaxStoresPerMemmoveOptSize = 128;
+
+ // CPU/Feature control
+ HasJmpExt = STI.getHasJmpExt();
}
bool BPFTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
return false;
}
+std::pair<unsigned, const TargetRegisterClass *>
+BPFTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
+ StringRef Constraint,
+ MVT VT) const {
+ if (Constraint.size() == 1)
+ // GCC Constraint Letters
+ switch (Constraint[0]) {
+ case 'r': // GENERAL_REGS
+ return std::make_pair(0U, &BPF::GPRRegClass);
+ default:
+ break;
+ }
+
+ return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
+}
+
SDValue BPFTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
switch (Op.getOpcode()) {
case ISD::BR_CC:
@@ -158,7 +177,7 @@ SDValue BPFTargetLowering::LowerFormalArguments(
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
switch (CallConv) {
default:
- llvm_unreachable("Unsupported calling convention");
+ report_fatal_error("Unsupported calling convention");
case CallingConv::C:
case CallingConv::Fast:
break;
@@ -208,7 +227,7 @@ SDValue BPFTargetLowering::LowerFormalArguments(
}
}
- if (IsVarArg || MF.getFunction()->hasStructRetAttr()) {
+ if (IsVarArg || MF.getFunction().hasStructRetAttr()) {
fail(DL, DAG, "functions with VarArgs or StructRet are not supported");
}
@@ -310,14 +329,6 @@ SDValue BPFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
// 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)) {
@@ -371,7 +382,7 @@ BPFTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
// CCState - Info about the registers and stack slot.
CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext());
- if (MF.getFunction()->getReturnType()->isAggregateType()) {
+ if (MF.getFunction().getReturnType()->isAggregateType()) {
fail(DL, DAG, "only integer returns supported");
return DAG.getNode(Opc, DL, MVT::Other, Chain);
}
@@ -456,7 +467,8 @@ SDValue BPFTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
SDValue Dest = Op.getOperand(4);
SDLoc DL(Op);
- NegateCC(LHS, RHS, CC);
+ if (!getHasJmpExt())
+ NegateCC(LHS, RHS, CC);
return DAG.getNode(BPFISD::BR_CC, DL, Op.getValueType(), Chain, LHS, RHS,
DAG.getConstant(CC, DL, MVT::i64), Dest);
@@ -470,7 +482,8 @@ SDValue BPFTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
SDLoc DL(Op);
- NegateCC(LHS, RHS, CC);
+ if (!getHasJmpExt())
+ NegateCC(LHS, RHS, CC);
SDValue TargetCC = DAG.getConstant(CC, DL, MVT::i64);
@@ -570,6 +583,18 @@ BPFTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
case ISD::SETNE:
NewCC = isSelectOp ? BPF::JNE_rr : BPF::JNE_ri;
break;
+ case ISD::SETLT:
+ NewCC = isSelectOp ? BPF::JSLT_rr : BPF::JSLT_ri;
+ break;
+ case ISD::SETULT:
+ NewCC = isSelectOp ? BPF::JULT_rr : BPF::JULT_ri;
+ break;
+ case ISD::SETLE:
+ NewCC = isSelectOp ? BPF::JSLE_rr : BPF::JSLE_ri;
+ break;
+ case ISD::SETULE:
+ NewCC = isSelectOp ? BPF::JULE_rr : BPF::JULE_ri;
+ break;
default:
report_fatal_error("unimplemented select CondCode " + Twine(CC));
}
diff --git a/lib/Target/BPF/BPFISelLowering.h b/lib/Target/BPF/BPFISelLowering.h
index 0b8a8ca20c3b..6ca2594a7e88 100644
--- a/lib/Target/BPF/BPFISelLowering.h
+++ b/lib/Target/BPF/BPFISelLowering.h
@@ -17,7 +17,7 @@
#include "BPF.h"
#include "llvm/CodeGen/SelectionDAG.h"
-#include "llvm/Target/TargetLowering.h"
+#include "llvm/CodeGen/TargetLowering.h"
namespace llvm {
class BPFSubtarget;
@@ -46,11 +46,20 @@ public:
// with the given GlobalAddress is legal.
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
+ std::pair<unsigned, const TargetRegisterClass *>
+ getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
+ StringRef Constraint, MVT VT) const override;
+
MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *BB) const override;
+ bool getHasJmpExt() const { return HasJmpExt; }
+
private:
+ // Control Instruction Selection Features
+ bool HasJmpExt;
+
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
diff --git a/lib/Target/BPF/BPFInstrFormats.td b/lib/Target/BPF/BPFInstrFormats.td
index 53f3ad623587..92d4a62fd875 100644
--- a/lib/Target/BPF/BPFInstrFormats.td
+++ b/lib/Target/BPF/BPFInstrFormats.td
@@ -7,6 +7,87 @@
//
//===----------------------------------------------------------------------===//
+class BPFOpClass<bits<3> val> {
+ bits<3> Value = val;
+}
+
+def BPF_LD : BPFOpClass<0x0>;
+def BPF_LDX : BPFOpClass<0x1>;
+def BPF_ST : BPFOpClass<0x2>;
+def BPF_STX : BPFOpClass<0x3>;
+def BPF_ALU : BPFOpClass<0x4>;
+def BPF_JMP : BPFOpClass<0x5>;
+def BPF_ALU64 : BPFOpClass<0x7>;
+
+class BPFSrcType<bits<1> val> {
+ bits<1> Value = val;
+}
+
+def BPF_K : BPFSrcType<0x0>;
+def BPF_X : BPFSrcType<0x1>;
+
+class BPFArithOp<bits<4> val> {
+ bits<4> Value = val;
+}
+
+def BPF_ADD : BPFArithOp<0x0>;
+def BPF_SUB : BPFArithOp<0x1>;
+def BPF_MUL : BPFArithOp<0x2>;
+def BPF_DIV : BPFArithOp<0x3>;
+def BPF_OR : BPFArithOp<0x4>;
+def BPF_AND : BPFArithOp<0x5>;
+def BPF_LSH : BPFArithOp<0x6>;
+def BPF_RSH : BPFArithOp<0x7>;
+def BPF_NEG : BPFArithOp<0x8>;
+def BPF_XOR : BPFArithOp<0xa>;
+def BPF_MOV : BPFArithOp<0xb>;
+def BPF_ARSH : BPFArithOp<0xc>;
+def BPF_END : BPFArithOp<0xd>;
+
+class BPFEndDir<bits<1> val> {
+ bits<1> Value = val;
+}
+
+def BPF_TO_LE : BPFSrcType<0x0>;
+def BPF_TO_BE : BPFSrcType<0x1>;
+
+class BPFJumpOp<bits<4> val> {
+ bits<4> Value = val;
+}
+
+def BPF_JA : BPFJumpOp<0x0>;
+def BPF_JEQ : BPFJumpOp<0x1>;
+def BPF_JGT : BPFJumpOp<0x2>;
+def BPF_JGE : BPFJumpOp<0x3>;
+def BPF_JNE : BPFJumpOp<0x5>;
+def BPF_JSGT : BPFJumpOp<0x6>;
+def BPF_JSGE : BPFJumpOp<0x7>;
+def BPF_CALL : BPFJumpOp<0x8>;
+def BPF_EXIT : BPFJumpOp<0x9>;
+def BPF_JLT : BPFJumpOp<0xa>;
+def BPF_JLE : BPFJumpOp<0xb>;
+def BPF_JSLT : BPFJumpOp<0xc>;
+def BPF_JSLE : BPFJumpOp<0xd>;
+
+class BPFWidthModifer<bits<2> val> {
+ bits<2> Value = val;
+}
+
+def BPF_W : BPFWidthModifer<0x0>;
+def BPF_H : BPFWidthModifer<0x1>;
+def BPF_B : BPFWidthModifer<0x2>;
+def BPF_DW : BPFWidthModifer<0x3>;
+
+class BPFModeModifer<bits<3> val> {
+ bits<3> Value = val;
+}
+
+def BPF_IMM : BPFModeModifer<0x0>;
+def BPF_ABS : BPFModeModifer<0x1>;
+def BPF_IND : BPFModeModifer<0x2>;
+def BPF_MEM : BPFModeModifer<0x3>;
+def BPF_XADD : BPFModeModifer<0x6>;
+
class InstBPF<dag outs, dag ins, string asmstr, list<dag> pattern>
: Instruction {
field bits<64> Inst;
@@ -16,8 +97,8 @@ class InstBPF<dag outs, dag ins, string asmstr, list<dag> pattern>
let Namespace = "BPF";
let DecoderNamespace = "BPF";
- bits<3> BPFClass;
- let Inst{58-56} = BPFClass;
+ BPFOpClass BPFClass;
+ let Inst{58-56} = BPFClass.Value;
dag OutOperandList = outs;
dag InOperandList = ins;
diff --git a/lib/Target/BPF/BPFInstrInfo.h b/lib/Target/BPF/BPFInstrInfo.h
index c7048ab979b7..f591f48a89a6 100644
--- a/lib/Target/BPF/BPFInstrInfo.h
+++ b/lib/Target/BPF/BPFInstrInfo.h
@@ -15,7 +15,7 @@
#define LLVM_LIB_TARGET_BPF_BPFINSTRINFO_H
#include "BPFRegisterInfo.h"
-#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
#define GET_INSTRINFO_HEADER
#include "BPFGenInstrInfo.inc"
diff --git a/lib/Target/BPF/BPFInstrInfo.td b/lib/Target/BPF/BPFInstrInfo.td
index 59e92f8edd0c..126d55fc28de 100644
--- a/lib/Target/BPF/BPFInstrInfo.td
+++ b/lib/Target/BPF/BPFInstrInfo.td
@@ -43,8 +43,12 @@ def BPFbrcc : SDNode<"BPFISD::BR_CC", SDT_BPFBrCC,
def BPFselectcc : SDNode<"BPFISD::SELECT_CC", SDT_BPFSelectCC, [SDNPInGlue]>;
def BPFWrapper : SDNode<"BPFISD::Wrapper", SDT_BPFWrapper>;
+def BPFIsLittleEndian : Predicate<"CurDAG->getDataLayout().isLittleEndian()">;
+def BPFIsBigEndian : Predicate<"!CurDAG->getDataLayout().isLittleEndian()">;
-def brtarget : Operand<OtherVT>;
+def brtarget : Operand<OtherVT> {
+ let PrintMethod = "printBrTargetOperand";
+}
def calltarget : Operand<i64>;
def u64imm : Operand<i64> {
@@ -79,320 +83,338 @@ def BPF_CC_GTU : PatLeaf<(i64 imm),
[{return (N->getZExtValue() == ISD::SETUGT);}]>;
def BPF_CC_GEU : PatLeaf<(i64 imm),
[{return (N->getZExtValue() == ISD::SETUGE);}]>;
+def BPF_CC_LE : PatLeaf<(i64 imm),
+ [{return (N->getZExtValue() == ISD::SETLE);}]>;
+def BPF_CC_LT : PatLeaf<(i64 imm),
+ [{return (N->getZExtValue() == ISD::SETLT);}]>;
+def BPF_CC_LTU : PatLeaf<(i64 imm),
+ [{return (N->getZExtValue() == ISD::SETULT);}]>;
+def BPF_CC_LEU : PatLeaf<(i64 imm),
+ [{return (N->getZExtValue() == ISD::SETULE);}]>;
+
+// For arithmetic and jump instructions the 8-bit 'code'
+// field is divided into three parts:
+//
+// +----------------+--------+--------------------+
+// | 4 bits | 1 bit | 3 bits |
+// | operation code | source | instruction class |
+// +----------------+--------+--------------------+
+// (MSB) (LSB)
+class TYPE_ALU_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;
+}
+
+//For load and store instructions the 8-bit 'code' field is divided as:
+//
+// +--------+--------+-------------------+
+// | 3 bits | 2 bits | 3 bits |
+// | mode | size | instruction class |
+// +--------+--------+-------------------+
+// (MSB) (LSB)
+class TYPE_LD_ST<bits<3> mode, bits<2> size,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : InstBPF<outs, ins, asmstr, pattern> {
+
+ let Inst{63-61} = mode;
+ let Inst{60-59} = size;
+}
// jump instructions
-class JMP_RR<bits<4> Opc, string OpcodeStr, PatLeaf Cond>
- : InstBPF<(outs), (ins GPR:$dst, GPR:$src, brtarget:$BrDst),
- "if $dst "#OpcodeStr#" $src goto $BrDst",
- [(BPFbrcc i64:$dst, i64:$src, Cond, bb:$BrDst)]> {
- bits<4> op;
- bits<1> BPFSrc;
+class JMP_RR<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond>
+ : TYPE_ALU_JMP<Opc.Value, BPF_X.Value,
+ (outs),
+ (ins GPR:$dst, GPR:$src, brtarget:$BrDst),
+ "if $dst "#OpcodeStr#" $src goto $BrDst",
+ [(BPFbrcc i64:$dst, i64:$src, Cond, bb:$BrDst)]> {
bits<4> dst;
bits<4> src;
bits<16> BrDst;
- let Inst{63-60} = op;
- let Inst{59} = BPFSrc;
let Inst{55-52} = src;
let Inst{51-48} = dst;
let Inst{47-32} = BrDst;
-
- let op = Opc;
- let BPFSrc = 1;
- let BPFClass = 5; // BPF_JMP
+ let BPFClass = BPF_JMP;
}
-class JMP_RI<bits<4> Opc, string OpcodeStr, PatLeaf Cond>
- : InstBPF<(outs), (ins GPR:$dst, i64imm:$imm, brtarget:$BrDst),
- "if $dst "#OpcodeStr#" $imm goto $BrDst",
- [(BPFbrcc i64:$dst, i64immSExt32:$imm, Cond, bb:$BrDst)]> {
- bits<4> op;
- bits<1> BPFSrc;
+class JMP_RI<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond>
+ : TYPE_ALU_JMP<Opc.Value, BPF_K.Value,
+ (outs),
+ (ins GPR:$dst, i64imm:$imm, brtarget:$BrDst),
+ "if $dst "#OpcodeStr#" $imm goto $BrDst",
+ [(BPFbrcc i64:$dst, i64immSExt32:$imm, Cond, bb:$BrDst)]> {
bits<4> dst;
bits<16> BrDst;
bits<32> imm;
- let Inst{63-60} = op;
- let Inst{59} = BPFSrc;
let Inst{51-48} = dst;
let Inst{47-32} = BrDst;
let Inst{31-0} = imm;
-
- let op = Opc;
- let BPFSrc = 0;
- let BPFClass = 5; // BPF_JMP
+ let BPFClass = BPF_JMP;
}
-multiclass J<bits<4> Opc, string OpcodeStr, PatLeaf Cond> {
+multiclass J<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond> {
def _rr : JMP_RR<Opc, OpcodeStr, Cond>;
def _ri : JMP_RI<Opc, OpcodeStr, Cond>;
}
let isBranch = 1, isTerminator = 1, hasDelaySlot=0 in {
// cmp+goto instructions
-defm JEQ : J<0x1, "==", BPF_CC_EQ>;
-defm JUGT : J<0x2, ">", BPF_CC_GTU>;
-defm JUGE : J<0x3, ">=", BPF_CC_GEU>;
-defm JNE : J<0x5, "!=", BPF_CC_NE>;
-defm JSGT : J<0x6, "s>", BPF_CC_GT>;
-defm JSGE : J<0x7, "s>=", BPF_CC_GE>;
+defm JEQ : J<BPF_JEQ, "==", BPF_CC_EQ>;
+defm JUGT : J<BPF_JGT, ">", BPF_CC_GTU>;
+defm JUGE : J<BPF_JGE, ">=", BPF_CC_GEU>;
+defm JNE : J<BPF_JNE, "!=", BPF_CC_NE>;
+defm JSGT : J<BPF_JSGT, "s>", BPF_CC_GT>;
+defm JSGE : J<BPF_JSGE, "s>=", BPF_CC_GE>;
+defm JULT : J<BPF_JLT, "<", BPF_CC_LTU>;
+defm JULE : J<BPF_JLE, "<=", BPF_CC_LEU>;
+defm JSLT : J<BPF_JSLT, "s<", BPF_CC_LT>;
+defm JSLE : J<BPF_JSLE, "s<=", BPF_CC_LE>;
}
// ALU instructions
-class ALU_RI<bits<4> Opc, string OpcodeStr, SDNode OpNode>
- : InstBPF<(outs GPR:$dst), (ins GPR:$src2, i64imm:$imm),
- "$dst "#OpcodeStr#" $imm",
- [(set GPR:$dst, (OpNode GPR:$src2, i64immSExt32:$imm))]> {
- bits<4> op;
- bits<1> BPFSrc;
+class ALU_RI<BPFOpClass Class, BPFArithOp Opc,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : TYPE_ALU_JMP<Opc.Value, BPF_K.Value, outs, ins, asmstr, pattern> {
bits<4> dst;
bits<32> imm;
- let Inst{63-60} = op;
- let Inst{59} = BPFSrc;
let Inst{51-48} = dst;
let Inst{31-0} = imm;
-
- let op = Opc;
- let BPFSrc = 0;
- let BPFClass = 7; // BPF_ALU64
+ let BPFClass = Class;
}
-class ALU_RR<bits<4> Opc, string OpcodeStr, SDNode OpNode>
- : InstBPF<(outs GPR:$dst), (ins GPR:$src2, GPR:$src),
- "$dst "#OpcodeStr#" $src",
- [(set GPR:$dst, (OpNode i64:$src2, i64:$src))]> {
- bits<4> op;
- bits<1> BPFSrc;
+class ALU_RR<BPFOpClass Class, BPFArithOp Opc,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : TYPE_ALU_JMP<Opc.Value, BPF_X.Value, outs, ins, asmstr, pattern> {
bits<4> dst;
bits<4> src;
- let Inst{63-60} = op;
- let Inst{59} = BPFSrc;
let Inst{55-52} = src;
let Inst{51-48} = dst;
-
- let op = Opc;
- let BPFSrc = 1;
- let BPFClass = 7; // BPF_ALU64
+ let BPFClass = Class;
}
-multiclass ALU<bits<4> Opc, string OpcodeStr, SDNode OpNode> {
- def _rr : ALU_RR<Opc, OpcodeStr, OpNode>;
- def _ri : ALU_RI<Opc, OpcodeStr, OpNode>;
+multiclass ALU<BPFArithOp Opc, string OpcodeStr, SDNode OpNode> {
+ def _rr : ALU_RR<BPF_ALU64, Opc,
+ (outs GPR:$dst),
+ (ins GPR:$src2, GPR:$src),
+ "$dst "#OpcodeStr#" $src",
+ [(set GPR:$dst, (OpNode i64:$src2, i64:$src))]>;
+ def _ri : ALU_RI<BPF_ALU64, Opc,
+ (outs GPR:$dst),
+ (ins GPR:$src2, i64imm:$imm),
+ "$dst "#OpcodeStr#" $imm",
+ [(set GPR:$dst, (OpNode GPR:$src2, i64immSExt32:$imm))]>;
+ def _rr_32 : ALU_RR<BPF_ALU, Opc,
+ (outs GPR32:$dst),
+ (ins GPR32:$src2, GPR32:$src),
+ "$dst "#OpcodeStr#" $src",
+ [(set GPR32:$dst, (OpNode i32:$src2, i32:$src))]>;
+ def _ri_32 : ALU_RI<BPF_ALU, Opc,
+ (outs GPR32:$dst),
+ (ins GPR32:$src2, i32imm:$imm),
+ "$dst "#OpcodeStr#" $imm",
+ [(set GPR32:$dst, (OpNode GPR32:$src2, i32:$imm))]>;
}
let Constraints = "$dst = $src2" in {
let isAsCheapAsAMove = 1 in {
- defm ADD : ALU<0x0, "+=", add>;
- defm SUB : ALU<0x1, "-=", sub>;
- defm OR : ALU<0x4, "|=", or>;
- defm AND : ALU<0x5, "&=", and>;
- defm SLL : ALU<0x6, "<<=", shl>;
- defm SRL : ALU<0x7, ">>=", srl>;
- defm XOR : ALU<0xa, "^=", xor>;
- defm SRA : ALU<0xc, "s>>=", sra>;
+ defm ADD : ALU<BPF_ADD, "+=", add>;
+ defm SUB : ALU<BPF_SUB, "-=", sub>;
+ defm OR : ALU<BPF_OR, "|=", or>;
+ defm AND : ALU<BPF_AND, "&=", and>;
+ defm SLL : ALU<BPF_LSH, "<<=", shl>;
+ defm SRL : ALU<BPF_RSH, ">>=", srl>;
+ defm XOR : ALU<BPF_XOR, "^=", xor>;
+ defm SRA : ALU<BPF_ARSH, "s>>=", sra>;
}
- defm MUL : ALU<0x2, "*=", mul>;
- defm DIV : ALU<0x3, "/=", udiv>;
+ defm MUL : ALU<BPF_MUL, "*=", mul>;
+ defm DIV : ALU<BPF_DIV, "/=", udiv>;
}
-class MOV_RR<string OpcodeStr>
- : InstBPF<(outs GPR:$dst), (ins GPR:$src),
- "$dst "#OpcodeStr#" $src",
- []> {
- bits<4> op;
- bits<1> BPFSrc;
+class NEG_RR<BPFOpClass Class, BPFArithOp Opc,
+ dag outs, dag ins, string asmstr, list<dag> pattern>
+ : TYPE_ALU_JMP<Opc.Value, 0, outs, ins, asmstr, pattern> {
bits<4> dst;
- bits<4> src;
- let Inst{63-60} = op;
- let Inst{59} = BPFSrc;
- let Inst{55-52} = src;
let Inst{51-48} = dst;
-
- let op = 0xb; // BPF_MOV
- let BPFSrc = 1; // BPF_X
- let BPFClass = 7; // BPF_ALU64
+ let BPFClass = Class;
}
-class MOV_RI<string OpcodeStr>
- : InstBPF<(outs GPR:$dst), (ins i64imm:$imm),
- "$dst "#OpcodeStr#" $imm",
- [(set GPR:$dst, (i64 i64immSExt32:$imm))]> {
- bits<4> op;
- bits<1> BPFSrc;
- bits<4> dst;
- bits<32> imm;
-
- let Inst{63-60} = op;
- let Inst{59} = BPFSrc;
- let Inst{51-48} = dst;
- let Inst{31-0} = imm;
-
- let op = 0xb; // BPF_MOV
- let BPFSrc = 0; // BPF_K
- let BPFClass = 7; // BPF_ALU64
+let Constraints = "$dst = $src", isAsCheapAsAMove = 1 in {
+ def NEG_64: NEG_RR<BPF_ALU64, BPF_NEG, (outs GPR:$dst), (ins GPR:$src),
+ "$dst = -$src",
+ [(set GPR:$dst, (ineg i64:$src))]>;
+ def NEG_32: NEG_RR<BPF_ALU, BPF_NEG, (outs GPR32:$dst), (ins GPR32:$src),
+ "$dst = -$src",
+ [(set GPR32:$dst, (ineg i32:$src))]>;
}
class LD_IMM64<bits<4> Pseudo, string OpcodeStr>
- : InstBPF<(outs GPR:$dst), (ins u64imm:$imm),
- "$dst "#OpcodeStr#" ${imm}ll",
- [(set GPR:$dst, (i64 imm:$imm))]> {
+ : TYPE_LD_ST<BPF_IMM.Value, BPF_DW.Value,
+ (outs GPR:$dst),
+ (ins u64imm:$imm),
+ "$dst "#OpcodeStr#" ${imm} ll",
+ [(set GPR:$dst, (i64 imm:$imm))]> {
- bits<3> mode;
- bits<2> size;
bits<4> dst;
bits<64> imm;
- let Inst{63-61} = mode;
- let Inst{60-59} = size;
let Inst{51-48} = dst;
let Inst{55-52} = Pseudo;
let Inst{47-32} = 0;
let Inst{31-0} = imm{31-0};
-
- let mode = 0; // BPF_IMM
- let size = 3; // BPF_DW
- let BPFClass = 0; // BPF_LD
+ let BPFClass = BPF_LD;
}
let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
def LD_imm64 : LD_IMM64<0, "=">;
-def MOV_rr : MOV_RR<"=">;
-def MOV_ri : MOV_RI<"=">;
+def MOV_rr : ALU_RR<BPF_ALU64, BPF_MOV,
+ (outs GPR:$dst),
+ (ins GPR:$src),
+ "$dst = $src",
+ []>;
+def MOV_ri : ALU_RI<BPF_ALU64, BPF_MOV,
+ (outs GPR:$dst),
+ (ins i64imm:$imm),
+ "$dst = $imm",
+ [(set GPR:$dst, (i64 i64immSExt32:$imm))]>;
+def MOV_rr_32 : ALU_RR<BPF_ALU, BPF_MOV,
+ (outs GPR32:$dst),
+ (ins GPR32:$src),
+ "$dst = $src",
+ []>;
+def MOV_ri_32 : ALU_RI<BPF_ALU, BPF_MOV,
+ (outs GPR32:$dst),
+ (ins i32imm:$imm),
+ "$dst = $imm",
+ [(set GPR32:$dst, (i32 i32:$imm))]>;
}
def FI_ri
- : InstBPF<(outs GPR:$dst), (ins MEMri:$addr),
- "lea\t$dst, $addr",
- [(set i64:$dst, FIri:$addr)]> {
+ : TYPE_LD_ST<BPF_IMM.Value, BPF_DW.Value,
+ (outs GPR:$dst),
+ (ins MEMri:$addr),
+ "lea\t$dst, $addr",
+ [(set i64:$dst, FIri:$addr)]> {
// This is a tentative instruction, and will be replaced
// with MOV_rr and ADD_ri in PEI phase
- let Inst{63-61} = 0;
- let Inst{60-59} = 3;
let Inst{51-48} = 0;
let Inst{55-52} = 2;
let Inst{47-32} = 0;
let Inst{31-0} = 0;
- let BPFClass = 0;
+ let BPFClass = BPF_LD;
}
-
def LD_pseudo
- : InstBPF<(outs GPR:$dst), (ins i64imm:$pseudo, u64imm:$imm),
- "ld_pseudo\t$dst, $pseudo, $imm",
- [(set GPR:$dst, (int_bpf_pseudo imm:$pseudo, imm:$imm))]> {
+ : TYPE_LD_ST<BPF_IMM.Value, BPF_DW.Value,
+ (outs GPR:$dst),
+ (ins i64imm:$pseudo, u64imm:$imm),
+ "ld_pseudo\t$dst, $pseudo, $imm",
+ [(set GPR:$dst, (int_bpf_pseudo imm:$pseudo, imm:$imm))]> {
- bits<3> mode;
- bits<2> size;
bits<4> dst;
bits<64> imm;
bits<4> pseudo;
- let Inst{63-61} = mode;
- let Inst{60-59} = size;
let Inst{51-48} = dst;
let Inst{55-52} = pseudo;
let Inst{47-32} = 0;
let Inst{31-0} = imm{31-0};
-
- let mode = 0; // BPF_IMM
- let size = 3; // BPF_DW
- let BPFClass = 0; // BPF_LD
+ let BPFClass = BPF_LD;
}
// STORE instructions
-class STORE<bits<2> SizeOp, string OpcodeStr, list<dag> Pattern>
- : InstBPF<(outs), (ins GPR:$src, MEMri:$addr),
- "*("#OpcodeStr#" *)($addr) = $src", Pattern> {
- bits<3> mode;
- bits<2> size;
+class STORE<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
+ : TYPE_LD_ST<BPF_MEM.Value, SizeOp.Value,
+ (outs),
+ (ins GPR:$src, MEMri:$addr),
+ "*("#OpcodeStr#" *)($addr) = $src",
+ Pattern> {
bits<4> src;
bits<20> addr;
- let Inst{63-61} = mode;
- let Inst{60-59} = size;
let Inst{51-48} = addr{19-16}; // base reg
let Inst{55-52} = src;
let Inst{47-32} = addr{15-0}; // offset
-
- let mode = 3; // BPF_MEM
- let size = SizeOp;
- let BPFClass = 3; // BPF_STX
+ let BPFClass = BPF_STX;
}
-class STOREi64<bits<2> Opc, string OpcodeStr, PatFrag OpNode>
+class STOREi64<BPFWidthModifer Opc, string OpcodeStr, PatFrag OpNode>
: STORE<Opc, OpcodeStr, [(OpNode i64:$src, ADDRri:$addr)]>;
-def STW : STOREi64<0x0, "u32", truncstorei32>;
-def STH : STOREi64<0x1, "u16", truncstorei16>;
-def STB : STOREi64<0x2, "u8", truncstorei8>;
-def STD : STOREi64<0x3, "u64", store>;
+def STW : STOREi64<BPF_W, "u32", truncstorei32>;
+def STH : STOREi64<BPF_H, "u16", truncstorei16>;
+def STB : STOREi64<BPF_B, "u8", truncstorei8>;
+def STD : STOREi64<BPF_DW, "u64", store>;
// LOAD instructions
-class LOAD<bits<2> SizeOp, string OpcodeStr, list<dag> Pattern>
- : InstBPF<(outs GPR:$dst), (ins MEMri:$addr),
- "$dst = *("#OpcodeStr#" *)($addr)", Pattern> {
- bits<3> mode;
- bits<2> size;
+class LOAD<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
+ : TYPE_LD_ST<BPF_MEM.Value, SizeOp.Value,
+ (outs GPR:$dst),
+ (ins MEMri:$addr),
+ "$dst = *("#OpcodeStr#" *)($addr)",
+ Pattern> {
bits<4> dst;
bits<20> addr;
- let Inst{63-61} = mode;
- let Inst{60-59} = size;
let Inst{51-48} = dst;
let Inst{55-52} = addr{19-16};
let Inst{47-32} = addr{15-0};
-
- let mode = 3; // BPF_MEM
- let size = SizeOp;
- let BPFClass = 1; // BPF_LDX
+ let BPFClass = BPF_LDX;
}
-class LOADi64<bits<2> SizeOp, string OpcodeStr, PatFrag OpNode>
+class LOADi64<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
: LOAD<SizeOp, OpcodeStr, [(set i64:$dst, (OpNode ADDRri:$addr))]>;
-def LDW : LOADi64<0x0, "u32", zextloadi32>;
-def LDH : LOADi64<0x1, "u16", zextloadi16>;
-def LDB : LOADi64<0x2, "u8", zextloadi8>;
-def LDD : LOADi64<0x3, "u64", load>;
+def LDW : LOADi64<BPF_W, "u32", zextloadi32>;
+def LDH : LOADi64<BPF_H, "u16", zextloadi16>;
+def LDB : LOADi64<BPF_B, "u8", zextloadi8>;
+def LDD : LOADi64<BPF_DW, "u64", load>;
-class BRANCH<bits<4> Opc, string OpcodeStr, list<dag> Pattern>
- : InstBPF<(outs), (ins brtarget:$BrDst),
- !strconcat(OpcodeStr, " $BrDst"), Pattern> {
- bits<4> op;
+class BRANCH<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
+ : TYPE_ALU_JMP<Opc.Value, BPF_K.Value,
+ (outs),
+ (ins brtarget:$BrDst),
+ !strconcat(OpcodeStr, " $BrDst"),
+ Pattern> {
bits<16> BrDst;
- bits<1> BPFSrc;
- let Inst{63-60} = op;
- let Inst{59} = BPFSrc;
let Inst{47-32} = BrDst;
-
- let op = Opc;
- let BPFSrc = 0;
- let BPFClass = 5; // BPF_JMP
+ let BPFClass = BPF_JMP;
}
class CALL<string OpcodeStr>
- : InstBPF<(outs), (ins calltarget:$BrDst),
- !strconcat(OpcodeStr, " $BrDst"), []> {
- bits<4> op;
+ : TYPE_ALU_JMP<BPF_CALL.Value, BPF_K.Value,
+ (outs),
+ (ins calltarget:$BrDst),
+ !strconcat(OpcodeStr, " $BrDst"),
+ []> {
bits<32> BrDst;
- bits<1> BPFSrc;
- let Inst{63-60} = op;
- let Inst{59} = BPFSrc;
let Inst{31-0} = BrDst;
+ let BPFClass = BPF_JMP;
+}
- let op = 8; // BPF_CALL
- let BPFSrc = 0;
- let BPFClass = 5; // 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<0x0, "goto", [(br bb:$BrDst)]>;
+ def JMP : BRANCH<BPF_JA, "goto", [(br bb:$BrDst)]>;
}
// Jump and link
@@ -400,43 +422,32 @@ 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>
- : InstBPF<(outs), (ins i32imm:$imm),
- !strconcat(OpcodeStr, "\t$imm"), []> {
+ : TYPE_ALU_JMP<BPF_MOV.Value, BPF_X.Value,
+ (outs),
+ (ins i32imm:$imm),
+ !strconcat(OpcodeStr, "\t$imm"),
+ []> {
// mov r0, r0 == nop
- bits<4> op;
- bits<1> BPFSrc;
- bits<4> dst;
- bits<4> src;
-
- let Inst{63-60} = op;
- let Inst{59} = BPFSrc;
- let Inst{55-52} = src;
- let Inst{51-48} = dst;
-
- let op = 0xb; // BPF_MOV
- let BPFSrc = 1; // BPF_X
- let BPFClass = 7; // BPF_ALU64
- let src = 0; // R0
- let dst = 0; // R0
+ let Inst{55-52} = 0;
+ let Inst{51-48} = 0;
+ let BPFClass = BPF_ALU64;
}
let hasSideEffects = 0 in
def NOP : NOP_I<"nop">;
class RET<string OpcodeStr>
- : InstBPF<(outs), (ins),
- !strconcat(OpcodeStr, ""), [(BPFretflag)]> {
- bits<4> op;
-
- let Inst{63-60} = op;
- let Inst{59} = 0;
+ : TYPE_ALU_JMP<BPF_EXIT.Value, BPF_K.Value,
+ (outs),
+ (ins),
+ !strconcat(OpcodeStr, ""),
+ [(BPFretflag)]> {
let Inst{31-0} = 0;
-
- let op = 9; // BPF_EXIT
- let BPFClass = 5; // BPF_JMP
+ let BPFClass = BPF_JMP;
}
let isReturn = 1, isTerminator = 1, hasDelaySlot=0, isBarrier = 1,
@@ -464,7 +475,7 @@ let usesCustomInserter = 1 in {
(ins GPR:$lhs, i64imm:$rhs, i64imm:$imm, GPR:$src, GPR:$src2),
"# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2",
[(set i64:$dst,
- (BPFselectcc i64:$lhs, (i64 i64immSExt32:$rhs), (i64 imm:$imm), i64:$src, i64:$src2))]>;
+ (BPFselectcc i64:$lhs, (i64immSExt32:$rhs), (i64 imm:$imm), i64:$src, i64:$src2))]>;
}
// load 64-bit global addr into register
@@ -478,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))>;
@@ -485,101 +497,87 @@ def : Pat<(extloadi16 ADDRri:$src), (i64 (LDH ADDRri:$src))>;
def : Pat<(extloadi32 ADDRri:$src), (i64 (LDW ADDRri:$src))>;
// Atomics
-class XADD<bits<2> SizeOp, string OpcodeStr, PatFrag OpNode>
- : InstBPF<(outs GPR:$dst), (ins MEMri:$addr, GPR:$val),
- "lock *("#OpcodeStr#" *)($addr) += $val",
- [(set GPR:$dst, (OpNode ADDRri:$addr, GPR:$val))]> {
- bits<3> mode;
- bits<2> size;
+class XADD<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
+ : TYPE_LD_ST<BPF_XADD.Value, SizeOp.Value,
+ (outs GPR:$dst),
+ (ins MEMri:$addr, GPR:$val),
+ "lock *("#OpcodeStr#" *)($addr) += $val",
+ [(set GPR:$dst, (OpNode ADDRri:$addr, GPR:$val))]> {
bits<4> dst;
bits<20> addr;
- let Inst{63-61} = mode;
- let Inst{60-59} = size;
let Inst{51-48} = addr{19-16}; // base reg
let Inst{55-52} = dst;
let Inst{47-32} = addr{15-0}; // offset
-
- let mode = 6; // BPF_XADD
- let size = SizeOp;
- let BPFClass = 3; // BPF_STX
+ let BPFClass = BPF_STX;
}
let Constraints = "$dst = $val" in {
-def XADD32 : XADD<0, "u32", atomic_load_add_32>;
-def XADD64 : XADD<3, "u64", atomic_load_add_64>;
+def XADD32 : XADD<BPF_W, "u32", atomic_load_add_32>;
+def XADD64 : XADD<BPF_DW, "u64", atomic_load_add_64>;
// undefined def XADD16 : XADD<1, "xadd16", atomic_load_add_16>;
// undefined def XADD8 : XADD<2, "xadd8", atomic_load_add_8>;
}
// bswap16, bswap32, bswap64
-class BSWAP<bits<32> SizeOp, string OpcodeStr, list<dag> Pattern>
- : InstBPF<(outs GPR:$dst), (ins GPR:$src),
- !strconcat(OpcodeStr, "\t$dst"),
- Pattern> {
- bits<4> op;
- bits<1> BPFSrc;
+class BSWAP<bits<32> SizeOp, string OpcodeStr, BPFSrcType SrcType, list<dag> Pattern>
+ : TYPE_ALU_JMP<BPF_END.Value, SrcType.Value,
+ (outs GPR:$dst),
+ (ins GPR:$src),
+ "$dst = "#OpcodeStr#" $src",
+ Pattern> {
bits<4> dst;
- bits<32> imm;
- let Inst{63-60} = op;
- let Inst{59} = BPFSrc;
let Inst{51-48} = dst;
- let Inst{31-0} = imm;
-
- let op = 0xd; // BPF_END
- let BPFSrc = 1; // BPF_TO_BE (TODO: use BPF_TO_LE for big-endian target)
- let BPFClass = 4; // BPF_ALU
- let imm = SizeOp;
+ let Inst{31-0} = SizeOp;
+ let BPFClass = BPF_ALU;
}
+
let Constraints = "$dst = $src" in {
-def BSWAP16 : BSWAP<16, "bswap16", [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
-def BSWAP32 : BSWAP<32, "bswap32", [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
-def BSWAP64 : BSWAP<64, "bswap64", [(set GPR:$dst, (bswap GPR:$src))]>;
+ let Predicates = [BPFIsLittleEndian] in {
+ def BE16 : BSWAP<16, "be16", BPF_TO_BE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
+ def BE32 : BSWAP<32, "be32", BPF_TO_BE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
+ def BE64 : BSWAP<64, "be64", BPF_TO_BE, [(set GPR:$dst, (bswap GPR:$src))]>;
+ }
+ let Predicates = [BPFIsBigEndian] in {
+ def LE16 : BSWAP<16, "le16", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
+ def LE32 : BSWAP<32, "le32", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
+ def LE64 : BSWAP<64, "le64", BPF_TO_LE, [(set GPR:$dst, (bswap GPR:$src))]>;
+ }
}
let Defs = [R0, R1, R2, R3, R4, R5], Uses = [R6], hasSideEffects = 1,
hasExtraDefRegAllocReq = 1, hasExtraSrcRegAllocReq = 1, mayLoad = 1 in {
-class LOAD_ABS<bits<2> SizeOp, string OpcodeStr, Intrinsic OpNode>
- : InstBPF<(outs), (ins GPR:$skb, i64imm:$imm),
- "r0 = *("#OpcodeStr#" *)skb[$imm]",
- [(set R0, (OpNode GPR:$skb, i64immSExt32:$imm))]> {
- bits<3> mode;
- bits<2> size;
+class LOAD_ABS<BPFWidthModifer SizeOp, string OpcodeStr, Intrinsic OpNode>
+ : TYPE_LD_ST<BPF_ABS.Value, SizeOp.Value,
+ (outs),
+ (ins GPR:$skb, i64imm:$imm),
+ "r0 = *("#OpcodeStr#" *)skb[$imm]",
+ [(set R0, (OpNode GPR:$skb, i64immSExt32:$imm))]> {
bits<32> imm;
- let Inst{63-61} = mode;
- let Inst{60-59} = size;
let Inst{31-0} = imm;
-
- let mode = 1; // BPF_ABS
- let size = SizeOp;
- let BPFClass = 0; // BPF_LD
+ let BPFClass = BPF_LD;
}
-class LOAD_IND<bits<2> SizeOp, string OpcodeStr, Intrinsic OpNode>
- : InstBPF<(outs), (ins GPR:$skb, GPR:$val),
- "r0 = *("#OpcodeStr#" *)skb[$val]",
- [(set R0, (OpNode GPR:$skb, GPR:$val))]> {
- bits<3> mode;
- bits<2> size;
+class LOAD_IND<BPFWidthModifer SizeOp, string OpcodeStr, Intrinsic OpNode>
+ : TYPE_LD_ST<BPF_IND.Value, SizeOp.Value,
+ (outs),
+ (ins GPR:$skb, GPR:$val),
+ "r0 = *("#OpcodeStr#" *)skb[$val]",
+ [(set R0, (OpNode GPR:$skb, GPR:$val))]> {
bits<4> val;
- let Inst{63-61} = mode;
- let Inst{60-59} = size;
let Inst{55-52} = val;
-
- let mode = 2; // BPF_IND
- let size = SizeOp;
- let BPFClass = 0; // BPF_LD
+ let BPFClass = BPF_LD;
}
}
-def LD_ABS_B : LOAD_ABS<2, "u8", int_bpf_load_byte>;
-def LD_ABS_H : LOAD_ABS<1, "u16", int_bpf_load_half>;
-def LD_ABS_W : LOAD_ABS<0, "u32", int_bpf_load_word>;
+def LD_ABS_B : LOAD_ABS<BPF_B, "u8", int_bpf_load_byte>;
+def LD_ABS_H : LOAD_ABS<BPF_H, "u16", int_bpf_load_half>;
+def LD_ABS_W : LOAD_ABS<BPF_W, "u32", int_bpf_load_word>;
-def LD_IND_B : LOAD_IND<2, "u8", int_bpf_load_byte>;
-def LD_IND_H : LOAD_IND<1, "u16", int_bpf_load_half>;
-def LD_IND_W : LOAD_IND<0, "u32", int_bpf_load_word>;
+def LD_IND_B : LOAD_IND<BPF_B, "u8", int_bpf_load_byte>;
+def LD_IND_H : LOAD_IND<BPF_H, "u16", int_bpf_load_half>;
+def LD_IND_W : LOAD_IND<BPF_W, "u32", int_bpf_load_word>;
diff --git a/lib/Target/BPF/BPFRegisterInfo.cpp b/lib/Target/BPF/BPFRegisterInfo.cpp
index 273843e92701..6f7067816098 100644
--- a/lib/Target/BPF/BPFRegisterInfo.cpp
+++ b/lib/Target/BPF/BPFRegisterInfo.cpp
@@ -18,10 +18,10 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/CodeGen/TargetFrameLowering.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Target/TargetFrameLowering.h"
-#include "llvm/Target/TargetInstrInfo.h"
#define GET_REGINFO_TARGET_DESC
#include "BPFGenRegisterInfo.inc"
@@ -45,12 +45,12 @@ BitVector BPFRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
static void WarnSize(int Offset, MachineFunction &MF, DebugLoc& DL)
{
if (Offset <= -512) {
- auto F = MF.getFunction();
- DiagnosticInfoUnsupported DiagStackSize(*F,
+ const Function &F = MF.getFunction();
+ DiagnosticInfoUnsupported DiagStackSize(F,
"Looks like the BPF stack limit of 512 bytes is exceeded. "
"Please move large on stack variables into BPF per-cpu array map.\n",
DL);
- F->getContext().diagnose(DiagStackSize);
+ F.getContext().diagnose(DiagStackSize);
}
}
diff --git a/lib/Target/BPF/BPFRegisterInfo.h b/lib/Target/BPF/BPFRegisterInfo.h
index 7072dd0bde1a..4202850e9eb9 100644
--- a/lib/Target/BPF/BPFRegisterInfo.h
+++ b/lib/Target/BPF/BPFRegisterInfo.h
@@ -14,7 +14,7 @@
#ifndef LLVM_LIB_TARGET_BPF_BPFREGISTERINFO_H
#define LLVM_LIB_TARGET_BPF_BPFREGISTERINFO_H
-#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
#define GET_REGINFO_HEADER
#include "BPFGenRegisterInfo.inc"
diff --git a/lib/Target/BPF/BPFRegisterInfo.td b/lib/Target/BPF/BPFRegisterInfo.td
index c8e24f810310..da1d6b505f84 100644
--- a/lib/Target/BPF/BPFRegisterInfo.td
+++ b/lib/Target/BPF/BPFRegisterInfo.td
@@ -11,31 +11,42 @@
// Declarations that describe the BPF register file
//===----------------------------------------------------------------------===//
+let Namespace = "BPF" in {
+ def sub_32 : SubRegIndex<32>;
+}
+
+class Wi<bits<16> Enc, string n> : Register<n> {
+ let HWEncoding = Enc;
+ let Namespace = "BPF";
+}
+
// Registers are identified with 4-bit ID numbers.
// Ri - 64-bit integer registers
-class Ri<bits<16> Enc, string n> : Register<n> {
- let Namespace = "BPF";
+class Ri<bits<16> Enc, string n, list<Register> subregs>
+ : RegisterWithSubRegs<n, subregs> {
let HWEncoding = Enc;
+ let Namespace = "BPF";
+ let SubRegIndices = [sub_32];
}
-// Integer registers
-def R0 : Ri< 0, "r0">, DwarfRegNum<[0]>;
-def R1 : Ri< 1, "r1">, DwarfRegNum<[1]>;
-def R2 : Ri< 2, "r2">, DwarfRegNum<[2]>;
-def R3 : Ri< 3, "r3">, DwarfRegNum<[3]>;
-def R4 : Ri< 4, "r4">, DwarfRegNum<[4]>;
-def R5 : Ri< 5, "r5">, DwarfRegNum<[5]>;
-def R6 : Ri< 6, "r6">, DwarfRegNum<[6]>;
-def R7 : Ri< 7, "r7">, DwarfRegNum<[7]>;
-def R8 : Ri< 8, "r8">, DwarfRegNum<[8]>;
-def R9 : Ri< 9, "r9">, DwarfRegNum<[9]>;
-def R10 : Ri<10, "r10">, DwarfRegNum<[10]>;
-def R11 : Ri<11, "r11">, DwarfRegNum<[11]>;
+foreach I = 0-11 in {
+ // 32-bit Integer (alias to low part of 64-bit register).
+ def W#I : Wi<I, "w"#I>, DwarfRegNum<[I]>;
+ // 64-bit Integer registers
+ def R#I : Ri<I, "r"#I, [!cast<Wi>("W"#I)]>, DwarfRegNum<[I]>;
+}
// Register classes.
-def GPR : RegisterClass<"BPF", [i64], 64, (add R1, R2, R3, R4, R5,
- R6, R7, R8, R9, // callee saved
- R0, // return value
- R11, // stack ptr
- R10 // frame ptr
- )>;
+def GPR32 : RegisterClass<"BPF", [i32], 32, (add
+ (sequence "W%u", 1, 9),
+ W0, // Return value
+ W11, // Stack Ptr
+ W10 // Frame Ptr
+)>;
+
+def GPR : RegisterClass<"BPF", [i64], 64, (add
+ (sequence "R%u", 1, 9),
+ R0, // Return value
+ R11, // Stack Ptr
+ R10 // Frame Ptr
+)>;
diff --git a/lib/Target/BPF/BPFSubtarget.cpp b/lib/Target/BPF/BPFSubtarget.cpp
index c3a8b1caa63d..42ca87f9ef67 100644
--- a/lib/Target/BPF/BPFSubtarget.cpp
+++ b/lib/Target/BPF/BPFSubtarget.cpp
@@ -13,6 +13,7 @@
#include "BPFSubtarget.h"
#include "BPF.h"
+#include "llvm/Support/Host.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
@@ -25,7 +26,30 @@ using namespace llvm;
void BPFSubtarget::anchor() {}
+BPFSubtarget &BPFSubtarget::initializeSubtargetDependencies(StringRef CPU,
+ StringRef FS) {
+ initializeEnvironment();
+ initSubtargetFeatures(CPU, FS);
+ return *this;
+}
+
+void BPFSubtarget::initializeEnvironment() {
+ HasJmpExt = false;
+}
+
+void BPFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
+ if (CPU == "probe")
+ CPU = sys::detail::getHostCPUNameForBPF();
+ if (CPU == "generic" || CPU == "v1")
+ return;
+ if (CPU == "v2") {
+ HasJmpExt = true;
+ return;
+ }
+}
+
BPFSubtarget::BPFSubtarget(const Triple &TT, const std::string &CPU,
const std::string &FS, const TargetMachine &TM)
- : BPFGenSubtargetInfo(TT, CPU, FS), InstrInfo(), FrameLowering(*this),
+ : BPFGenSubtargetInfo(TT, CPU, FS), InstrInfo(),
+ FrameLowering(initializeSubtargetDependencies(CPU, FS)),
TLInfo(TM, *this) {}
diff --git a/lib/Target/BPF/BPFSubtarget.h b/lib/Target/BPF/BPFSubtarget.h
index 27cc9a262fc3..fa1f24443bc3 100644
--- a/lib/Target/BPF/BPFSubtarget.h
+++ b/lib/Target/BPF/BPFSubtarget.h
@@ -18,9 +18,9 @@
#include "BPFISelLowering.h"
#include "BPFInstrInfo.h"
#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetSubtargetInfo.h"
#define GET_SUBTARGETINFO_HEADER
#include "BPFGenSubtargetInfo.inc"
@@ -35,15 +35,30 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
BPFTargetLowering TLInfo;
SelectionDAGTargetInfo TSInfo;
+private:
+ void initializeEnvironment();
+ void initSubtargetFeatures(StringRef CPU, StringRef FS);
+ bool probeJmpExt();
+
+protected:
+ // unused
+ bool isDummyMode;
+
+ // whether the cpu supports jmp ext
+ bool HasJmpExt;
+
public:
// This constructor initializes the data members to match that
// of the specified triple.
BPFSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS,
const TargetMachine &TM);
+ BPFSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS);
+
// ParseSubtargetFeatures - Parses features string setting specified
// subtarget options. Definition of function is auto generated by tblgen.
void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
+ bool getHasJmpExt() const { return HasJmpExt; }
const BPFInstrInfo *getInstrInfo() const override { return &InstrInfo; }
const BPFFrameLowering *getFrameLowering() const override {
diff --git a/lib/Target/BPF/BPFTargetMachine.cpp b/lib/Target/BPF/BPFTargetMachine.cpp
index d84b0a80fc0c..60672fa2684b 100644
--- a/lib/Target/BPF/BPFTargetMachine.cpp
+++ b/lib/Target/BPF/BPFTargetMachine.cpp
@@ -43,13 +43,21 @@ static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
return *RM;
}
+static CodeModel::Model getEffectiveCodeModel(Optional<CodeModel::Model> CM) {
+ if (CM)
+ return *CM;
+ return CodeModel::Small;
+}
+
BPFTargetMachine::BPFTargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
const TargetOptions &Options,
Optional<Reloc::Model> RM,
- CodeModel::Model CM, CodeGenOpt::Level OL)
+ Optional<CodeModel::Model> CM,
+ CodeGenOpt::Level OL, bool JIT)
: LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
- getEffectiveRelocModel(RM), CM, OL),
+ getEffectiveRelocModel(RM), getEffectiveCodeModel(CM),
+ OL),
TLOF(make_unique<TargetLoweringObjectFileELF>()),
Subtarget(TT, CPU, FS, *this) {
initAsmInfo();
diff --git a/lib/Target/BPF/BPFTargetMachine.h b/lib/Target/BPF/BPFTargetMachine.h
index 644481446883..a560dd27335a 100644
--- a/lib/Target/BPF/BPFTargetMachine.h
+++ b/lib/Target/BPF/BPFTargetMachine.h
@@ -25,8 +25,8 @@ class BPFTargetMachine : public LLVMTargetMachine {
public:
BPFTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
StringRef FS, const TargetOptions &Options,
- Optional<Reloc::Model> RM, CodeModel::Model CM,
- CodeGenOpt::Level OL);
+ Optional<Reloc::Model> RM, Optional<CodeModel::Model> CM,
+ CodeGenOpt::Level OL, bool JIT);
const BPFSubtarget *getSubtargetImpl() const { return &Subtarget; }
const BPFSubtarget *getSubtargetImpl(const Function &) const override {
diff --git a/lib/Target/BPF/CMakeLists.txt b/lib/Target/BPF/CMakeLists.txt
index 4918653ff19d..1e4b685a6092 100644
--- a/lib/Target/BPF/CMakeLists.txt
+++ b/lib/Target/BPF/CMakeLists.txt
@@ -23,6 +23,7 @@ add_llvm_target(BPFCodeGen
BPFTargetMachine.cpp
)
+add_subdirectory(AsmParser)
add_subdirectory(Disassembler)
add_subdirectory(InstPrinter)
add_subdirectory(TargetInfo)
diff --git a/lib/Target/BPF/Disassembler/BPFDisassembler.cpp b/lib/Target/BPF/Disassembler/BPFDisassembler.cpp
index a1d732c339e5..6fc87d79c439 100644
--- a/lib/Target/BPF/Disassembler/BPFDisassembler.cpp
+++ b/lib/Target/BPF/Disassembler/BPFDisassembler.cpp
@@ -79,6 +79,21 @@ static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
return MCDisassembler::Success;
}
+static const unsigned GPR32DecoderTable[] = {
+ BPF::W0, BPF::W1, BPF::W2, BPF::W3, BPF::W4, BPF::W5,
+ BPF::W6, BPF::W7, BPF::W8, BPF::W9, BPF::W10, BPF::W11};
+
+static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t /*Address*/,
+ const void * /*Decoder*/) {
+ if (RegNo > 11)
+ return MCDisassembler::Fail;
+
+ unsigned Reg = GPR32DecoderTable[RegNo];
+ Inst.addOperand(MCOperand::createReg(Reg));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus decodeMemoryOpValue(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
unsigned Register = (Insn >> 16) & 0xf;
@@ -131,7 +146,8 @@ DecodeStatus BPFDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
if (Result == MCDisassembler::Fail) return MCDisassembler::Fail;
switch (Instr.getOpcode()) {
- case BPF::LD_imm64: {
+ case BPF::LD_imm64:
+ case BPF::LD_pseudo: {
if (Bytes.size() < 16) {
Size = 0;
return MCDisassembler::Fail;
diff --git a/lib/Target/BPF/InstPrinter/BPFInstPrinter.cpp b/lib/Target/BPF/InstPrinter/BPFInstPrinter.cpp
index 64e986fe0f04..6f81e020b996 100644
--- a/lib/Target/BPF/InstPrinter/BPFInstPrinter.cpp
+++ b/lib/Target/BPF/InstPrinter/BPFInstPrinter.cpp
@@ -89,6 +89,21 @@ void BPFInstPrinter::printImm64Operand(const MCInst *MI, unsigned OpNo,
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isImm())
O << (uint64_t)Op.getImm();
+ else if (Op.isExpr())
+ printExpr(Op.getExpr(), O);
else
O << Op;
}
+
+void BPFInstPrinter::printBrTargetOperand(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ const MCOperand &Op = MI->getOperand(OpNo);
+ if (Op.isImm()) {
+ int16_t Imm = Op.getImm();
+ O << ((Imm >= 0) ? "+" : "") << Imm;
+ } else if (Op.isExpr()) {
+ printExpr(Op.getExpr(), O);
+ } else {
+ O << Op;
+ }
+}
diff --git a/lib/Target/BPF/InstPrinter/BPFInstPrinter.h b/lib/Target/BPF/InstPrinter/BPFInstPrinter.h
index 4276d0858c2e..bb0b0d71da53 100644
--- a/lib/Target/BPF/InstPrinter/BPFInstPrinter.h
+++ b/lib/Target/BPF/InstPrinter/BPFInstPrinter.h
@@ -30,6 +30,7 @@ public:
void printMemOperand(const MCInst *MI, int OpNo, raw_ostream &O,
const char *Modifier = nullptr);
void printImm64Operand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printBrTargetOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
// Autogenerated by tblgen.
void printInstruction(const MCInst *MI, raw_ostream &O);
diff --git a/lib/Target/BPF/LLVMBuild.txt b/lib/Target/BPF/LLVMBuild.txt
index 171536d78eaa..3f9849b5d922 100644
--- a/lib/Target/BPF/LLVMBuild.txt
+++ b/lib/Target/BPF/LLVMBuild.txt
@@ -16,7 +16,7 @@
;===------------------------------------------------------------------------===;
[common]
-subdirectories = InstPrinter Disassembler MCTargetDesc TargetInfo
+subdirectories = AsmParser InstPrinter Disassembler MCTargetDesc TargetInfo
[component_0]
type = TargetGroup
diff --git a/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp b/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
index 9fc812cdef14..e6ea92e08364 100644
--- a/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
+++ b/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
@@ -31,7 +31,8 @@ public:
const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsResolved) const override;
- MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
+ std::unique_ptr<MCObjectWriter>
+ createObjectWriter(raw_pwrite_stream &OS) const override;
// No instruction requires relaxation
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
@@ -75,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);
@@ -88,7 +98,8 @@ void BPFAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
}
}
-MCObjectWriter *BPFAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
+std::unique_ptr<MCObjectWriter>
+BPFAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
return createBPFELFObjectWriter(OS, 0, IsLittleEndian);
}
diff --git a/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp b/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp
index d5e1d7706edc..f7de612dab15 100644
--- a/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp
+++ b/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp
@@ -11,6 +11,7 @@
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCObjectWriter.h"
#include "llvm/Support/ErrorHandling.h"
#include <cstdint>
@@ -43,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:
@@ -52,8 +54,9 @@ unsigned BPFELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
}
}
-MCObjectWriter *llvm::createBPFELFObjectWriter(raw_pwrite_stream &OS,
- uint8_t OSABI, bool IsLittleEndian) {
- MCELFObjectTargetWriter *MOTW = new BPFELFObjectWriter(OSABI);
- return createELFObjectWriter(MOTW, OS, IsLittleEndian);
+std::unique_ptr<MCObjectWriter>
+llvm::createBPFELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI,
+ bool IsLittleEndian) {
+ return createELFObjectWriter(llvm::make_unique<BPFELFObjectWriter>(OSABI), OS,
+ IsLittleEndian);
}
diff --git a/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp b/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp
index e8c974479828..b4ecfdee7bff 100644
--- a/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp
+++ b/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
diff --git a/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp b/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp
index 797904e1c976..cbf1ea7d7fb8 100644
--- a/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp
+++ b/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp
@@ -15,6 +15,7 @@
#include "BPF.h"
#include "InstPrinter/BPFInstPrinter.h"
#include "MCTargetDesc/BPFMCAsmInfo.h"
+#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
@@ -49,11 +50,13 @@ static MCSubtargetInfo *createBPFMCSubtargetInfo(const Triple &TT,
return createBPFMCSubtargetInfoImpl(TT, CPU, FS);
}
-static MCStreamer *createBPFMCStreamer(const Triple &T,
- MCContext &Ctx, MCAsmBackend &MAB,
- raw_pwrite_stream &OS, MCCodeEmitter *Emitter,
+static MCStreamer *createBPFMCStreamer(const Triple &T, MCContext &Ctx,
+ std::unique_ptr<MCAsmBackend> &&MAB,
+ raw_pwrite_stream &OS,
+ std::unique_ptr<MCCodeEmitter> &&Emitter,
bool RelaxAll) {
- return createELFStreamer(Ctx, MAB, OS, Emitter, RelaxAll);
+ return createELFStreamer(Ctx, std::move(MAB), OS, std::move(Emitter),
+ RelaxAll);
}
static MCInstPrinter *createBPFMCInstPrinter(const Triple &T,
@@ -66,6 +69,35 @@ static MCInstPrinter *createBPFMCInstPrinter(const Triple &T,
return nullptr;
}
+namespace {
+
+class BPFMCInstrAnalysis : public MCInstrAnalysis {
+public:
+ explicit BPFMCInstrAnalysis(const MCInstrInfo *Info)
+ : MCInstrAnalysis(Info) {}
+
+ bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
+ uint64_t &Target) const override {
+ // The target is the 3rd operand of cond inst and the 1st of uncond inst.
+ int16_t Imm;
+ if (isConditionalBranch(Inst)) {
+ Imm = Inst.getOperand(2).getImm();
+ } else if (isUnconditionalBranch(Inst))
+ Imm = Inst.getOperand(0).getImm();
+ else
+ return false;
+
+ Target = Addr + Size + Imm * Size;
+ return true;
+ }
+};
+
+} // end anonymous namespace
+
+static MCInstrAnalysis *createBPFInstrAnalysis(const MCInstrInfo *Info) {
+ return new BPFMCInstrAnalysis(Info);
+}
+
extern "C" void LLVMInitializeBPFTargetMC() {
for (Target *T :
{&getTheBPFleTarget(), &getTheBPFbeTarget(), &getTheBPFTarget()}) {
@@ -87,6 +119,9 @@ extern "C" void LLVMInitializeBPFTargetMC() {
// Register the MCInstPrinter.
TargetRegistry::RegisterMCInstPrinter(*T, createBPFMCInstPrinter);
+
+ // Register the MC instruction analyzer.
+ TargetRegistry::RegisterMCInstrAnalysis(*T, createBPFInstrAnalysis);
}
// Register the MC code emitter
@@ -112,4 +147,5 @@ extern "C" void LLVMInitializeBPFTargetMC() {
TargetRegistry::RegisterMCAsmBackend(getTheBPFTarget(),
createBPFbeAsmBackend);
}
+
}
diff --git a/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h b/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h
index d1c97c9987e1..6466042f6929 100644
--- a/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h
+++ b/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h
@@ -17,6 +17,8 @@
#include "llvm/Config/config.h"
#include "llvm/Support/DataTypes.h"
+#include <memory>
+
namespace llvm {
class MCAsmBackend;
class MCCodeEmitter;
@@ -50,8 +52,9 @@ MCAsmBackend *createBPFbeAsmBackend(const Target &T, const MCRegisterInfo &MRI,
const Triple &TT, StringRef CPU,
const MCTargetOptions &Options);
-MCObjectWriter *createBPFELFObjectWriter(raw_pwrite_stream &OS,
- uint8_t OSABI, bool IsLittleEndian);
+std::unique_ptr<MCObjectWriter> createBPFELFObjectWriter(raw_pwrite_stream &OS,
+ uint8_t OSABI,
+ bool IsLittleEndian);
}
// Defines symbolic names for BPF registers. This defines a mapping from
diff --git a/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp b/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp
index 265180b99876..1f7b8a04d589 100644
--- a/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp
+++ b/lib/Target/BPF/TargetInfo/BPFTargetInfo.cpp
@@ -28,9 +28,10 @@ Target &getTheBPFTarget() {
extern "C" void LLVMInitializeBPFTargetInfo() {
TargetRegistry::RegisterTarget(getTheBPFTarget(), "bpf", "BPF (host endian)",
- [](Triple::ArchType) { return false; }, true);
- RegisterTarget<Triple::bpfel, /*HasJIT=*/true> X(getTheBPFleTarget(), "bpfel",
- "BPF (little endian)");
+ "BPF", [](Triple::ArchType) { return false; },
+ true);
+ RegisterTarget<Triple::bpfel, /*HasJIT=*/true> X(
+ getTheBPFleTarget(), "bpfel", "BPF (little endian)", "BPF");
RegisterTarget<Triple::bpfeb, /*HasJIT=*/true> Y(getTheBPFbeTarget(), "bpfeb",
- "BPF (big endian)");
+ "BPF (big endian)", "BPF");
}