LLVM 17.0.0git
RISCVAsmParser.cpp
Go to the documentation of this file.
1//===-- RISCVAsmParser.cpp - Parse RISCV assembly to MCInst instructions --===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
17#include "llvm/ADT/STLExtras.h"
21#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"
41
42#include <limits>
43
44using namespace llvm;
45
46#define DEBUG_TYPE "riscv-asm-parser"
47
48STATISTIC(RISCVNumInstrsCompressed,
49 "Number of RISC-V Compressed instructions emitted");
50
51namespace llvm {
52extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures];
53} // namespace llvm
54
55namespace {
56struct RISCVOperand;
57
58struct ParserOptionsSet {
59 bool IsPicEnabled;
60};
61
62class RISCVAsmParser : public MCTargetAsmParser {
63 SmallVector<FeatureBitset, 4> FeatureBitStack;
64
65 SmallVector<ParserOptionsSet, 4> ParserOptionsStack;
66 ParserOptionsSet ParserOptions;
67
68 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
69 bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
70 bool isRV32E() const { return getSTI().hasFeature(RISCV::FeatureRV32E); }
71
72 RISCVTargetStreamer &getTargetStreamer() {
73 assert(getParser().getStreamer().getTargetStreamer() &&
74 "do not have a target streamer");
76 return static_cast<RISCVTargetStreamer &>(TS);
77 }
78
80 unsigned Kind) override;
81 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
82
83 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
84 int64_t Lower, int64_t Upper, Twine Msg);
85
86 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
89 bool MatchingInlineAsm) override;
90
91 bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
92 SMLoc &EndLoc) override;
94 SMLoc &EndLoc) override;
95
97 SMLoc NameLoc, OperandVector &Operands) override;
98
99 bool ParseDirective(AsmToken DirectiveID) override;
100
101 // Helper to actually emit an instruction to the MCStreamer. Also, when
102 // possible, compression of the instruction is performed.
103 void emitToStreamer(MCStreamer &S, const MCInst &Inst);
104
105 // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
106 // synthesize the desired immedate value into the destination register.
107 void emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out);
108
109 // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
110 // helpers such as emitLoadLocalAddress and emitLoadAddress.
111 void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
112 const MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi,
113 unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
114
115 // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
116 void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
117
118 // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
119 void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
120
121 // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
122 // addressing.
123 void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
124
125 // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
126 // addressing.
127 void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
128
129 // Helper to emit pseudo load/store instruction with a symbol.
130 void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
131 MCStreamer &Out, bool HasTmpReg);
132
133 // Helper to emit pseudo sign/zero extend instruction.
134 void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width,
135 SMLoc IDLoc, MCStreamer &Out);
136
137 // Helper to emit pseudo vmsge{u}.vx instruction.
138 void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);
139
140 // Checks that a PseudoAddTPRel is using x4/tp in its second input operand.
141 // Enforcing this using a restricted register class for the second input
142 // operand of PseudoAddTPRel results in a poor diagnostic due to the fact
143 // 'add' is an overloaded mnemonic.
144 bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands);
145
146 // Check instruction constraints.
147 bool validateInstruction(MCInst &Inst, OperandVector &Operands);
148
149 /// Helper for processing MC instructions that have been successfully matched
150 /// by MatchAndEmitInstruction. Modifications to the emitted instructions,
151 /// like the expansion of pseudo instructions (e.g., "li"), can be performed
152 /// in this method.
153 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
154 MCStreamer &Out);
155
156// Auto-generated instruction matching functions
157#define GET_ASSEMBLER_HEADER
158#include "RISCVGenAsmMatcher.inc"
159
160 OperandMatchResultTy parseCSRSystemRegister(OperandVector &Operands);
163 bool AllowParens = false);
164 OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
165 OperandMatchResultTy parseZeroOffsetMemOp(OperandVector &Operands);
166 OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
169 OperandMatchResultTy parsePseudoJumpSymbol(OperandVector &Operands);
173 OperandMatchResultTy parseInsnDirectiveOpcode(OperandVector &Operands);
177
178 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
179
180 bool parseDirectiveOption();
181 bool parseDirectiveAttribute();
182 bool parseDirectiveInsn(SMLoc L);
183 bool parseDirectiveVariantCC();
184
185 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
186 if (!(getSTI().getFeatureBits()[Feature])) {
187 MCSubtargetInfo &STI = copySTI();
189 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
190 }
191 }
192
193 bool getFeatureBits(uint64_t Feature) {
194 return getSTI().getFeatureBits()[Feature];
195 }
196
197 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
198 if (getSTI().getFeatureBits()[Feature]) {
199 MCSubtargetInfo &STI = copySTI();
201 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
202 }
203 }
204
205 void pushFeatureBits() {
206 assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
207 "These two stacks must be kept synchronized");
208 FeatureBitStack.push_back(getSTI().getFeatureBits());
209 ParserOptionsStack.push_back(ParserOptions);
210 }
211
212 bool popFeatureBits() {
213 assert(FeatureBitStack.size() == ParserOptionsStack.size() &&
214 "These two stacks must be kept synchronized");
215 if (FeatureBitStack.empty())
216 return true;
217
218 FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
219 copySTI().setFeatureBits(FeatureBits);
220 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
221
222 ParserOptions = ParserOptionsStack.pop_back_val();
223
224 return false;
225 }
226
227 std::unique_ptr<RISCVOperand> defaultMaskRegOp() const;
228 std::unique_ptr<RISCVOperand> defaultFRMArgOp() const;
229
230public:
231 enum RISCVMatchResultTy {
232 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
233 Match_RequiresEvenGPRs,
234#define GET_OPERAND_DIAGNOSTIC_TYPES
235#include "RISCVGenAsmMatcher.inc"
236#undef GET_OPERAND_DIAGNOSTIC_TYPES
237 };
238
239 static bool classifySymbolRef(const MCExpr *Expr,
241
242 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
243 const MCInstrInfo &MII, const MCTargetOptions &Options)
244 : MCTargetAsmParser(Options, STI, MII) {
245 Parser.addAliasForDirective(".half", ".2byte");
246 Parser.addAliasForDirective(".hword", ".2byte");
247 Parser.addAliasForDirective(".word", ".4byte");
248 Parser.addAliasForDirective(".dword", ".8byte");
249 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
250
251 auto ABIName = StringRef(Options.ABIName);
252 if (ABIName.endswith("f") &&
253 !getSTI().getFeatureBits()[RISCV::FeatureStdExtF]) {
254 errs() << "Hard-float 'f' ABI can't be used for a target that "
255 "doesn't support the F instruction set extension (ignoring "
256 "target-abi)\n";
257 } else if (ABIName.endswith("d") &&
258 !getSTI().getFeatureBits()[RISCV::FeatureStdExtD]) {
259 errs() << "Hard-float 'd' ABI can't be used for a target that "
260 "doesn't support the D instruction set extension (ignoring "
261 "target-abi)\n";
262 }
263
264 // Use computeTargetABI to check if ABIName is valid. If invalid, output
265 // error message.
267 ABIName);
268
269 const MCObjectFileInfo *MOFI = Parser.getContext().getObjectFileInfo();
270 ParserOptions.IsPicEnabled = MOFI->isPositionIndependent();
271 }
272};
273
274/// RISCVOperand - Instances of this class represent a parsed machine
275/// instruction
276struct RISCVOperand final : public MCParsedAsmOperand {
277
278 enum class KindTy {
279 Token,
280 Register,
281 Immediate,
282 SystemRegister,
283 VType,
284 FRM,
285 Fence,
286 } Kind;
287
288 struct RegOp {
289 MCRegister RegNum;
290 bool IsGPRAsFPR;
291 };
292
293 struct ImmOp {
294 const MCExpr *Val;
295 bool IsRV64;
296 };
297
298 struct SysRegOp {
299 const char *Data;
300 unsigned Length;
301 unsigned Encoding;
302 // FIXME: Add the Encoding parsed fields as needed for checks,
303 // e.g.: read/write or user/supervisor/machine privileges.
304 };
305
306 struct VTypeOp {
307 unsigned Val;
308 };
309
310 struct FRMOp {
312 };
313
314 struct FenceOp {
315 unsigned Val;
316 };
317
318 SMLoc StartLoc, EndLoc;
319 union {
320 StringRef Tok;
321 RegOp Reg;
322 ImmOp Imm;
323 struct SysRegOp SysReg;
324 struct VTypeOp VType;
325 struct FRMOp FRM;
326 struct FenceOp Fence;
327 };
328
329 RISCVOperand(KindTy K) : Kind(K) {}
330
331public:
332 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
333 Kind = o.Kind;
334 StartLoc = o.StartLoc;
335 EndLoc = o.EndLoc;
336 switch (Kind) {
337 case KindTy::Register:
338 Reg = o.Reg;
339 break;
340 case KindTy::Immediate:
341 Imm = o.Imm;
342 break;
343 case KindTy::Token:
344 Tok = o.Tok;
345 break;
346 case KindTy::SystemRegister:
347 SysReg = o.SysReg;
348 break;
349 case KindTy::VType:
350 VType = o.VType;
351 break;
352 case KindTy::FRM:
353 FRM = o.FRM;
354 break;
355 case KindTy::Fence:
356 Fence = o.Fence;
357 break;
358 }
359 }
360
361 bool isToken() const override { return Kind == KindTy::Token; }
362 bool isReg() const override { return Kind == KindTy::Register; }
363 bool isV0Reg() const {
364 return Kind == KindTy::Register && Reg.RegNum == RISCV::V0;
365 }
366 bool isImm() const override { return Kind == KindTy::Immediate; }
367 bool isMem() const override { return false; }
368 bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
369
370 bool isGPR() const {
371 return Kind == KindTy::Register &&
372 RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum);
373 }
374
375 bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
376
377 bool isGPRF64AsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
378
379 bool isGPRPF64AsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
380
381 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
383 if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
384 VK = RE->getKind();
385 return RE->evaluateAsConstant(Imm);
386 }
387
388 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
390 Imm = CE->getValue();
391 return true;
392 }
393
394 return false;
395 }
396
397 // True if operand is a symbol with no modifiers, or a constant with no
398 // modifiers and isShiftedInt<N-1, 1>(Op).
399 template <int N> bool isBareSimmNLsb0() const {
400 int64_t Imm;
402 if (!isImm())
403 return false;
404 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
405 bool IsValid;
406 if (!IsConstantImm)
407 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
408 else
409 IsValid = isShiftedInt<N - 1, 1>(Imm);
410 return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
411 }
412
413 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
414
415 bool isBareSymbol() const {
416 int64_t Imm;
418 // Must be of 'immediate' type but not a constant.
419 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
420 return false;
421 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
423 }
424
425 bool isCallSymbol() const {
426 int64_t Imm;
428 // Must be of 'immediate' type but not a constant.
429 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
430 return false;
431 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
434 }
435
436 bool isPseudoJumpSymbol() const {
437 int64_t Imm;
439 // Must be of 'immediate' type but not a constant.
440 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
441 return false;
442 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
444 }
445
446 bool isTPRelAddSymbol() const {
447 int64_t Imm;
449 // Must be of 'immediate' type but not a constant.
450 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
451 return false;
452 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
454 }
455
456 bool isCSRSystemRegister() const { return isSystemRegister(); }
457
458 bool isVTypeImm(unsigned N) const {
459 int64_t Imm;
461 if (!isImm())
462 return false;
463 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
464 return IsConstantImm && isUIntN(N, Imm) && VK == RISCVMCExpr::VK_RISCV_None;
465 }
466
467 // If the last operand of the vsetvli/vsetvli instruction is a constant
468 // expression, KindTy is Immediate.
469 bool isVTypeI10() const {
470 if (Kind == KindTy::Immediate)
471 return isVTypeImm(10);
472 return Kind == KindTy::VType;
473 }
474 bool isVTypeI11() const {
475 if (Kind == KindTy::Immediate)
476 return isVTypeImm(11);
477 return Kind == KindTy::VType;
478 }
479
480 /// Return true if the operand is a valid for the fence instruction e.g.
481 /// ('iorw').
482 bool isFenceArg() const { return Kind == KindTy::Fence; }
483
484 /// Return true if the operand is a valid floating point rounding mode.
485 bool isFRMArg() const { return Kind == KindTy::FRM; }
486
487 bool isImmXLenLI() const {
488 int64_t Imm;
490 if (!isImm())
491 return false;
492 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
494 return true;
495 // Given only Imm, ensuring that the actually specified constant is either
496 // a signed or unsigned 64-bit number is unfortunately impossible.
497 return IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None &&
498 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
499 }
500
501 bool isUImmLog2XLen() const {
502 int64_t Imm;
504 if (!isImm())
505 return false;
506 if (!evaluateConstantImm(getImm(), Imm, VK) ||
508 return false;
509 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
510 }
511
512 bool isUImmLog2XLenNonZero() const {
513 int64_t Imm;
515 if (!isImm())
516 return false;
517 if (!evaluateConstantImm(getImm(), Imm, VK) ||
519 return false;
520 if (Imm == 0)
521 return false;
522 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
523 }
524
525 bool isUImmLog2XLenHalf() const {
526 int64_t Imm;
528 if (!isImm())
529 return false;
530 if (!evaluateConstantImm(getImm(), Imm, VK) ||
532 return false;
533 return (isRV64Imm() && isUInt<5>(Imm)) || isUInt<4>(Imm);
534 }
535
536 template <unsigned N> bool IsUImm() const {
537 int64_t Imm;
539 if (!isImm())
540 return false;
541 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
542 return IsConstantImm && isUInt<N>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
543 }
544
545 bool isUImm2() { return IsUImm<2>(); }
546 bool isUImm3() { return IsUImm<3>(); }
547 bool isUImm5() { return IsUImm<5>(); }
548 bool isUImm7() { return IsUImm<7>(); }
549
550 bool isRnumArg() const {
551 int64_t Imm;
553 if (!isImm())
554 return false;
555 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
556 return IsConstantImm && Imm >= INT64_C(0) && Imm <= INT64_C(10) &&
558 }
559
560 bool isSImm5() const {
561 if (!isImm())
562 return false;
564 int64_t Imm;
565 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
566 return IsConstantImm && isInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
567 }
568
569 bool isSImm6() const {
570 if (!isImm())
571 return false;
573 int64_t Imm;
574 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
575 return IsConstantImm && isInt<6>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
576 }
577
578 bool isSImm6NonZero() const {
579 if (!isImm())
580 return false;
582 int64_t Imm;
583 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
584 return IsConstantImm && isInt<6>(Imm) && (Imm != 0) &&
586 }
587
588 bool isCLUIImm() const {
589 if (!isImm())
590 return false;
591 int64_t Imm;
593 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
594 return IsConstantImm && (Imm != 0) &&
595 (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
597 }
598
599 bool isUImm2Lsb0() const {
600 if (!isImm())
601 return false;
602 int64_t Imm;
604 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
605 return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
607 }
608
609 bool isUImm7Lsb00() const {
610 if (!isImm())
611 return false;
612 int64_t Imm;
614 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
615 return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
617 }
618
619 bool isUImm8Lsb00() const {
620 if (!isImm())
621 return false;
622 int64_t Imm;
624 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
625 return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
627 }
628
629 bool isUImm8Lsb000() const {
630 if (!isImm())
631 return false;
632 int64_t Imm;
634 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
635 return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
637 }
638
639 bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
640
641 bool isUImm9Lsb000() const {
642 if (!isImm())
643 return false;
644 int64_t Imm;
646 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
647 return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
649 }
650
651 bool isUImm10Lsb00NonZero() const {
652 if (!isImm())
653 return false;
654 int64_t Imm;
656 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
657 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
659 }
660
661 bool isSImm12() const {
663 int64_t Imm;
664 bool IsValid;
665 if (!isImm())
666 return false;
667 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
668 if (!IsConstantImm)
669 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
670 else
671 IsValid = isInt<12>(Imm);
672 return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
676 }
677
678 bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
679
680 bool isSImm12Lsb00000() const {
681 if (!isImm())
682 return false;
684 int64_t Imm;
685 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
686 return IsConstantImm && isShiftedInt<7, 5>(Imm) &&
688 }
689
690 bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
691
692 bool isSImm10Lsb0000NonZero() const {
693 if (!isImm())
694 return false;
695 int64_t Imm;
697 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
698 return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) &&
700 }
701
702 bool isUImm20LUI() const {
704 int64_t Imm;
705 bool IsValid;
706 if (!isImm())
707 return false;
708 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
709 if (!IsConstantImm) {
710 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
711 return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI ||
713 } else {
714 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
717 }
718 }
719
720 bool isUImm20AUIPC() const {
722 int64_t Imm;
723 bool IsValid;
724 if (!isImm())
725 return false;
726 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
727 if (!IsConstantImm) {
728 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
729 return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
733 } else {
734 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
739 }
740 }
741
742 bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
743
744 bool isImmZero() const {
745 if (!isImm())
746 return false;
747 int64_t Imm;
749 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
750 return IsConstantImm && (Imm == 0) && VK == RISCVMCExpr::VK_RISCV_None;
751 }
752
753 bool isSImm5Plus1() const {
754 if (!isImm())
755 return false;
757 int64_t Imm;
758 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
759 return IsConstantImm && isInt<5>(Imm - 1) &&
761 }
762
763 /// getStartLoc - Gets location of the first token of this operand
764 SMLoc getStartLoc() const override { return StartLoc; }
765 /// getEndLoc - Gets location of the last token of this operand
766 SMLoc getEndLoc() const override { return EndLoc; }
767 /// True if this operand is for an RV64 instruction
768 bool isRV64Imm() const {
769 assert(Kind == KindTy::Immediate && "Invalid type access!");
770 return Imm.IsRV64;
771 }
772
773 unsigned getReg() const override {
774 assert(Kind == KindTy::Register && "Invalid type access!");
775 return Reg.RegNum.id();
776 }
777
778 StringRef getSysReg() const {
779 assert(Kind == KindTy::SystemRegister && "Invalid type access!");
780 return StringRef(SysReg.Data, SysReg.Length);
781 }
782
783 const MCExpr *getImm() const {
784 assert(Kind == KindTy::Immediate && "Invalid type access!");
785 return Imm.Val;
786 }
787
788 StringRef getToken() const {
789 assert(Kind == KindTy::Token && "Invalid type access!");
790 return Tok;
791 }
792
793 unsigned getVType() const {
794 assert(Kind == KindTy::VType && "Invalid type access!");
795 return VType.Val;
796 }
797
798 RISCVFPRndMode::RoundingMode getFRM() const {
799 assert(Kind == KindTy::FRM && "Invalid type access!");
800 return FRM.FRM;
801 }
802
803 unsigned getFence() const {
804 assert(Kind == KindTy::Fence && "Invalid type access!");
805 return Fence.Val;
806 }
807
808 void print(raw_ostream &OS) const override {
809 auto RegName = [](MCRegister Reg) {
810 if (Reg)
812 else
813 return "noreg";
814 };
815
816 switch (Kind) {
817 case KindTy::Immediate:
818 OS << *getImm();
819 break;
820 case KindTy::Register:
821 OS << "<register " << RegName(getReg()) << ">";
822 break;
823 case KindTy::Token:
824 OS << "'" << getToken() << "'";
825 break;
826 case KindTy::SystemRegister:
827 OS << "<sysreg: " << getSysReg() << '>';
828 break;
829 case KindTy::VType:
830 OS << "<vtype: ";
831 RISCVVType::printVType(getVType(), OS);
832 OS << '>';
833 break;
834 case KindTy::FRM:
835 OS << "<frm: ";
836 roundingModeToString(getFRM());
837 OS << '>';
838 break;
839 case KindTy::Fence:
840 OS << "<fence: ";
841 OS << getFence();
842 OS << '>';
843 break;
844 }
845 }
846
847 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {
848 auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
849 Op->Tok = Str;
850 Op->StartLoc = S;
851 Op->EndLoc = S;
852 return Op;
853 }
854
855 static std::unique_ptr<RISCVOperand>
856 createReg(unsigned RegNo, SMLoc S, SMLoc E, bool IsGPRAsFPR = false) {
857 auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
858 Op->Reg.RegNum = RegNo;
859 Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
860 Op->StartLoc = S;
861 Op->EndLoc = E;
862 return Op;
863 }
864
865 static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
866 SMLoc E, bool IsRV64) {
867 auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
868 Op->Imm.Val = Val;
869 Op->Imm.IsRV64 = IsRV64;
870 Op->StartLoc = S;
871 Op->EndLoc = E;
872 return Op;
873 }
874
875 static std::unique_ptr<RISCVOperand> createSysReg(StringRef Str, SMLoc S,
876 unsigned Encoding) {
877 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
878 Op->SysReg.Data = Str.data();
879 Op->SysReg.Length = Str.size();
880 Op->SysReg.Encoding = Encoding;
881 Op->StartLoc = S;
882 Op->EndLoc = S;
883 return Op;
884 }
885
886 static std::unique_ptr<RISCVOperand>
887 createFRMArg(RISCVFPRndMode::RoundingMode FRM, SMLoc S) {
888 auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
889 Op->FRM.FRM = FRM;
890 Op->StartLoc = S;
891 Op->EndLoc = S;
892 return Op;
893 }
894
895 static std::unique_ptr<RISCVOperand> createFenceArg(unsigned Val, SMLoc S) {
896 auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
897 Op->Fence.Val = Val;
898 Op->StartLoc = S;
899 Op->EndLoc = S;
900 return Op;
901 }
902
903 static std::unique_ptr<RISCVOperand> createVType(unsigned VTypeI, SMLoc S) {
904 auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
905 Op->VType.Val = VTypeI;
906 Op->StartLoc = S;
907 Op->EndLoc = S;
908 return Op;
909 }
910
911 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
912 assert(Expr && "Expr shouldn't be null!");
913 int64_t Imm = 0;
915 bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
916
917 if (IsConstant)
919 else
921 }
922
923 // Used by the TableGen Code
924 void addRegOperands(MCInst &Inst, unsigned N) const {
925 assert(N == 1 && "Invalid number of operands!");
927 }
928
929 void addImmOperands(MCInst &Inst, unsigned N) const {
930 assert(N == 1 && "Invalid number of operands!");
931 addExpr(Inst, getImm());
932 }
933
934 void addFenceArgOperands(MCInst &Inst, unsigned N) const {
935 assert(N == 1 && "Invalid number of operands!");
936 Inst.addOperand(MCOperand::createImm(Fence.Val));
937 }
938
939 void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
940 assert(N == 1 && "Invalid number of operands!");
941 Inst.addOperand(MCOperand::createImm(SysReg.Encoding));
942 }
943
944 // Support non-canonical syntax:
945 // "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"
946 // "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"
947 void addVTypeIOperands(MCInst &Inst, unsigned N) const {
948 assert(N == 1 && "Invalid number of operands!");
949 int64_t Imm = 0;
950 if (Kind == KindTy::Immediate) {
952 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
953 (void)IsConstantImm;
954 assert(IsConstantImm && "Invalid VTypeI Operand!");
955 } else {
956 Imm = getVType();
957 }
959 }
960
961 void addFRMArgOperands(MCInst &Inst, unsigned N) const {
962 assert(N == 1 && "Invalid number of operands!");
963 Inst.addOperand(MCOperand::createImm(getFRM()));
964 }
965};
966} // end anonymous namespace.
967
968#define GET_REGISTER_MATCHER
969#define GET_SUBTARGET_FEATURE_NAME
970#define GET_MATCHER_IMPLEMENTATION
971#define GET_MNEMONIC_SPELL_CHECKER
972#include "RISCVGenAsmMatcher.inc"
973
975 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
976 return Reg - RISCV::F0_D + RISCV::F0_H;
977}
978
980 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register");
981 return Reg - RISCV::F0_D + RISCV::F0_F;
982}
983
985 unsigned Kind) {
986 unsigned RegClassID;
987 if (Kind == MCK_VRM2)
988 RegClassID = RISCV::VRM2RegClassID;
989 else if (Kind == MCK_VRM4)
990 RegClassID = RISCV::VRM4RegClassID;
991 else if (Kind == MCK_VRM8)
992 RegClassID = RISCV::VRM8RegClassID;
993 else
994 return 0;
995 return RI.getMatchingSuperReg(Reg, RISCV::sub_vrm1_0,
996 &RISCVMCRegisterClasses[RegClassID]);
997}
998
999unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1000 unsigned Kind) {
1001 RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
1002 if (!Op.isReg())
1003 return Match_InvalidOperand;
1004
1005 MCRegister Reg = Op.getReg();
1006 bool IsRegFPR64 =
1007 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg);
1008 bool IsRegFPR64C =
1009 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);
1010 bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);
1011
1012 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1013 // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
1014 if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1015 (IsRegFPR64C && Kind == MCK_FPR32C)) {
1016 Op.Reg.RegNum = convertFPR64ToFPR32(Reg);
1017 return Match_Success;
1018 }
1019 // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
1020 // register from FPR64 to FPR16 if necessary.
1021 if (IsRegFPR64 && Kind == MCK_FPR16) {
1022 Op.Reg.RegNum = convertFPR64ToFPR16(Reg);
1023 return Match_Success;
1024 }
1025 // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
1026 // the register from VR to VRM2/VRM4/VRM8 if necessary.
1027 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1028 Op.Reg.RegNum = convertVRToVRMx(*getContext().getRegisterInfo(), Reg, Kind);
1029 if (Op.Reg.RegNum == 0)
1030 return Match_InvalidOperand;
1031 return Match_Success;
1032 }
1033 return Match_InvalidOperand;
1034}
1035
1036unsigned RISCVAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1037 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
1038
1039 for (unsigned I = 0; I < MCID.NumOperands; ++I) {
1040 if (MCID.operands()[I].RegClass == RISCV::GPRPF64RegClassID) {
1041 const auto &Op = Inst.getOperand(I);
1042 assert(Op.isReg());
1043
1044 MCRegister Reg = Op.getReg();
1045 if (((Reg.id() - RISCV::X0) & 1) != 0)
1046 return Match_RequiresEvenGPRs;
1047 }
1048 }
1049
1050 return Match_Success;
1051}
1052
1053bool RISCVAsmParser::generateImmOutOfRangeError(
1054 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
1055 Twine Msg = "immediate must be an integer in the range") {
1056 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1057 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1058}
1059
1060bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1062 MCStreamer &Out,
1064 bool MatchingInlineAsm) {
1065 MCInst Inst;
1066 FeatureBitset MissingFeatures;
1067
1068 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1069 MatchingInlineAsm);
1070 switch (Result) {
1071 default:
1072 break;
1073 case Match_Success:
1074 if (validateInstruction(Inst, Operands))
1075 return true;
1076 return processInstruction(Inst, IDLoc, Operands, Out);
1077 case Match_MissingFeature: {
1078 assert(MissingFeatures.any() && "Unknown missing features!");
1079 bool FirstFeature = true;
1080 std::string Msg = "instruction requires the following:";
1081 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1082 if (MissingFeatures[i]) {
1083 Msg += FirstFeature ? " " : ", ";
1085 FirstFeature = false;
1086 }
1087 }
1088 return Error(IDLoc, Msg);
1089 }
1090 case Match_MnemonicFail: {
1091 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1092 std::string Suggestion = RISCVMnemonicSpellCheck(
1093 ((RISCVOperand &)*Operands[0]).getToken(), FBS, 0);
1094 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1095 }
1096 case Match_InvalidOperand: {
1097 SMLoc ErrorLoc = IDLoc;
1098 if (ErrorInfo != ~0ULL) {
1099 if (ErrorInfo >= Operands.size())
1100 return Error(ErrorLoc, "too few operands for instruction");
1101
1102 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1103 if (ErrorLoc == SMLoc())
1104 ErrorLoc = IDLoc;
1105 }
1106 return Error(ErrorLoc, "invalid operand for instruction");
1107 }
1108 }
1109
1110 // Handle the case when the error message is of specific type
1111 // other than the generic Match_InvalidOperand, and the
1112 // corresponding operand is missing.
1113 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1114 SMLoc ErrorLoc = IDLoc;
1115 if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
1116 return Error(ErrorLoc, "too few operands for instruction");
1117 }
1118
1119 switch (Result) {
1120 default:
1121 break;
1122 case Match_RequiresEvenGPRs:
1123 return Error(IDLoc,
1124 "double precision floating point operands must use even "
1125 "numbered X register");
1126 case Match_InvalidImmXLenLI:
1127 if (isRV64()) {
1128 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1129 return Error(ErrorLoc, "operand must be a constant 64-bit integer");
1130 }
1131 return generateImmOutOfRangeError(Operands, ErrorInfo,
1132 std::numeric_limits<int32_t>::min(),
1133 std::numeric_limits<uint32_t>::max());
1134 case Match_InvalidImmZero: {
1135 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1136 return Error(ErrorLoc, "immediate must be zero");
1137 }
1138 case Match_InvalidUImmLog2XLen:
1139 if (isRV64())
1140 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
1141 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1142 case Match_InvalidUImmLog2XLenNonZero:
1143 if (isRV64())
1144 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
1145 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
1146 case Match_InvalidUImmLog2XLenHalf:
1147 if (isRV64())
1148 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1149 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
1150 case Match_InvalidUImm2:
1151 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
1152 case Match_InvalidUImm2Lsb0:
1153 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 2,
1154 "immediate must be one of");
1155 case Match_InvalidUImm3:
1156 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
1157 case Match_InvalidUImm5:
1158 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1159 case Match_InvalidUImm7:
1160 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
1161 case Match_InvalidSImm5:
1162 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),
1163 (1 << 4) - 1);
1164 case Match_InvalidSImm6:
1165 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
1166 (1 << 5) - 1);
1167 case Match_InvalidSImm6NonZero:
1168 return generateImmOutOfRangeError(
1169 Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,
1170 "immediate must be non-zero in the range");
1171 case Match_InvalidCLUIImm:
1172 return generateImmOutOfRangeError(
1173 Operands, ErrorInfo, 1, (1 << 5) - 1,
1174 "immediate must be in [0xfffe0, 0xfffff] or");
1175 case Match_InvalidUImm7Lsb00:
1176 return generateImmOutOfRangeError(
1177 Operands, ErrorInfo, 0, (1 << 7) - 4,
1178 "immediate must be a multiple of 4 bytes in the range");
1179 case Match_InvalidUImm8Lsb00:
1180 return generateImmOutOfRangeError(
1181 Operands, ErrorInfo, 0, (1 << 8) - 4,
1182 "immediate must be a multiple of 4 bytes in the range");
1183 case Match_InvalidUImm8Lsb000:
1184 return generateImmOutOfRangeError(
1185 Operands, ErrorInfo, 0, (1 << 8) - 8,
1186 "immediate must be a multiple of 8 bytes in the range");
1187 case Match_InvalidSImm9Lsb0:
1188 return generateImmOutOfRangeError(
1189 Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
1190 "immediate must be a multiple of 2 bytes in the range");
1191 case Match_InvalidUImm9Lsb000:
1192 return generateImmOutOfRangeError(
1193 Operands, ErrorInfo, 0, (1 << 9) - 8,
1194 "immediate must be a multiple of 8 bytes in the range");
1195 case Match_InvalidUImm10Lsb00NonZero:
1196 return generateImmOutOfRangeError(
1197 Operands, ErrorInfo, 4, (1 << 10) - 4,
1198 "immediate must be a multiple of 4 bytes in the range");
1199 case Match_InvalidSImm10Lsb0000NonZero:
1200 return generateImmOutOfRangeError(
1201 Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
1202 "immediate must be a multiple of 16 bytes and non-zero in the range");
1203 case Match_InvalidSImm12:
1204 return generateImmOutOfRangeError(
1205 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
1206 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1207 "integer in the range");
1208 case Match_InvalidSImm12Lsb0:
1209 return generateImmOutOfRangeError(
1210 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
1211 "immediate must be a multiple of 2 bytes in the range");
1212 case Match_InvalidSImm12Lsb00000:
1213 return generateImmOutOfRangeError(
1214 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 32,
1215 "immediate must be a multiple of 32 bytes in the range");
1216 case Match_InvalidSImm13Lsb0:
1217 return generateImmOutOfRangeError(
1218 Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
1219 "immediate must be a multiple of 2 bytes in the range");
1220 case Match_InvalidUImm20LUI:
1221 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
1222 "operand must be a symbol with "
1223 "%hi/%tprel_hi modifier or an integer in "
1224 "the range");
1225 case Match_InvalidUImm20AUIPC:
1226 return generateImmOutOfRangeError(
1227 Operands, ErrorInfo, 0, (1 << 20) - 1,
1228 "operand must be a symbol with a "
1229 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1230 "an integer in the range");
1231 case Match_InvalidSImm21Lsb0JAL:
1232 return generateImmOutOfRangeError(
1233 Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
1234 "immediate must be a multiple of 2 bytes in the range");
1235 case Match_InvalidCSRSystemRegister: {
1236 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,
1237 "operand must be a valid system register "
1238 "name or an integer in the range");
1239 }
1240 case Match_InvalidBareSymbol: {
1241 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1242 return Error(ErrorLoc, "operand must be a bare symbol name");
1243 }
1244 case Match_InvalidPseudoJumpSymbol: {
1245 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1246 return Error(ErrorLoc, "operand must be a valid jump target");
1247 }
1248 case Match_InvalidCallSymbol: {
1249 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1250 return Error(ErrorLoc, "operand must be a bare symbol name");
1251 }
1252 case Match_InvalidTPRelAddSymbol: {
1253 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1254 return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier");
1255 }
1256 case Match_InvalidVTypeI: {
1257 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1258 return Error(
1259 ErrorLoc,
1260 "operand must be "
1261 "e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
1262 }
1263 case Match_InvalidVMaskRegister: {
1264 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1265 return Error(ErrorLoc, "operand must be v0.t");
1266 }
1267 case Match_InvalidSImm5Plus1: {
1268 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4) + 1,
1269 (1 << 4),
1270 "immediate must be in the range");
1271 }
1272 case Match_InvalidRnumArg: {
1273 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
1274 }
1275 }
1276
1277 llvm_unreachable("Unknown match type detected!");
1278}
1279
1280// Attempts to match Name as a register (either using the default name or
1281// alternative ABI names), setting RegNo to the matching register. Upon
1282// failure, returns true and sets RegNo to 0. If IsRV32E then registers
1283// x16-x31 will be rejected.
1284static bool matchRegisterNameHelper(bool IsRV32E, MCRegister &RegNo,
1285 StringRef Name) {
1286 RegNo = MatchRegisterName(Name);
1287 // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
1288 // match always matches the 64-bit variant, and not the 16/32-bit one.
1289 assert(!(RegNo >= RISCV::F0_H && RegNo <= RISCV::F31_H));
1290 assert(!(RegNo >= RISCV::F0_F && RegNo <= RISCV::F31_F));
1291 // The default FPR register class is based on the tablegen enum ordering.
1292 static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");
1293 static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
1294 if (RegNo == RISCV::NoRegister)
1295 RegNo = MatchRegisterAltName(Name);
1296 if (IsRV32E && RegNo >= RISCV::X16 && RegNo <= RISCV::X31)
1297 RegNo = RISCV::NoRegister;
1298 return RegNo == RISCV::NoRegister;
1299}
1300
1301bool RISCVAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
1302 SMLoc &EndLoc) {
1303 if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success)
1304 return Error(StartLoc, "invalid register name");
1305 return false;
1306}
1307
1308OperandMatchResultTy RISCVAsmParser::tryParseRegister(MCRegister &RegNo,
1309 SMLoc &StartLoc,
1310 SMLoc &EndLoc) {
1311 const AsmToken &Tok = getParser().getTok();
1312 StartLoc = Tok.getLoc();
1313 EndLoc = Tok.getEndLoc();
1314 RegNo = 0;
1315 StringRef Name = getLexer().getTok().getIdentifier();
1316
1317 if (matchRegisterNameHelper(isRV32E(), (MCRegister &)RegNo, Name))
1318 return MatchOperand_NoMatch;
1319
1320 getParser().Lex(); // Eat identifier token.
1321 return MatchOperand_Success;
1322}
1323
1324OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands,
1325 bool AllowParens) {
1326 SMLoc FirstS = getLoc();
1327 bool HadParens = false;
1328 AsmToken LParen;
1329
1330 // If this is an LParen and a parenthesised register name is allowed, parse it
1331 // atomically.
1332 if (AllowParens && getLexer().is(AsmToken::LParen)) {
1333 AsmToken Buf[2];
1334 size_t ReadCount = getLexer().peekTokens(Buf);
1335 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
1336 HadParens = true;
1337 LParen = getParser().getTok();
1338 getParser().Lex(); // Eat '('
1339 }
1340 }
1341
1342 switch (getLexer().getKind()) {
1343 default:
1344 if (HadParens)
1345 getLexer().UnLex(LParen);
1346 return MatchOperand_NoMatch;
1348 StringRef Name = getLexer().getTok().getIdentifier();
1349 MCRegister RegNo;
1350 matchRegisterNameHelper(isRV32E(), RegNo, Name);
1351
1352 if (RegNo == RISCV::NoRegister) {
1353 if (HadParens)
1354 getLexer().UnLex(LParen);
1355 return MatchOperand_NoMatch;
1356 }
1357 if (HadParens)
1358 Operands.push_back(RISCVOperand::createToken("(", FirstS));
1359 SMLoc S = getLoc();
1361 getLexer().Lex();
1362 Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
1363 }
1364
1365 if (HadParens) {
1366 getParser().Lex(); // Eat ')'
1367 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
1368 }
1369
1370 return MatchOperand_Success;
1371}
1372
1374RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
1375 SMLoc S = getLoc();
1376 SMLoc E;
1377 const MCExpr *Res;
1378
1379 switch (getLexer().getKind()) {
1380 default:
1381 return MatchOperand_NoMatch;
1382 case AsmToken::LParen:
1383 case AsmToken::Minus:
1384 case AsmToken::Plus:
1385 case AsmToken::Exclaim:
1386 case AsmToken::Tilde:
1387 case AsmToken::Integer:
1388 case AsmToken::String: {
1389 if (getParser().parseExpression(Res, E))
1391
1392 auto *CE = dyn_cast<MCConstantExpr>(Res);
1393 if (CE) {
1394 int64_t Imm = CE->getValue();
1395 if (isUInt<7>(Imm)) {
1396 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1397 return MatchOperand_Success;
1398 }
1399 }
1400
1401 Twine Msg = "immediate must be an integer in the range";
1402 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 7) - 1) + "]");
1404 }
1405 case AsmToken::Identifier: {
1407 if (getParser().parseIdentifier(Identifier))
1409
1410 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1411 if (Opcode) {
1412 Res = MCConstantExpr::create(Opcode->Value, getContext());
1414 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1415 return MatchOperand_Success;
1416 }
1417
1418 Twine Msg = "operand must be a valid opcode name or an "
1419 "integer in the range";
1420 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 7) - 1) + "]");
1422 }
1423 case AsmToken::Percent: {
1424 // Discard operand with modifier.
1425 Twine Msg = "immediate must be an integer in the range";
1426 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 7) - 1) + "]");
1428 }
1429 }
1430
1431 return MatchOperand_NoMatch;
1432}
1433
1435RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
1436 SMLoc S = getLoc();
1437 const MCExpr *Res;
1438
1439 switch (getLexer().getKind()) {
1440 default:
1441 return MatchOperand_NoMatch;
1442 case AsmToken::LParen:
1443 case AsmToken::Minus:
1444 case AsmToken::Plus:
1445 case AsmToken::Exclaim:
1446 case AsmToken::Tilde:
1447 case AsmToken::Integer:
1448 case AsmToken::String: {
1449 if (getParser().parseExpression(Res))
1451
1452 auto *CE = dyn_cast<MCConstantExpr>(Res);
1453 if (CE) {
1454 int64_t Imm = CE->getValue();
1455 if (isUInt<12>(Imm)) {
1456 auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
1457 // Accept an immediate representing a named or un-named Sys Reg
1458 // if the range is valid, regardless of the required features.
1459 Operands.push_back(
1460 RISCVOperand::createSysReg(SysReg ? SysReg->Name : "", S, Imm));
1461 return MatchOperand_Success;
1462 }
1463 }
1464
1465 Twine Msg = "immediate must be an integer in the range";
1466 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1468 }
1469 case AsmToken::Identifier: {
1471 if (getParser().parseIdentifier(Identifier))
1473
1474 auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1475 if (!SysReg)
1476 SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);
1477 if (!SysReg)
1478 if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
1479 Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
1480 SysReg->Name + "'");
1481
1482 // Accept a named Sys Reg if the required features are present.
1483 if (SysReg) {
1484 if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits())) {
1485 Error(S, "system register use requires an option to be enabled");
1487 }
1488 Operands.push_back(
1489 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
1490 return MatchOperand_Success;
1491 }
1492
1493 Twine Msg = "operand must be a valid system register name "
1494 "or an integer in the range";
1495 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1497 }
1498 case AsmToken::Percent: {
1499 // Discard operand with modifier.
1500 Twine Msg = "immediate must be an integer in the range";
1501 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1503 }
1504 }
1505
1506 return MatchOperand_NoMatch;
1507}
1508
1509OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
1510 SMLoc S = getLoc();
1511 SMLoc E;
1512 const MCExpr *Res;
1513
1514 switch (getLexer().getKind()) {
1515 default:
1516 return MatchOperand_NoMatch;
1517 case AsmToken::LParen:
1518 case AsmToken::Dot:
1519 case AsmToken::Minus:
1520 case AsmToken::Plus:
1521 case AsmToken::Exclaim:
1522 case AsmToken::Tilde:
1523 case AsmToken::Integer:
1524 case AsmToken::String:
1526 if (getParser().parseExpression(Res, E))
1528 break;
1529 case AsmToken::Percent:
1530 return parseOperandWithModifier(Operands);
1531 }
1532
1533 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1534 return MatchOperand_Success;
1535}
1536
1538RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
1539 SMLoc S = getLoc();
1540 SMLoc E;
1541
1542 if (getLexer().getKind() != AsmToken::Percent) {
1543 Error(getLoc(), "expected '%' for operand modifier");
1545 }
1546
1547 getParser().Lex(); // Eat '%'
1548
1549 if (getLexer().getKind() != AsmToken::Identifier) {
1550 Error(getLoc(), "expected valid identifier for operand modifier");
1552 }
1553 StringRef Identifier = getParser().getTok().getIdentifier();
1556 Error(getLoc(), "unrecognized operand modifier");
1558 }
1559
1560 getParser().Lex(); // Eat the identifier
1561 if (getLexer().getKind() != AsmToken::LParen) {
1562 Error(getLoc(), "expected '('");
1564 }
1565 getParser().Lex(); // Eat '('
1566
1567 const MCExpr *SubExpr;
1568 if (getParser().parseParenExpression(SubExpr, E)) {
1570 }
1571
1572 const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
1573 Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
1574 return MatchOperand_Success;
1575}
1576
1577OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
1578 SMLoc S = getLoc();
1579 const MCExpr *Res;
1580
1581 if (getLexer().getKind() != AsmToken::Identifier)
1582 return MatchOperand_NoMatch;
1583
1585 AsmToken Tok = getLexer().getTok();
1586
1587 if (getParser().parseIdentifier(Identifier))
1589
1591
1592 if (Identifier.consume_back("@plt")) {
1593 Error(getLoc(), "'@plt' operand not valid for instruction");
1595 }
1596
1597 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1598
1599 if (Sym->isVariable()) {
1600 const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1601 if (!isa<MCSymbolRefExpr>(V)) {
1602 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1603 return MatchOperand_NoMatch;
1604 }
1605 Res = V;
1606 } else
1607 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1608
1609 MCBinaryExpr::Opcode Opcode;
1610 switch (getLexer().getKind()) {
1611 default:
1612 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1613 return MatchOperand_Success;
1614 case AsmToken::Plus:
1615 Opcode = MCBinaryExpr::Add;
1616 getLexer().Lex();
1617 break;
1618 case AsmToken::Minus:
1619 Opcode = MCBinaryExpr::Sub;
1620 getLexer().Lex();
1621 break;
1622 }
1623
1624 const MCExpr *Expr;
1625 if (getParser().parseExpression(Expr, E))
1627 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1628 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1629 return MatchOperand_Success;
1630}
1631
1632OperandMatchResultTy RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {
1633 SMLoc S = getLoc();
1634 const MCExpr *Res;
1635
1636 if (getLexer().getKind() != AsmToken::Identifier)
1637 return MatchOperand_NoMatch;
1638
1639 // Avoid parsing the register in `call rd, foo` as a call symbol.
1640 if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement)
1641 return MatchOperand_NoMatch;
1642
1644 if (getParser().parseIdentifier(Identifier))
1646
1648
1650 if (Identifier.consume_back("@plt"))
1652
1653 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1654 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1655 Res = RISCVMCExpr::create(Res, Kind, getContext());
1656 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1657 return MatchOperand_Success;
1658}
1659
1661RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
1662 SMLoc S = getLoc();
1663 SMLoc E;
1664 const MCExpr *Res;
1665
1666 if (getParser().parseExpression(Res, E))
1668
1669 if (Res->getKind() != MCExpr::ExprKind::SymbolRef ||
1670 cast<MCSymbolRefExpr>(Res)->getKind() ==
1671 MCSymbolRefExpr::VariantKind::VK_PLT) {
1672 Error(S, "operand must be a valid jump target");
1674 }
1675
1676 Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext());
1677 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1678 return MatchOperand_Success;
1679}
1680
1681OperandMatchResultTy RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
1682 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
1683 // both being acceptable forms. When parsing `jal ra, foo` this function
1684 // will be called for the `ra` register operand in an attempt to match the
1685 // single-operand alias. parseJALOffset must fail for this case. It would
1686 // seem logical to try parse the operand using parseImmediate and return
1687 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
1688 // the second form rather than the first). We can't do this as there's no
1689 // way of rewinding the lexer state. Instead, return NoMatch if this operand
1690 // is an identifier and is followed by a comma.
1691 if (getLexer().is(AsmToken::Identifier) &&
1692 getLexer().peekTok().is(AsmToken::Comma))
1693 return MatchOperand_NoMatch;
1694
1695 return parseImmediate(Operands);
1696}
1697
1698OperandMatchResultTy RISCVAsmParser::parseVTypeI(OperandVector &Operands) {
1699 SMLoc S = getLoc();
1700 if (getLexer().isNot(AsmToken::Identifier))
1701 return MatchOperand_NoMatch;
1702
1703 SmallVector<AsmToken, 7> VTypeIElements;
1704 // Put all the tokens for vtypei operand into VTypeIElements vector.
1705 while (getLexer().isNot(AsmToken::EndOfStatement)) {
1706 VTypeIElements.push_back(getLexer().getTok());
1707 getLexer().Lex();
1708 if (getLexer().is(AsmToken::EndOfStatement))
1709 break;
1710 if (getLexer().isNot(AsmToken::Comma))
1711 goto MatchFail;
1712 AsmToken Comma = getLexer().getTok();
1713 VTypeIElements.push_back(Comma);
1714 getLexer().Lex();
1715 }
1716
1717 if (VTypeIElements.size() == 7) {
1718 // The VTypeIElements layout is:
1719 // SEW comma LMUL comma TA comma MA
1720 // 0 1 2 3 4 5 6
1721 StringRef Name = VTypeIElements[0].getIdentifier();
1722 if (!Name.consume_front("e"))
1723 goto MatchFail;
1724 unsigned Sew;
1725 if (Name.getAsInteger(10, Sew))
1726 goto MatchFail;
1727 if (!RISCVVType::isValidSEW(Sew))
1728 goto MatchFail;
1729
1730 Name = VTypeIElements[2].getIdentifier();
1731 if (!Name.consume_front("m"))
1732 goto MatchFail;
1733 // "m" or "mf"
1734 bool Fractional = Name.consume_front("f");
1735 unsigned Lmul;
1736 if (Name.getAsInteger(10, Lmul))
1737 goto MatchFail;
1738 if (!RISCVVType::isValidLMUL(Lmul, Fractional))
1739 goto MatchFail;
1740
1741 // ta or tu
1742 Name = VTypeIElements[4].getIdentifier();
1743 bool TailAgnostic;
1744 if (Name == "ta")
1745 TailAgnostic = true;
1746 else if (Name == "tu")
1747 TailAgnostic = false;
1748 else
1749 goto MatchFail;
1750
1751 // ma or mu
1752 Name = VTypeIElements[6].getIdentifier();
1753 bool MaskAgnostic;
1754 if (Name == "ma")
1755 MaskAgnostic = true;
1756 else if (Name == "mu")
1757 MaskAgnostic = false;
1758 else
1759 goto MatchFail;
1760
1761 RISCVII::VLMUL VLMUL = RISCVVType::encodeLMUL(Lmul, Fractional);
1762
1763 unsigned VTypeI =
1765 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
1766 return MatchOperand_Success;
1767 }
1768
1769// If NoMatch, unlex all the tokens that comprise a vtypei operand
1770MatchFail:
1771 while (!VTypeIElements.empty())
1772 getLexer().UnLex(VTypeIElements.pop_back_val());
1773 return MatchOperand_NoMatch;
1774}
1775
1776OperandMatchResultTy RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
1777 if (getLexer().isNot(AsmToken::Identifier))
1778 return MatchOperand_NoMatch;
1779
1780 StringRef Name = getLexer().getTok().getIdentifier();
1781 if (!Name.consume_back(".t")) {
1782 Error(getLoc(), "expected '.t' suffix");
1784 }
1785 MCRegister RegNo;
1786 matchRegisterNameHelper(isRV32E(), RegNo, Name);
1787
1788 if (RegNo == RISCV::NoRegister)
1789 return MatchOperand_NoMatch;
1790 if (RegNo != RISCV::V0)
1791 return MatchOperand_NoMatch;
1792 SMLoc S = getLoc();
1794 getLexer().Lex();
1795 Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
1796 return MatchOperand_Success;
1797}
1798
1799OperandMatchResultTy RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
1800 if (getLexer().isNot(AsmToken::Identifier))
1801 return MatchOperand_NoMatch;
1802
1803 StringRef Name = getLexer().getTok().getIdentifier();
1804 MCRegister RegNo;
1805 matchRegisterNameHelper(isRV32E(), RegNo, Name);
1806
1807 if (RegNo == RISCV::NoRegister)
1808 return MatchOperand_NoMatch;
1809 SMLoc S = getLoc();
1811 getLexer().Lex();
1812 Operands.push_back(RISCVOperand::createReg(
1813 RegNo, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
1814 return MatchOperand_Success;
1815}
1816
1817OperandMatchResultTy RISCVAsmParser::parseFRMArg(OperandVector &Operands) {
1818 if (getLexer().isNot(AsmToken::Identifier)) {
1819 TokError("operand must be a valid floating point rounding mode mnemonic");
1821 }
1822
1823 StringRef Str = getLexer().getTok().getIdentifier();
1825
1826 if (FRM == RISCVFPRndMode::Invalid) {
1827 TokError("operand must be a valid floating point rounding mode mnemonic");
1829 }
1830
1831 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
1832 Lex(); // Eat identifier token.
1833 return MatchOperand_Success;
1834}
1835
1836OperandMatchResultTy RISCVAsmParser::parseFenceArg(OperandVector &Operands) {
1837 const AsmToken &Tok = getLexer().getTok();
1838
1839 if (Tok.is(AsmToken::Integer)) {
1840 if (Tok.getIntVal() != 0)
1841 goto ParseFail;
1842
1843 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
1844 Lex();
1845 return MatchOperand_Success;
1846 }
1847
1848 if (Tok.is(AsmToken::Identifier)) {
1849 StringRef Str = Tok.getIdentifier();
1850
1851 // Letters must be unique, taken from 'iorw', and in ascending order. This
1852 // holds as long as each individual character is one of 'iorw' and is
1853 // greater than the previous character.
1854 unsigned Imm = 0;
1855 bool Valid = true;
1856 char Prev = '\0';
1857 for (char c : Str) {
1858 switch (c) {
1859 default:
1860 Valid = false;
1861 break;
1862 case 'i':
1864 break;
1865 case 'o':
1867 break;
1868 case 'r':
1870 break;
1871 case 'w':
1873 break;
1874 }
1875
1876 if (c <= Prev) {
1877 Valid = false;
1878 break;
1879 }
1880 Prev = c;
1881 }
1882
1883 if (!Valid)
1884 goto ParseFail;
1885
1886 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
1887 Lex();
1888 return MatchOperand_Success;
1889 }
1890
1891ParseFail:
1892 TokError("operand must be formed of letters selected in-order from 'iorw' "
1893 "or be 0");
1895}
1896
1898RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
1899 if (getLexer().isNot(AsmToken::LParen)) {
1900 Error(getLoc(), "expected '('");
1902 }
1903
1904 getParser().Lex(); // Eat '('
1905 Operands.push_back(RISCVOperand::createToken("(", getLoc()));
1906
1907 if (parseRegister(Operands) != MatchOperand_Success) {
1908 Error(getLoc(), "expected register");
1910 }
1911
1912 if (getLexer().isNot(AsmToken::RParen)) {
1913 Error(getLoc(), "expected ')'");
1915 }
1916
1917 getParser().Lex(); // Eat ')'
1918 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
1919
1920 return MatchOperand_Success;
1921}
1922
1924RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {
1925 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
1926 // as one of their register operands, such as `(a0)`. This just denotes that
1927 // the register (in this case `a0`) contains a memory address.
1928 //
1929 // Normally, we would be able to parse these by putting the parens into the
1930 // instruction string. However, GNU as also accepts a zero-offset memory
1931 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
1932 // with parseImmediate followed by parseMemOpBaseReg, but these instructions
1933 // do not accept an immediate operand, and we do not want to add a "dummy"
1934 // operand that is silently dropped.
1935 //
1936 // Instead, we use this custom parser. This will: allow (and discard) an
1937 // offset if it is zero; require (and discard) parentheses; and add only the
1938 // parsed register operand to `Operands`.
1939 //
1940 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
1941 // which will only print the register surrounded by parentheses (which GNU as
1942 // also uses as its canonical representation for these operands).
1943 std::unique_ptr<RISCVOperand> OptionalImmOp;
1944
1945 if (getLexer().isNot(AsmToken::LParen)) {
1946 // Parse an Integer token. We do not accept arbritrary constant expressions
1947 // in the offset field (because they may include parens, which complicates
1948 // parsing a lot).
1949 int64_t ImmVal;
1950 SMLoc ImmStart = getLoc();
1951 if (getParser().parseIntToken(ImmVal,
1952 "expected '(' or optional integer offset"))
1954
1955 // Create a RISCVOperand for checking later (so the error messages are
1956 // nicer), but we don't add it to Operands.
1957 SMLoc ImmEnd = getLoc();
1958 OptionalImmOp =
1959 RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()),
1960 ImmStart, ImmEnd, isRV64());
1961 }
1962
1963 if (getLexer().isNot(AsmToken::LParen)) {
1964 Error(getLoc(), OptionalImmOp ? "expected '(' after optional integer offset"
1965 : "expected '(' or optional integer offset");
1967 }
1968 getParser().Lex(); // Eat '('
1969
1970 if (parseRegister(Operands) != MatchOperand_Success) {
1971 Error(getLoc(), "expected register");
1973 }
1974
1975 if (getLexer().isNot(AsmToken::RParen)) {
1976 Error(getLoc(), "expected ')'");
1978 }
1979 getParser().Lex(); // Eat ')'
1980
1981 // Deferred Handling of non-zero offsets. This makes the error messages nicer.
1982 if (OptionalImmOp && !OptionalImmOp->isImmZero()) {
1983 Error(OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
1984 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
1986 }
1987
1988 return MatchOperand_Success;
1989}
1990
1991/// Looks at a token type and creates the relevant operand from this
1992/// information, adding to Operands. If operand was parsed, returns false, else
1993/// true.
1994bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1995 // Check if the current operand has a custom associated parser, if so, try to
1996 // custom parse the operand, or fallback to the general approach.
1998 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
1999 if (Result == MatchOperand_Success)
2000 return false;
2001 if (Result == MatchOperand_ParseFail)
2002 return true;
2003
2004 // Attempt to parse token as a register.
2005 if (parseRegister(Operands, true) == MatchOperand_Success)
2006 return false;
2007
2008 // Attempt to parse token as an immediate
2010 // Parse memory base register if present
2011 if (getLexer().is(AsmToken::LParen))
2012 return parseMemOpBaseReg(Operands) != MatchOperand_Success;
2013 return false;
2014 }
2015
2016 // Finally we have exhausted all options and must declare defeat.
2017 Error(getLoc(), "unknown operand");
2018 return true;
2019}
2020
2021bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
2022 StringRef Name, SMLoc NameLoc,
2024 // Ensure that if the instruction occurs when relaxation is enabled,
2025 // relocations are forced for the file. Ideally this would be done when there
2026 // is enough information to reliably determine if the instruction itself may
2027 // cause relaxations. Unfortunately instruction processing stage occurs in the
2028 // same pass as relocation emission, so it's too late to set a 'sticky bit'
2029 // for the entire file.
2030 if (getSTI().getFeatureBits()[RISCV::FeatureRelax]) {
2031 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
2032 if (Assembler != nullptr) {
2033 RISCVAsmBackend &MAB =
2034 static_cast<RISCVAsmBackend &>(Assembler->getBackend());
2035 MAB.setForceRelocs();
2036 }
2037 }
2038
2039 // First operand is token for instruction
2040 Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
2041
2042 // If there are no more operands, then finish
2043 if (getLexer().is(AsmToken::EndOfStatement)) {
2044 getParser().Lex(); // Consume the EndOfStatement.
2045 return false;
2046 }
2047
2048 // Parse first operand
2049 if (parseOperand(Operands, Name))
2050 return true;
2051
2052 // Parse until end of statement, consuming commas between operands
2053 while (getLexer().is(AsmToken::Comma)) {
2054 // Consume comma token
2055 getLexer().Lex();
2056
2057 // Parse next operand
2058 if (parseOperand(Operands, Name))
2059 return true;
2060 }
2061
2062 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2063 SMLoc Loc = getLexer().getLoc();
2064 getParser().eatToEndOfStatement();
2065 return Error(Loc, "unexpected token");
2066 }
2067
2068 getParser().Lex(); // Consume the EndOfStatement.
2069 return false;
2070}
2071
2072bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
2075
2076 if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
2077 Kind = RE->getKind();
2078 Expr = RE->getSubExpr();
2079 }
2080
2081 MCValue Res;
2082 MCFixup Fixup;
2083 if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup))
2084 return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None;
2085 return false;
2086}
2087
2088bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
2089 // This returns false if this function recognizes the directive
2090 // regardless of whether it is successfully handles or reports an
2091 // error. Otherwise it returns true to give the generic parser a
2092 // chance at recognizing it.
2093 StringRef IDVal = DirectiveID.getString();
2094
2095 if (IDVal == ".option")
2096 return parseDirectiveOption();
2097 if (IDVal == ".attribute")
2098 return parseDirectiveAttribute();
2099 if (IDVal == ".insn")
2100 return parseDirectiveInsn(DirectiveID.getLoc());
2101 if (IDVal == ".variant_cc")
2102 return parseDirectiveVariantCC();
2103
2104 return true;
2105}
2106
2107bool RISCVAsmParser::parseDirectiveOption() {
2108 MCAsmParser &Parser = getParser();
2109 // Get the option token.
2110 AsmToken Tok = Parser.getTok();
2111
2112 // At the moment only identifiers are supported.
2113 if (parseToken(AsmToken::Identifier, "expected identifier"))
2114 return true;
2115
2117
2118 if (Option == "push") {
2119 if (Parser.parseEOL())
2120 return true;
2121
2122 getTargetStreamer().emitDirectiveOptionPush();
2123 pushFeatureBits();
2124 return false;
2125 }
2126
2127 if (Option == "pop") {
2128 SMLoc StartLoc = Parser.getTok().getLoc();
2129 if (Parser.parseEOL())
2130 return true;
2131
2132 getTargetStreamer().emitDirectiveOptionPop();
2133 if (popFeatureBits())
2134 return Error(StartLoc, ".option pop with no .option push");
2135
2136 return false;
2137 }
2138
2139 if (Option == "rvc") {
2140 if (Parser.parseEOL())
2141 return true;
2142
2143 getTargetStreamer().emitDirectiveOptionRVC();
2144 setFeatureBits(RISCV::FeatureStdExtC, "c");
2145 return false;
2146 }
2147
2148 if (Option == "norvc") {
2149 if (Parser.parseEOL())
2150 return true;
2151
2152 getTargetStreamer().emitDirectiveOptionNoRVC();
2153 clearFeatureBits(RISCV::FeatureStdExtC, "c");
2154 clearFeatureBits(RISCV::FeatureExtZca, "+experimental-zca");
2155 return false;
2156 }
2157
2158 if (Option == "pic") {
2159 if (Parser.parseEOL())
2160 return true;
2161
2162 getTargetStreamer().emitDirectiveOptionPIC();
2163 ParserOptions.IsPicEnabled = true;
2164 return false;
2165 }
2166
2167 if (Option == "nopic") {
2168 if (Parser.parseEOL())
2169 return true;
2170
2171 getTargetStreamer().emitDirectiveOptionNoPIC();
2172 ParserOptions.IsPicEnabled = false;
2173 return false;
2174 }
2175
2176 if (Option == "relax") {
2177 if (Parser.parseEOL())
2178 return true;
2179
2180 getTargetStreamer().emitDirectiveOptionRelax();
2181 setFeatureBits(RISCV::FeatureRelax, "relax");
2182 return false;
2183 }
2184
2185 if (Option == "norelax") {
2186 if (Parser.parseEOL())
2187 return true;
2188
2189 getTargetStreamer().emitDirectiveOptionNoRelax();
2190 clearFeatureBits(RISCV::FeatureRelax, "relax");
2191 return false;
2192 }
2193
2194 // Unknown option.
2195 Warning(Parser.getTok().getLoc(),
2196 "unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'relax' or "
2197 "'norelax'");
2198 Parser.eatToEndOfStatement();
2199 return false;
2200}
2201
2202/// parseDirectiveAttribute
2203/// ::= .attribute expression ',' ( expression | "string" )
2204/// ::= .attribute identifier ',' ( expression | "string" )
2205bool RISCVAsmParser::parseDirectiveAttribute() {
2206 MCAsmParser &Parser = getParser();
2207 int64_t Tag;
2208 SMLoc TagLoc;
2209 TagLoc = Parser.getTok().getLoc();
2210 if (Parser.getTok().is(AsmToken::Identifier)) {
2211 StringRef Name = Parser.getTok().getIdentifier();
2212 std::optional<unsigned> Ret =
2214 if (!Ret) {
2215 Error(TagLoc, "attribute name not recognised: " + Name);
2216 return false;
2217 }
2218 Tag = *Ret;
2219 Parser.Lex();
2220 } else {
2221 const MCExpr *AttrExpr;
2222
2223 TagLoc = Parser.getTok().getLoc();
2224 if (Parser.parseExpression(AttrExpr))
2225 return true;
2226
2227 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
2228 if (check(!CE, TagLoc, "expected numeric constant"))
2229 return true;
2230
2231 Tag = CE->getValue();
2232 }
2233
2234 if (Parser.parseComma())
2235 return true;
2236
2237 StringRef StringValue;
2238 int64_t IntegerValue = 0;
2239 bool IsIntegerValue = true;
2240
2241 // RISC-V attributes have a string value if the tag number is odd
2242 // and an integer value if the tag number is even.
2243 if (Tag % 2)
2244 IsIntegerValue = false;
2245
2246 SMLoc ValueExprLoc = Parser.getTok().getLoc();
2247 if (IsIntegerValue) {
2248 const MCExpr *ValueExpr;
2249 if (Parser.parseExpression(ValueExpr))
2250 return true;
2251
2252 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
2253 if (!CE)
2254 return Error(ValueExprLoc, "expected numeric constant");
2255 IntegerValue = CE->getValue();
2256 } else {
2257 if (Parser.getTok().isNot(AsmToken::String))
2258 return Error(Parser.getTok().getLoc(), "expected string constant");
2259
2260 StringValue = Parser.getTok().getStringContents();
2261 Parser.Lex();
2262 }
2263
2264 if (Parser.parseEOL())
2265 return true;
2266
2267 if (IsIntegerValue)
2268 getTargetStreamer().emitAttribute(Tag, IntegerValue);
2269 else if (Tag != RISCVAttrs::ARCH)
2270 getTargetStreamer().emitTextAttribute(Tag, StringValue);
2271 else {
2272 StringRef Arch = StringValue;
2273 for (auto Feature : RISCVFeatureKV)
2275 clearFeatureBits(Feature.Value, Feature.Key);
2276
2277 auto ParseResult = llvm::RISCVISAInfo::parseArchString(
2278 StringValue, /*EnableExperimentalExtension=*/true,
2279 /*ExperimentalExtensionVersionCheck=*/true);
2280 if (!ParseResult) {
2281 std::string Buffer;
2282 raw_string_ostream OutputErrMsg(Buffer);
2283 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2284 OutputErrMsg << "invalid arch name '" << Arch << "', "
2285 << ErrMsg.getMessage();
2286 });
2287
2288 return Error(ValueExprLoc, OutputErrMsg.str());
2289 }
2290 auto &ISAInfo = *ParseResult;
2291
2292 for (auto Feature : RISCVFeatureKV)
2293 if (ISAInfo->hasExtension(Feature.Key))
2294 setFeatureBits(Feature.Value, Feature.Key);
2295
2296 if (ISAInfo->getXLen() == 32)
2297 clearFeatureBits(RISCV::Feature64Bit, "64bit");
2298 else if (ISAInfo->getXLen() == 64)
2299 setFeatureBits(RISCV::Feature64Bit, "64bit");
2300 else
2301 return Error(ValueExprLoc, "bad arch string " + Arch);
2302
2303 // Then emit the arch string.
2304 getTargetStreamer().emitTextAttribute(Tag, ISAInfo->toString());
2305 }
2306
2307 return false;
2308}
2309
2310/// parseDirectiveInsn
2311/// ::= .insn [ format encoding, (operands (, operands)*) ]
2312bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
2313 MCAsmParser &Parser = getParser();
2314
2315 // Expect instruction format as identifier.
2317 SMLoc ErrorLoc = Parser.getTok().getLoc();
2318 if (Parser.parseIdentifier(Format))
2319 return Error(ErrorLoc, "expected instruction format");
2320
2321 if (Format != "r" && Format != "r4" && Format != "i" && Format != "b" &&
2322 Format != "sb" && Format != "u" && Format != "j" && Format != "uj" &&
2323 Format != "s")
2324 return Error(ErrorLoc, "invalid instruction format");
2325
2326 std::string FormatName = (".insn_" + Format).str();
2327
2330
2331 if (ParseInstruction(Info, FormatName, L, Operands))
2332 return true;
2333
2334 unsigned Opcode;
2336 return MatchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),
2337 ErrorInfo,
2338 /*MatchingInlineAsm=*/false);
2339}
2340
2341/// parseDirectiveVariantCC
2342/// ::= .variant_cc symbol
2343bool RISCVAsmParser::parseDirectiveVariantCC() {
2345 if (getParser().parseIdentifier(Name))
2346 return TokError("expected symbol name");
2347 if (parseEOL())
2348 return false;
2349 getTargetStreamer().emitDirectiveVariantCC(
2350 *getContext().getOrCreateSymbol(Name));
2351 return false;
2352}
2353
2354void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
2355 MCInst CInst;
2356 bool Res = RISCVRVC::compress(CInst, Inst, getSTI());
2357 if (Res)
2358 ++RISCVNumInstrsCompressed;
2359 S.emitInstruction((Res ? CInst : Inst), getSTI());
2360}
2361
2362void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
2363 MCStreamer &Out) {
2365 RISCVMatInt::generateInstSeq(Value, getSTI().getFeatureBits());
2366
2367 MCRegister SrcReg = RISCV::X0;
2368 for (RISCVMatInt::Inst &Inst : Seq) {
2369 switch (Inst.getOpndKind()) {
2370 case RISCVMatInt::Imm:
2371 emitToStreamer(Out,
2372 MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addImm(Inst.getImm()));
2373 break;
2374 case RISCVMatInt::RegX0:
2375 emitToStreamer(
2376 Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addReg(
2377 RISCV::X0));
2378 break;
2380 emitToStreamer(
2381 Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addReg(
2382 SrcReg));
2383 break;
2385 emitToStreamer(
2386 Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addImm(
2387 Inst.getImm()));
2388 break;
2389 }
2390
2391 // Only the first instruction has X0 as its source.
2392 SrcReg = DestReg;
2393 }
2394}
2395
2396void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
2397 const MCExpr *Symbol,
2399 unsigned SecondOpcode, SMLoc IDLoc,
2400 MCStreamer &Out) {
2401 // A pair of instructions for PC-relative addressing; expands to
2402 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
2403 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
2404 MCContext &Ctx = getContext();
2405
2406 MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
2407 Out.emitLabel(TmpLabel);
2408
2409 const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
2410 emitToStreamer(
2411 Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
2412
2413 const MCExpr *RefToLinkTmpLabel =
2416
2417 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
2418 .addOperand(DestReg)
2419 .addOperand(TmpReg)
2420 .addExpr(RefToLinkTmpLabel));
2421}
2422
2423void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
2424 MCStreamer &Out) {
2425 // The load local address pseudo-instruction "lla" is used in PC-relative
2426 // addressing of local symbols:
2427 // lla rdest, symbol
2428 // expands to
2429 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
2430 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
2431 MCOperand DestReg = Inst.getOperand(0);
2432 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2433 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
2434 RISCV::ADDI, IDLoc, Out);
2435}
2436
2437void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
2438 MCStreamer &Out) {
2439 // The load address pseudo-instruction "la" is used in PC-relative and
2440 // GOT-indirect addressing of global symbols:
2441 // la rdest, symbol
2442 // expands to either (for non-PIC)
2443 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
2444 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
2445 // or (for PIC)
2446 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
2447 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
2448 MCOperand DestReg = Inst.getOperand(0);
2449 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2450 unsigned SecondOpcode;
2452 if (ParserOptions.IsPicEnabled) {
2453 SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
2455 } else {
2456 SecondOpcode = RISCV::ADDI;
2458 }
2459 emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out);
2460}
2461
2462void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
2463 MCStreamer &Out) {
2464 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
2465 // initial-exec TLS model addressing of global symbols:
2466 // la.tls.ie rdest, symbol
2467 // expands to
2468 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
2469 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
2470 MCOperand DestReg = Inst.getOperand(0);
2471 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2472 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
2473 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI,
2474 SecondOpcode, IDLoc, Out);
2475}
2476
2477void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
2478 MCStreamer &Out) {
2479 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
2480 // global-dynamic TLS model addressing of global symbols:
2481 // la.tls.gd rdest, symbol
2482 // expands to
2483 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
2484 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
2485 MCOperand DestReg = Inst.getOperand(0);
2486 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2487 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI,
2488 RISCV::ADDI, IDLoc, Out);
2489}
2490
2491void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
2492 SMLoc IDLoc, MCStreamer &Out,
2493 bool HasTmpReg) {
2494 // The load/store pseudo-instruction does a pc-relative load with
2495 // a symbol.
2496 //
2497 // The expansion looks like this
2498 //
2499 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
2500 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
2501 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
2502 MCOperand DestReg = Inst.getOperand(DestRegOpIdx);
2503 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
2504 MCOperand TmpReg = Inst.getOperand(0);
2505 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
2506 emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
2507 Opcode, IDLoc, Out);
2508}
2509
2510void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
2511 int64_t Width, SMLoc IDLoc,
2512 MCStreamer &Out) {
2513 // The sign/zero extend pseudo-instruction does two shifts, with the shift
2514 // amounts dependent on the XLEN.
2515 //
2516 // The expansion looks like this
2517 //
2518 // SLLI rd, rs, XLEN - Width
2519 // SR[A|R]I rd, rd, XLEN - Width
2520 MCOperand DestReg = Inst.getOperand(0);
2521 MCOperand SourceReg = Inst.getOperand(1);
2522
2523 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
2524 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
2525
2526 assert(ShAmt > 0 && "Shift amount must be non-zero.");
2527
2528 emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)
2529 .addOperand(DestReg)
2530 .addOperand(SourceReg)
2531 .addImm(ShAmt));
2532
2533 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
2534 .addOperand(DestReg)
2535 .addOperand(DestReg)
2536 .addImm(ShAmt));
2537}
2538
2539void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
2540 MCStreamer &Out) {
2541 if (Inst.getNumOperands() == 3) {
2542 // unmasked va >= x
2543 //
2544 // pseudoinstruction: vmsge{u}.vx vd, va, x
2545 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
2546 emitToStreamer(Out, MCInstBuilder(Opcode)
2547 .addOperand(Inst.getOperand(0))
2548 .addOperand(Inst.getOperand(1))
2549 .addOperand(Inst.getOperand(2))
2550 .addReg(RISCV::NoRegister));
2551 emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)
2552 .addOperand(Inst.getOperand(0))
2553 .addOperand(Inst.getOperand(0))
2554 .addOperand(Inst.getOperand(0)));
2555 } else if (Inst.getNumOperands() == 4) {
2556 // masked va >= x, vd != v0
2557 //
2558 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
2559 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
2560 assert(Inst.getOperand(0).getReg() != RISCV::V0 &&
2561 "The destination register should not be V0.");
2562 emitToStreamer(Out, MCInstBuilder(Opcode)
2563 .addOperand(Inst.getOperand(0))
2564 .addOperand(Inst.getOperand(1))
2565 .addOperand(Inst.getOperand(2))
2566 .addOperand(Inst.getOperand(3)));
2567 emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)
2568 .addOperand(Inst.getOperand(0))
2569 .addOperand(Inst.getOperand(0))
2570 .addReg(RISCV::V0));
2571 } else if (Inst.getNumOperands() == 5 &&
2572 Inst.getOperand(0).getReg() == RISCV::V0) {
2573 // masked va >= x, vd == v0
2574 //
2575 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
2576 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
2577 assert(Inst.getOperand(0).getReg() == RISCV::V0 &&
2578 "The destination register should be V0.");
2579 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
2580 "The temporary vector register should not be V0.");
2581 emitToStreamer(Out, MCInstBuilder(Opcode)
2582 .addOperand(Inst.getOperand(1))
2583 .addOperand(Inst.getOperand(2))
2584 .addOperand(Inst.getOperand(3))
2585 .addOperand(Inst.getOperand(4)));
2586 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
2587 .addOperand(Inst.getOperand(0))
2588 .addOperand(Inst.getOperand(0))
2589 .addOperand(Inst.getOperand(1)));
2590 } else if (Inst.getNumOperands() == 5) {
2591 // masked va >= x, any vd
2592 //
2593 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
2594 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt; vmandn.mm vd,
2595 // vd, v0; vmor.mm vd, vt, vd
2596 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&
2597 "The temporary vector register should not be V0.");
2598 emitToStreamer(Out, MCInstBuilder(Opcode)
2599 .addOperand(Inst.getOperand(1))
2600 .addOperand(Inst.getOperand(2))
2601 .addOperand(Inst.getOperand(3))
2602 .addReg(RISCV::NoRegister));
2603 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
2604 .addOperand(Inst.getOperand(1))
2605 .addReg(RISCV::V0)
2606 .addOperand(Inst.getOperand(1)));
2607 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
2608 .addOperand(Inst.getOperand(0))
2609 .addOperand(Inst.getOperand(0))
2610 .addReg(RISCV::V0));
2611 emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)
2612 .addOperand(Inst.getOperand(0))
2613 .addOperand(Inst.getOperand(1))
2614 .addOperand(Inst.getOperand(0)));
2615 }
2616}
2617
2618bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
2620 assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction");
2621 assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind");
2622 if (Inst.getOperand(2).getReg() != RISCV::X4) {
2623 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
2624 return Error(ErrorLoc, "the second input operand must be tp/x4 when using "
2625 "%tprel_add modifier");
2626 }
2627
2628 return false;
2629}
2630
2631std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
2632 return RISCVOperand::createReg(RISCV::NoRegister, llvm::SMLoc(),
2633 llvm::SMLoc());
2634}
2635
2636std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
2637 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
2638 llvm::SMLoc());
2639}
2640
2641bool RISCVAsmParser::validateInstruction(MCInst &Inst,
2643 if (Inst.getOpcode() == RISCV::PseudoVMSGEU_VX_M_T ||
2644 Inst.getOpcode() == RISCV::PseudoVMSGE_VX_M_T) {
2645 unsigned DestReg = Inst.getOperand(0).getReg();
2646 unsigned TempReg = Inst.getOperand(1).getReg();
2647 if (DestReg == TempReg) {
2648 SMLoc Loc = Operands.back()->getStartLoc();
2649 return Error(Loc, "The temporary vector register cannot be the same as "
2650 "the destination register.");
2651 }
2652 }
2653
2654 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
2656 if (Constraints == RISCVII::NoConstraint)
2657 return false;
2658
2659 unsigned DestReg = Inst.getOperand(0).getReg();
2660 // Operands[1] will be the first operand, DestReg.
2661 SMLoc Loc = Operands[1]->getStartLoc();
2662 if (Constraints & RISCVII::VS2Constraint) {
2663 unsigned CheckReg = Inst.getOperand(1).getReg();
2664 if (DestReg == CheckReg)
2665 return Error(Loc, "The destination vector register group cannot overlap"
2666 " the source vector register group.");
2667 }
2668 if ((Constraints & RISCVII::VS1Constraint) && (Inst.getOperand(2).isReg())) {
2669 unsigned CheckReg = Inst.getOperand(2).getReg();
2670 if (DestReg == CheckReg)
2671 return Error(Loc, "The destination vector register group cannot overlap"
2672 " the source vector register group.");
2673 }
2674 if ((Constraints & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) {
2675 // vadc, vsbc are special cases. These instructions have no mask register.
2676 // The destination register could not be V0.
2677 unsigned Opcode = Inst.getOpcode();
2678 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
2679 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
2680 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
2681 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
2682 Opcode == RISCV::VMERGE_VXM)
2683 return Error(Loc, "The destination vector register group cannot be V0.");
2684
2685 // Regardless masked or unmasked version, the number of operands is the
2686 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
2687 // actually. We need to check the last operand to ensure whether it is
2688 // masked or not.
2689 unsigned CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
2690 assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) &&
2691 "Unexpected register for mask operand");
2692
2693 if (DestReg == CheckReg)
2694 return Error(Loc, "The destination vector register group cannot overlap"
2695 " the mask register.");
2696 }
2697 return false;
2698}
2699
2700bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
2702 MCStreamer &Out) {
2703 Inst.setLoc(IDLoc);
2704
2705 switch (Inst.getOpcode()) {
2706 default:
2707 break;
2708 case RISCV::PseudoLI: {
2709 MCRegister Reg = Inst.getOperand(0).getReg();
2710 const MCOperand &Op1 = Inst.getOperand(1);
2711 if (Op1.isExpr()) {
2712 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
2713 // Just convert to an addi. This allows compatibility with gas.
2714 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
2715 .addReg(Reg)
2716 .addReg(RISCV::X0)
2717 .addExpr(Op1.getExpr()));
2718 return false;
2719 }
2720 int64_t Imm = Inst.getOperand(1).getImm();
2721 // On RV32 the immediate here can either be a signed or an unsigned
2722 // 32-bit number. Sign extension has to be performed to ensure that Imm
2723 // represents the expected signed 64-bit number.
2724 if (!isRV64())
2725 Imm = SignExtend64<32>(Imm);
2726 emitLoadImm(Reg, Imm, Out);
2727 return false;
2728 }
2729 case RISCV::PseudoLLA:
2730 emitLoadLocalAddress(Inst, IDLoc, Out);
2731 return false;
2732 case RISCV::PseudoLA:
2733 emitLoadAddress(Inst, IDLoc, Out);
2734 return false;
2735 case RISCV::PseudoLA_TLS_IE:
2736 emitLoadTLSIEAddress(Inst, IDLoc, Out);
2737 return false;
2738 case RISCV::PseudoLA_TLS_GD:
2739 emitLoadTLSGDAddress(Inst, IDLoc, Out);
2740 return false;
2741 case RISCV::PseudoLB:
2742 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
2743 return false;
2744 case RISCV::PseudoLBU:
2745 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
2746 return false;
2747 case RISCV::PseudoLH:
2748 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
2749 return false;
2750 case RISCV::PseudoLHU:
2751 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
2752 return false;
2753 case RISCV::PseudoLW:
2754 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
2755 return false;
2756 case RISCV::PseudoLWU:
2757 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
2758 return false;
2759 case RISCV::PseudoLD:
2760 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
2761 return false;
2762 case RISCV::PseudoFLH:
2763 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
2764 return false;
2765 case RISCV::PseudoFLW:
2766 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
2767 return false;
2768 case RISCV::PseudoFLD:
2769 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
2770 return false;
2771 case RISCV::PseudoSB:
2772 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
2773 return false;
2774 case RISCV::PseudoSH:
2775 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
2776 return false;
2777 case RISCV::PseudoSW:
2778 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
2779 return false;
2780 case RISCV::PseudoSD:
2781 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
2782 return false;
2783 case RISCV::PseudoFSH:
2784 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
2785 return false;
2786 case RISCV::PseudoFSW:
2787 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
2788 return false;
2789 case RISCV::PseudoFSD:
2790 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
2791 return false;
2792 case RISCV::PseudoAddTPRel:
2793 if (checkPseudoAddTPRel(Inst, Operands))
2794 return true;
2795 break;
2796 case RISCV::PseudoSEXT_B:
2797 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
2798 return false;
2799 case RISCV::PseudoSEXT_H:
2800 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
2801 return false;
2802 case RISCV::PseudoZEXT_H:
2803 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
2804 return false;
2805 case RISCV::PseudoZEXT_W:
2806 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
2807 return false;
2808 case RISCV::PseudoVMSGEU_VX:
2809 case RISCV::PseudoVMSGEU_VX_M:
2810 case RISCV::PseudoVMSGEU_VX_M_T:
2811 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
2812 return false;
2813 case RISCV::PseudoVMSGE_VX:
2814 case RISCV::PseudoVMSGE_VX_M:
2815 case RISCV::PseudoVMSGE_VX_M_T:
2816 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
2817 return false;
2818 case RISCV::PseudoVMSGE_VI:
2819 case RISCV::PseudoVMSLT_VI: {
2820 // These instructions are signed and so is immediate so we can subtract one
2821 // and change the opcode.
2822 int64_t Imm = Inst.getOperand(2).getImm();
2823 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
2824 : RISCV::VMSLE_VI;
2825 emitToStreamer(Out, MCInstBuilder(Opc)
2826 .addOperand(Inst.getOperand(0))
2827 .addOperand(Inst.getOperand(1))
2828 .addImm(Imm - 1)
2829 .addOperand(Inst.getOperand(3)));
2830 return false;
2831 }
2832 case RISCV::PseudoVMSGEU_VI:
2833 case RISCV::PseudoVMSLTU_VI: {
2834 int64_t Imm = Inst.getOperand(2).getImm();
2835 // Unsigned comparisons are tricky because the immediate is signed. If the
2836 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
2837 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
2838 // vmsne v0, v1, v1 which is always false.
2839 if (Imm == 0) {
2840 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
2841 ? RISCV::VMSEQ_VV
2842 : RISCV::VMSNE_VV;
2843 emitToStreamer(Out, MCInstBuilder(Opc)
2844 .addOperand(Inst.getOperand(0))
2845 .addOperand(Inst.getOperand(1))
2846 .addOperand(Inst.getOperand(1))
2847 .addOperand(Inst.getOperand(3)));
2848 } else {
2849 // Other immediate values can subtract one like signed.
2850 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
2851 ? RISCV::VMSGTU_VI
2852 : RISCV::VMSLEU_VI;
2853 emitToStreamer(Out, MCInstBuilder(Opc)
2854 .addOperand(Inst.getOperand(0))
2855 .addOperand(Inst.getOperand(1))
2856 .addImm(Imm - 1)
2857 .addOperand(Inst.getOperand(3)));
2858 }
2859
2860 return false;
2861 }
2862 }
2863
2864 emitToStreamer(Out, Inst);
2865 return false;
2866}
2867
2871}
static const char * getSubtargetFeatureName(uint64_t Val)
static unsigned MatchRegisterName(StringRef Name)
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static unsigned 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
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:127
std::string Name
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)
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
PowerPC TLS Dynamic Call Fixup
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmParser()
static MCRegister convertFPR64ToFPR32(MCRegister Reg)
static MCRegister convertFPR64ToFPR16(MCRegister Reg)
static bool matchRegisterNameHelper(bool IsRV32E, MCRegister &RegNo, StringRef Name)
static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg, unsigned Kind)
bool MaskAgnostic
bool TailAgnostic
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.
This file implements the SmallBitVector class.
This file defines the SmallString 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
bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef< uint8_t > Bytes)
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
Base class for user error types.
Definition: Error.h:348
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
Container class for subtarget features.
constexpr size_t size() const
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.
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:183
@ Sub
Subtraction.
Definition: MCExpr.h:506
@ Add
Addition.
Definition: MCExpr.h:484
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
Context object for machine code objects.
Definition: MCContext.h:76
const MCObjectFileInfo * getObjectFileInfo() const
Definition: MCContext.h:450
MCSymbol * createNamedTempSymbol()
Create a temporary symbol with a unique name whose name cannot be omitted in the symbol table.
Definition: MCContext.cpp:320
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const
Try to evaluate the expression to a relocatable value, i.e.
Definition: MCExpr.cpp:749
ExprKind getKind() const
Definition: MCExpr.h:81
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:71
MCInstBuilder & addReg(unsigned Reg)
Add a new register operand.
Definition: MCInstBuilder.h:31
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:37
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
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:24
Streaming machine code generation interface.
Definition: MCStreamer.h:212
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:423
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:304
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:386
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
const MCExpr * getVariableValue(bool SetUsed=true) const
getVariableValue - Get the value for variable symbols.
Definition: MCSymbol.h:303
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition: MCSymbol.h:298
MCTargetAsmParser - Generic interface to target specific assembly parsers.
virtual bool ParseDirective(AsmToken DirectiveID)=0
ParseDirective - Parse 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
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 ...
virtual OperandMatchResultTy tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc)=0
tryParseRegister - parse one register if possible
Target specific streamer interface.
Definition: MCStreamer.h:93
This represents an "assembler immediate".
Definition: MCValue.h:36
uint32_t getRefKind() const
Definition: MCValue.h:46
static bool isSupportedExtensionFeature(StringRef Ext)
static llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseArchString(StringRef Arch, bool EnableExperimentalExtension, bool ExperimentalExtensionVersionCheck=true, bool IgnoreUnknown=false)
Parse RISCV 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:31
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
const char * getPointer() const
Definition: SMLoc.h:34
Represents a range in source code.
Definition: SMLoc.h:48
bool empty() const
Definition: SmallVector.h:94
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
This class wraps a string in an Error.
Definition: Error.h:1223
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
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:642
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const CustomOperand< const MCSubtargetInfo & > Msg[]
std::optional< unsigned > attrTypeFromString(StringRef tag, TagNameMap tagNameMap)
ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits, StringRef ABIName)
const TagNameMap & getRISCVAttributeTags()
static RoundingMode stringToRoundingMode(StringRef Str)
static VConstraintType getConstraint(uint64_t TSFlags)
InstSeq generateInstSeq(int64_t Val, const FeatureBitset &ActiveFeatures)
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)
@ CE
Windows NT (Windows on ARM)
Reg
All possible values of the reg field in the ModR/M byte.
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
@ Length
Definition: DWP.cpp:406
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:252
static bool isMem(const MachineInstr &MI, unsigned Op)
Definition: X86InstrInfo.h:131
@ MatchOperand_NoMatch
@ MatchOperand_ParseFail
@ MatchOperand_Success
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:966
Target & getTheRISCV32Target()
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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:190
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.