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