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