diff options
Diffstat (limited to 'lib/Target/BPF')
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"); } |
