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_InvalidUImmLog2XLenHalf:
1487 if (isRV64())
1488 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1489 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
1490 case Match_InvalidUImm1:
1491 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);
1492 case Match_InvalidUImm2:
1493 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
1494 case Match_InvalidUImm2Lsb0:
1495 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 2,
1496 "immediate must be one of");
1497 case Match_InvalidUImm3:
1498 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
1499 case Match_InvalidUImm4:
1500 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
1501 case Match_InvalidUImm5:
1502 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1503 case Match_InvalidUImm6:
1504 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
1505 case Match_InvalidUImm7:
1506 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
1507 case Match_InvalidUImm8:
1508 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);
1509 case Match_InvalidUImm8GE32:
1510 return generateImmOutOfRangeError(Operands, ErrorInfo, 32, (1 << 8) - 1);
1511 case Match_InvalidSImm5:
1512 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),
1513 (1 << 4) - 1);
1514 case Match_InvalidSImm6:
1515 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
1516 (1 << 5) - 1);
1517 case Match_InvalidSImm6NonZero:
1518 return generateImmOutOfRangeError(
1519 Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,
1520 "immediate must be non-zero in the range");
1521 case Match_InvalidCLUIImm:
1522 return generateImmOutOfRangeError(
1523 Operands, ErrorInfo, 1, (1 << 5) - 1,
1524 "immediate must be in [0xfffe0, 0xfffff] or");
1525 case Match_InvalidUImm5Lsb0:
1526 return generateImmOutOfRangeError(
1527 Operands, ErrorInfo, 0, (1 << 5) - 2,
1528 "immediate must be a multiple of 2 bytes in the range");
1529 case Match_InvalidUImm6Lsb0:
1530 return generateImmOutOfRangeError(
1531 Operands, ErrorInfo, 0, (1 << 6) - 2,
1532 "immediate must be a multiple of 2 bytes in the range");
1533 case Match_InvalidUImm7Lsb00:
1534 return generateImmOutOfRangeError(
1535 Operands, ErrorInfo, 0, (1 << 7) - 4,
1536 "immediate must be a multiple of 4 bytes in the range");
1537 case Match_InvalidUImm8Lsb00:
1538 return generateImmOutOfRangeError(
1539 Operands, ErrorInfo, 0, (1 << 8) - 4,
1540 "immediate must be a multiple of 4 bytes in the range");
1541 case Match_InvalidUImm8Lsb000:
1542 return generateImmOutOfRangeError(
1543 Operands, ErrorInfo, 0, (1 << 8) - 8,
1544 "immediate must be a multiple of 8 bytes in the range");
1545 case Match_InvalidSImm9Lsb0:
1546 return generateImmOutOfRangeError(
1547 Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
1548 "immediate must be a multiple of 2 bytes in the range");
1549 case Match_InvalidUImm9Lsb000:
1550 return generateImmOutOfRangeError(
1551 Operands, ErrorInfo, 0, (1 << 9) - 8,
1552 "immediate must be a multiple of 8 bytes in the range");
1553 case Match_InvalidUImm10Lsb00NonZero:
1554 return generateImmOutOfRangeError(
1555 Operands, ErrorInfo, 4, (1 << 10) - 4,
1556 "immediate must be a multiple of 4 bytes in the range");
1557 case Match_InvalidSImm10Lsb0000NonZero:
1558 return generateImmOutOfRangeError(
1559 Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
1560 "immediate must be a multiple of 16 bytes and non-zero in the range");
1561 case Match_InvalidSImm12:
1562 return generateImmOutOfRangeError(
1563 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
1564 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1565 "integer in the range");
1566 case Match_InvalidSImm12Lsb0:
1567 return generateImmOutOfRangeError(
1568 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
1569 "immediate must be a multiple of 2 bytes in the range");
1570 case Match_InvalidSImm12Lsb00000:
1571 return generateImmOutOfRangeError(
1572 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 32,
1573 "immediate must be a multiple of 32 bytes in the range");
1574 case Match_InvalidSImm13Lsb0:
1575 return generateImmOutOfRangeError(
1576 Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
1577 "immediate must be a multiple of 2 bytes in the range");
1578 case Match_InvalidUImm20LUI:
1579 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
1580 "operand must be a symbol with "
1581 "%hi/%tprel_hi modifier or an integer in "
1582 "the range");
1583 case Match_InvalidUImm20:
1584 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1);
1585 case Match_InvalidUImm20AUIPC:
1586 return generateImmOutOfRangeError(
1587 Operands, ErrorInfo, 0, (1 << 20) - 1,
1588 "operand must be a symbol with a "
1589 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1590 "an integer in the range");
1591 case Match_InvalidSImm21Lsb0JAL:
1592 return generateImmOutOfRangeError(
1593 Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
1594 "immediate must be a multiple of 2 bytes in the range");
1595 case Match_InvalidCSRSystemRegister: {
1596 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,
1597 "operand must be a valid system register "
1598 "name or an integer in the range");
1599 }
1600 case Match_InvalidLoadFPImm: {
1601 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1602 return Error(ErrorLoc, "operand must be a valid floating-point constant");
1603 }
1604 case Match_InvalidBareSymbol: {
1605 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1606 return Error(ErrorLoc, "operand must be a bare symbol name");
1607 }
1608 case Match_InvalidPseudoJumpSymbol: {
1609 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1610 return Error(ErrorLoc, "operand must be a valid jump target");
1611 }
1612 case Match_InvalidCallSymbol: {
1613 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1614 return Error(ErrorLoc, "operand must be a bare symbol name");
1615 }
1616 case Match_InvalidTPRelAddSymbol: {
1617 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1618 return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier");
1619 }
1620 case Match_InvalidTLSDESCCallSymbol: {
1621 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1622 return Error(ErrorLoc,
1623 "operand must be a symbol with %tlsdesc_call modifier");
1624 }
1625 case Match_InvalidRTZArg: {
1626 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1627 return Error(ErrorLoc, "operand must be 'rtz' floating-point rounding mode");
1628 }
1629 case Match_InvalidVTypeI: {
1630 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1631 return generateVTypeError(ErrorLoc);
1632 }
1633 case Match_InvalidVMaskRegister: {
1634 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1635 return Error(ErrorLoc, "operand must be v0.t");
1636 }
1637 case Match_InvalidSImm5Plus1: {
1638 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4) + 1,
1639 (1 << 4),
1640 "immediate must be in the range");
1641 }
1642 case Match_InvalidRlist: {
1643 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1644 return Error(
1645 ErrorLoc,
1646 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1647 }
1648 case Match_InvalidStackAdj: {
1649 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1650 return Error(
1651 ErrorLoc,
1652 "stack adjustment is invalid for this instruction and register list; "
1653 "refer to Zc spec for a detailed range of stack adjustment");
1654 }
1655 case Match_InvalidRnumArg: {
1656 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
1657 }
1658 case Match_InvalidRegReg: {
1659 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1660 return Error(ErrorLoc, "operands must be register and register");
1661 }
1662 }
1663
1664 llvm_unreachable("Unknown match type detected!");
1665}
1666
1667// Attempts to match Name as a register (either using the default name or
1668// alternative ABI names), setting RegNo to the matching register. Upon
1669// failure, returns a non-valid MCRegister. If IsRVE, then registers x16-x31
1670// will be rejected.
1671MCRegister RISCVAsmParser::matchRegisterNameHelper(StringRef Name) const {
1673 // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
1674 // match always matches the 64-bit variant, and not the 16/32-bit one.
1675 assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H));
1676 assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F));
1677 // The default FPR register class is based on the tablegen enum ordering.
1678 static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");
1679 static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
1680 if (!Reg)
1682 if (isRVE() && Reg >= RISCV::X16 && Reg <= RISCV::X31)
1683 Reg = RISCV::NoRegister;
1684 return Reg;
1685}
1686
1687bool RISCVAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
1688 SMLoc &EndLoc) {
1689 if (!tryParseRegister(Reg, StartLoc, EndLoc).isSuccess())
1690 return Error(StartLoc, "invalid register name");
1691 return false;
1692}
1693
1694ParseStatus RISCVAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
1695 SMLoc &EndLoc) {
1696 const AsmToken &Tok = getParser().getTok();
1697 StartLoc = Tok.getLoc();
1698 EndLoc = Tok.getEndLoc();
1699 StringRef Name = getLexer().getTok().getIdentifier();
1700
1702 if (!Reg)
1703 return ParseStatus::NoMatch;
1704
1705 getParser().Lex(); // Eat identifier token.
1706 return ParseStatus::Success;
1707}
1708
1709ParseStatus RISCVAsmParser::parseRegister(OperandVector &Operands,
1710 bool AllowParens) {
1711 SMLoc FirstS = getLoc();
1712 bool HadParens = false;
1713 AsmToken LParen;
1714
1715 // If this is an LParen and a parenthesised register name is allowed, parse it
1716 // atomically.
1717 if (AllowParens && getLexer().is(AsmToken::LParen)) {
1718 AsmToken Buf[2];
1719 size_t ReadCount = getLexer().peekTokens(Buf);
1720 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
1721 HadParens = true;
1722 LParen = getParser().getTok();
1723 getParser().Lex(); // Eat '('
1724 }
1725 }
1726
1727 switch (getLexer().getKind()) {
1728 default:
1729 if (HadParens)
1730 getLexer().UnLex(LParen);
1731 return ParseStatus::NoMatch;
1733 StringRef Name = getLexer().getTok().getIdentifier();
1735
1736 if (!RegNo) {
1737 if (HadParens)
1738 getLexer().UnLex(LParen);
1739 return ParseStatus::NoMatch;
1740 }
1741 if (HadParens)
1742 Operands.push_back(RISCVOperand::createToken("(", FirstS));
1743 SMLoc S = getLoc();
1745 getLexer().Lex();
1746 Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
1747 }
1748
1749 if (HadParens) {
1750 getParser().Lex(); // Eat ')'
1751 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
1752 }
1753
1754 return ParseStatus::Success;
1755}
1756
1757ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
1758 SMLoc S = getLoc();
1759 SMLoc E;
1760 const MCExpr *Res;
1761
1762 switch (getLexer().getKind()) {
1763 default:
1764 return ParseStatus::NoMatch;
1765 case AsmToken::LParen:
1766 case AsmToken::Minus:
1767 case AsmToken::Plus:
1768 case AsmToken::Exclaim:
1769 case AsmToken::Tilde:
1770 case AsmToken::Integer:
1771 case AsmToken::String: {
1772 if (getParser().parseExpression(Res, E))
1773 return ParseStatus::Failure;
1774
1775 auto *CE = dyn_cast<MCConstantExpr>(Res);
1776 if (CE) {
1777 int64_t Imm = CE->getValue();
1778 if (isUInt<7>(Imm)) {
1779 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1780 return ParseStatus::Success;
1781 }
1782 }
1783
1784 break;
1785 }
1786 case AsmToken::Identifier: {
1788 if (getParser().parseIdentifier(Identifier))
1789 return ParseStatus::Failure;
1790
1791 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1792 if (Opcode) {
1793 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&
1794 "Unexpected opcode");
1795 Res = MCConstantExpr::create(Opcode->Value, getContext());
1797 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1798 return ParseStatus::Success;
1799 }
1800
1801 break;
1802 }
1803 case AsmToken::Percent:
1804 break;
1805 }
1806
1807 return generateImmOutOfRangeError(
1808 S, 0, 127,
1809 "opcode must be a valid opcode name or an immediate in the range");
1810}
1811
1812ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
1813 SMLoc S = getLoc();
1814 SMLoc E;
1815 const MCExpr *Res;
1816
1817 switch (getLexer().getKind()) {
1818 default:
1819 return ParseStatus::NoMatch;
1820 case AsmToken::LParen:
1821 case AsmToken::Minus:
1822 case AsmToken::Plus:
1823 case AsmToken::Exclaim:
1824 case AsmToken::Tilde:
1825 case AsmToken::Integer:
1826 case AsmToken::String: {
1827 if (getParser().parseExpression(Res, E))
1828 return ParseStatus::Failure;
1829
1830 auto *CE = dyn_cast<MCConstantExpr>(Res);
1831 if (CE) {
1832 int64_t Imm = CE->getValue();
1833 if (Imm >= 0 && Imm <= 2) {
1834 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1835 return ParseStatus::Success;
1836 }
1837 }
1838
1839 break;
1840 }
1841 case AsmToken::Identifier: {
1843 if (getParser().parseIdentifier(Identifier))
1844 return ParseStatus::Failure;
1845
1846 unsigned Opcode;
1847 if (Identifier == "C0")
1848 Opcode = 0;
1849 else if (Identifier == "C1")
1850 Opcode = 1;
1851 else if (Identifier == "C2")
1852 Opcode = 2;
1853 else
1854 break;
1855
1856 Res = MCConstantExpr::create(Opcode, getContext());
1858 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1859 return ParseStatus::Success;
1860 }
1861 case AsmToken::Percent: {
1862 // Discard operand with modifier.
1863 break;
1864 }
1865 }
1866
1867 return generateImmOutOfRangeError(
1868 S, 0, 2,
1869 "opcode must be a valid opcode name or an immediate in the range");
1870}
1871
1872ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
1873 SMLoc S = getLoc();
1874 const MCExpr *Res;
1875
1876 switch (getLexer().getKind()) {
1877 default:
1878 return ParseStatus::NoMatch;
1879 case AsmToken::LParen:
1880 case AsmToken::Minus:
1881 case AsmToken::Plus:
1882 case AsmToken::Exclaim:
1883 case AsmToken::Tilde:
1884 case AsmToken::Integer:
1885 case AsmToken::String: {
1886 if (getParser().parseExpression(Res))
1887 return ParseStatus::Failure;
1888
1889 auto *CE = dyn_cast<MCConstantExpr>(Res);
1890 if (CE) {
1891 int64_t Imm = CE->getValue();
1892 if (isUInt<12>(Imm)) {
1893 auto Range = RISCVSysReg::lookupSysRegByEncoding(Imm);
1894 // Accept an immediate representing a named Sys Reg if it satisfies the
1895 // the required features.
1896 for (auto &Reg : Range) {
1897 if (Reg.haveRequiredFeatures(STI->getFeatureBits())) {
1898 Operands.push_back(RISCVOperand::createSysReg(Reg.Name, S, Imm));
1899 return ParseStatus::Success;
1900 }
1901 }
1902 // Accept an immediate representing an un-named Sys Reg if the range is
1903 // valid, regardless of the required features.
1904 Operands.push_back(RISCVOperand::createSysReg("", S, Imm));
1905 return ParseStatus::Success;
1906 }
1907 }
1908
1909 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1910 }
1911 case AsmToken::Identifier: {
1913 if (getParser().parseIdentifier(Identifier))
1914 return ParseStatus::Failure;
1915
1916 auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1917 if (!SysReg)
1918 SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);
1919 if (!SysReg)
1920 if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
1921 Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
1922 SysReg->Name + "'");
1923
1924 // Accept a named Sys Reg if the required features are present.
1925 if (SysReg) {
1926 if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits()))
1927 return Error(S, "system register use requires an option to be enabled");
1928 Operands.push_back(
1929 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
1930 return ParseStatus::Success;
1931 }
1932
1933 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
1934 "operand must be a valid system register "
1935 "name or an integer in the range");
1936 }
1937 case AsmToken::Percent: {
1938 // Discard operand with modifier.
1939 return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1940 }
1941 }
1942
1943 return ParseStatus::NoMatch;
1944}
1945
1946ParseStatus RISCVAsmParser::parseFPImm(OperandVector &Operands) {
1947 SMLoc S = getLoc();
1948
1949 // Parse special floats (inf/nan/min) representation.
1950 if (getTok().is(AsmToken::Identifier)) {
1951 StringRef Identifier = getTok().getIdentifier();
1952 if (Identifier.compare_insensitive("inf") == 0) {
1953 Operands.push_back(
1954 RISCVOperand::createImm(MCConstantExpr::create(30, getContext()), S,
1955 getTok().getEndLoc(), isRV64()));
1956 } else if (Identifier.compare_insensitive("nan") == 0) {
1957 Operands.push_back(
1958 RISCVOperand::createImm(MCConstantExpr::create(31, getContext()), S,
1959 getTok().getEndLoc(), isRV64()));
1960 } else if (Identifier.compare_insensitive("min") == 0) {
1961 Operands.push_back(
1962 RISCVOperand::createImm(MCConstantExpr::create(1, getContext()), S,
1963 getTok().getEndLoc(), isRV64()));
1964 } else {
1965 return TokError("invalid floating point literal");
1966 }
1967
1968 Lex(); // Eat the token.
1969
1970 return ParseStatus::Success;
1971 }
1972
1973 // Handle negation, as that still comes through as a separate token.
1974 bool IsNegative = parseOptionalToken(AsmToken::Minus);
1975
1976 const AsmToken &Tok = getTok();
1977 if (!Tok.is(AsmToken::Real))
1978 return TokError("invalid floating point immediate");
1979
1980 // Parse FP representation.
1981 APFloat RealVal(APFloat::IEEEdouble());
1982 auto StatusOrErr =
1983 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
1984 if (errorToBool(StatusOrErr.takeError()))
1985 return TokError("invalid floating point representation");
1986
1987 if (IsNegative)
1988 RealVal.changeSign();
1989
1990 Operands.push_back(RISCVOperand::createFPImm(
1991 RealVal.bitcastToAPInt().getZExtValue(), S));
1992
1993 Lex(); // Eat the token.
1994
1995 return ParseStatus::Success;
1996}
1997
1998ParseStatus RISCVAsmParser::parseImmediate(OperandVector &Operands) {
1999 SMLoc S = getLoc();
2000 SMLoc E;
2001 const MCExpr *Res;
2002
2003 switch (getLexer().getKind()) {
2004 default:
2005 return ParseStatus::NoMatch;
2006 case AsmToken::LParen:
2007 case AsmToken::Dot:
2008 case AsmToken::Minus:
2009 case AsmToken::Plus:
2010 case AsmToken::Exclaim:
2011 case AsmToken::Tilde:
2012 case AsmToken::Integer:
2013 case AsmToken::String:
2015 if (getParser().parseExpression(Res, E))
2016 return ParseStatus::Failure;
2017 break;
2018 case AsmToken::Percent:
2019 return parseOperandWithModifier(Operands);
2020 }
2021
2022 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2023 return ParseStatus::Success;
2024}
2025
2026ParseStatus RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
2027 SMLoc S = getLoc();
2028 SMLoc E;
2029
2030 if (parseToken(AsmToken::Percent, "expected '%' for operand modifier"))
2031 return ParseStatus::Failure;
2032
2033 if (getLexer().getKind() != AsmToken::Identifier)
2034 return Error(getLoc(), "expected valid identifier for operand modifier");
2035 StringRef Identifier = getParser().getTok().getIdentifier();
2038 return Error(getLoc(), "unrecognized operand modifier");
2039
2040 getParser().Lex(); // Eat the identifier
2041 if (parseToken(AsmToken::LParen, "expected '('"))
2042 return ParseStatus::Failure;
2043
2044 const MCExpr *SubExpr;
2045 if (getParser().parseParenExpression(SubExpr, E))
2046 return ParseStatus::Failure;
2047
2048 const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
2049 Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
2050 return ParseStatus::Success;
2051}
2052
2053ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
2054 SMLoc S = getLoc();
2055 const MCExpr *Res;
2056
2057 if (getLexer().getKind() != AsmToken::Identifier)
2058 return ParseStatus::NoMatch;
2059
2061 AsmToken Tok = getLexer().getTok();
2062
2063 if (getParser().parseIdentifier(Identifier))
2064 return ParseStatus::Failure;
2065
2067
2068 if (Identifier.consume_back("@plt"))
2069 return Error(getLoc(), "'@plt' operand not valid for instruction");
2070
2071 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2072
2073 if (Sym->isVariable()) {
2074 const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
2075 if (!isa<MCSymbolRefExpr>(V)) {
2076 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
2077 return ParseStatus::NoMatch;
2078 }
2079 Res = V;
2080 } else
2082
2083 MCBinaryExpr::Opcode Opcode;
2084 switch (getLexer().getKind()) {
2085 default:
2086 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2087 return ParseStatus::Success;
2088 case AsmToken::Plus:
2089 Opcode = MCBinaryExpr::Add;
2090 getLexer().Lex();
2091 break;
2092 case AsmToken::Minus:
2093 Opcode = MCBinaryExpr::Sub;
2094 getLexer().Lex();
2095 break;
2096 }
2097
2098 const MCExpr *Expr;
2099 if (getParser().parseExpression(Expr, E))
2100 return ParseStatus::Failure;
2101 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
2102 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2103 return ParseStatus::Success;
2104}
2105
2106ParseStatus RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {
2107 SMLoc S = getLoc();
2108 const MCExpr *Res;
2109
2110 if (getLexer().getKind() != AsmToken::Identifier)
2111 return ParseStatus::NoMatch;
2112
2113 // Avoid parsing the register in `call rd, foo` as a call symbol.
2114 if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement)
2115 return ParseStatus::NoMatch;
2116
2118 if (getParser().parseIdentifier(Identifier))
2119 return ParseStatus::Failure;
2120
2122
2124 (void)Identifier.consume_back("@plt");
2125
2126 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
2128 Res = RISCVMCExpr::create(Res, Kind, getContext());
2129 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2130 return ParseStatus::Success;
2131}
2132
2133ParseStatus RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
2134 SMLoc S = getLoc();
2135 SMLoc E;
2136 const MCExpr *Res;
2137
2138 if (getParser().parseExpression(Res, E))
2139 return ParseStatus::Failure;
2140
2141 if (Res->getKind() != MCExpr::ExprKind::SymbolRef ||
2142 cast<MCSymbolRefExpr>(Res)->getKind() ==
2143 MCSymbolRefExpr::VariantKind::VK_PLT)
2144 return Error(S, "operand must be a valid jump target");
2145
2146 Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext());
2147 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2148 return ParseStatus::Success;
2149}
2150
2151ParseStatus RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
2152 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
2153 // both being acceptable forms. When parsing `jal ra, foo` this function
2154 // will be called for the `ra` register operand in an attempt to match the
2155 // single-operand alias. parseJALOffset must fail for this case. It would
2156 // seem logical to try parse the operand using parseImmediate and return
2157 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
2158 // the second form rather than the first). We can't do this as there's no
2159 // way of rewinding the lexer state. Instead, return NoMatch if this operand
2160 // is an identifier and is followed by a comma.
2161 if (getLexer().is(AsmToken::Identifier) &&
2162 getLexer().peekTok().is(AsmToken::Comma))
2163 return ParseStatus::NoMatch;
2164
2165 return parseImmediate(Operands);
2166}
2167
2168bool RISCVAsmParser::parseVTypeToken(const AsmToken &Tok, VTypeState &State,
2169 unsigned &Sew, unsigned &Lmul,
2170 bool &Fractional, bool &TailAgnostic,
2171 bool &MaskAgnostic) {
2172 if (Tok.isNot(AsmToken::Identifier))
2173 return true;
2174
2176
2177 switch (State) {
2178 case VTypeState_SEW:
2179 if (!Identifier.consume_front("e"))
2180 break;
2181 if (Identifier.getAsInteger(10, Sew))
2182 break;
2183 if (!RISCVVType::isValidSEW(Sew))
2184 break;
2185 State = VTypeState_LMUL;
2186 return false;
2187 case VTypeState_LMUL: {
2188 if (!Identifier.consume_front("m"))
2189 break;
2190 Fractional = Identifier.consume_front("f");
2191 if (Identifier.getAsInteger(10, Lmul))
2192 break;
2193 if (!RISCVVType::isValidLMUL(Lmul, Fractional))
2194 break;
2195
2196 if (Fractional) {
2197 unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2198 unsigned MinLMUL = ELEN / 8;
2199 if (Lmul > MinLMUL)
2200 Warning(Tok.getLoc(),
2201 "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +
2202 Twine(MinLMUL) + " is reserved");
2203 }
2204
2205 State = VTypeState_TailPolicy;
2206 return false;
2207 }
2208 case VTypeState_TailPolicy:
2209 if (Identifier == "ta")
2210 TailAgnostic = true;
2211 else if (Identifier == "tu")
2212 TailAgnostic = false;
2213 else
2214 break;
2215 State = VTypeState_MaskPolicy;
2216 return false;
2217 case VTypeState_MaskPolicy:
2218 if (Identifier == "ma")
2219 MaskAgnostic = true;
2220 else if (Identifier == "mu")
2221 MaskAgnostic = false;
2222 else
2223 break;
2224 State = VTypeState_Done;
2225 return false;
2226 case VTypeState_Done:
2227 // Extra token?
2228 break;
2229 }
2230
2231 return true;
2232}
2233
2234ParseStatus RISCVAsmParser::parseVTypeI(OperandVector &Operands) {
2235 SMLoc S = getLoc();
2236
2237 unsigned Sew = 0;
2238 unsigned Lmul = 0;
2239 bool Fractional = false;
2240 bool TailAgnostic = false;
2241 bool MaskAgnostic = false;
2242
2243 VTypeState State = VTypeState_SEW;
2244 SMLoc SEWLoc = S;
2245
2246 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2247 MaskAgnostic))
2248 return ParseStatus::NoMatch;
2249
2250 getLexer().Lex();
2251
2252 while (parseOptionalToken(AsmToken::Comma)) {
2253 if (parseVTypeToken(getTok(), State, Sew, Lmul, Fractional, TailAgnostic,
2254 MaskAgnostic))
2255 break;
2256
2257 getLexer().Lex();
2258 }
2259
2260 if (getLexer().is(AsmToken::EndOfStatement) && State == VTypeState_Done) {
2261 RISCVII::VLMUL VLMUL = RISCVVType::encodeLMUL(Lmul, Fractional);
2262 if (Fractional) {
2263 unsigned ELEN = STI->hasFeature(RISCV::FeatureStdExtZve64x) ? 64 : 32;
2264 unsigned MaxSEW = ELEN / Lmul;
2265 // If MaxSEW < 8, we should have printed warning about reserved LMUL.
2266 if (MaxSEW >= 8 && Sew > MaxSEW)
2267 Warning(SEWLoc,
2268 "use of vtype encodings with SEW > " + Twine(MaxSEW) +
2269 " and LMUL == mf" + Twine(Lmul) +
2270 " may not be compatible with all RVV implementations");
2271 }
2272
2273 unsigned VTypeI =
2274 RISCVVType::encodeVTYPE(VLMUL, Sew, TailAgnostic, MaskAgnostic);
2275 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2276 return ParseStatus::Success;
2277 }
2278
2279 return generateVTypeError(S);
2280}
2281
2282bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc) {
2283 return Error(
2284 ErrorLoc,
2285 "operand must be "
2286 "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2287}
2288
2289ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
2290 if (getLexer().isNot(AsmToken::Identifier))
2291 return ParseStatus::NoMatch;
2292
2293 StringRef Name = getLexer().getTok().getIdentifier();
2294 if (!Name.consume_back(".t"))
2295 return Error(getLoc(), "expected '.t' suffix");
2297
2298 if (!RegNo)
2299 return ParseStatus::NoMatch;
2300 if (RegNo != RISCV::V0)
2301 return ParseStatus::NoMatch;
2302 SMLoc S = getLoc();
2304 getLexer().Lex();
2305 Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
2306 return ParseStatus::Success;
2307}
2308
2309ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
2310 if (getLexer().isNot(AsmToken::Identifier))
2311 return ParseStatus::NoMatch;
2312
2313 StringRef Name = getLexer().getTok().getIdentifier();
2315
2316 if (!RegNo)
2317 return ParseStatus::NoMatch;
2318 SMLoc S = getLoc();
2320 getLexer().Lex();
2321 Operands.push_back(RISCVOperand::createReg(
2322 RegNo, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2323 return ParseStatus::Success;
2324}
2325
2326template <bool IsRV64>
2327ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands) {
2328 return parseGPRPair(Operands, IsRV64);
2329}
2330
2331ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands,
2332 bool IsRV64Inst) {
2333 // If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on
2334 // RV64 as it will prevent matching the RV64 version of the same instruction
2335 // that doesn't use a GPRPair.
2336 // If this is an RV64 GPRPair instruction, there is no RV32 version so we can
2337 // still parse as a pair.
2338 if (!IsRV64Inst && isRV64())
2339 return ParseStatus::NoMatch;
2340
2341 if (getLexer().isNot(AsmToken::Identifier))
2342 return ParseStatus::NoMatch;
2343
2344 StringRef Name = getLexer().getTok().getIdentifier();
2346
2347 if (!RegNo)
2348 return ParseStatus::NoMatch;
2349
2350 if (!RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(RegNo))
2351 return ParseStatus::NoMatch;
2352
2353 if ((RegNo - RISCV::X0) & 1)
2354 return TokError("register must be even");
2355
2356 SMLoc S = getLoc();
2358 getLexer().Lex();
2359
2360 const MCRegisterInfo *RI = getContext().getRegisterInfo();
2361 unsigned Pair = RI->getMatchingSuperReg(
2362 RegNo, RISCV::sub_gpr_even,
2363 &RISCVMCRegisterClasses[RISCV::GPRPairRegClassID]);
2364 Operands.push_back(RISCVOperand::createReg(Pair, S, E));
2365 return ParseStatus::Success;
2366}
2367
2368ParseStatus RISCVAsmParser::parseFRMArg(OperandVector &Operands) {
2369 if (getLexer().isNot(AsmToken::Identifier))
2370 return TokError(
2371 "operand must be a valid floating point rounding mode mnemonic");
2372
2373 StringRef Str = getLexer().getTok().getIdentifier();
2375
2376 if (FRM == RISCVFPRndMode::Invalid)
2377 return TokError(
2378 "operand must be a valid floating point rounding mode mnemonic");
2379
2380 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2381 Lex(); // Eat identifier token.
2382 return ParseStatus::Success;
2383}
2384
2385ParseStatus RISCVAsmParser::parseFenceArg(OperandVector &Operands) {
2386 const AsmToken &Tok = getLexer().getTok();
2387
2388 if (Tok.is(AsmToken::Integer)) {
2389 if (Tok.getIntVal() != 0)
2390 goto ParseFail;
2391
2392 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2393 Lex();
2394 return ParseStatus::Success;
2395 }
2396
2397 if (Tok.is(AsmToken::Identifier)) {
2398 StringRef Str = Tok.getIdentifier();
2399
2400 // Letters must be unique, taken from 'iorw', and in ascending order. This
2401 // holds as long as each individual character is one of 'iorw' and is
2402 // greater than the previous character.
2403 unsigned Imm = 0;
2404 bool Valid = true;
2405 char Prev = '\0';
2406 for (char c : Str) {
2407 switch (c) {
2408 default:
2409 Valid = false;
2410 break;
2411 case 'i':
2413 break;
2414 case 'o':
2416 break;
2417 case 'r':
2419 break;
2420 case 'w':
2422 break;
2423 }
2424
2425 if (c <= Prev) {
2426 Valid = false;
2427 break;
2428 }
2429 Prev = c;
2430 }
2431
2432 if (!Valid)
2433 goto ParseFail;
2434
2435 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2436 Lex();
2437 return ParseStatus::Success;
2438 }
2439
2440ParseFail:
2441 return TokError("operand must be formed of letters selected in-order from "
2442 "'iorw' or be 0");
2443}
2444
2445ParseStatus RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
2446 if (parseToken(AsmToken::LParen, "expected '('"))
2447 return ParseStatus::Failure;
2448 Operands.push_back(RISCVOperand::createToken("(", getLoc()));
2449
2450 if (!parseRegister(Operands).isSuccess())
2451 return Error(getLoc(), "expected register");
2452
2453 if (parseToken(AsmToken::RParen, "expected ')'"))
2454 return ParseStatus::Failure;
2455 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
2456
2457 return ParseStatus::Success;
2458}
2459
2460ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {
2461 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
2462 // as one of their register operands, such as `(a0)`. This just denotes that
2463 // the register (in this case `a0`) contains a memory address.
2464 //
2465 // Normally, we would be able to parse these by putting the parens into the
2466 // instruction string. However, GNU as also accepts a zero-offset memory
2467 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
2468 // with parseImmediate followed by parseMemOpBaseReg, but these instructions
2469 // do not accept an immediate operand, and we do not want to add a "dummy"
2470 // operand that is silently dropped.
2471 //
2472 // Instead, we use this custom parser. This will: allow (and discard) an
2473 // offset if it is zero; require (and discard) parentheses; and add only the
2474 // parsed register operand to `Operands`.
2475 //
2476 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
2477 // which will only print the register surrounded by parentheses (which GNU as
2478 // also uses as its canonical representation for these operands).
2479 std::unique_ptr<RISCVOperand> OptionalImmOp;
2480
2481 if (getLexer().isNot(AsmToken::LParen)) {
2482 // Parse an Integer token. We do not accept arbritrary constant expressions
2483 // in the offset field (because they may include parens, which complicates
2484 // parsing a lot).
2485 int64_t ImmVal;
2486 SMLoc ImmStart = getLoc();
2487 if (getParser().parseIntToken(ImmVal,
2488 "expected '(' or optional integer offset"))
2489 return ParseStatus::Failure;
2490
2491 // Create a RISCVOperand for checking later (so the error messages are
2492 // nicer), but we don't add it to Operands.
2493 SMLoc ImmEnd = getLoc();
2494 OptionalImmOp =
2495 RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()),
2496 ImmStart, ImmEnd, isRV64());
2497 }
2498
2499 if (parseToken(AsmToken::LParen,
2500 OptionalImmOp ? "expected '(' after optional integer offset"
2501 : "expected '(' or optional integer offset"))
2502 return ParseStatus::Failure;
2503
2504 if (!parseRegister(Operands).isSuccess())
2505 return Error(getLoc(), "expected register");
2506
2507 if (parseToken(AsmToken::RParen, "expected ')'"))
2508 return ParseStatus::Failure;
2509
2510 // Deferred Handling of non-zero offsets. This makes the error messages nicer.
2511 if (OptionalImmOp && !OptionalImmOp->isImmZero())
2512 return Error(
2513 OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
2514 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2515
2516 return ParseStatus::Success;
2517}
2518
2519ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
2520 // RR : a2(a1)
2521 if (getLexer().getKind() != AsmToken::Identifier)
2522 return ParseStatus::NoMatch;
2523
2524 StringRef RegName = getLexer().getTok().getIdentifier();
2526 if (!Reg)
2527 return Error(getLoc(), "invalid register");
2528 getLexer().Lex();
2529
2530 if (parseToken(AsmToken::LParen, "expected '(' or invalid operand"))
2531 return ParseStatus::Failure;
2532
2533 if (getLexer().getKind() != AsmToken::Identifier)
2534 return Error(getLoc(), "expected register");
2535
2536 StringRef Reg2Name = getLexer().getTok().getIdentifier();
2537 MCRegister Reg2 = matchRegisterNameHelper(Reg2Name);
2538 if (!Reg2)
2539 return Error(getLoc(), "invalid register");
2540 getLexer().Lex();
2541
2542 if (parseToken(AsmToken::RParen, "expected ')'"))
2543 return ParseStatus::Failure;
2544
2545 Operands.push_back(RISCVOperand::createRegReg(Reg, Reg2, getLoc()));
2546
2547 return ParseStatus::Success;
2548}
2549
2550ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
2551 // Rlist: {ra [, s0[-sN]]}
2552 // XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
2553 SMLoc S = getLoc();
2554
2555 if (parseToken(AsmToken::LCurly, "register list must start with '{'"))
2556 return ParseStatus::Failure;
2557
2558 bool IsEABI = isRVE();
2559
2560 if (getLexer().isNot(AsmToken::Identifier))
2561 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2562
2563 StringRef RegName = getLexer().getTok().getIdentifier();
2565 MCRegister RegEnd;
2566 if (RegStart != RISCV::X1)
2567 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2568 getLexer().Lex();
2569
2570 // parse case like ,s0
2571 if (parseOptionalToken(AsmToken::Comma)) {
2572 if (getLexer().isNot(AsmToken::Identifier))
2573 return Error(getLoc(), "invalid register");
2574 StringRef RegName = getLexer().getTok().getIdentifier();
2575 RegStart = matchRegisterNameHelper(RegName);
2576 if (!RegStart)
2577 return Error(getLoc(), "invalid register");
2578 if (RegStart != RISCV::X8)
2579 return Error(getLoc(),
2580 "continuous register list must start from 's0' or 'x8'");
2581 getLexer().Lex(); // eat reg
2582 }
2583
2584 // parse case like -s1
2585 if (parseOptionalToken(AsmToken::Minus)) {
2586 StringRef EndName = getLexer().getTok().getIdentifier();
2587 // FIXME: the register mapping and checks of EABI is wrong
2588 RegEnd = matchRegisterNameHelper(EndName);
2589 if (!RegEnd)
2590 return Error(getLoc(), "invalid register");
2591 if (IsEABI && RegEnd != RISCV::X9)
2592 return Error(getLoc(), "contiguous register list of EABI can only be "
2593 "'s0-s1' or 'x8-x9' pair");
2594 getLexer().Lex();
2595 }
2596
2597 if (!IsEABI) {
2598 // parse extra part like ', x18[-x20]' for XRegList
2599 if (parseOptionalToken(AsmToken::Comma)) {
2600 if (RegEnd != RISCV::X9)
2601 return Error(
2602 getLoc(),
2603 "first contiguous registers pair of register list must be 'x8-x9'");
2604
2605 // parse ', x18' for extra part
2606 if (getLexer().isNot(AsmToken::Identifier))
2607 return Error(getLoc(), "invalid register");
2608 StringRef EndName = getLexer().getTok().getIdentifier();
2609 if (MatchRegisterName(EndName) != RISCV::X18)
2610 return Error(getLoc(),
2611 "second contiguous registers pair of register list "
2612 "must start from 'x18'");
2613 getLexer().Lex();
2614
2615 // parse '-x20' for extra part
2616 if (parseOptionalToken(AsmToken::Minus)) {
2617 if (getLexer().isNot(AsmToken::Identifier))
2618 return Error(getLoc(), "invalid register");
2619 EndName = getLexer().getTok().getIdentifier();
2620 if (MatchRegisterName(EndName) == RISCV::NoRegister)
2621 return Error(getLoc(), "invalid register");
2622 getLexer().Lex();
2623 }
2624 RegEnd = MatchRegisterName(EndName);
2625 }
2626 }
2627
2628 if (RegEnd == RISCV::X26)
2629 return Error(getLoc(), "invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2630 "x18-x26} is not supported");
2631
2632 if (parseToken(AsmToken::RCurly, "register list must end with '}'"))
2633 return ParseStatus::Failure;
2634
2635 if (RegEnd == RISCV::NoRegister)
2636 RegEnd = RegStart;
2637
2638 auto Encode = RISCVZC::encodeRlist(RegEnd, IsEABI);
2639 if (Encode == RISCVZC::INVALID_RLIST)
2640 return Error(S, "invalid register list");
2641 Operands.push_back(RISCVOperand::createRlist(Encode, S));
2642
2643 return ParseStatus::Success;
2644}
2645
2646ParseStatus RISCVAsmParser::parseZcmpStackAdj(OperandVector &Operands,
2647 bool ExpectNegative) {
2648 bool Negative = parseOptionalToken(AsmToken::Minus);
2649
2650 SMLoc S = getLoc();
2651 int64_t StackAdjustment = getLexer().getTok().getIntVal();
2652 unsigned Spimm = 0;
2653 unsigned RlistVal = static_cast<RISCVOperand *>(Operands[1].get())->Rlist.Val;
2654
2655 if (Negative != ExpectNegative ||
2656 !RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64()))
2657 return ParseStatus::NoMatch;
2658 Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
2659 getLexer().Lex();
2660 return ParseStatus::Success;
2661}
2662
2663/// Looks at a token type and creates the relevant operand from this
2664/// information, adding to Operands. If operand was parsed, returns false, else
2665/// true.
2666bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2667 // Check if the current operand has a custom associated parser, if so, try to
2668 // custom parse the operand, or fallback to the general approach.
2670 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
2671 if (Result.isSuccess())
2672 return false;
2673 if (Result.isFailure())
2674 return true;
2675
2676 // Attempt to parse token as a register.
2677 if (parseRegister(Operands, true).isSuccess())
2678 return false;
2679
2680 // Attempt to parse token as an immediate
2681 if (parseImmediate(Operands).isSuccess()) {
2682 // Parse memory base register if present
2683 if (getLexer().is(AsmToken::LParen))
2684 return !parseMemOpBaseReg(Operands).isSuccess();
2685 return false;
2686 }
2687
2688 // Finally we have exhausted all options and must declare defeat.
2689 Error(getLoc(), "unknown operand");
2690 return true;
2691}
2692
2693bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
2694 StringRef Name, SMLoc NameLoc,
2696 // Ensure that if the instruction occurs when relaxation is enabled,
2697 // relocations are forced for the file. Ideally this would be done when there
2698 // is enough information to reliably determine if the instruction itself may
2699 // cause relaxations. Unfortunately instruction processing stage occurs in the
2700 // same pass as relocation emission, so it's too late to set a 'sticky bit'
2701 // for the entire file.
2702 if (getSTI().hasFeature(RISCV::FeatureRelax)) {
2703 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
2704 if (Assembler != nullptr) {
2705 RISCVAsmBackend &MAB =
2706 static_cast<RISCVAsmBackend &>(Assembler->getBackend());
2707 MAB.setForceRelocs();
2708 }
2709 }
2710
2711 // First operand is token for instruction
2712 Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
2713
2714 // If there are no more operands, then finish
2715 if (getLexer().is(AsmToken::EndOfStatement)) {
2716 getParser().Lex(); // Consume the EndOfStatement.
2717 return false;
2718 }
2719
2720 // Parse first operand
2721 if (parseOperand(Operands, Name))
2722 return true;
2723
2724 // Parse until end of statement, consuming commas between operands
2725 while (parseOptionalToken(AsmToken::Comma)) {
2726 // Parse next operand
2727 if (parseOperand(Operands, Name))
2728 return true;
2729 }
2730
2731 if (getParser().parseEOL("unexpected token")) {
2732 getParser().eatToEndOfStatement();
2733 return true;
2734 }
2735 return false;
2736}
2737
2738bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
2741
2742 if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
2743 Kind = RE->getKind();
2744 Expr = RE->getSubExpr();
2745 }
2746
2747 MCValue Res;
2748 MCFixup Fixup;
2749 if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup))
2750 return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None;
2751 return false;
2752}
2753
2754bool RISCVAsmParser::isSymbolDiff(const MCExpr *Expr) {
2755 MCValue Res;
2756 MCFixup Fixup;
2757 if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup)) {
2758 return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None && Res.getSymA() &&
2759 Res.getSymB();
2760 }
2761 return false;
2762}
2763
2764ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) {
2765 StringRef IDVal = DirectiveID.getString();
2766
2767 if (IDVal == ".option")
2768 return parseDirectiveOption();
2769 if (IDVal == ".attribute")
2770 return parseDirectiveAttribute();
2771 if (IDVal == ".insn")
2772 return parseDirectiveInsn(DirectiveID.getLoc());
2773 if (IDVal == ".variant_cc")
2774 return parseDirectiveVariantCC();
2775
2776 return ParseStatus::NoMatch;
2777}
2778
2779bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
2780 bool FromOptionDirective) {
2781 for (auto &Feature : RISCVFeatureKV)
2783 clearFeatureBits(Feature.Value, Feature.Key);
2784
2786 Arch, /*EnableExperimentalExtension=*/true,
2787 /*ExperimentalExtensionVersionCheck=*/true);
2788 if (!ParseResult) {
2789 std::string Buffer;
2790 raw_string_ostream OutputErrMsg(Buffer);
2791 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2792 OutputErrMsg << "invalid arch name '" << Arch << "', "
2793 << ErrMsg.getMessage();
2794 });
2795
2796 return Error(Loc, OutputErrMsg.str());
2797 }
2798 auto &ISAInfo = *ParseResult;
2799
2800 for (auto &Feature : RISCVFeatureKV)
2801 if (ISAInfo->hasExtension(Feature.Key))
2802 setFeatureBits(Feature.Value, Feature.Key);
2803
2804 if (FromOptionDirective) {
2805 if (ISAInfo->getXLen() == 32 && isRV64())
2806 return Error(Loc, "bad arch string switching from rv64 to rv32");
2807 else if (ISAInfo->getXLen() == 64 && !isRV64())
2808 return Error(Loc, "bad arch string switching from rv32 to rv64");
2809 }
2810
2811 if (ISAInfo->getXLen() == 32)
2812 clearFeatureBits(RISCV::Feature64Bit, "64bit");
2813 else if (ISAInfo->getXLen() == 64)
2814 setFeatureBits(RISCV::Feature64Bit, "64bit");
2815 else
2816 return Error(Loc, "bad arch string " + Arch);
2817
2818 Result = ISAInfo->toString();
2819 return false;
2820}
2821
2822bool RISCVAsmParser::parseDirectiveOption() {
2823 MCAsmParser &Parser = getParser();
2824 // Get the option token.
2825 AsmToken Tok = Parser.getTok();
2826
2827 // At the moment only identifiers are supported.
2828 if (parseToken(AsmToken::Identifier, "expected identifier"))
2829 return true;
2830
2832
2833 if (Option == "push") {
2834 if (Parser.parseEOL())
2835 return true;
2836
2837 getTargetStreamer().emitDirectiveOptionPush();
2838 pushFeatureBits();
2839 return false;
2840 }
2841
2842 if (Option == "pop") {
2843 SMLoc StartLoc = Parser.getTok().getLoc();
2844 if (Parser.parseEOL())
2845 return true;
2846
2847 getTargetStreamer().emitDirectiveOptionPop();
2848 if (popFeatureBits())
2849 return Error(StartLoc, ".option pop with no .option push");
2850
2851 return false;
2852 }
2853
2854 if (Option == "arch") {
2856 do {
2857 if (Parser.parseComma())
2858 return true;
2859
2861 if (parseOptionalToken(AsmToken::Plus))
2862 Type = RISCVOptionArchArgType::Plus;
2863 else if (parseOptionalToken(AsmToken::Minus))
2864 Type = RISCVOptionArchArgType::Minus;
2865 else if (!Args.empty())
2866 return Error(Parser.getTok().getLoc(),
2867 "unexpected token, expected + or -");
2868 else
2869 Type = RISCVOptionArchArgType::Full;
2870
2871 if (Parser.getTok().isNot(AsmToken::Identifier))
2872 return Error(Parser.getTok().getLoc(),
2873 "unexpected token, expected identifier");
2874
2875 StringRef Arch = Parser.getTok().getString();
2876 SMLoc Loc = Parser.getTok().getLoc();
2877 Parser.Lex();
2878
2879 if (Type == RISCVOptionArchArgType::Full) {
2880 std::string Result;
2881 if (resetToArch(Arch, Loc, Result, true))
2882 return true;
2883
2884 Args.emplace_back(Type, Result);
2885 break;
2886 }
2887
2888 if (isDigit(Arch.back()))
2889 return Error(
2890 Loc, "extension version number parsing not currently implemented");
2891
2892 std::string Feature = RISCVISAInfo::getTargetFeatureForExtension(Arch);
2893 if (!enableExperimentalExtension() &&
2894 StringRef(Feature).starts_with("experimental-"))
2895 return Error(Loc, "unexpected experimental extensions");
2896 auto Ext = llvm::lower_bound(RISCVFeatureKV, Feature);
2897 if (Ext == std::end(RISCVFeatureKV) || StringRef(Ext->Key) != Feature)
2898 return Error(Loc, "unknown extension feature");
2899
2900 Args.emplace_back(Type, Arch.str());
2901
2902 if (Type == RISCVOptionArchArgType::Plus) {
2903 FeatureBitset OldFeatureBits = STI->getFeatureBits();
2904
2905 setFeatureBits(Ext->Value, Ext->Key);
2907 if (!ParseResult) {
2908 copySTI().setFeatureBits(OldFeatureBits);
2909 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits));
2910
2911 std::string Buffer;
2912 raw_string_ostream OutputErrMsg(Buffer);
2913 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2914 OutputErrMsg << ErrMsg.getMessage();
2915 });
2916
2917 return Error(Loc, OutputErrMsg.str());
2918 }
2919 } else {
2920 assert(Type == RISCVOptionArchArgType::Minus);
2921 // It is invalid to disable an extension that there are other enabled
2922 // extensions depend on it.
2923 // TODO: Make use of RISCVISAInfo to handle this
2924 for (auto &Feature : RISCVFeatureKV) {
2925 if (getSTI().hasFeature(Feature.Value) &&
2926 Feature.Implies.test(Ext->Value))
2927 return Error(Loc, Twine("can't disable ") + Ext->Key +
2928 " extension; " + Feature.Key +
2929 " extension requires " + Ext->Key +
2930 " extension");
2931 }
2932
2933 clearFeatureBits(Ext->Value, Ext->Key);
2934 }
2935 } while (Parser.getTok().isNot(AsmToken::EndOfStatement));
2936
2937 if (Parser.parseEOL())
2938 return true;
2939
2940 getTargetStreamer().emitDirectiveOptionArch(Args);
2941 return false;
2942 }
2943
2944 if (Option == "rvc") {
2945 if (Parser.parseEOL())
2946 return true;
2947
2948 getTargetStreamer().emitDirectiveOptionRVC();
2949 setFeatureBits(RISCV::FeatureStdExtC, "c");
2950 return false;
2951 }
2952
2953 if (Option == "norvc") {
2954 if (Parser.parseEOL())
2955 return true;
2956
2957 getTargetStreamer().emitDirectiveOptionNoRVC();
2958 clearFeatureBits(RISCV::FeatureStdExtC, "c");
2959 clearFeatureBits(RISCV::FeatureStdExtZca, "zca");
2960 return false;
2961 }
2962
2963 if (Option == "pic") {
2964 if (Parser.parseEOL())
2965 return true;
2966
2967 getTargetStreamer().emitDirectiveOptionPIC();
2968 ParserOptions.IsPicEnabled = true;
2969 return false;
2970 }
2971
2972 if (Option == "nopic") {
2973 if (Parser.parseEOL())
2974 return true;
2975
2976 getTargetStreamer().emitDirectiveOptionNoPIC();
2977 ParserOptions.IsPicEnabled = false;
2978 return false;
2979 }
2980
2981 if (Option == "relax") {
2982 if (Parser.parseEOL())
2983 return true;
2984
2985 getTargetStreamer().emitDirectiveOptionRelax();
2986 setFeatureBits(RISCV::FeatureRelax, "relax");
2987 return false;
2988 }
2989
2990 if (Option == "norelax") {
2991 if (Parser.parseEOL())
2992 return true;
2993
2994 getTargetStreamer().emitDirectiveOptionNoRelax();
2995 clearFeatureBits(RISCV::FeatureRelax, "relax");
2996 return false;
2997 }
2998
2999 // Unknown option.
3000 Warning(Parser.getTok().getLoc(), "unknown option, expected 'push', 'pop', "
3001 "'rvc', 'norvc', 'arch', 'relax' or "
3002 "'norelax'");
3003 Parser.eatToEndOfStatement();
3004 return false;
3005}
3006
3007/// parseDirectiveAttribute
3008/// ::= .attribute expression ',' ( expression | "string" )
3009/// ::= .attribute identifier ',' ( expression | "string" )
3010bool RISCVAsmParser::parseDirectiveAttribute() {
3011 MCAsmParser &Parser = getParser();
3012 int64_t Tag;
3013 SMLoc TagLoc;
3014 TagLoc = Parser.getTok().getLoc();
3015 if (Parser.getTok().is(AsmToken::Identifier)) {
3016 StringRef Name = Parser.getTok().getIdentifier();
3017 std::optional<unsigned> Ret =
3019 if (!Ret)
3020 return Error(TagLoc, "attribute name not recognised: " + Name);
3021 Tag = *Ret;
3022 Parser.Lex();
3023 } else {
3024 const MCExpr *AttrExpr;
3025
3026 TagLoc = Parser.getTok().getLoc();
3027 if (Parser.parseExpression(AttrExpr))
3028 return true;
3029
3030 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
3031 if (check(!CE, TagLoc, "expected numeric constant"))
3032 return true;
3033
3034 Tag = CE->getValue();
3035 }
3036
3037 if (Parser.parseComma())
3038 return true;
3039
3040 StringRef StringValue;
3041 int64_t IntegerValue = 0;
3042 bool IsIntegerValue = true;
3043
3044 // RISC-V attributes have a string value if the tag number is odd
3045 // and an integer value if the tag number is even.
3046 if (Tag % 2)
3047 IsIntegerValue = false;
3048
3049 SMLoc ValueExprLoc = Parser.getTok().getLoc();
3050 if (IsIntegerValue) {
3051 const MCExpr *ValueExpr;
3052 if (Parser.parseExpression(ValueExpr))
3053 return true;
3054
3055 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
3056 if (!CE)
3057 return Error(ValueExprLoc, "expected numeric constant");
3058 IntegerValue = CE->getValue();
3059 } else {
3060 if (Parser.getTok().isNot(AsmToken::String))
3061 return Error(Parser.getTok().getLoc(), "expected string constant");
3062
3063 StringValue = Parser.getTok().getStringContents();
3064 Parser.Lex();
3065 }
3066
3067 if (Parser.parseEOL())
3068 return true;
3069
3070 if (IsIntegerValue)
3071 getTargetStreamer().emitAttribute(Tag, IntegerValue);
3072 else if (Tag != RISCVAttrs::ARCH)
3073 getTargetStreamer().emitTextAttribute(Tag, StringValue);
3074 else {
3075 std::string Result;
3076 if (resetToArch(StringValue, ValueExprLoc, Result, false))
3077 return true;
3078
3079 // Then emit the arch string.
3080 getTargetStreamer().emitTextAttribute(Tag, Result);
3081 }
3082
3083 return false;
3084}
3085
3086bool isValidInsnFormat(StringRef Format, bool AllowC) {
3087 return StringSwitch<bool>(Format)
3088 .Cases("r", "r4", "i", "b", "sb", "u", "j", "uj", "s", true)
3089 .Cases("cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj", AllowC)
3090 .Default(false);
3091}
3092
3093/// parseDirectiveInsn
3094/// ::= .insn [ format encoding, (operands (, operands)*) ]
3095/// ::= .insn [ length, value ]
3096/// ::= .insn [ value ]
3097bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
3098 MCAsmParser &Parser = getParser();
3099
3100 bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
3101 getSTI().hasFeature(RISCV::FeatureStdExtZca);
3102
3103 // Expect instruction format as identifier.
3105 SMLoc ErrorLoc = Parser.getTok().getLoc();
3106 if (Parser.parseIdentifier(Format)) {
3107 // Try parsing .insn [length], value
3108 int64_t Length = 0;
3109 int64_t Value = 0;
3110 if (Parser.parseIntToken(
3111 Value, "expected instruction format or an integer constant"))
3112 return true;
3113 if (Parser.parseOptionalToken(AsmToken::Comma)) {
3114 Length = Value;
3115 if (Parser.parseIntToken(Value, "expected an integer constant"))
3116 return true;
3117 }
3118
3119 // TODO: Add support for long instructions
3120 int64_t RealLength = (Value & 3) == 3 ? 4 : 2;
3121 if (!isUIntN(RealLength * 8, Value))
3122 return Error(ErrorLoc, "invalid operand for instruction");
3123 if (RealLength == 2 && !AllowC)
3124 return Error(ErrorLoc, "compressed instructions are not allowed");
3125 if (Length != 0 && Length != RealLength)
3126 return Error(ErrorLoc, "instruction length mismatch");
3127
3128 if (getParser().parseEOL("invalid operand for instruction")) {
3129 getParser().eatToEndOfStatement();
3130 return true;
3131 }
3132
3133 emitToStreamer(getStreamer(), MCInstBuilder(RealLength == 2 ? RISCV::Insn16
3134 : RISCV::Insn32)
3135 .addImm(Value));
3136 return false;
3137 }
3138
3139 if (!isValidInsnFormat(Format, AllowC))
3140 return Error(ErrorLoc, "invalid instruction format");
3141
3142 std::string FormatName = (".insn_" + Format).str();
3143
3146
3147 if (ParseInstruction(Info, FormatName, L, Operands))
3148 return true;
3149
3150 unsigned Opcode;
3152 return MatchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),
3153 ErrorInfo,
3154 /*MatchingInlineAsm=*/false);
3155}
3156
3157/// parseDirectiveVariantCC
3158/// ::= .variant_cc symbol
3159bool RISCVAsmParser::parseDirectiveVariantCC() {
3161 if (getParser().parseIdentifier(Name))
3162 return TokError("expected symbol name");
3163 if (parseEOL())
3164 return true;
3165 getTargetStreamer().emitDirectiveVariantCC(
3166 *getContext().getOrCreateSymbol(Name));
3167 return false;
3168}
3169
3170void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
3171 MCInst CInst;
3172 bool Res = RISCVRVC::compress(CInst, Inst, getSTI());
3173 if (Res)
3174 ++RISCVNumInstrsCompressed;
3175 S.emitInstruction((Res ? CInst : Inst), getSTI());
3176}
3177
3178void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
3179 MCStreamer &Out) {
3181 RISCVMatInt::generateMCInstSeq(Value, getSTI(), DestReg, Seq);
3182
3183 for (MCInst &Inst : Seq) {
3184 emitToStreamer(Out, Inst);
3185 }
3186}
3187
3188void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
3189 const MCExpr *Symbol,
3191 unsigned SecondOpcode, SMLoc IDLoc,
3192 MCStreamer &Out) {
3193 // A pair of instructions for PC-relative addressing; expands to
3194 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
3195 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
3196 MCContext &Ctx = getContext();
3197
3198 MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
3199 Out.emitLabel(TmpLabel);
3200
3201 const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
3202 emitToStreamer(
3203 Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
3204
3205 const MCExpr *RefToLinkTmpLabel =
3208
3209 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3210 .addOperand(DestReg)
3211 .addOperand(TmpReg)
3212 .addExpr(RefToLinkTmpLabel));
3213}
3214
3215void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
3216 MCStreamer &Out) {
3217 // The load local address pseudo-instruction "lla" is used in PC-relative
3218 // addressing of local symbols:
3219 // lla rdest, symbol
3220 // expands to
3221 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
3222 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3223 MCOperand DestReg = Inst.getOperand(0);
3224 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3225 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
3226 RISCV::ADDI, IDLoc, Out);
3227}
3228
3229void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,
3230 MCStreamer &Out) {
3231 // The load global address pseudo-instruction "lga" is used in GOT-indirect
3232 // addressing of global symbols:
3233 // lga rdest, symbol
3234 // expands to
3235 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
3236 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3237 MCOperand DestReg = Inst.getOperand(0);
3238 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3239 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3240 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_GOT_HI,
3241 SecondOpcode, IDLoc, Out);
3242}
3243
3244void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
3245 MCStreamer &Out) {
3246 // The load address pseudo-instruction "la" is used in PC-relative and
3247 // GOT-indirect addressing of global symbols:
3248 // la rdest, symbol
3249 // is an alias for either (for non-PIC)
3250 // lla rdest, symbol
3251 // or (for PIC)
3252 // lga rdest, symbol
3253 if (ParserOptions.IsPicEnabled)
3254 emitLoadGlobalAddress(Inst, IDLoc, Out);
3255 else
3256 emitLoadLocalAddress(Inst, IDLoc, Out);
3257}
3258
3259void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
3260 MCStreamer &Out) {
3261 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
3262 // initial-exec TLS model addressing of global symbols:
3263 // la.tls.ie rdest, symbol
3264 // expands to
3265 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
3266 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3267 MCOperand DestReg = Inst.getOperand(0);
3268 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3269 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3270 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI,
3271 SecondOpcode, IDLoc, Out);
3272}
3273
3274void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
3275 MCStreamer &Out) {
3276 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
3277 // global-dynamic TLS model addressing of global symbols:
3278 // la.tls.gd rdest, symbol
3279 // expands to
3280 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
3281 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3282 MCOperand DestReg = Inst.getOperand(0);
3283 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3284 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI,
3285 RISCV::ADDI, IDLoc, Out);
3286}
3287
3288void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
3289 SMLoc IDLoc, MCStreamer &Out,
3290 bool HasTmpReg) {
3291 // The load/store pseudo-instruction does a pc-relative load with
3292 // a symbol.
3293 //
3294 // The expansion looks like this
3295 //
3296 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
3297 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
3298 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
3299 MCOperand DestReg = Inst.getOperand(DestRegOpIdx);
3300 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
3301 MCOperand TmpReg = Inst.getOperand(0);
3302 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
3303 emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
3304 Opcode, IDLoc, Out);
3305}
3306
3307void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
3308 int64_t Width, SMLoc IDLoc,
3309 MCStreamer &Out) {
3310 // The sign/zero extend pseudo-instruction does two shifts, with the shift
3311 // amounts dependent on the XLEN.
3312 //
3313 // The expansion looks like this
3314 //
3315 // SLLI rd, rs, XLEN - Width
3316 // SR[A|R]I rd, rd, XLEN - Width
3317 MCOperand DestReg = Inst.getOperand(0);
3318 MCOperand SourceReg = Inst.getOperand(1);
3319
3320 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
3321 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
3322
3323 assert(ShAmt > 0 && "Shift amount must be non-zero.");
3324
3325 emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)
3326 .addOperand(DestReg)
3327 .addOperand(SourceReg)
3328 .addImm(ShAmt));
3329
3330 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3331 .addOperand(DestReg)
3332 .addOperand(DestReg)
3333 .addImm(ShAmt));
3334}
3335
3336void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
3337 MCStreamer &Out) {
3338 if (Inst.getNumOperands() == 3) {
3339 // unmasked va >= x
3340 //
3341 // pseudoinstruction: vmsge{u}.vx vd, va, x
3342 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
3343 emitToStreamer(Out, MCInstBuilder(Opcode)
3344 .addOperand(Inst.getOperand(0))
3345 .addOperand(Inst.getOperand(1))
3346 .addOperand(Inst.getOperand(2))
3347 .addReg(RISCV::NoRegister)
3348 .setLoc(IDLoc));
3349 emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)
3350 .addOperand(Inst.getOperand(0))
3351 .addOperand(Inst.getOperand(0))
3352 .addOperand(Inst.getOperand(0))
3353 .setLoc(IDLoc));
3354 } else if (Inst.getNumOperands() == 4) {
3355 // masked va >= x, vd != v0
3356 //
3357 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
3358 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
3359 assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
3360 "The destination register should not be V0.");
3361 emitToStreamer(Out, MCInstBuilder(Opcode)
3362 .addOperand(Inst.getOperand(0))
3363 .addOperand(Inst.getOperand(1))
3364 .addOperand(Inst.getOperand(2))
3365 .addOperand(Inst.getOperand(3))
3366 .setLoc(IDLoc));
3367 emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)
3368 .addOperand(Inst.getOperand(0))
3369 .addOperand(Inst.getOperand(0))
3370 .addReg(RISCV::V0)
3371 .setLoc(IDLoc));
3372 } else if (Inst.getNumOperands() == 5 &&
3373 Inst.getOperand(0).getReg() == RISCV::V0) {
3374 // masked va >= x, vd == v0
3375 //
3376 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3377 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
3378 assert(Inst.getOperand(0).getReg() == RISCV::V0 &&
3379 "The destination register should be V0.");
3380 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3381 "The temporary vector register should not be V0.");
3382 emitToStreamer(Out, MCInstBuilder(Opcode)
3383 .addOperand(Inst.getOperand(1))
3384 .addOperand(Inst.getOperand(2))
3385 .addOperand(Inst.getOperand(3))
3386 .addReg(RISCV::NoRegister)
3387 .setLoc(IDLoc));
3388 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3389 .addOperand(Inst.getOperand(0))
3390 .addOperand(Inst.getOperand(0))
3391 .addOperand(Inst.getOperand(1))
3392 .setLoc(IDLoc));
3393 } else if (Inst.getNumOperands() == 5) {
3394 // masked va >= x, any vd
3395 //
3396 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3397 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;
3398 // vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd
3399 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
3400 "The temporary vector register should not be V0.");
3401 emitToStreamer(Out, MCInstBuilder(Opcode)
3402 .addOperand(Inst.getOperand(1))
3403 .addOperand(Inst.getOperand(2))
3404 .addOperand(Inst.getOperand(3))
3405 .addReg(RISCV::NoRegister)
3406 .setLoc(IDLoc));
3407 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3408 .addOperand(Inst.getOperand(1))
3409 .addReg(RISCV::V0)
3410 .addOperand(Inst.getOperand(1))
3411 .setLoc(IDLoc));
3412 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3413 .addOperand(Inst.getOperand(0))
3414 .addOperand(Inst.getOperand(0))
3415 .addReg(RISCV::V0)
3416 .setLoc(IDLoc));
3417 emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)
3418 .addOperand(Inst.getOperand(0))
3419 .addOperand(Inst.getOperand(1))
3420 .addOperand(Inst.getOperand(0))
3421 .setLoc(IDLoc));
3422 }
3423}
3424
3425bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
3427 assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
3428 assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
3429 if (Inst.getOperand(2).getReg() != RISCV::X4) {
3430 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
3431 return Error(ErrorLoc, "the second input operand must be tp/x4 when using "
3432 "%tprel_add modifier");
3433 }
3434
3435 return false;
3436}
3437
3438bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst &Inst,
3440 assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction");
3441 assert(Inst.getOperand(0).isReg() && "Unexpected operand kind");
3442 if (Inst.getOperand(0).getReg() != RISCV::X5) {
3443 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
3444 return Error(ErrorLoc, "the output operand must be t0/x5 when using "
3445 "%tlsdesc_call modifier");
3446 }
3447
3448 return false;
3449}
3450
3451std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
3452 return RISCVOperand::createReg(RISCV::NoRegister, llvm::SMLoc(),
3453 llvm::SMLoc());
3454}
3455
3456std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
3457 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
3458 llvm::SMLoc());
3459}
3460
3461std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgLegacyOp() const {
3462 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE,
3463 llvm::SMLoc());
3464}
3465
3466bool RISCVAsmParser::validateInstruction(MCInst &Inst,
3468 unsigned Opcode = Inst.getOpcode();
3469
3470 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3471 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3472 unsigned DestReg = Inst.getOperand(0).getReg();
3473 unsigned TempReg = Inst.getOperand(1).getReg();
3474 if (DestReg == TempReg) {
3475 SMLoc Loc = Operands.back()->getStartLoc();
3476 return Error(Loc, "the temporary vector register cannot be the same as "
3477 "the destination register");
3478 }
3479 }
3480
3481 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
3482 Opcode == RISCV::TH_LWD) {
3483 unsigned Rd1 = Inst.getOperand(0).getReg();
3484 unsigned Rd2 = Inst.getOperand(1).getReg();
3485 unsigned Rs1 = Inst.getOperand(2).getReg();
3486 // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.
3487 if (Rs1 == Rd1 && Rs1 == Rd2) {
3488 SMLoc Loc = Operands[1]->getStartLoc();
3489 return Error(Loc, "rs1, rd1, and rd2 cannot all be the same");
3490 }
3491 }
3492
3493 if (Opcode == RISCV::CM_MVSA01) {
3494 unsigned Rd1 = Inst.getOperand(0).getReg();
3495 unsigned Rd2 = Inst.getOperand(1).getReg();
3496 if (Rd1 == Rd2) {
3497 SMLoc Loc = Operands[1]->getStartLoc();
3498 return Error(Loc, "rs1 and rs2 must be different");
3499 }
3500 }
3501
3502 bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
3503 Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
3504 bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
3505 // The last operand of XTHeadMemPair instructions must be constant 3 or 4
3506 // depending on the data width.
3507 if (IsTHeadMemPair32 && Inst.getOperand(4).getImm() != 3) {
3508 SMLoc Loc = Operands.back()->getStartLoc();
3509 return Error(Loc, "operand must be constant 3");
3510 } else if (IsTHeadMemPair64 && Inst.getOperand(4).getImm() != 4) {
3511 SMLoc Loc = Operands.back()->getStartLoc();
3512 return Error(Loc, "operand must be constant 4");
3513 }
3514
3515 const MCInstrDesc &MCID = MII.get(Opcode);
3516 if (!(MCID.TSFlags & RISCVII::ConstraintMask))
3517 return false;
3518
3519 if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW ||
3520 Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) {
3521 // Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for VC_V_XVW.
3522 unsigned VCIXDst = Inst.getOperand(0).getReg();
3523 SMLoc VCIXDstLoc = Operands[2]->getStartLoc();
3524 if (MCID.TSFlags & RISCVII::VS1Constraint) {
3525 unsigned VCIXRs1 = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
3526 if (VCIXDst == VCIXRs1)
3527 return Error(VCIXDstLoc, "the destination vector register group cannot"
3528 " overlap the source vector register group");
3529 }
3530 if (MCID.TSFlags & RISCVII::VS2Constraint) {
3531 unsigned VCIXRs2 = Inst.getOperand(Inst.getNumOperands() - 2).getReg();
3532 if (VCIXDst == VCIXRs2)
3533 return Error(VCIXDstLoc, "the destination vector register group cannot"
3534 " overlap the source vector register group");
3535 }
3536 return false;
3537 }
3538
3539 unsigned DestReg = Inst.getOperand(0).getReg();
3540 unsigned Offset = 0;
3541 int TiedOp = MCID.getOperandConstraint(1, MCOI::TIED_TO);
3542 if (TiedOp == 0)
3543 Offset = 1;
3544
3545 // Operands[1] will be the first operand, DestReg.
3546 SMLoc Loc = Operands[1]->getStartLoc();
3547 if (MCID.TSFlags & RISCVII::VS2Constraint) {
3548 unsigned CheckReg = Inst.getOperand(Offset + 1).getReg();
3549 if (DestReg == CheckReg)
3550 return Error(Loc, "the destination vector register group cannot overlap"
3551 " the source vector register group");
3552 }
3553 if ((MCID.TSFlags & RISCVII::VS1Constraint) && Inst.getOperand(Offset + 2).isReg()) {
3554 unsigned CheckReg = Inst.getOperand(Offset + 2).getReg();
3555 if (DestReg == CheckReg)
3556 return Error(Loc, "the destination vector register group cannot overlap"
3557 " the source vector register group");
3558 }
3559 if ((MCID.TSFlags & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) {
3560 // vadc, vsbc are special cases. These instructions have no mask register.
3561 // The destination register could not be V0.
3562 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
3563 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
3564 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
3565 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
3566 Opcode == RISCV::VMERGE_VXM)
3567 return Error(Loc, "the destination vector register group cannot be V0");
3568
3569 // Regardless masked or unmasked version, the number of operands is the
3570 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
3571 // actually. We need to check the last operand to ensure whether it is
3572 // masked or not.
3573 unsigned CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
3574 assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) &&
3575 "Unexpected register for mask operand");
3576
3577 if (DestReg == CheckReg)
3578 return Error(Loc, "the destination vector register group cannot overlap"
3579 " the mask register");
3580 }
3581 return false;
3582}
3583
3584bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
3586 MCStreamer &Out) {
3587 Inst.setLoc(IDLoc);
3588
3589 switch (Inst.getOpcode()) {
3590 default:
3591 break;
3592 case RISCV::PseudoLLAImm:
3593 case RISCV::PseudoLAImm:
3594 case RISCV::PseudoLI: {
3595 MCRegister Reg = Inst.getOperand(0).getReg();
3596 const MCOperand &Op1 = Inst.getOperand(1);
3597 if (Op1.isExpr()) {
3598 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
3599 // Just convert to an addi. This allows compatibility with gas.
3600 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
3601 .addReg(Reg)
3602 .addReg(RISCV::X0)
3603 .addExpr(Op1.getExpr()));
3604 return false;
3605 }
3606 int64_t Imm = Inst.getOperand(1).getImm();
3607 // On RV32 the immediate here can either be a signed or an unsigned
3608 // 32-bit number. Sign extension has to be performed to ensure that Imm
3609 // represents the expected signed 64-bit number.
3610 if (!isRV64())
3611 Imm = SignExtend64<32>(Imm);
3612 emitLoadImm(Reg, Imm, Out);
3613 return false;
3614 }
3615 case RISCV::PseudoLLA:
3616 emitLoadLocalAddress(Inst, IDLoc, Out);
3617 return false;
3618 case RISCV::PseudoLGA:
3619 emitLoadGlobalAddress(Inst, IDLoc, Out);
3620 return false;
3621 case RISCV::PseudoLA:
3622 emitLoadAddress(Inst, IDLoc, Out);
3623 return false;
3624 case RISCV::PseudoLA_TLS_IE:
3625 emitLoadTLSIEAddress(Inst, IDLoc, Out);
3626 return false;
3627 case RISCV::PseudoLA_TLS_GD:
3628 emitLoadTLSGDAddress(Inst, IDLoc, Out);
3629 return false;
3630 case RISCV::PseudoLB:
3631 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
3632 return false;
3633 case RISCV::PseudoLBU:
3634 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
3635 return false;
3636 case RISCV::PseudoLH:
3637 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
3638 return false;
3639 case RISCV::PseudoLHU:
3640 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
3641 return false;
3642 case RISCV::PseudoLW:
3643 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
3644 return false;
3645 case RISCV::PseudoLWU:
3646 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
3647 return false;
3648 case RISCV::PseudoLD:
3649 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
3650 return false;
3651 case RISCV::PseudoFLH:
3652 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
3653 return false;
3654 case RISCV::PseudoFLW:
3655 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
3656 return false;
3657 case RISCV::PseudoFLD:
3658 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
3659 return false;
3660 case RISCV::PseudoSB:
3661 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
3662 return false;
3663 case RISCV::PseudoSH:
3664 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
3665 return false;
3666 case RISCV::PseudoSW:
3667 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
3668 return false;
3669 case RISCV::PseudoSD:
3670 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
3671 return false;
3672 case RISCV::PseudoFSH:
3673 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
3674 return false;
3675 case RISCV::PseudoFSW:
3676 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
3677 return false;
3678 case RISCV::PseudoFSD:
3679 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
3680 return false;
3681 case RISCV::PseudoAddTPRel:
3682 if (checkPseudoAddTPRel(Inst, Operands))
3683 return true;
3684 break;
3685 case RISCV::PseudoTLSDESCCall:
3686 if (checkPseudoTLSDESCCall(Inst, Operands))
3687 return true;
3688 break;
3689 case RISCV::PseudoSEXT_B:
3690 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
3691 return false;
3692 case RISCV::PseudoSEXT_H:
3693 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
3694 return false;
3695 case RISCV::PseudoZEXT_H:
3696 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
3697 return false;
3698 case RISCV::PseudoZEXT_W:
3699 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
3700 return false;
3701 case RISCV::PseudoVMSGEU_VX:
3702 case RISCV::PseudoVMSGEU_VX_M:
3703 case RISCV::PseudoVMSGEU_VX_M_T:
3704 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
3705 return false;
3706 case RISCV::PseudoVMSGE_VX:
3707 case RISCV::PseudoVMSGE_VX_M:
3708 case RISCV::PseudoVMSGE_VX_M_T:
3709 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
3710 return false;
3711 case RISCV::PseudoVMSGE_VI:
3712 case RISCV::PseudoVMSLT_VI: {
3713 // These instructions are signed and so is immediate so we can subtract one
3714 // and change the opcode.
3715 int64_t Imm = Inst.getOperand(2).getImm();
3716 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
3717 : RISCV::VMSLE_VI;
3718 emitToStreamer(Out, MCInstBuilder(Opc)
3719 .addOperand(Inst.getOperand(0))
3720 .addOperand(Inst.getOperand(1))
3721 .addImm(Imm - 1)
3722 .addOperand(Inst.getOperand(3))
3723 .setLoc(IDLoc));
3724 return false;
3725 }
3726 case RISCV::PseudoVMSGEU_VI:
3727 case RISCV::PseudoVMSLTU_VI: {
3728 int64_t Imm = Inst.getOperand(2).getImm();
3729 // Unsigned comparisons are tricky because the immediate is signed. If the
3730 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
3731 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
3732 // vmsne v0, v1, v1 which is always false.
3733 if (Imm == 0) {
3734 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3735 ? RISCV::VMSEQ_VV
3736 : RISCV::VMSNE_VV;
3737 emitToStreamer(Out, MCInstBuilder(Opc)
3738 .addOperand(Inst.getOperand(0))
3739 .addOperand(Inst.getOperand(1))
3740 .addOperand(Inst.getOperand(1))
3741 .addOperand(Inst.getOperand(3))
3742 .setLoc(IDLoc));
3743 } else {
3744 // Other immediate values can subtract one like signed.
3745 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3746 ? RISCV::VMSGTU_VI
3747 : RISCV::VMSLEU_VI;
3748 emitToStreamer(Out, MCInstBuilder(Opc)
3749 .addOperand(Inst.getOperand(0))
3750 .addOperand(Inst.getOperand(1))
3751 .addImm(Imm - 1)
3752 .addOperand(Inst.getOperand(3))
3753 .setLoc(IDLoc));
3754 }
3755
3756 return false;
3757 }
3758 }
3759
3760 emitToStreamer(Out, Inst);
3761 return false;
3762}
3763
3767}
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:135
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 check(cond)
#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:167
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:95
size_t size() const
Definition: SmallVector.h:92
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:587
void push_back(const T &Elt)
Definition: SmallVector.h:427
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1210
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:1954
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
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.