1 //===-- RISCVAsmParser.cpp - Parse RISC-V 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/RISCVBaseInfo.h" 11 #include "MCTargetDesc/RISCVInstPrinter.h" 12 #include "MCTargetDesc/RISCVMCExpr.h" 13 #include "MCTargetDesc/RISCVMCTargetDesc.h" 14 #include "MCTargetDesc/RISCVMatInt.h" 15 #include "MCTargetDesc/RISCVTargetStreamer.h" 16 #include "TargetInfo/RISCVTargetInfo.h" 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/SmallBitVector.h" 19 #include "llvm/ADT/SmallVector.h" 20 #include "llvm/ADT/Statistic.h" 21 #include "llvm/ADT/StringExtras.h" 22 #include "llvm/MC/MCAssembler.h" 23 #include "llvm/MC/MCContext.h" 24 #include "llvm/MC/MCExpr.h" 25 #include "llvm/MC/MCInst.h" 26 #include "llvm/MC/MCInstBuilder.h" 27 #include "llvm/MC/MCInstrInfo.h" 28 #include "llvm/MC/MCObjectFileInfo.h" 29 #include "llvm/MC/MCParser/MCAsmLexer.h" 30 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 31 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 32 #include "llvm/MC/MCRegisterInfo.h" 33 #include "llvm/MC/MCStreamer.h" 34 #include "llvm/MC/MCSubtargetInfo.h" 35 #include "llvm/MC/MCValue.h" 36 #include "llvm/MC/TargetRegistry.h" 37 #include "llvm/Support/Casting.h" 38 #include "llvm/Support/CommandLine.h" 39 #include "llvm/Support/MathExtras.h" 40 #include "llvm/Support/RISCVAttributes.h" 41 #include "llvm/TargetParser/RISCVISAInfo.h" 42 43 #include <limits> 44 45 using namespace llvm; 46 47 #define DEBUG_TYPE "riscv-asm-parser" 48 49 STATISTIC(RISCVNumInstrsCompressed, 50 "Number of RISC-V Compressed instructions emitted"); 51 52 static cl::opt<bool> AddBuildAttributes("riscv-add-build-attributes", 53 cl::init(false)); 54 55 namespace llvm { 56 extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures]; 57 } // namespace llvm 58 59 namespace { 60 struct RISCVOperand; 61 62 struct ParserOptionsSet { 63 bool IsPicEnabled; 64 }; 65 66 class RISCVAsmParser : public MCTargetAsmParser { 67 // This tracks the parsing of the 4 operands that make up the vtype portion 68 // of vset(i)vli instructions which are separated by commas. The state names 69 // represent the next expected operand with Done meaning no other operands are 70 // expected. 71 enum VTypeState { 72 VTypeState_SEW, 73 VTypeState_LMUL, 74 VTypeState_TailPolicy, 75 VTypeState_MaskPolicy, 76 VTypeState_Done, 77 }; 78 79 SmallVector<FeatureBitset, 4> FeatureBitStack; 80 81 SmallVector<ParserOptionsSet, 4> ParserOptionsStack; 82 ParserOptionsSet ParserOptions; 83 84 SMLoc getLoc() const { return getParser().getTok().getLoc(); } 85 bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); } 86 bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureStdExtE); } 87 bool enableExperimentalExtension() const { 88 return getSTI().hasFeature(RISCV::Experimental); 89 } 90 91 RISCVTargetStreamer &getTargetStreamer() { 92 assert(getParser().getStreamer().getTargetStreamer() && 93 "do not have a target streamer"); 94 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); 95 return static_cast<RISCVTargetStreamer &>(TS); 96 } 97 98 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 99 unsigned Kind) override; 100 unsigned checkTargetMatchPredicate(MCInst &Inst) override; 101 102 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo, 103 int64_t Lower, int64_t Upper, 104 const Twine &Msg); 105 bool generateImmOutOfRangeError(SMLoc ErrorLoc, int64_t Lower, int64_t Upper, 106 const Twine &Msg); 107 108 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 109 OperandVector &Operands, MCStreamer &Out, 110 uint64_t &ErrorInfo, 111 bool MatchingInlineAsm) override; 112 113 MCRegister matchRegisterNameHelper(StringRef Name) const; 114 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override; 115 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, 116 SMLoc &EndLoc) override; 117 118 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 119 SMLoc NameLoc, OperandVector &Operands) override; 120 121 ParseStatus parseDirective(AsmToken DirectiveID) override; 122 123 bool parseVTypeToken(const AsmToken &Tok, VTypeState &State, unsigned &Sew, 124 unsigned &Lmul, bool &Fractional, bool &TailAgnostic, 125 bool &MaskAgnostic); 126 bool generateVTypeError(SMLoc ErrorLoc); 127 128 // Helper to actually emit an instruction to the MCStreamer. Also, when 129 // possible, compression of the instruction is performed. 130 void emitToStreamer(MCStreamer &S, const MCInst &Inst); 131 132 // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that 133 // synthesize the desired immedate value into the destination register. 134 void emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out); 135 136 // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement 137 // helpers such as emitLoadLocalAddress and emitLoadAddress. 138 void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg, 139 const MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi, 140 unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out); 141 142 // Helper to emit pseudo instruction "lla" used in PC-rel addressing. 143 void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 144 145 // Helper to emit pseudo instruction "lga" used in GOT-rel addressing. 146 void emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 147 148 // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing. 149 void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 150 151 // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS 152 // addressing. 153 void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 154 155 // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS 156 // addressing. 157 void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); 158 159 // Helper to emit pseudo load/store instruction with a symbol. 160 void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, 161 MCStreamer &Out, bool HasTmpReg); 162 163 // Helper to emit pseudo sign/zero extend instruction. 164 void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width, 165 SMLoc IDLoc, MCStreamer &Out); 166 167 // Helper to emit pseudo vmsge{u}.vx instruction. 168 void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out); 169 170 // Checks that a PseudoAddTPRel is using x4/tp in its second input operand. 171 // Enforcing this using a restricted register class for the second input 172 // operand of PseudoAddTPRel results in a poor diagnostic due to the fact 173 // 'add' is an overloaded mnemonic. 174 bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands); 175 176 // Checks that a PseudoTLSDESCCall is using x5/t0 in its output operand. 177 // Enforcing this using a restricted register class for the output 178 // operand of PseudoTLSDESCCall results in a poor diagnostic due to the fact 179 // 'jalr' is an overloaded mnemonic. 180 bool checkPseudoTLSDESCCall(MCInst &Inst, OperandVector &Operands); 181 182 // Check instruction constraints. 183 bool validateInstruction(MCInst &Inst, OperandVector &Operands); 184 185 /// Helper for processing MC instructions that have been successfully matched 186 /// by MatchAndEmitInstruction. Modifications to the emitted instructions, 187 /// like the expansion of pseudo instructions (e.g., "li"), can be performed 188 /// in this method. 189 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands, 190 MCStreamer &Out); 191 192 // Auto-generated instruction matching functions 193 #define GET_ASSEMBLER_HEADER 194 #include "RISCVGenAsmMatcher.inc" 195 196 ParseStatus parseCSRSystemRegister(OperandVector &Operands); 197 ParseStatus parseFPImm(OperandVector &Operands); 198 ParseStatus parseImmediate(OperandVector &Operands); 199 ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false); 200 ParseStatus parseMemOpBaseReg(OperandVector &Operands); 201 ParseStatus parseZeroOffsetMemOp(OperandVector &Operands); 202 ParseStatus parseOperandWithModifier(OperandVector &Operands); 203 ParseStatus parseBareSymbol(OperandVector &Operands); 204 ParseStatus parseCallSymbol(OperandVector &Operands); 205 ParseStatus parsePseudoJumpSymbol(OperandVector &Operands); 206 ParseStatus parseJALOffset(OperandVector &Operands); 207 ParseStatus parseVTypeI(OperandVector &Operands); 208 ParseStatus parseMaskReg(OperandVector &Operands); 209 ParseStatus parseInsnDirectiveOpcode(OperandVector &Operands); 210 ParseStatus parseInsnCDirectiveOpcode(OperandVector &Operands); 211 ParseStatus parseGPRAsFPR(OperandVector &Operands); 212 template <bool IsRV64Inst> ParseStatus parseGPRPair(OperandVector &Operands); 213 ParseStatus parseGPRPair(OperandVector &Operands, bool IsRV64Inst); 214 ParseStatus parseFRMArg(OperandVector &Operands); 215 ParseStatus parseFenceArg(OperandVector &Operands); 216 ParseStatus parseReglist(OperandVector &Operands); 217 ParseStatus parseRegReg(OperandVector &Operands); 218 ParseStatus parseRetval(OperandVector &Operands); 219 ParseStatus parseZcmpStackAdj(OperandVector &Operands, 220 bool ExpectNegative = false); 221 ParseStatus parseZcmpNegStackAdj(OperandVector &Operands) { 222 return parseZcmpStackAdj(Operands, /*ExpectNegative*/ true); 223 } 224 225 bool parseOperand(OperandVector &Operands, StringRef Mnemonic); 226 227 bool parseDirectiveOption(); 228 bool parseDirectiveAttribute(); 229 bool parseDirectiveInsn(SMLoc L); 230 bool parseDirectiveVariantCC(); 231 232 /// Helper to reset target features for a new arch string. It 233 /// also records the new arch string that is expanded by RISCVISAInfo 234 /// and reports error for invalid arch string. 235 bool resetToArch(StringRef Arch, SMLoc Loc, std::string &Result, 236 bool FromOptionDirective); 237 238 void setFeatureBits(uint64_t Feature, StringRef FeatureString) { 239 if (!(getSTI().hasFeature(Feature))) { 240 MCSubtargetInfo &STI = copySTI(); 241 setAvailableFeatures( 242 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); 243 } 244 } 245 246 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) { 247 if (getSTI().hasFeature(Feature)) { 248 MCSubtargetInfo &STI = copySTI(); 249 setAvailableFeatures( 250 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); 251 } 252 } 253 254 void pushFeatureBits() { 255 assert(FeatureBitStack.size() == ParserOptionsStack.size() && 256 "These two stacks must be kept synchronized"); 257 FeatureBitStack.push_back(getSTI().getFeatureBits()); 258 ParserOptionsStack.push_back(ParserOptions); 259 } 260 261 bool popFeatureBits() { 262 assert(FeatureBitStack.size() == ParserOptionsStack.size() && 263 "These two stacks must be kept synchronized"); 264 if (FeatureBitStack.empty()) 265 return true; 266 267 FeatureBitset FeatureBits = FeatureBitStack.pop_back_val(); 268 copySTI().setFeatureBits(FeatureBits); 269 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits)); 270 271 ParserOptions = ParserOptionsStack.pop_back_val(); 272 273 return false; 274 } 275 276 std::unique_ptr<RISCVOperand> defaultMaskRegOp() const; 277 std::unique_ptr<RISCVOperand> defaultFRMArgOp() const; 278 std::unique_ptr<RISCVOperand> defaultFRMArgLegacyOp() const; 279 280 public: 281 enum RISCVMatchResultTy { 282 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, 283 Match_RequiresEvenGPRs, 284 #define GET_OPERAND_DIAGNOSTIC_TYPES 285 #include "RISCVGenAsmMatcher.inc" 286 #undef GET_OPERAND_DIAGNOSTIC_TYPES 287 }; 288 289 static bool classifySymbolRef(const MCExpr *Expr, 290 RISCVMCExpr::VariantKind &Kind); 291 static bool isSymbolDiff(const MCExpr *Expr); 292 293 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, 294 const MCInstrInfo &MII, const MCTargetOptions &Options) 295 : MCTargetAsmParser(Options, STI, MII) { 296 MCAsmParserExtension::Initialize(Parser); 297 298 Parser.addAliasForDirective(".half", ".2byte"); 299 Parser.addAliasForDirective(".hword", ".2byte"); 300 Parser.addAliasForDirective(".word", ".4byte"); 301 Parser.addAliasForDirective(".dword", ".8byte"); 302 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 303 304 auto ABIName = StringRef(Options.ABIName); 305 if (ABIName.ends_with("f") && !getSTI().hasFeature(RISCV::FeatureStdExtF)) { 306 errs() << "Hard-float 'f' ABI can't be used for a target that " 307 "doesn't support the F instruction set extension (ignoring " 308 "target-abi)\n"; 309 } else if (ABIName.ends_with("d") && 310 !getSTI().hasFeature(RISCV::FeatureStdExtD)) { 311 errs() << "Hard-float 'd' ABI can't be used for a target that " 312 "doesn't support the D instruction set extension (ignoring " 313 "target-abi)\n"; 314 } 315 316 // Use computeTargetABI to check if ABIName is valid. If invalid, output 317 // error message. 318 RISCVABI::computeTargetABI(STI.getTargetTriple(), STI.getFeatureBits(), 319 ABIName); 320 321 const MCObjectFileInfo *MOFI = Parser.getContext().getObjectFileInfo(); 322 ParserOptions.IsPicEnabled = MOFI->isPositionIndependent(); 323 324 if (AddBuildAttributes) 325 getTargetStreamer().emitTargetAttributes(STI, /*EmitStackAlign*/ false); 326 } 327 }; 328 329 /// RISCVOperand - Instances of this class represent a parsed machine 330 /// instruction 331 struct RISCVOperand final : public MCParsedAsmOperand { 332 333 enum class KindTy { 334 Token, 335 Register, 336 Immediate, 337 FPImmediate, 338 SystemRegister, 339 VType, 340 FRM, 341 Fence, 342 Rlist, 343 Spimm, 344 RegReg, 345 } Kind; 346 347 struct RegOp { 348 MCRegister RegNum; 349 bool IsGPRAsFPR; 350 }; 351 352 struct ImmOp { 353 const MCExpr *Val; 354 bool IsRV64; 355 }; 356 357 struct FPImmOp { 358 uint64_t Val; 359 }; 360 361 struct SysRegOp { 362 const char *Data; 363 unsigned Length; 364 unsigned Encoding; 365 // FIXME: Add the Encoding parsed fields as needed for checks, 366 // e.g.: read/write or user/supervisor/machine privileges. 367 }; 368 369 struct VTypeOp { 370 unsigned Val; 371 }; 372 373 struct FRMOp { 374 RISCVFPRndMode::RoundingMode FRM; 375 }; 376 377 struct FenceOp { 378 unsigned Val; 379 }; 380 381 struct RlistOp { 382 unsigned Val; 383 }; 384 385 struct SpimmOp { 386 unsigned Val; 387 }; 388 389 struct RegRegOp { 390 MCRegister Reg1; 391 MCRegister Reg2; 392 }; 393 394 SMLoc StartLoc, EndLoc; 395 union { 396 StringRef Tok; 397 RegOp Reg; 398 ImmOp Imm; 399 FPImmOp FPImm; 400 struct SysRegOp SysReg; 401 struct VTypeOp VType; 402 struct FRMOp FRM; 403 struct FenceOp Fence; 404 struct RlistOp Rlist; 405 struct SpimmOp Spimm; 406 struct RegRegOp RegReg; 407 }; 408 409 RISCVOperand(KindTy K) : Kind(K) {} 410 411 public: 412 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() { 413 Kind = o.Kind; 414 StartLoc = o.StartLoc; 415 EndLoc = o.EndLoc; 416 switch (Kind) { 417 case KindTy::Register: 418 Reg = o.Reg; 419 break; 420 case KindTy::Immediate: 421 Imm = o.Imm; 422 break; 423 case KindTy::FPImmediate: 424 FPImm = o.FPImm; 425 break; 426 case KindTy::Token: 427 Tok = o.Tok; 428 break; 429 case KindTy::SystemRegister: 430 SysReg = o.SysReg; 431 break; 432 case KindTy::VType: 433 VType = o.VType; 434 break; 435 case KindTy::FRM: 436 FRM = o.FRM; 437 break; 438 case KindTy::Fence: 439 Fence = o.Fence; 440 break; 441 case KindTy::Rlist: 442 Rlist = o.Rlist; 443 break; 444 case KindTy::Spimm: 445 Spimm = o.Spimm; 446 break; 447 case KindTy::RegReg: 448 RegReg = o.RegReg; 449 break; 450 } 451 } 452 453 bool isToken() const override { return Kind == KindTy::Token; } 454 bool isReg() const override { return Kind == KindTy::Register; } 455 bool isV0Reg() const { 456 return Kind == KindTy::Register && Reg.RegNum == RISCV::V0; 457 } 458 bool isAnyReg() const { 459 return Kind == KindTy::Register && 460 (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum) || 461 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg.RegNum) || 462 RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg.RegNum)); 463 } 464 bool isAnyRegC() const { 465 return Kind == KindTy::Register && 466 (RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains( 467 Reg.RegNum) || 468 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains( 469 Reg.RegNum)); 470 } 471 bool isImm() const override { return Kind == KindTy::Immediate; } 472 bool isMem() const override { return false; } 473 bool isSystemRegister() const { return Kind == KindTy::SystemRegister; } 474 bool isRegReg() const { return Kind == KindTy::RegReg; } 475 bool isRlist() const { return Kind == KindTy::Rlist; } 476 bool isSpimm() const { return Kind == KindTy::Spimm; } 477 478 bool isGPR() const { 479 return Kind == KindTy::Register && 480 RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum); 481 } 482 483 bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; } 484 485 bool isGPRPair() const { 486 return Kind == KindTy::Register && 487 RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains( 488 Reg.RegNum); 489 } 490 491 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm, 492 RISCVMCExpr::VariantKind &VK) { 493 if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) { 494 VK = RE->getKind(); 495 return RE->evaluateAsConstant(Imm); 496 } 497 498 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) { 499 VK = RISCVMCExpr::VK_RISCV_None; 500 Imm = CE->getValue(); 501 return true; 502 } 503 504 return false; 505 } 506 507 // True if operand is a symbol with no modifiers, or a constant with no 508 // modifiers and isShiftedInt<N-1, 1>(Op). 509 template <int N> bool isBareSimmNLsb0() const { 510 int64_t Imm; 511 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 512 if (!isImm()) 513 return false; 514 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 515 bool IsValid; 516 if (!IsConstantImm) 517 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK); 518 else 519 IsValid = isShiftedInt<N - 1, 1>(Imm); 520 return IsValid && VK == RISCVMCExpr::VK_RISCV_None; 521 } 522 523 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td 524 525 bool isBareSymbol() const { 526 int64_t Imm; 527 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 528 // Must be of 'immediate' type but not a constant. 529 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) 530 return false; 531 return RISCVAsmParser::classifySymbolRef(getImm(), VK) && 532 VK == RISCVMCExpr::VK_RISCV_None; 533 } 534 535 bool isCallSymbol() const { 536 int64_t Imm; 537 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 538 // Must be of 'immediate' type but not a constant. 539 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) 540 return false; 541 return RISCVAsmParser::classifySymbolRef(getImm(), VK) && 542 (VK == RISCVMCExpr::VK_RISCV_CALL || 543 VK == RISCVMCExpr::VK_RISCV_CALL_PLT); 544 } 545 546 bool isPseudoJumpSymbol() const { 547 int64_t Imm; 548 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 549 // Must be of 'immediate' type but not a constant. 550 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) 551 return false; 552 return RISCVAsmParser::classifySymbolRef(getImm(), VK) && 553 VK == RISCVMCExpr::VK_RISCV_CALL; 554 } 555 556 bool isTPRelAddSymbol() const { 557 int64_t Imm; 558 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 559 // Must be of 'immediate' type but not a constant. 560 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) 561 return false; 562 return RISCVAsmParser::classifySymbolRef(getImm(), VK) && 563 VK == RISCVMCExpr::VK_RISCV_TPREL_ADD; 564 } 565 566 bool isTLSDESCCallSymbol() const { 567 int64_t Imm; 568 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 569 // Must be of 'immediate' type but not a constant. 570 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK)) 571 return false; 572 return RISCVAsmParser::classifySymbolRef(getImm(), VK) && 573 VK == RISCVMCExpr::VK_RISCV_TLSDESC_CALL; 574 } 575 576 bool isCSRSystemRegister() const { return isSystemRegister(); } 577 578 bool isVTypeImm(unsigned N) const { 579 int64_t Imm; 580 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 581 if (!isImm()) 582 return false; 583 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 584 return IsConstantImm && isUIntN(N, Imm) && VK == RISCVMCExpr::VK_RISCV_None; 585 } 586 587 // If the last operand of the vsetvli/vsetvli instruction is a constant 588 // expression, KindTy is Immediate. 589 bool isVTypeI10() const { 590 if (Kind == KindTy::Immediate) 591 return isVTypeImm(10); 592 return Kind == KindTy::VType; 593 } 594 bool isVTypeI11() const { 595 if (Kind == KindTy::Immediate) 596 return isVTypeImm(11); 597 return Kind == KindTy::VType; 598 } 599 600 /// Return true if the operand is a valid for the fence instruction e.g. 601 /// ('iorw'). 602 bool isFenceArg() const { return Kind == KindTy::Fence; } 603 604 /// Return true if the operand is a valid floating point rounding mode. 605 bool isFRMArg() const { return Kind == KindTy::FRM; } 606 bool isFRMArgLegacy() const { return Kind == KindTy::FRM; } 607 bool isRTZArg() const { return isFRMArg() && FRM.FRM == RISCVFPRndMode::RTZ; } 608 609 /// Return true if the operand is a valid fli.s floating-point immediate. 610 bool isLoadFPImm() const { 611 if (isImm()) 612 return isUImm5(); 613 if (Kind != KindTy::FPImmediate) 614 return false; 615 int Idx = RISCVLoadFPImm::getLoadFPImm( 616 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst()))); 617 // Don't allow decimal version of the minimum value. It is a different value 618 // for each supported data type. 619 return Idx >= 0 && Idx != 1; 620 } 621 622 bool isImmXLenLI() const { 623 int64_t Imm; 624 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 625 if (!isImm()) 626 return false; 627 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 628 if (VK == RISCVMCExpr::VK_RISCV_LO || 629 VK == RISCVMCExpr::VK_RISCV_PCREL_LO || 630 VK == RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO || 631 VK == RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO) 632 return true; 633 // Given only Imm, ensuring that the actually specified constant is either 634 // a signed or unsigned 64-bit number is unfortunately impossible. 635 if (IsConstantImm) { 636 return VK == RISCVMCExpr::VK_RISCV_None && 637 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm))); 638 } 639 640 return RISCVAsmParser::isSymbolDiff(getImm()); 641 } 642 643 bool isImmXLenLI_Restricted() const { 644 int64_t Imm; 645 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 646 if (!isImm()) 647 return false; 648 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 649 // 'la imm' supports constant immediates only. 650 return IsConstantImm && (VK == RISCVMCExpr::VK_RISCV_None) && 651 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm))); 652 } 653 654 bool isUImmLog2XLen() const { 655 int64_t Imm; 656 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 657 if (!isImm()) 658 return false; 659 if (!evaluateConstantImm(getImm(), Imm, VK) || 660 VK != RISCVMCExpr::VK_RISCV_None) 661 return false; 662 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm); 663 } 664 665 bool isUImmLog2XLenNonZero() const { 666 int64_t Imm; 667 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 668 if (!isImm()) 669 return false; 670 if (!evaluateConstantImm(getImm(), Imm, VK) || 671 VK != RISCVMCExpr::VK_RISCV_None) 672 return false; 673 if (Imm == 0) 674 return false; 675 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm); 676 } 677 678 bool isUImmLog2XLenHalf() const { 679 int64_t Imm; 680 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 681 if (!isImm()) 682 return false; 683 if (!evaluateConstantImm(getImm(), Imm, VK) || 684 VK != RISCVMCExpr::VK_RISCV_None) 685 return false; 686 return (isRV64Imm() && isUInt<5>(Imm)) || isUInt<4>(Imm); 687 } 688 689 template <unsigned N> bool IsUImm() const { 690 int64_t Imm; 691 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 692 if (!isImm()) 693 return false; 694 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 695 return IsConstantImm && isUInt<N>(Imm) && VK == RISCVMCExpr::VK_RISCV_None; 696 } 697 698 bool isUImm1() const { return IsUImm<1>(); } 699 bool isUImm2() const { return IsUImm<2>(); } 700 bool isUImm3() const { return IsUImm<3>(); } 701 bool isUImm4() const { return IsUImm<4>(); } 702 bool isUImm5() const { return IsUImm<5>(); } 703 bool isUImm6() const { return IsUImm<6>(); } 704 bool isUImm7() const { return IsUImm<7>(); } 705 bool isUImm8() const { return IsUImm<8>(); } 706 bool isUImm16() const { return IsUImm<16>(); } 707 bool isUImm20() const { return IsUImm<20>(); } 708 bool isUImm32() const { return IsUImm<32>(); } 709 710 bool isUImm8GE32() const { 711 int64_t Imm; 712 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 713 if (!isImm()) 714 return false; 715 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 716 return IsConstantImm && isUInt<8>(Imm) && Imm >= 32 && 717 VK == RISCVMCExpr::VK_RISCV_None; 718 } 719 720 bool isRnumArg() const { 721 int64_t Imm; 722 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 723 if (!isImm()) 724 return false; 725 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 726 return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(10) && 727 VK == RISCVMCExpr::VK_RISCV_None; 728 } 729 730 bool isRnumArg_0_7() const { 731 int64_t Imm; 732 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 733 if (!isImm()) 734 return false; 735 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 736 return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(7) && 737 VK == RISCVMCExpr::VK_RISCV_None; 738 } 739 740 bool isRnumArg_1_10() const { 741 int64_t Imm; 742 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 743 if (!isImm()) 744 return false; 745 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 746 return IsConstantImm && Imm >= INT64_C(1) && Imm <= INT64_C(10) && 747 VK == RISCVMCExpr::VK_RISCV_None; 748 } 749 750 bool isRnumArg_2_14() const { 751 int64_t Imm; 752 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 753 if (!isImm()) 754 return false; 755 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 756 return IsConstantImm && Imm >= INT64_C(2) && Imm <= INT64_C(14) && 757 VK == RISCVMCExpr::VK_RISCV_None; 758 } 759 760 bool isSImm5() const { 761 if (!isImm()) 762 return false; 763 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 764 int64_t Imm; 765 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 766 return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) && 767 VK == RISCVMCExpr::VK_RISCV_None; 768 } 769 770 bool isSImm6() const { 771 if (!isImm()) 772 return false; 773 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 774 int64_t Imm; 775 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 776 return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) && 777 VK == RISCVMCExpr::VK_RISCV_None; 778 } 779 780 bool isSImm6NonZero() const { 781 if (!isImm()) 782 return false; 783 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 784 int64_t Imm; 785 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 786 return IsConstantImm && Imm != 0 && 787 isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) && 788 VK == RISCVMCExpr::VK_RISCV_None; 789 } 790 791 bool isCLUIImm() const { 792 if (!isImm()) 793 return false; 794 int64_t Imm; 795 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 796 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 797 return IsConstantImm && (Imm != 0) && 798 (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) && 799 VK == RISCVMCExpr::VK_RISCV_None; 800 } 801 802 bool isUImm2Lsb0() const { 803 if (!isImm()) 804 return false; 805 int64_t Imm; 806 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 807 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 808 return IsConstantImm && isShiftedUInt<1, 1>(Imm) && 809 VK == RISCVMCExpr::VK_RISCV_None; 810 } 811 812 bool isUImm5Lsb0() const { 813 if (!isImm()) 814 return false; 815 int64_t Imm; 816 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 817 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 818 return IsConstantImm && isShiftedUInt<4, 1>(Imm) && 819 VK == RISCVMCExpr::VK_RISCV_None; 820 } 821 822 bool isUImm6Lsb0() const { 823 if (!isImm()) 824 return false; 825 int64_t Imm; 826 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 827 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 828 return IsConstantImm && isShiftedUInt<5, 1>(Imm) && 829 VK == RISCVMCExpr::VK_RISCV_None; 830 } 831 832 bool isUImm7Lsb00() const { 833 if (!isImm()) 834 return false; 835 int64_t Imm; 836 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 837 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 838 return IsConstantImm && isShiftedUInt<5, 2>(Imm) && 839 VK == RISCVMCExpr::VK_RISCV_None; 840 } 841 842 bool isUImm8Lsb00() const { 843 if (!isImm()) 844 return false; 845 int64_t Imm; 846 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 847 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 848 return IsConstantImm && isShiftedUInt<6, 2>(Imm) && 849 VK == RISCVMCExpr::VK_RISCV_None; 850 } 851 852 bool isUImm8Lsb000() const { 853 if (!isImm()) 854 return false; 855 int64_t Imm; 856 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 857 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 858 return IsConstantImm && isShiftedUInt<5, 3>(Imm) && 859 VK == RISCVMCExpr::VK_RISCV_None; 860 } 861 862 bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); } 863 864 bool isUImm9Lsb000() const { 865 if (!isImm()) 866 return false; 867 int64_t Imm; 868 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 869 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 870 return IsConstantImm && isShiftedUInt<6, 3>(Imm) && 871 VK == RISCVMCExpr::VK_RISCV_None; 872 } 873 874 bool isUImm10Lsb00NonZero() const { 875 if (!isImm()) 876 return false; 877 int64_t Imm; 878 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 879 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 880 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) && 881 VK == RISCVMCExpr::VK_RISCV_None; 882 } 883 884 // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits. 885 // This allows writing 'addi a0, a0, 0xffffffff'. 886 static int64_t fixImmediateForRV32(int64_t Imm, bool IsRV64Imm) { 887 if (IsRV64Imm || !isUInt<32>(Imm)) 888 return Imm; 889 return SignExtend64<32>(Imm); 890 } 891 892 bool isSImm12() const { 893 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 894 int64_t Imm; 895 bool IsValid; 896 if (!isImm()) 897 return false; 898 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 899 if (!IsConstantImm) 900 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK); 901 else 902 IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm())); 903 return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) || 904 VK == RISCVMCExpr::VK_RISCV_LO || 905 VK == RISCVMCExpr::VK_RISCV_PCREL_LO || 906 VK == RISCVMCExpr::VK_RISCV_TPREL_LO || 907 VK == RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO || 908 VK == RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO); 909 } 910 911 bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); } 912 913 bool isSImm12Lsb00000() const { 914 if (!isImm()) 915 return false; 916 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 917 int64_t Imm; 918 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 919 return IsConstantImm && isShiftedInt<7, 5>(Imm) && 920 VK == RISCVMCExpr::VK_RISCV_None; 921 } 922 923 bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); } 924 925 bool isSImm10Lsb0000NonZero() const { 926 if (!isImm()) 927 return false; 928 int64_t Imm; 929 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 930 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 931 return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) && 932 VK == RISCVMCExpr::VK_RISCV_None; 933 } 934 935 bool isUImm20LUI() const { 936 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 937 int64_t Imm; 938 bool IsValid; 939 if (!isImm()) 940 return false; 941 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 942 if (!IsConstantImm) { 943 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK); 944 return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI || 945 VK == RISCVMCExpr::VK_RISCV_TPREL_HI); 946 } else { 947 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None || 948 VK == RISCVMCExpr::VK_RISCV_HI || 949 VK == RISCVMCExpr::VK_RISCV_TPREL_HI); 950 } 951 } 952 953 bool isUImm20AUIPC() const { 954 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 955 int64_t Imm; 956 bool IsValid; 957 if (!isImm()) 958 return false; 959 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 960 if (!IsConstantImm) { 961 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK); 962 return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI || 963 VK == RISCVMCExpr::VK_RISCV_GOT_HI || 964 VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI || 965 VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI || 966 VK == RISCVMCExpr::VK_RISCV_TLSDESC_HI); 967 } 968 969 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None || 970 VK == RISCVMCExpr::VK_RISCV_PCREL_HI || 971 VK == RISCVMCExpr::VK_RISCV_GOT_HI || 972 VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI || 973 VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI || 974 VK == RISCVMCExpr::VK_RISCV_TLSDESC_HI); 975 } 976 977 bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); } 978 979 bool isImmZero() const { 980 if (!isImm()) 981 return false; 982 int64_t Imm; 983 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 984 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 985 return IsConstantImm && (Imm == 0) && VK == RISCVMCExpr::VK_RISCV_None; 986 } 987 988 bool isSImm5Plus1() const { 989 if (!isImm()) 990 return false; 991 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 992 int64_t Imm; 993 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); 994 return IsConstantImm && 995 isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) && 996 VK == RISCVMCExpr::VK_RISCV_None; 997 } 998 999 /// getStartLoc - Gets location of the first token of this operand 1000 SMLoc getStartLoc() const override { return StartLoc; } 1001 /// getEndLoc - Gets location of the last token of this operand 1002 SMLoc getEndLoc() const override { return EndLoc; } 1003 /// True if this operand is for an RV64 instruction 1004 bool isRV64Imm() const { 1005 assert(Kind == KindTy::Immediate && "Invalid type access!"); 1006 return Imm.IsRV64; 1007 } 1008 1009 MCRegister getReg() const override { 1010 assert(Kind == KindTy::Register && "Invalid type access!"); 1011 return Reg.RegNum; 1012 } 1013 1014 StringRef getSysReg() const { 1015 assert(Kind == KindTy::SystemRegister && "Invalid type access!"); 1016 return StringRef(SysReg.Data, SysReg.Length); 1017 } 1018 1019 const MCExpr *getImm() const { 1020 assert(Kind == KindTy::Immediate && "Invalid type access!"); 1021 return Imm.Val; 1022 } 1023 1024 uint64_t getFPConst() const { 1025 assert(Kind == KindTy::FPImmediate && "Invalid type access!"); 1026 return FPImm.Val; 1027 } 1028 1029 StringRef getToken() const { 1030 assert(Kind == KindTy::Token && "Invalid type access!"); 1031 return Tok; 1032 } 1033 1034 unsigned getVType() const { 1035 assert(Kind == KindTy::VType && "Invalid type access!"); 1036 return VType.Val; 1037 } 1038 1039 RISCVFPRndMode::RoundingMode getFRM() const { 1040 assert(Kind == KindTy::FRM && "Invalid type access!"); 1041 return FRM.FRM; 1042 } 1043 1044 unsigned getFence() const { 1045 assert(Kind == KindTy::Fence && "Invalid type access!"); 1046 return Fence.Val; 1047 } 1048 1049 void print(raw_ostream &OS) const override { 1050 auto RegName = [](MCRegister Reg) { 1051 if (Reg) 1052 return RISCVInstPrinter::getRegisterName(Reg); 1053 else 1054 return "noreg"; 1055 }; 1056 1057 switch (Kind) { 1058 case KindTy::Immediate: 1059 OS << *getImm(); 1060 break; 1061 case KindTy::FPImmediate: 1062 break; 1063 case KindTy::Register: 1064 OS << "<register " << RegName(getReg()) << ">"; 1065 break; 1066 case KindTy::Token: 1067 OS << "'" << getToken() << "'"; 1068 break; 1069 case KindTy::SystemRegister: 1070 OS << "<sysreg: " << getSysReg() << '>'; 1071 break; 1072 case KindTy::VType: 1073 OS << "<vtype: "; 1074 RISCVVType::printVType(getVType(), OS); 1075 OS << '>'; 1076 break; 1077 case KindTy::FRM: 1078 OS << "<frm: "; 1079 roundingModeToString(getFRM()); 1080 OS << '>'; 1081 break; 1082 case KindTy::Fence: 1083 OS << "<fence: "; 1084 OS << getFence(); 1085 OS << '>'; 1086 break; 1087 case KindTy::Rlist: 1088 OS << "<rlist: "; 1089 RISCVZC::printRlist(Rlist.Val, OS); 1090 OS << '>'; 1091 break; 1092 case KindTy::Spimm: 1093 OS << "<Spimm: "; 1094 OS << Spimm.Val; 1095 OS << '>'; 1096 break; 1097 case KindTy::RegReg: 1098 OS << "<RegReg: Reg1 " << RegName(RegReg.Reg1); 1099 OS << " Reg2 " << RegName(RegReg.Reg2); 1100 break; 1101 } 1102 } 1103 1104 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) { 1105 auto Op = std::make_unique<RISCVOperand>(KindTy::Token); 1106 Op->Tok = Str; 1107 Op->StartLoc = S; 1108 Op->EndLoc = S; 1109 return Op; 1110 } 1111 1112 static std::unique_ptr<RISCVOperand> 1113 createReg(unsigned RegNo, SMLoc S, SMLoc E, bool IsGPRAsFPR = false) { 1114 auto Op = std::make_unique<RISCVOperand>(KindTy::Register); 1115 Op->Reg.RegNum = RegNo; 1116 Op->Reg.IsGPRAsFPR = IsGPRAsFPR; 1117 Op->StartLoc = S; 1118 Op->EndLoc = E; 1119 return Op; 1120 } 1121 1122 static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S, 1123 SMLoc E, bool IsRV64) { 1124 auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate); 1125 Op->Imm.Val = Val; 1126 Op->Imm.IsRV64 = IsRV64; 1127 Op->StartLoc = S; 1128 Op->EndLoc = E; 1129 return Op; 1130 } 1131 1132 static std::unique_ptr<RISCVOperand> createFPImm(uint64_t Val, SMLoc S) { 1133 auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate); 1134 Op->FPImm.Val = Val; 1135 Op->StartLoc = S; 1136 Op->EndLoc = S; 1137 return Op; 1138 } 1139 1140 static std::unique_ptr<RISCVOperand> createSysReg(StringRef Str, SMLoc S, 1141 unsigned Encoding) { 1142 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister); 1143 Op->SysReg.Data = Str.data(); 1144 Op->SysReg.Length = Str.size(); 1145 Op->SysReg.Encoding = Encoding; 1146 Op->StartLoc = S; 1147 Op->EndLoc = S; 1148 return Op; 1149 } 1150 1151 static std::unique_ptr<RISCVOperand> 1152 createFRMArg(RISCVFPRndMode::RoundingMode FRM, SMLoc S) { 1153 auto Op = std::make_unique<RISCVOperand>(KindTy::FRM); 1154 Op->FRM.FRM = FRM; 1155 Op->StartLoc = S; 1156 Op->EndLoc = S; 1157 return Op; 1158 } 1159 1160 static std::unique_ptr<RISCVOperand> createFenceArg(unsigned Val, SMLoc S) { 1161 auto Op = std::make_unique<RISCVOperand>(KindTy::Fence); 1162 Op->Fence.Val = Val; 1163 Op->StartLoc = S; 1164 Op->EndLoc = S; 1165 return Op; 1166 } 1167 1168 static std::unique_ptr<RISCVOperand> createVType(unsigned VTypeI, SMLoc S) { 1169 auto Op = std::make_unique<RISCVOperand>(KindTy::VType); 1170 Op->VType.Val = VTypeI; 1171 Op->StartLoc = S; 1172 Op->EndLoc = S; 1173 return Op; 1174 } 1175 1176 static std::unique_ptr<RISCVOperand> createRlist(unsigned RlistEncode, 1177 SMLoc S) { 1178 auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist); 1179 Op->Rlist.Val = RlistEncode; 1180 Op->StartLoc = S; 1181 return Op; 1182 } 1183 1184 static std::unique_ptr<RISCVOperand> createRegReg(unsigned Reg1No, 1185 unsigned Reg2No, SMLoc S) { 1186 auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg); 1187 Op->RegReg.Reg1 = Reg1No; 1188 Op->RegReg.Reg2 = Reg2No; 1189 Op->StartLoc = S; 1190 Op->EndLoc = S; 1191 return Op; 1192 } 1193 1194 static std::unique_ptr<RISCVOperand> createSpimm(unsigned Spimm, SMLoc S) { 1195 auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm); 1196 Op->Spimm.Val = Spimm; 1197 Op->StartLoc = S; 1198 return Op; 1199 } 1200 1201 static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) { 1202 assert(Expr && "Expr shouldn't be null!"); 1203 int64_t Imm = 0; 1204 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 1205 bool IsConstant = evaluateConstantImm(Expr, Imm, VK); 1206 1207 if (IsConstant) 1208 Inst.addOperand( 1209 MCOperand::createImm(fixImmediateForRV32(Imm, IsRV64Imm))); 1210 else 1211 Inst.addOperand(MCOperand::createExpr(Expr)); 1212 } 1213 1214 // Used by the TableGen Code 1215 void addRegOperands(MCInst &Inst, unsigned N) const { 1216 assert(N == 1 && "Invalid number of operands!"); 1217 Inst.addOperand(MCOperand::createReg(getReg())); 1218 } 1219 1220 void addImmOperands(MCInst &Inst, unsigned N) const { 1221 assert(N == 1 && "Invalid number of operands!"); 1222 addExpr(Inst, getImm(), isRV64Imm()); 1223 } 1224 1225 void addFPImmOperands(MCInst &Inst, unsigned N) const { 1226 assert(N == 1 && "Invalid number of operands!"); 1227 if (isImm()) { 1228 addExpr(Inst, getImm(), isRV64Imm()); 1229 return; 1230 } 1231 1232 int Imm = RISCVLoadFPImm::getLoadFPImm( 1233 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst()))); 1234 Inst.addOperand(MCOperand::createImm(Imm)); 1235 } 1236 1237 void addFenceArgOperands(MCInst &Inst, unsigned N) const { 1238 assert(N == 1 && "Invalid number of operands!"); 1239 Inst.addOperand(MCOperand::createImm(Fence.Val)); 1240 } 1241 1242 void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const { 1243 assert(N == 1 && "Invalid number of operands!"); 1244 Inst.addOperand(MCOperand::createImm(SysReg.Encoding)); 1245 } 1246 1247 // Support non-canonical syntax: 1248 // "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc" 1249 // "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)" 1250 void addVTypeIOperands(MCInst &Inst, unsigned N) const { 1251 assert(N == 1 && "Invalid number of operands!"); 1252 int64_t Imm = 0; 1253 if (Kind == KindTy::Immediate) { 1254 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; 1255 [[maybe_unused]] bool IsConstantImm = 1256 evaluateConstantImm(getImm(), Imm, VK); 1257 assert(IsConstantImm && "Invalid VTypeI Operand!"); 1258 } else { 1259 Imm = getVType(); 1260 } 1261 Inst.addOperand(MCOperand::createImm(Imm)); 1262 } 1263 1264 void addRlistOperands(MCInst &Inst, unsigned N) const { 1265 assert(N == 1 && "Invalid number of operands!"); 1266 Inst.addOperand(MCOperand::createImm(Rlist.Val)); 1267 } 1268 1269 void addRegRegOperands(MCInst &Inst, unsigned N) const { 1270 assert(N == 2 && "Invalid number of operands!"); 1271 Inst.addOperand(MCOperand::createReg(RegReg.Reg1)); 1272 Inst.addOperand(MCOperand::createReg(RegReg.Reg2)); 1273 } 1274 1275 void addSpimmOperands(MCInst &Inst, unsigned N) const { 1276 assert(N == 1 && "Invalid number of operands!"); 1277 Inst.addOperand(MCOperand::createImm(Spimm.Val)); 1278 } 1279 1280 void addFRMArgOperands(MCInst &Inst, unsigned N) const { 1281 assert(N == 1 && "Invalid number of operands!"); 1282 Inst.addOperand(MCOperand::createImm(getFRM())); 1283 } 1284 }; 1285 } // end anonymous namespace. 1286 1287 #define GET_REGISTER_MATCHER 1288 #define GET_SUBTARGET_FEATURE_NAME 1289 #define GET_MATCHER_IMPLEMENTATION 1290 #define GET_MNEMONIC_SPELL_CHECKER 1291 #include "RISCVGenAsmMatcher.inc" 1292 1293 static MCRegister convertFPR64ToFPR16(MCRegister Reg) { 1294 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register"); 1295 return Reg - RISCV::F0_D + RISCV::F0_H; 1296 } 1297 1298 static MCRegister convertFPR64ToFPR32(MCRegister Reg) { 1299 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register"); 1300 return Reg - RISCV::F0_D + RISCV::F0_F; 1301 } 1302 1303 static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg, 1304 unsigned Kind) { 1305 unsigned RegClassID; 1306 if (Kind == MCK_VRM2) 1307 RegClassID = RISCV::VRM2RegClassID; 1308 else if (Kind == MCK_VRM4) 1309 RegClassID = RISCV::VRM4RegClassID; 1310 else if (Kind == MCK_VRM8) 1311 RegClassID = RISCV::VRM8RegClassID; 1312 else 1313 return 0; 1314 return RI.getMatchingSuperReg(Reg, RISCV::sub_vrm1_0, 1315 &RISCVMCRegisterClasses[RegClassID]); 1316 } 1317 1318 unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, 1319 unsigned Kind) { 1320 RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp); 1321 if (!Op.isReg()) 1322 return Match_InvalidOperand; 1323 1324 MCRegister Reg = Op.getReg(); 1325 bool IsRegFPR64 = 1326 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg); 1327 bool IsRegFPR64C = 1328 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg); 1329 bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg); 1330 1331 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the 1332 // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary. 1333 if ((IsRegFPR64 && Kind == MCK_FPR32) || 1334 (IsRegFPR64C && Kind == MCK_FPR32C)) { 1335 Op.Reg.RegNum = convertFPR64ToFPR32(Reg); 1336 return Match_Success; 1337 } 1338 // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the 1339 // register from FPR64 to FPR16 if necessary. 1340 if (IsRegFPR64 && Kind == MCK_FPR16) { 1341 Op.Reg.RegNum = convertFPR64ToFPR16(Reg); 1342 return Match_Success; 1343 } 1344 // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce 1345 // the register from VR to VRM2/VRM4/VRM8 if necessary. 1346 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) { 1347 Op.Reg.RegNum = convertVRToVRMx(*getContext().getRegisterInfo(), Reg, Kind); 1348 if (Op.Reg.RegNum == 0) 1349 return Match_InvalidOperand; 1350 return Match_Success; 1351 } 1352 return Match_InvalidOperand; 1353 } 1354 1355 unsigned RISCVAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 1356 const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); 1357 1358 for (unsigned I = 0; I < MCID.NumOperands; ++I) { 1359 if (MCID.operands()[I].RegClass == RISCV::GPRPairRegClassID) { 1360 const auto &Op = Inst.getOperand(I); 1361 assert(Op.isReg()); 1362 1363 MCRegister Reg = Op.getReg(); 1364 if (RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(Reg)) 1365 continue; 1366 1367 // FIXME: We should form a paired register during parsing/matching. 1368 if (((Reg.id() - RISCV::X0) & 1) != 0) 1369 return Match_RequiresEvenGPRs; 1370 } 1371 } 1372 1373 return Match_Success; 1374 } 1375 1376 bool RISCVAsmParser::generateImmOutOfRangeError( 1377 SMLoc ErrorLoc, int64_t Lower, int64_t Upper, 1378 const Twine &Msg = "immediate must be an integer in the range") { 1379 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); 1380 } 1381 1382 bool RISCVAsmParser::generateImmOutOfRangeError( 1383 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper, 1384 const Twine &Msg = "immediate must be an integer in the range") { 1385 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1386 return generateImmOutOfRangeError(ErrorLoc, Lower, Upper, Msg); 1387 } 1388 1389 bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 1390 OperandVector &Operands, 1391 MCStreamer &Out, 1392 uint64_t &ErrorInfo, 1393 bool MatchingInlineAsm) { 1394 MCInst Inst; 1395 FeatureBitset MissingFeatures; 1396 1397 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures, 1398 MatchingInlineAsm); 1399 switch (Result) { 1400 default: 1401 break; 1402 case Match_Success: 1403 if (validateInstruction(Inst, Operands)) 1404 return true; 1405 return processInstruction(Inst, IDLoc, Operands, Out); 1406 case Match_MissingFeature: { 1407 assert(MissingFeatures.any() && "Unknown missing features!"); 1408 bool FirstFeature = true; 1409 std::string Msg = "instruction requires the following:"; 1410 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) { 1411 if (MissingFeatures[i]) { 1412 Msg += FirstFeature ? " " : ", "; 1413 Msg += getSubtargetFeatureName(i); 1414 FirstFeature = false; 1415 } 1416 } 1417 return Error(IDLoc, Msg); 1418 } 1419 case Match_MnemonicFail: { 1420 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); 1421 std::string Suggestion = RISCVMnemonicSpellCheck( 1422 ((RISCVOperand &)*Operands[0]).getToken(), FBS, 0); 1423 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion); 1424 } 1425 case Match_InvalidOperand: { 1426 SMLoc ErrorLoc = IDLoc; 1427 if (ErrorInfo != ~0ULL) { 1428 if (ErrorInfo >= Operands.size()) 1429 return Error(ErrorLoc, "too few operands for instruction"); 1430 1431 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1432 if (ErrorLoc == SMLoc()) 1433 ErrorLoc = IDLoc; 1434 } 1435 return Error(ErrorLoc, "invalid operand for instruction"); 1436 } 1437 } 1438 1439 // Handle the case when the error message is of specific type 1440 // other than the generic Match_InvalidOperand, and the 1441 // corresponding operand is missing. 1442 if (Result > FIRST_TARGET_MATCH_RESULT_TY) { 1443 SMLoc ErrorLoc = IDLoc; 1444 if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size()) 1445 return Error(ErrorLoc, "too few operands for instruction"); 1446 } 1447 1448 switch (Result) { 1449 default: 1450 break; 1451 case Match_RequiresEvenGPRs: 1452 return Error(IDLoc, 1453 "double precision floating point operands must use even " 1454 "numbered X register"); 1455 case Match_InvalidImmXLenLI: 1456 if (isRV64()) { 1457 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1458 return Error(ErrorLoc, "operand must be a constant 64-bit integer"); 1459 } 1460 return generateImmOutOfRangeError(Operands, ErrorInfo, 1461 std::numeric_limits<int32_t>::min(), 1462 std::numeric_limits<uint32_t>::max()); 1463 case Match_InvalidImmXLenLI_Restricted: 1464 if (isRV64()) { 1465 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1466 return Error(ErrorLoc, "operand either must be a constant 64-bit integer " 1467 "or a bare symbol name"); 1468 } 1469 return generateImmOutOfRangeError( 1470 Operands, ErrorInfo, std::numeric_limits<int32_t>::min(), 1471 std::numeric_limits<uint32_t>::max(), 1472 "operand either must be a bare symbol name or an immediate integer in " 1473 "the range"); 1474 case Match_InvalidImmZero: { 1475 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1476 return Error(ErrorLoc, "immediate must be zero"); 1477 } 1478 case Match_InvalidUImmLog2XLen: 1479 if (isRV64()) 1480 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1); 1481 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); 1482 case Match_InvalidUImmLog2XLenNonZero: 1483 if (isRV64()) 1484 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1); 1485 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1); 1486 case Match_InvalidUImmLog2XLenHalf: 1487 if (isRV64()) 1488 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); 1489 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1); 1490 case Match_InvalidUImm1: 1491 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1); 1492 case Match_InvalidUImm2: 1493 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1); 1494 case Match_InvalidUImm2Lsb0: 1495 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 2, 1496 "immediate must be one of"); 1497 case Match_InvalidUImm3: 1498 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1); 1499 case Match_InvalidUImm4: 1500 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1); 1501 case Match_InvalidUImm5: 1502 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1); 1503 case Match_InvalidUImm6: 1504 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1); 1505 case Match_InvalidUImm7: 1506 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1); 1507 case Match_InvalidUImm8: 1508 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1); 1509 case Match_InvalidUImm8GE32: 1510 return generateImmOutOfRangeError(Operands, ErrorInfo, 32, (1 << 8) - 1); 1511 case Match_InvalidSImm5: 1512 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4), 1513 (1 << 4) - 1); 1514 case Match_InvalidSImm6: 1515 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5), 1516 (1 << 5) - 1); 1517 case Match_InvalidSImm6NonZero: 1518 return generateImmOutOfRangeError( 1519 Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1, 1520 "immediate must be non-zero in the range"); 1521 case Match_InvalidCLUIImm: 1522 return generateImmOutOfRangeError( 1523 Operands, ErrorInfo, 1, (1 << 5) - 1, 1524 "immediate must be in [0xfffe0, 0xfffff] or"); 1525 case Match_InvalidUImm5Lsb0: 1526 return generateImmOutOfRangeError( 1527 Operands, ErrorInfo, 0, (1 << 5) - 2, 1528 "immediate must be a multiple of 2 bytes in the range"); 1529 case Match_InvalidUImm6Lsb0: 1530 return generateImmOutOfRangeError( 1531 Operands, ErrorInfo, 0, (1 << 6) - 2, 1532 "immediate must be a multiple of 2 bytes in the range"); 1533 case Match_InvalidUImm7Lsb00: 1534 return generateImmOutOfRangeError( 1535 Operands, ErrorInfo, 0, (1 << 7) - 4, 1536 "immediate must be a multiple of 4 bytes in the range"); 1537 case Match_InvalidUImm8Lsb00: 1538 return generateImmOutOfRangeError( 1539 Operands, ErrorInfo, 0, (1 << 8) - 4, 1540 "immediate must be a multiple of 4 bytes in the range"); 1541 case Match_InvalidUImm8Lsb000: 1542 return generateImmOutOfRangeError( 1543 Operands, ErrorInfo, 0, (1 << 8) - 8, 1544 "immediate must be a multiple of 8 bytes in the range"); 1545 case Match_InvalidSImm9Lsb0: 1546 return generateImmOutOfRangeError( 1547 Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2, 1548 "immediate must be a multiple of 2 bytes in the range"); 1549 case Match_InvalidUImm9Lsb000: 1550 return generateImmOutOfRangeError( 1551 Operands, ErrorInfo, 0, (1 << 9) - 8, 1552 "immediate must be a multiple of 8 bytes in the range"); 1553 case Match_InvalidUImm10Lsb00NonZero: 1554 return generateImmOutOfRangeError( 1555 Operands, ErrorInfo, 4, (1 << 10) - 4, 1556 "immediate must be a multiple of 4 bytes in the range"); 1557 case Match_InvalidSImm10Lsb0000NonZero: 1558 return generateImmOutOfRangeError( 1559 Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16, 1560 "immediate must be a multiple of 16 bytes and non-zero in the range"); 1561 case Match_InvalidSImm12: 1562 return generateImmOutOfRangeError( 1563 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1, 1564 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an " 1565 "integer in the range"); 1566 case Match_InvalidSImm12Lsb0: 1567 return generateImmOutOfRangeError( 1568 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2, 1569 "immediate must be a multiple of 2 bytes in the range"); 1570 case Match_InvalidSImm12Lsb00000: 1571 return generateImmOutOfRangeError( 1572 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 32, 1573 "immediate must be a multiple of 32 bytes in the range"); 1574 case Match_InvalidSImm13Lsb0: 1575 return generateImmOutOfRangeError( 1576 Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2, 1577 "immediate must be a multiple of 2 bytes in the range"); 1578 case Match_InvalidUImm20LUI: 1579 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1, 1580 "operand must be a symbol with " 1581 "%hi/%tprel_hi modifier or an integer in " 1582 "the range"); 1583 case Match_InvalidUImm20: 1584 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1); 1585 case Match_InvalidUImm20AUIPC: 1586 return generateImmOutOfRangeError( 1587 Operands, ErrorInfo, 0, (1 << 20) - 1, 1588 "operand must be a symbol with a " 1589 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or " 1590 "an integer in the range"); 1591 case Match_InvalidSImm21Lsb0JAL: 1592 return generateImmOutOfRangeError( 1593 Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2, 1594 "immediate must be a multiple of 2 bytes in the range"); 1595 case Match_InvalidCSRSystemRegister: { 1596 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1, 1597 "operand must be a valid system register " 1598 "name or an integer in the range"); 1599 } 1600 case Match_InvalidLoadFPImm: { 1601 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1602 return Error(ErrorLoc, "operand must be a valid floating-point constant"); 1603 } 1604 case Match_InvalidBareSymbol: { 1605 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1606 return Error(ErrorLoc, "operand must be a bare symbol name"); 1607 } 1608 case Match_InvalidPseudoJumpSymbol: { 1609 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1610 return Error(ErrorLoc, "operand must be a valid jump target"); 1611 } 1612 case Match_InvalidCallSymbol: { 1613 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1614 return Error(ErrorLoc, "operand must be a bare symbol name"); 1615 } 1616 case Match_InvalidTPRelAddSymbol: { 1617 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1618 return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier"); 1619 } 1620 case Match_InvalidTLSDESCCallSymbol: { 1621 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1622 return Error(ErrorLoc, 1623 "operand must be a symbol with %tlsdesc_call modifier"); 1624 } 1625 case Match_InvalidRTZArg: { 1626 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1627 return Error(ErrorLoc, "operand must be 'rtz' floating-point rounding mode"); 1628 } 1629 case Match_InvalidVTypeI: { 1630 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1631 return generateVTypeError(ErrorLoc); 1632 } 1633 case Match_InvalidVMaskRegister: { 1634 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1635 return Error(ErrorLoc, "operand must be v0.t"); 1636 } 1637 case Match_InvalidSImm5Plus1: { 1638 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4) + 1, 1639 (1 << 4), 1640 "immediate must be in the range"); 1641 } 1642 case Match_InvalidRlist: { 1643 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1644 return Error( 1645 ErrorLoc, 1646 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}"); 1647 } 1648 case Match_InvalidStackAdj: { 1649 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1650 return Error( 1651 ErrorLoc, 1652 "stack adjustment is invalid for this instruction and register list; " 1653 "refer to Zc spec for a detailed range of stack adjustment"); 1654 } 1655 case Match_InvalidRnumArg: { 1656 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10); 1657 } 1658 case Match_InvalidRegReg: { 1659 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); 1660 return Error(ErrorLoc, "operands must be register and register"); 1661 } 1662 } 1663 1664 llvm_unreachable("Unknown match type detected!"); 1665 } 1666 1667 // Attempts to match Name as a register (either using the default name or 1668 // alternative ABI names), setting RegNo to the matching register. Upon 1669 // failure, returns a non-valid MCRegister. If IsRVE, then registers x16-x31 1670 // will be rejected. 1671 MCRegister RISCVAsmParser::matchRegisterNameHelper(StringRef Name) const { 1672 MCRegister Reg = MatchRegisterName(Name); 1673 // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial 1674 // match always matches the 64-bit variant, and not the 16/32-bit one. 1675 assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H)); 1676 assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F)); 1677 // The default FPR register class is based on the tablegen enum ordering. 1678 static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated"); 1679 static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated"); 1680 if (!Reg) 1681 Reg = MatchRegisterAltName(Name); 1682 if (isRVE() && Reg >= RISCV::X16 && Reg <= RISCV::X31) 1683 Reg = RISCV::NoRegister; 1684 return Reg; 1685 } 1686 1687 bool RISCVAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, 1688 SMLoc &EndLoc) { 1689 if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess()) 1690 return Error(StartLoc, "invalid register name"); 1691 return false; 1692 } 1693 1694 ParseStatus RISCVAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, 1695 SMLoc &EndLoc) { 1696 const AsmToken &Tok = getParser().getTok(); 1697 StartLoc = Tok.getLoc(); 1698 EndLoc = Tok.getEndLoc(); 1699 StringRef Name = getLexer().getTok().getIdentifier(); 1700 1701 Reg = matchRegisterNameHelper(Name); 1702 if (!Reg) 1703 return ParseStatus::NoMatch; 1704 1705 getParser().Lex(); // Eat identifier token. 1706 return ParseStatus::Success; 1707 } 1708 1709 ParseStatus RISCVAsmParser::parseRegister(OperandVector &Operands, 1710 bool AllowParens) { 1711 SMLoc FirstS = getLoc(); 1712 bool HadParens = false; 1713 AsmToken LParen; 1714 1715 // If this is an LParen and a parenthesised register name is allowed, parse it 1716 // atomically. 1717 if (AllowParens && getLexer().is(AsmToken::LParen)) { 1718 AsmToken Buf[2]; 1719 size_t ReadCount = getLexer().peekTokens(Buf); 1720 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) { 1721 HadParens = true; 1722 LParen = getParser().getTok(); 1723 getParser().Lex(); // Eat '(' 1724 } 1725 } 1726 1727 switch (getLexer().getKind()) { 1728 default: 1729 if (HadParens) 1730 getLexer().UnLex(LParen); 1731 return ParseStatus::NoMatch; 1732 case AsmToken::Identifier: 1733 StringRef Name = getLexer().getTok().getIdentifier(); 1734 MCRegister RegNo = matchRegisterNameHelper(Name); 1735 1736 if (!RegNo) { 1737 if (HadParens) 1738 getLexer().UnLex(LParen); 1739 return ParseStatus::NoMatch; 1740 } 1741 if (HadParens) 1742 Operands.push_back(RISCVOperand::createToken("(", FirstS)); 1743 SMLoc S = getLoc(); 1744 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size()); 1745 getLexer().Lex(); 1746 Operands.push_back(RISCVOperand::createReg(RegNo, S, E)); 1747 } 1748 1749 if (HadParens) { 1750 getParser().Lex(); // Eat ')' 1751 Operands.push_back(RISCVOperand::createToken(")", getLoc())); 1752 } 1753 1754 return ParseStatus::Success; 1755 } 1756 1757 ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) { 1758 SMLoc S = getLoc(); 1759 SMLoc E; 1760 const MCExpr *Res; 1761 1762 switch (getLexer().getKind()) { 1763 default: 1764 return ParseStatus::NoMatch; 1765 case AsmToken::LParen: 1766 case AsmToken::Minus: 1767 case AsmToken::Plus: 1768 case AsmToken::Exclaim: 1769 case AsmToken::Tilde: 1770 case AsmToken::Integer: 1771 case AsmToken::String: { 1772 if (getParser().parseExpression(Res, E)) 1773 return ParseStatus::Failure; 1774 1775 auto *CE = dyn_cast<MCConstantExpr>(Res); 1776 if (CE) { 1777 int64_t Imm = CE->getValue(); 1778 if (isUInt<7>(Imm)) { 1779 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); 1780 return ParseStatus::Success; 1781 } 1782 } 1783 1784 break; 1785 } 1786 case AsmToken::Identifier: { 1787 StringRef Identifier; 1788 if (getParser().parseIdentifier(Identifier)) 1789 return ParseStatus::Failure; 1790 1791 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier); 1792 if (Opcode) { 1793 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 && 1794 "Unexpected opcode"); 1795 Res = MCConstantExpr::create(Opcode->Value, getContext()); 1796 E = SMLoc::getFromPointer(S.getPointer() + Identifier.size()); 1797 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); 1798 return ParseStatus::Success; 1799 } 1800 1801 break; 1802 } 1803 case AsmToken::Percent: 1804 break; 1805 } 1806 1807 return generateImmOutOfRangeError( 1808 S, 0, 127, 1809 "opcode must be a valid opcode name or an immediate in the range"); 1810 } 1811 1812 ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) { 1813 SMLoc S = getLoc(); 1814 SMLoc E; 1815 const MCExpr *Res; 1816 1817 switch (getLexer().getKind()) { 1818 default: 1819 return ParseStatus::NoMatch; 1820 case AsmToken::LParen: 1821 case AsmToken::Minus: 1822 case AsmToken::Plus: 1823 case AsmToken::Exclaim: 1824 case AsmToken::Tilde: 1825 case AsmToken::Integer: 1826 case AsmToken::String: { 1827 if (getParser().parseExpression(Res, E)) 1828 return ParseStatus::Failure; 1829 1830 auto *CE = dyn_cast<MCConstantExpr>(Res); 1831 if (CE) { 1832 int64_t Imm = CE->getValue(); 1833 if (Imm >= 0 && Imm <= 2) { 1834 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); 1835 return ParseStatus::Success; 1836 } 1837 } 1838 1839 break; 1840 } 1841 case AsmToken::Identifier: { 1842 StringRef Identifier; 1843 if (getParser().parseIdentifier(Identifier)) 1844 return ParseStatus::Failure; 1845 1846 unsigned Opcode; 1847 if (Identifier == "C0") 1848 Opcode = 0; 1849 else if (Identifier == "C1") 1850 Opcode = 1; 1851 else if (Identifier == "C2") 1852 Opcode = 2; 1853 else 1854 break; 1855 1856 Res = MCConstantExpr::create(Opcode, getContext()); 1857 E = SMLoc::getFromPointer(S.getPointer() + Identifier.size()); 1858 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); 1859 return ParseStatus::Success; 1860 } 1861 case AsmToken::Percent: { 1862 // Discard operand with modifier. 1863 break; 1864 } 1865 } 1866 1867 return generateImmOutOfRangeError( 1868 S, 0, 2, 1869 "opcode must be a valid opcode name or an immediate in the range"); 1870 } 1871 1872 ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) { 1873 SMLoc S = getLoc(); 1874 const MCExpr *Res; 1875 1876 switch (getLexer().getKind()) { 1877 default: 1878 return ParseStatus::NoMatch; 1879 case AsmToken::LParen: 1880 case AsmToken::Minus: 1881 case AsmToken::Plus: 1882 case AsmToken::Exclaim: 1883 case AsmToken::Tilde: 1884 case AsmToken::Integer: 1885 case AsmToken::String: { 1886 if (getParser().parseExpression(Res)) 1887 return ParseStatus::Failure; 1888 1889 auto *CE = dyn_cast<MCConstantExpr>(Res); 1890 if (CE) { 1891 int64_t Imm = CE->getValue(); 1892 if (isUInt<12>(Imm)) { 1893 auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm); 1894 // Accept an immediate representing a named Sys Reg if it satisfies the 1895 // the required features. 1896 for (auto &Reg : Range) { 1897 if (Reg.haveRequiredFeatures(STI->getFeatureBits())) { 1898 Operands.push_back(RISCVOperand::createSysReg(Reg.Name, S, Imm)); 1899 return ParseStatus::Success; 1900 } 1901 } 1902 // Accept an immediate representing an un-named Sys Reg if the range is 1903 // valid, regardless of the required features. 1904 Operands.push_back(RISCVOperand::createSysReg("", S, Imm)); 1905 return ParseStatus::Success; 1906 } 1907 } 1908 1909 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1); 1910 } 1911 case AsmToken::Identifier: { 1912 StringRef Identifier; 1913 if (getParser().parseIdentifier(Identifier)) 1914 return ParseStatus::Failure; 1915 1916 auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier); 1917 if (!SysReg) 1918 SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier); 1919 if (!SysReg) 1920 if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier))) 1921 Warning(S, "'" + Identifier + "' is a deprecated alias for '" + 1922 SysReg->Name + "'"); 1923 1924 // Accept a named Sys Reg if the required features are present. 1925 if (SysReg) { 1926 if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits())) 1927 return Error(S, "system register use requires an option to be enabled"); 1928 Operands.push_back( 1929 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding)); 1930 return ParseStatus::Success; 1931 } 1932 1933 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1, 1934 "operand must be a valid system register " 1935 "name or an integer in the range"); 1936 } 1937 case AsmToken::Percent: { 1938 // Discard operand with modifier. 1939 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1); 1940 } 1941 } 1942 1943 return ParseStatus::NoMatch; 1944 } 1945 1946 ParseStatus RISCVAsmParser::parseFPImm(OperandVector &Operands) { 1947 SMLoc S = getLoc(); 1948 1949 // Parse special floats (inf/nan/min) representation. 1950 if (getTok().is(AsmToken::Identifier)) { 1951 StringRef Identifier = getTok().getIdentifier(); 1952 if (Identifier.compare_insensitive("inf") == 0) { 1953 Operands.push_back( 1954 RISCVOperand::createImm(MCConstantExpr::create(30, getContext()), S, 1955 getTok().getEndLoc(), isRV64())); 1956 } else if (Identifier.compare_insensitive("nan") == 0) { 1957 Operands.push_back( 1958 RISCVOperand::createImm(MCConstantExpr::create(31, getContext()), S, 1959 getTok().getEndLoc(), isRV64())); 1960 } else if (Identifier.compare_insensitive("min") == 0) { 1961 Operands.push_back( 1962 RISCVOperand::createImm(MCConstantExpr::create(1, getContext()), S, 1963 getTok().getEndLoc(), isRV64())); 1964 } else { 1965 return TokError("invalid floating point literal"); 1966 } 1967 1968 Lex(); // Eat the token. 1969 1970 return ParseStatus::Success; 1971 } 1972 1973 // Handle negation, as that still comes through as a separate token. 1974 bool IsNegative = parseOptionalToken(AsmToken::Minus); 1975 1976 const AsmToken &Tok = getTok(); 1977 if (!Tok.is(AsmToken::Real)) 1978 return TokError("invalid floating point immediate"); 1979 1980 // Parse FP representation. 1981 APFloat RealVal(APFloat::IEEEdouble()); 1982 auto StatusOrErr = 1983 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero); 1984 if (errorToBool(StatusOrErr.takeError())) 1985 return TokError("invalid floating point representation"); 1986 1987 if (IsNegative) 1988 RealVal.changeSign(); 1989 1990 Operands.push_back(RISCVOperand::createFPImm( 1991 RealVal.bitcastToAPInt().getZExtValue(), S)); 1992 1993 Lex(); // Eat the token. 1994 1995 return ParseStatus::Success; 1996 } 1997 1998 ParseStatus RISCVAsmParser::parseImmediate(OperandVector &Operands) { 1999 SMLoc S = getLoc(); 2000 SMLoc E; 2001 const MCExpr *Res; 2002 2003 switch (getLexer().getKind()) { 2004 default: 2005 return ParseStatus::NoMatch; 2006 case AsmToken::LParen: 2007 case AsmToken::Dot: 2008 case AsmToken::Minus: 2009 case AsmToken::Plus: 2010 case AsmToken::Exclaim: 2011 case AsmToken::Tilde: 2012 case AsmToken::Integer: 2013 case AsmToken::String: 2014 case AsmToken::Identifier: 2015 if (getParser().parseExpression(Res, E)) 2016 return ParseStatus::Failure; 2017 break; 2018 case AsmToken::Percent: 2019 return parseOperandWithModifier(Operands); 2020 } 2021 2022 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); 2023 return ParseStatus::Success; 2024 } 2025 2026 ParseStatus RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) { 2027 SMLoc S = getLoc(); 2028 SMLoc E; 2029 2030 if (parseToken(AsmToken::Percent, "expected '%' for operand modifier")) 2031 return ParseStatus::Failure; 2032 2033 if (getLexer().getKind() != AsmToken::Identifier) 2034 return Error(getLoc(), "expected valid identifier for operand modifier"); 2035 StringRef Identifier = getParser().getTok().getIdentifier(); 2036 RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier); 2037 if (VK == RISCVMCExpr::VK_RISCV_Invalid) 2038 return Error(getLoc(), "unrecognized operand modifier"); 2039 2040 getParser().Lex(); // Eat the identifier 2041 if (parseToken(AsmToken::LParen, "expected '('")) 2042 return ParseStatus::Failure; 2043 2044 const MCExpr *SubExpr; 2045 if (getParser().parseParenExpression(SubExpr, E)) 2046 return ParseStatus::Failure; 2047 2048 const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext()); 2049 Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64())); 2050 return ParseStatus::Success; 2051 } 2052 2053 ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) { 2054 SMLoc S = getLoc(); 2055 const MCExpr *Res; 2056 2057 if (getLexer().getKind() != AsmToken::Identifier) 2058 return ParseStatus::NoMatch; 2059 2060 StringRef Identifier; 2061 AsmToken Tok = getLexer().getTok(); 2062 2063 if (getParser().parseIdentifier(Identifier)) 2064 return ParseStatus::Failure; 2065 2066 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size()); 2067 2068 if (Identifier.consume_back("@plt")) 2069 return Error(getLoc(), "'@plt' operand not valid for instruction"); 2070 2071 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 2072 2073 if (Sym->isVariable()) { 2074 const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false); 2075 if (!isa<MCSymbolRefExpr>(V)) { 2076 getLexer().UnLex(Tok); // Put back if it's not a bare symbol. 2077 return ParseStatus::NoMatch; 2078 } 2079 Res = V; 2080 } else 2081 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 2082 2083 MCBinaryExpr::Opcode Opcode; 2084 switch (getLexer().getKind()) { 2085 default: 2086 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); 2087 return ParseStatus::Success; 2088 case AsmToken::Plus: 2089 Opcode = MCBinaryExpr::Add; 2090 getLexer().Lex(); 2091 break; 2092 case AsmToken::Minus: 2093 Opcode = MCBinaryExpr::Sub; 2094 getLexer().Lex(); 2095 break; 2096 } 2097 2098 const MCExpr *Expr; 2099 if (getParser().parseExpression(Expr, E)) 2100 return ParseStatus::Failure; 2101 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext()); 2102 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); 2103 return ParseStatus::Success; 2104 } 2105 2106 ParseStatus RISCVAsmParser::parseCallSymbol(OperandVector &Operands) { 2107 SMLoc S = getLoc(); 2108 const MCExpr *Res; 2109 2110 if (getLexer().getKind() != AsmToken::Identifier) 2111 return ParseStatus::NoMatch; 2112 2113 // Avoid parsing the register in `call rd, foo` as a call symbol. 2114 if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement) 2115 return ParseStatus::NoMatch; 2116 2117 StringRef Identifier; 2118 if (getParser().parseIdentifier(Identifier)) 2119 return ParseStatus::Failure; 2120 2121 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size()); 2122 2123 RISCVMCExpr::VariantKind Kind = RISCVMCExpr::VK_RISCV_CALL_PLT; 2124 (void)Identifier.consume_back("@plt"); 2125 2126 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); 2127 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); 2128 Res = RISCVMCExpr::create(Res, Kind, getContext()); 2129 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); 2130 return ParseStatus::Success; 2131 } 2132 2133 ParseStatus RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) { 2134 SMLoc S = getLoc(); 2135 SMLoc E; 2136 const MCExpr *Res; 2137 2138 if (getParser().parseExpression(Res, E)) 2139 return ParseStatus::Failure; 2140 2141 if (Res->getKind() != MCExpr::ExprKind::SymbolRef || 2142 cast<MCSymbolRefExpr>(Res)->getKind() == 2143 MCSymbolRefExpr::VariantKind::VK_PLT) 2144 return Error(S, "operand must be a valid jump target"); 2145 2146 Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext()); 2147 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); 2148 return ParseStatus::Success; 2149 } 2150 2151 ParseStatus RISCVAsmParser::parseJALOffset(OperandVector &Operands) { 2152 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo` 2153 // both being acceptable forms. When parsing `jal ra, foo` this function 2154 // will be called for the `ra` register operand in an attempt to match the 2155 // single-operand alias. parseJALOffset must fail for this case. It would 2156 // seem logical to try parse the operand using parseImmediate and return 2157 // NoMatch if the next token is a comma (meaning we must be parsing a jal in 2158 // the second form rather than the first). We can't do this as there's no 2159 // way of rewinding the lexer state. Instead, return NoMatch if this operand 2160 // is an identifier and is followed by a comma. 2161 if (getLexer().is(AsmToken::Identifier) && 2162 getLexer().peekTok().is(AsmToken::Comma)) 2163 return ParseStatus::NoMatch; 2164 2165 return parseImmediate(Operands); 2166 } 2167 2168 bool RISCVAsmParser::parseVTypeToken(const AsmToken &Tok, VTypeState &State, 2169 unsigned &Sew, unsigned &Lmul, 2170 bool &Fractional, bool &TailAgnostic, 2171 bool &MaskAgnostic) { 2172 if (Tok.isNot(AsmToken::Identifier)) 2173 return true; 2174 2175 StringRef Identifier = Tok.getIdentifier(); 2176 2177 switch (State) { 2178 case VTypeState_SEW: 2179 if (!Identifier.consume_front("e")) 2180 break; 2181 if (Identifier.getAsInteger(10, Sew)) 2182 break; 2183 if (!RISCVVType::isValidSEW(Sew)) 2184 break; 2185 State = VTypeState_LMUL; 2186 return false; 2187 case VTypeState_LMUL: { 2188 if (!Identifier.consume_front("m")) 2189 break; 2190 Fractional = Identifier.consume_front("f"); 2191 if (Identifier.getAsInteger(10, Lmul)) 2192 break; 2193 if (!RISCVVType::isValidLMUL(Lmul, Fractional)) 2194 break; 2195 2196 if (Fractional) { 2197 unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32; 2198 unsigned MinLMUL = ELEN / 8; 2199 if (Lmul > MinLMUL) 2200 Warning(Tok.getLoc(), 2201 "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" + 2202 Twine(MinLMUL) + " is reserved"); 2203 } 2204 2205 State = VTypeState_TailPolicy; 2206 return false; 2207 } 2208 case VTypeState_TailPolicy: 2209 if (Identifier == "ta") 2210 TailAgnostic = true; 2211 else if (Identifier == "tu") 2212 TailAgnostic = false; 2213 else 2214 break; 2215 State = VTypeState_MaskPolicy; 2216 return false; 2217 case VTypeState_MaskPolicy: 2218 if (Identifier == "ma") 2219 MaskAgnostic = true; 2220 else if (Identifier == "mu") 2221 MaskAgnostic = false; 2222 else 2223 break; 2224 State = VTypeState_Done; 2225 return false; 2226 case VTypeState_Done: 2227 // Extra token? 2228 break; 2229 } 2230 2231 return true; 2232 } 2233 2234 ParseStatus RISCVAsmParser::parseVTypeI(OperandVector &Operands) { 2235 SMLoc S = getLoc(); 2236 2237 unsigned Sew = 0; 2238 unsigned Lmul = 0; 2239 bool Fractional = false; 2240 bool TailAgnostic = false; 2241 bool MaskAgnostic = false; 2242 2243 VTypeState State = VTypeState_SEW; 2244 SMLoc SEWLoc = S; 2245 2246 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic, 2247 MaskAgnostic)) 2248 return ParseStatus::NoMatch; 2249 2250 getLexer().Lex(); 2251 2252 while (parseOptionalToken(AsmToken::Comma)) { 2253 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic, 2254 MaskAgnostic)) 2255 break; 2256 2257 getLexer().Lex(); 2258 } 2259 2260 if (getLexer().is(AsmToken::EndOfStatement) && State == VTypeState_Done) { 2261 RISCVII::VLMUL VLMUL = RISCVVType::encodeLMUL(Lmul, Fractional); 2262 if (Fractional) { 2263 unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32; 2264 unsigned MaxSEW = ELEN / Lmul; 2265 // If MaxSEW < 8, we should have printed warning about reserved LMUL. 2266 if (MaxSEW >= 8 && Sew > MaxSEW) 2267 Warning(SEWLoc, 2268 "use of vtype encodings with SEW > " + Twine(MaxSEW) + 2269 " and LMUL == mf" + Twine(Lmul) + 2270 " may not be compatible with all RVV implementations"); 2271 } 2272 2273 unsigned VTypeI = 2274 RISCVVType::encodeVTYPE(VLMUL, Sew, TailAgnostic, MaskAgnostic); 2275 Operands.push_back(RISCVOperand::createVType(VTypeI, S)); 2276 return ParseStatus::Success; 2277 } 2278 2279 return generateVTypeError(S); 2280 } 2281 2282 bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) { 2283 return Error( 2284 ErrorLoc, 2285 "operand must be " 2286 "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]"); 2287 } 2288 2289 ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) { 2290 if (getLexer().isNot(AsmToken::Identifier)) 2291 return ParseStatus::NoMatch; 2292 2293 StringRef Name = getLexer().getTok().getIdentifier(); 2294 if (!Name.consume_back(".t")) 2295 return Error(getLoc(), "expected '.t' suffix"); 2296 MCRegister RegNo = matchRegisterNameHelper(Name); 2297 2298 if (!RegNo) 2299 return ParseStatus::NoMatch; 2300 if (RegNo != RISCV::V0) 2301 return ParseStatus::NoMatch; 2302 SMLoc S = getLoc(); 2303 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size()); 2304 getLexer().Lex(); 2305 Operands.push_back(RISCVOperand::createReg(RegNo, S, E)); 2306 return ParseStatus::Success; 2307 } 2308 2309 ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) { 2310 if (getLexer().isNot(AsmToken::Identifier)) 2311 return ParseStatus::NoMatch; 2312 2313 StringRef Name = getLexer().getTok().getIdentifier(); 2314 MCRegister RegNo = matchRegisterNameHelper(Name); 2315 2316 if (!RegNo) 2317 return ParseStatus::NoMatch; 2318 SMLoc S = getLoc(); 2319 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size()); 2320 getLexer().Lex(); 2321 Operands.push_back(RISCVOperand::createReg( 2322 RegNo, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF))); 2323 return ParseStatus::Success; 2324 } 2325 2326 template <bool IsRV64> 2327 ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands) { 2328 return parseGPRPair(Operands, IsRV64); 2329 } 2330 2331 ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands, 2332 bool IsRV64Inst) { 2333 // If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on 2334 // RV64 as it will prevent matching the RV64 version of the same instruction 2335 // that doesn't use a GPRPair. 2336 // If this is an RV64 GPRPair instruction, there is no RV32 version so we can 2337 // still parse as a pair. 2338 if (!IsRV64Inst && isRV64()) 2339 return ParseStatus::NoMatch; 2340 2341 if (getLexer().isNot(AsmToken::Identifier)) 2342 return ParseStatus::NoMatch; 2343 2344 StringRef Name = getLexer().getTok().getIdentifier(); 2345 MCRegister RegNo = matchRegisterNameHelper(Name); 2346 2347 if (!RegNo) 2348 return ParseStatus::NoMatch; 2349 2350 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(RegNo)) 2351 return ParseStatus::NoMatch; 2352 2353 if ((RegNo - RISCV::X0) & 1) 2354 return TokError("register must be even"); 2355 2356 SMLoc S = getLoc(); 2357 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size()); 2358 getLexer().Lex(); 2359 2360 const MCRegisterInfo *RI = getContext().getRegisterInfo(); 2361 unsigned Pair = RI->getMatchingSuperReg( 2362 RegNo, RISCV::sub_gpr_even, 2363 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]); 2364 Operands.push_back(RISCVOperand::createReg(Pair, S, E)); 2365 return ParseStatus::Success; 2366 } 2367 2368 ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) { 2369 if (getLexer().isNot(AsmToken::Identifier)) 2370 return TokError( 2371 "operand must be a valid floating point rounding mode mnemonic"); 2372 2373 StringRef Str = getLexer().getTok().getIdentifier(); 2374 RISCVFPRndMode::RoundingMode FRM = RISCVFPRndMode::stringToRoundingMode(Str); 2375 2376 if (FRM == RISCVFPRndMode::Invalid) 2377 return TokError( 2378 "operand must be a valid floating point rounding mode mnemonic"); 2379 2380 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc())); 2381 Lex(); // Eat identifier token. 2382 return ParseStatus::Success; 2383 } 2384 2385 ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) { 2386 const AsmToken &Tok = getLexer().getTok(); 2387 2388 if (Tok.is(AsmToken::Integer)) { 2389 if (Tok.getIntVal() != 0) 2390 goto ParseFail; 2391 2392 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc())); 2393 Lex(); 2394 return ParseStatus::Success; 2395 } 2396 2397 if (Tok.is(AsmToken::Identifier)) { 2398 StringRef Str = Tok.getIdentifier(); 2399 2400 // Letters must be unique, taken from 'iorw', and in ascending order. This 2401 // holds as long as each individual character is one of 'iorw' and is 2402 // greater than the previous character. 2403 unsigned Imm = 0; 2404 bool Valid = true; 2405 char Prev = '\0'; 2406 for (char c : Str) { 2407 switch (c) { 2408 default: 2409 Valid = false; 2410 break; 2411 case 'i': 2412 Imm |= RISCVFenceField::I; 2413 break; 2414 case 'o': 2415 Imm |= RISCVFenceField::O; 2416 break; 2417 case 'r': 2418 Imm |= RISCVFenceField::R; 2419 break; 2420 case 'w': 2421 Imm |= RISCVFenceField::W; 2422 break; 2423 } 2424 2425 if (c <= Prev) { 2426 Valid = false; 2427 break; 2428 } 2429 Prev = c; 2430 } 2431 2432 if (!Valid) 2433 goto ParseFail; 2434 2435 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc())); 2436 Lex(); 2437 return ParseStatus::Success; 2438 } 2439 2440 ParseFail: 2441 return TokError("operand must be formed of letters selected in-order from " 2442 "'iorw' or be 0"); 2443 } 2444 2445 ParseStatus RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) { 2446 if (parseToken(AsmToken::LParen, "expected '('")) 2447 return ParseStatus::Failure; 2448 Operands.push_back(RISCVOperand::createToken("(", getLoc())); 2449 2450 if (!parseRegister(Operands).isSuccess()) 2451 return Error(getLoc(), "expected register"); 2452 2453 if (parseToken(AsmToken::RParen, "expected ')'")) 2454 return ParseStatus::Failure; 2455 Operands.push_back(RISCVOperand::createToken(")", getLoc())); 2456 2457 return ParseStatus::Success; 2458 } 2459 2460 ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) { 2461 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand" 2462 // as one of their register operands, such as `(a0)`. This just denotes that 2463 // the register (in this case `a0`) contains a memory address. 2464 // 2465 // Normally, we would be able to parse these by putting the parens into the 2466 // instruction string. However, GNU as also accepts a zero-offset memory 2467 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed 2468 // with parseImmediate followed by parseMemOpBaseReg, but these instructions 2469 // do not accept an immediate operand, and we do not want to add a "dummy" 2470 // operand that is silently dropped. 2471 // 2472 // Instead, we use this custom parser. This will: allow (and discard) an 2473 // offset if it is zero; require (and discard) parentheses; and add only the 2474 // parsed register operand to `Operands`. 2475 // 2476 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp, 2477 // which will only print the register surrounded by parentheses (which GNU as 2478 // also uses as its canonical representation for these operands). 2479 std::unique_ptr<RISCVOperand> OptionalImmOp; 2480 2481 if (getLexer().isNot(AsmToken::LParen)) { 2482 // Parse an Integer token. We do not accept arbritrary constant expressions 2483 // in the offset field (because they may include parens, which complicates 2484 // parsing a lot). 2485 int64_t ImmVal; 2486 SMLoc ImmStart = getLoc(); 2487 if (getParser().parseIntToken(ImmVal, 2488 "expected '(' or optional integer offset")) 2489 return ParseStatus::Failure; 2490 2491 // Create a RISCVOperand for checking later (so the error messages are 2492 // nicer), but we don't add it to Operands. 2493 SMLoc ImmEnd = getLoc(); 2494 OptionalImmOp = 2495 RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()), 2496 ImmStart, ImmEnd, isRV64()); 2497 } 2498 2499 if (parseToken(AsmToken::LParen, 2500 OptionalImmOp ? "expected '(' after optional integer offset" 2501 : "expected '(' or optional integer offset")) 2502 return ParseStatus::Failure; 2503 2504 if (!parseRegister(Operands).isSuccess()) 2505 return Error(getLoc(), "expected register"); 2506 2507 if (parseToken(AsmToken::RParen, "expected ')'")) 2508 return ParseStatus::Failure; 2509 2510 // Deferred Handling of non-zero offsets. This makes the error messages nicer. 2511 if (OptionalImmOp && !OptionalImmOp->isImmZero()) 2512 return Error( 2513 OptionalImmOp->getStartLoc(), "optional integer offset must be 0", 2514 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc())); 2515 2516 return ParseStatus::Success; 2517 } 2518 2519 ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) { 2520 // RR : a2(a1) 2521 if (getLexer().getKind() != AsmToken::Identifier) 2522 return ParseStatus::NoMatch; 2523 2524 StringRef RegName = getLexer().getTok().getIdentifier(); 2525 MCRegister Reg = matchRegisterNameHelper(RegName); 2526 if (!Reg) 2527 return Error(getLoc(), "invalid register"); 2528 getLexer().Lex(); 2529 2530 if (parseToken(AsmToken::LParen, "expected '(' or invalid operand")) 2531 return ParseStatus::Failure; 2532 2533 if (getLexer().getKind() != AsmToken::Identifier) 2534 return Error(getLoc(), "expected register"); 2535 2536 StringRef Reg2Name = getLexer().getTok().getIdentifier(); 2537 MCRegister Reg2 = matchRegisterNameHelper(Reg2Name); 2538 if (!Reg2) 2539 return Error(getLoc(), "invalid register"); 2540 getLexer().Lex(); 2541 2542 if (parseToken(AsmToken::RParen, "expected ')'")) 2543 return ParseStatus::Failure; 2544 2545 Operands.push_back(RISCVOperand::createRegReg(Reg, Reg2, getLoc())); 2546 2547 return ParseStatus::Success; 2548 } 2549 2550 ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) { 2551 // Rlist: {ra [, s0[-sN]]} 2552 // XRlist: {x1 [, x8[-x9][, x18[-xN]]]} 2553 SMLoc S = getLoc(); 2554 2555 if (parseToken(AsmToken::LCurly, "register list must start with '{'")) 2556 return ParseStatus::Failure; 2557 2558 bool IsEABI = isRVE(); 2559 2560 if (getLexer().isNot(AsmToken::Identifier)) 2561 return Error(getLoc(), "register list must start from 'ra' or 'x1'"); 2562 2563 StringRef RegName = getLexer().getTok().getIdentifier(); 2564 MCRegister RegStart = matchRegisterNameHelper(RegName); 2565 MCRegister RegEnd; 2566 if (RegStart != RISCV::X1) 2567 return Error(getLoc(), "register list must start from 'ra' or 'x1'"); 2568 getLexer().Lex(); 2569 2570 // parse case like ,s0 2571 if (parseOptionalToken(AsmToken::Comma)) { 2572 if (getLexer().isNot(AsmToken::Identifier)) 2573 return Error(getLoc(), "invalid register"); 2574 StringRef RegName = getLexer().getTok().getIdentifier(); 2575 RegStart = matchRegisterNameHelper(RegName); 2576 if (!RegStart) 2577 return Error(getLoc(), "invalid register"); 2578 if (RegStart != RISCV::X8) 2579 return Error(getLoc(), 2580 "continuous register list must start from 's0' or 'x8'"); 2581 getLexer().Lex(); // eat reg 2582 } 2583 2584 // parse case like -s1 2585 if (parseOptionalToken(AsmToken::Minus)) { 2586 StringRef EndName = getLexer().getTok().getIdentifier(); 2587 // FIXME: the register mapping and checks of EABI is wrong 2588 RegEnd = matchRegisterNameHelper(EndName); 2589 if (!RegEnd) 2590 return Error(getLoc(), "invalid register"); 2591 if (IsEABI && RegEnd != RISCV::X9) 2592 return Error(getLoc(), "contiguous register list of EABI can only be " 2593 "'s0-s1' or 'x8-x9' pair"); 2594 getLexer().Lex(); 2595 } 2596 2597 if (!IsEABI) { 2598 // parse extra part like ', x18[-x20]' for XRegList 2599 if (parseOptionalToken(AsmToken::Comma)) { 2600 if (RegEnd != RISCV::X9) 2601 return Error( 2602 getLoc(), 2603 "first contiguous registers pair of register list must be 'x8-x9'"); 2604 2605 // parse ', x18' for extra part 2606 if (getLexer().isNot(AsmToken::Identifier)) 2607 return Error(getLoc(), "invalid register"); 2608 StringRef EndName = getLexer().getTok().getIdentifier(); 2609 if (MatchRegisterName(EndName) != RISCV::X18) 2610 return Error(getLoc(), 2611 "second contiguous registers pair of register list " 2612 "must start from 'x18'"); 2613 getLexer().Lex(); 2614 2615 // parse '-x20' for extra part 2616 if (parseOptionalToken(AsmToken::Minus)) { 2617 if (getLexer().isNot(AsmToken::Identifier)) 2618 return Error(getLoc(), "invalid register"); 2619 EndName = getLexer().getTok().getIdentifier(); 2620 if (MatchRegisterName(EndName) == RISCV::NoRegister) 2621 return Error(getLoc(), "invalid register"); 2622 getLexer().Lex(); 2623 } 2624 RegEnd = MatchRegisterName(EndName); 2625 } 2626 } 2627 2628 if (RegEnd == RISCV::X26) 2629 return Error(getLoc(), "invalid register list, {ra, s0-s10} or {x1, x8-x9, " 2630 "x18-x26} is not supported"); 2631 2632 if (parseToken(AsmToken::RCurly, "register list must end with '}'")) 2633 return ParseStatus::Failure; 2634 2635 if (RegEnd == RISCV::NoRegister) 2636 RegEnd = RegStart; 2637 2638 auto Encode = RISCVZC::encodeRlist(RegEnd, IsEABI); 2639 if (Encode == RISCVZC::INVALID_RLIST) 2640 return Error(S, "invalid register list"); 2641 Operands.push_back(RISCVOperand::createRlist(Encode, S)); 2642 2643 return ParseStatus::Success; 2644 } 2645 2646 ParseStatus RISCVAsmParser::parseZcmpStackAdj(OperandVector &Operands, 2647 bool ExpectNegative) { 2648 bool Negative = parseOptionalToken(AsmToken::Minus); 2649 2650 SMLoc S = getLoc(); 2651 int64_t StackAdjustment = getLexer().getTok().getIntVal(); 2652 unsigned Spimm = 0; 2653 unsigned RlistVal = static_cast<RISCVOperand *>(Operands[1].get())->Rlist.Val; 2654 2655 if (Negative != ExpectNegative || 2656 !RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64())) 2657 return ParseStatus::NoMatch; 2658 Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S)); 2659 getLexer().Lex(); 2660 return ParseStatus::Success; 2661 } 2662 2663 /// Looks at a token type and creates the relevant operand from this 2664 /// information, adding to Operands. If operand was parsed, returns false, else 2665 /// true. 2666 bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { 2667 // Check if the current operand has a custom associated parser, if so, try to 2668 // custom parse the operand, or fallback to the general approach. 2669 ParseStatus Result = 2670 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true); 2671 if (Result.isSuccess()) 2672 return false; 2673 if (Result.isFailure()) 2674 return true; 2675 2676 // Attempt to parse token as a register. 2677 if (parseRegister(Operands, true).isSuccess()) 2678 return false; 2679 2680 // Attempt to parse token as an immediate 2681 if (parseImmediate(Operands).isSuccess()) { 2682 // Parse memory base register if present 2683 if (getLexer().is(AsmToken::LParen)) 2684 return !parseMemOpBaseReg(Operands).isSuccess(); 2685 return false; 2686 } 2687 2688 // Finally we have exhausted all options and must declare defeat. 2689 Error(getLoc(), "unknown operand"); 2690 return true; 2691 } 2692 2693 bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info, 2694 StringRef Name, SMLoc NameLoc, 2695 OperandVector &Operands) { 2696 // Ensure that if the instruction occurs when relaxation is enabled, 2697 // relocations are forced for the file. Ideally this would be done when there 2698 // is enough information to reliably determine if the instruction itself may 2699 // cause relaxations. Unfortunately instruction processing stage occurs in the 2700 // same pass as relocation emission, so it's too late to set a 'sticky bit' 2701 // for the entire file. 2702 if (getSTI().hasFeature(RISCV::FeatureRelax)) { 2703 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr(); 2704 if (Assembler != nullptr) { 2705 RISCVAsmBackend &MAB = 2706 static_cast<RISCVAsmBackend &>(Assembler->getBackend()); 2707 MAB.setForceRelocs(); 2708 } 2709 } 2710 2711 // First operand is token for instruction 2712 Operands.push_back(RISCVOperand::createToken(Name, NameLoc)); 2713 2714 // If there are no more operands, then finish 2715 if (getLexer().is(AsmToken::EndOfStatement)) { 2716 getParser().Lex(); // Consume the EndOfStatement. 2717 return false; 2718 } 2719 2720 // Parse first operand 2721 if (parseOperand(Operands, Name)) 2722 return true; 2723 2724 // Parse until end of statement, consuming commas between operands 2725 while (parseOptionalToken(AsmToken::Comma)) { 2726 // Parse next operand 2727 if (parseOperand(Operands, Name)) 2728 return true; 2729 } 2730 2731 if (getParser().parseEOL("unexpected token")) { 2732 getParser().eatToEndOfStatement(); 2733 return true; 2734 } 2735 return false; 2736 } 2737 2738 bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr, 2739 RISCVMCExpr::VariantKind &Kind) { 2740 Kind = RISCVMCExpr::VK_RISCV_None; 2741 2742 if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) { 2743 Kind = RE->getKind(); 2744 Expr = RE->getSubExpr(); 2745 } 2746 2747 MCValue Res; 2748 MCFixup Fixup; 2749 if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup)) 2750 return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None; 2751 return false; 2752 } 2753 2754 bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) { 2755 MCValue Res; 2756 MCFixup Fixup; 2757 if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup)) { 2758 return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None && Res.getSymA() && 2759 Res.getSymB(); 2760 } 2761 return false; 2762 } 2763 2764 ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) { 2765 StringRef IDVal = DirectiveID.getString(); 2766 2767 if (IDVal == ".option") 2768 return parseDirectiveOption(); 2769 if (IDVal == ".attribute") 2770 return parseDirectiveAttribute(); 2771 if (IDVal == ".insn") 2772 return parseDirectiveInsn(DirectiveID.getLoc()); 2773 if (IDVal == ".variant_cc") 2774 return parseDirectiveVariantCC(); 2775 2776 return ParseStatus::NoMatch; 2777 } 2778 2779 bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result, 2780 bool FromOptionDirective) { 2781 for (auto &Feature : RISCVFeatureKV) 2782 if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key)) 2783 clearFeatureBits(Feature.Value, Feature.Key); 2784 2785 auto ParseResult = llvm::RISCVISAInfo::parseArchString( 2786 Arch, /*EnableExperimentalExtension=*/true, 2787 /*ExperimentalExtensionVersionCheck=*/true); 2788 if (!ParseResult) { 2789 std::string Buffer; 2790 raw_string_ostream OutputErrMsg(Buffer); 2791 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) { 2792 OutputErrMsg << "invalid arch name '" << Arch << "', " 2793 << ErrMsg.getMessage(); 2794 }); 2795 2796 return Error(Loc, OutputErrMsg.str()); 2797 } 2798 auto &ISAInfo = *ParseResult; 2799 2800 for (auto &Feature : RISCVFeatureKV) 2801 if (ISAInfo->hasExtension(Feature.Key)) 2802 setFeatureBits(Feature.Value, Feature.Key); 2803 2804 if (FromOptionDirective) { 2805 if (ISAInfo->getXLen() == 32 && isRV64()) 2806 return Error(Loc, "bad arch string switching from rv64 to rv32"); 2807 else if (ISAInfo->getXLen() == 64 && !isRV64()) 2808 return Error(Loc, "bad arch string switching from rv32 to rv64"); 2809 } 2810 2811 if (ISAInfo->getXLen() == 32) 2812 clearFeatureBits(RISCV::Feature64Bit, "64bit"); 2813 else if (ISAInfo->getXLen() == 64) 2814 setFeatureBits(RISCV::Feature64Bit, "64bit"); 2815 else 2816 return Error(Loc, "bad arch string " + Arch); 2817 2818 Result = ISAInfo->toString(); 2819 return false; 2820 } 2821 2822 bool RISCVAsmParser::parseDirectiveOption() { 2823 MCAsmParser &Parser = getParser(); 2824 // Get the option token. 2825 AsmToken Tok = Parser.getTok(); 2826 2827 // At the moment only identifiers are supported. 2828 if (parseToken(AsmToken::Identifier, "expected identifier")) 2829 return true; 2830 2831 StringRef Option = Tok.getIdentifier(); 2832 2833 if (Option == "push") { 2834 if (Parser.parseEOL()) 2835 return true; 2836 2837 getTargetStreamer().emitDirectiveOptionPush(); 2838 pushFeatureBits(); 2839 return false; 2840 } 2841 2842 if (Option == "pop") { 2843 SMLoc StartLoc = Parser.getTok().getLoc(); 2844 if (Parser.parseEOL()) 2845 return true; 2846 2847 getTargetStreamer().emitDirectiveOptionPop(); 2848 if (popFeatureBits()) 2849 return Error(StartLoc, ".option pop with no .option push"); 2850 2851 return false; 2852 } 2853 2854 if (Option == "arch") { 2855 SmallVector<RISCVOptionArchArg> Args; 2856 do { 2857 if (Parser.parseComma()) 2858 return true; 2859 2860 RISCVOptionArchArgType Type; 2861 if (parseOptionalToken(AsmToken::Plus)) 2862 Type = RISCVOptionArchArgType::Plus; 2863 else if (parseOptionalToken(AsmToken::Minus)) 2864 Type = RISCVOptionArchArgType::Minus; 2865 else if (!Args.empty()) 2866 return Error(Parser.getTok().getLoc(), 2867 "unexpected token, expected + or -"); 2868 else 2869 Type = RISCVOptionArchArgType::Full; 2870 2871 if (Parser.getTok().isNot(AsmToken::Identifier)) 2872 return Error(Parser.getTok().getLoc(), 2873 "unexpected token, expected identifier"); 2874 2875 StringRef Arch = Parser.getTok().getString(); 2876 SMLoc Loc = Parser.getTok().getLoc(); 2877 Parser.Lex(); 2878 2879 if (Type == RISCVOptionArchArgType::Full) { 2880 std::string Result; 2881 if (resetToArch(Arch, Loc, Result, true)) 2882 return true; 2883 2884 Args.emplace_back(Type, Result); 2885 break; 2886 } 2887 2888 if (isDigit(Arch.back())) 2889 return Error( 2890 Loc, "extension version number parsing not currently implemented"); 2891 2892 std::string Feature = RISCVISAInfo::getTargetFeatureForExtension(Arch); 2893 if (!enableExperimentalExtension() && 2894 StringRef(Feature).starts_with("experimental-")) 2895 return Error(Loc, "unexpected experimental extensions"); 2896 auto Ext = llvm::lower_bound(RISCVFeatureKV, Feature); 2897 if (Ext == std::end(RISCVFeatureKV) || StringRef(Ext->Key) != Feature) 2898 return Error(Loc, "unknown extension feature"); 2899 2900 Args.emplace_back(Type, Arch.str()); 2901 2902 if (Type == RISCVOptionArchArgType::Plus) { 2903 FeatureBitset OldFeatureBits = STI->getFeatureBits(); 2904 2905 setFeatureBits(Ext->Value, Ext->Key); 2906 auto ParseResult = RISCVFeatures::parseFeatureBits(isRV64(), STI->getFeatureBits()); 2907 if (!ParseResult) { 2908 copySTI().setFeatureBits(OldFeatureBits); 2909 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits)); 2910 2911 std::string Buffer; 2912 raw_string_ostream OutputErrMsg(Buffer); 2913 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) { 2914 OutputErrMsg << ErrMsg.getMessage(); 2915 }); 2916 2917 return Error(Loc, OutputErrMsg.str()); 2918 } 2919 } else { 2920 assert(Type == RISCVOptionArchArgType::Minus); 2921 // It is invalid to disable an extension that there are other enabled 2922 // extensions depend on it. 2923 // TODO: Make use of RISCVISAInfo to handle this 2924 for (auto &Feature : RISCVFeatureKV) { 2925 if (getSTI().hasFeature(Feature.Value) && 2926 Feature.Implies.test(Ext->Value)) 2927 return Error(Loc, Twine("can't disable ") + Ext->Key + 2928 " extension; " + Feature.Key + 2929 " extension requires " + Ext->Key + 2930 " extension"); 2931 } 2932 2933 clearFeatureBits(Ext->Value, Ext->Key); 2934 } 2935 } while (Parser.getTok().isNot(AsmToken::EndOfStatement)); 2936 2937 if (Parser.parseEOL()) 2938 return true; 2939 2940 getTargetStreamer().emitDirectiveOptionArch(Args); 2941 return false; 2942 } 2943 2944 if (Option == "rvc") { 2945 if (Parser.parseEOL()) 2946 return true; 2947 2948 getTargetStreamer().emitDirectiveOptionRVC(); 2949 setFeatureBits(RISCV::FeatureStdExtC, "c"); 2950 return false; 2951 } 2952 2953 if (Option == "norvc") { 2954 if (Parser.parseEOL()) 2955 return true; 2956 2957 getTargetStreamer().emitDirectiveOptionNoRVC(); 2958 clearFeatureBits(RISCV::FeatureStdExtC, "c"); 2959 clearFeatureBits(RISCV::FeatureStdExtZca, "zca"); 2960 return false; 2961 } 2962 2963 if (Option == "pic") { 2964 if (Parser.parseEOL()) 2965 return true; 2966 2967 getTargetStreamer().emitDirectiveOptionPIC(); 2968 ParserOptions.IsPicEnabled = true; 2969 return false; 2970 } 2971 2972 if (Option == "nopic") { 2973 if (Parser.parseEOL()) 2974 return true; 2975 2976 getTargetStreamer().emitDirectiveOptionNoPIC(); 2977 ParserOptions.IsPicEnabled = false; 2978 return false; 2979 } 2980 2981 if (Option == "relax") { 2982 if (Parser.parseEOL()) 2983 return true; 2984 2985 getTargetStreamer().emitDirectiveOptionRelax(); 2986 setFeatureBits(RISCV::FeatureRelax, "relax"); 2987 return false; 2988 } 2989 2990 if (Option == "norelax") { 2991 if (Parser.parseEOL()) 2992 return true; 2993 2994 getTargetStreamer().emitDirectiveOptionNoRelax(); 2995 clearFeatureBits(RISCV::FeatureRelax, "relax"); 2996 return false; 2997 } 2998 2999 // Unknown option. 3000 Warning(Parser.getTok().getLoc(), "unknown option, expected 'push', 'pop', " 3001 "'rvc', 'norvc', 'arch', 'relax' or " 3002 "'norelax'"); 3003 Parser.eatToEndOfStatement(); 3004 return false; 3005 } 3006 3007 /// parseDirectiveAttribute 3008 /// ::= .attribute expression ',' ( expression | "string" ) 3009 /// ::= .attribute identifier ',' ( expression | "string" ) 3010 bool RISCVAsmParser::parseDirectiveAttribute() { 3011 MCAsmParser &Parser = getParser(); 3012 int64_t Tag; 3013 SMLoc TagLoc; 3014 TagLoc = Parser.getTok().getLoc(); 3015 if (Parser.getTok().is(AsmToken::Identifier)) { 3016 StringRef Name = Parser.getTok().getIdentifier(); 3017 std::optional<unsigned> Ret = 3018 ELFAttrs::attrTypeFromString(Name, RISCVAttrs::getRISCVAttributeTags()); 3019 if (!Ret) 3020 return Error(TagLoc, "attribute name not recognised: " + Name); 3021 Tag = *Ret; 3022 Parser.Lex(); 3023 } else { 3024 const MCExpr *AttrExpr; 3025 3026 TagLoc = Parser.getTok().getLoc(); 3027 if (Parser.parseExpression(AttrExpr)) 3028 return true; 3029 3030 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr); 3031 if (check(!CE, TagLoc, "expected numeric constant")) 3032 return true; 3033 3034 Tag = CE->getValue(); 3035 } 3036 3037 if (Parser.parseComma()) 3038 return true; 3039 3040 StringRef StringValue; 3041 int64_t IntegerValue = 0; 3042 bool IsIntegerValue = true; 3043 3044 // RISC-V attributes have a string value if the tag number is odd 3045 // and an integer value if the tag number is even. 3046 if (Tag % 2) 3047 IsIntegerValue = false; 3048 3049 SMLoc ValueExprLoc = Parser.getTok().getLoc(); 3050 if (IsIntegerValue) { 3051 const MCExpr *ValueExpr; 3052 if (Parser.parseExpression(ValueExpr)) 3053 return true; 3054 3055 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr); 3056 if (!CE) 3057 return Error(ValueExprLoc, "expected numeric constant"); 3058 IntegerValue = CE->getValue(); 3059 } else { 3060 if (Parser.getTok().isNot(AsmToken::String)) 3061 return Error(Parser.getTok().getLoc(), "expected string constant"); 3062 3063 StringValue = Parser.getTok().getStringContents(); 3064 Parser.Lex(); 3065 } 3066 3067 if (Parser.parseEOL()) 3068 return true; 3069 3070 if (IsIntegerValue) 3071 getTargetStreamer().emitAttribute(Tag, IntegerValue); 3072 else if (Tag != RISCVAttrs::ARCH) 3073 getTargetStreamer().emitTextAttribute(Tag, StringValue); 3074 else { 3075 std::string Result; 3076 if (resetToArch(StringValue, ValueExprLoc, Result, false)) 3077 return true; 3078 3079 // Then emit the arch string. 3080 getTargetStreamer().emitTextAttribute(Tag, Result); 3081 } 3082 3083 return false; 3084 } 3085 3086 bool isValidInsnFormat(StringRef Format, bool AllowC) { 3087 return StringSwitch<bool>(Format) 3088 .Cases("r", "r4", "i", "b", "sb", "u", "j", "uj", "s", true) 3089 .Cases("cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj", AllowC) 3090 .Default(false); 3091 } 3092 3093 /// parseDirectiveInsn 3094 /// ::= .insn [ format encoding, (operands (, operands)*) ] 3095 /// ::= .insn [ length, value ] 3096 /// ::= .insn [ value ] 3097 bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) { 3098 MCAsmParser &Parser = getParser(); 3099 3100 bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) || 3101 getSTI().hasFeature(RISCV::FeatureStdExtZca); 3102 3103 // Expect instruction format as identifier. 3104 StringRef Format; 3105 SMLoc ErrorLoc = Parser.getTok().getLoc(); 3106 if (Parser.parseIdentifier(Format)) { 3107 // Try parsing .insn [length], value 3108 int64_t Length = 0; 3109 int64_t Value = 0; 3110 if (Parser.parseIntToken( 3111 Value, "expected instruction format or an integer constant")) 3112 return true; 3113 if (Parser.parseOptionalToken(AsmToken::Comma)) { 3114 Length = Value; 3115 if (Parser.parseIntToken(Value, "expected an integer constant")) 3116 return true; 3117 } 3118 3119 // TODO: Add support for long instructions 3120 int64_t RealLength = (Value & 3) == 3 ? 4 : 2; 3121 if (!isUIntN(RealLength * 8, Value)) 3122 return Error(ErrorLoc, "invalid operand for instruction"); 3123 if (RealLength == 2 && !AllowC) 3124 return Error(ErrorLoc, "compressed instructions are not allowed"); 3125 if (Length != 0 && Length != RealLength) 3126 return Error(ErrorLoc, "instruction length mismatch"); 3127 3128 if (getParser().parseEOL("invalid operand for instruction")) { 3129 getParser().eatToEndOfStatement(); 3130 return true; 3131 } 3132 3133 emitToStreamer(getStreamer(), MCInstBuilder(RealLength == 2 ? RISCV::Insn16 3134 : RISCV::Insn32) 3135 .addImm(Value)); 3136 return false; 3137 } 3138 3139 if (!isValidInsnFormat(Format, AllowC)) 3140 return Error(ErrorLoc, "invalid instruction format"); 3141 3142 std::string FormatName = (".insn_" + Format).str(); 3143 3144 ParseInstructionInfo Info; 3145 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands; 3146 3147 if (ParseInstruction(Info, FormatName, L, Operands)) 3148 return true; 3149 3150 unsigned Opcode; 3151 uint64_t ErrorInfo; 3152 return MatchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(), 3153 ErrorInfo, 3154 /*MatchingInlineAsm=*/false); 3155 } 3156 3157 /// parseDirectiveVariantCC 3158 /// ::= .variant_cc symbol 3159 bool RISCVAsmParser::parseDirectiveVariantCC() { 3160 StringRef Name; 3161 if (getParser().parseIdentifier(Name)) 3162 return TokError("expected symbol name"); 3163 if (parseEOL()) 3164 return true; 3165 getTargetStreamer().emitDirectiveVariantCC( 3166 *getContext().getOrCreateSymbol(Name)); 3167 return false; 3168 } 3169 3170 void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) { 3171 MCInst CInst; 3172 bool Res = RISCVRVC::compress(CInst, Inst, getSTI()); 3173 if (Res) 3174 ++RISCVNumInstrsCompressed; 3175 S.emitInstruction((Res ? CInst : Inst), getSTI()); 3176 } 3177 3178 void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value, 3179 MCStreamer &Out) { 3180 SmallVector<MCInst, 8> Seq; 3181 RISCVMatInt::generateMCInstSeq(Value, getSTI(), DestReg, Seq); 3182 3183 for (MCInst &Inst : Seq) { 3184 emitToStreamer(Out, Inst); 3185 } 3186 } 3187 3188 void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg, 3189 const MCExpr *Symbol, 3190 RISCVMCExpr::VariantKind VKHi, 3191 unsigned SecondOpcode, SMLoc IDLoc, 3192 MCStreamer &Out) { 3193 // A pair of instructions for PC-relative addressing; expands to 3194 // TmpLabel: AUIPC TmpReg, VKHi(symbol) 3195 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel) 3196 MCContext &Ctx = getContext(); 3197 3198 MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi"); 3199 Out.emitLabel(TmpLabel); 3200 3201 const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx); 3202 emitToStreamer( 3203 Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi)); 3204 3205 const MCExpr *RefToLinkTmpLabel = 3206 RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx), 3207 RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx); 3208 3209 emitToStreamer(Out, MCInstBuilder(SecondOpcode) 3210 .addOperand(DestReg) 3211 .addOperand(TmpReg) 3212 .addExpr(RefToLinkTmpLabel)); 3213 } 3214 3215 void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, 3216 MCStreamer &Out) { 3217 // The load local address pseudo-instruction "lla" is used in PC-relative 3218 // addressing of local symbols: 3219 // lla rdest, symbol 3220 // expands to 3221 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol) 3222 // ADDI rdest, rdest, %pcrel_lo(TmpLabel) 3223 MCOperand DestReg = Inst.getOperand(0); 3224 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 3225 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI, 3226 RISCV::ADDI, IDLoc, Out); 3227 } 3228 3229 void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc, 3230 MCStreamer &Out) { 3231 // The load global address pseudo-instruction "lga" is used in GOT-indirect 3232 // addressing of global symbols: 3233 // lga rdest, symbol 3234 // expands to 3235 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol) 3236 // Lx rdest, %pcrel_lo(TmpLabel)(rdest) 3237 MCOperand DestReg = Inst.getOperand(0); 3238 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 3239 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW; 3240 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_GOT_HI, 3241 SecondOpcode, IDLoc, Out); 3242 } 3243 3244 void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc, 3245 MCStreamer &Out) { 3246 // The load address pseudo-instruction "la" is used in PC-relative and 3247 // GOT-indirect addressing of global symbols: 3248 // la rdest, symbol 3249 // is an alias for either (for non-PIC) 3250 // lla rdest, symbol 3251 // or (for PIC) 3252 // lga rdest, symbol 3253 if (ParserOptions.IsPicEnabled) 3254 emitLoadGlobalAddress(Inst, IDLoc, Out); 3255 else 3256 emitLoadLocalAddress(Inst, IDLoc, Out); 3257 } 3258 3259 void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, 3260 MCStreamer &Out) { 3261 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in 3262 // initial-exec TLS model addressing of global symbols: 3263 // la.tls.ie rdest, symbol 3264 // expands to 3265 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol) 3266 // Lx rdest, %pcrel_lo(TmpLabel)(rdest) 3267 MCOperand DestReg = Inst.getOperand(0); 3268 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 3269 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW; 3270 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI, 3271 SecondOpcode, IDLoc, Out); 3272 } 3273 3274 void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, 3275 MCStreamer &Out) { 3276 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in 3277 // global-dynamic TLS model addressing of global symbols: 3278 // la.tls.gd rdest, symbol 3279 // expands to 3280 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol) 3281 // ADDI rdest, rdest, %pcrel_lo(TmpLabel) 3282 MCOperand DestReg = Inst.getOperand(0); 3283 const MCExpr *Symbol = Inst.getOperand(1).getExpr(); 3284 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI, 3285 RISCV::ADDI, IDLoc, Out); 3286 } 3287 3288 void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, 3289 SMLoc IDLoc, MCStreamer &Out, 3290 bool HasTmpReg) { 3291 // The load/store pseudo-instruction does a pc-relative load with 3292 // a symbol. 3293 // 3294 // The expansion looks like this 3295 // 3296 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol) 3297 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp) 3298 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0; 3299 MCOperand DestReg = Inst.getOperand(DestRegOpIdx); 3300 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1; 3301 MCOperand TmpReg = Inst.getOperand(0); 3302 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr(); 3303 emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI, 3304 Opcode, IDLoc, Out); 3305 } 3306 3307 void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend, 3308 int64_t Width, SMLoc IDLoc, 3309 MCStreamer &Out) { 3310 // The sign/zero extend pseudo-instruction does two shifts, with the shift 3311 // amounts dependent on the XLEN. 3312 // 3313 // The expansion looks like this 3314 // 3315 // SLLI rd, rs, XLEN - Width 3316 // SR[A|R]I rd, rd, XLEN - Width 3317 MCOperand DestReg = Inst.getOperand(0); 3318 MCOperand SourceReg = Inst.getOperand(1); 3319 3320 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI; 3321 int64_t ShAmt = (isRV64() ? 64 : 32) - Width; 3322 3323 assert(ShAmt > 0 && "Shift amount must be non-zero."); 3324 3325 emitToStreamer(Out, MCInstBuilder(RISCV::SLLI) 3326 .addOperand(DestReg) 3327 .addOperand(SourceReg) 3328 .addImm(ShAmt)); 3329 3330 emitToStreamer(Out, MCInstBuilder(SecondOpcode) 3331 .addOperand(DestReg) 3332 .addOperand(DestReg) 3333 .addImm(ShAmt)); 3334 } 3335 3336 void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, 3337 MCStreamer &Out) { 3338 if (Inst.getNumOperands() == 3) { 3339 // unmasked va >= x 3340 // 3341 // pseudoinstruction: vmsge{u}.vx vd, va, x 3342 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd 3343 emitToStreamer(Out, MCInstBuilder(Opcode) 3344 .addOperand(Inst.getOperand(0)) 3345 .addOperand(Inst.getOperand(1)) 3346 .addOperand(Inst.getOperand(2)) 3347 .addReg(RISCV::NoRegister) 3348 .setLoc(IDLoc)); 3349 emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM) 3350 .addOperand(Inst.getOperand(0)) 3351 .addOperand(Inst.getOperand(0)) 3352 .addOperand(Inst.getOperand(0)) 3353 .setLoc(IDLoc)); 3354 } else if (Inst.getNumOperands() == 4) { 3355 // masked va >= x, vd != v0 3356 // 3357 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t 3358 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0 3359 assert(Inst.getOperand(0).getReg() != RISCV::V0 && 3360 "The destination register should not be V0."); 3361 emitToStreamer(Out, MCInstBuilder(Opcode) 3362 .addOperand(Inst.getOperand(0)) 3363 .addOperand(Inst.getOperand(1)) 3364 .addOperand(Inst.getOperand(2)) 3365 .addOperand(Inst.getOperand(3)) 3366 .setLoc(IDLoc)); 3367 emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM) 3368 .addOperand(Inst.getOperand(0)) 3369 .addOperand(Inst.getOperand(0)) 3370 .addReg(RISCV::V0) 3371 .setLoc(IDLoc)); 3372 } else if (Inst.getNumOperands() == 5 && 3373 Inst.getOperand(0).getReg() == RISCV::V0) { 3374 // masked va >= x, vd == v0 3375 // 3376 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt 3377 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt 3378 assert(Inst.getOperand(0).getReg() == RISCV::V0 && 3379 "The destination register should be V0."); 3380 assert(Inst.getOperand(1).getReg() != RISCV::V0 && 3381 "The temporary vector register should not be V0."); 3382 emitToStreamer(Out, MCInstBuilder(Opcode) 3383 .addOperand(Inst.getOperand(1)) 3384 .addOperand(Inst.getOperand(2)) 3385 .addOperand(Inst.getOperand(3)) 3386 .addReg(RISCV::NoRegister) 3387 .setLoc(IDLoc)); 3388 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM) 3389 .addOperand(Inst.getOperand(0)) 3390 .addOperand(Inst.getOperand(0)) 3391 .addOperand(Inst.getOperand(1)) 3392 .setLoc(IDLoc)); 3393 } else if (Inst.getNumOperands() == 5) { 3394 // masked va >= x, any vd 3395 // 3396 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt 3397 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt; 3398 // vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd 3399 assert(Inst.getOperand(1).getReg() != RISCV::V0 && 3400 "The temporary vector register should not be V0."); 3401 emitToStreamer(Out, MCInstBuilder(Opcode) 3402 .addOperand(Inst.getOperand(1)) 3403 .addOperand(Inst.getOperand(2)) 3404 .addOperand(Inst.getOperand(3)) 3405 .addReg(RISCV::NoRegister) 3406 .setLoc(IDLoc)); 3407 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM) 3408 .addOperand(Inst.getOperand(1)) 3409 .addReg(RISCV::V0) 3410 .addOperand(Inst.getOperand(1)) 3411 .setLoc(IDLoc)); 3412 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM) 3413 .addOperand(Inst.getOperand(0)) 3414 .addOperand(Inst.getOperand(0)) 3415 .addReg(RISCV::V0) 3416 .setLoc(IDLoc)); 3417 emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM) 3418 .addOperand(Inst.getOperand(0)) 3419 .addOperand(Inst.getOperand(1)) 3420 .addOperand(Inst.getOperand(0)) 3421 .setLoc(IDLoc)); 3422 } 3423 } 3424 3425 bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst, 3426 OperandVector &Operands) { 3427 assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction"); 3428 assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind"); 3429 if (Inst.getOperand(2).getReg() != RISCV::X4) { 3430 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc(); 3431 return Error(ErrorLoc, "the second input operand must be tp/x4 when using " 3432 "%tprel_add modifier"); 3433 } 3434 3435 return false; 3436 } 3437 3438 bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst &Inst, 3439 OperandVector &Operands) { 3440 assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction"); 3441 assert(Inst.getOperand(0).isReg() && "Unexpected operand kind"); 3442 if (Inst.getOperand(0).getReg() != RISCV::X5) { 3443 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc(); 3444 return Error(ErrorLoc, "the output operand must be t0/x5 when using " 3445 "%tlsdesc_call modifier"); 3446 } 3447 3448 return false; 3449 } 3450 3451 std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const { 3452 return RISCVOperand::createReg(RISCV::NoRegister, llvm::SMLoc(), 3453 llvm::SMLoc()); 3454 } 3455 3456 std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const { 3457 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN, 3458 llvm::SMLoc()); 3459 } 3460 3461 std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const { 3462 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE, 3463 llvm::SMLoc()); 3464 } 3465 3466 bool RISCVAsmParser::validateInstruction(MCInst &Inst, 3467 OperandVector &Operands) { 3468 unsigned Opcode = Inst.getOpcode(); 3469 3470 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T || 3471 Opcode == RISCV::PseudoVMSGE_VX_M_T) { 3472 unsigned DestReg = Inst.getOperand(0).getReg(); 3473 unsigned TempReg = Inst.getOperand(1).getReg(); 3474 if (DestReg == TempReg) { 3475 SMLoc Loc = Operands.back()->getStartLoc(); 3476 return Error(Loc, "the temporary vector register cannot be the same as " 3477 "the destination register"); 3478 } 3479 } 3480 3481 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD || 3482 Opcode == RISCV::TH_LWD) { 3483 unsigned Rd1 = Inst.getOperand(0).getReg(); 3484 unsigned Rd2 = Inst.getOperand(1).getReg(); 3485 unsigned Rs1 = Inst.getOperand(2).getReg(); 3486 // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair. 3487 if (Rs1 == Rd1 && Rs1 == Rd2) { 3488 SMLoc Loc = Operands[1]->getStartLoc(); 3489 return Error(Loc, "rs1, rd1, and rd2 cannot all be the same"); 3490 } 3491 } 3492 3493 if (Opcode == RISCV::CM_MVSA01) { 3494 unsigned Rd1 = Inst.getOperand(0).getReg(); 3495 unsigned Rd2 = Inst.getOperand(1).getReg(); 3496 if (Rd1 == Rd2) { 3497 SMLoc Loc = Operands[1]->getStartLoc(); 3498 return Error(Loc, "rs1 and rs2 must be different"); 3499 } 3500 } 3501 3502 bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD || 3503 Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD); 3504 bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD); 3505 // The last operand of XTHeadMemPair instructions must be constant 3 or 4 3506 // depending on the data width. 3507 if (IsTHeadMemPair32 && Inst.getOperand(4).getImm() != 3) { 3508 SMLoc Loc = Operands.back()->getStartLoc(); 3509 return Error(Loc, "operand must be constant 3"); 3510 } else if (IsTHeadMemPair64 && Inst.getOperand(4).getImm() != 4) { 3511 SMLoc Loc = Operands.back()->getStartLoc(); 3512 return Error(Loc, "operand must be constant 4"); 3513 } 3514 3515 const MCInstrDesc &MCID = MII.get(Opcode); 3516 if (!(MCID.TSFlags & RISCVII::ConstraintMask)) 3517 return false; 3518 3519 if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW || 3520 Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) { 3521 // Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for VC_V_XVW. 3522 unsigned VCIXDst = Inst.getOperand(0).getReg(); 3523 SMLoc VCIXDstLoc = Operands[2]->getStartLoc(); 3524 if (MCID.TSFlags & RISCVII::VS1Constraint) { 3525 unsigned VCIXRs1 = Inst.getOperand(Inst.getNumOperands() - 1).getReg(); 3526 if (VCIXDst == VCIXRs1) 3527 return Error(VCIXDstLoc, "the destination vector register group cannot" 3528 " overlap the source vector register group"); 3529 } 3530 if (MCID.TSFlags & RISCVII::VS2Constraint) { 3531 unsigned VCIXRs2 = Inst.getOperand(Inst.getNumOperands() - 2).getReg(); 3532 if (VCIXDst == VCIXRs2) 3533 return Error(VCIXDstLoc, "the destination vector register group cannot" 3534 " overlap the source vector register group"); 3535 } 3536 return false; 3537 } 3538 3539 unsigned DestReg = Inst.getOperand(0).getReg(); 3540 unsigned Offset = 0; 3541 int TiedOp = MCID.getOperandConstraint(1, MCOI::TIED_TO); 3542 if (TiedOp == 0) 3543 Offset = 1; 3544 3545 // Operands[1] will be the first operand, DestReg. 3546 SMLoc Loc = Operands[1]->getStartLoc(); 3547 if (MCID.TSFlags & RISCVII::VS2Constraint) { 3548 unsigned CheckReg = Inst.getOperand(Offset + 1).getReg(); 3549 if (DestReg == CheckReg) 3550 return Error(Loc, "the destination vector register group cannot overlap" 3551 " the source vector register group"); 3552 } 3553 if ((MCID.TSFlags & RISCVII::VS1Constraint) && Inst.getOperand(Offset + 2).isReg()) { 3554 unsigned CheckReg = Inst.getOperand(Offset + 2).getReg(); 3555 if (DestReg == CheckReg) 3556 return Error(Loc, "the destination vector register group cannot overlap" 3557 " the source vector register group"); 3558 } 3559 if ((MCID.TSFlags & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) { 3560 // vadc, vsbc are special cases. These instructions have no mask register. 3561 // The destination register could not be V0. 3562 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM || 3563 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM || 3564 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM || 3565 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM || 3566 Opcode == RISCV::VMERGE_VXM) 3567 return Error(Loc, "the destination vector register group cannot be V0"); 3568 3569 // Regardless masked or unmasked version, the number of operands is the 3570 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister" 3571 // actually. We need to check the last operand to ensure whether it is 3572 // masked or not. 3573 unsigned CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg(); 3574 assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) && 3575 "Unexpected register for mask operand"); 3576 3577 if (DestReg == CheckReg) 3578 return Error(Loc, "the destination vector register group cannot overlap" 3579 " the mask register"); 3580 } 3581 return false; 3582 } 3583 3584 bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 3585 OperandVector &Operands, 3586 MCStreamer &Out) { 3587 Inst.setLoc(IDLoc); 3588 3589 switch (Inst.getOpcode()) { 3590 default: 3591 break; 3592 case RISCV::PseudoLLAImm: 3593 case RISCV::PseudoLAImm: 3594 case RISCV::PseudoLI: { 3595 MCRegister Reg = Inst.getOperand(0).getReg(); 3596 const MCOperand &Op1 = Inst.getOperand(1); 3597 if (Op1.isExpr()) { 3598 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar. 3599 // Just convert to an addi. This allows compatibility with gas. 3600 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI) 3601 .addReg(Reg) 3602 .addReg(RISCV::X0) 3603 .addExpr(Op1.getExpr())); 3604 return false; 3605 } 3606 int64_t Imm = Inst.getOperand(1).getImm(); 3607 // On RV32 the immediate here can either be a signed or an unsigned 3608 // 32-bit number. Sign extension has to be performed to ensure that Imm 3609 // represents the expected signed 64-bit number. 3610 if (!isRV64()) 3611 Imm = SignExtend64<32>(Imm); 3612 emitLoadImm(Reg, Imm, Out); 3613 return false; 3614 } 3615 case RISCV::PseudoLLA: 3616 emitLoadLocalAddress(Inst, IDLoc, Out); 3617 return false; 3618 case RISCV::PseudoLGA: 3619 emitLoadGlobalAddress(Inst, IDLoc, Out); 3620 return false; 3621 case RISCV::PseudoLA: 3622 emitLoadAddress(Inst, IDLoc, Out); 3623 return false; 3624 case RISCV::PseudoLA_TLS_IE: 3625 emitLoadTLSIEAddress(Inst, IDLoc, Out); 3626 return false; 3627 case RISCV::PseudoLA_TLS_GD: 3628 emitLoadTLSGDAddress(Inst, IDLoc, Out); 3629 return false; 3630 case RISCV::PseudoLB: 3631 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false); 3632 return false; 3633 case RISCV::PseudoLBU: 3634 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false); 3635 return false; 3636 case RISCV::PseudoLH: 3637 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false); 3638 return false; 3639 case RISCV::PseudoLHU: 3640 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false); 3641 return false; 3642 case RISCV::PseudoLW: 3643 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false); 3644 return false; 3645 case RISCV::PseudoLWU: 3646 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false); 3647 return false; 3648 case RISCV::PseudoLD: 3649 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false); 3650 return false; 3651 case RISCV::PseudoFLH: 3652 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true); 3653 return false; 3654 case RISCV::PseudoFLW: 3655 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true); 3656 return false; 3657 case RISCV::PseudoFLD: 3658 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true); 3659 return false; 3660 case RISCV::PseudoSB: 3661 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true); 3662 return false; 3663 case RISCV::PseudoSH: 3664 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true); 3665 return false; 3666 case RISCV::PseudoSW: 3667 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true); 3668 return false; 3669 case RISCV::PseudoSD: 3670 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true); 3671 return false; 3672 case RISCV::PseudoFSH: 3673 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true); 3674 return false; 3675 case RISCV::PseudoFSW: 3676 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true); 3677 return false; 3678 case RISCV::PseudoFSD: 3679 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true); 3680 return false; 3681 case RISCV::PseudoAddTPRel: 3682 if (checkPseudoAddTPRel(Inst, Operands)) 3683 return true; 3684 break; 3685 case RISCV::PseudoTLSDESCCall: 3686 if (checkPseudoTLSDESCCall(Inst, Operands)) 3687 return true; 3688 break; 3689 case RISCV::PseudoSEXT_B: 3690 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out); 3691 return false; 3692 case RISCV::PseudoSEXT_H: 3693 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out); 3694 return false; 3695 case RISCV::PseudoZEXT_H: 3696 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out); 3697 return false; 3698 case RISCV::PseudoZEXT_W: 3699 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out); 3700 return false; 3701 case RISCV::PseudoVMSGEU_VX: 3702 case RISCV::PseudoVMSGEU_VX_M: 3703 case RISCV::PseudoVMSGEU_VX_M_T: 3704 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out); 3705 return false; 3706 case RISCV::PseudoVMSGE_VX: 3707 case RISCV::PseudoVMSGE_VX_M: 3708 case RISCV::PseudoVMSGE_VX_M_T: 3709 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out); 3710 return false; 3711 case RISCV::PseudoVMSGE_VI: 3712 case RISCV::PseudoVMSLT_VI: { 3713 // These instructions are signed and so is immediate so we can subtract one 3714 // and change the opcode. 3715 int64_t Imm = Inst.getOperand(2).getImm(); 3716 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI 3717 : RISCV::VMSLE_VI; 3718 emitToStreamer(Out, MCInstBuilder(Opc) 3719 .addOperand(Inst.getOperand(0)) 3720 .addOperand(Inst.getOperand(1)) 3721 .addImm(Imm - 1) 3722 .addOperand(Inst.getOperand(3)) 3723 .setLoc(IDLoc)); 3724 return false; 3725 } 3726 case RISCV::PseudoVMSGEU_VI: 3727 case RISCV::PseudoVMSLTU_VI: { 3728 int64_t Imm = Inst.getOperand(2).getImm(); 3729 // Unsigned comparisons are tricky because the immediate is signed. If the 3730 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always 3731 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use 3732 // vmsne v0, v1, v1 which is always false. 3733 if (Imm == 0) { 3734 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI 3735 ? RISCV::VMSEQ_VV 3736 : RISCV::VMSNE_VV; 3737 emitToStreamer(Out, MCInstBuilder(Opc) 3738 .addOperand(Inst.getOperand(0)) 3739 .addOperand(Inst.getOperand(1)) 3740 .addOperand(Inst.getOperand(1)) 3741 .addOperand(Inst.getOperand(3)) 3742 .setLoc(IDLoc)); 3743 } else { 3744 // Other immediate values can subtract one like signed. 3745 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI 3746 ? RISCV::VMSGTU_VI 3747 : RISCV::VMSLEU_VI; 3748 emitToStreamer(Out, MCInstBuilder(Opc) 3749 .addOperand(Inst.getOperand(0)) 3750 .addOperand(Inst.getOperand(1)) 3751 .addImm(Imm - 1) 3752 .addOperand(Inst.getOperand(3)) 3753 .setLoc(IDLoc)); 3754 } 3755 3756 return false; 3757 } 3758 } 3759 3760 emitToStreamer(Out, Inst); 3761 return false; 3762 } 3763 3764 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmParser() { 3765 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target()); 3766 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target()); 3767 } 3768