1 //===-- RISCVAsmParser.cpp - Parse RISCV 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/RISCVBaseInfo.h" 11 #include "MCTargetDesc/RISCVMCTargetDesc.h" 12 #include "llvm/ADT/STLExtras.h" 13 #include "llvm/ADT/StringSwitch.h" 14 #include "llvm/MC/MCContext.h" 15 #include "llvm/MC/MCExpr.h" 16 #include "llvm/MC/MCInst.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/Support/Casting.h" 24 #include "llvm/Support/TargetRegistry.h" 25 26 using namespace llvm; 27 28 namespace { 29 struct RISCVOperand; 30 31 class RISCVAsmParser : public MCTargetAsmParser { 32 SMLoc getLoc() const { return getParser().getTok().getLoc(); } 33 34 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo, 35 int Lower, int Upper, Twine Msg); 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(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; 43 44 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 45 SMLoc NameLoc, OperandVector &Operands) override; 46 47 bool ParseDirective(AsmToken DirectiveID) override; 48 49 // Auto-generated instruction matching functions 50 #define GET_ASSEMBLER_HEADER 51 #include "RISCVGenAsmMatcher.inc" 52 53 OperandMatchResultTy parseImmediate(OperandVector &Operands); 54 OperandMatchResultTy parseRegister(OperandVector &Operands); 55 OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands); 56 57 bool parseOperand(OperandVector &Operands); 58 59 public: 60 enum RISCVMatchResultTy { 61 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, 62 #define GET_OPERAND_DIAGNOSTIC_TYPES 63 #include "RISCVGenAsmMatcher.inc" 64 #undef GET_OPERAND_DIAGNOSTIC_TYPES 65 }; 66 67 RISCVAsmParser(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 /// RISCVOperand - Instances of this class represent a parsed machine 75 /// instruction 76 struct RISCVOperand : 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 RISCVOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 100 101 public: 102 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() { 103 Kind = o.Kind; 104 StartLoc = o.StartLoc; 105 EndLoc = o.EndLoc; 106 switch (Kind) { 107 case Register: 108 Reg = o.Reg; 109 break; 110 case Immediate: 111 Imm = o.Imm; 112 break; 113 case Token: 114 Tok = o.Tok; 115 break; 116 } 117 } 118 119 bool isToken() const override { return Kind == Token; } 120 bool isReg() const override { return Kind == Register; } 121 bool isImm() const override { return Kind == Immediate; } 122 bool isMem() const override { return false; } 123 124 bool isConstantImm() const { 125 return isImm() && dyn_cast<MCConstantExpr>(getImm()); 126 } 127 128 int64_t getConstantImm() const { 129 const MCExpr *Val = getImm(); 130 return static_cast<const MCConstantExpr *>(Val)->getValue(); 131 } 132 133 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td 134 135 /// Return true if the operand is a valid for the fence instruction e.g. 136 /// ('iorw'). 137 bool isFenceArg() const { 138 if (!isImm()) 139 return false; 140 const MCExpr *Val = getImm(); 141 auto *SVal = dyn_cast<MCSymbolRefExpr>(Val); 142 if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None) 143 return false; 144 145 StringRef Str = SVal->getSymbol().getName(); 146 // Letters must be unique, taken from 'iorw', and in ascending order. This 147 // holds as long as each individual character is one of 'iorw' and is 148 // greater than the previous character. 149 char Prev = '\0'; 150 for (char c : Str) { 151 if (c != 'i' && c != 'o' && c != 'r' && c != 'w') 152 return false; 153 if (c <= Prev) 154 return false; 155 Prev = c; 156 } 157 return true; 158 } 159 160 bool isUImm5() const { 161 return (isConstantImm() && isUInt<5>(getConstantImm())); 162 } 163 164 bool isSImm12() const { 165 return (isConstantImm() && isInt<12>(getConstantImm())); 166 } 167 168 bool isUImm12() const { 169 return (isConstantImm() && isUInt<12>(getConstantImm())); 170 } 171 172 bool isSImm13Lsb0() const { 173 return (isConstantImm() && isShiftedInt<12, 1>(getConstantImm())); 174 } 175 176 bool isUImm20() const { 177 return (isConstantImm() && isUInt<20>(getConstantImm())); 178 } 179 180 bool isSImm21Lsb0() const { 181 return (isConstantImm() && isShiftedInt<20, 1>(getConstantImm())); 182 } 183 184 /// getStartLoc - Gets location of the first token of this operand 185 SMLoc getStartLoc() const override { return StartLoc; } 186 /// getEndLoc - Gets location of the last token of this operand 187 SMLoc getEndLoc() const override { return EndLoc; } 188 189 unsigned getReg() const override { 190 assert(Kind == Register && "Invalid type access!"); 191 return Reg.RegNum; 192 } 193 194 const MCExpr *getImm() const { 195 assert(Kind == Immediate && "Invalid type access!"); 196 return Imm.Val; 197 } 198 199 StringRef getToken() const { 200 assert(Kind == Token && "Invalid type access!"); 201 return Tok; 202 } 203 204 void print(raw_ostream &OS) const override { 205 switch (Kind) { 206 case Immediate: 207 OS << *getImm(); 208 break; 209 case Register: 210 OS << "<register x"; 211 OS << getReg() << ">"; 212 break; 213 case Token: 214 OS << "'" << getToken() << "'"; 215 break; 216 } 217 } 218 219 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) { 220 auto Op = make_unique<RISCVOperand>(Token); 221 Op->Tok = Str; 222 Op->StartLoc = S; 223 Op->EndLoc = S; 224 return Op; 225 } 226 227 static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S, 228 SMLoc E) { 229 auto Op = make_unique<RISCVOperand>(Register); 230 Op->Reg.RegNum = RegNo; 231 Op->StartLoc = S; 232 Op->EndLoc = E; 233 return Op; 234 } 235 236 static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S, 237 SMLoc E) { 238 auto Op = make_unique<RISCVOperand>(Immediate); 239 Op->Imm.Val = Val; 240 Op->StartLoc = S; 241 Op->EndLoc = E; 242 return Op; 243 } 244 245 void addExpr(MCInst &Inst, const MCExpr *Expr) const { 246 assert(Expr && "Expr shouldn't be null!"); 247 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) 248 Inst.addOperand(MCOperand::createImm(CE->getValue())); 249 else 250 Inst.addOperand(MCOperand::createExpr(Expr)); 251 } 252 253 // Used by the TableGen Code 254 void addRegOperands(MCInst &Inst, unsigned N) const { 255 assert(N == 1 && "Invalid number of operands!"); 256 Inst.addOperand(MCOperand::createReg(getReg())); 257 } 258 259 void addImmOperands(MCInst &Inst, unsigned N) const { 260 assert(N == 1 && "Invalid number of operands!"); 261 addExpr(Inst, getImm()); 262 } 263 264 void addFenceArgOperands(MCInst &Inst, unsigned N) const { 265 assert(N == 1 && "Invalid number of operands!"); 266 // isFenceArg has validated the operand, meaning this cast is safe 267 auto SE = cast<MCSymbolRefExpr>(getImm()); 268 269 unsigned Imm = 0; 270 for (char c : SE->getSymbol().getName()) { 271 switch (c) { 272 default: llvm_unreachable("FenceArg must contain only [iorw]"); 273 case 'i': Imm |= RISCVFenceField::I; break; 274 case 'o': Imm |= RISCVFenceField::O; break; 275 case 'r': Imm |= RISCVFenceField::R; break; 276 case 'w': Imm |= RISCVFenceField::W; break; 277 } 278 } 279 Inst.addOperand(MCOperand::createImm(Imm)); 280 } 281 }; 282 } // end anonymous namespace. 283 284 #define GET_REGISTER_MATCHER 285 #define GET_MATCHER_IMPLEMENTATION 286 #include "RISCVGenAsmMatcher.inc" 287 288 bool RISCVAsmParser::generateImmOutOfRangeError( 289 OperandVector &Operands, uint64_t ErrorInfo, int Lower, int Upper, 290 Twine Msg = "immediate must be an integer in the range") { 291 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 292 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); 293 } 294 295 bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 296 OperandVector &Operands, 297 MCStreamer &Out, 298 uint64_t &ErrorInfo, 299 bool MatchingInlineAsm) { 300 MCInst Inst; 301 302 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) { 303 default: 304 break; 305 case Match_Success: 306 Inst.setLoc(IDLoc); 307 Out.EmitInstruction(Inst, getSTI()); 308 return false; 309 case Match_MissingFeature: 310 return Error(IDLoc, "instruction use requires an option to be enabled"); 311 case Match_MnemonicFail: 312 return Error(IDLoc, "unrecognized instruction mnemonic"); 313 case Match_InvalidOperand: { 314 SMLoc ErrorLoc = IDLoc; 315 if (ErrorInfo != ~0U) { 316 if (ErrorInfo >= Operands.size()) 317 return Error(ErrorLoc, "too few operands for instruction"); 318 319 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 320 if (ErrorLoc == SMLoc()) 321 ErrorLoc = IDLoc; 322 } 323 return Error(ErrorLoc, "invalid operand for instruction"); 324 } 325 case Match_InvalidUImm5: 326 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); 327 case Match_InvalidSImm12: 328 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 11), 329 (1 << 11) - 1); 330 case Match_InvalidUImm12: 331 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1); 332 case Match_InvalidSImm13Lsb0: 333 return generateImmOutOfRangeError( 334 Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2, 335 "immediate must be a multiple of 2 bytes in the range"); 336 case Match_InvalidUImm20: 337 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1); 338 case Match_InvalidSImm21Lsb0: 339 return generateImmOutOfRangeError( 340 Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2, 341 "immediate must be a multiple of 2 bytes in the range"); 342 case Match_InvalidFenceArg: { 343 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 344 return Error( 345 ErrorLoc, 346 "operand must be formed of letters selected in-order from 'iorw'"); 347 } 348 } 349 350 llvm_unreachable("Unknown match type detected!"); 351 } 352 353 bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, 354 SMLoc &EndLoc) { 355 const AsmToken &Tok = getParser().getTok(); 356 StartLoc = Tok.getLoc(); 357 EndLoc = Tok.getEndLoc(); 358 RegNo = 0; 359 StringRef Name = getLexer().getTok().getIdentifier(); 360 361 if (!MatchRegisterName(Name) || !MatchRegisterAltName(Name)) { 362 getParser().Lex(); // Eat identifier token. 363 return false; 364 } 365 366 return Error(StartLoc, "invalid register name"); 367 } 368 369 OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands) { 370 SMLoc S = getLoc(); 371 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 372 373 switch (getLexer().getKind()) { 374 default: 375 return MatchOperand_NoMatch; 376 case AsmToken::Identifier: 377 StringRef Name = getLexer().getTok().getIdentifier(); 378 unsigned RegNo = MatchRegisterName(Name); 379 if (RegNo == 0) { 380 RegNo = MatchRegisterAltName(Name); 381 if (RegNo == 0) 382 return MatchOperand_NoMatch; 383 } 384 getLexer().Lex(); 385 Operands.push_back(RISCVOperand::createReg(RegNo, S, E)); 386 } 387 return MatchOperand_Success; 388 } 389 390 OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) { 391 SMLoc S = getLoc(); 392 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 393 const MCExpr *Res; 394 395 switch (getLexer().getKind()) { 396 default: 397 return MatchOperand_NoMatch; 398 case AsmToken::LParen: 399 case AsmToken::Minus: 400 case AsmToken::Plus: 401 case AsmToken::Integer: 402 case AsmToken::String: 403 if (getParser().parseExpression(Res)) 404 return MatchOperand_ParseFail; 405 break; 406 case AsmToken::Identifier: { 407 StringRef Identifier; 408 if (getParser().parseIdentifier(Identifier)) 409 return MatchOperand_ParseFail; 410 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 411 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 412 break; 413 } 414 } 415 416 Operands.push_back(RISCVOperand::createImm(Res, S, E)); 417 return MatchOperand_Success; 418 } 419 420 OperandMatchResultTy 421 RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) { 422 if (getLexer().isNot(AsmToken::LParen)) { 423 Error(getLoc(), "expected '('"); 424 return MatchOperand_ParseFail; 425 } 426 427 getParser().Lex(); // Eat '(' 428 Operands.push_back(RISCVOperand::createToken("(", getLoc())); 429 430 if (parseRegister(Operands) != MatchOperand_Success) { 431 Error(getLoc(), "expected register"); 432 return MatchOperand_ParseFail; 433 } 434 435 if (getLexer().isNot(AsmToken::RParen)) { 436 Error(getLoc(), "expected ')'"); 437 return MatchOperand_ParseFail; 438 } 439 440 getParser().Lex(); // Eat ')' 441 Operands.push_back(RISCVOperand::createToken(")", getLoc())); 442 443 return MatchOperand_Success; 444 } 445 446 /// Looks at a token type and creates the relevant operand 447 /// from this information, adding to Operands. 448 /// If operand was parsed, returns false, else true. 449 bool RISCVAsmParser::parseOperand(OperandVector &Operands) { 450 // Attempt to parse token as register 451 if (parseRegister(Operands) == MatchOperand_Success) 452 return false; 453 454 // Attempt to parse token as an immediate 455 if (parseImmediate(Operands) == MatchOperand_Success) { 456 // Parse memory base register if present 457 if (getLexer().is(AsmToken::LParen)) 458 return parseMemOpBaseReg(Operands) != MatchOperand_Success; 459 return false; 460 } 461 462 // Finally we have exhausted all options and must declare defeat. 463 Error(getLoc(), "unknown operand"); 464 return true; 465 } 466 467 bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info, 468 StringRef Name, SMLoc NameLoc, 469 OperandVector &Operands) { 470 // First operand is token for instruction 471 Operands.push_back(RISCVOperand::createToken(Name, NameLoc)); 472 473 // If there are no more operands, then finish 474 if (getLexer().is(AsmToken::EndOfStatement)) 475 return false; 476 477 // Parse first operand 478 if (parseOperand(Operands)) 479 return true; 480 481 // Parse until end of statement, consuming commas between operands 482 while (getLexer().is(AsmToken::Comma)) { 483 // Consume comma token 484 getLexer().Lex(); 485 486 // Parse next operand 487 if (parseOperand(Operands)) 488 return true; 489 } 490 491 if (getLexer().isNot(AsmToken::EndOfStatement)) { 492 SMLoc Loc = getLexer().getLoc(); 493 getParser().eatToEndOfStatement(); 494 return Error(Loc, "unexpected token"); 495 } 496 497 getParser().Lex(); // Consume the EndOfStatement. 498 return false; 499 } 500 501 bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) { return true; } 502 503 extern "C" void LLVMInitializeRISCVAsmParser() { 504 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target()); 505 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target()); 506 } 507