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