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