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