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