1 //===-- BPFAsmParser.cpp - Parse BPF assembly to MCInst instructions --===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "MCTargetDesc/BPFMCTargetDesc.h"
10 #include "TargetInfo/BPFTargetInfo.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/StringSwitch.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCInst.h"
16 #include "llvm/MC/MCParser/MCAsmLexer.h"
17 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
18 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
19 #include "llvm/MC/MCRegisterInfo.h"
20 #include "llvm/MC/MCStreamer.h"
21 #include "llvm/MC/MCSubtargetInfo.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/TargetRegistry.h"
30 class BPFAsmParser : public MCTargetAsmParser {
32 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
34 bool PreMatchCheck(OperandVector &Operands);
36 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
37 OperandVector &Operands, MCStreamer &Out,
39 bool MatchingInlineAsm) override;
41 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
42 OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
43 SMLoc &EndLoc) override;
45 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
46 SMLoc NameLoc, OperandVector &Operands) override;
48 bool ParseDirective(AsmToken DirectiveID) override;
50 // "=" is used as assignment operator for assembly statment, so can't be used
51 // for symbol assignment.
52 bool equalIsAsmAssignment() override { return false; }
53 // "*" is used for dereferencing memory that it will be the start of
55 bool starIsStartOfStatement() override { return true; }
57 #define GET_ASSEMBLER_HEADER
58 #include "BPFGenAsmMatcher.inc"
60 OperandMatchResultTy parseImmediate(OperandVector &Operands);
61 OperandMatchResultTy parseRegister(OperandVector &Operands);
62 OperandMatchResultTy parseOperandAsOperator(OperandVector &Operands);
65 enum BPFMatchResultTy {
66 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
67 #define GET_OPERAND_DIAGNOSTIC_TYPES
68 #include "BPFGenAsmMatcher.inc"
69 #undef GET_OPERAND_DIAGNOSTIC_TYPES
72 BPFAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
73 const MCInstrInfo &MII, const MCTargetOptions &Options)
74 : MCTargetAsmParser(Options, STI, MII) {
75 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
79 /// BPFOperand - Instances of this class represent a parsed machine
81 struct BPFOperand : public MCParsedAsmOperand {
97 SMLoc StartLoc, EndLoc;
104 BPFOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
107 BPFOperand(const BPFOperand &o) : MCParsedAsmOperand() {
109 StartLoc = o.StartLoc;
125 bool isToken() const override { return Kind == Token; }
126 bool isReg() const override { return Kind == Register; }
127 bool isImm() const override { return Kind == Immediate; }
128 bool isMem() const override { return false; }
130 bool isConstantImm() const {
131 return isImm() && isa<MCConstantExpr>(getImm());
134 int64_t getConstantImm() const {
135 const MCExpr *Val = getImm();
136 return static_cast<const MCConstantExpr *>(Val)->getValue();
139 bool isSImm12() const {
140 return (isConstantImm() && isInt<12>(getConstantImm()));
143 /// getStartLoc - Gets location of the first token of this operand
144 SMLoc getStartLoc() const override { return StartLoc; }
145 /// getEndLoc - Gets location of the last token of this operand
146 SMLoc getEndLoc() const override { return EndLoc; }
148 unsigned getReg() const override {
149 assert(Kind == Register && "Invalid type access!");
153 const MCExpr *getImm() const {
154 assert(Kind == Immediate && "Invalid type access!");
158 StringRef getToken() const {
159 assert(Kind == Token && "Invalid type access!");
163 void print(raw_ostream &OS) const override {
170 OS << getReg() << ">";
173 OS << "'" << getToken() << "'";
178 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
179 assert(Expr && "Expr shouldn't be null!");
181 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
182 Inst.addOperand(MCOperand::createImm(CE->getValue()));
184 Inst.addOperand(MCOperand::createExpr(Expr));
187 // Used by the TableGen Code
188 void addRegOperands(MCInst &Inst, unsigned N) const {
189 assert(N == 1 && "Invalid number of operands!");
190 Inst.addOperand(MCOperand::createReg(getReg()));
193 void addImmOperands(MCInst &Inst, unsigned N) const {
194 assert(N == 1 && "Invalid number of operands!");
195 addExpr(Inst, getImm());
198 static std::unique_ptr<BPFOperand> createToken(StringRef Str, SMLoc S) {
199 auto Op = std::make_unique<BPFOperand>(Token);
206 static std::unique_ptr<BPFOperand> createReg(unsigned RegNo, SMLoc S,
208 auto Op = std::make_unique<BPFOperand>(Register);
209 Op->Reg.RegNum = RegNo;
215 static std::unique_ptr<BPFOperand> createImm(const MCExpr *Val, SMLoc S,
217 auto Op = std::make_unique<BPFOperand>(Immediate);
224 // Identifiers that can be used at the start of a statment.
225 static bool isValidIdAtStart(StringRef Name) {
226 return StringSwitch<bool>(Name.lower())
233 .Case("ld_pseudo", true)
237 // Identifiers that can be used in the middle of a statment.
238 static bool isValidIdInMiddle(StringRef Name) {
239 return StringSwitch<bool>(Name.lower())
257 } // end anonymous namespace.
259 #define GET_REGISTER_MATCHER
260 #define GET_MATCHER_IMPLEMENTATION
261 #include "BPFGenAsmMatcher.inc"
263 bool BPFAsmParser::PreMatchCheck(OperandVector &Operands) {
265 if (Operands.size() == 4) {
266 // check "reg1 = -reg2" and "reg1 = be16/be32/be64/le16/le32/le64 reg2",
267 // reg1 must be the same as reg2
268 BPFOperand &Op0 = (BPFOperand &)*Operands[0];
269 BPFOperand &Op1 = (BPFOperand &)*Operands[1];
270 BPFOperand &Op2 = (BPFOperand &)*Operands[2];
271 BPFOperand &Op3 = (BPFOperand &)*Operands[3];
272 if (Op0.isReg() && Op1.isToken() && Op2.isToken() && Op3.isReg()
273 && Op1.getToken() == "="
274 && (Op2.getToken() == "-" || Op2.getToken() == "be16"
275 || Op2.getToken() == "be32" || Op2.getToken() == "be64"
276 || Op2.getToken() == "le16" || Op2.getToken() == "le32"
277 || Op2.getToken() == "le64")
278 && Op0.getReg() != Op3.getReg())
285 bool BPFAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
286 OperandVector &Operands,
287 MCStreamer &Out, uint64_t &ErrorInfo,
288 bool MatchingInlineAsm) {
292 if (PreMatchCheck(Operands))
293 return Error(IDLoc, "additional inst constraint not met");
295 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
300 Out.emitInstruction(Inst, getSTI());
302 case Match_MissingFeature:
303 return Error(IDLoc, "instruction use requires an option to be enabled");
304 case Match_MnemonicFail:
305 return Error(IDLoc, "unrecognized instruction mnemonic");
306 case Match_InvalidOperand:
309 if (ErrorInfo != ~0U) {
310 if (ErrorInfo >= Operands.size())
311 return Error(ErrorLoc, "too few operands for instruction");
313 ErrorLoc = ((BPFOperand &)*Operands[ErrorInfo]).getStartLoc();
315 if (ErrorLoc == SMLoc())
319 return Error(ErrorLoc, "invalid operand for instruction");
322 llvm_unreachable("Unknown match type detected!");
325 bool BPFAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
327 if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success)
328 return Error(StartLoc, "invalid register name");
332 OperandMatchResultTy BPFAsmParser::tryParseRegister(unsigned &RegNo,
335 const AsmToken &Tok = getParser().getTok();
336 StartLoc = Tok.getLoc();
337 EndLoc = Tok.getEndLoc();
339 StringRef Name = getLexer().getTok().getIdentifier();
341 if (!MatchRegisterName(Name)) {
342 getParser().Lex(); // Eat identifier token.
343 return MatchOperand_Success;
346 return MatchOperand_NoMatch;
350 BPFAsmParser::parseOperandAsOperator(OperandVector &Operands) {
353 if (getLexer().getKind() == AsmToken::Identifier) {
354 StringRef Name = getLexer().getTok().getIdentifier();
356 if (BPFOperand::isValidIdInMiddle(Name)) {
358 Operands.push_back(BPFOperand::createToken(Name, S));
359 return MatchOperand_Success;
362 return MatchOperand_NoMatch;
365 switch (getLexer().getKind()) {
366 case AsmToken::Minus:
367 case AsmToken::Plus: {
368 if (getLexer().peekTok().is(AsmToken::Integer))
369 return MatchOperand_NoMatch;
373 case AsmToken::Equal:
374 case AsmToken::Greater:
378 case AsmToken::LParen:
379 case AsmToken::RParen:
380 case AsmToken::LBrac:
381 case AsmToken::RBrac:
382 case AsmToken::Slash:
384 case AsmToken::Percent:
385 case AsmToken::Caret: {
386 StringRef Name = getLexer().getTok().getString();
388 Operands.push_back(BPFOperand::createToken(Name, S));
390 return MatchOperand_Success;
393 case AsmToken::EqualEqual:
394 case AsmToken::ExclaimEqual:
395 case AsmToken::GreaterEqual:
396 case AsmToken::GreaterGreater:
397 case AsmToken::LessEqual:
398 case AsmToken::LessLess: {
399 Operands.push_back(BPFOperand::createToken(
400 getLexer().getTok().getString().substr(0, 1), S));
401 Operands.push_back(BPFOperand::createToken(
402 getLexer().getTok().getString().substr(1, 1), S));
405 return MatchOperand_Success;
412 return MatchOperand_NoMatch;
415 OperandMatchResultTy BPFAsmParser::parseRegister(OperandVector &Operands) {
417 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
419 switch (getLexer().getKind()) {
421 return MatchOperand_NoMatch;
422 case AsmToken::Identifier:
423 StringRef Name = getLexer().getTok().getIdentifier();
424 unsigned RegNo = MatchRegisterName(Name);
427 return MatchOperand_NoMatch;
430 Operands.push_back(BPFOperand::createReg(RegNo, S, E));
432 return MatchOperand_Success;
435 OperandMatchResultTy BPFAsmParser::parseImmediate(OperandVector &Operands) {
436 switch (getLexer().getKind()) {
438 return MatchOperand_NoMatch;
439 case AsmToken::LParen:
440 case AsmToken::Minus:
442 case AsmToken::Integer:
443 case AsmToken::String:
444 case AsmToken::Identifier:
451 if (getParser().parseExpression(IdVal))
452 return MatchOperand_ParseFail;
454 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
455 Operands.push_back(BPFOperand::createImm(IdVal, S, E));
457 return MatchOperand_Success;
460 /// ParseInstruction - Parse an BPF instruction which is in BPF verifier
462 bool BPFAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
463 SMLoc NameLoc, OperandVector &Operands) {
464 // The first operand could be either register or actually an operator.
465 unsigned RegNo = MatchRegisterName(Name);
468 SMLoc E = SMLoc::getFromPointer(NameLoc.getPointer() - 1);
469 Operands.push_back(BPFOperand::createReg(RegNo, NameLoc, E));
470 } else if (BPFOperand::isValidIdAtStart (Name))
471 Operands.push_back(BPFOperand::createToken(Name, NameLoc));
473 return Error(NameLoc, "invalid register/token name");
475 while (!getLexer().is(AsmToken::EndOfStatement)) {
476 // Attempt to parse token as operator
477 if (parseOperandAsOperator(Operands) == MatchOperand_Success)
480 // Attempt to parse token as register
481 if (parseRegister(Operands) == MatchOperand_Success)
484 // Attempt to parse token as an immediate
485 if (parseImmediate(Operands) != MatchOperand_Success) {
486 SMLoc Loc = getLexer().getLoc();
487 return Error(Loc, "unexpected token");
491 if (getLexer().isNot(AsmToken::EndOfStatement)) {
492 SMLoc Loc = getLexer().getLoc();
494 getParser().eatToEndOfStatement();
496 return Error(Loc, "unexpected token");
499 // Consume the EndOfStatement.
504 bool BPFAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
506 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFAsmParser() {
507 RegisterMCAsmParser<BPFAsmParser> X(getTheBPFTarget());
508 RegisterMCAsmParser<BPFAsmParser> Y(getTheBPFleTarget());
509 RegisterMCAsmParser<BPFAsmParser> Z(getTheBPFbeTarget());