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