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