BPFAsmParser.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. //===-- BPFAsmParser.cpp - Parse BPF assembly to MCInst instructions --===//
  2. //
  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
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "MCTargetDesc/BPFMCTargetDesc.h"
  9. #include "TargetInfo/BPFTargetInfo.h"
  10. #include "llvm/ADT/STLExtras.h"
  11. #include "llvm/ADT/StringSwitch.h"
  12. #include "llvm/MC/MCContext.h"
  13. #include "llvm/MC/MCExpr.h"
  14. #include "llvm/MC/MCInst.h"
  15. #include "llvm/MC/MCInstrInfo.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/MC/TargetRegistry.h"
  23. #include "llvm/Support/Casting.h"
  24. using namespace llvm;
  25. namespace {
  26. struct BPFOperand;
  27. class BPFAsmParser : public MCTargetAsmParser {
  28. SMLoc getLoc() const { return getParser().getTok().getLoc(); }
  29. bool PreMatchCheck(OperandVector &Operands);
  30. bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
  31. OperandVector &Operands, MCStreamer &Out,
  32. uint64_t &ErrorInfo,
  33. bool MatchingInlineAsm) override;
  34. bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
  35. SMLoc &EndLoc) override;
  36. OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc,
  37. SMLoc &EndLoc) override;
  38. bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
  39. SMLoc NameLoc, OperandVector &Operands) override;
  40. bool ParseDirective(AsmToken DirectiveID) override;
  41. // "=" is used as assignment operator for assembly statment, so can't be used
  42. // for symbol assignment.
  43. bool equalIsAsmAssignment() override { return false; }
  44. // "*" is used for dereferencing memory that it will be the start of
  45. // statement.
  46. bool starIsStartOfStatement() override { return true; }
  47. #define GET_ASSEMBLER_HEADER
  48. #include "BPFGenAsmMatcher.inc"
  49. OperandMatchResultTy parseImmediate(OperandVector &Operands);
  50. OperandMatchResultTy parseRegister(OperandVector &Operands);
  51. OperandMatchResultTy parseOperandAsOperator(OperandVector &Operands);
  52. public:
  53. enum BPFMatchResultTy {
  54. Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
  55. #define GET_OPERAND_DIAGNOSTIC_TYPES
  56. #include "BPFGenAsmMatcher.inc"
  57. #undef GET_OPERAND_DIAGNOSTIC_TYPES
  58. };
  59. BPFAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
  60. const MCInstrInfo &MII, const MCTargetOptions &Options)
  61. : MCTargetAsmParser(Options, STI, MII) {
  62. setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
  63. }
  64. };
  65. /// BPFOperand - Instances of this class represent a parsed machine
  66. /// instruction
  67. struct BPFOperand : public MCParsedAsmOperand {
  68. enum KindTy {
  69. Token,
  70. Register,
  71. Immediate,
  72. } Kind;
  73. struct RegOp {
  74. unsigned RegNum;
  75. };
  76. struct ImmOp {
  77. const MCExpr *Val;
  78. };
  79. SMLoc StartLoc, EndLoc;
  80. union {
  81. StringRef Tok;
  82. RegOp Reg;
  83. ImmOp Imm;
  84. };
  85. BPFOperand(KindTy K) : Kind(K) {}
  86. public:
  87. BPFOperand(const BPFOperand &o) : MCParsedAsmOperand() {
  88. Kind = o.Kind;
  89. StartLoc = o.StartLoc;
  90. EndLoc = o.EndLoc;
  91. switch (Kind) {
  92. case Register:
  93. Reg = o.Reg;
  94. break;
  95. case Immediate:
  96. Imm = o.Imm;
  97. break;
  98. case Token:
  99. Tok = o.Tok;
  100. break;
  101. }
  102. }
  103. bool isToken() const override { return Kind == Token; }
  104. bool isReg() const override { return Kind == Register; }
  105. bool isImm() const override { return Kind == Immediate; }
  106. bool isMem() const override { return false; }
  107. bool isConstantImm() const {
  108. return isImm() && isa<MCConstantExpr>(getImm());
  109. }
  110. int64_t getConstantImm() const {
  111. const MCExpr *Val = getImm();
  112. return static_cast<const MCConstantExpr *>(Val)->getValue();
  113. }
  114. bool isSImm12() const {
  115. return (isConstantImm() && isInt<12>(getConstantImm()));
  116. }
  117. /// getStartLoc - Gets location of the first token of this operand
  118. SMLoc getStartLoc() const override { return StartLoc; }
  119. /// getEndLoc - Gets location of the last token of this operand
  120. SMLoc getEndLoc() const override { return EndLoc; }
  121. unsigned getReg() const override {
  122. assert(Kind == Register && "Invalid type access!");
  123. return Reg.RegNum;
  124. }
  125. const MCExpr *getImm() const {
  126. assert(Kind == Immediate && "Invalid type access!");
  127. return Imm.Val;
  128. }
  129. StringRef getToken() const {
  130. assert(Kind == Token && "Invalid type access!");
  131. return Tok;
  132. }
  133. void print(raw_ostream &OS) const override {
  134. switch (Kind) {
  135. case Immediate:
  136. OS << *getImm();
  137. break;
  138. case Register:
  139. OS << "<register x";
  140. OS << getReg() << ">";
  141. break;
  142. case Token:
  143. OS << "'" << getToken() << "'";
  144. break;
  145. }
  146. }
  147. void addExpr(MCInst &Inst, const MCExpr *Expr) const {
  148. assert(Expr && "Expr shouldn't be null!");
  149. if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
  150. Inst.addOperand(MCOperand::createImm(CE->getValue()));
  151. else
  152. Inst.addOperand(MCOperand::createExpr(Expr));
  153. }
  154. // Used by the TableGen Code
  155. void addRegOperands(MCInst &Inst, unsigned N) const {
  156. assert(N == 1 && "Invalid number of operands!");
  157. Inst.addOperand(MCOperand::createReg(getReg()));
  158. }
  159. void addImmOperands(MCInst &Inst, unsigned N) const {
  160. assert(N == 1 && "Invalid number of operands!");
  161. addExpr(Inst, getImm());
  162. }
  163. static std::unique_ptr<BPFOperand> createToken(StringRef Str, SMLoc S) {
  164. auto Op = std::make_unique<BPFOperand>(Token);
  165. Op->Tok = Str;
  166. Op->StartLoc = S;
  167. Op->EndLoc = S;
  168. return Op;
  169. }
  170. static std::unique_ptr<BPFOperand> createReg(unsigned RegNo, SMLoc S,
  171. SMLoc E) {
  172. auto Op = std::make_unique<BPFOperand>(Register);
  173. Op->Reg.RegNum = RegNo;
  174. Op->StartLoc = S;
  175. Op->EndLoc = E;
  176. return Op;
  177. }
  178. static std::unique_ptr<BPFOperand> createImm(const MCExpr *Val, SMLoc S,
  179. SMLoc E) {
  180. auto Op = std::make_unique<BPFOperand>(Immediate);
  181. Op->Imm.Val = Val;
  182. Op->StartLoc = S;
  183. Op->EndLoc = E;
  184. return Op;
  185. }
  186. // Identifiers that can be used at the start of a statment.
  187. static bool isValidIdAtStart(StringRef Name) {
  188. return StringSwitch<bool>(Name.lower())
  189. .Case("if", true)
  190. .Case("call", true)
  191. .Case("goto", true)
  192. .Case("*", true)
  193. .Case("exit", true)
  194. .Case("lock", true)
  195. .Case("ld_pseudo", true)
  196. .Default(false);
  197. }
  198. // Identifiers that can be used in the middle of a statment.
  199. static bool isValidIdInMiddle(StringRef Name) {
  200. return StringSwitch<bool>(Name.lower())
  201. .Case("u64", true)
  202. .Case("u32", true)
  203. .Case("u16", true)
  204. .Case("u8", true)
  205. .Case("be64", true)
  206. .Case("be32", true)
  207. .Case("be16", true)
  208. .Case("le64", true)
  209. .Case("le32", true)
  210. .Case("le16", true)
  211. .Case("goto", true)
  212. .Case("ll", true)
  213. .Case("skb", true)
  214. .Case("s", true)
  215. .Default(false);
  216. }
  217. };
  218. } // end anonymous namespace.
  219. #define GET_REGISTER_MATCHER
  220. #define GET_MATCHER_IMPLEMENTATION
  221. #include "BPFGenAsmMatcher.inc"
  222. bool BPFAsmParser::PreMatchCheck(OperandVector &Operands) {
  223. if (Operands.size() == 4) {
  224. // check "reg1 = -reg2" and "reg1 = be16/be32/be64/le16/le32/le64 reg2",
  225. // reg1 must be the same as reg2
  226. BPFOperand &Op0 = (BPFOperand &)*Operands[0];
  227. BPFOperand &Op1 = (BPFOperand &)*Operands[1];
  228. BPFOperand &Op2 = (BPFOperand &)*Operands[2];
  229. BPFOperand &Op3 = (BPFOperand &)*Operands[3];
  230. if (Op0.isReg() && Op1.isToken() && Op2.isToken() && Op3.isReg()
  231. && Op1.getToken() == "="
  232. && (Op2.getToken() == "-" || Op2.getToken() == "be16"
  233. || Op2.getToken() == "be32" || Op2.getToken() == "be64"
  234. || Op2.getToken() == "le16" || Op2.getToken() == "le32"
  235. || Op2.getToken() == "le64")
  236. && Op0.getReg() != Op3.getReg())
  237. return true;
  238. }
  239. return false;
  240. }
  241. bool BPFAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
  242. OperandVector &Operands,
  243. MCStreamer &Out, uint64_t &ErrorInfo,
  244. bool MatchingInlineAsm) {
  245. MCInst Inst;
  246. SMLoc ErrorLoc;
  247. if (PreMatchCheck(Operands))
  248. return Error(IDLoc, "additional inst constraint not met");
  249. switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
  250. default:
  251. break;
  252. case Match_Success:
  253. Inst.setLoc(IDLoc);
  254. Out.emitInstruction(Inst, getSTI());
  255. return false;
  256. case Match_MissingFeature:
  257. return Error(IDLoc, "instruction use requires an option to be enabled");
  258. case Match_MnemonicFail:
  259. return Error(IDLoc, "unrecognized instruction mnemonic");
  260. case Match_InvalidOperand:
  261. ErrorLoc = IDLoc;
  262. if (ErrorInfo != ~0U) {
  263. if (ErrorInfo >= Operands.size())
  264. return Error(ErrorLoc, "too few operands for instruction");
  265. ErrorLoc = ((BPFOperand &)*Operands[ErrorInfo]).getStartLoc();
  266. if (ErrorLoc == SMLoc())
  267. ErrorLoc = IDLoc;
  268. }
  269. return Error(ErrorLoc, "invalid operand for instruction");
  270. }
  271. llvm_unreachable("Unknown match type detected!");
  272. }
  273. bool BPFAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
  274. SMLoc &EndLoc) {
  275. if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success)
  276. return Error(StartLoc, "invalid register name");
  277. return false;
  278. }
  279. OperandMatchResultTy BPFAsmParser::tryParseRegister(MCRegister &RegNo,
  280. SMLoc &StartLoc,
  281. SMLoc &EndLoc) {
  282. const AsmToken &Tok = getParser().getTok();
  283. StartLoc = Tok.getLoc();
  284. EndLoc = Tok.getEndLoc();
  285. RegNo = 0;
  286. StringRef Name = getLexer().getTok().getIdentifier();
  287. if (!MatchRegisterName(Name)) {
  288. getParser().Lex(); // Eat identifier token.
  289. return MatchOperand_Success;
  290. }
  291. return MatchOperand_NoMatch;
  292. }
  293. OperandMatchResultTy
  294. BPFAsmParser::parseOperandAsOperator(OperandVector &Operands) {
  295. SMLoc S = getLoc();
  296. if (getLexer().getKind() == AsmToken::Identifier) {
  297. StringRef Name = getLexer().getTok().getIdentifier();
  298. if (BPFOperand::isValidIdInMiddle(Name)) {
  299. getLexer().Lex();
  300. Operands.push_back(BPFOperand::createToken(Name, S));
  301. return MatchOperand_Success;
  302. }
  303. return MatchOperand_NoMatch;
  304. }
  305. switch (getLexer().getKind()) {
  306. case AsmToken::Minus:
  307. case AsmToken::Plus: {
  308. if (getLexer().peekTok().is(AsmToken::Integer))
  309. return MatchOperand_NoMatch;
  310. [[fallthrough]];
  311. }
  312. case AsmToken::Equal:
  313. case AsmToken::Greater:
  314. case AsmToken::Less:
  315. case AsmToken::Pipe:
  316. case AsmToken::Star:
  317. case AsmToken::LParen:
  318. case AsmToken::RParen:
  319. case AsmToken::LBrac:
  320. case AsmToken::RBrac:
  321. case AsmToken::Slash:
  322. case AsmToken::Amp:
  323. case AsmToken::Percent:
  324. case AsmToken::Caret: {
  325. StringRef Name = getLexer().getTok().getString();
  326. getLexer().Lex();
  327. Operands.push_back(BPFOperand::createToken(Name, S));
  328. return MatchOperand_Success;
  329. }
  330. case AsmToken::EqualEqual:
  331. case AsmToken::ExclaimEqual:
  332. case AsmToken::GreaterEqual:
  333. case AsmToken::GreaterGreater:
  334. case AsmToken::LessEqual:
  335. case AsmToken::LessLess: {
  336. Operands.push_back(BPFOperand::createToken(
  337. getLexer().getTok().getString().substr(0, 1), S));
  338. Operands.push_back(BPFOperand::createToken(
  339. getLexer().getTok().getString().substr(1, 1), S));
  340. getLexer().Lex();
  341. return MatchOperand_Success;
  342. }
  343. default:
  344. break;
  345. }
  346. return MatchOperand_NoMatch;
  347. }
  348. OperandMatchResultTy BPFAsmParser::parseRegister(OperandVector &Operands) {
  349. SMLoc S = getLoc();
  350. SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
  351. switch (getLexer().getKind()) {
  352. default:
  353. return MatchOperand_NoMatch;
  354. case AsmToken::Identifier:
  355. StringRef Name = getLexer().getTok().getIdentifier();
  356. unsigned RegNo = MatchRegisterName(Name);
  357. if (RegNo == 0)
  358. return MatchOperand_NoMatch;
  359. getLexer().Lex();
  360. Operands.push_back(BPFOperand::createReg(RegNo, S, E));
  361. }
  362. return MatchOperand_Success;
  363. }
  364. OperandMatchResultTy BPFAsmParser::parseImmediate(OperandVector &Operands) {
  365. switch (getLexer().getKind()) {
  366. default:
  367. return MatchOperand_NoMatch;
  368. case AsmToken::LParen:
  369. case AsmToken::Minus:
  370. case AsmToken::Plus:
  371. case AsmToken::Integer:
  372. case AsmToken::String:
  373. case AsmToken::Identifier:
  374. break;
  375. }
  376. const MCExpr *IdVal;
  377. SMLoc S = getLoc();
  378. if (getParser().parseExpression(IdVal))
  379. return MatchOperand_ParseFail;
  380. SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
  381. Operands.push_back(BPFOperand::createImm(IdVal, S, E));
  382. return MatchOperand_Success;
  383. }
  384. /// ParseInstruction - Parse an BPF instruction which is in BPF verifier
  385. /// format.
  386. bool BPFAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
  387. SMLoc NameLoc, OperandVector &Operands) {
  388. // The first operand could be either register or actually an operator.
  389. unsigned RegNo = MatchRegisterName(Name);
  390. if (RegNo != 0) {
  391. SMLoc E = SMLoc::getFromPointer(NameLoc.getPointer() - 1);
  392. Operands.push_back(BPFOperand::createReg(RegNo, NameLoc, E));
  393. } else if (BPFOperand::isValidIdAtStart (Name))
  394. Operands.push_back(BPFOperand::createToken(Name, NameLoc));
  395. else
  396. return Error(NameLoc, "invalid register/token name");
  397. while (!getLexer().is(AsmToken::EndOfStatement)) {
  398. // Attempt to parse token as operator
  399. if (parseOperandAsOperator(Operands) == MatchOperand_Success)
  400. continue;
  401. // Attempt to parse token as register
  402. if (parseRegister(Operands) == MatchOperand_Success)
  403. continue;
  404. // Attempt to parse token as an immediate
  405. if (parseImmediate(Operands) != MatchOperand_Success) {
  406. SMLoc Loc = getLexer().getLoc();
  407. return Error(Loc, "unexpected token");
  408. }
  409. }
  410. if (getLexer().isNot(AsmToken::EndOfStatement)) {
  411. SMLoc Loc = getLexer().getLoc();
  412. getParser().eatToEndOfStatement();
  413. return Error(Loc, "unexpected token");
  414. }
  415. // Consume the EndOfStatement.
  416. getParser().Lex();
  417. return false;
  418. }
  419. bool BPFAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
  420. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeBPFAsmParser() {
  421. RegisterMCAsmParser<BPFAsmParser> X(getTheBPFTarget());
  422. RegisterMCAsmParser<BPFAsmParser> Y(getTheBPFleTarget());
  423. RegisterMCAsmParser<BPFAsmParser> Z(getTheBPFbeTarget());
  424. }