BPFAsmParser.cpp 15 KB

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