1 //===-- RISCVAsmParser.cpp - Parse RISC-V assembly to MCInst instructions -===//
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
7 //===----------------------------------------------------------------------===//
9 #include "MCTargetDesc/RISCVAsmBackend.h"
10 #include "MCTargetDesc/RISCVBaseInfo.h"
11 #include "MCTargetDesc/RISCVInstPrinter.h"
12 #include "MCTargetDesc/RISCVMCExpr.h"
13 #include "MCTargetDesc/RISCVMCTargetDesc.h"
14 #include "MCTargetDesc/RISCVMatInt.h"
15 #include "MCTargetDesc/RISCVTargetStreamer.h"
16 #include "TargetInfo/RISCVTargetInfo.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/SmallBitVector.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/Statistic.h"
21 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/MC/MCAssembler.h"
23 #include "llvm/MC/MCContext.h"
24 #include "llvm/MC/MCExpr.h"
25 #include "llvm/MC/MCInst.h"
26 #include "llvm/MC/MCInstBuilder.h"
27 #include "llvm/MC/MCInstrInfo.h"
28 #include "llvm/MC/MCObjectFileInfo.h"
29 #include "llvm/MC/MCParser/MCAsmLexer.h"
30 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
31 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
32 #include "llvm/MC/MCRegisterInfo.h"
33 #include "llvm/MC/MCStreamer.h"
34 #include "llvm/MC/MCSubtargetInfo.h"
35 #include "llvm/MC/MCValue.h"
36 #include "llvm/MC/TargetRegistry.h"
37 #include "llvm/Support/Casting.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/MathExtras.h"
40 #include "llvm/Support/RISCVAttributes.h"
41 #include "llvm/TargetParser/RISCVISAInfo.h"
48 #define DEBUG_TYPE "riscv-asm-parser"
50 STATISTIC(RISCVNumInstrsCompressed
,
51 "Number of RISC-V Compressed instructions emitted");
53 static cl::opt
<bool> AddBuildAttributes("riscv-add-build-attributes",
57 extern const SubtargetFeatureKV RISCVFeatureKV
[RISCV::NumSubtargetFeatures
];
63 struct ParserOptionsSet
{
67 class RISCVAsmParser
: public MCTargetAsmParser
{
68 // This tracks the parsing of the 4 operands that make up the vtype portion
69 // of vset(i)vli instructions which are separated by commas. The state names
70 // represent the next expected operand with Done meaning no other operands are
75 VTypeState_TailPolicy
,
76 VTypeState_MaskPolicy
,
80 SmallVector
<FeatureBitset
, 4> FeatureBitStack
;
82 SmallVector
<ParserOptionsSet
, 4> ParserOptionsStack
;
83 ParserOptionsSet ParserOptions
;
85 SMLoc
getLoc() const { return getParser().getTok().getLoc(); }
86 bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit
); }
87 bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureStdExtE
); }
88 bool enableExperimentalExtension() const {
89 return getSTI().hasFeature(RISCV::Experimental
);
92 RISCVTargetStreamer
&getTargetStreamer() {
93 assert(getParser().getStreamer().getTargetStreamer() &&
94 "do not have a target streamer");
95 MCTargetStreamer
&TS
= *getParser().getStreamer().getTargetStreamer();
96 return static_cast<RISCVTargetStreamer
&>(TS
);
99 unsigned validateTargetOperandClass(MCParsedAsmOperand
&Op
,
100 unsigned Kind
) override
;
102 bool generateImmOutOfRangeError(OperandVector
&Operands
, uint64_t ErrorInfo
,
103 int64_t Lower
, int64_t Upper
,
105 bool generateImmOutOfRangeError(SMLoc ErrorLoc
, int64_t Lower
, int64_t Upper
,
108 bool matchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
109 OperandVector
&Operands
, MCStreamer
&Out
,
111 bool MatchingInlineAsm
) override
;
113 MCRegister
matchRegisterNameHelper(StringRef Name
) const;
114 bool parseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
, SMLoc
&EndLoc
) override
;
115 ParseStatus
tryParseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
116 SMLoc
&EndLoc
) override
;
118 bool parseInstruction(ParseInstructionInfo
&Info
, StringRef Name
,
119 SMLoc NameLoc
, OperandVector
&Operands
) override
;
121 ParseStatus
parseDirective(AsmToken DirectiveID
) override
;
123 bool parseVTypeToken(const AsmToken
&Tok
, VTypeState
&State
, unsigned &Sew
,
124 unsigned &Lmul
, bool &Fractional
, bool &TailAgnostic
,
126 bool generateVTypeError(SMLoc ErrorLoc
);
128 // Helper to actually emit an instruction to the MCStreamer. Also, when
129 // possible, compression of the instruction is performed.
130 void emitToStreamer(MCStreamer
&S
, const MCInst
&Inst
);
132 // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
133 // synthesize the desired immedate value into the destination register.
134 void emitLoadImm(MCRegister DestReg
, int64_t Value
, MCStreamer
&Out
);
136 // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
137 // helpers such as emitLoadLocalAddress and emitLoadAddress.
138 void emitAuipcInstPair(MCOperand DestReg
, MCOperand TmpReg
,
139 const MCExpr
*Symbol
, RISCVMCExpr::VariantKind VKHi
,
140 unsigned SecondOpcode
, SMLoc IDLoc
, MCStreamer
&Out
);
142 // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
143 void emitLoadLocalAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
145 // Helper to emit pseudo instruction "lga" used in GOT-rel addressing.
146 void emitLoadGlobalAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
148 // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
149 void emitLoadAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
151 // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
153 void emitLoadTLSIEAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
155 // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
157 void emitLoadTLSGDAddress(MCInst
&Inst
, SMLoc IDLoc
, MCStreamer
&Out
);
159 // Helper to emit pseudo load/store instruction with a symbol.
160 void emitLoadStoreSymbol(MCInst
&Inst
, unsigned Opcode
, SMLoc IDLoc
,
161 MCStreamer
&Out
, bool HasTmpReg
);
163 // Helper to emit pseudo sign/zero extend instruction.
164 void emitPseudoExtend(MCInst
&Inst
, bool SignExtend
, int64_t Width
,
165 SMLoc IDLoc
, MCStreamer
&Out
);
167 // Helper to emit pseudo vmsge{u}.vx instruction.
168 void emitVMSGE(MCInst
&Inst
, unsigned Opcode
, SMLoc IDLoc
, MCStreamer
&Out
);
170 // Checks that a PseudoAddTPRel is using x4/tp in its second input operand.
171 // Enforcing this using a restricted register class for the second input
172 // operand of PseudoAddTPRel results in a poor diagnostic due to the fact
173 // 'add' is an overloaded mnemonic.
174 bool checkPseudoAddTPRel(MCInst
&Inst
, OperandVector
&Operands
);
176 // Checks that a PseudoTLSDESCCall is using x5/t0 in its output operand.
177 // Enforcing this using a restricted register class for the output
178 // operand of PseudoTLSDESCCall results in a poor diagnostic due to the fact
179 // 'jalr' is an overloaded mnemonic.
180 bool checkPseudoTLSDESCCall(MCInst
&Inst
, OperandVector
&Operands
);
182 // Check instruction constraints.
183 bool validateInstruction(MCInst
&Inst
, OperandVector
&Operands
);
185 /// Helper for processing MC instructions that have been successfully matched
186 /// by matchAndEmitInstruction. Modifications to the emitted instructions,
187 /// like the expansion of pseudo instructions (e.g., "li"), can be performed
189 bool processInstruction(MCInst
&Inst
, SMLoc IDLoc
, OperandVector
&Operands
,
192 // Auto-generated instruction matching functions
193 #define GET_ASSEMBLER_HEADER
194 #include "RISCVGenAsmMatcher.inc"
196 ParseStatus
parseCSRSystemRegister(OperandVector
&Operands
);
197 ParseStatus
parseFPImm(OperandVector
&Operands
);
198 ParseStatus
parseImmediate(OperandVector
&Operands
);
199 ParseStatus
parseRegister(OperandVector
&Operands
, bool AllowParens
= false);
200 ParseStatus
parseMemOpBaseReg(OperandVector
&Operands
);
201 ParseStatus
parseZeroOffsetMemOp(OperandVector
&Operands
);
202 ParseStatus
parseOperandWithModifier(OperandVector
&Operands
);
203 ParseStatus
parseBareSymbol(OperandVector
&Operands
);
204 ParseStatus
parseCallSymbol(OperandVector
&Operands
);
205 ParseStatus
parsePseudoJumpSymbol(OperandVector
&Operands
);
206 ParseStatus
parseJALOffset(OperandVector
&Operands
);
207 ParseStatus
parseVTypeI(OperandVector
&Operands
);
208 ParseStatus
parseMaskReg(OperandVector
&Operands
);
209 ParseStatus
parseInsnDirectiveOpcode(OperandVector
&Operands
);
210 ParseStatus
parseInsnCDirectiveOpcode(OperandVector
&Operands
);
211 ParseStatus
parseGPRAsFPR(OperandVector
&Operands
);
212 ParseStatus
parseGPRAsFPR64(OperandVector
&Operands
);
213 ParseStatus
parseGPRPairAsFPR64(OperandVector
&Operands
);
214 template <bool IsRV64Inst
> ParseStatus
parseGPRPair(OperandVector
&Operands
);
215 ParseStatus
parseGPRPair(OperandVector
&Operands
, bool IsRV64Inst
);
216 ParseStatus
parseFRMArg(OperandVector
&Operands
);
217 ParseStatus
parseFenceArg(OperandVector
&Operands
);
218 ParseStatus
parseReglist(OperandVector
&Operands
);
219 ParseStatus
parseRegReg(OperandVector
&Operands
);
220 ParseStatus
parseRetval(OperandVector
&Operands
);
221 ParseStatus
parseZcmpStackAdj(OperandVector
&Operands
,
222 bool ExpectNegative
= false);
223 ParseStatus
parseZcmpNegStackAdj(OperandVector
&Operands
) {
224 return parseZcmpStackAdj(Operands
, /*ExpectNegative*/ true);
227 bool parseOperand(OperandVector
&Operands
, StringRef Mnemonic
);
229 bool parseDirectiveOption();
230 bool parseDirectiveAttribute();
231 bool parseDirectiveInsn(SMLoc L
);
232 bool parseDirectiveVariantCC();
234 /// Helper to reset target features for a new arch string. It
235 /// also records the new arch string that is expanded by RISCVISAInfo
236 /// and reports error for invalid arch string.
237 bool resetToArch(StringRef Arch
, SMLoc Loc
, std::string
&Result
,
238 bool FromOptionDirective
);
240 void setFeatureBits(uint64_t Feature
, StringRef FeatureString
) {
241 if (!(getSTI().hasFeature(Feature
))) {
242 MCSubtargetInfo
&STI
= copySTI();
243 setAvailableFeatures(
244 ComputeAvailableFeatures(STI
.ToggleFeature(FeatureString
)));
248 void clearFeatureBits(uint64_t Feature
, StringRef FeatureString
) {
249 if (getSTI().hasFeature(Feature
)) {
250 MCSubtargetInfo
&STI
= copySTI();
251 setAvailableFeatures(
252 ComputeAvailableFeatures(STI
.ToggleFeature(FeatureString
)));
256 void pushFeatureBits() {
257 assert(FeatureBitStack
.size() == ParserOptionsStack
.size() &&
258 "These two stacks must be kept synchronized");
259 FeatureBitStack
.push_back(getSTI().getFeatureBits());
260 ParserOptionsStack
.push_back(ParserOptions
);
263 bool popFeatureBits() {
264 assert(FeatureBitStack
.size() == ParserOptionsStack
.size() &&
265 "These two stacks must be kept synchronized");
266 if (FeatureBitStack
.empty())
269 FeatureBitset FeatureBits
= FeatureBitStack
.pop_back_val();
270 copySTI().setFeatureBits(FeatureBits
);
271 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits
));
273 ParserOptions
= ParserOptionsStack
.pop_back_val();
278 std::unique_ptr
<RISCVOperand
> defaultMaskRegOp() const;
279 std::unique_ptr
<RISCVOperand
> defaultFRMArgOp() const;
280 std::unique_ptr
<RISCVOperand
> defaultFRMArgLegacyOp() const;
283 enum RISCVMatchResultTy
{
284 Match_Dummy
= FIRST_TARGET_MATCH_RESULT_TY
,
285 #define GET_OPERAND_DIAGNOSTIC_TYPES
286 #include "RISCVGenAsmMatcher.inc"
287 #undef GET_OPERAND_DIAGNOSTIC_TYPES
290 static bool classifySymbolRef(const MCExpr
*Expr
,
291 RISCVMCExpr::VariantKind
&Kind
);
292 static bool isSymbolDiff(const MCExpr
*Expr
);
294 RISCVAsmParser(const MCSubtargetInfo
&STI
, MCAsmParser
&Parser
,
295 const MCInstrInfo
&MII
, const MCTargetOptions
&Options
)
296 : MCTargetAsmParser(Options
, STI
, MII
) {
297 MCAsmParserExtension::Initialize(Parser
);
299 Parser
.addAliasForDirective(".half", ".2byte");
300 Parser
.addAliasForDirective(".hword", ".2byte");
301 Parser
.addAliasForDirective(".word", ".4byte");
302 Parser
.addAliasForDirective(".dword", ".8byte");
303 setAvailableFeatures(ComputeAvailableFeatures(STI
.getFeatureBits()));
305 auto ABIName
= StringRef(Options
.ABIName
);
306 if (ABIName
.ends_with("f") && !getSTI().hasFeature(RISCV::FeatureStdExtF
)) {
307 errs() << "Hard-float 'f' ABI can't be used for a target that "
308 "doesn't support the F instruction set extension (ignoring "
310 } else if (ABIName
.ends_with("d") &&
311 !getSTI().hasFeature(RISCV::FeatureStdExtD
)) {
312 errs() << "Hard-float 'd' ABI can't be used for a target that "
313 "doesn't support the D instruction set extension (ignoring "
317 // Use computeTargetABI to check if ABIName is valid. If invalid, output
319 RISCVABI::computeTargetABI(STI
.getTargetTriple(), STI
.getFeatureBits(),
322 const MCObjectFileInfo
*MOFI
= Parser
.getContext().getObjectFileInfo();
323 ParserOptions
.IsPicEnabled
= MOFI
->isPositionIndependent();
325 if (AddBuildAttributes
)
326 getTargetStreamer().emitTargetAttributes(STI
, /*EmitStackAlign*/ false);
330 /// RISCVOperand - Instances of this class represent a parsed machine
332 struct RISCVOperand final
: public MCParsedAsmOperand
{
366 // FIXME: Add the Encoding parsed fields as needed for checks,
367 // e.g.: read/write or user/supervisor/machine privileges.
375 RISCVFPRndMode::RoundingMode FRM
;
395 SMLoc StartLoc
, EndLoc
;
401 struct SysRegOp SysReg
;
402 struct VTypeOp VType
;
404 struct FenceOp Fence
;
405 struct RlistOp Rlist
;
406 struct SpimmOp Spimm
;
407 struct RegRegOp RegReg
;
410 RISCVOperand(KindTy K
) : Kind(K
) {}
413 RISCVOperand(const RISCVOperand
&o
) : MCParsedAsmOperand() {
415 StartLoc
= o
.StartLoc
;
418 case KindTy::Register
:
421 case KindTy::Immediate
:
424 case KindTy::FPImmediate
:
430 case KindTy::SystemRegister
:
454 bool isToken() const override
{ return Kind
== KindTy::Token
; }
455 bool isReg() const override
{ return Kind
== KindTy::Register
; }
456 bool isV0Reg() const {
457 return Kind
== KindTy::Register
&& Reg
.RegNum
== RISCV::V0
;
459 bool isAnyReg() const {
460 return Kind
== KindTy::Register
&&
461 (RISCVMCRegisterClasses
[RISCV::GPRRegClassID
].contains(Reg
.RegNum
) ||
462 RISCVMCRegisterClasses
[RISCV::FPR64RegClassID
].contains(Reg
.RegNum
) ||
463 RISCVMCRegisterClasses
[RISCV::VRRegClassID
].contains(Reg
.RegNum
));
465 bool isAnyRegC() const {
466 return Kind
== KindTy::Register
&&
467 (RISCVMCRegisterClasses
[RISCV::GPRCRegClassID
].contains(
469 RISCVMCRegisterClasses
[RISCV::FPR64CRegClassID
].contains(
472 bool isImm() const override
{ return Kind
== KindTy::Immediate
; }
473 bool isMem() const override
{ return false; }
474 bool isSystemRegister() const { return Kind
== KindTy::SystemRegister
; }
475 bool isRegReg() const { return Kind
== KindTy::RegReg
; }
476 bool isRlist() const { return Kind
== KindTy::Rlist
; }
477 bool isSpimm() const { return Kind
== KindTy::Spimm
; }
480 return Kind
== KindTy::Register
&&
481 RISCVMCRegisterClasses
[RISCV::GPRRegClassID
].contains(Reg
.RegNum
);
484 bool isGPRPair() const {
485 return Kind
== KindTy::Register
&&
486 RISCVMCRegisterClasses
[RISCV::GPRPairRegClassID
].contains(
490 bool isGPRF16() const {
491 return Kind
== KindTy::Register
&&
492 RISCVMCRegisterClasses
[RISCV::GPRF16RegClassID
].contains(Reg
.RegNum
);
495 bool isGPRF32() const {
496 return Kind
== KindTy::Register
&&
497 RISCVMCRegisterClasses
[RISCV::GPRF32RegClassID
].contains(Reg
.RegNum
);
500 bool isGPRAsFPR() const { return isGPR() && Reg
.IsGPRAsFPR
; }
501 bool isGPRAsFPR16() const { return isGPRF16() && Reg
.IsGPRAsFPR
; }
502 bool isGPRAsFPR32() const { return isGPRF32() && Reg
.IsGPRAsFPR
; }
503 bool isGPRPairAsFPR64() const { return isGPRPair() && Reg
.IsGPRAsFPR
; }
505 static bool evaluateConstantImm(const MCExpr
*Expr
, int64_t &Imm
,
506 RISCVMCExpr::VariantKind
&VK
) {
507 if (auto *RE
= dyn_cast
<RISCVMCExpr
>(Expr
)) {
509 return RE
->evaluateAsConstant(Imm
);
512 if (auto CE
= dyn_cast
<MCConstantExpr
>(Expr
)) {
513 VK
= RISCVMCExpr::VK_RISCV_None
;
514 Imm
= CE
->getValue();
521 // True if operand is a symbol with no modifiers, or a constant with no
522 // modifiers and isShiftedInt<N-1, 1>(Op).
523 template <int N
> bool isBareSimmNLsb0() const {
525 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
528 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
531 IsValid
= RISCVAsmParser::classifySymbolRef(getImm(), VK
);
533 IsValid
= isShiftedInt
<N
- 1, 1>(Imm
);
534 return IsValid
&& VK
== RISCVMCExpr::VK_RISCV_None
;
537 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
539 bool isBareSymbol() const {
541 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
542 // Must be of 'immediate' type but not a constant.
543 if (!isImm() || evaluateConstantImm(getImm(), Imm
, VK
))
545 return RISCVAsmParser::classifySymbolRef(getImm(), VK
) &&
546 VK
== RISCVMCExpr::VK_RISCV_None
;
549 bool isCallSymbol() const {
551 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
552 // Must be of 'immediate' type but not a constant.
553 if (!isImm() || evaluateConstantImm(getImm(), Imm
, VK
))
555 return RISCVAsmParser::classifySymbolRef(getImm(), VK
) &&
556 (VK
== RISCVMCExpr::VK_RISCV_CALL
||
557 VK
== RISCVMCExpr::VK_RISCV_CALL_PLT
);
560 bool isPseudoJumpSymbol() const {
562 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
563 // Must be of 'immediate' type but not a constant.
564 if (!isImm() || evaluateConstantImm(getImm(), Imm
, VK
))
566 return RISCVAsmParser::classifySymbolRef(getImm(), VK
) &&
567 VK
== RISCVMCExpr::VK_RISCV_CALL
;
570 bool isTPRelAddSymbol() const {
572 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
573 // Must be of 'immediate' type but not a constant.
574 if (!isImm() || evaluateConstantImm(getImm(), Imm
, VK
))
576 return RISCVAsmParser::classifySymbolRef(getImm(), VK
) &&
577 VK
== RISCVMCExpr::VK_RISCV_TPREL_ADD
;
580 bool isTLSDESCCallSymbol() const {
582 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
583 // Must be of 'immediate' type but not a constant.
584 if (!isImm() || evaluateConstantImm(getImm(), Imm
, VK
))
586 return RISCVAsmParser::classifySymbolRef(getImm(), VK
) &&
587 VK
== RISCVMCExpr::VK_RISCV_TLSDESC_CALL
;
590 bool isCSRSystemRegister() const { return isSystemRegister(); }
592 bool isVTypeImm(unsigned N
) const {
594 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
597 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
598 return IsConstantImm
&& isUIntN(N
, Imm
) && VK
== RISCVMCExpr::VK_RISCV_None
;
601 // If the last operand of the vsetvli/vsetvli instruction is a constant
602 // expression, KindTy is Immediate.
603 bool isVTypeI10() const {
604 if (Kind
== KindTy::Immediate
)
605 return isVTypeImm(10);
606 return Kind
== KindTy::VType
;
608 bool isVTypeI11() const {
609 if (Kind
== KindTy::Immediate
)
610 return isVTypeImm(11);
611 return Kind
== KindTy::VType
;
614 /// Return true if the operand is a valid for the fence instruction e.g.
616 bool isFenceArg() const { return Kind
== KindTy::Fence
; }
618 /// Return true if the operand is a valid floating point rounding mode.
619 bool isFRMArg() const { return Kind
== KindTy::FRM
; }
620 bool isFRMArgLegacy() const { return Kind
== KindTy::FRM
; }
621 bool isRTZArg() const { return isFRMArg() && FRM
.FRM
== RISCVFPRndMode::RTZ
; }
623 /// Return true if the operand is a valid fli.s floating-point immediate.
624 bool isLoadFPImm() const {
627 if (Kind
!= KindTy::FPImmediate
)
629 int Idx
= RISCVLoadFPImm::getLoadFPImm(
630 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
631 // Don't allow decimal version of the minimum value. It is a different value
632 // for each supported data type.
633 return Idx
>= 0 && Idx
!= 1;
636 bool isImmXLenLI() const {
638 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
641 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
642 if (VK
== RISCVMCExpr::VK_RISCV_LO
||
643 VK
== RISCVMCExpr::VK_RISCV_PCREL_LO
||
644 VK
== RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO
||
645 VK
== RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO
)
647 // Given only Imm, ensuring that the actually specified constant is either
648 // a signed or unsigned 64-bit number is unfortunately impossible.
650 return VK
== RISCVMCExpr::VK_RISCV_None
&&
651 (isRV64Imm() || (isInt
<32>(Imm
) || isUInt
<32>(Imm
)));
654 return RISCVAsmParser::isSymbolDiff(getImm());
657 bool isImmXLenLI_Restricted() const {
659 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
662 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
663 // 'la imm' supports constant immediates only.
664 return IsConstantImm
&& (VK
== RISCVMCExpr::VK_RISCV_None
) &&
665 (isRV64Imm() || (isInt
<32>(Imm
) || isUInt
<32>(Imm
)));
668 bool isUImmLog2XLen() const {
670 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
673 if (!evaluateConstantImm(getImm(), Imm
, VK
) ||
674 VK
!= RISCVMCExpr::VK_RISCV_None
)
676 return (isRV64Imm() && isUInt
<6>(Imm
)) || isUInt
<5>(Imm
);
679 bool isUImmLog2XLenNonZero() const {
681 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
684 if (!evaluateConstantImm(getImm(), Imm
, VK
) ||
685 VK
!= RISCVMCExpr::VK_RISCV_None
)
689 return (isRV64Imm() && isUInt
<6>(Imm
)) || isUInt
<5>(Imm
);
692 bool isUImmLog2XLenHalf() const {
694 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
697 if (!evaluateConstantImm(getImm(), Imm
, VK
) ||
698 VK
!= RISCVMCExpr::VK_RISCV_None
)
700 return (isRV64Imm() && isUInt
<5>(Imm
)) || isUInt
<4>(Imm
);
703 template <unsigned N
> bool IsUImm() const {
705 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
708 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
709 return IsConstantImm
&& isUInt
<N
>(Imm
) && VK
== RISCVMCExpr::VK_RISCV_None
;
712 bool isUImm1() const { return IsUImm
<1>(); }
713 bool isUImm2() const { return IsUImm
<2>(); }
714 bool isUImm3() const { return IsUImm
<3>(); }
715 bool isUImm4() const { return IsUImm
<4>(); }
716 bool isUImm5() const { return IsUImm
<5>(); }
717 bool isUImm6() const { return IsUImm
<6>(); }
718 bool isUImm7() const { return IsUImm
<7>(); }
719 bool isUImm8() const { return IsUImm
<8>(); }
720 bool isUImm11() const { return IsUImm
<11>(); }
721 bool isUImm16() const { return IsUImm
<16>(); }
722 bool isUImm20() const { return IsUImm
<20>(); }
723 bool isUImm32() const { return IsUImm
<32>(); }
724 bool isUImm48() const { return IsUImm
<48>(); }
725 bool isUImm64() const { return IsUImm
<64>(); }
727 bool isUImm8GE32() const {
729 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
732 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
733 return IsConstantImm
&& isUInt
<8>(Imm
) && Imm
>= 32 &&
734 VK
== RISCVMCExpr::VK_RISCV_None
;
737 bool isRnumArg() const {
739 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
742 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
743 return IsConstantImm
&& Imm
>= INT64_C(0) && Imm
<= INT64_C(10) &&
744 VK
== RISCVMCExpr::VK_RISCV_None
;
747 bool isRnumArg_0_7() const {
749 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
752 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
753 return IsConstantImm
&& Imm
>= INT64_C(0) && Imm
<= INT64_C(7) &&
754 VK
== RISCVMCExpr::VK_RISCV_None
;
757 bool isRnumArg_1_10() const {
759 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
762 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
763 return IsConstantImm
&& Imm
>= INT64_C(1) && Imm
<= INT64_C(10) &&
764 VK
== RISCVMCExpr::VK_RISCV_None
;
767 bool isRnumArg_2_14() const {
769 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
772 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
773 return IsConstantImm
&& Imm
>= INT64_C(2) && Imm
<= INT64_C(14) &&
774 VK
== RISCVMCExpr::VK_RISCV_None
;
777 bool isSImm5() const {
780 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
782 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
783 return IsConstantImm
&& isInt
<5>(fixImmediateForRV32(Imm
, isRV64Imm())) &&
784 VK
== RISCVMCExpr::VK_RISCV_None
;
787 bool isSImm6() const {
790 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
792 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
793 return IsConstantImm
&& isInt
<6>(fixImmediateForRV32(Imm
, isRV64Imm())) &&
794 VK
== RISCVMCExpr::VK_RISCV_None
;
797 bool isSImm6NonZero() const {
800 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
802 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
803 return IsConstantImm
&& Imm
!= 0 &&
804 isInt
<6>(fixImmediateForRV32(Imm
, isRV64Imm())) &&
805 VK
== RISCVMCExpr::VK_RISCV_None
;
808 bool isCLUIImm() const {
812 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
813 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
814 return IsConstantImm
&& (Imm
!= 0) &&
815 (isUInt
<5>(Imm
) || (Imm
>= 0xfffe0 && Imm
<= 0xfffff)) &&
816 VK
== RISCVMCExpr::VK_RISCV_None
;
819 bool isUImm2Lsb0() const {
823 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
824 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
825 return IsConstantImm
&& isShiftedUInt
<1, 1>(Imm
) &&
826 VK
== RISCVMCExpr::VK_RISCV_None
;
829 bool isUImm5Lsb0() const {
833 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
834 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
835 return IsConstantImm
&& isShiftedUInt
<4, 1>(Imm
) &&
836 VK
== RISCVMCExpr::VK_RISCV_None
;
839 bool isUImm6Lsb0() const {
843 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
844 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
845 return IsConstantImm
&& isShiftedUInt
<5, 1>(Imm
) &&
846 VK
== RISCVMCExpr::VK_RISCV_None
;
849 bool isUImm7Lsb00() const {
853 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
854 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
855 return IsConstantImm
&& isShiftedUInt
<5, 2>(Imm
) &&
856 VK
== RISCVMCExpr::VK_RISCV_None
;
859 bool isUImm8Lsb00() const {
863 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
864 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
865 return IsConstantImm
&& isShiftedUInt
<6, 2>(Imm
) &&
866 VK
== RISCVMCExpr::VK_RISCV_None
;
869 bool isUImm8Lsb000() const {
873 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
874 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
875 return IsConstantImm
&& isShiftedUInt
<5, 3>(Imm
) &&
876 VK
== RISCVMCExpr::VK_RISCV_None
;
879 bool isSImm9Lsb0() const { return isBareSimmNLsb0
<9>(); }
881 bool isUImm9Lsb000() const {
885 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
886 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
887 return IsConstantImm
&& isShiftedUInt
<6, 3>(Imm
) &&
888 VK
== RISCVMCExpr::VK_RISCV_None
;
891 bool isUImm10Lsb00NonZero() const {
895 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
896 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
897 return IsConstantImm
&& isShiftedUInt
<8, 2>(Imm
) && (Imm
!= 0) &&
898 VK
== RISCVMCExpr::VK_RISCV_None
;
901 // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.
902 // This allows writing 'addi a0, a0, 0xffffffff'.
903 static int64_t fixImmediateForRV32(int64_t Imm
, bool IsRV64Imm
) {
904 if (IsRV64Imm
|| !isUInt
<32>(Imm
))
906 return SignExtend64
<32>(Imm
);
909 bool isSImm12() const {
910 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
915 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
917 IsValid
= RISCVAsmParser::classifySymbolRef(getImm(), VK
);
919 IsValid
= isInt
<12>(fixImmediateForRV32(Imm
, isRV64Imm()));
920 return IsValid
&& ((IsConstantImm
&& VK
== RISCVMCExpr::VK_RISCV_None
) ||
921 VK
== RISCVMCExpr::VK_RISCV_LO
||
922 VK
== RISCVMCExpr::VK_RISCV_PCREL_LO
||
923 VK
== RISCVMCExpr::VK_RISCV_TPREL_LO
||
924 VK
== RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO
||
925 VK
== RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO
);
928 bool isSImm12Lsb0() const { return isBareSimmNLsb0
<12>(); }
930 bool isSImm12Lsb00000() const {
933 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
935 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
936 return IsConstantImm
&& isShiftedInt
<7, 5>(Imm
) &&
937 VK
== RISCVMCExpr::VK_RISCV_None
;
940 bool isSImm13Lsb0() const { return isBareSimmNLsb0
<13>(); }
942 bool isSImm10Lsb0000NonZero() const {
946 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
947 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
948 return IsConstantImm
&& (Imm
!= 0) && isShiftedInt
<6, 4>(Imm
) &&
949 VK
== RISCVMCExpr::VK_RISCV_None
;
952 bool isUImm20LUI() const {
953 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
958 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
959 if (!IsConstantImm
) {
960 IsValid
= RISCVAsmParser::classifySymbolRef(getImm(), VK
);
961 return IsValid
&& (VK
== RISCVMCExpr::VK_RISCV_HI
||
962 VK
== RISCVMCExpr::VK_RISCV_TPREL_HI
);
964 return isUInt
<20>(Imm
) && (VK
== RISCVMCExpr::VK_RISCV_None
||
965 VK
== RISCVMCExpr::VK_RISCV_HI
||
966 VK
== RISCVMCExpr::VK_RISCV_TPREL_HI
);
970 bool isUImm20AUIPC() const {
971 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
976 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
977 if (!IsConstantImm
) {
978 IsValid
= RISCVAsmParser::classifySymbolRef(getImm(), VK
);
979 return IsValid
&& (VK
== RISCVMCExpr::VK_RISCV_PCREL_HI
||
980 VK
== RISCVMCExpr::VK_RISCV_GOT_HI
||
981 VK
== RISCVMCExpr::VK_RISCV_TLS_GOT_HI
||
982 VK
== RISCVMCExpr::VK_RISCV_TLS_GD_HI
||
983 VK
== RISCVMCExpr::VK_RISCV_TLSDESC_HI
);
986 return isUInt
<20>(Imm
) && (VK
== RISCVMCExpr::VK_RISCV_None
||
987 VK
== RISCVMCExpr::VK_RISCV_PCREL_HI
||
988 VK
== RISCVMCExpr::VK_RISCV_GOT_HI
||
989 VK
== RISCVMCExpr::VK_RISCV_TLS_GOT_HI
||
990 VK
== RISCVMCExpr::VK_RISCV_TLS_GD_HI
||
991 VK
== RISCVMCExpr::VK_RISCV_TLSDESC_HI
);
994 bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0
<21>(); }
996 bool isImmZero() const {
1000 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
1001 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
1002 return IsConstantImm
&& (Imm
== 0) && VK
== RISCVMCExpr::VK_RISCV_None
;
1005 bool isSImm5Plus1() const {
1008 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
1010 bool IsConstantImm
= evaluateConstantImm(getImm(), Imm
, VK
);
1011 return IsConstantImm
&&
1012 isInt
<5>(fixImmediateForRV32(Imm
, isRV64Imm()) - 1) &&
1013 VK
== RISCVMCExpr::VK_RISCV_None
;
1016 /// getStartLoc - Gets location of the first token of this operand
1017 SMLoc
getStartLoc() const override
{ return StartLoc
; }
1018 /// getEndLoc - Gets location of the last token of this operand
1019 SMLoc
getEndLoc() const override
{ return EndLoc
; }
1020 /// True if this operand is for an RV64 instruction
1021 bool isRV64Imm() const {
1022 assert(Kind
== KindTy::Immediate
&& "Invalid type access!");
1026 MCRegister
getReg() const override
{
1027 assert(Kind
== KindTy::Register
&& "Invalid type access!");
1031 StringRef
getSysReg() const {
1032 assert(Kind
== KindTy::SystemRegister
&& "Invalid type access!");
1033 return StringRef(SysReg
.Data
, SysReg
.Length
);
1036 const MCExpr
*getImm() const {
1037 assert(Kind
== KindTy::Immediate
&& "Invalid type access!");
1041 uint64_t getFPConst() const {
1042 assert(Kind
== KindTy::FPImmediate
&& "Invalid type access!");
1046 StringRef
getToken() const {
1047 assert(Kind
== KindTy::Token
&& "Invalid type access!");
1051 unsigned getVType() const {
1052 assert(Kind
== KindTy::VType
&& "Invalid type access!");
1056 RISCVFPRndMode::RoundingMode
getFRM() const {
1057 assert(Kind
== KindTy::FRM
&& "Invalid type access!");
1061 unsigned getFence() const {
1062 assert(Kind
== KindTy::Fence
&& "Invalid type access!");
1066 void print(raw_ostream
&OS
) const override
{
1067 auto RegName
= [](MCRegister Reg
) {
1069 return RISCVInstPrinter::getRegisterName(Reg
);
1075 case KindTy::Immediate
:
1078 case KindTy::FPImmediate
:
1080 case KindTy::Register
:
1081 OS
<< "<register " << RegName(getReg()) << ">";
1084 OS
<< "'" << getToken() << "'";
1086 case KindTy::SystemRegister
:
1087 OS
<< "<sysreg: " << getSysReg() << '>';
1091 RISCVVType::printVType(getVType(), OS
);
1096 roundingModeToString(getFRM());
1106 RISCVZC::printRlist(Rlist
.Val
, OS
);
1114 case KindTy::RegReg
:
1115 OS
<< "<RegReg: Reg1 " << RegName(RegReg
.Reg1
);
1116 OS
<< " Reg2 " << RegName(RegReg
.Reg2
);
1121 static std::unique_ptr
<RISCVOperand
> createToken(StringRef Str
, SMLoc S
) {
1122 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Token
);
1129 static std::unique_ptr
<RISCVOperand
>
1130 createReg(MCRegister Reg
, SMLoc S
, SMLoc E
, bool IsGPRAsFPR
= false) {
1131 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Register
);
1132 Op
->Reg
.RegNum
= Reg
.id();
1133 Op
->Reg
.IsGPRAsFPR
= IsGPRAsFPR
;
1139 static std::unique_ptr
<RISCVOperand
> createImm(const MCExpr
*Val
, SMLoc S
,
1140 SMLoc E
, bool IsRV64
) {
1141 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Immediate
);
1143 Op
->Imm
.IsRV64
= IsRV64
;
1149 static std::unique_ptr
<RISCVOperand
> createFPImm(uint64_t Val
, SMLoc S
) {
1150 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::FPImmediate
);
1151 Op
->FPImm
.Val
= Val
;
1157 static std::unique_ptr
<RISCVOperand
> createSysReg(StringRef Str
, SMLoc S
,
1158 unsigned Encoding
) {
1159 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::SystemRegister
);
1160 Op
->SysReg
.Data
= Str
.data();
1161 Op
->SysReg
.Length
= Str
.size();
1162 Op
->SysReg
.Encoding
= Encoding
;
1168 static std::unique_ptr
<RISCVOperand
>
1169 createFRMArg(RISCVFPRndMode::RoundingMode FRM
, SMLoc S
) {
1170 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::FRM
);
1177 static std::unique_ptr
<RISCVOperand
> createFenceArg(unsigned Val
, SMLoc S
) {
1178 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Fence
);
1179 Op
->Fence
.Val
= Val
;
1185 static std::unique_ptr
<RISCVOperand
> createVType(unsigned VTypeI
, SMLoc S
) {
1186 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::VType
);
1187 Op
->VType
.Val
= VTypeI
;
1193 static std::unique_ptr
<RISCVOperand
> createRlist(unsigned RlistEncode
,
1195 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Rlist
);
1196 Op
->Rlist
.Val
= RlistEncode
;
1201 static std::unique_ptr
<RISCVOperand
> createRegReg(MCRegister Reg1
,
1202 MCRegister Reg2
, SMLoc S
) {
1203 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::RegReg
);
1204 Op
->RegReg
.Reg1
= Reg1
.id();
1205 Op
->RegReg
.Reg2
= Reg2
.id();
1211 static std::unique_ptr
<RISCVOperand
> createSpimm(unsigned Spimm
, SMLoc S
) {
1212 auto Op
= std::make_unique
<RISCVOperand
>(KindTy::Spimm
);
1213 Op
->Spimm
.Val
= Spimm
;
1218 static void addExpr(MCInst
&Inst
, const MCExpr
*Expr
, bool IsRV64Imm
) {
1219 assert(Expr
&& "Expr shouldn't be null!");
1221 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
1222 bool IsConstant
= evaluateConstantImm(Expr
, Imm
, VK
);
1226 MCOperand::createImm(fixImmediateForRV32(Imm
, IsRV64Imm
)));
1228 Inst
.addOperand(MCOperand::createExpr(Expr
));
1231 // Used by the TableGen Code
1232 void addRegOperands(MCInst
&Inst
, unsigned N
) const {
1233 assert(N
== 1 && "Invalid number of operands!");
1234 Inst
.addOperand(MCOperand::createReg(getReg()));
1237 void addImmOperands(MCInst
&Inst
, unsigned N
) const {
1238 assert(N
== 1 && "Invalid number of operands!");
1239 addExpr(Inst
, getImm(), isRV64Imm());
1242 void addFPImmOperands(MCInst
&Inst
, unsigned N
) const {
1243 assert(N
== 1 && "Invalid number of operands!");
1245 addExpr(Inst
, getImm(), isRV64Imm());
1249 int Imm
= RISCVLoadFPImm::getLoadFPImm(
1250 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
1251 Inst
.addOperand(MCOperand::createImm(Imm
));
1254 void addFenceArgOperands(MCInst
&Inst
, unsigned N
) const {
1255 assert(N
== 1 && "Invalid number of operands!");
1256 Inst
.addOperand(MCOperand::createImm(Fence
.Val
));
1259 void addCSRSystemRegisterOperands(MCInst
&Inst
, unsigned N
) const {
1260 assert(N
== 1 && "Invalid number of operands!");
1261 Inst
.addOperand(MCOperand::createImm(SysReg
.Encoding
));
1264 // Support non-canonical syntax:
1265 // "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"
1266 // "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"
1267 void addVTypeIOperands(MCInst
&Inst
, unsigned N
) const {
1268 assert(N
== 1 && "Invalid number of operands!");
1270 if (Kind
== KindTy::Immediate
) {
1271 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::VK_RISCV_None
;
1272 [[maybe_unused
]] bool IsConstantImm
=
1273 evaluateConstantImm(getImm(), Imm
, VK
);
1274 assert(IsConstantImm
&& "Invalid VTypeI Operand!");
1278 Inst
.addOperand(MCOperand::createImm(Imm
));
1281 void addRlistOperands(MCInst
&Inst
, unsigned N
) const {
1282 assert(N
== 1 && "Invalid number of operands!");
1283 Inst
.addOperand(MCOperand::createImm(Rlist
.Val
));
1286 void addRegRegOperands(MCInst
&Inst
, unsigned N
) const {
1287 assert(N
== 2 && "Invalid number of operands!");
1288 Inst
.addOperand(MCOperand::createReg(RegReg
.Reg1
));
1289 Inst
.addOperand(MCOperand::createReg(RegReg
.Reg2
));
1292 void addSpimmOperands(MCInst
&Inst
, unsigned N
) const {
1293 assert(N
== 1 && "Invalid number of operands!");
1294 Inst
.addOperand(MCOperand::createImm(Spimm
.Val
));
1297 void addFRMArgOperands(MCInst
&Inst
, unsigned N
) const {
1298 assert(N
== 1 && "Invalid number of operands!");
1299 Inst
.addOperand(MCOperand::createImm(getFRM()));
1302 } // end anonymous namespace.
1304 #define GET_REGISTER_MATCHER
1305 #define GET_SUBTARGET_FEATURE_NAME
1306 #define GET_MATCHER_IMPLEMENTATION
1307 #define GET_MNEMONIC_SPELL_CHECKER
1308 #include "RISCVGenAsmMatcher.inc"
1310 static MCRegister
convertFPR64ToFPR16(MCRegister Reg
) {
1311 assert(Reg
>= RISCV::F0_D
&& Reg
<= RISCV::F31_D
&& "Invalid register");
1312 return Reg
- RISCV::F0_D
+ RISCV::F0_H
;
1315 static MCRegister
convertFPR64ToFPR32(MCRegister Reg
) {
1316 assert(Reg
>= RISCV::F0_D
&& Reg
<= RISCV::F31_D
&& "Invalid register");
1317 return Reg
- RISCV::F0_D
+ RISCV::F0_F
;
1320 static MCRegister
convertVRToVRMx(const MCRegisterInfo
&RI
, MCRegister Reg
,
1322 unsigned RegClassID
;
1323 if (Kind
== MCK_VRM2
)
1324 RegClassID
= RISCV::VRM2RegClassID
;
1325 else if (Kind
== MCK_VRM4
)
1326 RegClassID
= RISCV::VRM4RegClassID
;
1327 else if (Kind
== MCK_VRM8
)
1328 RegClassID
= RISCV::VRM8RegClassID
;
1330 return MCRegister();
1331 return RI
.getMatchingSuperReg(Reg
, RISCV::sub_vrm1_0
,
1332 &RISCVMCRegisterClasses
[RegClassID
]);
1335 unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand
&AsmOp
,
1337 RISCVOperand
&Op
= static_cast<RISCVOperand
&>(AsmOp
);
1339 return Match_InvalidOperand
;
1341 MCRegister Reg
= Op
.getReg();
1343 RISCVMCRegisterClasses
[RISCV::FPR64RegClassID
].contains(Reg
);
1345 RISCVMCRegisterClasses
[RISCV::FPR64CRegClassID
].contains(Reg
);
1346 bool IsRegVR
= RISCVMCRegisterClasses
[RISCV::VRRegClassID
].contains(Reg
);
1348 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1349 // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
1350 if ((IsRegFPR64
&& Kind
== MCK_FPR32
) ||
1351 (IsRegFPR64C
&& Kind
== MCK_FPR32C
)) {
1352 Op
.Reg
.RegNum
= convertFPR64ToFPR32(Reg
);
1353 return Match_Success
;
1355 // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
1356 // register from FPR64 to FPR16 if necessary.
1357 if (IsRegFPR64
&& Kind
== MCK_FPR16
) {
1358 Op
.Reg
.RegNum
= convertFPR64ToFPR16(Reg
);
1359 return Match_Success
;
1361 if (Kind
== MCK_GPRAsFPR16
&& Op
.isGPRAsFPR()) {
1362 Op
.Reg
.RegNum
= Reg
- RISCV::X0
+ RISCV::X0_H
;
1363 return Match_Success
;
1365 if (Kind
== MCK_GPRAsFPR32
&& Op
.isGPRAsFPR()) {
1366 Op
.Reg
.RegNum
= Reg
- RISCV::X0
+ RISCV::X0_W
;
1367 return Match_Success
;
1370 // There are some GPRF64AsFPR instructions that have no RV32 equivalent. We
1371 // reject them at parsing thinking we should match as GPRPairAsFPR for RV32.
1372 // So we explicitly accept them here for RV32 to allow the generic code to
1373 // report that the instruction requires RV64.
1374 if (RISCVMCRegisterClasses
[RISCV::GPRRegClassID
].contains(Reg
) &&
1375 Kind
== MCK_GPRF64AsFPR
&& STI
->hasFeature(RISCV::FeatureStdExtZdinx
) &&
1377 return Match_Success
;
1379 // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
1380 // the register from VR to VRM2/VRM4/VRM8 if necessary.
1381 if (IsRegVR
&& (Kind
== MCK_VRM2
|| Kind
== MCK_VRM4
|| Kind
== MCK_VRM8
)) {
1382 Op
.Reg
.RegNum
= convertVRToVRMx(*getContext().getRegisterInfo(), Reg
, Kind
);
1384 return Match_InvalidOperand
;
1385 return Match_Success
;
1387 return Match_InvalidOperand
;
1390 bool RISCVAsmParser::generateImmOutOfRangeError(
1391 SMLoc ErrorLoc
, int64_t Lower
, int64_t Upper
,
1392 const Twine
&Msg
= "immediate must be an integer in the range") {
1393 return Error(ErrorLoc
, Msg
+ " [" + Twine(Lower
) + ", " + Twine(Upper
) + "]");
1396 bool RISCVAsmParser::generateImmOutOfRangeError(
1397 OperandVector
&Operands
, uint64_t ErrorInfo
, int64_t Lower
, int64_t Upper
,
1398 const Twine
&Msg
= "immediate must be an integer in the range") {
1399 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1400 return generateImmOutOfRangeError(ErrorLoc
, Lower
, Upper
, Msg
);
1403 bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc
, unsigned &Opcode
,
1404 OperandVector
&Operands
,
1406 uint64_t &ErrorInfo
,
1407 bool MatchingInlineAsm
) {
1409 FeatureBitset MissingFeatures
;
1411 auto Result
= MatchInstructionImpl(Operands
, Inst
, ErrorInfo
, MissingFeatures
,
1417 if (validateInstruction(Inst
, Operands
))
1419 return processInstruction(Inst
, IDLoc
, Operands
, Out
);
1420 case Match_MissingFeature
: {
1421 assert(MissingFeatures
.any() && "Unknown missing features!");
1422 bool FirstFeature
= true;
1423 std::string Msg
= "instruction requires the following:";
1424 for (unsigned i
= 0, e
= MissingFeatures
.size(); i
!= e
; ++i
) {
1425 if (MissingFeatures
[i
]) {
1426 Msg
+= FirstFeature
? " " : ", ";
1427 Msg
+= getSubtargetFeatureName(i
);
1428 FirstFeature
= false;
1431 return Error(IDLoc
, Msg
);
1433 case Match_MnemonicFail
: {
1434 FeatureBitset FBS
= ComputeAvailableFeatures(getSTI().getFeatureBits());
1435 std::string Suggestion
= RISCVMnemonicSpellCheck(
1436 ((RISCVOperand
&)*Operands
[0]).getToken(), FBS
, 0);
1437 return Error(IDLoc
, "unrecognized instruction mnemonic" + Suggestion
);
1439 case Match_InvalidOperand
: {
1440 SMLoc ErrorLoc
= IDLoc
;
1441 if (ErrorInfo
!= ~0ULL) {
1442 if (ErrorInfo
>= Operands
.size())
1443 return Error(ErrorLoc
, "too few operands for instruction");
1445 ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1446 if (ErrorLoc
== SMLoc())
1449 return Error(ErrorLoc
, "invalid operand for instruction");
1453 // Handle the case when the error message is of specific type
1454 // other than the generic Match_InvalidOperand, and the
1455 // corresponding operand is missing.
1456 if (Result
> FIRST_TARGET_MATCH_RESULT_TY
) {
1457 SMLoc ErrorLoc
= IDLoc
;
1458 if (ErrorInfo
!= ~0ULL && ErrorInfo
>= Operands
.size())
1459 return Error(ErrorLoc
, "too few operands for instruction");
1465 case Match_InvalidImmXLenLI
:
1467 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1468 return Error(ErrorLoc
, "operand must be a constant 64-bit integer");
1470 return generateImmOutOfRangeError(Operands
, ErrorInfo
,
1471 std::numeric_limits
<int32_t>::min(),
1472 std::numeric_limits
<uint32_t>::max());
1473 case Match_InvalidImmXLenLI_Restricted
:
1475 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1476 return Error(ErrorLoc
, "operand either must be a constant 64-bit integer "
1477 "or a bare symbol name");
1479 return generateImmOutOfRangeError(
1480 Operands
, ErrorInfo
, std::numeric_limits
<int32_t>::min(),
1481 std::numeric_limits
<uint32_t>::max(),
1482 "operand either must be a bare symbol name or an immediate integer in "
1484 case Match_InvalidImmZero
: {
1485 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1486 return Error(ErrorLoc
, "immediate must be zero");
1488 case Match_InvalidUImmLog2XLen
:
1490 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 6) - 1);
1491 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 5) - 1);
1492 case Match_InvalidUImmLog2XLenNonZero
:
1494 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 1, (1 << 6) - 1);
1495 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 1, (1 << 5) - 1);
1496 case Match_InvalidUImm1
:
1497 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 1) - 1);
1498 case Match_InvalidUImm2
:
1499 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 2) - 1);
1500 case Match_InvalidUImm2Lsb0
:
1501 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, 2,
1502 "immediate must be one of");
1503 case Match_InvalidUImm3
:
1504 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 3) - 1);
1505 case Match_InvalidUImm4
:
1506 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 4) - 1);
1507 case Match_InvalidUImm5
:
1508 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 5) - 1);
1509 case Match_InvalidUImm6
:
1510 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 6) - 1);
1511 case Match_InvalidUImm7
:
1512 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 7) - 1);
1513 case Match_InvalidUImm8
:
1514 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 8) - 1);
1515 case Match_InvalidUImm8GE32
:
1516 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 32, (1 << 8) - 1);
1517 case Match_InvalidSImm5
:
1518 return generateImmOutOfRangeError(Operands
, ErrorInfo
, -(1 << 4),
1520 case Match_InvalidSImm6
:
1521 return generateImmOutOfRangeError(Operands
, ErrorInfo
, -(1 << 5),
1523 case Match_InvalidSImm6NonZero
:
1524 return generateImmOutOfRangeError(
1525 Operands
, ErrorInfo
, -(1 << 5), (1 << 5) - 1,
1526 "immediate must be non-zero in the range");
1527 case Match_InvalidCLUIImm
:
1528 return generateImmOutOfRangeError(
1529 Operands
, ErrorInfo
, 1, (1 << 5) - 1,
1530 "immediate must be in [0xfffe0, 0xfffff] or");
1531 case Match_InvalidUImm5Lsb0
:
1532 return generateImmOutOfRangeError(
1533 Operands
, ErrorInfo
, 0, (1 << 5) - 2,
1534 "immediate must be a multiple of 2 bytes in the range");
1535 case Match_InvalidUImm6Lsb0
:
1536 return generateImmOutOfRangeError(
1537 Operands
, ErrorInfo
, 0, (1 << 6) - 2,
1538 "immediate must be a multiple of 2 bytes in the range");
1539 case Match_InvalidUImm7Lsb00
:
1540 return generateImmOutOfRangeError(
1541 Operands
, ErrorInfo
, 0, (1 << 7) - 4,
1542 "immediate must be a multiple of 4 bytes in the range");
1543 case Match_InvalidUImm8Lsb00
:
1544 return generateImmOutOfRangeError(
1545 Operands
, ErrorInfo
, 0, (1 << 8) - 4,
1546 "immediate must be a multiple of 4 bytes in the range");
1547 case Match_InvalidUImm8Lsb000
:
1548 return generateImmOutOfRangeError(
1549 Operands
, ErrorInfo
, 0, (1 << 8) - 8,
1550 "immediate must be a multiple of 8 bytes in the range");
1551 case Match_InvalidSImm9Lsb0
:
1552 return generateImmOutOfRangeError(
1553 Operands
, ErrorInfo
, -(1 << 8), (1 << 8) - 2,
1554 "immediate must be a multiple of 2 bytes in the range");
1555 case Match_InvalidUImm9Lsb000
:
1556 return generateImmOutOfRangeError(
1557 Operands
, ErrorInfo
, 0, (1 << 9) - 8,
1558 "immediate must be a multiple of 8 bytes in the range");
1559 case Match_InvalidUImm10Lsb00NonZero
:
1560 return generateImmOutOfRangeError(
1561 Operands
, ErrorInfo
, 4, (1 << 10) - 4,
1562 "immediate must be a multiple of 4 bytes in the range");
1563 case Match_InvalidSImm10Lsb0000NonZero
:
1564 return generateImmOutOfRangeError(
1565 Operands
, ErrorInfo
, -(1 << 9), (1 << 9) - 16,
1566 "immediate must be a multiple of 16 bytes and non-zero in the range");
1567 case Match_InvalidUImm11
:
1568 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 11) - 1);
1569 case Match_InvalidSImm12
:
1570 return generateImmOutOfRangeError(
1571 Operands
, ErrorInfo
, -(1 << 11), (1 << 11) - 1,
1572 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1573 "integer in the range");
1574 case Match_InvalidSImm12Lsb0
:
1575 return generateImmOutOfRangeError(
1576 Operands
, ErrorInfo
, -(1 << 11), (1 << 11) - 2,
1577 "immediate must be a multiple of 2 bytes in the range");
1578 case Match_InvalidSImm12Lsb00000
:
1579 return generateImmOutOfRangeError(
1580 Operands
, ErrorInfo
, -(1 << 11), (1 << 11) - 32,
1581 "immediate must be a multiple of 32 bytes in the range");
1582 case Match_InvalidSImm13Lsb0
:
1583 return generateImmOutOfRangeError(
1584 Operands
, ErrorInfo
, -(1 << 12), (1 << 12) - 2,
1585 "immediate must be a multiple of 2 bytes in the range");
1586 case Match_InvalidUImm20LUI
:
1587 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 20) - 1,
1588 "operand must be a symbol with "
1589 "%hi/%tprel_hi modifier or an integer in "
1591 case Match_InvalidUImm20
:
1592 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 20) - 1);
1593 case Match_InvalidUImm20AUIPC
:
1594 return generateImmOutOfRangeError(
1595 Operands
, ErrorInfo
, 0, (1 << 20) - 1,
1596 "operand must be a symbol with a "
1597 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1598 "an integer in the range");
1599 case Match_InvalidSImm21Lsb0JAL
:
1600 return generateImmOutOfRangeError(
1601 Operands
, ErrorInfo
, -(1 << 20), (1 << 20) - 2,
1602 "immediate must be a multiple of 2 bytes in the range");
1603 case Match_InvalidCSRSystemRegister
: {
1604 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, (1 << 12) - 1,
1605 "operand must be a valid system register "
1606 "name or an integer in the range");
1608 case Match_InvalidLoadFPImm
: {
1609 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1610 return Error(ErrorLoc
, "operand must be a valid floating-point constant");
1612 case Match_InvalidBareSymbol
: {
1613 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1614 return Error(ErrorLoc
, "operand must be a bare symbol name");
1616 case Match_InvalidPseudoJumpSymbol
: {
1617 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1618 return Error(ErrorLoc
, "operand must be a valid jump target");
1620 case Match_InvalidCallSymbol
: {
1621 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1622 return Error(ErrorLoc
, "operand must be a bare symbol name");
1624 case Match_InvalidTPRelAddSymbol
: {
1625 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1626 return Error(ErrorLoc
, "operand must be a symbol with %tprel_add modifier");
1628 case Match_InvalidTLSDESCCallSymbol
: {
1629 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1630 return Error(ErrorLoc
,
1631 "operand must be a symbol with %tlsdesc_call modifier");
1633 case Match_InvalidRTZArg
: {
1634 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1635 return Error(ErrorLoc
, "operand must be 'rtz' floating-point rounding mode");
1637 case Match_InvalidVTypeI
: {
1638 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1639 return generateVTypeError(ErrorLoc
);
1641 case Match_InvalidVMaskRegister
: {
1642 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1643 return Error(ErrorLoc
, "operand must be v0.t");
1645 case Match_InvalidSImm5Plus1
: {
1646 return generateImmOutOfRangeError(Operands
, ErrorInfo
, -(1 << 4) + 1,
1648 "immediate must be in the range");
1650 case Match_InvalidRlist
: {
1651 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1654 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1656 case Match_InvalidStackAdj
: {
1657 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1660 "stack adjustment is invalid for this instruction and register list; "
1661 "refer to Zc spec for a detailed range of stack adjustment");
1663 case Match_InvalidRnumArg
: {
1664 return generateImmOutOfRangeError(Operands
, ErrorInfo
, 0, 10);
1666 case Match_InvalidRegReg
: {
1667 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[ErrorInfo
]).getStartLoc();
1668 return Error(ErrorLoc
, "operands must be register and register");
1672 llvm_unreachable("Unknown match type detected!");
1675 // Attempts to match Name as a register (either using the default name or
1676 // alternative ABI names), returning the matching register. Upon failure,
1677 // returns a non-valid MCRegister. If IsRVE, then registers x16-x31 will be
1679 MCRegister
RISCVAsmParser::matchRegisterNameHelper(StringRef Name
) const {
1680 MCRegister Reg
= MatchRegisterName(Name
);
1681 // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
1682 // match always matches the 64-bit variant, and not the 16/32-bit one.
1683 assert(!(Reg
>= RISCV::F0_H
&& Reg
<= RISCV::F31_H
));
1684 assert(!(Reg
>= RISCV::F0_F
&& Reg
<= RISCV::F31_F
));
1685 // The default FPR register class is based on the tablegen enum ordering.
1686 static_assert(RISCV::F0_D
< RISCV::F0_H
, "FPR matching must be updated");
1687 static_assert(RISCV::F0_D
< RISCV::F0_F
, "FPR matching must be updated");
1689 Reg
= MatchRegisterAltName(Name
);
1690 if (isRVE() && Reg
>= RISCV::X16
&& Reg
<= RISCV::X31
)
1695 bool RISCVAsmParser::parseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
1697 if (!tryParseRegister(Reg
, StartLoc
, EndLoc
).isSuccess())
1698 return Error(StartLoc
, "invalid register name");
1702 ParseStatus
RISCVAsmParser::tryParseRegister(MCRegister
&Reg
, SMLoc
&StartLoc
,
1704 const AsmToken
&Tok
= getParser().getTok();
1705 StartLoc
= Tok
.getLoc();
1706 EndLoc
= Tok
.getEndLoc();
1707 StringRef Name
= getLexer().getTok().getIdentifier();
1709 Reg
= matchRegisterNameHelper(Name
);
1711 return ParseStatus::NoMatch
;
1713 getParser().Lex(); // Eat identifier token.
1714 return ParseStatus::Success
;
1717 ParseStatus
RISCVAsmParser::parseRegister(OperandVector
&Operands
,
1719 SMLoc FirstS
= getLoc();
1720 bool HadParens
= false;
1723 // If this is an LParen and a parenthesised register name is allowed, parse it
1725 if (AllowParens
&& getLexer().is(AsmToken::LParen
)) {
1727 size_t ReadCount
= getLexer().peekTokens(Buf
);
1728 if (ReadCount
== 2 && Buf
[1].getKind() == AsmToken::RParen
) {
1730 LParen
= getParser().getTok();
1731 getParser().Lex(); // Eat '('
1735 switch (getLexer().getKind()) {
1738 getLexer().UnLex(LParen
);
1739 return ParseStatus::NoMatch
;
1740 case AsmToken::Identifier
:
1741 StringRef Name
= getLexer().getTok().getIdentifier();
1742 MCRegister Reg
= matchRegisterNameHelper(Name
);
1746 getLexer().UnLex(LParen
);
1747 return ParseStatus::NoMatch
;
1750 Operands
.push_back(RISCVOperand::createToken("(", FirstS
));
1752 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Name
.size());
1754 Operands
.push_back(RISCVOperand::createReg(Reg
, S
, E
));
1758 getParser().Lex(); // Eat ')'
1759 Operands
.push_back(RISCVOperand::createToken(")", getLoc()));
1762 return ParseStatus::Success
;
1765 ParseStatus
RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector
&Operands
) {
1770 switch (getLexer().getKind()) {
1772 return ParseStatus::NoMatch
;
1773 case AsmToken::LParen
:
1774 case AsmToken::Minus
:
1775 case AsmToken::Plus
:
1776 case AsmToken::Exclaim
:
1777 case AsmToken::Tilde
:
1778 case AsmToken::Integer
:
1779 case AsmToken::String
: {
1780 if (getParser().parseExpression(Res
, E
))
1781 return ParseStatus::Failure
;
1783 auto *CE
= dyn_cast
<MCConstantExpr
>(Res
);
1785 int64_t Imm
= CE
->getValue();
1786 if (isUInt
<7>(Imm
)) {
1787 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
1788 return ParseStatus::Success
;
1794 case AsmToken::Identifier
: {
1795 StringRef Identifier
;
1796 if (getParser().parseIdentifier(Identifier
))
1797 return ParseStatus::Failure
;
1799 auto Opcode
= RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier
);
1801 assert(isUInt
<7>(Opcode
->Value
) && (Opcode
->Value
& 0x3) == 3 &&
1802 "Unexpected opcode");
1803 Res
= MCConstantExpr::create(Opcode
->Value
, getContext());
1804 E
= SMLoc::getFromPointer(S
.getPointer() + Identifier
.size());
1805 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
1806 return ParseStatus::Success
;
1811 case AsmToken::Percent
:
1815 return generateImmOutOfRangeError(
1817 "opcode must be a valid opcode name or an immediate in the range");
1820 ParseStatus
RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector
&Operands
) {
1825 switch (getLexer().getKind()) {
1827 return ParseStatus::NoMatch
;
1828 case AsmToken::LParen
:
1829 case AsmToken::Minus
:
1830 case AsmToken::Plus
:
1831 case AsmToken::Exclaim
:
1832 case AsmToken::Tilde
:
1833 case AsmToken::Integer
:
1834 case AsmToken::String
: {
1835 if (getParser().parseExpression(Res
, E
))
1836 return ParseStatus::Failure
;
1838 auto *CE
= dyn_cast
<MCConstantExpr
>(Res
);
1840 int64_t Imm
= CE
->getValue();
1841 if (Imm
>= 0 && Imm
<= 2) {
1842 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
1843 return ParseStatus::Success
;
1849 case AsmToken::Identifier
: {
1850 StringRef Identifier
;
1851 if (getParser().parseIdentifier(Identifier
))
1852 return ParseStatus::Failure
;
1855 if (Identifier
== "C0")
1857 else if (Identifier
== "C1")
1859 else if (Identifier
== "C2")
1864 Res
= MCConstantExpr::create(Opcode
, getContext());
1865 E
= SMLoc::getFromPointer(S
.getPointer() + Identifier
.size());
1866 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
1867 return ParseStatus::Success
;
1869 case AsmToken::Percent
: {
1870 // Discard operand with modifier.
1875 return generateImmOutOfRangeError(
1877 "opcode must be a valid opcode name or an immediate in the range");
1880 ParseStatus
RISCVAsmParser::parseCSRSystemRegister(OperandVector
&Operands
) {
1884 auto SysRegFromConstantInt
= [this](const MCExpr
*E
, SMLoc S
) {
1885 if (auto *CE
= dyn_cast
<MCConstantExpr
>(E
)) {
1886 int64_t Imm
= CE
->getValue();
1887 if (isUInt
<12>(Imm
)) {
1888 auto Range
= RISCVSysReg::lookupSysRegByEncoding(Imm
);
1889 // Accept an immediate representing a named Sys Reg if it satisfies the
1890 // the required features.
1891 for (auto &Reg
: Range
) {
1892 if (Reg
.haveRequiredFeatures(STI
->getFeatureBits()))
1893 return RISCVOperand::createSysReg(Reg
.Name
, S
, Imm
);
1895 // Accept an immediate representing an un-named Sys Reg if the range is
1896 // valid, regardless of the required features.
1897 return RISCVOperand::createSysReg("", S
, Imm
);
1900 return std::unique_ptr
<RISCVOperand
>();
1903 switch (getLexer().getKind()) {
1905 return ParseStatus::NoMatch
;
1906 case AsmToken::LParen
:
1907 case AsmToken::Minus
:
1908 case AsmToken::Plus
:
1909 case AsmToken::Exclaim
:
1910 case AsmToken::Tilde
:
1911 case AsmToken::Integer
:
1912 case AsmToken::String
: {
1913 if (getParser().parseExpression(Res
))
1914 return ParseStatus::Failure
;
1916 if (auto SysOpnd
= SysRegFromConstantInt(Res
, S
)) {
1917 Operands
.push_back(std::move(SysOpnd
));
1918 return ParseStatus::Success
;
1921 return generateImmOutOfRangeError(S
, 0, (1 << 12) - 1);
1923 case AsmToken::Identifier
: {
1924 StringRef Identifier
;
1925 if (getParser().parseIdentifier(Identifier
))
1926 return ParseStatus::Failure
;
1928 const auto *SysReg
= RISCVSysReg::lookupSysRegByName(Identifier
);
1930 SysReg
= RISCVSysReg::lookupSysRegByAltName(Identifier
);
1932 if ((SysReg
= RISCVSysReg::lookupSysRegByDeprecatedName(Identifier
)))
1933 Warning(S
, "'" + Identifier
+ "' is a deprecated alias for '" +
1934 SysReg
->Name
+ "'");
1936 // Accept a named Sys Reg if the required features are present.
1938 const auto &FeatureBits
= getSTI().getFeatureBits();
1939 if (!SysReg
->haveRequiredFeatures(FeatureBits
)) {
1940 const auto *Feature
= llvm::find_if(RISCVFeatureKV
, [&](auto Feature
) {
1941 return SysReg
->FeaturesRequired
[Feature
.Value
];
1943 auto ErrorMsg
= std::string("system register '") + SysReg
->Name
+ "' ";
1944 if (SysReg
->isRV32Only
&& FeatureBits
[RISCV::Feature64Bit
]) {
1945 ErrorMsg
+= "is RV32 only";
1946 if (Feature
!= std::end(RISCVFeatureKV
))
1947 ErrorMsg
+= " and ";
1949 if (Feature
!= std::end(RISCVFeatureKV
)) {
1951 "requires '" + std::string(Feature
->Key
) + "' to be enabled";
1954 return Error(S
, ErrorMsg
);
1957 RISCVOperand::createSysReg(Identifier
, S
, SysReg
->Encoding
));
1958 return ParseStatus::Success
;
1961 // Accept a symbol name that evaluates to an absolute value.
1962 MCSymbol
*Sym
= getContext().lookupSymbol(Identifier
);
1963 if (Sym
&& Sym
->isVariable()) {
1964 // Pass false for SetUsed, since redefining the value later does not
1965 // affect this instruction.
1966 if (auto SysOpnd
= SysRegFromConstantInt(
1967 Sym
->getVariableValue(/*SetUsed=*/false), S
)) {
1968 Operands
.push_back(std::move(SysOpnd
));
1969 return ParseStatus::Success
;
1973 return generateImmOutOfRangeError(S
, 0, (1 << 12) - 1,
1974 "operand must be a valid system register "
1975 "name or an integer in the range");
1977 case AsmToken::Percent
: {
1978 // Discard operand with modifier.
1979 return generateImmOutOfRangeError(S
, 0, (1 << 12) - 1);
1983 return ParseStatus::NoMatch
;
1986 ParseStatus
RISCVAsmParser::parseFPImm(OperandVector
&Operands
) {
1989 // Parse special floats (inf/nan/min) representation.
1990 if (getTok().is(AsmToken::Identifier
)) {
1991 StringRef Identifier
= getTok().getIdentifier();
1992 if (Identifier
.compare_insensitive("inf") == 0) {
1994 RISCVOperand::createImm(MCConstantExpr::create(30, getContext()), S
,
1995 getTok().getEndLoc(), isRV64()));
1996 } else if (Identifier
.compare_insensitive("nan") == 0) {
1998 RISCVOperand::createImm(MCConstantExpr::create(31, getContext()), S
,
1999 getTok().getEndLoc(), isRV64()));
2000 } else if (Identifier
.compare_insensitive("min") == 0) {
2002 RISCVOperand::createImm(MCConstantExpr::create(1, getContext()), S
,
2003 getTok().getEndLoc(), isRV64()));
2005 return TokError("invalid floating point literal");
2008 Lex(); // Eat the token.
2010 return ParseStatus::Success
;
2013 // Handle negation, as that still comes through as a separate token.
2014 bool IsNegative
= parseOptionalToken(AsmToken::Minus
);
2016 const AsmToken
&Tok
= getTok();
2017 if (!Tok
.is(AsmToken::Real
))
2018 return TokError("invalid floating point immediate");
2020 // Parse FP representation.
2021 APFloat
RealVal(APFloat::IEEEdouble());
2023 RealVal
.convertFromString(Tok
.getString(), APFloat::rmTowardZero
);
2024 if (errorToBool(StatusOrErr
.takeError()))
2025 return TokError("invalid floating point representation");
2028 RealVal
.changeSign();
2030 Operands
.push_back(RISCVOperand::createFPImm(
2031 RealVal
.bitcastToAPInt().getZExtValue(), S
));
2033 Lex(); // Eat the token.
2035 return ParseStatus::Success
;
2038 ParseStatus
RISCVAsmParser::parseImmediate(OperandVector
&Operands
) {
2043 switch (getLexer().getKind()) {
2045 return ParseStatus::NoMatch
;
2046 case AsmToken::LParen
:
2048 case AsmToken::Minus
:
2049 case AsmToken::Plus
:
2050 case AsmToken::Exclaim
:
2051 case AsmToken::Tilde
:
2052 case AsmToken::Integer
:
2053 case AsmToken::String
:
2054 case AsmToken::Identifier
:
2055 if (getParser().parseExpression(Res
, E
))
2056 return ParseStatus::Failure
;
2058 case AsmToken::Percent
:
2059 return parseOperandWithModifier(Operands
);
2062 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
2063 return ParseStatus::Success
;
2066 ParseStatus
RISCVAsmParser::parseOperandWithModifier(OperandVector
&Operands
) {
2070 if (parseToken(AsmToken::Percent
, "expected '%' for operand modifier"))
2071 return ParseStatus::Failure
;
2073 if (getLexer().getKind() != AsmToken::Identifier
)
2074 return Error(getLoc(), "expected valid identifier for operand modifier");
2075 StringRef Identifier
= getParser().getTok().getIdentifier();
2076 RISCVMCExpr::VariantKind VK
= RISCVMCExpr::getVariantKindForName(Identifier
);
2077 if (VK
== RISCVMCExpr::VK_RISCV_Invalid
)
2078 return Error(getLoc(), "unrecognized operand modifier");
2080 getParser().Lex(); // Eat the identifier
2081 if (parseToken(AsmToken::LParen
, "expected '('"))
2082 return ParseStatus::Failure
;
2084 const MCExpr
*SubExpr
;
2085 if (getParser().parseParenExpression(SubExpr
, E
))
2086 return ParseStatus::Failure
;
2088 const MCExpr
*ModExpr
= RISCVMCExpr::create(SubExpr
, VK
, getContext());
2089 Operands
.push_back(RISCVOperand::createImm(ModExpr
, S
, E
, isRV64()));
2090 return ParseStatus::Success
;
2093 ParseStatus
RISCVAsmParser::parseBareSymbol(OperandVector
&Operands
) {
2097 if (getLexer().getKind() != AsmToken::Identifier
)
2098 return ParseStatus::NoMatch
;
2100 StringRef Identifier
;
2101 AsmToken Tok
= getLexer().getTok();
2103 if (getParser().parseIdentifier(Identifier
))
2104 return ParseStatus::Failure
;
2106 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Identifier
.size());
2108 if (Identifier
.consume_back("@plt"))
2109 return Error(getLoc(), "'@plt' operand not valid for instruction");
2111 MCSymbol
*Sym
= getContext().getOrCreateSymbol(Identifier
);
2113 if (Sym
->isVariable()) {
2114 const MCExpr
*V
= Sym
->getVariableValue(/*SetUsed=*/false);
2115 if (!isa
<MCSymbolRefExpr
>(V
)) {
2116 getLexer().UnLex(Tok
); // Put back if it's not a bare symbol.
2117 return ParseStatus::NoMatch
;
2121 Res
= MCSymbolRefExpr::create(Sym
, MCSymbolRefExpr::VK_None
, getContext());
2123 MCBinaryExpr::Opcode Opcode
;
2124 switch (getLexer().getKind()) {
2126 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
2127 return ParseStatus::Success
;
2128 case AsmToken::Plus
:
2129 Opcode
= MCBinaryExpr::Add
;
2132 case AsmToken::Minus
:
2133 Opcode
= MCBinaryExpr::Sub
;
2139 if (getParser().parseExpression(Expr
, E
))
2140 return ParseStatus::Failure
;
2141 Res
= MCBinaryExpr::create(Opcode
, Res
, Expr
, getContext());
2142 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
2143 return ParseStatus::Success
;
2146 ParseStatus
RISCVAsmParser::parseCallSymbol(OperandVector
&Operands
) {
2150 if (getLexer().getKind() != AsmToken::Identifier
)
2151 return ParseStatus::NoMatch
;
2153 // Avoid parsing the register in `call rd, foo` as a call symbol.
2154 if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement
)
2155 return ParseStatus::NoMatch
;
2157 StringRef Identifier
;
2158 if (getParser().parseIdentifier(Identifier
))
2159 return ParseStatus::Failure
;
2161 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Identifier
.size());
2163 RISCVMCExpr::VariantKind Kind
= RISCVMCExpr::VK_RISCV_CALL_PLT
;
2164 (void)Identifier
.consume_back("@plt");
2166 MCSymbol
*Sym
= getContext().getOrCreateSymbol(Identifier
);
2167 Res
= MCSymbolRefExpr::create(Sym
, MCSymbolRefExpr::VK_None
, getContext());
2168 Res
= RISCVMCExpr::create(Res
, Kind
, getContext());
2169 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
2170 return ParseStatus::Success
;
2173 ParseStatus
RISCVAsmParser::parsePseudoJumpSymbol(OperandVector
&Operands
) {
2178 if (getParser().parseExpression(Res
, E
))
2179 return ParseStatus::Failure
;
2181 if (Res
->getKind() != MCExpr::ExprKind::SymbolRef
||
2182 cast
<MCSymbolRefExpr
>(Res
)->getKind() ==
2183 MCSymbolRefExpr::VariantKind::VK_PLT
)
2184 return Error(S
, "operand must be a valid jump target");
2186 Res
= RISCVMCExpr::create(Res
, RISCVMCExpr::VK_RISCV_CALL
, getContext());
2187 Operands
.push_back(RISCVOperand::createImm(Res
, S
, E
, isRV64()));
2188 return ParseStatus::Success
;
2191 ParseStatus
RISCVAsmParser::parseJALOffset(OperandVector
&Operands
) {
2192 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
2193 // both being acceptable forms. When parsing `jal ra, foo` this function
2194 // will be called for the `ra` register operand in an attempt to match the
2195 // single-operand alias. parseJALOffset must fail for this case. It would
2196 // seem logical to try parse the operand using parseImmediate and return
2197 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
2198 // the second form rather than the first). We can't do this as there's no
2199 // way of rewinding the lexer state. Instead, return NoMatch if this operand
2200 // is an identifier and is followed by a comma.
2201 if (getLexer().is(AsmToken::Identifier
) &&
2202 getLexer().peekTok().is(AsmToken::Comma
))
2203 return ParseStatus::NoMatch
;
2205 return parseImmediate(Operands
);
2208 bool RISCVAsmParser::parseVTypeToken(const AsmToken
&Tok
, VTypeState
&State
,
2209 unsigned &Sew
, unsigned &Lmul
,
2210 bool &Fractional
, bool &TailAgnostic
,
2211 bool &MaskAgnostic
) {
2212 if (Tok
.isNot(AsmToken::Identifier
))
2215 StringRef Identifier
= Tok
.getIdentifier();
2218 case VTypeState_SEW
:
2219 if (!Identifier
.consume_front("e"))
2221 if (Identifier
.getAsInteger(10, Sew
))
2223 if (!RISCVVType::isValidSEW(Sew
))
2225 State
= VTypeState_LMUL
;
2227 case VTypeState_LMUL
: {
2228 if (!Identifier
.consume_front("m"))
2230 Fractional
= Identifier
.consume_front("f");
2231 if (Identifier
.getAsInteger(10, Lmul
))
2233 if (!RISCVVType::isValidLMUL(Lmul
, Fractional
))
2237 unsigned ELEN
= STI
->hasFeature(RISCV::FeatureStdExtZve64x
) ? 64 : 32;
2238 unsigned MinLMUL
= ELEN
/ 8;
2240 Warning(Tok
.getLoc(),
2241 "use of vtype encodings with LMUL < SEWMIN/ELEN == mf" +
2242 Twine(MinLMUL
) + " is reserved");
2245 State
= VTypeState_TailPolicy
;
2248 case VTypeState_TailPolicy
:
2249 if (Identifier
== "ta")
2250 TailAgnostic
= true;
2251 else if (Identifier
== "tu")
2252 TailAgnostic
= false;
2255 State
= VTypeState_MaskPolicy
;
2257 case VTypeState_MaskPolicy
:
2258 if (Identifier
== "ma")
2259 MaskAgnostic
= true;
2260 else if (Identifier
== "mu")
2261 MaskAgnostic
= false;
2264 State
= VTypeState_Done
;
2266 case VTypeState_Done
:
2274 ParseStatus
RISCVAsmParser::parseVTypeI(OperandVector
&Operands
) {
2279 bool Fractional
= false;
2280 bool TailAgnostic
= false;
2281 bool MaskAgnostic
= false;
2283 VTypeState State
= VTypeState_SEW
;
2286 if (parseVTypeToken(getTok(), State
, Sew
, Lmul
, Fractional
, TailAgnostic
,
2288 return ParseStatus::NoMatch
;
2292 while (parseOptionalToken(AsmToken::Comma
)) {
2293 if (parseVTypeToken(getTok(), State
, Sew
, Lmul
, Fractional
, TailAgnostic
,
2300 if (getLexer().is(AsmToken::EndOfStatement
) && State
== VTypeState_Done
) {
2301 RISCVII::VLMUL VLMUL
= RISCVVType::encodeLMUL(Lmul
, Fractional
);
2303 unsigned ELEN
= STI
->hasFeature(RISCV::FeatureStdExtZve64x
) ? 64 : 32;
2304 unsigned MaxSEW
= ELEN
/ Lmul
;
2305 // If MaxSEW < 8, we should have printed warning about reserved LMUL.
2306 if (MaxSEW
>= 8 && Sew
> MaxSEW
)
2308 "use of vtype encodings with SEW > " + Twine(MaxSEW
) +
2309 " and LMUL == mf" + Twine(Lmul
) +
2310 " may not be compatible with all RVV implementations");
2314 RISCVVType::encodeVTYPE(VLMUL
, Sew
, TailAgnostic
, MaskAgnostic
);
2315 Operands
.push_back(RISCVOperand::createVType(VTypeI
, S
));
2316 return ParseStatus::Success
;
2319 return generateVTypeError(S
);
2322 bool RISCVAsmParser::generateVTypeError(SMLoc ErrorLoc
) {
2326 "e[8|16|32|64],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
2329 ParseStatus
RISCVAsmParser::parseMaskReg(OperandVector
&Operands
) {
2330 if (getLexer().isNot(AsmToken::Identifier
))
2331 return ParseStatus::NoMatch
;
2333 StringRef Name
= getLexer().getTok().getIdentifier();
2334 if (!Name
.consume_back(".t"))
2335 return Error(getLoc(), "expected '.t' suffix");
2336 MCRegister Reg
= matchRegisterNameHelper(Name
);
2339 return ParseStatus::NoMatch
;
2340 if (Reg
!= RISCV::V0
)
2341 return ParseStatus::NoMatch
;
2343 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Name
.size());
2345 Operands
.push_back(RISCVOperand::createReg(Reg
, S
, E
));
2346 return ParseStatus::Success
;
2349 ParseStatus
RISCVAsmParser::parseGPRAsFPR64(OperandVector
&Operands
) {
2350 if (!isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF
))
2351 return ParseStatus::NoMatch
;
2353 return parseGPRAsFPR(Operands
);
2356 ParseStatus
RISCVAsmParser::parseGPRAsFPR(OperandVector
&Operands
) {
2357 if (getLexer().isNot(AsmToken::Identifier
))
2358 return ParseStatus::NoMatch
;
2360 StringRef Name
= getLexer().getTok().getIdentifier();
2361 MCRegister Reg
= matchRegisterNameHelper(Name
);
2364 return ParseStatus::NoMatch
;
2366 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Name
.size());
2368 Operands
.push_back(RISCVOperand::createReg(
2369 Reg
, S
, E
, !getSTI().hasFeature(RISCV::FeatureStdExtF
)));
2370 return ParseStatus::Success
;
2373 ParseStatus
RISCVAsmParser::parseGPRPairAsFPR64(OperandVector
&Operands
) {
2374 if (isRV64() || getSTI().hasFeature(RISCV::FeatureStdExtF
))
2375 return ParseStatus::NoMatch
;
2377 if (getLexer().isNot(AsmToken::Identifier
))
2378 return ParseStatus::NoMatch
;
2380 StringRef Name
= getLexer().getTok().getIdentifier();
2381 MCRegister Reg
= matchRegisterNameHelper(Name
);
2384 return ParseStatus::NoMatch
;
2386 if (!RISCVMCRegisterClasses
[RISCV::GPRRegClassID
].contains(Reg
))
2387 return ParseStatus::NoMatch
;
2389 if ((Reg
- RISCV::X0
) & 1) {
2390 // Only report the even register error if we have at least Zfinx so we know
2391 // some FP is enabled. We already checked F earlier.
2392 if (getSTI().hasFeature(RISCV::FeatureStdExtZfinx
))
2393 return TokError("double precision floating point operands must use even "
2394 "numbered X register");
2395 return ParseStatus::NoMatch
;
2399 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Name
.size());
2402 const MCRegisterInfo
*RI
= getContext().getRegisterInfo();
2403 MCRegister Pair
= RI
->getMatchingSuperReg(
2404 Reg
, RISCV::sub_gpr_even
,
2405 &RISCVMCRegisterClasses
[RISCV::GPRPairRegClassID
]);
2406 Operands
.push_back(RISCVOperand::createReg(Pair
, S
, E
, /*isGPRAsFPR=*/true));
2407 return ParseStatus::Success
;
2410 template <bool IsRV64
>
2411 ParseStatus
RISCVAsmParser::parseGPRPair(OperandVector
&Operands
) {
2412 return parseGPRPair(Operands
, IsRV64
);
2415 ParseStatus
RISCVAsmParser::parseGPRPair(OperandVector
&Operands
,
2417 // If this is not an RV64 GPRPair instruction, don't parse as a GPRPair on
2418 // RV64 as it will prevent matching the RV64 version of the same instruction
2419 // that doesn't use a GPRPair.
2420 // If this is an RV64 GPRPair instruction, there is no RV32 version so we can
2421 // still parse as a pair.
2422 if (!IsRV64Inst
&& isRV64())
2423 return ParseStatus::NoMatch
;
2425 if (getLexer().isNot(AsmToken::Identifier
))
2426 return ParseStatus::NoMatch
;
2428 StringRef Name
= getLexer().getTok().getIdentifier();
2429 MCRegister Reg
= matchRegisterNameHelper(Name
);
2432 return ParseStatus::NoMatch
;
2434 if (!RISCVMCRegisterClasses
[RISCV::GPRRegClassID
].contains(Reg
))
2435 return ParseStatus::NoMatch
;
2437 if ((Reg
- RISCV::X0
) & 1)
2438 return TokError("register must be even");
2441 SMLoc E
= SMLoc::getFromPointer(S
.getPointer() + Name
.size());
2444 const MCRegisterInfo
*RI
= getContext().getRegisterInfo();
2445 MCRegister Pair
= RI
->getMatchingSuperReg(
2446 Reg
, RISCV::sub_gpr_even
,
2447 &RISCVMCRegisterClasses
[RISCV::GPRPairRegClassID
]);
2448 Operands
.push_back(RISCVOperand::createReg(Pair
, S
, E
));
2449 return ParseStatus::Success
;
2452 ParseStatus
RISCVAsmParser::parseFRMArg(OperandVector
&Operands
) {
2453 if (getLexer().isNot(AsmToken::Identifier
))
2455 "operand must be a valid floating point rounding mode mnemonic");
2457 StringRef Str
= getLexer().getTok().getIdentifier();
2458 RISCVFPRndMode::RoundingMode FRM
= RISCVFPRndMode::stringToRoundingMode(Str
);
2460 if (FRM
== RISCVFPRndMode::Invalid
)
2462 "operand must be a valid floating point rounding mode mnemonic");
2464 Operands
.push_back(RISCVOperand::createFRMArg(FRM
, getLoc()));
2465 Lex(); // Eat identifier token.
2466 return ParseStatus::Success
;
2469 ParseStatus
RISCVAsmParser::parseFenceArg(OperandVector
&Operands
) {
2470 const AsmToken
&Tok
= getLexer().getTok();
2472 if (Tok
.is(AsmToken::Integer
)) {
2473 if (Tok
.getIntVal() != 0)
2476 Operands
.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2478 return ParseStatus::Success
;
2481 if (Tok
.is(AsmToken::Identifier
)) {
2482 StringRef Str
= Tok
.getIdentifier();
2484 // Letters must be unique, taken from 'iorw', and in ascending order. This
2485 // holds as long as each individual character is one of 'iorw' and is
2486 // greater than the previous character.
2490 for (char c
: Str
) {
2496 Imm
|= RISCVFenceField::I
;
2499 Imm
|= RISCVFenceField::O
;
2502 Imm
|= RISCVFenceField::R
;
2505 Imm
|= RISCVFenceField::W
;
2519 Operands
.push_back(RISCVOperand::createFenceArg(Imm
, getLoc()));
2521 return ParseStatus::Success
;
2525 return TokError("operand must be formed of letters selected in-order from "
2529 ParseStatus
RISCVAsmParser::parseMemOpBaseReg(OperandVector
&Operands
) {
2530 if (parseToken(AsmToken::LParen
, "expected '('"))
2531 return ParseStatus::Failure
;
2532 Operands
.push_back(RISCVOperand::createToken("(", getLoc()));
2534 if (!parseRegister(Operands
).isSuccess())
2535 return Error(getLoc(), "expected register");
2537 if (parseToken(AsmToken::RParen
, "expected ')'"))
2538 return ParseStatus::Failure
;
2539 Operands
.push_back(RISCVOperand::createToken(")", getLoc()));
2541 return ParseStatus::Success
;
2544 ParseStatus
RISCVAsmParser::parseZeroOffsetMemOp(OperandVector
&Operands
) {
2545 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
2546 // as one of their register operands, such as `(a0)`. This just denotes that
2547 // the register (in this case `a0`) contains a memory address.
2549 // Normally, we would be able to parse these by putting the parens into the
2550 // instruction string. However, GNU as also accepts a zero-offset memory
2551 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
2552 // with parseImmediate followed by parseMemOpBaseReg, but these instructions
2553 // do not accept an immediate operand, and we do not want to add a "dummy"
2554 // operand that is silently dropped.
2556 // Instead, we use this custom parser. This will: allow (and discard) an
2557 // offset if it is zero; require (and discard) parentheses; and add only the
2558 // parsed register operand to `Operands`.
2560 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
2561 // which will only print the register surrounded by parentheses (which GNU as
2562 // also uses as its canonical representation for these operands).
2563 std::unique_ptr
<RISCVOperand
> OptionalImmOp
;
2565 if (getLexer().isNot(AsmToken::LParen
)) {
2566 // Parse an Integer token. We do not accept arbritrary constant expressions
2567 // in the offset field (because they may include parens, which complicates
2570 SMLoc ImmStart
= getLoc();
2571 if (getParser().parseIntToken(ImmVal
,
2572 "expected '(' or optional integer offset"))
2573 return ParseStatus::Failure
;
2575 // Create a RISCVOperand for checking later (so the error messages are
2576 // nicer), but we don't add it to Operands.
2577 SMLoc ImmEnd
= getLoc();
2579 RISCVOperand::createImm(MCConstantExpr::create(ImmVal
, getContext()),
2580 ImmStart
, ImmEnd
, isRV64());
2583 if (parseToken(AsmToken::LParen
,
2584 OptionalImmOp
? "expected '(' after optional integer offset"
2585 : "expected '(' or optional integer offset"))
2586 return ParseStatus::Failure
;
2588 if (!parseRegister(Operands
).isSuccess())
2589 return Error(getLoc(), "expected register");
2591 if (parseToken(AsmToken::RParen
, "expected ')'"))
2592 return ParseStatus::Failure
;
2594 // Deferred Handling of non-zero offsets. This makes the error messages nicer.
2595 if (OptionalImmOp
&& !OptionalImmOp
->isImmZero())
2597 OptionalImmOp
->getStartLoc(), "optional integer offset must be 0",
2598 SMRange(OptionalImmOp
->getStartLoc(), OptionalImmOp
->getEndLoc()));
2600 return ParseStatus::Success
;
2603 ParseStatus
RISCVAsmParser::parseRegReg(OperandVector
&Operands
) {
2605 if (getLexer().getKind() != AsmToken::Identifier
)
2606 return ParseStatus::NoMatch
;
2608 StringRef RegName
= getLexer().getTok().getIdentifier();
2609 MCRegister Reg
= matchRegisterNameHelper(RegName
);
2611 return Error(getLoc(), "invalid register");
2614 if (parseToken(AsmToken::LParen
, "expected '(' or invalid operand"))
2615 return ParseStatus::Failure
;
2617 if (getLexer().getKind() != AsmToken::Identifier
)
2618 return Error(getLoc(), "expected register");
2620 StringRef Reg2Name
= getLexer().getTok().getIdentifier();
2621 MCRegister Reg2
= matchRegisterNameHelper(Reg2Name
);
2623 return Error(getLoc(), "invalid register");
2626 if (parseToken(AsmToken::RParen
, "expected ')'"))
2627 return ParseStatus::Failure
;
2629 Operands
.push_back(RISCVOperand::createRegReg(Reg
, Reg2
, getLoc()));
2631 return ParseStatus::Success
;
2634 ParseStatus
RISCVAsmParser::parseReglist(OperandVector
&Operands
) {
2635 // Rlist: {ra [, s0[-sN]]}
2636 // XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
2639 if (parseToken(AsmToken::LCurly
, "register list must start with '{'"))
2640 return ParseStatus::Failure
;
2642 bool IsEABI
= isRVE();
2644 if (getLexer().isNot(AsmToken::Identifier
))
2645 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2647 StringRef RegName
= getLexer().getTok().getIdentifier();
2648 MCRegister RegStart
= matchRegisterNameHelper(RegName
);
2650 if (RegStart
!= RISCV::X1
)
2651 return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2654 // parse case like ,s0
2655 if (parseOptionalToken(AsmToken::Comma
)) {
2656 if (getLexer().isNot(AsmToken::Identifier
))
2657 return Error(getLoc(), "invalid register");
2658 StringRef RegName
= getLexer().getTok().getIdentifier();
2659 RegStart
= matchRegisterNameHelper(RegName
);
2661 return Error(getLoc(), "invalid register");
2662 if (RegStart
!= RISCV::X8
)
2663 return Error(getLoc(),
2664 "continuous register list must start from 's0' or 'x8'");
2665 getLexer().Lex(); // eat reg
2668 // parse case like -s1
2669 if (parseOptionalToken(AsmToken::Minus
)) {
2670 StringRef EndName
= getLexer().getTok().getIdentifier();
2671 // FIXME: the register mapping and checks of EABI is wrong
2672 RegEnd
= matchRegisterNameHelper(EndName
);
2674 return Error(getLoc(), "invalid register");
2675 if (IsEABI
&& RegEnd
!= RISCV::X9
)
2676 return Error(getLoc(), "contiguous register list of EABI can only be "
2677 "'s0-s1' or 'x8-x9' pair");
2682 // parse extra part like ', x18[-x20]' for XRegList
2683 if (parseOptionalToken(AsmToken::Comma
)) {
2684 if (RegEnd
!= RISCV::X9
)
2687 "first contiguous registers pair of register list must be 'x8-x9'");
2689 // parse ', x18' for extra part
2690 if (getLexer().isNot(AsmToken::Identifier
))
2691 return Error(getLoc(), "invalid register");
2692 StringRef EndName
= getLexer().getTok().getIdentifier();
2693 if (MatchRegisterName(EndName
) != RISCV::X18
)
2694 return Error(getLoc(),
2695 "second contiguous registers pair of register list "
2696 "must start from 'x18'");
2699 // parse '-x20' for extra part
2700 if (parseOptionalToken(AsmToken::Minus
)) {
2701 if (getLexer().isNot(AsmToken::Identifier
))
2702 return Error(getLoc(), "invalid register");
2703 EndName
= getLexer().getTok().getIdentifier();
2704 if (!MatchRegisterName(EndName
))
2705 return Error(getLoc(), "invalid register");
2708 RegEnd
= MatchRegisterName(EndName
);
2712 if (RegEnd
== RISCV::X26
)
2713 return Error(getLoc(), "invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2714 "x18-x26} is not supported");
2716 if (parseToken(AsmToken::RCurly
, "register list must end with '}'"))
2717 return ParseStatus::Failure
;
2722 auto Encode
= RISCVZC::encodeRlist(RegEnd
, IsEABI
);
2723 if (Encode
== RISCVZC::INVALID_RLIST
)
2724 return Error(S
, "invalid register list");
2725 Operands
.push_back(RISCVOperand::createRlist(Encode
, S
));
2727 return ParseStatus::Success
;
2730 ParseStatus
RISCVAsmParser::parseZcmpStackAdj(OperandVector
&Operands
,
2731 bool ExpectNegative
) {
2732 bool Negative
= parseOptionalToken(AsmToken::Minus
);
2735 int64_t StackAdjustment
= getLexer().getTok().getIntVal();
2737 unsigned RlistVal
= static_cast<RISCVOperand
*>(Operands
[1].get())->Rlist
.Val
;
2739 if (Negative
!= ExpectNegative
||
2740 !RISCVZC::getSpimm(RlistVal
, Spimm
, StackAdjustment
, isRV64()))
2741 return ParseStatus::NoMatch
;
2742 Operands
.push_back(RISCVOperand::createSpimm(Spimm
<< 4, S
));
2744 return ParseStatus::Success
;
2747 /// Looks at a token type and creates the relevant operand from this
2748 /// information, adding to Operands. If operand was parsed, returns false, else
2750 bool RISCVAsmParser::parseOperand(OperandVector
&Operands
, StringRef Mnemonic
) {
2751 // Check if the current operand has a custom associated parser, if so, try to
2752 // custom parse the operand, or fallback to the general approach.
2753 ParseStatus Result
=
2754 MatchOperandParserImpl(Operands
, Mnemonic
, /*ParseForAllFeatures=*/true);
2755 if (Result
.isSuccess())
2757 if (Result
.isFailure())
2760 // Attempt to parse token as a register.
2761 if (parseRegister(Operands
, true).isSuccess())
2764 // Attempt to parse token as an immediate
2765 if (parseImmediate(Operands
).isSuccess()) {
2766 // Parse memory base register if present
2767 if (getLexer().is(AsmToken::LParen
))
2768 return !parseMemOpBaseReg(Operands
).isSuccess();
2772 // Finally we have exhausted all options and must declare defeat.
2773 Error(getLoc(), "unknown operand");
2777 bool RISCVAsmParser::parseInstruction(ParseInstructionInfo
&Info
,
2778 StringRef Name
, SMLoc NameLoc
,
2779 OperandVector
&Operands
) {
2780 // Ensure that if the instruction occurs when relaxation is enabled,
2781 // relocations are forced for the file. Ideally this would be done when there
2782 // is enough information to reliably determine if the instruction itself may
2783 // cause relaxations. Unfortunately instruction processing stage occurs in the
2784 // same pass as relocation emission, so it's too late to set a 'sticky bit'
2785 // for the entire file.
2786 if (getSTI().hasFeature(RISCV::FeatureRelax
)) {
2787 auto *Assembler
= getTargetStreamer().getStreamer().getAssemblerPtr();
2788 if (Assembler
!= nullptr) {
2789 RISCVAsmBackend
&MAB
=
2790 static_cast<RISCVAsmBackend
&>(Assembler
->getBackend());
2791 MAB
.setForceRelocs();
2795 // First operand is token for instruction
2796 Operands
.push_back(RISCVOperand::createToken(Name
, NameLoc
));
2798 // If there are no more operands, then finish
2799 if (getLexer().is(AsmToken::EndOfStatement
)) {
2800 getParser().Lex(); // Consume the EndOfStatement.
2804 // Parse first operand
2805 if (parseOperand(Operands
, Name
))
2808 // Parse until end of statement, consuming commas between operands
2809 while (parseOptionalToken(AsmToken::Comma
)) {
2810 // Parse next operand
2811 if (parseOperand(Operands
, Name
))
2815 if (getParser().parseEOL("unexpected token")) {
2816 getParser().eatToEndOfStatement();
2822 bool RISCVAsmParser::classifySymbolRef(const MCExpr
*Expr
,
2823 RISCVMCExpr::VariantKind
&Kind
) {
2824 Kind
= RISCVMCExpr::VK_RISCV_None
;
2826 if (const RISCVMCExpr
*RE
= dyn_cast
<RISCVMCExpr
>(Expr
)) {
2827 Kind
= RE
->getKind();
2828 Expr
= RE
->getSubExpr();
2833 if (Expr
->evaluateAsRelocatable(Res
, nullptr, &Fixup
))
2834 return Res
.getRefKind() == RISCVMCExpr::VK_RISCV_None
;
2838 bool RISCVAsmParser::isSymbolDiff(const MCExpr
*Expr
) {
2841 if (Expr
->evaluateAsRelocatable(Res
, nullptr, &Fixup
)) {
2842 return Res
.getRefKind() == RISCVMCExpr::VK_RISCV_None
&& Res
.getSymA() &&
2848 ParseStatus
RISCVAsmParser::parseDirective(AsmToken DirectiveID
) {
2849 StringRef IDVal
= DirectiveID
.getString();
2851 if (IDVal
== ".option")
2852 return parseDirectiveOption();
2853 if (IDVal
== ".attribute")
2854 return parseDirectiveAttribute();
2855 if (IDVal
== ".insn")
2856 return parseDirectiveInsn(DirectiveID
.getLoc());
2857 if (IDVal
== ".variant_cc")
2858 return parseDirectiveVariantCC();
2860 return ParseStatus::NoMatch
;
2863 bool RISCVAsmParser::resetToArch(StringRef Arch
, SMLoc Loc
, std::string
&Result
,
2864 bool FromOptionDirective
) {
2865 for (auto &Feature
: RISCVFeatureKV
)
2866 if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature
.Key
))
2867 clearFeatureBits(Feature
.Value
, Feature
.Key
);
2869 auto ParseResult
= llvm::RISCVISAInfo::parseArchString(
2870 Arch
, /*EnableExperimentalExtension=*/true,
2871 /*ExperimentalExtensionVersionCheck=*/true);
2874 raw_string_ostream
OutputErrMsg(Buffer
);
2875 handleAllErrors(ParseResult
.takeError(), [&](llvm::StringError
&ErrMsg
) {
2876 OutputErrMsg
<< "invalid arch name '" << Arch
<< "', "
2877 << ErrMsg
.getMessage();
2880 return Error(Loc
, OutputErrMsg
.str());
2882 auto &ISAInfo
= *ParseResult
;
2884 for (auto &Feature
: RISCVFeatureKV
)
2885 if (ISAInfo
->hasExtension(Feature
.Key
))
2886 setFeatureBits(Feature
.Value
, Feature
.Key
);
2888 if (FromOptionDirective
) {
2889 if (ISAInfo
->getXLen() == 32 && isRV64())
2890 return Error(Loc
, "bad arch string switching from rv64 to rv32");
2891 else if (ISAInfo
->getXLen() == 64 && !isRV64())
2892 return Error(Loc
, "bad arch string switching from rv32 to rv64");
2895 if (ISAInfo
->getXLen() == 32)
2896 clearFeatureBits(RISCV::Feature64Bit
, "64bit");
2897 else if (ISAInfo
->getXLen() == 64)
2898 setFeatureBits(RISCV::Feature64Bit
, "64bit");
2900 return Error(Loc
, "bad arch string " + Arch
);
2902 Result
= ISAInfo
->toString();
2906 bool RISCVAsmParser::parseDirectiveOption() {
2907 MCAsmParser
&Parser
= getParser();
2908 // Get the option token.
2909 AsmToken Tok
= Parser
.getTok();
2911 // At the moment only identifiers are supported.
2912 if (parseToken(AsmToken::Identifier
, "expected identifier"))
2915 StringRef Option
= Tok
.getIdentifier();
2917 if (Option
== "push") {
2918 if (Parser
.parseEOL())
2921 getTargetStreamer().emitDirectiveOptionPush();
2926 if (Option
== "pop") {
2927 SMLoc StartLoc
= Parser
.getTok().getLoc();
2928 if (Parser
.parseEOL())
2931 getTargetStreamer().emitDirectiveOptionPop();
2932 if (popFeatureBits())
2933 return Error(StartLoc
, ".option pop with no .option push");
2938 if (Option
== "arch") {
2939 SmallVector
<RISCVOptionArchArg
> Args
;
2941 if (Parser
.parseComma())
2944 RISCVOptionArchArgType Type
;
2945 if (parseOptionalToken(AsmToken::Plus
))
2946 Type
= RISCVOptionArchArgType::Plus
;
2947 else if (parseOptionalToken(AsmToken::Minus
))
2948 Type
= RISCVOptionArchArgType::Minus
;
2949 else if (!Args
.empty())
2950 return Error(Parser
.getTok().getLoc(),
2951 "unexpected token, expected + or -");
2953 Type
= RISCVOptionArchArgType::Full
;
2955 if (Parser
.getTok().isNot(AsmToken::Identifier
))
2956 return Error(Parser
.getTok().getLoc(),
2957 "unexpected token, expected identifier");
2959 StringRef Arch
= Parser
.getTok().getString();
2960 SMLoc Loc
= Parser
.getTok().getLoc();
2963 if (Type
== RISCVOptionArchArgType::Full
) {
2965 if (resetToArch(Arch
, Loc
, Result
, true))
2968 Args
.emplace_back(Type
, Result
);
2972 if (isDigit(Arch
.back()))
2974 Loc
, "extension version number parsing not currently implemented");
2976 std::string Feature
= RISCVISAInfo::getTargetFeatureForExtension(Arch
);
2977 if (!enableExperimentalExtension() &&
2978 StringRef(Feature
).starts_with("experimental-"))
2979 return Error(Loc
, "unexpected experimental extensions");
2980 auto Ext
= llvm::lower_bound(RISCVFeatureKV
, Feature
);
2981 if (Ext
== std::end(RISCVFeatureKV
) || StringRef(Ext
->Key
) != Feature
)
2982 return Error(Loc
, "unknown extension feature");
2984 Args
.emplace_back(Type
, Arch
.str());
2986 if (Type
== RISCVOptionArchArgType::Plus
) {
2987 FeatureBitset OldFeatureBits
= STI
->getFeatureBits();
2989 setFeatureBits(Ext
->Value
, Ext
->Key
);
2990 auto ParseResult
= RISCVFeatures::parseFeatureBits(isRV64(), STI
->getFeatureBits());
2992 copySTI().setFeatureBits(OldFeatureBits
);
2993 setAvailableFeatures(ComputeAvailableFeatures(OldFeatureBits
));
2996 raw_string_ostream
OutputErrMsg(Buffer
);
2997 handleAllErrors(ParseResult
.takeError(), [&](llvm::StringError
&ErrMsg
) {
2998 OutputErrMsg
<< ErrMsg
.getMessage();
3001 return Error(Loc
, OutputErrMsg
.str());
3004 assert(Type
== RISCVOptionArchArgType::Minus
);
3005 // It is invalid to disable an extension that there are other enabled
3006 // extensions depend on it.
3007 // TODO: Make use of RISCVISAInfo to handle this
3008 for (auto &Feature
: RISCVFeatureKV
) {
3009 if (getSTI().hasFeature(Feature
.Value
) &&
3010 Feature
.Implies
.test(Ext
->Value
))
3011 return Error(Loc
, Twine("can't disable ") + Ext
->Key
+
3012 " extension; " + Feature
.Key
+
3013 " extension requires " + Ext
->Key
+
3017 clearFeatureBits(Ext
->Value
, Ext
->Key
);
3019 } while (Parser
.getTok().isNot(AsmToken::EndOfStatement
));
3021 if (Parser
.parseEOL())
3024 getTargetStreamer().emitDirectiveOptionArch(Args
);
3028 if (Option
== "rvc") {
3029 if (Parser
.parseEOL())
3032 getTargetStreamer().emitDirectiveOptionRVC();
3033 setFeatureBits(RISCV::FeatureStdExtC
, "c");
3037 if (Option
== "norvc") {
3038 if (Parser
.parseEOL())
3041 getTargetStreamer().emitDirectiveOptionNoRVC();
3042 clearFeatureBits(RISCV::FeatureStdExtC
, "c");
3043 clearFeatureBits(RISCV::FeatureStdExtZca
, "zca");
3047 if (Option
== "pic") {
3048 if (Parser
.parseEOL())
3051 getTargetStreamer().emitDirectiveOptionPIC();
3052 ParserOptions
.IsPicEnabled
= true;
3056 if (Option
== "nopic") {
3057 if (Parser
.parseEOL())
3060 getTargetStreamer().emitDirectiveOptionNoPIC();
3061 ParserOptions
.IsPicEnabled
= false;
3065 if (Option
== "relax") {
3066 if (Parser
.parseEOL())
3069 getTargetStreamer().emitDirectiveOptionRelax();
3070 setFeatureBits(RISCV::FeatureRelax
, "relax");
3074 if (Option
== "norelax") {
3075 if (Parser
.parseEOL())
3078 getTargetStreamer().emitDirectiveOptionNoRelax();
3079 clearFeatureBits(RISCV::FeatureRelax
, "relax");
3084 Warning(Parser
.getTok().getLoc(), "unknown option, expected 'push', 'pop', "
3085 "'rvc', 'norvc', 'arch', 'relax' or "
3087 Parser
.eatToEndOfStatement();
3091 /// parseDirectiveAttribute
3092 /// ::= .attribute expression ',' ( expression | "string" )
3093 /// ::= .attribute identifier ',' ( expression | "string" )
3094 bool RISCVAsmParser::parseDirectiveAttribute() {
3095 MCAsmParser
&Parser
= getParser();
3098 TagLoc
= Parser
.getTok().getLoc();
3099 if (Parser
.getTok().is(AsmToken::Identifier
)) {
3100 StringRef Name
= Parser
.getTok().getIdentifier();
3101 std::optional
<unsigned> Ret
=
3102 ELFAttrs::attrTypeFromString(Name
, RISCVAttrs::getRISCVAttributeTags());
3104 return Error(TagLoc
, "attribute name not recognised: " + Name
);
3108 const MCExpr
*AttrExpr
;
3110 TagLoc
= Parser
.getTok().getLoc();
3111 if (Parser
.parseExpression(AttrExpr
))
3114 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(AttrExpr
);
3115 if (check(!CE
, TagLoc
, "expected numeric constant"))
3118 Tag
= CE
->getValue();
3121 if (Parser
.parseComma())
3124 StringRef StringValue
;
3125 int64_t IntegerValue
= 0;
3126 bool IsIntegerValue
= true;
3128 // RISC-V attributes have a string value if the tag number is odd
3129 // and an integer value if the tag number is even.
3131 IsIntegerValue
= false;
3133 SMLoc ValueExprLoc
= Parser
.getTok().getLoc();
3134 if (IsIntegerValue
) {
3135 const MCExpr
*ValueExpr
;
3136 if (Parser
.parseExpression(ValueExpr
))
3139 const MCConstantExpr
*CE
= dyn_cast
<MCConstantExpr
>(ValueExpr
);
3141 return Error(ValueExprLoc
, "expected numeric constant");
3142 IntegerValue
= CE
->getValue();
3144 if (Parser
.getTok().isNot(AsmToken::String
))
3145 return Error(Parser
.getTok().getLoc(), "expected string constant");
3147 StringValue
= Parser
.getTok().getStringContents();
3151 if (Parser
.parseEOL())
3155 getTargetStreamer().emitAttribute(Tag
, IntegerValue
);
3156 else if (Tag
!= RISCVAttrs::ARCH
)
3157 getTargetStreamer().emitTextAttribute(Tag
, StringValue
);
3160 if (resetToArch(StringValue
, ValueExprLoc
, Result
, false))
3163 // Then emit the arch string.
3164 getTargetStreamer().emitTextAttribute(Tag
, Result
);
3170 bool isValidInsnFormat(StringRef Format
, bool AllowC
) {
3171 return StringSwitch
<bool>(Format
)
3172 .Cases("r", "r4", "i", "b", "sb", "u", "j", "uj", "s", true)
3173 .Cases("cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj", AllowC
)
3177 /// parseDirectiveInsn
3178 /// ::= .insn [ format encoding, (operands (, operands)*) ]
3179 /// ::= .insn [ length, value ]
3180 /// ::= .insn [ value ]
3181 bool RISCVAsmParser::parseDirectiveInsn(SMLoc L
) {
3182 MCAsmParser
&Parser
= getParser();
3184 bool AllowC
= getSTI().hasFeature(RISCV::FeatureStdExtC
) ||
3185 getSTI().hasFeature(RISCV::FeatureStdExtZca
);
3187 // Expect instruction format as identifier.
3189 SMLoc ErrorLoc
= Parser
.getTok().getLoc();
3190 if (Parser
.parseIdentifier(Format
)) {
3191 // Try parsing .insn [ length , ] value
3192 std::optional
<int64_t> Length
;
3194 if (Parser
.parseAbsoluteExpression(Value
))
3196 if (Parser
.parseOptionalToken(AsmToken::Comma
)) {
3198 if (Parser
.parseAbsoluteExpression(Value
))
3201 if (*Length
== 0 || (*Length
% 2) != 0)
3202 return Error(ErrorLoc
,
3203 "instruction lengths must be a non-zero multiple of two");
3205 // TODO: Support Instructions > 64 bits.
3207 return Error(ErrorLoc
,
3208 "instruction lengths over 64 bits are not supported");
3211 // We only derive a length from the encoding for 16- and 32-bit
3212 // instructions, as the encodings for longer instructions are not frozen in
3214 int64_t EncodingDerivedLength
= ((Value
& 0b11) == 0b11) ? 4 : 2;
3217 // Only check the length against the encoding if the length is present and
3219 if ((*Length
<= 4) && (*Length
!= EncodingDerivedLength
))
3220 return Error(ErrorLoc
,
3221 "instruction length does not match the encoding");
3223 if (!isUIntN(*Length
* 8, Value
))
3224 return Error(ErrorLoc
, "encoding value does not fit into instruction");
3226 if (!isUIntN(EncodingDerivedLength
* 8, Value
))
3227 return Error(ErrorLoc
, "encoding value does not fit into instruction");
3230 if (!AllowC
&& (EncodingDerivedLength
== 2))
3231 return Error(ErrorLoc
, "compressed instructions are not allowed");
3233 if (getParser().parseEOL("invalid operand for instruction")) {
3234 getParser().eatToEndOfStatement();
3242 Opcode
= RISCV::Insn16
;
3245 Opcode
= RISCV::Insn32
;
3248 Opcode
= RISCV::Insn48
;
3251 Opcode
= RISCV::Insn64
;
3254 llvm_unreachable("Error should have already been emitted");
3257 Opcode
= (EncodingDerivedLength
== 2) ? RISCV::Insn16
: RISCV::Insn32
;
3259 emitToStreamer(getStreamer(), MCInstBuilder(Opcode
).addImm(Value
));
3263 if (!isValidInsnFormat(Format
, AllowC
))
3264 return Error(ErrorLoc
, "invalid instruction format");
3266 std::string FormatName
= (".insn_" + Format
).str();
3268 ParseInstructionInfo Info
;
3269 SmallVector
<std::unique_ptr
<MCParsedAsmOperand
>, 8> Operands
;
3271 if (parseInstruction(Info
, FormatName
, L
, Operands
))
3276 return matchAndEmitInstruction(L
, Opcode
, Operands
, Parser
.getStreamer(),
3278 /*MatchingInlineAsm=*/false);
3281 /// parseDirectiveVariantCC
3282 /// ::= .variant_cc symbol
3283 bool RISCVAsmParser::parseDirectiveVariantCC() {
3285 if (getParser().parseIdentifier(Name
))
3286 return TokError("expected symbol name");
3289 getTargetStreamer().emitDirectiveVariantCC(
3290 *getContext().getOrCreateSymbol(Name
));
3294 void RISCVAsmParser::emitToStreamer(MCStreamer
&S
, const MCInst
&Inst
) {
3296 bool Res
= RISCVRVC::compress(CInst
, Inst
, getSTI());
3298 ++RISCVNumInstrsCompressed
;
3299 S
.emitInstruction((Res
? CInst
: Inst
), getSTI());
3302 void RISCVAsmParser::emitLoadImm(MCRegister DestReg
, int64_t Value
,
3304 SmallVector
<MCInst
, 8> Seq
;
3305 RISCVMatInt::generateMCInstSeq(Value
, getSTI(), DestReg
, Seq
);
3307 for (MCInst
&Inst
: Seq
) {
3308 emitToStreamer(Out
, Inst
);
3312 void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg
, MCOperand TmpReg
,
3313 const MCExpr
*Symbol
,
3314 RISCVMCExpr::VariantKind VKHi
,
3315 unsigned SecondOpcode
, SMLoc IDLoc
,
3317 // A pair of instructions for PC-relative addressing; expands to
3318 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
3319 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
3320 MCContext
&Ctx
= getContext();
3322 MCSymbol
*TmpLabel
= Ctx
.createNamedTempSymbol("pcrel_hi");
3323 Out
.emitLabel(TmpLabel
);
3325 const RISCVMCExpr
*SymbolHi
= RISCVMCExpr::create(Symbol
, VKHi
, Ctx
);
3327 Out
, MCInstBuilder(RISCV::AUIPC
).addOperand(TmpReg
).addExpr(SymbolHi
));
3329 const MCExpr
*RefToLinkTmpLabel
=
3330 RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel
, Ctx
),
3331 RISCVMCExpr::VK_RISCV_PCREL_LO
, Ctx
);
3333 emitToStreamer(Out
, MCInstBuilder(SecondOpcode
)
3334 .addOperand(DestReg
)
3336 .addExpr(RefToLinkTmpLabel
));
3339 void RISCVAsmParser::emitLoadLocalAddress(MCInst
&Inst
, SMLoc IDLoc
,
3341 // The load local address pseudo-instruction "lla" is used in PC-relative
3342 // addressing of local symbols:
3343 // lla rdest, symbol
3345 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
3346 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3347 MCOperand DestReg
= Inst
.getOperand(0);
3348 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
3349 emitAuipcInstPair(DestReg
, DestReg
, Symbol
, RISCVMCExpr::VK_RISCV_PCREL_HI
,
3350 RISCV::ADDI
, IDLoc
, Out
);
3353 void RISCVAsmParser::emitLoadGlobalAddress(MCInst
&Inst
, SMLoc IDLoc
,
3355 // The load global address pseudo-instruction "lga" is used in GOT-indirect
3356 // addressing of global symbols:
3357 // lga rdest, symbol
3359 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
3360 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3361 MCOperand DestReg
= Inst
.getOperand(0);
3362 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
3363 unsigned SecondOpcode
= isRV64() ? RISCV::LD
: RISCV::LW
;
3364 emitAuipcInstPair(DestReg
, DestReg
, Symbol
, RISCVMCExpr::VK_RISCV_GOT_HI
,
3365 SecondOpcode
, IDLoc
, Out
);
3368 void RISCVAsmParser::emitLoadAddress(MCInst
&Inst
, SMLoc IDLoc
,
3370 // The load address pseudo-instruction "la" is used in PC-relative and
3371 // GOT-indirect addressing of global symbols:
3373 // is an alias for either (for non-PIC)
3374 // lla rdest, symbol
3376 // lga rdest, symbol
3377 if (ParserOptions
.IsPicEnabled
)
3378 emitLoadGlobalAddress(Inst
, IDLoc
, Out
);
3380 emitLoadLocalAddress(Inst
, IDLoc
, Out
);
3383 void RISCVAsmParser::emitLoadTLSIEAddress(MCInst
&Inst
, SMLoc IDLoc
,
3385 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
3386 // initial-exec TLS model addressing of global symbols:
3387 // la.tls.ie rdest, symbol
3389 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
3390 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3391 MCOperand DestReg
= Inst
.getOperand(0);
3392 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
3393 unsigned SecondOpcode
= isRV64() ? RISCV::LD
: RISCV::LW
;
3394 emitAuipcInstPair(DestReg
, DestReg
, Symbol
, RISCVMCExpr::VK_RISCV_TLS_GOT_HI
,
3395 SecondOpcode
, IDLoc
, Out
);
3398 void RISCVAsmParser::emitLoadTLSGDAddress(MCInst
&Inst
, SMLoc IDLoc
,
3400 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
3401 // global-dynamic TLS model addressing of global symbols:
3402 // la.tls.gd rdest, symbol
3404 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
3405 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3406 MCOperand DestReg
= Inst
.getOperand(0);
3407 const MCExpr
*Symbol
= Inst
.getOperand(1).getExpr();
3408 emitAuipcInstPair(DestReg
, DestReg
, Symbol
, RISCVMCExpr::VK_RISCV_TLS_GD_HI
,
3409 RISCV::ADDI
, IDLoc
, Out
);
3412 void RISCVAsmParser::emitLoadStoreSymbol(MCInst
&Inst
, unsigned Opcode
,
3413 SMLoc IDLoc
, MCStreamer
&Out
,
3415 // The load/store pseudo-instruction does a pc-relative load with
3418 // The expansion looks like this
3420 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
3421 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
3422 unsigned DestRegOpIdx
= HasTmpReg
? 1 : 0;
3423 MCOperand DestReg
= Inst
.getOperand(DestRegOpIdx
);
3424 unsigned SymbolOpIdx
= HasTmpReg
? 2 : 1;
3425 MCOperand TmpReg
= Inst
.getOperand(0);
3426 const MCExpr
*Symbol
= Inst
.getOperand(SymbolOpIdx
).getExpr();
3427 emitAuipcInstPair(DestReg
, TmpReg
, Symbol
, RISCVMCExpr::VK_RISCV_PCREL_HI
,
3428 Opcode
, IDLoc
, Out
);
3431 void RISCVAsmParser::emitPseudoExtend(MCInst
&Inst
, bool SignExtend
,
3432 int64_t Width
, SMLoc IDLoc
,
3434 // The sign/zero extend pseudo-instruction does two shifts, with the shift
3435 // amounts dependent on the XLEN.
3437 // The expansion looks like this
3439 // SLLI rd, rs, XLEN - Width
3440 // SR[A|R]I rd, rd, XLEN - Width
3441 MCOperand DestReg
= Inst
.getOperand(0);
3442 MCOperand SourceReg
= Inst
.getOperand(1);
3444 unsigned SecondOpcode
= SignExtend
? RISCV::SRAI
: RISCV::SRLI
;
3445 int64_t ShAmt
= (isRV64() ? 64 : 32) - Width
;
3447 assert(ShAmt
> 0 && "Shift amount must be non-zero.");
3449 emitToStreamer(Out
, MCInstBuilder(RISCV::SLLI
)
3450 .addOperand(DestReg
)
3451 .addOperand(SourceReg
)
3454 emitToStreamer(Out
, MCInstBuilder(SecondOpcode
)
3455 .addOperand(DestReg
)
3456 .addOperand(DestReg
)
3460 void RISCVAsmParser::emitVMSGE(MCInst
&Inst
, unsigned Opcode
, SMLoc IDLoc
,
3462 if (Inst
.getNumOperands() == 3) {
3465 // pseudoinstruction: vmsge{u}.vx vd, va, x
3466 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
3467 emitToStreamer(Out
, MCInstBuilder(Opcode
)
3468 .addOperand(Inst
.getOperand(0))
3469 .addOperand(Inst
.getOperand(1))
3470 .addOperand(Inst
.getOperand(2))
3471 .addReg(MCRegister())
3473 emitToStreamer(Out
, MCInstBuilder(RISCV::VMNAND_MM
)
3474 .addOperand(Inst
.getOperand(0))
3475 .addOperand(Inst
.getOperand(0))
3476 .addOperand(Inst
.getOperand(0))
3478 } else if (Inst
.getNumOperands() == 4) {
3479 // masked va >= x, vd != v0
3481 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
3482 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
3483 assert(Inst
.getOperand(0).getReg() != RISCV::V0
&&
3484 "The destination register should not be V0.");
3485 emitToStreamer(Out
, MCInstBuilder(Opcode
)
3486 .addOperand(Inst
.getOperand(0))
3487 .addOperand(Inst
.getOperand(1))
3488 .addOperand(Inst
.getOperand(2))
3489 .addOperand(Inst
.getOperand(3))
3491 emitToStreamer(Out
, MCInstBuilder(RISCV::VMXOR_MM
)
3492 .addOperand(Inst
.getOperand(0))
3493 .addOperand(Inst
.getOperand(0))
3496 } else if (Inst
.getNumOperands() == 5 &&
3497 Inst
.getOperand(0).getReg() == RISCV::V0
) {
3498 // masked va >= x, vd == v0
3500 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3501 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
3502 assert(Inst
.getOperand(0).getReg() == RISCV::V0
&&
3503 "The destination register should be V0.");
3504 assert(Inst
.getOperand(1).getReg() != RISCV::V0
&&
3505 "The temporary vector register should not be V0.");
3506 emitToStreamer(Out
, MCInstBuilder(Opcode
)
3507 .addOperand(Inst
.getOperand(1))
3508 .addOperand(Inst
.getOperand(2))
3509 .addOperand(Inst
.getOperand(3))
3510 .addReg(MCRegister())
3512 emitToStreamer(Out
, MCInstBuilder(RISCV::VMANDN_MM
)
3513 .addOperand(Inst
.getOperand(0))
3514 .addOperand(Inst
.getOperand(0))
3515 .addOperand(Inst
.getOperand(1))
3517 } else if (Inst
.getNumOperands() == 5) {
3518 // masked va >= x, any vd
3520 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3521 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt;
3522 // vmandn.mm vd, vd, v0; vmor.mm vd, vt, vd
3523 assert(Inst
.getOperand(1).getReg() != RISCV::V0
&&
3524 "The temporary vector register should not be V0.");
3525 emitToStreamer(Out
, MCInstBuilder(Opcode
)
3526 .addOperand(Inst
.getOperand(1))
3527 .addOperand(Inst
.getOperand(2))
3528 .addOperand(Inst
.getOperand(3))
3529 .addReg(MCRegister())
3531 emitToStreamer(Out
, MCInstBuilder(RISCV::VMANDN_MM
)
3532 .addOperand(Inst
.getOperand(1))
3534 .addOperand(Inst
.getOperand(1))
3536 emitToStreamer(Out
, MCInstBuilder(RISCV::VMANDN_MM
)
3537 .addOperand(Inst
.getOperand(0))
3538 .addOperand(Inst
.getOperand(0))
3541 emitToStreamer(Out
, MCInstBuilder(RISCV::VMOR_MM
)
3542 .addOperand(Inst
.getOperand(0))
3543 .addOperand(Inst
.getOperand(1))
3544 .addOperand(Inst
.getOperand(0))
3549 bool RISCVAsmParser::checkPseudoAddTPRel(MCInst
&Inst
,
3550 OperandVector
&Operands
) {
3551 assert(Inst
.getOpcode() == RISCV::PseudoAddTPRel
&& "Invalid instruction");
3552 assert(Inst
.getOperand(2).isReg() && "Unexpected second operand kind");
3553 if (Inst
.getOperand(2).getReg() != RISCV::X4
) {
3554 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[3]).getStartLoc();
3555 return Error(ErrorLoc
, "the second input operand must be tp/x4 when using "
3556 "%tprel_add modifier");
3562 bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst
&Inst
,
3563 OperandVector
&Operands
) {
3564 assert(Inst
.getOpcode() == RISCV::PseudoTLSDESCCall
&& "Invalid instruction");
3565 assert(Inst
.getOperand(0).isReg() && "Unexpected operand kind");
3566 if (Inst
.getOperand(0).getReg() != RISCV::X5
) {
3567 SMLoc ErrorLoc
= ((RISCVOperand
&)*Operands
[3]).getStartLoc();
3568 return Error(ErrorLoc
, "the output operand must be t0/x5 when using "
3569 "%tlsdesc_call modifier");
3575 std::unique_ptr
<RISCVOperand
> RISCVAsmParser::defaultMaskRegOp() const {
3576 return RISCVOperand::createReg(MCRegister(), llvm::SMLoc(), llvm::SMLoc());
3579 std::unique_ptr
<RISCVOperand
> RISCVAsmParser::defaultFRMArgOp() const {
3580 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN
,
3584 std::unique_ptr
<RISCVOperand
> RISCVAsmParser::defaultFRMArgLegacyOp() const {
3585 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::RNE
,
3589 bool RISCVAsmParser::validateInstruction(MCInst
&Inst
,
3590 OperandVector
&Operands
) {
3591 unsigned Opcode
= Inst
.getOpcode();
3593 if (Opcode
== RISCV::PseudoVMSGEU_VX_M_T
||
3594 Opcode
== RISCV::PseudoVMSGE_VX_M_T
) {
3595 MCRegister DestReg
= Inst
.getOperand(0).getReg();
3596 MCRegister TempReg
= Inst
.getOperand(1).getReg();
3597 if (DestReg
== TempReg
) {
3598 SMLoc Loc
= Operands
.back()->getStartLoc();
3599 return Error(Loc
, "the temporary vector register cannot be the same as "
3600 "the destination register");
3604 if (Opcode
== RISCV::TH_LDD
|| Opcode
== RISCV::TH_LWUD
||
3605 Opcode
== RISCV::TH_LWD
) {
3606 MCRegister Rd1
= Inst
.getOperand(0).getReg();
3607 MCRegister Rd2
= Inst
.getOperand(1).getReg();
3608 MCRegister Rs1
= Inst
.getOperand(2).getReg();
3609 // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.
3610 if (Rs1
== Rd1
&& Rs1
== Rd2
) {
3611 SMLoc Loc
= Operands
[1]->getStartLoc();
3612 return Error(Loc
, "rs1, rd1, and rd2 cannot all be the same");
3616 if (Opcode
== RISCV::CM_MVSA01
) {
3617 MCRegister Rd1
= Inst
.getOperand(0).getReg();
3618 MCRegister Rd2
= Inst
.getOperand(1).getReg();
3620 SMLoc Loc
= Operands
[1]->getStartLoc();
3621 return Error(Loc
, "rs1 and rs2 must be different");
3625 bool IsTHeadMemPair32
= (Opcode
== RISCV::TH_LWD
||
3626 Opcode
== RISCV::TH_LWUD
|| Opcode
== RISCV::TH_SWD
);
3627 bool IsTHeadMemPair64
= (Opcode
== RISCV::TH_LDD
|| Opcode
== RISCV::TH_SDD
);
3628 // The last operand of XTHeadMemPair instructions must be constant 3 or 4
3629 // depending on the data width.
3630 if (IsTHeadMemPair32
&& Inst
.getOperand(4).getImm() != 3) {
3631 SMLoc Loc
= Operands
.back()->getStartLoc();
3632 return Error(Loc
, "operand must be constant 3");
3633 } else if (IsTHeadMemPair64
&& Inst
.getOperand(4).getImm() != 4) {
3634 SMLoc Loc
= Operands
.back()->getStartLoc();
3635 return Error(Loc
, "operand must be constant 4");
3638 const MCInstrDesc
&MCID
= MII
.get(Opcode
);
3639 if (!(MCID
.TSFlags
& RISCVII::ConstraintMask
))
3642 if (Opcode
== RISCV::VC_V_XVW
|| Opcode
== RISCV::VC_V_IVW
||
3643 Opcode
== RISCV::VC_V_FVW
|| Opcode
== RISCV::VC_V_VVW
) {
3644 // Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for VC_V_XVW.
3645 MCRegister VCIXDst
= Inst
.getOperand(0).getReg();
3646 SMLoc VCIXDstLoc
= Operands
[2]->getStartLoc();
3647 if (MCID
.TSFlags
& RISCVII::VS1Constraint
) {
3648 MCRegister VCIXRs1
= Inst
.getOperand(Inst
.getNumOperands() - 1).getReg();
3649 if (VCIXDst
== VCIXRs1
)
3650 return Error(VCIXDstLoc
, "the destination vector register group cannot"
3651 " overlap the source vector register group");
3653 if (MCID
.TSFlags
& RISCVII::VS2Constraint
) {
3654 MCRegister VCIXRs2
= Inst
.getOperand(Inst
.getNumOperands() - 2).getReg();
3655 if (VCIXDst
== VCIXRs2
)
3656 return Error(VCIXDstLoc
, "the destination vector register group cannot"
3657 " overlap the source vector register group");
3662 MCRegister DestReg
= Inst
.getOperand(0).getReg();
3663 unsigned Offset
= 0;
3664 int TiedOp
= MCID
.getOperandConstraint(1, MCOI::TIED_TO
);
3668 // Operands[1] will be the first operand, DestReg.
3669 SMLoc Loc
= Operands
[1]->getStartLoc();
3670 if (MCID
.TSFlags
& RISCVII::VS2Constraint
) {
3671 MCRegister CheckReg
= Inst
.getOperand(Offset
+ 1).getReg();
3672 if (DestReg
== CheckReg
)
3673 return Error(Loc
, "the destination vector register group cannot overlap"
3674 " the source vector register group");
3676 if ((MCID
.TSFlags
& RISCVII::VS1Constraint
) && Inst
.getOperand(Offset
+ 2).isReg()) {
3677 MCRegister CheckReg
= Inst
.getOperand(Offset
+ 2).getReg();
3678 if (DestReg
== CheckReg
)
3679 return Error(Loc
, "the destination vector register group cannot overlap"
3680 " the source vector register group");
3682 if ((MCID
.TSFlags
& RISCVII::VMConstraint
) && (DestReg
== RISCV::V0
)) {
3683 // vadc, vsbc are special cases. These instructions have no mask register.
3684 // The destination register could not be V0.
3685 if (Opcode
== RISCV::VADC_VVM
|| Opcode
== RISCV::VADC_VXM
||
3686 Opcode
== RISCV::VADC_VIM
|| Opcode
== RISCV::VSBC_VVM
||
3687 Opcode
== RISCV::VSBC_VXM
|| Opcode
== RISCV::VFMERGE_VFM
||
3688 Opcode
== RISCV::VMERGE_VIM
|| Opcode
== RISCV::VMERGE_VVM
||
3689 Opcode
== RISCV::VMERGE_VXM
)
3690 return Error(Loc
, "the destination vector register group cannot be V0");
3692 // Regardless masked or unmasked version, the number of operands is the
3693 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
3694 // actually. We need to check the last operand to ensure whether it is
3696 MCRegister CheckReg
= Inst
.getOperand(Inst
.getNumOperands() - 1).getReg();
3697 assert((CheckReg
== RISCV::V0
|| !CheckReg
) &&
3698 "Unexpected register for mask operand");
3700 if (DestReg
== CheckReg
)
3701 return Error(Loc
, "the destination vector register group cannot overlap"
3702 " the mask register");
3707 bool RISCVAsmParser::processInstruction(MCInst
&Inst
, SMLoc IDLoc
,
3708 OperandVector
&Operands
,
3712 switch (Inst
.getOpcode()) {
3715 case RISCV::PseudoC_ADDI_NOP
:
3716 emitToStreamer(Out
, MCInstBuilder(RISCV::C_NOP
));
3718 case RISCV::PseudoLLAImm
:
3719 case RISCV::PseudoLAImm
:
3720 case RISCV::PseudoLI
: {
3721 MCRegister Reg
= Inst
.getOperand(0).getReg();
3722 const MCOperand
&Op1
= Inst
.getOperand(1);
3724 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
3725 // Just convert to an addi. This allows compatibility with gas.
3726 emitToStreamer(Out
, MCInstBuilder(RISCV::ADDI
)
3729 .addExpr(Op1
.getExpr()));
3732 int64_t Imm
= Inst
.getOperand(1).getImm();
3733 // On RV32 the immediate here can either be a signed or an unsigned
3734 // 32-bit number. Sign extension has to be performed to ensure that Imm
3735 // represents the expected signed 64-bit number.
3737 Imm
= SignExtend64
<32>(Imm
);
3738 emitLoadImm(Reg
, Imm
, Out
);
3741 case RISCV::PseudoLLA
:
3742 emitLoadLocalAddress(Inst
, IDLoc
, Out
);
3744 case RISCV::PseudoLGA
:
3745 emitLoadGlobalAddress(Inst
, IDLoc
, Out
);
3747 case RISCV::PseudoLA
:
3748 emitLoadAddress(Inst
, IDLoc
, Out
);
3750 case RISCV::PseudoLA_TLS_IE
:
3751 emitLoadTLSIEAddress(Inst
, IDLoc
, Out
);
3753 case RISCV::PseudoLA_TLS_GD
:
3754 emitLoadTLSGDAddress(Inst
, IDLoc
, Out
);
3756 case RISCV::PseudoLB
:
3757 emitLoadStoreSymbol(Inst
, RISCV::LB
, IDLoc
, Out
, /*HasTmpReg=*/false);
3759 case RISCV::PseudoLBU
:
3760 emitLoadStoreSymbol(Inst
, RISCV::LBU
, IDLoc
, Out
, /*HasTmpReg=*/false);
3762 case RISCV::PseudoLH
:
3763 emitLoadStoreSymbol(Inst
, RISCV::LH
, IDLoc
, Out
, /*HasTmpReg=*/false);
3765 case RISCV::PseudoLHU
:
3766 emitLoadStoreSymbol(Inst
, RISCV::LHU
, IDLoc
, Out
, /*HasTmpReg=*/false);
3768 case RISCV::PseudoLW
:
3769 emitLoadStoreSymbol(Inst
, RISCV::LW
, IDLoc
, Out
, /*HasTmpReg=*/false);
3771 case RISCV::PseudoLWU
:
3772 emitLoadStoreSymbol(Inst
, RISCV::LWU
, IDLoc
, Out
, /*HasTmpReg=*/false);
3774 case RISCV::PseudoLD
:
3775 emitLoadStoreSymbol(Inst
, RISCV::LD
, IDLoc
, Out
, /*HasTmpReg=*/false);
3777 case RISCV::PseudoFLH
:
3778 emitLoadStoreSymbol(Inst
, RISCV::FLH
, IDLoc
, Out
, /*HasTmpReg=*/true);
3780 case RISCV::PseudoFLW
:
3781 emitLoadStoreSymbol(Inst
, RISCV::FLW
, IDLoc
, Out
, /*HasTmpReg=*/true);
3783 case RISCV::PseudoFLD
:
3784 emitLoadStoreSymbol(Inst
, RISCV::FLD
, IDLoc
, Out
, /*HasTmpReg=*/true);
3786 case RISCV::PseudoSB
:
3787 emitLoadStoreSymbol(Inst
, RISCV::SB
, IDLoc
, Out
, /*HasTmpReg=*/true);
3789 case RISCV::PseudoSH
:
3790 emitLoadStoreSymbol(Inst
, RISCV::SH
, IDLoc
, Out
, /*HasTmpReg=*/true);
3792 case RISCV::PseudoSW
:
3793 emitLoadStoreSymbol(Inst
, RISCV::SW
, IDLoc
, Out
, /*HasTmpReg=*/true);
3795 case RISCV::PseudoSD
:
3796 emitLoadStoreSymbol(Inst
, RISCV::SD
, IDLoc
, Out
, /*HasTmpReg=*/true);
3798 case RISCV::PseudoFSH
:
3799 emitLoadStoreSymbol(Inst
, RISCV::FSH
, IDLoc
, Out
, /*HasTmpReg=*/true);
3801 case RISCV::PseudoFSW
:
3802 emitLoadStoreSymbol(Inst
, RISCV::FSW
, IDLoc
, Out
, /*HasTmpReg=*/true);
3804 case RISCV::PseudoFSD
:
3805 emitLoadStoreSymbol(Inst
, RISCV::FSD
, IDLoc
, Out
, /*HasTmpReg=*/true);
3807 case RISCV::PseudoAddTPRel
:
3808 if (checkPseudoAddTPRel(Inst
, Operands
))
3811 case RISCV::PseudoTLSDESCCall
:
3812 if (checkPseudoTLSDESCCall(Inst
, Operands
))
3815 case RISCV::PseudoSEXT_B
:
3816 emitPseudoExtend(Inst
, /*SignExtend=*/true, /*Width=*/8, IDLoc
, Out
);
3818 case RISCV::PseudoSEXT_H
:
3819 emitPseudoExtend(Inst
, /*SignExtend=*/true, /*Width=*/16, IDLoc
, Out
);
3821 case RISCV::PseudoZEXT_H
:
3822 emitPseudoExtend(Inst
, /*SignExtend=*/false, /*Width=*/16, IDLoc
, Out
);
3824 case RISCV::PseudoZEXT_W
:
3825 emitPseudoExtend(Inst
, /*SignExtend=*/false, /*Width=*/32, IDLoc
, Out
);
3827 case RISCV::PseudoVMSGEU_VX
:
3828 case RISCV::PseudoVMSGEU_VX_M
:
3829 case RISCV::PseudoVMSGEU_VX_M_T
:
3830 emitVMSGE(Inst
, RISCV::VMSLTU_VX
, IDLoc
, Out
);
3832 case RISCV::PseudoVMSGE_VX
:
3833 case RISCV::PseudoVMSGE_VX_M
:
3834 case RISCV::PseudoVMSGE_VX_M_T
:
3835 emitVMSGE(Inst
, RISCV::VMSLT_VX
, IDLoc
, Out
);
3837 case RISCV::PseudoVMSGE_VI
:
3838 case RISCV::PseudoVMSLT_VI
: {
3839 // These instructions are signed and so is immediate so we can subtract one
3840 // and change the opcode.
3841 int64_t Imm
= Inst
.getOperand(2).getImm();
3842 unsigned Opc
= Inst
.getOpcode() == RISCV::PseudoVMSGE_VI
? RISCV::VMSGT_VI
3844 emitToStreamer(Out
, MCInstBuilder(Opc
)
3845 .addOperand(Inst
.getOperand(0))
3846 .addOperand(Inst
.getOperand(1))
3848 .addOperand(Inst
.getOperand(3))
3852 case RISCV::PseudoVMSGEU_VI
:
3853 case RISCV::PseudoVMSLTU_VI
: {
3854 int64_t Imm
= Inst
.getOperand(2).getImm();
3855 // Unsigned comparisons are tricky because the immediate is signed. If the
3856 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
3857 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
3858 // vmsne v0, v1, v1 which is always false.
3860 unsigned Opc
= Inst
.getOpcode() == RISCV::PseudoVMSGEU_VI
3863 emitToStreamer(Out
, MCInstBuilder(Opc
)
3864 .addOperand(Inst
.getOperand(0))
3865 .addOperand(Inst
.getOperand(1))
3866 .addOperand(Inst
.getOperand(1))
3867 .addOperand(Inst
.getOperand(3))
3870 // Other immediate values can subtract one like signed.
3871 unsigned Opc
= Inst
.getOpcode() == RISCV::PseudoVMSGEU_VI
3874 emitToStreamer(Out
, MCInstBuilder(Opc
)
3875 .addOperand(Inst
.getOperand(0))
3876 .addOperand(Inst
.getOperand(1))
3878 .addOperand(Inst
.getOperand(3))
3886 emitToStreamer(Out
, Inst
);
3890 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeRISCVAsmParser() {
3891 RegisterMCAsmParser
<RISCVAsmParser
> X(getTheRISCV32Target());
3892 RegisterMCAsmParser
<RISCVAsmParser
> Y(getTheRISCV64Target());