1 //===-- RISCVAsmParser.cpp - Parse RISCV 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/RISCVAsmBackend.h" 10 #include "MCTargetDesc/RISCVMCExpr.h" 11 #include "MCTargetDesc/RISCVMCTargetDesc.h" 12 #include "MCTargetDesc/RISCVTargetStreamer.h" 13 #include "TargetInfo/RISCVTargetInfo.h" 14 #include "Utils/RISCVBaseInfo.h" 15 #include "Utils/RISCVMatInt.h" 16 #include "llvm/ADT/STLExtras.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/StringSwitch.h" 19 #include "llvm/CodeGen/Register.h" 20 #include "llvm/MC/MCAssembler.h" 21 #include "llvm/MC/MCContext.h" 22 #include "llvm/MC/MCExpr.h" 23 #include "llvm/MC/MCInst.h" 24 #include "llvm/MC/MCInstBuilder.h" 25 #include "llvm/MC/MCObjectFileInfo.h" 26 #include "llvm/MC/MCParser/MCAsmLexer.h" 27 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 28 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 29 #include "llvm/MC/MCRegisterInfo.h" 30 #include "llvm/MC/MCStreamer.h" 31 #include "llvm/MC/MCSubtargetInfo.h" 32 #include "llvm/Support/Casting.h" 33 #include "llvm/Support/MathExtras.h" 34 #include "llvm/Support/TargetRegistry.h" 35 36 #include <limits> 37 38 using namespace llvm; 39 40 // Include the auto-generated portion of the compress emitter. 41 #define GEN_COMPRESS_INSTR 42 #include "RISCVGenCompressInstEmitter.inc" 43 44 namespace { 45 struct RISCVOperand; 46 47 class RISCVAsmParser : public MCTargetAsmParser { 48 SmallVector<FeatureBitset, 4> FeatureBitStack; 49 50 SMLoc getLoc() const { return getParser().getTok().getLoc(); } 51 bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); } 52 bool isRV32E() const { return getSTI().hasFeature(RISCV::FeatureRV32E); } 53 54 RISCVTargetStreamer &getTargetStreamer() { 55 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); 56 return static_cast<RISCVTargetStreamer &>(TS); 57 } 58 59 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 60 unsigned Kind) override; 61 62 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo, 63 int64_t Lower, int64_t Upper, Twine Msg); 64 65 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 66 OperandVector &Operands, MCStreamer &Out, 67 uint64_t &ErrorInfo, 68 bool MatchingInlineAsm) override; 69 70 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; 71 72 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 73 SMLoc NameLoc, OperandVector &Operands) override; 74 75 bool ParseDirective(AsmToken DirectiveID) override; 76 77 // Helper to actually emit an instruction to the MCStreamer. Also, when 78 // possible, compression of the instruction is performed. 79 void emitToStreamer(MCStreamer &S, const MCInst &Inst); 80 81 // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that 82 // synthesize the desired immedate value into the destination register. 83 void emitLoadImm(Register DestReg, int64_t Value, MCStreamer &Out); 84 85 // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement 86 // helpers such as emitLoadLocalAddress and emitLoadAddress. 87 void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg, 88 const MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi, 89 unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out); 90 91 // Helper to emit pseudo instruction "lla" used in PC-rel addressing. 92 void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 93 94 // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing. 95 void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 96 97 // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS 98 // addressing. 99 void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 100 101 // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS 102 // addressing. 103 void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 104 105 // Helper to emit pseudo load/store instruction with a symbol. 106 void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, 107 MCStreamer &Out, bool HasTmpReg); 108 109 // Checks that a PseudoAddTPRel is using x4/tp in its second input operand. 110 // Enforcing this using a restricted register class for the second input 111 // operand of PseudoAddTPRel results in a poor diagnostic due to the fact 112 // 'add' is an overloaded mnemonic. 113 bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands); 114 115 /// Helper for processing MC instructions that have been successfully matched 116 /// by MatchAndEmitInstruction. Modifications to the emitted instructions, 117 /// like the expansion of pseudo instructions (e.g., "li"), can be performed 118 /// in this method. 119 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands, 120 MCStreamer &Out); 121 122 // Auto-generated instruction matching functions 123 #define GET_ASSEMBLER_HEADER 124 #include "RISCVGenAsmMatcher.inc" 125 126 OperandMatchResultTy parseCSRSystemRegister(OperandVector &Operands); 127 OperandMatchResultTy parseImmediate(OperandVector &Operands); 128 OperandMatchResultTy parseRegister(OperandVector &Operands, 129 bool AllowParens = false); 130 OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands); 131 OperandMatchResultTy parseAtomicMemOp(OperandVector &Operands); 132 OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands); 133 OperandMatchResultTy parseBareSymbol(OperandVector &Operands); 134 OperandMatchResultTy parseCallSymbol(OperandVector &Operands); 135 OperandMatchResultTy parseJALOffset(OperandVector &Operands); 136 137 bool parseOperand(OperandVector &Operands, StringRef Mnemonic); 138 139 bool parseDirectiveOption(); 140 141 void setFeatureBits(uint64_t Feature, StringRef FeatureString) { 142 if (!(getSTI().getFeatureBits()[Feature])) { 143 MCSubtargetInfo &STI = copySTI(); 144 setAvailableFeatures( 145 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); 146 } 147 } 148 149 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) { 150 if (getSTI().getFeatureBits()[Feature]) { 151 MCSubtargetInfo &STI = copySTI(); 152 setAvailableFeatures( 153 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); 154 } 155 } 156 157 void pushFeatureBits() { 158 FeatureBitStack.push_back(getSTI().getFeatureBits()); 159 } 160 161 bool popFeatureBits() { 162 if (FeatureBitStack.empty()) 163 return true; 164 165 FeatureBitset FeatureBits = FeatureBitStack.pop_back_val(); 166 copySTI().setFeatureBits(FeatureBits); 167 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits)); 168 169 return false; 170 } 171 public: 172 enum RISCVMatchResultTy { 173 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, 174 #define GET_OPERAND_DIAGNOSTIC_TYPES 175 #include "RISCVGenAsmMatcher.inc" 176 #undef GET_OPERAND_DIAGNOSTIC_TYPES 177 }; 178 179 static bool classifySymbolRef(const MCExpr *Expr, 180 RISCVMCExpr::VariantKind &Kind, 181 int64_t &Addend); 182 183 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 184 const MCInstrInfo &MII, const MCTargetOptions &Options) 185 : MCTargetAsmParser(Options, STI, MII) { 186 Parser.addAliasForDirective(".half", ".2byte"); 187 Parser.addAliasForDirective(".hword", ".2byte"); 188 Parser.addAliasForDirective(".word", ".4byte"); 189 Parser.addAliasForDirective(".dword", ".8byte"); 190 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 191 } 192 }; 193 194 /// RISCVOperand - Instances of this class represent a parsed machine 195 /// instruction 196 struct RISCVOperand : public MCParsedAsmOperand { 197 198 enum class KindTy { 199 Token, 200 Register, 201 Immediate, 202 SystemRegister 203 } Kind; 204 205 bool IsRV64; 206 207 struct RegOp { 208 Register RegNum; 209 }; 210 211 struct ImmOp { 212 const MCExpr *Val; 213 }; 214 215 struct SysRegOp { 216 const char *Data; 217 unsigned Length; 218 unsigned Encoding; 219 // FIXME: Add the Encoding parsed fields as needed for checks, 220 // e.g.: read/write or user/supervisor/machine privileges. 221 }; 222 223 SMLoc StartLoc, EndLoc; 224 union { 225 StringRef Tok; 226 RegOp Reg; 227 ImmOp Imm; 228 struct SysRegOp SysReg; 229 }; 230 231 RISCVOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} 232 233 public: 234 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() { 235 Kind = o.Kind; 236 IsRV64 = o.IsRV64; 237 StartLoc = o.StartLoc; 238 EndLoc = o.EndLoc; 239 switch (Kind) { 240 case KindTy::Register: 241 Reg = o.Reg; 242 break; 243 case KindTy::Immediate: 244 Imm = o.Imm; 245 break; 246 case KindTy::Token: 247 Tok = o.Tok; 248 break; 249 case KindTy::SystemRegister: 250 SysReg = o.SysReg; 251 break; 252 } 253 } 254 255 bool isToken() const override { return Kind == KindTy::Token; } 256 bool isReg() const override { return Kind == KindTy::Register; } 257 bool isImm() const override { return Kind == KindTy::Immediate; } 258 bool isMem() const override { return false; } 259 bool isSystemRegister() const { return Kind == KindTy::SystemRegister; } 260 261 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm, 262 RISCVMCExpr::VariantKind &VK) { 263 if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) { 264 VK = RE->getKind(); 265 return RE->evaluateAsConstant(Imm); 266 } 267 268 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) { 269 VK = RISCVMCExpr::VK_RISCV_None; 270 Imm = CE->getValue(); 271 return true; 272 } 273 274 return false; 275 } 276 277 // True if operand is a symbol with no modifiers, or a constant with no 278 // modifiers and isShiftedInt<N-1, 1>(Op). 279 template <int N> bool isBareSimmNLsb0() const { 280 int64_t Imm; 281 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 282 if (!isImm()) 283 return false; 284 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 285 bool IsValid; 286 if (!IsConstantImm) 287 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm); 288 else 289 IsValid = isShiftedInt<N - 1, 1>(Imm); 290 return IsValid && VK == RISCVMCExpr::VK_RISCV_None; 291 } 292 293 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td 294 295 bool isBareSymbol() const { 296 int64_t Imm; 297 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 298 // Must be of 'immediate' type but not a constant. 299 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) 300 return false; 301 return RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm) && 302 VK == RISCVMCExpr::VK_RISCV_None; 303 } 304 305 bool isCallSymbol() const { 306 int64_t Imm; 307 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 308 // Must be of 'immediate' type but not a constant. 309 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) 310 return false; 311 return RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm) && 312 (VK == RISCVMCExpr::VK_RISCV_CALL || 313 VK == RISCVMCExpr::VK_RISCV_CALL_PLT); 314 } 315 316 bool isTPRelAddSymbol() const { 317 int64_t Imm; 318 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 319 // Must be of 'immediate' type but not a constant. 320 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) 321 return false; 322 return RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm) && 323 VK == RISCVMCExpr::VK_RISCV_TPREL_ADD; 324 } 325 326 bool isCSRSystemRegister() const { return isSystemRegister(); } 327 328 /// Return true if the operand is a valid for the fence instruction e.g. 329 /// ('iorw'). 330 bool isFenceArg() const { 331 if (!isImm()) 332 return false; 333 const MCExpr *Val = getImm(); 334 auto *SVal = dyn_cast<MCSymbolRefExpr>(Val); 335 if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None) 336 return false; 337 338 StringRef Str = SVal->getSymbol().getName(); 339 // Letters must be unique, taken from 'iorw', and in ascending order. This 340 // holds as long as each individual character is one of 'iorw' and is 341 // greater than the previous character. 342 char Prev = '\0'; 343 for (char c : Str) { 344 if (c != 'i' && c != 'o' && c != 'r' && c != 'w') 345 return false; 346 if (c <= Prev) 347 return false; 348 Prev = c; 349 } 350 return true; 351 } 352 353 /// Return true if the operand is a valid floating point rounding mode. 354 bool isFRMArg() const { 355 if (!isImm()) 356 return false; 357 const MCExpr *Val = getImm(); 358 auto *SVal = dyn_cast<MCSymbolRefExpr>(Val); 359 if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None) 360 return false; 361 362 StringRef Str = SVal->getSymbol().getName(); 363 364 return RISCVFPRndMode::stringToRoundingMode(Str) != RISCVFPRndMode::Invalid; 365 } 366 367 bool isImmXLenLI() const { 368 int64_t Imm; 369 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 370 if (!isImm()) 371 return false; 372 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 373 if (VK == RISCVMCExpr::VK_RISCV_LO || VK == RISCVMCExpr::VK_RISCV_PCREL_LO) 374 return true; 375 // Given only Imm, ensuring that the actually specified constant is either 376 // a signed or unsigned 64-bit number is unfortunately impossible. 377 bool IsInRange = isRV64() ? true : isInt<32>(Imm) || isUInt<32>(Imm); 378 return IsConstantImm && IsInRange && VK == RISCVMCExpr::VK_RISCV_None; 379 } 380 381 bool isUImmLog2XLen() const { 382 int64_t Imm; 383 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 384 if (!isImm()) 385 return false; 386 if (!evaluateConstantImm(getImm(), Imm, VK) || 387 VK != RISCVMCExpr::VK_RISCV_None) 388 return false; 389 return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm); 390 } 391 392 bool isUImmLog2XLenNonZero() const { 393 int64_t Imm; 394 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 395 if (!isImm()) 396 return false; 397 if (!evaluateConstantImm(getImm(), Imm, VK) || 398 VK != RISCVMCExpr::VK_RISCV_None) 399 return false; 400 if (Imm == 0) 401 return false; 402 return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm); 403 } 404 405 bool isUImm5() const { 406 int64_t Imm; 407 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 408 if (!isImm()) 409 return false; 410 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 411 return IsConstantImm && isUInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None; 412 } 413 414 bool isUImm5NonZero() const { 415 int64_t Imm; 416 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 417 if (!isImm()) 418 return false; 419 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 420 return IsConstantImm && isUInt<5>(Imm) && (Imm != 0) && 421 VK == RISCVMCExpr::VK_RISCV_None; 422 } 423 424 bool isSImm6() const { 425 if (!isImm()) 426 return false; 427 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 428 int64_t Imm; 429 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 430 return IsConstantImm && isInt<6>(Imm) && 431 VK == RISCVMCExpr::VK_RISCV_None; 432 } 433 434 bool isSImm6NonZero() const { 435 if (!isImm()) 436 return false; 437 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 438 int64_t Imm; 439 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 440 return IsConstantImm && isInt<6>(Imm) && (Imm != 0) && 441 VK == RISCVMCExpr::VK_RISCV_None; 442 } 443 444 bool isCLUIImm() const { 445 if (!isImm()) 446 return false; 447 int64_t Imm; 448 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 449 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 450 return IsConstantImm && (Imm != 0) && 451 (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) && 452 VK == RISCVMCExpr::VK_RISCV_None; 453 } 454 455 bool isUImm7Lsb00() const { 456 if (!isImm()) 457 return false; 458 int64_t Imm; 459 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 460 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 461 return IsConstantImm && isShiftedUInt<5, 2>(Imm) && 462 VK == RISCVMCExpr::VK_RISCV_None; 463 } 464 465 bool isUImm8Lsb00() const { 466 if (!isImm()) 467 return false; 468 int64_t Imm; 469 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 470 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 471 return IsConstantImm && isShiftedUInt<6, 2>(Imm) && 472 VK == RISCVMCExpr::VK_RISCV_None; 473 } 474 475 bool isUImm8Lsb000() const { 476 if (!isImm()) 477 return false; 478 int64_t Imm; 479 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 480 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 481 return IsConstantImm && isShiftedUInt<5, 3>(Imm) && 482 VK == RISCVMCExpr::VK_RISCV_None; 483 } 484 485 bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); } 486 487 bool isUImm9Lsb000() const { 488 if (!isImm()) 489 return false; 490 int64_t Imm; 491 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 492 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 493 return IsConstantImm && isShiftedUInt<6, 3>(Imm) && 494 VK == RISCVMCExpr::VK_RISCV_None; 495 } 496 497 bool isUImm10Lsb00NonZero() const { 498 if (!isImm()) 499 return false; 500 int64_t Imm; 501 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 502 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 503 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) && 504 VK == RISCVMCExpr::VK_RISCV_None; 505 } 506 507 bool isSImm12() const { 508 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 509 int64_t Imm; 510 bool IsValid; 511 if (!isImm()) 512 return false; 513 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 514 if (!IsConstantImm) 515 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm); 516 else 517 IsValid = isInt<12>(Imm); 518 return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) || 519 VK == RISCVMCExpr::VK_RISCV_LO || 520 VK == RISCVMCExpr::VK_RISCV_PCREL_LO || 521 VK == RISCVMCExpr::VK_RISCV_TPREL_LO); 522 } 523 524 bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); } 525 526 bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); } 527 528 bool isSImm10Lsb0000NonZero() const { 529 if (!isImm()) 530 return false; 531 int64_t Imm; 532 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 533 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 534 return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) && 535 VK == RISCVMCExpr::VK_RISCV_None; 536 } 537 538 bool isUImm20LUI() const { 539 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 540 int64_t Imm; 541 bool IsValid; 542 if (!isImm()) 543 return false; 544 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 545 if (!IsConstantImm) { 546 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm); 547 return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI || 548 VK == RISCVMCExpr::VK_RISCV_TPREL_HI); 549 } else { 550 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None || 551 VK == RISCVMCExpr::VK_RISCV_HI || 552 VK == RISCVMCExpr::VK_RISCV_TPREL_HI); 553 } 554 } 555 556 bool isUImm20AUIPC() const { 557 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 558 int64_t Imm; 559 bool IsValid; 560 if (!isImm()) 561 return false; 562 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 563 if (!IsConstantImm) { 564 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm); 565 return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI || 566 VK == RISCVMCExpr::VK_RISCV_GOT_HI || 567 VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI || 568 VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI); 569 } else { 570 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None || 571 VK == RISCVMCExpr::VK_RISCV_PCREL_HI || 572 VK == RISCVMCExpr::VK_RISCV_GOT_HI || 573 VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI || 574 VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI); 575 } 576 } 577 578 bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); } 579 580 bool isImmZero() const { 581 if (!isImm()) 582 return false; 583 int64_t Imm; 584 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 585 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 586 return IsConstantImm && (Imm == 0) && VK == RISCVMCExpr::VK_RISCV_None; 587 } 588 589 /// getStartLoc - Gets location of the first token of this operand 590 SMLoc getStartLoc() const override { return StartLoc; } 591 /// getEndLoc - Gets location of the last token of this operand 592 SMLoc getEndLoc() const override { return EndLoc; } 593 /// True if this operand is for an RV64 instruction 594 bool isRV64() const { return IsRV64; } 595 596 unsigned getReg() const override { 597 assert(Kind == KindTy::Register && "Invalid type access!"); 598 return Reg.RegNum.id(); 599 } 600 601 StringRef getSysReg() const { 602 assert(Kind == KindTy::SystemRegister && "Invalid access!"); 603 return StringRef(SysReg.Data, SysReg.Length); 604 } 605 606 const MCExpr *getImm() const { 607 assert(Kind == KindTy::Immediate && "Invalid type access!"); 608 return Imm.Val; 609 } 610 611 StringRef getToken() const { 612 assert(Kind == KindTy::Token && "Invalid type access!"); 613 return Tok; 614 } 615 616 void print(raw_ostream &OS) const override { 617 switch (Kind) { 618 case KindTy::Immediate: 619 OS << *getImm(); 620 break; 621 case KindTy::Register: 622 OS << "<register x"; 623 OS << getReg() << ">"; 624 break; 625 case KindTy::Token: 626 OS << "'" << getToken() << "'"; 627 break; 628 case KindTy::SystemRegister: 629 OS << "<sysreg: " << getSysReg() << '>'; 630 break; 631 } 632 } 633 634 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S, 635 bool IsRV64) { 636 auto Op = std::make_unique<RISCVOperand>(KindTy::Token); 637 Op->Tok = Str; 638 Op->StartLoc = S; 639 Op->EndLoc = S; 640 Op->IsRV64 = IsRV64; 641 return Op; 642 } 643 644 static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S, 645 SMLoc E, bool IsRV64) { 646 auto Op = std::make_unique<RISCVOperand>(KindTy::Register); 647 Op->Reg.RegNum = RegNo; 648 Op->StartLoc = S; 649 Op->EndLoc = E; 650 Op->IsRV64 = IsRV64; 651 return Op; 652 } 653 654 static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S, 655 SMLoc E, bool IsRV64) { 656 auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate); 657 Op->Imm.Val = Val; 658 Op->StartLoc = S; 659 Op->EndLoc = E; 660 Op->IsRV64 = IsRV64; 661 return Op; 662 } 663 664 static std::unique_ptr<RISCVOperand> 665 createSysReg(StringRef Str, SMLoc S, unsigned Encoding, bool IsRV64) { 666 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister); 667 Op->SysReg.Data = Str.data(); 668 Op->SysReg.Length = Str.size(); 669 Op->SysReg.Encoding = Encoding; 670 Op->StartLoc = S; 671 Op->IsRV64 = IsRV64; 672 return Op; 673 } 674 675 void addExpr(MCInst &Inst, const MCExpr *Expr) const { 676 assert(Expr && "Expr shouldn't be null!"); 677 int64_t Imm = 0; 678 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 679 bool IsConstant = evaluateConstantImm(Expr, Imm, VK); 680 681 if (IsConstant) 682 Inst.addOperand(MCOperand::createImm(Imm)); 683 else 684 Inst.addOperand(MCOperand::createExpr(Expr)); 685 } 686 687 // Used by the TableGen Code 688 void addRegOperands(MCInst &Inst, unsigned N) const { 689 assert(N == 1 && "Invalid number of operands!"); 690 Inst.addOperand(MCOperand::createReg(getReg())); 691 } 692 693 void addImmOperands(MCInst &Inst, unsigned N) const { 694 assert(N == 1 && "Invalid number of operands!"); 695 addExpr(Inst, getImm()); 696 } 697 698 void addFenceArgOperands(MCInst &Inst, unsigned N) const { 699 assert(N == 1 && "Invalid number of operands!"); 700 // isFenceArg has validated the operand, meaning this cast is safe 701 auto SE = cast<MCSymbolRefExpr>(getImm()); 702 703 unsigned Imm = 0; 704 for (char c : SE->getSymbol().getName()) { 705 switch (c) { 706 default: 707 llvm_unreachable("FenceArg must contain only [iorw]"); 708 case 'i': Imm |= RISCVFenceField::I; break; 709 case 'o': Imm |= RISCVFenceField::O; break; 710 case 'r': Imm |= RISCVFenceField::R; break; 711 case 'w': Imm |= RISCVFenceField::W; break; 712 } 713 } 714 Inst.addOperand(MCOperand::createImm(Imm)); 715 } 716 717 void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const { 718 assert(N == 1 && "Invalid number of operands!"); 719 Inst.addOperand(MCOperand::createImm(SysReg.Encoding)); 720 } 721 722 // Returns the rounding mode represented by this RISCVOperand. Should only 723 // be called after checking isFRMArg. 724 RISCVFPRndMode::RoundingMode getRoundingMode() const { 725 // isFRMArg has validated the operand, meaning this cast is safe. 726 auto SE = cast<MCSymbolRefExpr>(getImm()); 727 RISCVFPRndMode::RoundingMode FRM = 728 RISCVFPRndMode::stringToRoundingMode(SE->getSymbol().getName()); 729 assert(FRM != RISCVFPRndMode::Invalid && "Invalid rounding mode"); 730 return FRM; 731 } 732 733 void addFRMArgOperands(MCInst &Inst, unsigned N) const { 734 assert(N == 1 && "Invalid number of operands!"); 735 Inst.addOperand(MCOperand::createImm(getRoundingMode())); 736 } 737 }; 738 } // end anonymous namespace. 739 740 #define GET_REGISTER_MATCHER 741 #define GET_MATCHER_IMPLEMENTATION 742 #include "RISCVGenAsmMatcher.inc" 743 744 // Return the matching FPR64 register for the given FPR32. 745 // FIXME: Ideally this function could be removed in favour of using 746 // information from TableGen. 747 static Register convertFPR32ToFPR64(Register Reg) { 748 switch (Reg) { 749 default: 750 llvm_unreachable("Not a recognised FPR32 register"); 751 case RISCV::F0_32: return RISCV::F0_64; 752 case RISCV::F1_32: return RISCV::F1_64; 753 case RISCV::F2_32: return RISCV::F2_64; 754 case RISCV::F3_32: return RISCV::F3_64; 755 case RISCV::F4_32: return RISCV::F4_64; 756 case RISCV::F5_32: return RISCV::F5_64; 757 case RISCV::F6_32: return RISCV::F6_64; 758 case RISCV::F7_32: return RISCV::F7_64; 759 case RISCV::F8_32: return RISCV::F8_64; 760 case RISCV::F9_32: return RISCV::F9_64; 761 case RISCV::F10_32: return RISCV::F10_64; 762 case RISCV::F11_32: return RISCV::F11_64; 763 case RISCV::F12_32: return RISCV::F12_64; 764 case RISCV::F13_32: return RISCV::F13_64; 765 case RISCV::F14_32: return RISCV::F14_64; 766 case RISCV::F15_32: return RISCV::F15_64; 767 case RISCV::F16_32: return RISCV::F16_64; 768 case RISCV::F17_32: return RISCV::F17_64; 769 case RISCV::F18_32: return RISCV::F18_64; 770 case RISCV::F19_32: return RISCV::F19_64; 771 case RISCV::F20_32: return RISCV::F20_64; 772 case RISCV::F21_32: return RISCV::F21_64; 773 case RISCV::F22_32: return RISCV::F22_64; 774 case RISCV::F23_32: return RISCV::F23_64; 775 case RISCV::F24_32: return RISCV::F24_64; 776 case RISCV::F25_32: return RISCV::F25_64; 777 case RISCV::F26_32: return RISCV::F26_64; 778 case RISCV::F27_32: return RISCV::F27_64; 779 case RISCV::F28_32: return RISCV::F28_64; 780 case RISCV::F29_32: return RISCV::F29_64; 781 case RISCV::F30_32: return RISCV::F30_64; 782 case RISCV::F31_32: return RISCV::F31_64; 783 } 784 } 785 786 unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, 787 unsigned Kind) { 788 RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp); 789 if (!Op.isReg()) 790 return Match_InvalidOperand; 791 792 Register Reg = Op.getReg(); 793 bool IsRegFPR32 = 794 RISCVMCRegisterClasses[RISCV::FPR32RegClassID].contains(Reg); 795 bool IsRegFPR32C = 796 RISCVMCRegisterClasses[RISCV::FPR32CRegClassID].contains(Reg); 797 798 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the 799 // register from FPR32 to FPR64 or FPR32C to FPR64C if necessary. 800 if ((IsRegFPR32 && Kind == MCK_FPR64) || 801 (IsRegFPR32C && Kind == MCK_FPR64C)) { 802 Op.Reg.RegNum = convertFPR32ToFPR64(Reg); 803 return Match_Success; 804 } 805 return Match_InvalidOperand; 806 } 807 808 bool RISCVAsmParser::generateImmOutOfRangeError( 809 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper, 810 Twine Msg = "immediate must be an integer in the range") { 811 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 812 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); 813 } 814 815 bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 816 OperandVector &Operands, 817 MCStreamer &Out, 818 uint64_t &ErrorInfo, 819 bool MatchingInlineAsm) { 820 MCInst Inst; 821 822 auto Result = 823 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); 824 switch (Result) { 825 default: 826 break; 827 case Match_Success: 828 return processInstruction(Inst, IDLoc, Operands, Out); 829 case Match_MissingFeature: 830 return Error(IDLoc, "instruction use requires an option to be enabled"); 831 case Match_MnemonicFail: 832 return Error(IDLoc, "unrecognized instruction mnemonic"); 833 case Match_InvalidOperand: { 834 SMLoc ErrorLoc = IDLoc; 835 if (ErrorInfo != ~0U) { 836 if (ErrorInfo >= Operands.size()) 837 return Error(ErrorLoc, "too few operands for instruction"); 838 839 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 840 if (ErrorLoc == SMLoc()) 841 ErrorLoc = IDLoc; 842 } 843 return Error(ErrorLoc, "invalid operand for instruction"); 844 } 845 } 846 847 // Handle the case when the error message is of specific type 848 // other than the generic Match_InvalidOperand, and the 849 // corresponding operand is missing. 850 if (Result > FIRST_TARGET_MATCH_RESULT_TY) { 851 SMLoc ErrorLoc = IDLoc; 852 if (ErrorInfo != ~0U && ErrorInfo >= Operands.size()) 853 return Error(ErrorLoc, "too few operands for instruction"); 854 } 855 856 switch(Result) { 857 default: 858 break; 859 case Match_InvalidImmXLenLI: 860 if (isRV64()) { 861 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 862 return Error(ErrorLoc, "operand must be a constant 64-bit integer"); 863 } 864 return generateImmOutOfRangeError(Operands, ErrorInfo, 865 std::numeric_limits<int32_t>::min(), 866 std::numeric_limits<uint32_t>::max()); 867 case Match_InvalidImmZero: { 868 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 869 return Error(ErrorLoc, "immediate must be zero"); 870 } 871 case Match_InvalidUImmLog2XLen: 872 if (isRV64()) 873 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1); 874 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); 875 case Match_InvalidUImmLog2XLenNonZero: 876 if (isRV64()) 877 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1); 878 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1); 879 case Match_InvalidUImm5: 880 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); 881 case Match_InvalidSImm6: 882 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5), 883 (1 << 5) - 1); 884 case Match_InvalidSImm6NonZero: 885 return generateImmOutOfRangeError( 886 Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1, 887 "immediate must be non-zero in the range"); 888 case Match_InvalidCLUIImm: 889 return generateImmOutOfRangeError( 890 Operands, ErrorInfo, 1, (1 << 5) - 1, 891 "immediate must be in [0xfffe0, 0xfffff] or"); 892 case Match_InvalidUImm7Lsb00: 893 return generateImmOutOfRangeError( 894 Operands, ErrorInfo, 0, (1 << 7) - 4, 895 "immediate must be a multiple of 4 bytes in the range"); 896 case Match_InvalidUImm8Lsb00: 897 return generateImmOutOfRangeError( 898 Operands, ErrorInfo, 0, (1 << 8) - 4, 899 "immediate must be a multiple of 4 bytes in the range"); 900 case Match_InvalidUImm8Lsb000: 901 return generateImmOutOfRangeError( 902 Operands, ErrorInfo, 0, (1 << 8) - 8, 903 "immediate must be a multiple of 8 bytes in the range"); 904 case Match_InvalidSImm9Lsb0: 905 return generateImmOutOfRangeError( 906 Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2, 907 "immediate must be a multiple of 2 bytes in the range"); 908 case Match_InvalidUImm9Lsb000: 909 return generateImmOutOfRangeError( 910 Operands, ErrorInfo, 0, (1 << 9) - 8, 911 "immediate must be a multiple of 8 bytes in the range"); 912 case Match_InvalidUImm10Lsb00NonZero: 913 return generateImmOutOfRangeError( 914 Operands, ErrorInfo, 4, (1 << 10) - 4, 915 "immediate must be a multiple of 4 bytes in the range"); 916 case Match_InvalidSImm10Lsb0000NonZero: 917 return generateImmOutOfRangeError( 918 Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16, 919 "immediate must be a multiple of 16 bytes and non-zero in the range"); 920 case Match_InvalidSImm12: 921 return generateImmOutOfRangeError( 922 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1, 923 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an " 924 "integer in the range"); 925 case Match_InvalidSImm12Lsb0: 926 return generateImmOutOfRangeError( 927 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2, 928 "immediate must be a multiple of 2 bytes in the range"); 929 case Match_InvalidSImm13Lsb0: 930 return generateImmOutOfRangeError( 931 Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2, 932 "immediate must be a multiple of 2 bytes in the range"); 933 case Match_InvalidUImm20LUI: 934 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1, 935 "operand must be a symbol with " 936 "%hi/%tprel_hi modifier or an integer in " 937 "the range"); 938 case Match_InvalidUImm20AUIPC: 939 return generateImmOutOfRangeError( 940 Operands, ErrorInfo, 0, (1 << 20) - 1, 941 "operand must be a symbol with a " 942 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or " 943 "an integer in the range"); 944 case Match_InvalidSImm21Lsb0JAL: 945 return generateImmOutOfRangeError( 946 Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2, 947 "immediate must be a multiple of 2 bytes in the range"); 948 case Match_InvalidCSRSystemRegister: { 949 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1, 950 "operand must be a valid system register " 951 "name or an integer in the range"); 952 } 953 case Match_InvalidFenceArg: { 954 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 955 return Error( 956 ErrorLoc, 957 "operand must be formed of letters selected in-order from 'iorw'"); 958 } 959 case Match_InvalidFRMArg: { 960 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 961 return Error( 962 ErrorLoc, 963 "operand must be a valid floating point rounding mode mnemonic"); 964 } 965 case Match_InvalidBareSymbol: { 966 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 967 return Error(ErrorLoc, "operand must be a bare symbol name"); 968 } 969 case Match_InvalidCallSymbol: { 970 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 971 return Error(ErrorLoc, "operand must be a bare symbol name"); 972 } 973 case Match_InvalidTPRelAddSymbol: { 974 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 975 return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier"); 976 } 977 } 978 979 llvm_unreachable("Unknown match type detected!"); 980 } 981 982 // Attempts to match Name as a register (either using the default name or 983 // alternative ABI names), setting RegNo to the matching register. Upon 984 // failure, returns true and sets RegNo to 0. If IsRV32E then registers 985 // x16-x31 will be rejected. 986 static bool matchRegisterNameHelper(bool IsRV32E, Register &RegNo, 987 StringRef Name) { 988 RegNo = MatchRegisterName(Name); 989 if (RegNo == RISCV::NoRegister) 990 RegNo = MatchRegisterAltName(Name); 991 if (IsRV32E && RegNo >= RISCV::X16 && RegNo <= RISCV::X31) 992 RegNo = RISCV::NoRegister; 993 return RegNo == RISCV::NoRegister; 994 } 995 996 bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, 997 SMLoc &EndLoc) { 998 const AsmToken &Tok = getParser().getTok(); 999 StartLoc = Tok.getLoc(); 1000 EndLoc = Tok.getEndLoc(); 1001 RegNo = 0; 1002 StringRef Name = getLexer().getTok().getIdentifier(); 1003 1004 if (matchRegisterNameHelper(isRV32E(), (Register&)RegNo, Name)) 1005 return Error(StartLoc, "invalid register name"); 1006 1007 getParser().Lex(); // Eat identifier token. 1008 return false; 1009 } 1010 1011 OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands, 1012 bool AllowParens) { 1013 SMLoc FirstS = getLoc(); 1014 bool HadParens = false; 1015 AsmToken LParen; 1016 1017 // If this is an LParen and a parenthesised register name is allowed, parse it 1018 // atomically. 1019 if (AllowParens && getLexer().is(AsmToken::LParen)) { 1020 AsmToken Buf[2]; 1021 size_t ReadCount = getLexer().peekTokens(Buf); 1022 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) { 1023 HadParens = true; 1024 LParen = getParser().getTok(); 1025 getParser().Lex(); // Eat '(' 1026 } 1027 } 1028 1029 switch (getLexer().getKind()) { 1030 default: 1031 if (HadParens) 1032 getLexer().UnLex(LParen); 1033 return MatchOperand_NoMatch; 1034 case AsmToken::Identifier: 1035 StringRef Name = getLexer().getTok().getIdentifier(); 1036 Register RegNo; 1037 matchRegisterNameHelper(isRV32E(), RegNo, Name); 1038 1039 if (RegNo == RISCV::NoRegister) { 1040 if (HadParens) 1041 getLexer().UnLex(LParen); 1042 return MatchOperand_NoMatch; 1043 } 1044 if (HadParens) 1045 Operands.push_back(RISCVOperand::createToken("(", FirstS, isRV64())); 1046 SMLoc S = getLoc(); 1047 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 1048 getLexer().Lex(); 1049 Operands.push_back(RISCVOperand::createReg(RegNo, S, E, isRV64())); 1050 } 1051 1052 if (HadParens) { 1053 getParser().Lex(); // Eat ')' 1054 Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64())); 1055 } 1056 1057 return MatchOperand_Success; 1058 } 1059 1060 OperandMatchResultTy 1061 RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) { 1062 SMLoc S = getLoc(); 1063 const MCExpr *Res; 1064 1065 switch (getLexer().getKind()) { 1066 default: 1067 return MatchOperand_NoMatch; 1068 case AsmToken::LParen: 1069 case AsmToken::Minus: 1070 case AsmToken::Plus: 1071 case AsmToken::Exclaim: 1072 case AsmToken::Tilde: 1073 case AsmToken::Integer: 1074 case AsmToken::String: { 1075 if (getParser().parseExpression(Res)) 1076 return MatchOperand_ParseFail; 1077 1078 auto *CE = dyn_cast<MCConstantExpr>(Res); 1079 if (CE) { 1080 int64_t Imm = CE->getValue(); 1081 if (isUInt<12>(Imm)) { 1082 auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm); 1083 // Accept an immediate representing a named or un-named Sys Reg 1084 // if the range is valid, regardless of the required features. 1085 Operands.push_back(RISCVOperand::createSysReg( 1086 SysReg ? SysReg->Name : "", S, Imm, isRV64())); 1087 return MatchOperand_Success; 1088 } 1089 } 1090 1091 Twine Msg = "immediate must be an integer in the range"; 1092 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]"); 1093 return MatchOperand_ParseFail; 1094 } 1095 case AsmToken::Identifier: { 1096 StringRef Identifier; 1097 if (getParser().parseIdentifier(Identifier)) 1098 return MatchOperand_ParseFail; 1099 1100 auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier); 1101 // Accept a named Sys Reg if the required features are present. 1102 if (SysReg) { 1103 if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits())) { 1104 Error(S, "system register use requires an option to be enabled"); 1105 return MatchOperand_ParseFail; 1106 } 1107 Operands.push_back(RISCVOperand::createSysReg( 1108 Identifier, S, SysReg->Encoding, isRV64())); 1109 return MatchOperand_Success; 1110 } 1111 1112 Twine Msg = "operand must be a valid system register name " 1113 "or an integer in the range"; 1114 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]"); 1115 return MatchOperand_ParseFail; 1116 } 1117 case AsmToken::Percent: { 1118 // Discard operand with modifier. 1119 Twine Msg = "immediate must be an integer in the range"; 1120 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]"); 1121 return MatchOperand_ParseFail; 1122 } 1123 } 1124 1125 return MatchOperand_NoMatch; 1126 } 1127 1128 OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) { 1129 SMLoc S = getLoc(); 1130 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 1131 const MCExpr *Res; 1132 1133 switch (getLexer().getKind()) { 1134 default: 1135 return MatchOperand_NoMatch; 1136 case AsmToken::LParen: 1137 case AsmToken::Dot: 1138 case AsmToken::Minus: 1139 case AsmToken::Plus: 1140 case AsmToken::Exclaim: 1141 case AsmToken::Tilde: 1142 case AsmToken::Integer: 1143 case AsmToken::String: 1144 case AsmToken::Identifier: 1145 if (getParser().parseExpression(Res)) 1146 return MatchOperand_ParseFail; 1147 break; 1148 case AsmToken::Percent: 1149 return parseOperandWithModifier(Operands); 1150 } 1151 1152 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); 1153 return MatchOperand_Success; 1154 } 1155 1156 OperandMatchResultTy 1157 RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) { 1158 SMLoc S = getLoc(); 1159 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 1160 1161 if (getLexer().getKind() != AsmToken::Percent) { 1162 Error(getLoc(), "expected '%' for operand modifier"); 1163 return MatchOperand_ParseFail; 1164 } 1165 1166 getParser().Lex(); // Eat '%' 1167 1168 if (getLexer().getKind() != AsmToken::Identifier) { 1169 Error(getLoc(), "expected valid identifier for operand modifier"); 1170 return MatchOperand_ParseFail; 1171 } 1172 StringRef Identifier = getParser().getTok().getIdentifier(); 1173 RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier); 1174 if (VK == RISCVMCExpr::VK_RISCV_Invalid) { 1175 Error(getLoc(), "unrecognized operand modifier"); 1176 return MatchOperand_ParseFail; 1177 } 1178 1179 getParser().Lex(); // Eat the identifier 1180 if (getLexer().getKind() != AsmToken::LParen) { 1181 Error(getLoc(), "expected '('"); 1182 return MatchOperand_ParseFail; 1183 } 1184 getParser().Lex(); // Eat '(' 1185 1186 const MCExpr *SubExpr; 1187 if (getParser().parseParenExpression(SubExpr, E)) { 1188 return MatchOperand_ParseFail; 1189 } 1190 1191 const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext()); 1192 Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64())); 1193 return MatchOperand_Success; 1194 } 1195 1196 OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) { 1197 SMLoc S = getLoc(); 1198 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 1199 const MCExpr *Res; 1200 1201 if (getLexer().getKind() != AsmToken::Identifier) 1202 return MatchOperand_NoMatch; 1203 1204 StringRef Identifier; 1205 AsmToken Tok = getLexer().getTok(); 1206 1207 if (getParser().parseIdentifier(Identifier)) 1208 return MatchOperand_ParseFail; 1209 1210 if (Identifier.consume_back("@plt")) { 1211 Error(getLoc(), "'@plt' operand not valid for instruction"); 1212 return MatchOperand_ParseFail; 1213 } 1214 1215 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 1216 1217 if (Sym->isVariable()) { 1218 const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false); 1219 if (!isa<MCSymbolRefExpr>(V)) { 1220 getLexer().UnLex(Tok); // Put back if it's not a bare symbol. 1221 return MatchOperand_NoMatch; 1222 } 1223 Res = V; 1224 } else 1225 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 1226 1227 MCBinaryExpr::Opcode Opcode; 1228 switch (getLexer().getKind()) { 1229 default: 1230 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); 1231 return MatchOperand_Success; 1232 case AsmToken::Plus: 1233 Opcode = MCBinaryExpr::Add; 1234 break; 1235 case AsmToken::Minus: 1236 Opcode = MCBinaryExpr::Sub; 1237 break; 1238 } 1239 1240 const MCExpr *Expr; 1241 if (getParser().parseExpression(Expr)) 1242 return MatchOperand_ParseFail; 1243 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext()); 1244 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); 1245 return MatchOperand_Success; 1246 } 1247 1248 OperandMatchResultTy RISCVAsmParser::parseCallSymbol(OperandVector &Operands) { 1249 SMLoc S = getLoc(); 1250 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); 1251 const MCExpr *Res; 1252 1253 if (getLexer().getKind() != AsmToken::Identifier) 1254 return MatchOperand_NoMatch; 1255 1256 // Avoid parsing the register in `call rd, foo` as a call symbol. 1257 if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement) 1258 return MatchOperand_NoMatch; 1259 1260 StringRef Identifier; 1261 if (getParser().parseIdentifier(Identifier)) 1262 return MatchOperand_ParseFail; 1263 1264 RISCVMCExpr::VariantKind Kind = RISCVMCExpr::VK_RISCV_CALL; 1265 if (Identifier.consume_back("@plt")) 1266 Kind = RISCVMCExpr::VK_RISCV_CALL_PLT; 1267 1268 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 1269 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 1270 Res = RISCVMCExpr::create(Res, Kind, getContext()); 1271 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); 1272 return MatchOperand_Success; 1273 } 1274 1275 OperandMatchResultTy RISCVAsmParser::parseJALOffset(OperandVector &Operands) { 1276 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo` 1277 // both being acceptable forms. When parsing `jal ra, foo` this function 1278 // will be called for the `ra` register operand in an attempt to match the 1279 // single-operand alias. parseJALOffset must fail for this case. It would 1280 // seem logical to try parse the operand using parseImmediate and return 1281 // NoMatch if the next token is a comma (meaning we must be parsing a jal in 1282 // the second form rather than the first). We can't do this as there's no 1283 // way of rewinding the lexer state. Instead, return NoMatch if this operand 1284 // is an identifier and is followed by a comma. 1285 if (getLexer().is(AsmToken::Identifier) && 1286 getLexer().peekTok().is(AsmToken::Comma)) 1287 return MatchOperand_NoMatch; 1288 1289 return parseImmediate(Operands); 1290 } 1291 1292 OperandMatchResultTy 1293 RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) { 1294 if (getLexer().isNot(AsmToken::LParen)) { 1295 Error(getLoc(), "expected '('"); 1296 return MatchOperand_ParseFail; 1297 } 1298 1299 getParser().Lex(); // Eat '(' 1300 Operands.push_back(RISCVOperand::createToken("(", getLoc(), isRV64())); 1301 1302 if (parseRegister(Operands) != MatchOperand_Success) { 1303 Error(getLoc(), "expected register"); 1304 return MatchOperand_ParseFail; 1305 } 1306 1307 if (getLexer().isNot(AsmToken::RParen)) { 1308 Error(getLoc(), "expected ')'"); 1309 return MatchOperand_ParseFail; 1310 } 1311 1312 getParser().Lex(); // Eat ')' 1313 Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64())); 1314 1315 return MatchOperand_Success; 1316 } 1317 1318 OperandMatchResultTy RISCVAsmParser::parseAtomicMemOp(OperandVector &Operands) { 1319 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand" 1320 // as one of their register operands, such as `(a0)`. This just denotes that 1321 // the register (in this case `a0`) contains a memory address. 1322 // 1323 // Normally, we would be able to parse these by putting the parens into the 1324 // instruction string. However, GNU as also accepts a zero-offset memory 1325 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed 1326 // with parseImmediate followed by parseMemOpBaseReg, but these instructions 1327 // do not accept an immediate operand, and we do not want to add a "dummy" 1328 // operand that is silently dropped. 1329 // 1330 // Instead, we use this custom parser. This will: allow (and discard) an 1331 // offset if it is zero; require (and discard) parentheses; and add only the 1332 // parsed register operand to `Operands`. 1333 // 1334 // These operands are printed with RISCVInstPrinter::printAtomicMemOp, which 1335 // will only print the register surrounded by parentheses (which GNU as also 1336 // uses as its canonical representation for these operands). 1337 std::unique_ptr<RISCVOperand> OptionalImmOp; 1338 1339 if (getLexer().isNot(AsmToken::LParen)) { 1340 // Parse an Integer token. We do not accept arbritrary constant expressions 1341 // in the offset field (because they may include parens, which complicates 1342 // parsing a lot). 1343 int64_t ImmVal; 1344 SMLoc ImmStart = getLoc(); 1345 if (getParser().parseIntToken(ImmVal, 1346 "expected '(' or optional integer offset")) 1347 return MatchOperand_ParseFail; 1348 1349 // Create a RISCVOperand for checking later (so the error messages are 1350 // nicer), but we don't add it to Operands. 1351 SMLoc ImmEnd = getLoc(); 1352 OptionalImmOp = 1353 RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()), 1354 ImmStart, ImmEnd, isRV64()); 1355 } 1356 1357 if (getLexer().isNot(AsmToken::LParen)) { 1358 Error(getLoc(), OptionalImmOp ? "expected '(' after optional integer offset" 1359 : "expected '(' or optional integer offset"); 1360 return MatchOperand_ParseFail; 1361 } 1362 getParser().Lex(); // Eat '(' 1363 1364 if (parseRegister(Operands) != MatchOperand_Success) { 1365 Error(getLoc(), "expected register"); 1366 return MatchOperand_ParseFail; 1367 } 1368 1369 if (getLexer().isNot(AsmToken::RParen)) { 1370 Error(getLoc(), "expected ')'"); 1371 return MatchOperand_ParseFail; 1372 } 1373 getParser().Lex(); // Eat ')' 1374 1375 // Deferred Handling of non-zero offsets. This makes the error messages nicer. 1376 if (OptionalImmOp && !OptionalImmOp->isImmZero()) { 1377 Error(OptionalImmOp->getStartLoc(), "optional integer offset must be 0", 1378 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc())); 1379 return MatchOperand_ParseFail; 1380 } 1381 1382 return MatchOperand_Success; 1383 } 1384 1385 /// Looks at a token type and creates the relevant operand from this 1386 /// information, adding to Operands. If operand was parsed, returns false, else 1387 /// true. 1388 bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { 1389 // Check if the current operand has a custom associated parser, if so, try to 1390 // custom parse the operand, or fallback to the general approach. 1391 OperandMatchResultTy Result = 1392 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true); 1393 if (Result == MatchOperand_Success) 1394 return false; 1395 if (Result == MatchOperand_ParseFail) 1396 return true; 1397 1398 // Attempt to parse token as a register. 1399 if (parseRegister(Operands, true) == MatchOperand_Success) 1400 return false; 1401 1402 // Attempt to parse token as an immediate 1403 if (parseImmediate(Operands) == MatchOperand_Success) { 1404 // Parse memory base register if present 1405 if (getLexer().is(AsmToken::LParen)) 1406 return parseMemOpBaseReg(Operands) != MatchOperand_Success; 1407 return false; 1408 } 1409 1410 // Finally we have exhausted all options and must declare defeat. 1411 Error(getLoc(), "unknown operand"); 1412 return true; 1413 } 1414 1415 bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info, 1416 StringRef Name, SMLoc NameLoc, 1417 OperandVector &Operands) { 1418 // Ensure that if the instruction occurs when relaxation is enabled, 1419 // relocations are forced for the file. Ideally this would be done when there 1420 // is enough information to reliably determine if the instruction itself may 1421 // cause relaxations. Unfortunately instruction processing stage occurs in the 1422 // same pass as relocation emission, so it's too late to set a 'sticky bit' 1423 // for the entire file. 1424 if (getSTI().getFeatureBits()[RISCV::FeatureRelax]) { 1425 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr(); 1426 if (Assembler != nullptr) { 1427 RISCVAsmBackend &MAB = 1428 static_cast<RISCVAsmBackend &>(Assembler->getBackend()); 1429 MAB.setForceRelocs(); 1430 } 1431 } 1432 1433 // First operand is token for instruction 1434 Operands.push_back(RISCVOperand::createToken(Name, NameLoc, isRV64())); 1435 1436 // If there are no more operands, then finish 1437 if (getLexer().is(AsmToken::EndOfStatement)) 1438 return false; 1439 1440 // Parse first operand 1441 if (parseOperand(Operands, Name)) 1442 return true; 1443 1444 // Parse until end of statement, consuming commas between operands 1445 unsigned OperandIdx = 1; 1446 while (getLexer().is(AsmToken::Comma)) { 1447 // Consume comma token 1448 getLexer().Lex(); 1449 1450 // Parse next operand 1451 if (parseOperand(Operands, Name)) 1452 return true; 1453 1454 ++OperandIdx; 1455 } 1456 1457 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1458 SMLoc Loc = getLexer().getLoc(); 1459 getParser().eatToEndOfStatement(); 1460 return Error(Loc, "unexpected token"); 1461 } 1462 1463 getParser().Lex(); // Consume the EndOfStatement. 1464 return false; 1465 } 1466 1467 bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr, 1468 RISCVMCExpr::VariantKind &Kind, 1469 int64_t &Addend) { 1470 Kind = RISCVMCExpr::VK_RISCV_None; 1471 Addend = 0; 1472 1473 if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) { 1474 Kind = RE->getKind(); 1475 Expr = RE->getSubExpr(); 1476 } 1477 1478 // It's a simple symbol reference or constant with no addend. 1479 if (isa<MCConstantExpr>(Expr) || isa<MCSymbolRefExpr>(Expr)) 1480 return true; 1481 1482 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr); 1483 if (!BE) 1484 return false; 1485 1486 if (!isa<MCSymbolRefExpr>(BE->getLHS())) 1487 return false; 1488 1489 if (BE->getOpcode() != MCBinaryExpr::Add && 1490 BE->getOpcode() != MCBinaryExpr::Sub) 1491 return false; 1492 1493 // We are able to support the subtraction of two symbol references 1494 if (BE->getOpcode() == MCBinaryExpr::Sub && 1495 isa<MCSymbolRefExpr>(BE->getRHS())) 1496 return true; 1497 1498 // See if the addend is a constant, otherwise there's more going 1499 // on here than we can deal with. 1500 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS()); 1501 if (!AddendExpr) 1502 return false; 1503 1504 Addend = AddendExpr->getValue(); 1505 if (BE->getOpcode() == MCBinaryExpr::Sub) 1506 Addend = -Addend; 1507 1508 // It's some symbol reference + a constant addend 1509 return Kind != RISCVMCExpr::VK_RISCV_Invalid; 1510 } 1511 1512 bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) { 1513 // This returns false if this function recognizes the directive 1514 // regardless of whether it is successfully handles or reports an 1515 // error. Otherwise it returns true to give the generic parser a 1516 // chance at recognizing it. 1517 StringRef IDVal = DirectiveID.getString(); 1518 1519 if (IDVal == ".option") 1520 return parseDirectiveOption(); 1521 1522 return true; 1523 } 1524 1525 bool RISCVAsmParser::parseDirectiveOption() { 1526 MCAsmParser &Parser = getParser(); 1527 // Get the option token. 1528 AsmToken Tok = Parser.getTok(); 1529 // At the moment only identifiers are supported. 1530 if (Tok.isNot(AsmToken::Identifier)) 1531 return Error(Parser.getTok().getLoc(), 1532 "unexpected token, expected identifier"); 1533 1534 StringRef Option = Tok.getIdentifier(); 1535 1536 if (Option == "push") { 1537 getTargetStreamer().emitDirectiveOptionPush(); 1538 1539 Parser.Lex(); 1540 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) 1541 return Error(Parser.getTok().getLoc(), 1542 "unexpected token, expected end of statement"); 1543 1544 pushFeatureBits(); 1545 return false; 1546 } 1547 1548 if (Option == "pop") { 1549 SMLoc StartLoc = Parser.getTok().getLoc(); 1550 getTargetStreamer().emitDirectiveOptionPop(); 1551 1552 Parser.Lex(); 1553 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) 1554 return Error(Parser.getTok().getLoc(), 1555 "unexpected token, expected end of statement"); 1556 1557 if (popFeatureBits()) 1558 return Error(StartLoc, ".option pop with no .option push"); 1559 1560 return false; 1561 } 1562 1563 if (Option == "rvc") { 1564 getTargetStreamer().emitDirectiveOptionRVC(); 1565 1566 Parser.Lex(); 1567 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) 1568 return Error(Parser.getTok().getLoc(), 1569 "unexpected token, expected end of statement"); 1570 1571 setFeatureBits(RISCV::FeatureStdExtC, "c"); 1572 return false; 1573 } 1574 1575 if (Option == "norvc") { 1576 getTargetStreamer().emitDirectiveOptionNoRVC(); 1577 1578 Parser.Lex(); 1579 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) 1580 return Error(Parser.getTok().getLoc(), 1581 "unexpected token, expected end of statement"); 1582 1583 clearFeatureBits(RISCV::FeatureStdExtC, "c"); 1584 return false; 1585 } 1586 1587 if (Option == "relax") { 1588 getTargetStreamer().emitDirectiveOptionRelax(); 1589 1590 Parser.Lex(); 1591 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) 1592 return Error(Parser.getTok().getLoc(), 1593 "unexpected token, expected end of statement"); 1594 1595 setFeatureBits(RISCV::FeatureRelax, "relax"); 1596 return false; 1597 } 1598 1599 if (Option == "norelax") { 1600 getTargetStreamer().emitDirectiveOptionNoRelax(); 1601 1602 Parser.Lex(); 1603 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) 1604 return Error(Parser.getTok().getLoc(), 1605 "unexpected token, expected end of statement"); 1606 1607 clearFeatureBits(RISCV::FeatureRelax, "relax"); 1608 return false; 1609 } 1610 1611 // Unknown option. 1612 Warning(Parser.getTok().getLoc(), 1613 "unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'relax' or " 1614 "'norelax'"); 1615 Parser.eatToEndOfStatement(); 1616 return false; 1617 } 1618 1619 void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) { 1620 MCInst CInst; 1621 bool Res = compressInst(CInst, Inst, getSTI(), S.getContext()); 1622 CInst.setLoc(Inst.getLoc()); 1623 S.EmitInstruction((Res ? CInst : Inst), getSTI()); 1624 } 1625 1626 void RISCVAsmParser::emitLoadImm(Register DestReg, int64_t Value, 1627 MCStreamer &Out) { 1628 RISCVMatInt::InstSeq Seq; 1629 RISCVMatInt::generateInstSeq(Value, isRV64(), Seq); 1630 1631 Register SrcReg = RISCV::X0; 1632 for (RISCVMatInt::Inst &Inst : Seq) { 1633 if (Inst.Opc == RISCV::LUI) { 1634 emitToStreamer( 1635 Out, MCInstBuilder(RISCV::LUI).addReg(DestReg).addImm(Inst.Imm)); 1636 } else { 1637 emitToStreamer( 1638 Out, MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm( 1639 Inst.Imm)); 1640 } 1641 1642 // Only the first instruction has X0 as its source. 1643 SrcReg = DestReg; 1644 } 1645 } 1646 1647 void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg, 1648 const MCExpr *Symbol, 1649 RISCVMCExpr::VariantKind VKHi, 1650 unsigned SecondOpcode, SMLoc IDLoc, 1651 MCStreamer &Out) { 1652 // A pair of instructions for PC-relative addressing; expands to 1653 // TmpLabel: AUIPC TmpReg, VKHi(symbol) 1654 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel) 1655 MCContext &Ctx = getContext(); 1656 1657 MCSymbol *TmpLabel = Ctx.createTempSymbol( 1658 "pcrel_hi", /* AlwaysAddSuffix */ true, /* CanBeUnnamed */ false); 1659 Out.EmitLabel(TmpLabel); 1660 1661 const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx); 1662 emitToStreamer( 1663 Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi)); 1664 1665 const MCExpr *RefToLinkTmpLabel = 1666 RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx), 1667 RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx); 1668 1669 emitToStreamer(Out, MCInstBuilder(SecondOpcode) 1670 .addOperand(DestReg) 1671 .addOperand(TmpReg) 1672 .addExpr(RefToLinkTmpLabel)); 1673 } 1674 1675 void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, 1676 MCStreamer &Out) { 1677 // The load local address pseudo-instruction "lla" is used in PC-relative 1678 // addressing of local symbols: 1679 // lla rdest, symbol 1680 // expands to 1681 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol) 1682 // ADDI rdest, rdest, %pcrel_lo(TmpLabel) 1683 MCOperand DestReg = Inst.getOperand(0); 1684 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1685 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI, 1686 RISCV::ADDI, IDLoc, Out); 1687 } 1688 1689 void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc, 1690 MCStreamer &Out) { 1691 // The load address pseudo-instruction "la" is used in PC-relative and 1692 // GOT-indirect addressing of global symbols: 1693 // la rdest, symbol 1694 // expands to either (for non-PIC) 1695 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol) 1696 // ADDI rdest, rdest, %pcrel_lo(TmpLabel) 1697 // or (for PIC) 1698 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol) 1699 // Lx rdest, %pcrel_lo(TmpLabel)(rdest) 1700 MCOperand DestReg = Inst.getOperand(0); 1701 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1702 unsigned SecondOpcode; 1703 RISCVMCExpr::VariantKind VKHi; 1704 // FIXME: Should check .option (no)pic when implemented 1705 if (getContext().getObjectFileInfo()->isPositionIndependent()) { 1706 SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW; 1707 VKHi = RISCVMCExpr::VK_RISCV_GOT_HI; 1708 } else { 1709 SecondOpcode = RISCV::ADDI; 1710 VKHi = RISCVMCExpr::VK_RISCV_PCREL_HI; 1711 } 1712 emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out); 1713 } 1714 1715 void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, 1716 MCStreamer &Out) { 1717 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in 1718 // initial-exec TLS model addressing of global symbols: 1719 // la.tls.ie rdest, symbol 1720 // expands to 1721 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol) 1722 // Lx rdest, %pcrel_lo(TmpLabel)(rdest) 1723 MCOperand DestReg = Inst.getOperand(0); 1724 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1725 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW; 1726 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI, 1727 SecondOpcode, IDLoc, Out); 1728 } 1729 1730 void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, 1731 MCStreamer &Out) { 1732 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in 1733 // global-dynamic TLS model addressing of global symbols: 1734 // la.tls.gd rdest, symbol 1735 // expands to 1736 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol) 1737 // ADDI rdest, rdest, %pcrel_lo(TmpLabel) 1738 MCOperand DestReg = Inst.getOperand(0); 1739 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 1740 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI, 1741 RISCV::ADDI, IDLoc, Out); 1742 } 1743 1744 void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, 1745 SMLoc IDLoc, MCStreamer &Out, 1746 bool HasTmpReg) { 1747 // The load/store pseudo-instruction does a pc-relative load with 1748 // a symbol. 1749 // 1750 // The expansion looks like this 1751 // 1752 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol) 1753 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp) 1754 MCOperand DestReg = Inst.getOperand(0); 1755 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1; 1756 unsigned TmpRegOpIdx = HasTmpReg ? 1 : 0; 1757 MCOperand TmpReg = Inst.getOperand(TmpRegOpIdx); 1758 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr(); 1759 emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI, 1760 Opcode, IDLoc, Out); 1761 } 1762 1763 bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst, 1764 OperandVector &Operands) { 1765 assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction"); 1766 assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind"); 1767 if (Inst.getOperand(2).getReg() != RISCV::X4) { 1768 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc(); 1769 return Error(ErrorLoc, "the second input operand must be tp/x4 when using " 1770 "%tprel_add modifier"); 1771 } 1772 1773 return false; 1774 } 1775 1776 bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 1777 OperandVector &Operands, 1778 MCStreamer &Out) { 1779 Inst.setLoc(IDLoc); 1780 1781 switch (Inst.getOpcode()) { 1782 default: 1783 break; 1784 case RISCV::PseudoLI: { 1785 Register Reg = Inst.getOperand(0).getReg(); 1786 const MCOperand &Op1 = Inst.getOperand(1); 1787 if (Op1.isExpr()) { 1788 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar. 1789 // Just convert to an addi. This allows compatibility with gas. 1790 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI) 1791 .addReg(Reg) 1792 .addReg(RISCV::X0) 1793 .addExpr(Op1.getExpr())); 1794 return false; 1795 } 1796 int64_t Imm = Inst.getOperand(1).getImm(); 1797 // On RV32 the immediate here can either be a signed or an unsigned 1798 // 32-bit number. Sign extension has to be performed to ensure that Imm 1799 // represents the expected signed 64-bit number. 1800 if (!isRV64()) 1801 Imm = SignExtend64<32>(Imm); 1802 emitLoadImm(Reg, Imm, Out); 1803 return false; 1804 } 1805 case RISCV::PseudoLLA: 1806 emitLoadLocalAddress(Inst, IDLoc, Out); 1807 return false; 1808 case RISCV::PseudoLA: 1809 emitLoadAddress(Inst, IDLoc, Out); 1810 return false; 1811 case RISCV::PseudoLA_TLS_IE: 1812 emitLoadTLSIEAddress(Inst, IDLoc, Out); 1813 return false; 1814 case RISCV::PseudoLA_TLS_GD: 1815 emitLoadTLSGDAddress(Inst, IDLoc, Out); 1816 return false; 1817 case RISCV::PseudoLB: 1818 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false); 1819 return false; 1820 case RISCV::PseudoLBU: 1821 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false); 1822 return false; 1823 case RISCV::PseudoLH: 1824 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false); 1825 return false; 1826 case RISCV::PseudoLHU: 1827 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false); 1828 return false; 1829 case RISCV::PseudoLW: 1830 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false); 1831 return false; 1832 case RISCV::PseudoLWU: 1833 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false); 1834 return false; 1835 case RISCV::PseudoLD: 1836 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false); 1837 return false; 1838 case RISCV::PseudoFLW: 1839 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true); 1840 return false; 1841 case RISCV::PseudoFLD: 1842 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true); 1843 return false; 1844 case RISCV::PseudoSB: 1845 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true); 1846 return false; 1847 case RISCV::PseudoSH: 1848 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true); 1849 return false; 1850 case RISCV::PseudoSW: 1851 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true); 1852 return false; 1853 case RISCV::PseudoSD: 1854 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true); 1855 return false; 1856 case RISCV::PseudoFSW: 1857 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true); 1858 return false; 1859 case RISCV::PseudoFSD: 1860 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true); 1861 return false; 1862 case RISCV::PseudoAddTPRel: 1863 if (checkPseudoAddTPRel(Inst, Operands)) 1864 return true; 1865 break; 1866 } 1867 1868 emitToStreamer(Out, Inst); 1869 return false; 1870 } 1871 1872 extern "C" void LLVMInitializeRISCVAsmParser() { 1873 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target()); 1874 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target()); 1875 } 1876