Bug Summary

File:build/source/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Warning:line 2693, column 11
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name RISCVAsmParser.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-17/lib/clang/17 -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I lib/Target/RISCV/AsmParser -I /build/source/llvm/lib/Target/RISCV/AsmParser -I /build/source/llvm/lib/Target/RISCV -I lib/Target/RISCV -I include -I /build/source/llvm/include -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1683717183 -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility=hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2023-05-10-133810-16478-1 -x c++ /build/source/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
1//===-- RISCVAsmParser.cpp - Parse RISC-V assembly to MCInst instructions -===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
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/SmallString.h"
20#include "llvm/ADT/SmallVector.h"
21#include "llvm/ADT/Statistic.h"
22#include "llvm/MC/MCAssembler.h"
23#include "llvm/MC/MCContext.h"
24#include "llvm/MC/MCExpr.h"
25#include "llvm/MC/MCInst.h"
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/Support/RISCVISAInfo.h"
42
43#include <limits>
44
45using namespace llvm;
46
47#define DEBUG_TYPE"riscv-asm-parser" "riscv-asm-parser"
48
49STATISTIC(RISCVNumInstrsCompressed,static llvm::Statistic RISCVNumInstrsCompressed = {"riscv-asm-parser"
, "RISCVNumInstrsCompressed", "Number of RISC-V Compressed instructions emitted"
}
50 "Number of RISC-V Compressed instructions emitted")static llvm::Statistic RISCVNumInstrsCompressed = {"riscv-asm-parser"
, "RISCVNumInstrsCompressed", "Number of RISC-V Compressed instructions emitted"
}
;
51
52static cl::opt<bool> AddBuildAttributes("riscv-add-build-attributes",
53 cl::init(false));
54
55namespace llvm {
56extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures];
57} // namespace llvm
58
59namespace {
60struct RISCVOperand;
61
62struct ParserOptionsSet {
63 bool IsPicEnabled;
64};
65
66class RISCVAsmParser : public MCTargetAsmParser {
67 SmallVector<FeatureBitset, 4> FeatureBitStack;
68
69 SmallVector<ParserOptionsSet, 4> ParserOptionsStack;
70 ParserOptionsSet ParserOptions;
71
72 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
73 bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
74 bool isRVE() const { return getSTI().hasFeature(RISCV::FeatureRVE); }
75
76 RISCVTargetStreamer &getTargetStreamer() {
77 assert(getParser().getStreamer().getTargetStreamer() &&(static_cast <bool> (getParser().getStreamer().getTargetStreamer
() && "do not have a target streamer") ? void (0) : __assert_fail
("getParser().getStreamer().getTargetStreamer() && \"do not have a target streamer\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 78, __extension__
__PRETTY_FUNCTION__))
78 "do not have a target streamer")(static_cast <bool> (getParser().getStreamer().getTargetStreamer
() && "do not have a target streamer") ? void (0) : __assert_fail
("getParser().getStreamer().getTargetStreamer() && \"do not have a target streamer\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 78, __extension__
__PRETTY_FUNCTION__))
;
79 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
80 return static_cast<RISCVTargetStreamer &>(TS);
81 }
82
83 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
84 unsigned Kind) override;
85 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
86
87 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
88 int64_t Lower, int64_t Upper,
89 const Twine &Msg);
90 bool generateImmOutOfRangeError(SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
91 const Twine &Msg);
92
93 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
94 OperandVector &Operands, MCStreamer &Out,
95 uint64_t &ErrorInfo,
96 bool MatchingInlineAsm) override;
97
98 bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
99 SMLoc &EndLoc) override;
100 OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc,
101 SMLoc &EndLoc) override;
102
103 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
104 SMLoc NameLoc, OperandVector &Operands) override;
105
106 bool ParseDirective(AsmToken DirectiveID) override;
107
108 // Helper to actually emit an instruction to the MCStreamer. Also, when
109 // possible, compression of the instruction is performed.
110 void emitToStreamer(MCStreamer &S, const MCInst &Inst);
111
112 // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
113 // synthesize the desired immedate value into the destination register.
114 void emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out);
115
116 // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
117 // helpers such as emitLoadLocalAddress and emitLoadAddress.
118 void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
119 const MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi,
120 unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
121
122 // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
123 void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
124
125 // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
126 void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
127
128 // Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
129 // addressing.
130 void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
131
132 // Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
133 // addressing.
134 void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
135
136 // Helper to emit pseudo load/store instruction with a symbol.
137 void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
138 MCStreamer &Out, bool HasTmpReg);
139
140 // Helper to emit pseudo sign/zero extend instruction.
141 void emitPseudoExtend(MCInst &Inst, bool SignExtend, int64_t Width,
142 SMLoc IDLoc, MCStreamer &Out);
143
144 // Helper to emit pseudo vmsge{u}.vx instruction.
145 void emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out);
146
147 // Checks that a PseudoAddTPRel is using x4/tp in its second input operand.
148 // Enforcing this using a restricted register class for the second input
149 // operand of PseudoAddTPRel results in a poor diagnostic due to the fact
150 // 'add' is an overloaded mnemonic.
151 bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands);
152
153 // Check instruction constraints.
154 bool validateInstruction(MCInst &Inst, OperandVector &Operands);
155
156 /// Helper for processing MC instructions that have been successfully matched
157 /// by MatchAndEmitInstruction. Modifications to the emitted instructions,
158 /// like the expansion of pseudo instructions (e.g., "li"), can be performed
159 /// in this method.
160 bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands,
161 MCStreamer &Out);
162
163// Auto-generated instruction matching functions
164#define GET_ASSEMBLER_HEADER
165#include "RISCVGenAsmMatcher.inc"
166
167 OperandMatchResultTy parseCSRSystemRegister(OperandVector &Operands);
168 OperandMatchResultTy parseFPImm(OperandVector &Operands);
169 OperandMatchResultTy parseImmediate(OperandVector &Operands);
170 OperandMatchResultTy parseRegister(OperandVector &Operands,
171 bool AllowParens = false);
172 OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
173 OperandMatchResultTy parseZeroOffsetMemOp(OperandVector &Operands);
174 OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
175 OperandMatchResultTy parseBareSymbol(OperandVector &Operands);
176 OperandMatchResultTy parseCallSymbol(OperandVector &Operands);
177 OperandMatchResultTy parsePseudoJumpSymbol(OperandVector &Operands);
178 OperandMatchResultTy parseJALOffset(OperandVector &Operands);
179 OperandMatchResultTy parseVTypeI(OperandVector &Operands);
180 OperandMatchResultTy parseMaskReg(OperandVector &Operands);
181 OperandMatchResultTy parseInsnDirectiveOpcode(OperandVector &Operands);
182 OperandMatchResultTy parseInsnCDirectiveOpcode(OperandVector &Operands);
183 OperandMatchResultTy parseGPRAsFPR(OperandVector &Operands);
184 OperandMatchResultTy parseFRMArg(OperandVector &Operands);
185 OperandMatchResultTy parseFenceArg(OperandVector &Operands);
186 OperandMatchResultTy parseReglist(OperandVector &Operands);
187 OperandMatchResultTy parseRetval(OperandVector &Operands);
188 OperandMatchResultTy parseZcmpSpimm(OperandVector &Operands);
189
190 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
191
192 bool parseDirectiveOption();
193 bool parseDirectiveAttribute();
194 bool parseDirectiveInsn(SMLoc L);
195 bool parseDirectiveVariantCC();
196
197 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
198 if (!(getSTI().hasFeature(Feature))) {
199 MCSubtargetInfo &STI = copySTI();
200 setAvailableFeatures(
201 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
202 }
203 }
204
205 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
206 if (getSTI().hasFeature(Feature)) {
207 MCSubtargetInfo &STI = copySTI();
208 setAvailableFeatures(
209 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
210 }
211 }
212
213 void pushFeatureBits() {
214 assert(FeatureBitStack.size() == ParserOptionsStack.size() &&(static_cast <bool> (FeatureBitStack.size() == ParserOptionsStack
.size() && "These two stacks must be kept synchronized"
) ? void (0) : __assert_fail ("FeatureBitStack.size() == ParserOptionsStack.size() && \"These two stacks must be kept synchronized\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 215, __extension__
__PRETTY_FUNCTION__))
215 "These two stacks must be kept synchronized")(static_cast <bool> (FeatureBitStack.size() == ParserOptionsStack
.size() && "These two stacks must be kept synchronized"
) ? void (0) : __assert_fail ("FeatureBitStack.size() == ParserOptionsStack.size() && \"These two stacks must be kept synchronized\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 215, __extension__
__PRETTY_FUNCTION__))
;
216 FeatureBitStack.push_back(getSTI().getFeatureBits());
217 ParserOptionsStack.push_back(ParserOptions);
218 }
219
220 bool popFeatureBits() {
221 assert(FeatureBitStack.size() == ParserOptionsStack.size() &&(static_cast <bool> (FeatureBitStack.size() == ParserOptionsStack
.size() && "These two stacks must be kept synchronized"
) ? void (0) : __assert_fail ("FeatureBitStack.size() == ParserOptionsStack.size() && \"These two stacks must be kept synchronized\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 222, __extension__
__PRETTY_FUNCTION__))
222 "These two stacks must be kept synchronized")(static_cast <bool> (FeatureBitStack.size() == ParserOptionsStack
.size() && "These two stacks must be kept synchronized"
) ? void (0) : __assert_fail ("FeatureBitStack.size() == ParserOptionsStack.size() && \"These two stacks must be kept synchronized\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 222, __extension__
__PRETTY_FUNCTION__))
;
223 if (FeatureBitStack.empty())
224 return true;
225
226 FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
227 copySTI().setFeatureBits(FeatureBits);
228 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
229
230 ParserOptions = ParserOptionsStack.pop_back_val();
231
232 return false;
233 }
234
235 std::unique_ptr<RISCVOperand> defaultMaskRegOp() const;
236 std::unique_ptr<RISCVOperand> defaultFRMArgOp() const;
237
238public:
239 enum RISCVMatchResultTy {
240 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
241 Match_RequiresEvenGPRs,
242#define GET_OPERAND_DIAGNOSTIC_TYPES
243#include "RISCVGenAsmMatcher.inc"
244#undef GET_OPERAND_DIAGNOSTIC_TYPES
245 };
246
247 static bool classifySymbolRef(const MCExpr *Expr,
248 RISCVMCExpr::VariantKind &Kind);
249
250 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
251 const MCInstrInfo &MII, const MCTargetOptions &Options)
252 : MCTargetAsmParser(Options, STI, MII) {
253 MCAsmParserExtension::Initialize(Parser);
254
255 Parser.addAliasForDirective(".half", ".2byte");
256 Parser.addAliasForDirective(".hword", ".2byte");
257 Parser.addAliasForDirective(".word", ".4byte");
258 Parser.addAliasForDirective(".dword", ".8byte");
259 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
260
261 auto ABIName = StringRef(Options.ABIName);
262 if (ABIName.endswith("f") && !getSTI().hasFeature(RISCV::FeatureStdExtF)) {
263 errs() << "Hard-float 'f' ABI can't be used for a target that "
264 "doesn't support the F instruction set extension (ignoring "
265 "target-abi)\n";
266 } else if (ABIName.endswith("d") &&
267 !getSTI().hasFeature(RISCV::FeatureStdExtD)) {
268 errs() << "Hard-float 'd' ABI can't be used for a target that "
269 "doesn't support the D instruction set extension (ignoring "
270 "target-abi)\n";
271 }
272
273 // Use computeTargetABI to check if ABIName is valid. If invalid, output
274 // error message.
275 RISCVABI::computeTargetABI(STI.getTargetTriple(), STI.getFeatureBits(),
276 ABIName);
277
278 const MCObjectFileInfo *MOFI = Parser.getContext().getObjectFileInfo();
279 ParserOptions.IsPicEnabled = MOFI->isPositionIndependent();
280
281 if (AddBuildAttributes)
282 getTargetStreamer().emitTargetAttributes(STI, /*EmitStackAlign*/ false);
283 }
284};
285
286/// RISCVOperand - Instances of this class represent a parsed machine
287/// instruction
288struct RISCVOperand final : public MCParsedAsmOperand {
289
290 enum class KindTy {
291 Token,
292 Register,
293 Immediate,
294 FPImmediate,
295 SystemRegister,
296 VType,
297 FRM,
298 Fence,
299 Rlist,
300 Spimm,
301 } Kind;
302
303 struct RegOp {
304 MCRegister RegNum;
305 bool IsGPRAsFPR;
306 };
307
308 struct ImmOp {
309 const MCExpr *Val;
310 bool IsRV64;
311 };
312
313 struct FPImmOp {
314 uint64_t Val;
315 };
316
317 struct SysRegOp {
318 const char *Data;
319 unsigned Length;
320 unsigned Encoding;
321 // FIXME: Add the Encoding parsed fields as needed for checks,
322 // e.g.: read/write or user/supervisor/machine privileges.
323 };
324
325 struct VTypeOp {
326 unsigned Val;
327 };
328
329 struct FRMOp {
330 RISCVFPRndMode::RoundingMode FRM;
331 };
332
333 struct FenceOp {
334 unsigned Val;
335 };
336
337 struct RlistOp {
338 unsigned Val;
339 };
340
341 struct SpimmOp {
342 unsigned Val;
343 };
344
345 SMLoc StartLoc, EndLoc;
346 union {
347 StringRef Tok;
348 RegOp Reg;
349 ImmOp Imm;
350 FPImmOp FPImm;
351 struct SysRegOp SysReg;
352 struct VTypeOp VType;
353 struct FRMOp FRM;
354 struct FenceOp Fence;
355 struct RlistOp Rlist;
356 struct SpimmOp Spimm;
357 };
358
359 RISCVOperand(KindTy K) : Kind(K) {}
360
361public:
362 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
363 Kind = o.Kind;
364 StartLoc = o.StartLoc;
365 EndLoc = o.EndLoc;
366 switch (Kind) {
367 case KindTy::Register:
368 Reg = o.Reg;
369 break;
370 case KindTy::Immediate:
371 Imm = o.Imm;
372 break;
373 case KindTy::FPImmediate:
374 FPImm = o.FPImm;
375 break;
376 case KindTy::Token:
377 Tok = o.Tok;
378 break;
379 case KindTy::SystemRegister:
380 SysReg = o.SysReg;
381 break;
382 case KindTy::VType:
383 VType = o.VType;
384 break;
385 case KindTy::FRM:
386 FRM = o.FRM;
387 break;
388 case KindTy::Fence:
389 Fence = o.Fence;
390 break;
391 case KindTy::Rlist:
392 Rlist = o.Rlist;
393 break;
394 case KindTy::Spimm:
395 Spimm = o.Spimm;
396 break;
397 }
398 }
399
400 bool isToken() const override { return Kind == KindTy::Token; }
401 bool isReg() const override { return Kind == KindTy::Register; }
402 bool isV0Reg() const {
403 return Kind == KindTy::Register && Reg.RegNum == RISCV::V0;
404 }
405 bool isAnyReg() const {
406 return Kind == KindTy::Register &&
407 (RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum) ||
408 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg.RegNum) ||
409 RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg.RegNum));
410 }
411 bool isAnyRegC() const {
412 return Kind == KindTy::Register &&
413 (RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains(
414 Reg.RegNum) ||
415 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
416 Reg.RegNum));
417 }
418 bool isImm() const override { return Kind == KindTy::Immediate; }
419 bool isMem() const override { return false; }
420 bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
421 bool isRlist() const { return Kind == KindTy::Rlist; }
422 bool isSpimm() const { return Kind == KindTy::Spimm; }
423
424 bool isGPR() const {
425 return Kind == KindTy::Register &&
426 RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum);
427 }
428
429 bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
430
431 bool isGPRF64AsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
432
433 bool isGPRPF64AsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
434
435 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
436 RISCVMCExpr::VariantKind &VK) {
437 if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
438 VK = RE->getKind();
439 return RE->evaluateAsConstant(Imm);
440 }
441
442 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
443 VK = RISCVMCExpr::VK_RISCV_None;
444 Imm = CE->getValue();
445 return true;
446 }
447
448 return false;
449 }
450
451 // True if operand is a symbol with no modifiers, or a constant with no
452 // modifiers and isShiftedInt<N-1, 1>(Op).
453 template <int N> bool isBareSimmNLsb0() const {
454 int64_t Imm;
455 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
456 if (!isImm())
457 return false;
458 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
459 bool IsValid;
460 if (!IsConstantImm)
461 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
462 else
463 IsValid = isShiftedInt<N - 1, 1>(Imm);
464 return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
465 }
466
467 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
468
469 bool isBareSymbol() const {
470 int64_t Imm;
471 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
472 // Must be of 'immediate' type but not a constant.
473 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
474 return false;
475 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
476 VK == RISCVMCExpr::VK_RISCV_None;
477 }
478
479 bool isCallSymbol() const {
480 int64_t Imm;
481 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
482 // Must be of 'immediate' type but not a constant.
483 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
484 return false;
485 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
486 (VK == RISCVMCExpr::VK_RISCV_CALL ||
487 VK == RISCVMCExpr::VK_RISCV_CALL_PLT);
488 }
489
490 bool isPseudoJumpSymbol() const {
491 int64_t Imm;
492 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
493 // Must be of 'immediate' type but not a constant.
494 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
495 return false;
496 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
497 VK == RISCVMCExpr::VK_RISCV_CALL;
498 }
499
500 bool isTPRelAddSymbol() const {
501 int64_t Imm;
502 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
503 // Must be of 'immediate' type but not a constant.
504 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
505 return false;
506 return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
507 VK == RISCVMCExpr::VK_RISCV_TPREL_ADD;
508 }
509
510 bool isCSRSystemRegister() const { return isSystemRegister(); }
511
512 bool isVTypeImm(unsigned N) const {
513 int64_t Imm;
514 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
515 if (!isImm())
516 return false;
517 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
518 return IsConstantImm && isUIntN(N, Imm) && VK == RISCVMCExpr::VK_RISCV_None;
519 }
520
521 // If the last operand of the vsetvli/vsetvli instruction is a constant
522 // expression, KindTy is Immediate.
523 bool isVTypeI10() const {
524 if (Kind == KindTy::Immediate)
525 return isVTypeImm(10);
526 return Kind == KindTy::VType;
527 }
528 bool isVTypeI11() const {
529 if (Kind == KindTy::Immediate)
530 return isVTypeImm(11);
531 return Kind == KindTy::VType;
532 }
533
534 /// Return true if the operand is a valid for the fence instruction e.g.
535 /// ('iorw').
536 bool isFenceArg() const { return Kind == KindTy::Fence; }
537
538 /// Return true if the operand is a valid floating point rounding mode.
539 bool isFRMArg() const { return Kind == KindTy::FRM; }
540 bool isRTZArg() const { return isFRMArg() && FRM.FRM == RISCVFPRndMode::RTZ; }
541
542 /// Return true if the operand is a valid fli.s floating-point immediate.
543 bool isLoadFPImm() const {
544 if (isImm())
545 return isUImm5();
546 if (Kind != KindTy::FPImmediate)
547 return false;
548 int Idx = RISCVLoadFPImm::getLoadFPImm(
549 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
550 // Don't allow decimal version of the minimum value. It is a different value
551 // for each supported data type.
552 return Idx >= 0 && Idx != 1;
553 }
554
555 bool isImmXLenLI() const {
556 int64_t Imm;
557 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
558 if (!isImm())
559 return false;
560 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
561 if (VK == RISCVMCExpr::VK_RISCV_LO || VK == RISCVMCExpr::VK_RISCV_PCREL_LO)
562 return true;
563 // Given only Imm, ensuring that the actually specified constant is either
564 // a signed or unsigned 64-bit number is unfortunately impossible.
565 return IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None &&
566 (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
567 }
568
569 bool isUImmLog2XLen() const {
570 int64_t Imm;
571 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
572 if (!isImm())
573 return false;
574 if (!evaluateConstantImm(getImm(), Imm, VK) ||
575 VK != RISCVMCExpr::VK_RISCV_None)
576 return false;
577 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
578 }
579
580 bool isUImmLog2XLenNonZero() const {
581 int64_t Imm;
582 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
583 if (!isImm())
584 return false;
585 if (!evaluateConstantImm(getImm(), Imm, VK) ||
586 VK != RISCVMCExpr::VK_RISCV_None)
587 return false;
588 if (Imm == 0)
589 return false;
590 return (isRV64Imm() && isUInt<6>(Imm)) || isUInt<5>(Imm);
591 }
592
593 bool isUImmLog2XLenHalf() const {
594 int64_t Imm;
595 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
596 if (!isImm())
597 return false;
598 if (!evaluateConstantImm(getImm(), Imm, VK) ||
599 VK != RISCVMCExpr::VK_RISCV_None)
600 return false;
601 return (isRV64Imm() && isUInt<5>(Imm)) || isUInt<4>(Imm);
602 }
603
604 template <unsigned N> bool IsUImm() const {
605 int64_t Imm;
606 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
607 if (!isImm())
608 return false;
609 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
610 return IsConstantImm && isUInt<N>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
611 }
612
613 bool isUImm1() const { return IsUImm<1>(); }
614 bool isUImm2() const { return IsUImm<2>(); }
615 bool isUImm3() const { return IsUImm<3>(); }
616 bool isUImm4() const { return IsUImm<4>(); }
617 bool isUImm5() const { return IsUImm<5>(); }
618 bool isUImm6() const { return IsUImm<6>(); }
619 bool isUImm7() const { return IsUImm<7>(); }
620 bool isUImm8() const { return IsUImm<8>(); }
621
622 bool isUImm8GE32() const {
623 int64_t Imm;
624 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
625 if (!isImm())
626 return false;
627 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
628 return IsConstantImm && isUInt<8>(Imm) && Imm >= 32 &&
629 VK == RISCVMCExpr::VK_RISCV_None;
630 }
631
632 bool isRnumArg() const {
633 int64_t Imm;
634 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
635 if (!isImm())
636 return false;
637 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
638 return IsConstantImm && Imm >= INT64_C(0)0L && Imm <= INT64_C(10)10L &&
639 VK == RISCVMCExpr::VK_RISCV_None;
640 }
641
642 bool isRnumArg_0_7() const {
643 int64_t Imm;
644 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
645 if (!isImm())
646 return false;
647 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
648 return IsConstantImm && Imm >= INT64_C(0)0L && Imm <= INT64_C(7)7L &&
649 VK == RISCVMCExpr::VK_RISCV_None;
650 }
651
652 bool isRnumArg_1_10() const {
653 int64_t Imm;
654 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
655 if (!isImm())
656 return false;
657 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
658 return IsConstantImm && Imm >= INT64_C(1)1L && Imm <= INT64_C(10)10L &&
659 VK == RISCVMCExpr::VK_RISCV_None;
660 }
661
662 bool isRnumArg_2_14() const {
663 int64_t Imm;
664 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
665 if (!isImm())
666 return false;
667 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
668 return IsConstantImm && Imm >= INT64_C(2)2L && Imm <= INT64_C(14)14L &&
669 VK == RISCVMCExpr::VK_RISCV_None;
670 }
671
672 bool isSImm5() const {
673 if (!isImm())
674 return false;
675 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
676 int64_t Imm;
677 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
678 return IsConstantImm && isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
679 VK == RISCVMCExpr::VK_RISCV_None;
680 }
681
682 bool isSImm6() const {
683 if (!isImm())
684 return false;
685 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
686 int64_t Imm;
687 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
688 return IsConstantImm && isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
689 VK == RISCVMCExpr::VK_RISCV_None;
690 }
691
692 bool isSImm6NonZero() const {
693 if (!isImm())
694 return false;
695 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
696 int64_t Imm;
697 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
698 return IsConstantImm && Imm != 0 &&
699 isInt<6>(fixImmediateForRV32(Imm, isRV64Imm())) &&
700 VK == RISCVMCExpr::VK_RISCV_None;
701 }
702
703 bool isCLUIImm() const {
704 if (!isImm())
705 return false;
706 int64_t Imm;
707 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
708 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
709 return IsConstantImm && (Imm != 0) &&
710 (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
711 VK == RISCVMCExpr::VK_RISCV_None;
712 }
713
714 bool isUImm2Lsb0() const {
715 if (!isImm())
716 return false;
717 int64_t Imm;
718 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
719 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
720 return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
721 VK == RISCVMCExpr::VK_RISCV_None;
722 }
723
724 bool isUImm7Lsb00() const {
725 if (!isImm())
726 return false;
727 int64_t Imm;
728 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
729 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
730 return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
731 VK == RISCVMCExpr::VK_RISCV_None;
732 }
733
734 bool isUImm8Lsb00() const {
735 if (!isImm())
736 return false;
737 int64_t Imm;
738 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
739 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
740 return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
741 VK == RISCVMCExpr::VK_RISCV_None;
742 }
743
744 bool isUImm8Lsb000() const {
745 if (!isImm())
746 return false;
747 int64_t Imm;
748 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
749 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
750 return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
751 VK == RISCVMCExpr::VK_RISCV_None;
752 }
753
754 bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
755
756 bool isUImm9Lsb000() const {
757 if (!isImm())
758 return false;
759 int64_t Imm;
760 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
761 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
762 return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
763 VK == RISCVMCExpr::VK_RISCV_None;
764 }
765
766 bool isUImm10Lsb00NonZero() const {
767 if (!isImm())
768 return false;
769 int64_t Imm;
770 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
771 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
772 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
773 VK == RISCVMCExpr::VK_RISCV_None;
774 }
775
776 // If this a RV32 and the immediate is a uimm32, sign extend it to 32 bits.
777 // This allows writing 'addi a0, a0, 0xffffffff'.
778 static int64_t fixImmediateForRV32(int64_t Imm, bool IsRV64Imm) {
779 if (IsRV64Imm || !isUInt<32>(Imm))
780 return Imm;
781 return SignExtend64<32>(Imm);
782 }
783
784 bool isSImm12() const {
785 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
786 int64_t Imm;
787 bool IsValid;
788 if (!isImm())
789 return false;
790 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
791 if (!IsConstantImm)
792 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
793 else
794 IsValid = isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
795 return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
796 VK == RISCVMCExpr::VK_RISCV_LO ||
797 VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
798 VK == RISCVMCExpr::VK_RISCV_TPREL_LO);
799 }
800
801 bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
802
803 bool isSImm12Lsb00000() const {
804 if (!isImm())
805 return false;
806 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
807 int64_t Imm;
808 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
809 return IsConstantImm && isShiftedInt<7, 5>(Imm) &&
810 VK == RISCVMCExpr::VK_RISCV_None;
811 }
812
813 bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
814
815 bool isSImm10Lsb0000NonZero() const {
816 if (!isImm())
817 return false;
818 int64_t Imm;
819 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
820 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
821 return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) &&
822 VK == RISCVMCExpr::VK_RISCV_None;
823 }
824
825 bool isUImm20LUI() const {
826 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
827 int64_t Imm;
828 bool IsValid;
829 if (!isImm())
830 return false;
831 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
832 if (!IsConstantImm) {
833 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
834 return IsValid && (VK == RISCVMCExpr::VK_RISCV_HI ||
835 VK == RISCVMCExpr::VK_RISCV_TPREL_HI);
836 } else {
837 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
838 VK == RISCVMCExpr::VK_RISCV_HI ||
839 VK == RISCVMCExpr::VK_RISCV_TPREL_HI);
840 }
841 }
842
843 bool isUImm20AUIPC() const {
844 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
845 int64_t Imm;
846 bool IsValid;
847 if (!isImm())
848 return false;
849 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
850 if (!IsConstantImm) {
851 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
852 return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
853 VK == RISCVMCExpr::VK_RISCV_GOT_HI ||
854 VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||
855 VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI);
856 } else {
857 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
858 VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
859 VK == RISCVMCExpr::VK_RISCV_GOT_HI ||
860 VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||
861 VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI);
862 }
863 }
864
865 bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
866
867 bool isImmZero() const {
868 if (!isImm())
869 return false;
870 int64_t Imm;
871 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
872 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
873 return IsConstantImm && (Imm == 0) && VK == RISCVMCExpr::VK_RISCV_None;
874 }
875
876 bool isSImm5Plus1() const {
877 if (!isImm())
878 return false;
879 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
880 int64_t Imm;
881 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
882 return IsConstantImm &&
883 isInt<5>(fixImmediateForRV32(Imm, isRV64Imm()) - 1) &&
884 VK == RISCVMCExpr::VK_RISCV_None;
885 }
886
887 /// getStartLoc - Gets location of the first token of this operand
888 SMLoc getStartLoc() const override { return StartLoc; }
889 /// getEndLoc - Gets location of the last token of this operand
890 SMLoc getEndLoc() const override { return EndLoc; }
891 /// True if this operand is for an RV64 instruction
892 bool isRV64Imm() const {
893 assert(Kind == KindTy::Immediate && "Invalid type access!")(static_cast <bool> (Kind == KindTy::Immediate &&
"Invalid type access!") ? void (0) : __assert_fail ("Kind == KindTy::Immediate && \"Invalid type access!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 893, __extension__
__PRETTY_FUNCTION__))
;
894 return Imm.IsRV64;
895 }
896
897 unsigned getReg() const override {
898 assert(Kind == KindTy::Register && "Invalid type access!")(static_cast <bool> (Kind == KindTy::Register &&
"Invalid type access!") ? void (0) : __assert_fail ("Kind == KindTy::Register && \"Invalid type access!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 898, __extension__
__PRETTY_FUNCTION__))
;
899 return Reg.RegNum.id();
900 }
901
902 StringRef getSysReg() const {
903 assert(Kind == KindTy::SystemRegister && "Invalid type access!")(static_cast <bool> (Kind == KindTy::SystemRegister &&
"Invalid type access!") ? void (0) : __assert_fail ("Kind == KindTy::SystemRegister && \"Invalid type access!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 903, __extension__
__PRETTY_FUNCTION__))
;
904 return StringRef(SysReg.Data, SysReg.Length);
905 }
906
907 const MCExpr *getImm() const {
908 assert(Kind == KindTy::Immediate && "Invalid type access!")(static_cast <bool> (Kind == KindTy::Immediate &&
"Invalid type access!") ? void (0) : __assert_fail ("Kind == KindTy::Immediate && \"Invalid type access!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 908, __extension__
__PRETTY_FUNCTION__))
;
909 return Imm.Val;
910 }
911
912 uint64_t getFPConst() const {
913 assert(Kind == KindTy::FPImmediate && "Invalid type access!")(static_cast <bool> (Kind == KindTy::FPImmediate &&
"Invalid type access!") ? void (0) : __assert_fail ("Kind == KindTy::FPImmediate && \"Invalid type access!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 913, __extension__
__PRETTY_FUNCTION__))
;
914 return FPImm.Val;
915 }
916
917 StringRef getToken() const {
918 assert(Kind == KindTy::Token && "Invalid type access!")(static_cast <bool> (Kind == KindTy::Token && "Invalid type access!"
) ? void (0) : __assert_fail ("Kind == KindTy::Token && \"Invalid type access!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 918, __extension__
__PRETTY_FUNCTION__))
;
919 return Tok;
920 }
921
922 unsigned getVType() const {
923 assert(Kind == KindTy::VType && "Invalid type access!")(static_cast <bool> (Kind == KindTy::VType && "Invalid type access!"
) ? void (0) : __assert_fail ("Kind == KindTy::VType && \"Invalid type access!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 923, __extension__
__PRETTY_FUNCTION__))
;
924 return VType.Val;
925 }
926
927 RISCVFPRndMode::RoundingMode getFRM() const {
928 assert(Kind == KindTy::FRM && "Invalid type access!")(static_cast <bool> (Kind == KindTy::FRM && "Invalid type access!"
) ? void (0) : __assert_fail ("Kind == KindTy::FRM && \"Invalid type access!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 928, __extension__
__PRETTY_FUNCTION__))
;
929 return FRM.FRM;
930 }
931
932 unsigned getFence() const {
933 assert(Kind == KindTy::Fence && "Invalid type access!")(static_cast <bool> (Kind == KindTy::Fence && "Invalid type access!"
) ? void (0) : __assert_fail ("Kind == KindTy::Fence && \"Invalid type access!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 933, __extension__
__PRETTY_FUNCTION__))
;
934 return Fence.Val;
935 }
936
937 void print(raw_ostream &OS) const override {
938 auto RegName = [](MCRegister Reg) {
939 if (Reg)
940 return RISCVInstPrinter::getRegisterName(Reg);
941 else
942 return "noreg";
943 };
944
945 switch (Kind) {
946 case KindTy::Immediate:
947 OS << *getImm();
948 break;
949 case KindTy::FPImmediate:
950 break;
951 case KindTy::Register:
952 OS << "<register " << RegName(getReg()) << ">";
953 break;
954 case KindTy::Token:
955 OS << "'" << getToken() << "'";
956 break;
957 case KindTy::SystemRegister:
958 OS << "<sysreg: " << getSysReg() << '>';
959 break;
960 case KindTy::VType:
961 OS << "<vtype: ";
962 RISCVVType::printVType(getVType(), OS);
963 OS << '>';
964 break;
965 case KindTy::FRM:
966 OS << "<frm: ";
967 roundingModeToString(getFRM());
968 OS << '>';
969 break;
970 case KindTy::Fence:
971 OS << "<fence: ";
972 OS << getFence();
973 OS << '>';
974 break;
975 case KindTy::Rlist:
976 OS << "<rlist: ";
977 RISCVZC::printRlist(Rlist.Val, OS);
978 OS << '>';
979 break;
980 case KindTy::Spimm:
981 OS << "<Spimm: ";
982 RISCVZC::printSpimm(Spimm.Val, OS);
983 OS << '>';
984 break;
985 }
986 }
987
988 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {
989 auto Op = std::make_unique<RISCVOperand>(KindTy::Token);
990 Op->Tok = Str;
991 Op->StartLoc = S;
992 Op->EndLoc = S;
993 return Op;
994 }
995
996 static std::unique_ptr<RISCVOperand>
997 createReg(unsigned RegNo, SMLoc S, SMLoc E, bool IsGPRAsFPR = false) {
998 auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
999 Op->Reg.RegNum = RegNo;
1000 Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
1001 Op->StartLoc = S;
1002 Op->EndLoc = E;
1003 return Op;
1004 }
1005
1006 static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
1007 SMLoc E, bool IsRV64) {
1008 auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
1009 Op->Imm.Val = Val;
1010 Op->Imm.IsRV64 = IsRV64;
1011 Op->StartLoc = S;
1012 Op->EndLoc = E;
1013 return Op;
1014 }
1015
1016 static std::unique_ptr<RISCVOperand> createFPImm(uint64_t Val, SMLoc S) {
1017 auto Op = std::make_unique<RISCVOperand>(KindTy::FPImmediate);
1018 Op->FPImm.Val = Val;
1019 Op->StartLoc = S;
1020 Op->EndLoc = S;
1021 return Op;
1022 }
1023
1024 static std::unique_ptr<RISCVOperand> createSysReg(StringRef Str, SMLoc S,
1025 unsigned Encoding) {
1026 auto Op = std::make_unique<RISCVOperand>(KindTy::SystemRegister);
1027 Op->SysReg.Data = Str.data();
1028 Op->SysReg.Length = Str.size();
1029 Op->SysReg.Encoding = Encoding;
1030 Op->StartLoc = S;
1031 Op->EndLoc = S;
1032 return Op;
1033 }
1034
1035 static std::unique_ptr<RISCVOperand>
1036 createFRMArg(RISCVFPRndMode::RoundingMode FRM, SMLoc S) {
1037 auto Op = std::make_unique<RISCVOperand>(KindTy::FRM);
1038 Op->FRM.FRM = FRM;
1039 Op->StartLoc = S;
1040 Op->EndLoc = S;
1041 return Op;
1042 }
1043
1044 static std::unique_ptr<RISCVOperand> createFenceArg(unsigned Val, SMLoc S) {
1045 auto Op = std::make_unique<RISCVOperand>(KindTy::Fence);
1046 Op->Fence.Val = Val;
1047 Op->StartLoc = S;
1048 Op->EndLoc = S;
1049 return Op;
1050 }
1051
1052 static std::unique_ptr<RISCVOperand> createVType(unsigned VTypeI, SMLoc S) {
1053 auto Op = std::make_unique<RISCVOperand>(KindTy::VType);
1054 Op->VType.Val = VTypeI;
1055 Op->StartLoc = S;
1056 Op->EndLoc = S;
1057 return Op;
1058 }
1059
1060 static std::unique_ptr<RISCVOperand> createRlist(unsigned RlistEncode,
1061 SMLoc S) {
1062 auto Op = std::make_unique<RISCVOperand>(KindTy::Rlist);
1063 Op->Rlist.Val = RlistEncode;
1064 Op->StartLoc = S;
1065 return Op;
1066 }
1067
1068 static std::unique_ptr<RISCVOperand> createSpimm(unsigned Spimm, SMLoc S) {
1069 auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm);
1070 Op->Spimm.Val = Spimm;
1071 Op->StartLoc = S;
1072 return Op;
1073 }
1074
1075 static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {
1076 assert(Expr && "Expr shouldn't be null!")(static_cast <bool> (Expr && "Expr shouldn't be null!"
) ? void (0) : __assert_fail ("Expr && \"Expr shouldn't be null!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1076,
__extension__ __PRETTY_FUNCTION__))
;
1077 int64_t Imm = 0;
1078 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
1079 bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
1080
1081 if (IsConstant)
1082 Inst.addOperand(
1083 MCOperand::createImm(fixImmediateForRV32(Imm, IsRV64Imm)));
1084 else
1085 Inst.addOperand(MCOperand::createExpr(Expr));
1086 }
1087
1088 // Used by the TableGen Code
1089 void addRegOperands(MCInst &Inst, unsigned N) const {
1090 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1090,
__extension__ __PRETTY_FUNCTION__))
;
1091 Inst.addOperand(MCOperand::createReg(getReg()));
1092 }
1093
1094 void addImmOperands(MCInst &Inst, unsigned N) const {
1095 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1095,
__extension__ __PRETTY_FUNCTION__))
;
1096 addExpr(Inst, getImm(), isRV64Imm());
1097 }
1098
1099 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1100 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1100,
__extension__ __PRETTY_FUNCTION__))
;
1101 if (isImm()) {
1102 addExpr(Inst, getImm(), isRV64Imm());
1103 return;
1104 }
1105
1106 int Imm = RISCVLoadFPImm::getLoadFPImm(
1107 APFloat(APFloat::IEEEdouble(), APInt(64, getFPConst())));
1108 Inst.addOperand(MCOperand::createImm(Imm));
1109 }
1110
1111 void addFenceArgOperands(MCInst &Inst, unsigned N) const {
1112 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1112,
__extension__ __PRETTY_FUNCTION__))
;
1113 Inst.addOperand(MCOperand::createImm(Fence.Val));
1114 }
1115
1116 void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1117 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1117,
__extension__ __PRETTY_FUNCTION__))
;
1118 Inst.addOperand(MCOperand::createImm(SysReg.Encoding));
1119 }
1120
1121 // Support non-canonical syntax:
1122 // "vsetivli rd, uimm, 0xabc" or "vsetvli rd, rs1, 0xabc"
1123 // "vsetivli rd, uimm, (0xc << N)" or "vsetvli rd, rs1, (0xc << N)"
1124 void addVTypeIOperands(MCInst &Inst, unsigned N) const {
1125 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1125,
__extension__ __PRETTY_FUNCTION__))
;
1126 int64_t Imm = 0;
1127 if (Kind == KindTy::Immediate) {
1128 RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
1129 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1130 (void)IsConstantImm;
1131 assert(IsConstantImm && "Invalid VTypeI Operand!")(static_cast <bool> (IsConstantImm && "Invalid VTypeI Operand!"
) ? void (0) : __assert_fail ("IsConstantImm && \"Invalid VTypeI Operand!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1131,
__extension__ __PRETTY_FUNCTION__))
;
1132 } else {
1133 Imm = getVType();
1134 }
1135 Inst.addOperand(MCOperand::createImm(Imm));
1136 }
1137
1138 void addRlistOperands(MCInst &Inst, unsigned N) const {
1139 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1139,
__extension__ __PRETTY_FUNCTION__))
;
1140 Inst.addOperand(MCOperand::createImm(Rlist.Val));
1141 }
1142
1143 void addSpimmOperands(MCInst &Inst, unsigned N) const {
1144 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1144,
__extension__ __PRETTY_FUNCTION__))
;
1145 Inst.addOperand(MCOperand::createImm(Spimm.Val));
1146 }
1147
1148 void addFRMArgOperands(MCInst &Inst, unsigned N) const {
1149 assert(N == 1 && "Invalid number of operands!")(static_cast <bool> (N == 1 && "Invalid number of operands!"
) ? void (0) : __assert_fail ("N == 1 && \"Invalid number of operands!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1149,
__extension__ __PRETTY_FUNCTION__))
;
1150 Inst.addOperand(MCOperand::createImm(getFRM()));
1151 }
1152};
1153} // end anonymous namespace.
1154
1155#define GET_REGISTER_MATCHER
1156#define GET_SUBTARGET_FEATURE_NAME
1157#define GET_MATCHER_IMPLEMENTATION
1158#define GET_MNEMONIC_SPELL_CHECKER
1159#include "RISCVGenAsmMatcher.inc"
1160
1161static MCRegister convertFPR64ToFPR16(MCRegister Reg) {
1162 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register")(static_cast <bool> (Reg >= RISCV::F0_D && Reg
<= RISCV::F31_D && "Invalid register") ? void (0)
: __assert_fail ("Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && \"Invalid register\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1162,
__extension__ __PRETTY_FUNCTION__))
;
1163 return Reg - RISCV::F0_D + RISCV::F0_H;
1164}
1165
1166static MCRegister convertFPR64ToFPR32(MCRegister Reg) {
1167 assert(Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && "Invalid register")(static_cast <bool> (Reg >= RISCV::F0_D && Reg
<= RISCV::F31_D && "Invalid register") ? void (0)
: __assert_fail ("Reg >= RISCV::F0_D && Reg <= RISCV::F31_D && \"Invalid register\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1167,
__extension__ __PRETTY_FUNCTION__))
;
1168 return Reg - RISCV::F0_D + RISCV::F0_F;
1169}
1170
1171static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg,
1172 unsigned Kind) {
1173 unsigned RegClassID;
1174 if (Kind == MCK_VRM2)
1175 RegClassID = RISCV::VRM2RegClassID;
1176 else if (Kind == MCK_VRM4)
1177 RegClassID = RISCV::VRM4RegClassID;
1178 else if (Kind == MCK_VRM8)
1179 RegClassID = RISCV::VRM8RegClassID;
1180 else
1181 return 0;
1182 return RI.getMatchingSuperReg(Reg, RISCV::sub_vrm1_0,
1183 &RISCVMCRegisterClasses[RegClassID]);
1184}
1185
1186unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
1187 unsigned Kind) {
1188 RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
1189 if (!Op.isReg())
1190 return Match_InvalidOperand;
1191
1192 MCRegister Reg = Op.getReg();
1193 bool IsRegFPR64 =
1194 RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg);
1195 bool IsRegFPR64C =
1196 RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);
1197 bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);
1198
1199 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
1200 // register from FPR64 to FPR32 or FPR64C to FPR32C if necessary.
1201 if ((IsRegFPR64 && Kind == MCK_FPR32) ||
1202 (IsRegFPR64C && Kind == MCK_FPR32C)) {
1203 Op.Reg.RegNum = convertFPR64ToFPR32(Reg);
1204 return Match_Success;
1205 }
1206 // As the parser couldn't differentiate an FPR16 from an FPR64, coerce the
1207 // register from FPR64 to FPR16 if necessary.
1208 if (IsRegFPR64 && Kind == MCK_FPR16) {
1209 Op.Reg.RegNum = convertFPR64ToFPR16(Reg);
1210 return Match_Success;
1211 }
1212 // As the parser couldn't differentiate an VRM2/VRM4/VRM8 from an VR, coerce
1213 // the register from VR to VRM2/VRM4/VRM8 if necessary.
1214 if (IsRegVR && (Kind == MCK_VRM2 || Kind == MCK_VRM4 || Kind == MCK_VRM8)) {
1215 Op.Reg.RegNum = convertVRToVRMx(*getContext().getRegisterInfo(), Reg, Kind);
1216 if (Op.Reg.RegNum == 0)
1217 return Match_InvalidOperand;
1218 return Match_Success;
1219 }
1220 return Match_InvalidOperand;
1221}
1222
1223unsigned RISCVAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1224 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
1225
1226 for (unsigned I = 0; I < MCID.NumOperands; ++I) {
1227 if (MCID.operands()[I].RegClass == RISCV::GPRPF64RegClassID) {
1228 const auto &Op = Inst.getOperand(I);
1229 assert(Op.isReg())(static_cast <bool> (Op.isReg()) ? void (0) : __assert_fail
("Op.isReg()", "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp"
, 1229, __extension__ __PRETTY_FUNCTION__))
;
1230
1231 MCRegister Reg = Op.getReg();
1232 if (((Reg.id() - RISCV::X0) & 1) != 0)
1233 return Match_RequiresEvenGPRs;
1234 }
1235 }
1236
1237 return Match_Success;
1238}
1239
1240bool RISCVAsmParser::generateImmOutOfRangeError(
1241 SMLoc ErrorLoc, int64_t Lower, int64_t Upper,
1242 const Twine &Msg = "immediate must be an integer in the range") {
1243 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
1244}
1245
1246bool RISCVAsmParser::generateImmOutOfRangeError(
1247 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
1248 const Twine &Msg = "immediate must be an integer in the range") {
1249 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1250 return generateImmOutOfRangeError(ErrorLoc, Lower, Upper, Msg);
1251}
1252
1253bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1254 OperandVector &Operands,
1255 MCStreamer &Out,
1256 uint64_t &ErrorInfo,
1257 bool MatchingInlineAsm) {
1258 MCInst Inst;
1259 FeatureBitset MissingFeatures;
1260
1261 auto Result = MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
1262 MatchingInlineAsm);
1263 switch (Result) {
1264 default:
1265 break;
1266 case Match_Success:
1267 if (validateInstruction(Inst, Operands))
1268 return true;
1269 return processInstruction(Inst, IDLoc, Operands, Out);
1270 case Match_MissingFeature: {
1271 assert(MissingFeatures.any() && "Unknown missing features!")(static_cast <bool> (MissingFeatures.any() && "Unknown missing features!"
) ? void (0) : __assert_fail ("MissingFeatures.any() && \"Unknown missing features!\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1271,
__extension__ __PRETTY_FUNCTION__))
;
1272 bool FirstFeature = true;
1273 std::string Msg = "instruction requires the following:";
1274 for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
1275 if (MissingFeatures[i]) {
1276 Msg += FirstFeature ? " " : ", ";
1277 Msg += getSubtargetFeatureName(i);
1278 FirstFeature = false;
1279 }
1280 }
1281 return Error(IDLoc, Msg);
1282 }
1283 case Match_MnemonicFail: {
1284 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
1285 std::string Suggestion = RISCVMnemonicSpellCheck(
1286 ((RISCVOperand &)*Operands[0]).getToken(), FBS, 0);
1287 return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
1288 }
1289 case Match_InvalidOperand: {
1290 SMLoc ErrorLoc = IDLoc;
1291 if (ErrorInfo != ~0ULL) {
1292 if (ErrorInfo >= Operands.size())
1293 return Error(ErrorLoc, "too few operands for instruction");
1294
1295 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1296 if (ErrorLoc == SMLoc())
1297 ErrorLoc = IDLoc;
1298 }
1299 return Error(ErrorLoc, "invalid operand for instruction");
1300 }
1301 }
1302
1303 // Handle the case when the error message is of specific type
1304 // other than the generic Match_InvalidOperand, and the
1305 // corresponding operand is missing.
1306 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
1307 SMLoc ErrorLoc = IDLoc;
1308 if (ErrorInfo != ~0ULL && ErrorInfo >= Operands.size())
1309 return Error(ErrorLoc, "too few operands for instruction");
1310 }
1311
1312 switch (Result) {
1313 default:
1314 break;
1315 case Match_RequiresEvenGPRs:
1316 return Error(IDLoc,
1317 "double precision floating point operands must use even "
1318 "numbered X register");
1319 case Match_InvalidImmXLenLI:
1320 if (isRV64()) {
1321 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1322 return Error(ErrorLoc, "operand must be a constant 64-bit integer");
1323 }
1324 return generateImmOutOfRangeError(Operands, ErrorInfo,
1325 std::numeric_limits<int32_t>::min(),
1326 std::numeric_limits<uint32_t>::max());
1327 case Match_InvalidImmZero: {
1328 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1329 return Error(ErrorLoc, "immediate must be zero");
1330 }
1331 case Match_InvalidUImmLog2XLen:
1332 if (isRV64())
1333 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
1334 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1335 case Match_InvalidUImmLog2XLenNonZero:
1336 if (isRV64())
1337 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
1338 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
1339 case Match_InvalidUImmLog2XLenHalf:
1340 if (isRV64())
1341 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1342 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
1343 case Match_InvalidUImm1:
1344 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 1) - 1);
1345 case Match_InvalidUImm2:
1346 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
1347 case Match_InvalidUImm2Lsb0:
1348 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 2,
1349 "immediate must be one of");
1350 case Match_InvalidUImm3:
1351 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
1352 case Match_InvalidUImm4:
1353 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
1354 case Match_InvalidUImm5:
1355 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
1356 case Match_InvalidUImm6:
1357 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
1358 case Match_InvalidUImm7:
1359 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
1360 case Match_InvalidUImm8:
1361 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);
1362 case Match_InvalidUImm8GE32:
1363 return generateImmOutOfRangeError(Operands, ErrorInfo, 32, (1 << 8) - 1);
1364 case Match_InvalidSImm5:
1365 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),
1366 (1 << 4) - 1);
1367 case Match_InvalidSImm6:
1368 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
1369 (1 << 5) - 1);
1370 case Match_InvalidSImm6NonZero:
1371 return generateImmOutOfRangeError(
1372 Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,
1373 "immediate must be non-zero in the range");
1374 case Match_InvalidCLUIImm:
1375 return generateImmOutOfRangeError(
1376 Operands, ErrorInfo, 1, (1 << 5) - 1,
1377 "immediate must be in [0xfffe0, 0xfffff] or");
1378 case Match_InvalidUImm7Lsb00:
1379 return generateImmOutOfRangeError(
1380 Operands, ErrorInfo, 0, (1 << 7) - 4,
1381 "immediate must be a multiple of 4 bytes in the range");
1382 case Match_InvalidUImm8Lsb00:
1383 return generateImmOutOfRangeError(
1384 Operands, ErrorInfo, 0, (1 << 8) - 4,
1385 "immediate must be a multiple of 4 bytes in the range");
1386 case Match_InvalidUImm8Lsb000:
1387 return generateImmOutOfRangeError(
1388 Operands, ErrorInfo, 0, (1 << 8) - 8,
1389 "immediate must be a multiple of 8 bytes in the range");
1390 case Match_InvalidSImm9Lsb0:
1391 return generateImmOutOfRangeError(
1392 Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
1393 "immediate must be a multiple of 2 bytes in the range");
1394 case Match_InvalidUImm9Lsb000:
1395 return generateImmOutOfRangeError(
1396 Operands, ErrorInfo, 0, (1 << 9) - 8,
1397 "immediate must be a multiple of 8 bytes in the range");
1398 case Match_InvalidUImm10Lsb00NonZero:
1399 return generateImmOutOfRangeError(
1400 Operands, ErrorInfo, 4, (1 << 10) - 4,
1401 "immediate must be a multiple of 4 bytes in the range");
1402 case Match_InvalidSImm10Lsb0000NonZero:
1403 return generateImmOutOfRangeError(
1404 Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
1405 "immediate must be a multiple of 16 bytes and non-zero in the range");
1406 case Match_InvalidSImm12:
1407 return generateImmOutOfRangeError(
1408 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
1409 "operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an "
1410 "integer in the range");
1411 case Match_InvalidSImm12Lsb0:
1412 return generateImmOutOfRangeError(
1413 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
1414 "immediate must be a multiple of 2 bytes in the range");
1415 case Match_InvalidSImm12Lsb00000:
1416 return generateImmOutOfRangeError(
1417 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 32,
1418 "immediate must be a multiple of 32 bytes in the range");
1419 case Match_InvalidSImm13Lsb0:
1420 return generateImmOutOfRangeError(
1421 Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
1422 "immediate must be a multiple of 2 bytes in the range");
1423 case Match_InvalidUImm20LUI:
1424 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
1425 "operand must be a symbol with "
1426 "%hi/%tprel_hi modifier or an integer in "
1427 "the range");
1428 case Match_InvalidUImm20AUIPC:
1429 return generateImmOutOfRangeError(
1430 Operands, ErrorInfo, 0, (1 << 20) - 1,
1431 "operand must be a symbol with a "
1432 "%pcrel_hi/%got_pcrel_hi/%tls_ie_pcrel_hi/%tls_gd_pcrel_hi modifier or "
1433 "an integer in the range");
1434 case Match_InvalidSImm21Lsb0JAL:
1435 return generateImmOutOfRangeError(
1436 Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
1437 "immediate must be a multiple of 2 bytes in the range");
1438 case Match_InvalidCSRSystemRegister: {
1439 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,
1440 "operand must be a valid system register "
1441 "name or an integer in the range");
1442 }
1443 case Match_InvalidLoadFPImm: {
1444 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1445 return Error(ErrorLoc, "operand must be a valid floating-point constant");
1446 }
1447 case Match_InvalidBareSymbol: {
1448 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1449 return Error(ErrorLoc, "operand must be a bare symbol name");
1450 }
1451 case Match_InvalidPseudoJumpSymbol: {
1452 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1453 return Error(ErrorLoc, "operand must be a valid jump target");
1454 }
1455 case Match_InvalidCallSymbol: {
1456 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1457 return Error(ErrorLoc, "operand must be a bare symbol name");
1458 }
1459 case Match_InvalidTPRelAddSymbol: {
1460 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1461 return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier");
1462 }
1463 case Match_InvalidRTZArg: {
1464 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1465 return Error(ErrorLoc, "operand must be 'rtz' floating-point rounding mode");
1466 }
1467 case Match_InvalidVTypeI: {
1468 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1469 return Error(
1470 ErrorLoc,
1471 "operand must be "
1472 "e[8|16|32|64|128|256|512|1024],m[1|2|4|8|f2|f4|f8],[ta|tu],[ma|mu]");
1473 }
1474 case Match_InvalidVMaskRegister: {
1475 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1476 return Error(ErrorLoc, "operand must be v0.t");
1477 }
1478 case Match_InvalidSImm5Plus1: {
1479 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4) + 1,
1480 (1 << 4),
1481 "immediate must be in the range");
1482 }
1483 case Match_InvalidRlist: {
1484 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1485 return Error(
1486 ErrorLoc,
1487 "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}");
1488 }
1489 case Match_InvalidSpimm: {
1490 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1491 return Error(
1492 ErrorLoc,
1493 "stack adjustment is invalid for this instruction and register list; "
1494 "refer to Zc spec for a detailed range of stack adjustment");
1495 }
1496 case Match_InvalidRnumArg: {
1497 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
1498 }
1499 case Match_InvalidRnumArg_0_7: {
1500 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 7);
1501 }
1502 case Match_InvalidRnumArg_1_10: {
1503 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, 10);
1504 }
1505 case Match_InvalidRnumArg_2_14: {
1506 return generateImmOutOfRangeError(Operands, ErrorInfo, 2, 14);
1507 }
1508 }
1509
1510 llvm_unreachable("Unknown match type detected!")::llvm::llvm_unreachable_internal("Unknown match type detected!"
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1510)
;
1511}
1512
1513// Attempts to match Name as a register (either using the default name or
1514// alternative ABI names), setting RegNo to the matching register. Upon
1515// failure, returns a non-valid MCRegister. If IsRVE, then registers x16-x31
1516// will be rejected.
1517static MCRegister matchRegisterNameHelper(bool IsRVE, StringRef Name) {
1518 MCRegister Reg = MatchRegisterName(Name);
1519 // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial
1520 // match always matches the 64-bit variant, and not the 16/32-bit one.
1521 assert(!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H))(static_cast <bool> (!(Reg >= RISCV::F0_H &&
Reg <= RISCV::F31_H)) ? void (0) : __assert_fail ("!(Reg >= RISCV::F0_H && Reg <= RISCV::F31_H)"
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1521,
__extension__ __PRETTY_FUNCTION__))
;
1522 assert(!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F))(static_cast <bool> (!(Reg >= RISCV::F0_F &&
Reg <= RISCV::F31_F)) ? void (0) : __assert_fail ("!(Reg >= RISCV::F0_F && Reg <= RISCV::F31_F)"
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1522,
__extension__ __PRETTY_FUNCTION__))
;
1523 // The default FPR register class is based on the tablegen enum ordering.
1524 static_assert(RISCV::F0_D < RISCV::F0_H, "FPR matching must be updated");
1525 static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated");
1526 if (!Reg)
1527 Reg = MatchRegisterAltName(Name);
1528 if (IsRVE && Reg >= RISCV::X16 && Reg <= RISCV::X31)
1529 Reg = RISCV::NoRegister;
1530 return Reg;
1531}
1532
1533bool RISCVAsmParser::parseRegister(MCRegister &RegNo, SMLoc &StartLoc,
1534 SMLoc &EndLoc) {
1535 if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success)
1536 return Error(StartLoc, "invalid register name");
1537 return false;
1538}
1539
1540OperandMatchResultTy RISCVAsmParser::tryParseRegister(MCRegister &RegNo,
1541 SMLoc &StartLoc,
1542 SMLoc &EndLoc) {
1543 const AsmToken &Tok = getParser().getTok();
1544 StartLoc = Tok.getLoc();
1545 EndLoc = Tok.getEndLoc();
1546 StringRef Name = getLexer().getTok().getIdentifier();
1547
1548 RegNo = matchRegisterNameHelper(isRVE(), Name);
1549 if (!RegNo)
1550 return MatchOperand_NoMatch;
1551
1552 getParser().Lex(); // Eat identifier token.
1553 return MatchOperand_Success;
1554}
1555
1556OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands,
1557 bool AllowParens) {
1558 SMLoc FirstS = getLoc();
1559 bool HadParens = false;
1560 AsmToken LParen;
1561
1562 // If this is an LParen and a parenthesised register name is allowed, parse it
1563 // atomically.
1564 if (AllowParens && getLexer().is(AsmToken::LParen)) {
1565 AsmToken Buf[2];
1566 size_t ReadCount = getLexer().peekTokens(Buf);
1567 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
1568 HadParens = true;
1569 LParen = getParser().getTok();
1570 getParser().Lex(); // Eat '('
1571 }
1572 }
1573
1574 switch (getLexer().getKind()) {
1575 default:
1576 if (HadParens)
1577 getLexer().UnLex(LParen);
1578 return MatchOperand_NoMatch;
1579 case AsmToken::Identifier:
1580 StringRef Name = getLexer().getTok().getIdentifier();
1581 MCRegister RegNo = matchRegisterNameHelper(isRVE(), Name);
1582
1583 if (!RegNo) {
1584 if (HadParens)
1585 getLexer().UnLex(LParen);
1586 return MatchOperand_NoMatch;
1587 }
1588 if (HadParens)
1589 Operands.push_back(RISCVOperand::createToken("(", FirstS));
1590 SMLoc S = getLoc();
1591 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
1592 getLexer().Lex();
1593 Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
1594 }
1595
1596 if (HadParens) {
1597 getParser().Lex(); // Eat ')'
1598 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
1599 }
1600
1601 return MatchOperand_Success;
1602}
1603
1604OperandMatchResultTy
1605RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
1606 SMLoc S = getLoc();
1607 SMLoc E;
1608 const MCExpr *Res;
1609
1610 switch (getLexer().getKind()) {
1611 default:
1612 return MatchOperand_NoMatch;
1613 case AsmToken::LParen:
1614 case AsmToken::Minus:
1615 case AsmToken::Plus:
1616 case AsmToken::Exclaim:
1617 case AsmToken::Tilde:
1618 case AsmToken::Integer:
1619 case AsmToken::String: {
1620 if (getParser().parseExpression(Res, E))
1621 return MatchOperand_ParseFail;
1622
1623 auto *CE = dyn_cast<MCConstantExpr>(Res);
1624 if (CE) {
1625 int64_t Imm = CE->getValue();
1626 if (isUInt<7>(Imm)) {
1627 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1628 return MatchOperand_Success;
1629 }
1630 }
1631
1632 break;
1633 }
1634 case AsmToken::Identifier: {
1635 StringRef Identifier;
1636 if (getParser().parseIdentifier(Identifier))
1637 return MatchOperand_ParseFail;
1638
1639 auto Opcode = RISCVInsnOpcode::lookupRISCVOpcodeByName(Identifier);
1640 if (Opcode) {
1641 assert(isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 &&(static_cast <bool> (isUInt<7>(Opcode->Value) &&
(Opcode->Value & 0x3) == 3 && "Unexpected opcode"
) ? void (0) : __assert_fail ("isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 && \"Unexpected opcode\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1642,
__extension__ __PRETTY_FUNCTION__))
1642 "Unexpected opcode")(static_cast <bool> (isUInt<7>(Opcode->Value) &&
(Opcode->Value & 0x3) == 3 && "Unexpected opcode"
) ? void (0) : __assert_fail ("isUInt<7>(Opcode->Value) && (Opcode->Value & 0x3) == 3 && \"Unexpected opcode\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 1642,
__extension__ __PRETTY_FUNCTION__))
;
1643 Res = MCConstantExpr::create(Opcode->Value, getContext());
1644 E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
1645 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1646 return MatchOperand_Success;
1647 }
1648
1649 break;
1650 }
1651 case AsmToken::Percent:
1652 break;
1653 }
1654
1655 generateImmOutOfRangeError(S, 0, 127,
1656 "opcode must be a valid opcode name or an "
1657 "immediate in the range");
1658 return MatchOperand_ParseFail;
1659}
1660
1661OperandMatchResultTy
1662RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
1663 SMLoc S = getLoc();
1664 SMLoc E;
1665 const MCExpr *Res;
1666
1667 switch (getLexer().getKind()) {
1668 default:
1669 return MatchOperand_NoMatch;
1670 case AsmToken::LParen:
1671 case AsmToken::Minus:
1672 case AsmToken::Plus:
1673 case AsmToken::Exclaim:
1674 case AsmToken::Tilde:
1675 case AsmToken::Integer:
1676 case AsmToken::String: {
1677 if (getParser().parseExpression(Res, E))
1678 return MatchOperand_ParseFail;
1679
1680 auto *CE = dyn_cast<MCConstantExpr>(Res);
1681 if (CE) {
1682 int64_t Imm = CE->getValue();
1683 if (Imm >= 0 && Imm <= 2) {
1684 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1685 return MatchOperand_Success;
1686 }
1687 }
1688
1689 break;
1690 }
1691 case AsmToken::Identifier: {
1692 StringRef Identifier;
1693 if (getParser().parseIdentifier(Identifier))
1694 return MatchOperand_ParseFail;
1695
1696 unsigned Opcode;
1697 if (Identifier == "C0")
1698 Opcode = 0;
1699 else if (Identifier == "C1")
1700 Opcode = 1;
1701 else if (Identifier == "C2")
1702 Opcode = 2;
1703 else
1704 break;
1705
1706 Res = MCConstantExpr::create(Opcode, getContext());
1707 E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
1708 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1709 return MatchOperand_Success;
1710 }
1711 case AsmToken::Percent: {
1712 // Discard operand with modifier.
1713 break;
1714 }
1715 }
1716
1717 generateImmOutOfRangeError(S, 0, 2,
1718 "opcode must be a valid opcode name or an "
1719 "immediate in the range");
1720 return MatchOperand_ParseFail;
1721}
1722
1723OperandMatchResultTy
1724RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
1725 SMLoc S = getLoc();
1726 const MCExpr *Res;
1727
1728 switch (getLexer().getKind()) {
1729 default:
1730 return MatchOperand_NoMatch;
1731 case AsmToken::LParen:
1732 case AsmToken::Minus:
1733 case AsmToken::Plus:
1734 case AsmToken::Exclaim:
1735 case AsmToken::Tilde:
1736 case AsmToken::Integer:
1737 case AsmToken::String: {
1738 if (getParser().parseExpression(Res))
1739 return MatchOperand_ParseFail;
1740
1741 auto *CE = dyn_cast<MCConstantExpr>(Res);
1742 if (CE) {
1743 int64_t Imm = CE->getValue();
1744 if (isUInt<12>(Imm)) {
1745 auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
1746 // Accept an immediate representing a named or un-named Sys Reg
1747 // if the range is valid, regardless of the required features.
1748 Operands.push_back(
1749 RISCVOperand::createSysReg(SysReg ? SysReg->Name : "", S, Imm));
1750 return MatchOperand_Success;
1751 }
1752 }
1753
1754 generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1755 return MatchOperand_ParseFail;
1756 }
1757 case AsmToken::Identifier: {
1758 StringRef Identifier;
1759 if (getParser().parseIdentifier(Identifier))
1760 return MatchOperand_ParseFail;
1761
1762 auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1763 if (!SysReg)
1764 SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);
1765 if (!SysReg)
1766 if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
1767 Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
1768 SysReg->Name + "'");
1769
1770 // Accept a named Sys Reg if the required features are present.
1771 if (SysReg) {
1772 if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits())) {
1773 Error(S, "system register use requires an option to be enabled");
1774 return MatchOperand_ParseFail;
1775 }
1776 Operands.push_back(
1777 RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
1778 return MatchOperand_Success;
1779 }
1780
1781 generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
1782 "operand must be a valid system register name "
1783 "or an integer in the range");
1784 return MatchOperand_ParseFail;
1785 }
1786 case AsmToken::Percent: {
1787 // Discard operand with modifier.
1788 generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
1789 return MatchOperand_ParseFail;
1790 }
1791 }
1792
1793 return MatchOperand_NoMatch;
1794}
1795
1796OperandMatchResultTy RISCVAsmParser::parseFPImm(OperandVector &Operands) {
1797 SMLoc S = getLoc();
1798
1799 // Parse special floats (inf/nan/min) representation.
1800 if (getTok().is(AsmToken::Identifier)) {
1801 StringRef Identifier = getTok().getIdentifier();
1802 if (Identifier.compare_insensitive("inf") == 0) {
1803 Operands.push_back(
1804 RISCVOperand::createImm(MCConstantExpr::create(30, getContext()), S,
1805 getTok().getEndLoc(), isRV64()));
1806 } else if (Identifier.compare_insensitive("nan") == 0) {
1807 Operands.push_back(
1808 RISCVOperand::createImm(MCConstantExpr::create(31, getContext()), S,
1809 getTok().getEndLoc(), isRV64()));
1810 } else if (Identifier.compare_insensitive("min") == 0) {
1811 Operands.push_back(
1812 RISCVOperand::createImm(MCConstantExpr::create(1, getContext()), S,
1813 getTok().getEndLoc(), isRV64()));
1814 } else {
1815 TokError("invalid floating point literal");
1816 return MatchOperand_ParseFail;
1817 }
1818
1819 Lex(); // Eat the token.
1820
1821 return MatchOperand_Success;
1822 }
1823
1824 // Handle negation, as that still comes through as a separate token.
1825 bool IsNegative = parseOptionalToken(AsmToken::Minus);
1826
1827 const AsmToken &Tok = getTok();
1828 if (!Tok.is(AsmToken::Real)) {
1829 TokError("invalid floating point immediate");
1830 return MatchOperand_ParseFail;
1831 }
1832
1833 // Parse FP representation.
1834 APFloat RealVal(APFloat::IEEEdouble());
1835 auto StatusOrErr =
1836 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
1837 if (errorToBool(StatusOrErr.takeError())) {
1838 TokError("invalid floating point representation");
1839 return MatchOperand_ParseFail;
1840 }
1841
1842 if (IsNegative)
1843 RealVal.changeSign();
1844
1845 Operands.push_back(RISCVOperand::createFPImm(
1846 RealVal.bitcastToAPInt().getZExtValue(), S));
1847
1848 Lex(); // Eat the token.
1849
1850 return MatchOperand_Success;
1851}
1852
1853OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
1854 SMLoc S = getLoc();
1855 SMLoc E;
1856 const MCExpr *Res;
1857
1858 switch (getLexer().getKind()) {
1859 default:
1860 return MatchOperand_NoMatch;
1861 case AsmToken::LParen:
1862 case AsmToken::Dot:
1863 case AsmToken::Minus:
1864 case AsmToken::Plus:
1865 case AsmToken::Exclaim:
1866 case AsmToken::Tilde:
1867 case AsmToken::Integer:
1868 case AsmToken::String:
1869 case AsmToken::Identifier:
1870 if (getParser().parseExpression(Res, E))
1871 return MatchOperand_ParseFail;
1872 break;
1873 case AsmToken::Percent:
1874 return parseOperandWithModifier(Operands);
1875 }
1876
1877 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1878 return MatchOperand_Success;
1879}
1880
1881OperandMatchResultTy
1882RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
1883 SMLoc S = getLoc();
1884 SMLoc E;
1885
1886 if (parseToken(AsmToken::Percent, "expected '%' for operand modifier"))
1887 return MatchOperand_ParseFail;
1888
1889 if (getLexer().getKind() != AsmToken::Identifier) {
1890 Error(getLoc(), "expected valid identifier for operand modifier");
1891 return MatchOperand_ParseFail;
1892 }
1893 StringRef Identifier = getParser().getTok().getIdentifier();
1894 RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier);
1895 if (VK == RISCVMCExpr::VK_RISCV_Invalid) {
1896 Error(getLoc(), "unrecognized operand modifier");
1897 return MatchOperand_ParseFail;
1898 }
1899
1900 getParser().Lex(); // Eat the identifier
1901 if (parseToken(AsmToken::LParen, "expected '('"))
1902 return MatchOperand_ParseFail;
1903
1904 const MCExpr *SubExpr;
1905 if (getParser().parseParenExpression(SubExpr, E)) {
1906 return MatchOperand_ParseFail;
1907 }
1908
1909 const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
1910 Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
1911 return MatchOperand_Success;
1912}
1913
1914OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
1915 SMLoc S = getLoc();
1916 const MCExpr *Res;
1917
1918 if (getLexer().getKind() != AsmToken::Identifier)
1919 return MatchOperand_NoMatch;
1920
1921 StringRef Identifier;
1922 AsmToken Tok = getLexer().getTok();
1923
1924 if (getParser().parseIdentifier(Identifier))
1925 return MatchOperand_ParseFail;
1926
1927 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
1928
1929 if (Identifier.consume_back("@plt")) {
1930 Error(getLoc(), "'@plt' operand not valid for instruction");
1931 return MatchOperand_ParseFail;
1932 }
1933
1934 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1935
1936 if (Sym->isVariable()) {
1937 const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1938 if (!isa<MCSymbolRefExpr>(V)) {
1939 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1940 return MatchOperand_NoMatch;
1941 }
1942 Res = V;
1943 } else
1944 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1945
1946 MCBinaryExpr::Opcode Opcode;
1947 switch (getLexer().getKind()) {
1948 default:
1949 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1950 return MatchOperand_Success;
1951 case AsmToken::Plus:
1952 Opcode = MCBinaryExpr::Add;
1953 getLexer().Lex();
1954 break;
1955 case AsmToken::Minus:
1956 Opcode = MCBinaryExpr::Sub;
1957 getLexer().Lex();
1958 break;
1959 }
1960
1961 const MCExpr *Expr;
1962 if (getParser().parseExpression(Expr, E))
1963 return MatchOperand_ParseFail;
1964 Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext());
1965 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1966 return MatchOperand_Success;
1967}
1968
1969OperandMatchResultTy RISCVAsmParser::parseCallSymbol(OperandVector &Operands) {
1970 SMLoc S = getLoc();
1971 const MCExpr *Res;
1972
1973 if (getLexer().getKind() != AsmToken::Identifier)
1974 return MatchOperand_NoMatch;
1975
1976 // Avoid parsing the register in `call rd, foo` as a call symbol.
1977 if (getLexer().peekTok().getKind() != AsmToken::EndOfStatement)
1978 return MatchOperand_NoMatch;
1979
1980 StringRef Identifier;
1981 if (getParser().parseIdentifier(Identifier))
1982 return MatchOperand_ParseFail;
1983
1984 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
1985
1986 RISCVMCExpr::VariantKind Kind = RISCVMCExpr::VK_RISCV_CALL;
1987 if (Identifier.consume_back("@plt"))
1988 Kind = RISCVMCExpr::VK_RISCV_CALL_PLT;
1989
1990 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1991 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1992 Res = RISCVMCExpr::create(Res, Kind, getContext());
1993 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1994 return MatchOperand_Success;
1995}
1996
1997OperandMatchResultTy
1998RISCVAsmParser::parsePseudoJumpSymbol(OperandVector &Operands) {
1999 SMLoc S = getLoc();
2000 SMLoc E;
2001 const MCExpr *Res;
2002
2003 if (getParser().parseExpression(Res, E))
2004 return MatchOperand_ParseFail;
2005
2006 if (Res->getKind() != MCExpr::ExprKind::SymbolRef ||
2007 cast<MCSymbolRefExpr>(Res)->getKind() ==
2008 MCSymbolRefExpr::VariantKind::VK_PLT) {
2009 Error(S, "operand must be a valid jump target");
2010 return MatchOperand_ParseFail;
2011 }
2012
2013 Res = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, getContext());
2014 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
2015 return MatchOperand_Success;
2016}
2017
2018OperandMatchResultTy RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
2019 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
2020 // both being acceptable forms. When parsing `jal ra, foo` this function
2021 // will be called for the `ra` register operand in an attempt to match the
2022 // single-operand alias. parseJALOffset must fail for this case. It would
2023 // seem logical to try parse the operand using parseImmediate and return
2024 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
2025 // the second form rather than the first). We can't do this as there's no
2026 // way of rewinding the lexer state. Instead, return NoMatch if this operand
2027 // is an identifier and is followed by a comma.
2028 if (getLexer().is(AsmToken::Identifier) &&
2029 getLexer().peekTok().is(AsmToken::Comma))
2030 return MatchOperand_NoMatch;
2031
2032 return parseImmediate(Operands);
2033}
2034
2035OperandMatchResultTy RISCVAsmParser::parseVTypeI(OperandVector &Operands) {
2036 SMLoc S = getLoc();
2037 if (getLexer().isNot(AsmToken::Identifier))
2038 return MatchOperand_NoMatch;
2039
2040 SmallVector<AsmToken, 7> VTypeIElements;
2041 // Put all the tokens for vtypei operand into VTypeIElements vector.
2042 while (getLexer().isNot(AsmToken::EndOfStatement)) {
2043 VTypeIElements.push_back(getLexer().getTok());
2044 getLexer().Lex();
2045 if (getLexer().is(AsmToken::EndOfStatement))
2046 break;
2047 if (getLexer().isNot(AsmToken::Comma))
2048 goto MatchFail;
2049 AsmToken Comma = getLexer().getTok();
2050 VTypeIElements.push_back(Comma);
2051 getLexer().Lex();
2052 }
2053
2054 if (VTypeIElements.size() == 7) {
2055 // The VTypeIElements layout is:
2056 // SEW comma LMUL comma TA comma MA
2057 // 0 1 2 3 4 5 6
2058 StringRef Name = VTypeIElements[0].getIdentifier();
2059 if (!Name.consume_front("e"))
2060 goto MatchFail;
2061 unsigned Sew;
2062 if (Name.getAsInteger(10, Sew))
2063 goto MatchFail;
2064 if (!RISCVVType::isValidSEW(Sew))
2065 goto MatchFail;
2066
2067 Name = VTypeIElements[2].getIdentifier();
2068 if (!Name.consume_front("m"))
2069 goto MatchFail;
2070 // "m" or "mf"
2071 bool Fractional = Name.consume_front("f");
2072 unsigned Lmul;
2073 if (Name.getAsInteger(10, Lmul))
2074 goto MatchFail;
2075 if (!RISCVVType::isValidLMUL(Lmul, Fractional))
2076 goto MatchFail;
2077
2078 // ta or tu
2079 Name = VTypeIElements[4].getIdentifier();
2080 bool TailAgnostic;
2081 if (Name == "ta")
2082 TailAgnostic = true;
2083 else if (Name == "tu")
2084 TailAgnostic = false;
2085 else
2086 goto MatchFail;
2087
2088 // ma or mu
2089 Name = VTypeIElements[6].getIdentifier();
2090 bool MaskAgnostic;
2091 if (Name == "ma")
2092 MaskAgnostic = true;
2093 else if (Name == "mu")
2094 MaskAgnostic = false;
2095 else
2096 goto MatchFail;
2097
2098 RISCVII::VLMUL VLMUL = RISCVVType::encodeLMUL(Lmul, Fractional);
2099
2100 unsigned VTypeI =
2101 RISCVVType::encodeVTYPE(VLMUL, Sew, TailAgnostic, MaskAgnostic);
2102 Operands.push_back(RISCVOperand::createVType(VTypeI, S));
2103 return MatchOperand_Success;
2104 }
2105
2106// If NoMatch, unlex all the tokens that comprise a vtypei operand
2107MatchFail:
2108 while (!VTypeIElements.empty())
2109 getLexer().UnLex(VTypeIElements.pop_back_val());
2110 return MatchOperand_NoMatch;
2111}
2112
2113OperandMatchResultTy RISCVAsmParser::parseMaskReg(OperandVector &Operands) {
2114 if (getLexer().isNot(AsmToken::Identifier))
2115 return MatchOperand_NoMatch;
2116
2117 StringRef Name = getLexer().getTok().getIdentifier();
2118 if (!Name.consume_back(".t")) {
2119 Error(getLoc(), "expected '.t' suffix");
2120 return MatchOperand_ParseFail;
2121 }
2122 MCRegister RegNo = matchRegisterNameHelper(isRVE(), Name);
2123
2124 if (!RegNo)
2125 return MatchOperand_NoMatch;
2126 if (RegNo != RISCV::V0)
2127 return MatchOperand_NoMatch;
2128 SMLoc S = getLoc();
2129 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
2130 getLexer().Lex();
2131 Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
2132 return MatchOperand_Success;
2133}
2134
2135OperandMatchResultTy RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) {
2136 if (getLexer().isNot(AsmToken::Identifier))
2137 return MatchOperand_NoMatch;
2138
2139 StringRef Name = getLexer().getTok().getIdentifier();
2140 MCRegister RegNo = matchRegisterNameHelper(isRVE(), Name);
2141
2142 if (!RegNo)
2143 return MatchOperand_NoMatch;
2144 SMLoc S = getLoc();
2145 SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
2146 getLexer().Lex();
2147 Operands.push_back(RISCVOperand::createReg(
2148 RegNo, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
2149 return MatchOperand_Success;
2150}
2151
2152OperandMatchResultTy RISCVAsmParser::parseFRMArg(OperandVector &Operands) {
2153 if (getLexer().isNot(AsmToken::Identifier)) {
2154 TokError("operand must be a valid floating point rounding mode mnemonic");
2155 return MatchOperand_ParseFail;
2156 }
2157
2158 StringRef Str = getLexer().getTok().getIdentifier();
2159 RISCVFPRndMode::RoundingMode FRM = RISCVFPRndMode::stringToRoundingMode(Str);
2160
2161 if (FRM == RISCVFPRndMode::Invalid) {
2162 TokError("operand must be a valid floating point rounding mode mnemonic");
2163 return MatchOperand_ParseFail;
2164 }
2165
2166 Operands.push_back(RISCVOperand::createFRMArg(FRM, getLoc()));
2167 Lex(); // Eat identifier token.
2168 return MatchOperand_Success;
2169}
2170
2171OperandMatchResultTy RISCVAsmParser::parseFenceArg(OperandVector &Operands) {
2172 const AsmToken &Tok = getLexer().getTok();
2173
2174 if (Tok.is(AsmToken::Integer)) {
2175 if (Tok.getIntVal() != 0)
2176 goto ParseFail;
2177
2178 Operands.push_back(RISCVOperand::createFenceArg(0, getLoc()));
2179 Lex();
2180 return MatchOperand_Success;
2181 }
2182
2183 if (Tok.is(AsmToken::Identifier)) {
2184 StringRef Str = Tok.getIdentifier();
2185
2186 // Letters must be unique, taken from 'iorw', and in ascending order. This
2187 // holds as long as each individual character is one of 'iorw' and is
2188 // greater than the previous character.
2189 unsigned Imm = 0;
2190 bool Valid = true;
2191 char Prev = '\0';
2192 for (char c : Str) {
2193 switch (c) {
2194 default:
2195 Valid = false;
2196 break;
2197 case 'i':
2198 Imm |= RISCVFenceField::I;
2199 break;
2200 case 'o':
2201 Imm |= RISCVFenceField::O;
2202 break;
2203 case 'r':
2204 Imm |= RISCVFenceField::R;
2205 break;
2206 case 'w':
2207 Imm |= RISCVFenceField::W;
2208 break;
2209 }
2210
2211 if (c <= Prev) {
2212 Valid = false;
2213 break;
2214 }
2215 Prev = c;
2216 }
2217
2218 if (!Valid)
2219 goto ParseFail;
2220
2221 Operands.push_back(RISCVOperand::createFenceArg(Imm, getLoc()));
2222 Lex();
2223 return MatchOperand_Success;
2224 }
2225
2226ParseFail:
2227 TokError("operand must be formed of letters selected in-order from 'iorw' "
2228 "or be 0");
2229 return MatchOperand_ParseFail;
2230}
2231
2232OperandMatchResultTy
2233RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
2234 if (parseToken(AsmToken::LParen, "expected '('"))
2235 return MatchOperand_ParseFail;
2236 Operands.push_back(RISCVOperand::createToken("(", getLoc()));
2237
2238 if (parseRegister(Operands) != MatchOperand_Success) {
2239 Error(getLoc(), "expected register");
2240 return MatchOperand_ParseFail;
2241 }
2242
2243 if (parseToken(AsmToken::RParen, "expected ')'"))
2244 return MatchOperand_ParseFail;
2245 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
2246
2247 return MatchOperand_Success;
2248}
2249
2250OperandMatchResultTy
2251RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {
2252 // Atomic operations such as lr.w, sc.w, and amo*.w accept a "memory operand"
2253 // as one of their register operands, such as `(a0)`. This just denotes that
2254 // the register (in this case `a0`) contains a memory address.
2255 //
2256 // Normally, we would be able to parse these by putting the parens into the
2257 // instruction string. However, GNU as also accepts a zero-offset memory
2258 // operand (such as `0(a0)`), and ignores the 0. Normally this would be parsed
2259 // with parseImmediate followed by parseMemOpBaseReg, but these instructions
2260 // do not accept an immediate operand, and we do not want to add a "dummy"
2261 // operand that is silently dropped.
2262 //
2263 // Instead, we use this custom parser. This will: allow (and discard) an
2264 // offset if it is zero; require (and discard) parentheses; and add only the
2265 // parsed register operand to `Operands`.
2266 //
2267 // These operands are printed with RISCVInstPrinter::printZeroOffsetMemOp,
2268 // which will only print the register surrounded by parentheses (which GNU as
2269 // also uses as its canonical representation for these operands).
2270 std::unique_ptr<RISCVOperand> OptionalImmOp;
2271
2272 if (getLexer().isNot(AsmToken::LParen)) {
2273 // Parse an Integer token. We do not accept arbritrary constant expressions
2274 // in the offset field (because they may include parens, which complicates
2275 // parsing a lot).
2276 int64_t ImmVal;
2277 SMLoc ImmStart = getLoc();
2278 if (getParser().parseIntToken(ImmVal,
2279 "expected '(' or optional integer offset"))
2280 return MatchOperand_ParseFail;
2281
2282 // Create a RISCVOperand for checking later (so the error messages are
2283 // nicer), but we don't add it to Operands.
2284 SMLoc ImmEnd = getLoc();
2285 OptionalImmOp =
2286 RISCVOperand::createImm(MCConstantExpr::create(ImmVal, getContext()),
2287 ImmStart, ImmEnd, isRV64());
2288 }
2289
2290 if (parseToken(AsmToken::LParen,
2291 OptionalImmOp ? "expected '(' after optional integer offset"
2292 : "expected '(' or optional integer offset"))
2293 return MatchOperand_ParseFail;
2294
2295 if (parseRegister(Operands) != MatchOperand_Success) {
2296 Error(getLoc(), "expected register");
2297 return MatchOperand_ParseFail;
2298 }
2299
2300 if (parseToken(AsmToken::RParen, "expected ')'"))
2301 return MatchOperand_ParseFail;
2302
2303 // Deferred Handling of non-zero offsets. This makes the error messages nicer.
2304 if (OptionalImmOp && !OptionalImmOp->isImmZero()) {
2305 Error(OptionalImmOp->getStartLoc(), "optional integer offset must be 0",
2306 SMRange(OptionalImmOp->getStartLoc(), OptionalImmOp->getEndLoc()));
2307 return MatchOperand_ParseFail;
2308 }
2309
2310 return MatchOperand_Success;
2311}
2312
2313OperandMatchResultTy RISCVAsmParser::parseReglist(OperandVector &Operands) {
2314 // Rlist: {ra [, s0[-sN]]}
2315 // XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
2316 SMLoc S = getLoc();
2317
2318 if (parseToken(AsmToken::LCurly, "register list must start with '{'"))
2319 return MatchOperand_ParseFail;
2320
2321 bool IsEABI = isRVE();
2322
2323 if (getLexer().isNot(AsmToken::Identifier)) {
2324 Error(getLoc(), "register list must start from 'ra' or 'x1'");
2325 return MatchOperand_ParseFail;
2326 }
2327
2328 StringRef RegName = getLexer().getTok().getIdentifier();
2329 MCRegister RegStart = matchRegisterNameHelper(IsEABI, RegName);
2330 MCRegister RegEnd;
2331 if (RegStart != RISCV::X1) {
2332 Error(getLoc(), "register list must start from 'ra' or 'x1'");
2333 return MatchOperand_ParseFail;
2334 }
2335 getLexer().Lex();
2336
2337 // parse case like ,s0
2338 if (getLexer().is(AsmToken::Comma)) {
2339 getLexer().Lex();
2340 if (getLexer().isNot(AsmToken::Identifier)) {
2341 Error(getLoc(), "invalid register");
2342 return MatchOperand_ParseFail;
2343 }
2344 StringRef RegName = getLexer().getTok().getIdentifier();
2345 RegStart = matchRegisterNameHelper(IsEABI, RegName);
2346 if (!RegStart) {
2347 Error(getLoc(), "invalid register");
2348 return MatchOperand_ParseFail;
2349 }
2350 if (RegStart != RISCV::X8) {
2351 Error(getLoc(), "continuous register list must start from 's0' or 'x8'");
2352 return MatchOperand_ParseFail;
2353 }
2354 getLexer().Lex(); // eat reg
2355 }
2356
2357 // parse case like -s1
2358 if (getLexer().is(AsmToken::Minus)) {
2359 getLexer().Lex();
2360 StringRef EndName = getLexer().getTok().getIdentifier();
2361 // FIXME: the register mapping and checks of EABI is wrong
2362 RegEnd = matchRegisterNameHelper(IsEABI, EndName);
2363 if (!RegEnd) {
2364 Error(getLoc(), "invalid register");
2365 return MatchOperand_ParseFail;
2366 }
2367 if (IsEABI && RegEnd != RISCV::X9) {
2368 Error(getLoc(), "contiguous register list of EABI can only be 's0-s1' or "
2369 "'x8-x9' pair");
2370 return MatchOperand_ParseFail;
2371 }
2372 getLexer().Lex();
2373 }
2374
2375 if (!IsEABI) {
2376 // parse extra part like ', x18[-x20]' for XRegList
2377 if (getLexer().is(AsmToken::Comma)) {
2378 if (RegEnd != RISCV::X9) {
2379 Error(
2380 getLoc(),
2381 "first contiguous registers pair of register list must be 'x8-x9'");
2382 return MatchOperand_ParseFail;
2383 }
2384
2385 // parse ', x18' for extra part
2386 getLexer().Lex();
2387 if (getLexer().isNot(AsmToken::Identifier)) {
2388 Error(getLoc(), "invalid register");
2389 return MatchOperand_ParseFail;
2390 }
2391 StringRef EndName = getLexer().getTok().getIdentifier();
2392 if (MatchRegisterName(EndName) != RISCV::X18) {
2393 Error(getLoc(), "second contiguous registers pair of register list "
2394 "must start from 'x18'");
2395 return MatchOperand_ParseFail;
2396 }
2397 getLexer().Lex();
2398
2399 // parse '-x20' for extra part
2400 if (getLexer().is(AsmToken::Minus)) {
2401 getLexer().Lex();
2402 if (getLexer().isNot(AsmToken::Identifier)) {
2403 Error(getLoc(), "invalid register");
2404 return MatchOperand_ParseFail;
2405 }
2406 EndName = getLexer().getTok().getIdentifier();
2407 if (MatchRegisterName(EndName) == RISCV::NoRegister) {
2408 Error(getLoc(), "invalid register");
2409 return MatchOperand_ParseFail;
2410 }
2411 getLexer().Lex();
2412 }
2413 RegEnd = MatchRegisterName(EndName);
2414 }
2415 }
2416
2417 if (RegEnd == RISCV::X26) {
2418 Error(getLoc(), "invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2419 "x18-x26} is not supported");
2420 return MatchOperand_ParseFail;
2421 }
2422
2423 if (parseToken(AsmToken::RCurly, "register list must end with '}'"))
2424 return MatchOperand_ParseFail;
2425
2426 if (RegEnd == RISCV::NoRegister)
2427 RegEnd = RegStart;
2428
2429 auto Encode = RISCVZC::encodeRlist(RegEnd, IsEABI);
2430 if (Encode == 16) {
2431 Error(S, "invalid register list");
2432 return MatchOperand_ParseFail;
2433 }
2434 Operands.push_back(RISCVOperand::createRlist(Encode, S));
2435
2436 return MatchOperand_Success;
2437}
2438
2439OperandMatchResultTy RISCVAsmParser::parseZcmpSpimm(OperandVector &Operands) {
2440 if (getLexer().is(AsmToken::Minus))
2441 getLexer().Lex();
2442
2443 SMLoc S = getLoc();
2444 int64_t StackAdjustment = getLexer().getTok().getIntVal();
2445 unsigned Spimm = 0;
2446 unsigned RlistVal = static_cast<RISCVOperand *>(Operands[1].get())->Rlist.Val;
2447
2448 bool IsEABI = isRVE();
2449 if (!RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64(), IsEABI))
2450 return MatchOperand_NoMatch;
2451 Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S));
2452 getLexer().Lex();
2453 return MatchOperand_Success;
2454}
2455
2456/// Looks at a token type and creates the relevant operand from this
2457/// information, adding to Operands. If operand was parsed, returns false, else
2458/// true.
2459bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2460 // Check if the current operand has a custom associated parser, if so, try to
2461 // custom parse the operand, or fallback to the general approach.
2462 OperandMatchResultTy Result =
2463 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
2464 if (Result == MatchOperand_Success)
2465 return false;
2466 if (Result == MatchOperand_ParseFail)
2467 return true;
2468
2469 // Attempt to parse token as a register.
2470 if (parseRegister(Operands, true) == MatchOperand_Success)
2471 return false;
2472
2473 // Attempt to parse token as an immediate
2474 if (parseImmediate(Operands) == MatchOperand_Success) {
2475 // Parse memory base register if present
2476 if (getLexer().is(AsmToken::LParen))
2477 return parseMemOpBaseReg(Operands) != MatchOperand_Success;
2478 return false;
2479 }
2480
2481 // Finally we have exhausted all options and must declare defeat.
2482 Error(getLoc(), "unknown operand");
2483 return true;
2484}
2485
2486bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
2487 StringRef Name, SMLoc NameLoc,
2488 OperandVector &Operands) {
2489 // Ensure that if the instruction occurs when relaxation is enabled,
2490 // relocations are forced for the file. Ideally this would be done when there
2491 // is enough information to reliably determine if the instruction itself may
2492 // cause relaxations. Unfortunately instruction processing stage occurs in the
2493 // same pass as relocation emission, so it's too late to set a 'sticky bit'
2494 // for the entire file.
2495 if (getSTI().hasFeature(RISCV::FeatureRelax)) {
2496 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
2497 if (Assembler != nullptr) {
2498 RISCVAsmBackend &MAB =
2499 static_cast<RISCVAsmBackend &>(Assembler->getBackend());
2500 MAB.setForceRelocs();
2501 }
2502 }
2503
2504 // First operand is token for instruction
2505 Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
2506
2507 // If there are no more operands, then finish
2508 if (getLexer().is(AsmToken::EndOfStatement)) {
2509 getParser().Lex(); // Consume the EndOfStatement.
2510 return false;
2511 }
2512
2513 // Parse first operand
2514 if (parseOperand(Operands, Name))
2515 return true;
2516
2517 // Parse until end of statement, consuming commas between operands
2518 while (getLexer().is(AsmToken::Comma)) {
2519 // Consume comma token
2520 getLexer().Lex();
2521
2522 // Parse next operand
2523 if (parseOperand(Operands, Name))
2524 return true;
2525 }
2526
2527 if (getParser().parseEOL("unexpected token")) {
2528 getParser().eatToEndOfStatement();
2529 return true;
2530 }
2531 return false;
2532}
2533
2534bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
2535 RISCVMCExpr::VariantKind &Kind) {
2536 Kind = RISCVMCExpr::VK_RISCV_None;
2537
2538 if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
2539 Kind = RE->getKind();
2540 Expr = RE->getSubExpr();
2541 }
2542
2543 MCValue Res;
2544 MCFixup Fixup;
2545 if (Expr->evaluateAsRelocatable(Res, nullptr, &Fixup))
2546 return Res.getRefKind() == RISCVMCExpr::VK_RISCV_None;
2547 return false;
2548}
2549
2550bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
2551 // This returns false if this function recognizes the directive
2552 // regardless of whether it is successfully handles or reports an
2553 // error. Otherwise it returns true to give the generic parser a
2554 // chance at recognizing it.
2555 StringRef IDVal = DirectiveID.getString();
2556
2557 if (IDVal == ".option")
1
Assuming the condition is false
2
Taking false branch
2558 return parseDirectiveOption();
2559 if (IDVal == ".attribute")
3
Assuming the condition is true
4
Taking true branch
2560 return parseDirectiveAttribute();
5
Calling 'RISCVAsmParser::parseDirectiveAttribute'
2561 if (IDVal == ".insn")
2562 return parseDirectiveInsn(DirectiveID.getLoc());
2563 if (IDVal == ".variant_cc")
2564 return parseDirectiveVariantCC();
2565
2566 return true;
2567}
2568
2569bool RISCVAsmParser::parseDirectiveOption() {
2570 MCAsmParser &Parser = getParser();
2571 // Get the option token.
2572 AsmToken Tok = Parser.getTok();
2573
2574 // At the moment only identifiers are supported.
2575 if (parseToken(AsmToken::Identifier, "expected identifier"))
2576 return true;
2577
2578 StringRef Option = Tok.getIdentifier();
2579
2580 if (Option == "push") {
2581 if (Parser.parseEOL())
2582 return true;
2583
2584 getTargetStreamer().emitDirectiveOptionPush();
2585 pushFeatureBits();
2586 return false;
2587 }
2588
2589 if (Option == "pop") {
2590 SMLoc StartLoc = Parser.getTok().getLoc();
2591 if (Parser.parseEOL())
2592 return true;
2593
2594 getTargetStreamer().emitDirectiveOptionPop();
2595 if (popFeatureBits())
2596 return Error(StartLoc, ".option pop with no .option push");
2597
2598 return false;
2599 }
2600
2601 if (Option == "rvc") {
2602 if (Parser.parseEOL())
2603 return true;
2604
2605 getTargetStreamer().emitDirectiveOptionRVC();
2606 setFeatureBits(RISCV::FeatureStdExtC, "c");
2607 return false;
2608 }
2609
2610 if (Option == "norvc") {
2611 if (Parser.parseEOL())
2612 return true;
2613
2614 getTargetStreamer().emitDirectiveOptionNoRVC();
2615 clearFeatureBits(RISCV::FeatureStdExtC, "c");
2616 clearFeatureBits(RISCV::FeatureStdExtZca, "+experimental-zca");
2617 return false;
2618 }
2619
2620 if (Option == "pic") {
2621 if (Parser.parseEOL())
2622 return true;
2623
2624 getTargetStreamer().emitDirectiveOptionPIC();
2625 ParserOptions.IsPicEnabled = true;
2626 return false;
2627 }
2628
2629 if (Option == "nopic") {
2630 if (Parser.parseEOL())
2631 return true;
2632
2633 getTargetStreamer().emitDirectiveOptionNoPIC();
2634 ParserOptions.IsPicEnabled = false;
2635 return false;
2636 }
2637
2638 if (Option == "relax") {
2639 if (Parser.parseEOL())
2640 return true;
2641
2642 getTargetStreamer().emitDirectiveOptionRelax();
2643 setFeatureBits(RISCV::FeatureRelax, "relax");
2644 return false;
2645 }
2646
2647 if (Option == "norelax") {
2648 if (Parser.parseEOL())
2649 return true;
2650
2651 getTargetStreamer().emitDirectiveOptionNoRelax();
2652 clearFeatureBits(RISCV::FeatureRelax, "relax");
2653 return false;
2654 }
2655
2656 // Unknown option.
2657 Warning(Parser.getTok().getLoc(),
2658 "unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'relax' or "
2659 "'norelax'");
2660 Parser.eatToEndOfStatement();
2661 return false;
2662}
2663
2664/// parseDirectiveAttribute
2665/// ::= .attribute expression ',' ( expression | "string" )
2666/// ::= .attribute identifier ',' ( expression | "string" )
2667bool RISCVAsmParser::parseDirectiveAttribute() {
2668 MCAsmParser &Parser = getParser();
2669 int64_t Tag;
2670 SMLoc TagLoc;
2671 TagLoc = Parser.getTok().getLoc();
2672 if (Parser.getTok().is(AsmToken::Identifier)) {
6
Taking false branch
2673 StringRef Name = Parser.getTok().getIdentifier();
2674 std::optional<unsigned> Ret =
2675 ELFAttrs::attrTypeFromString(Name, RISCVAttrs::getRISCVAttributeTags());
2676 if (!Ret) {
2677 Error(TagLoc, "attribute name not recognised: " + Name);
2678 return false;
2679 }
2680 Tag = *Ret;
2681 Parser.Lex();
2682 } else {
2683 const MCExpr *AttrExpr;
2684
2685 TagLoc = Parser.getTok().getLoc();
2686 if (Parser.parseExpression(AttrExpr))
7
Assuming the condition is false
8
Taking false branch
2687 return true;
2688
2689 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
9
Assuming 'AttrExpr' is not a 'CastReturnType'
10
'CE' initialized to a null pointer value
2690 if (check(!CE, TagLoc, "expected numeric constant"))
11
Assuming the condition is false
12
Taking false branch
2691 return true;
2692
2693 Tag = CE->getValue();
13
Called C++ object pointer is null
2694 }
2695
2696 if (Parser.parseComma())
2697 return true;
2698
2699 StringRef StringValue;
2700 int64_t IntegerValue = 0;
2701 bool IsIntegerValue = true;
2702
2703 // RISC-V attributes have a string value if the tag number is odd
2704 // and an integer value if the tag number is even.
2705 if (Tag % 2)
2706 IsIntegerValue = false;
2707
2708 SMLoc ValueExprLoc = Parser.getTok().getLoc();
2709 if (IsIntegerValue) {
2710 const MCExpr *ValueExpr;
2711 if (Parser.parseExpression(ValueExpr))
2712 return true;
2713
2714 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
2715 if (!CE)
2716 return Error(ValueExprLoc, "expected numeric constant");
2717 IntegerValue = CE->getValue();
2718 } else {
2719 if (Parser.getTok().isNot(AsmToken::String))
2720 return Error(Parser.getTok().getLoc(), "expected string constant");
2721
2722 StringValue = Parser.getTok().getStringContents();
2723 Parser.Lex();
2724 }
2725
2726 if (Parser.parseEOL())
2727 return true;
2728
2729 if (IsIntegerValue)
2730 getTargetStreamer().emitAttribute(Tag, IntegerValue);
2731 else if (Tag != RISCVAttrs::ARCH)
2732 getTargetStreamer().emitTextAttribute(Tag, StringValue);
2733 else {
2734 StringRef Arch = StringValue;
2735 for (auto Feature : RISCVFeatureKV)
2736 if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key))
2737 clearFeatureBits(Feature.Value, Feature.Key);
2738
2739 auto ParseResult = llvm::RISCVISAInfo::parseArchString(
2740 StringValue, /*EnableExperimentalExtension=*/true,
2741 /*ExperimentalExtensionVersionCheck=*/true);
2742 if (!ParseResult) {
2743 std::string Buffer;
2744 raw_string_ostream OutputErrMsg(Buffer);
2745 handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2746 OutputErrMsg << "invalid arch name '" << Arch << "', "
2747 << ErrMsg.getMessage();
2748 });
2749
2750 return Error(ValueExprLoc, OutputErrMsg.str());
2751 }
2752 auto &ISAInfo = *ParseResult;
2753
2754 for (auto Feature : RISCVFeatureKV)
2755 if (ISAInfo->hasExtension(Feature.Key))
2756 setFeatureBits(Feature.Value, Feature.Key);
2757
2758 if (ISAInfo->getXLen() == 32)
2759 clearFeatureBits(RISCV::Feature64Bit, "64bit");
2760 else if (ISAInfo->getXLen() == 64)
2761 setFeatureBits(RISCV::Feature64Bit, "64bit");
2762 else
2763 return Error(ValueExprLoc, "bad arch string " + Arch);
2764
2765 // Then emit the arch string.
2766 getTargetStreamer().emitTextAttribute(Tag, ISAInfo->toString());
2767 }
2768
2769 return false;
2770}
2771
2772bool isValidInsnFormat(StringRef Format, bool AllowC) {
2773 return StringSwitch<bool>(Format)
2774 .Cases("r", "r4", "i", "b", "sb", "u", "j", "uj", "s", true)
2775 .Cases("cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj", AllowC)
2776 .Default(false);
2777}
2778
2779/// parseDirectiveInsn
2780/// ::= .insn [ format encoding, (operands (, operands)*) ]
2781bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
2782 MCAsmParser &Parser = getParser();
2783
2784 // Expect instruction format as identifier.
2785 StringRef Format;
2786 SMLoc ErrorLoc = Parser.getTok().getLoc();
2787 if (Parser.parseIdentifier(Format))
2788 return Error(ErrorLoc, "expected instruction format");
2789
2790 bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
2791 getSTI().hasFeature(RISCV::FeatureStdExtZca);
2792 if (!isValidInsnFormat(Format, AllowC))
2793 return Error(ErrorLoc, "invalid instruction format");
2794
2795 std::string FormatName = (".insn_" + Format).str();
2796
2797 ParseInstructionInfo Info;
2798 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands;
2799
2800 if (ParseInstruction(Info, FormatName, L, Operands))
2801 return true;
2802
2803 unsigned Opcode;
2804 uint64_t ErrorInfo;
2805 return MatchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),
2806 ErrorInfo,
2807 /*MatchingInlineAsm=*/false);
2808}
2809
2810/// parseDirectiveVariantCC
2811/// ::= .variant_cc symbol
2812bool RISCVAsmParser::parseDirectiveVariantCC() {
2813 StringRef Name;
2814 if (getParser().parseIdentifier(Name))
2815 return TokError("expected symbol name");
2816 if (parseEOL())
2817 return false;
2818 getTargetStreamer().emitDirectiveVariantCC(
2819 *getContext().getOrCreateSymbol(Name));
2820 return false;
2821}
2822
2823void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
2824 MCInst CInst;
2825 bool Res = RISCVRVC::compress(CInst, Inst, getSTI());
2826 if (Res)
2827 ++RISCVNumInstrsCompressed;
2828 S.emitInstruction((Res ? CInst : Inst), getSTI());
2829}
2830
2831void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value,
2832 MCStreamer &Out) {
2833 RISCVMatInt::InstSeq Seq =
2834 RISCVMatInt::generateInstSeq(Value, getSTI().getFeatureBits());
2835
2836 MCRegister SrcReg = RISCV::X0;
2837 for (RISCVMatInt::Inst &Inst : Seq) {
2838 switch (Inst.getOpndKind()) {
2839 case RISCVMatInt::Imm:
2840 emitToStreamer(Out,
2841 MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addImm(Inst.getImm()));
2842 break;
2843 case RISCVMatInt::RegX0:
2844 emitToStreamer(
2845 Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addReg(
2846 RISCV::X0));
2847 break;
2848 case RISCVMatInt::RegReg:
2849 emitToStreamer(
2850 Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addReg(
2851 SrcReg));
2852 break;
2853 case RISCVMatInt::RegImm:
2854 emitToStreamer(
2855 Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addImm(
2856 Inst.getImm()));
2857 break;
2858 }
2859
2860 // Only the first instruction has X0 as its source.
2861 SrcReg = DestReg;
2862 }
2863}
2864
2865void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
2866 const MCExpr *Symbol,
2867 RISCVMCExpr::VariantKind VKHi,
2868 unsigned SecondOpcode, SMLoc IDLoc,
2869 MCStreamer &Out) {
2870 // A pair of instructions for PC-relative addressing; expands to
2871 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
2872 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
2873 MCContext &Ctx = getContext();
2874
2875 MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
2876 Out.emitLabel(TmpLabel);
2877
2878 const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
2879 emitToStreamer(
2880 Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
2881
2882 const MCExpr *RefToLinkTmpLabel =
2883 RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),
2884 RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
2885
2886 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
2887 .addOperand(DestReg)
2888 .addOperand(TmpReg)
2889 .addExpr(RefToLinkTmpLabel));
2890}
2891
2892void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
2893 MCStreamer &Out) {
2894 // The load local address pseudo-instruction "lla" is used in PC-relative
2895 // addressing of local symbols:
2896 // lla rdest, symbol
2897 // expands to
2898 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
2899 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
2900 MCOperand DestReg = Inst.getOperand(0);
2901 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2902 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
2903 RISCV::ADDI, IDLoc, Out);
2904}
2905
2906void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
2907 MCStreamer &Out) {
2908 // The load address pseudo-instruction "la" is used in PC-relative and
2909 // GOT-indirect addressing of global symbols:
2910 // la rdest, symbol
2911 // expands to either (for non-PIC)
2912 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
2913 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
2914 // or (for PIC)
2915 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
2916 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
2917 MCOperand DestReg = Inst.getOperand(0);
2918 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2919 unsigned SecondOpcode;
2920 RISCVMCExpr::VariantKind VKHi;
2921 if (ParserOptions.IsPicEnabled) {
2922 SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
2923 VKHi = RISCVMCExpr::VK_RISCV_GOT_HI;
2924 } else {
2925 SecondOpcode = RISCV::ADDI;
2926 VKHi = RISCVMCExpr::VK_RISCV_PCREL_HI;
2927 }
2928 emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out);
2929}
2930
2931void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
2932 MCStreamer &Out) {
2933 // The load TLS IE address pseudo-instruction "la.tls.ie" is used in
2934 // initial-exec TLS model addressing of global symbols:
2935 // la.tls.ie rdest, symbol
2936 // expands to
2937 // TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
2938 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
2939 MCOperand DestReg = Inst.getOperand(0);
2940 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2941 unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
2942 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI,
2943 SecondOpcode, IDLoc, Out);
2944}
2945
2946void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
2947 MCStreamer &Out) {
2948 // The load TLS GD address pseudo-instruction "la.tls.gd" is used in
2949 // global-dynamic TLS model addressing of global symbols:
2950 // la.tls.gd rdest, symbol
2951 // expands to
2952 // TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
2953 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
2954 MCOperand DestReg = Inst.getOperand(0);
2955 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
2956 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI,
2957 RISCV::ADDI, IDLoc, Out);
2958}
2959
2960void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
2961 SMLoc IDLoc, MCStreamer &Out,
2962 bool HasTmpReg) {
2963 // The load/store pseudo-instruction does a pc-relative load with
2964 // a symbol.
2965 //
2966 // The expansion looks like this
2967 //
2968 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
2969 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
2970 unsigned DestRegOpIdx = HasTmpReg ? 1 : 0;
2971 MCOperand DestReg = Inst.getOperand(DestRegOpIdx);
2972 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
2973 MCOperand TmpReg = Inst.getOperand(0);
2974 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
2975 emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
2976 Opcode, IDLoc, Out);
2977}
2978
2979void RISCVAsmParser::emitPseudoExtend(MCInst &Inst, bool SignExtend,
2980 int64_t Width, SMLoc IDLoc,
2981 MCStreamer &Out) {
2982 // The sign/zero extend pseudo-instruction does two shifts, with the shift
2983 // amounts dependent on the XLEN.
2984 //
2985 // The expansion looks like this
2986 //
2987 // SLLI rd, rs, XLEN - Width
2988 // SR[A|R]I rd, rd, XLEN - Width
2989 MCOperand DestReg = Inst.getOperand(0);
2990 MCOperand SourceReg = Inst.getOperand(1);
2991
2992 unsigned SecondOpcode = SignExtend ? RISCV::SRAI : RISCV::SRLI;
2993 int64_t ShAmt = (isRV64() ? 64 : 32) - Width;
2994
2995 assert(ShAmt > 0 && "Shift amount must be non-zero.")(static_cast <bool> (ShAmt > 0 && "Shift amount must be non-zero."
) ? void (0) : __assert_fail ("ShAmt > 0 && \"Shift amount must be non-zero.\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 2995,
__extension__ __PRETTY_FUNCTION__))
;
2996
2997 emitToStreamer(Out, MCInstBuilder(RISCV::SLLI)
2998 .addOperand(DestReg)
2999 .addOperand(SourceReg)
3000 .addImm(ShAmt));
3001
3002 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
3003 .addOperand(DestReg)
3004 .addOperand(DestReg)
3005 .addImm(ShAmt));
3006}
3007
3008void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
3009 MCStreamer &Out) {
3010 if (Inst.getNumOperands() == 3) {
3011 // unmasked va >= x
3012 //
3013 // pseudoinstruction: vmsge{u}.vx vd, va, x
3014 // expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
3015 emitToStreamer(Out, MCInstBuilder(Opcode)
3016 .addOperand(Inst.getOperand(0))
3017 .addOperand(Inst.getOperand(1))
3018 .addOperand(Inst.getOperand(2))
3019 .addReg(RISCV::NoRegister));
3020 emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM)
3021 .addOperand(Inst.getOperand(0))
3022 .addOperand(Inst.getOperand(0))
3023 .addOperand(Inst.getOperand(0)));
3024 } else if (Inst.getNumOperands() == 4) {
3025 // masked va >= x, vd != v0
3026 //
3027 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t
3028 // expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
3029 assert(Inst.getOperand(0).getReg() != RISCV::V0 &&(static_cast <bool> (Inst.getOperand(0).getReg() != RISCV
::V0 && "The destination register should not be V0.")
? void (0) : __assert_fail ("Inst.getOperand(0).getReg() != RISCV::V0 && \"The destination register should not be V0.\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 3030,
__extension__ __PRETTY_FUNCTION__))
3030 "The destination register should not be V0.")(static_cast <bool> (Inst.getOperand(0).getReg() != RISCV
::V0 && "The destination register should not be V0.")
? void (0) : __assert_fail ("Inst.getOperand(0).getReg() != RISCV::V0 && \"The destination register should not be V0.\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 3030,
__extension__ __PRETTY_FUNCTION__))
;
3031 emitToStreamer(Out, MCInstBuilder(Opcode)
3032 .addOperand(Inst.getOperand(0))
3033 .addOperand(Inst.getOperand(1))
3034 .addOperand(Inst.getOperand(2))
3035 .addOperand(Inst.getOperand(3)));
3036 emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM)
3037 .addOperand(Inst.getOperand(0))
3038 .addOperand(Inst.getOperand(0))
3039 .addReg(RISCV::V0));
3040 } else if (Inst.getNumOperands() == 5 &&
3041 Inst.getOperand(0).getReg() == RISCV::V0) {
3042 // masked va >= x, vd == v0
3043 //
3044 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3045 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt
3046 assert(Inst.getOperand(0).getReg() == RISCV::V0 &&(static_cast <bool> (Inst.getOperand(0).getReg() == RISCV
::V0 && "The destination register should be V0.") ? void
(0) : __assert_fail ("Inst.getOperand(0).getReg() == RISCV::V0 && \"The destination register should be V0.\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 3047,
__extension__ __PRETTY_FUNCTION__))
3047 "The destination register should be V0.")(static_cast <bool> (Inst.getOperand(0).getReg() == RISCV
::V0 && "The destination register should be V0.") ? void
(0) : __assert_fail ("Inst.getOperand(0).getReg() == RISCV::V0 && \"The destination register should be V0.\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 3047,
__extension__ __PRETTY_FUNCTION__))
;
3048 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&(static_cast <bool> (Inst.getOperand(1).getReg() != RISCV
::V0 && "The temporary vector register should not be V0."
) ? void (0) : __assert_fail ("Inst.getOperand(1).getReg() != RISCV::V0 && \"The temporary vector register should not be V0.\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 3049,
__extension__ __PRETTY_FUNCTION__))
3049 "The temporary vector register should not be V0.")(static_cast <bool> (Inst.getOperand(1).getReg() != RISCV
::V0 && "The temporary vector register should not be V0."
) ? void (0) : __assert_fail ("Inst.getOperand(1).getReg() != RISCV::V0 && \"The temporary vector register should not be V0.\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 3049,
__extension__ __PRETTY_FUNCTION__))
;
3050 emitToStreamer(Out, MCInstBuilder(Opcode)
3051 .addOperand(Inst.getOperand(1))
3052 .addOperand(Inst.getOperand(2))
3053 .addOperand(Inst.getOperand(3))
3054 .addOperand(Inst.getOperand(4)));
3055 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3056 .addOperand(Inst.getOperand(0))
3057 .addOperand(Inst.getOperand(0))
3058 .addOperand(Inst.getOperand(1)));
3059 } else if (Inst.getNumOperands() == 5) {
3060 // masked va >= x, any vd
3061 //
3062 // pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt
3063 // expansion: vmslt{u}.vx vt, va, x; vmandn.mm vt, v0, vt; vmandn.mm vd,
3064 // vd, v0; vmor.mm vd, vt, vd
3065 assert(Inst.getOperand(1).getReg() != RISCV::V0 &&(static_cast <bool> (Inst.getOperand(1).getReg() != RISCV
::V0 && "The temporary vector register should not be V0."
) ? void (0) : __assert_fail ("Inst.getOperand(1).getReg() != RISCV::V0 && \"The temporary vector register should not be V0.\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 3066,
__extension__ __PRETTY_FUNCTION__))
3066 "The temporary vector register should not be V0.")(static_cast <bool> (Inst.getOperand(1).getReg() != RISCV
::V0 && "The temporary vector register should not be V0."
) ? void (0) : __assert_fail ("Inst.getOperand(1).getReg() != RISCV::V0 && \"The temporary vector register should not be V0.\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 3066,
__extension__ __PRETTY_FUNCTION__))
;
3067 emitToStreamer(Out, MCInstBuilder(Opcode)
3068 .addOperand(Inst.getOperand(1))
3069 .addOperand(Inst.getOperand(2))
3070 .addOperand(Inst.getOperand(3))
3071 .addReg(RISCV::NoRegister));
3072 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3073 .addOperand(Inst.getOperand(1))
3074 .addReg(RISCV::V0)
3075 .addOperand(Inst.getOperand(1)));
3076 emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM)
3077 .addOperand(Inst.getOperand(0))
3078 .addOperand(Inst.getOperand(0))
3079 .addReg(RISCV::V0));
3080 emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM)
3081 .addOperand(Inst.getOperand(0))
3082 .addOperand(Inst.getOperand(1))
3083 .addOperand(Inst.getOperand(0)));
3084 }
3085}
3086
3087bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
3088 OperandVector &Operands) {
3089 assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction")(static_cast <bool> (Inst.getOpcode() == RISCV::PseudoAddTPRel
&& "Invalid instruction") ? void (0) : __assert_fail
("Inst.getOpcode() == RISCV::PseudoAddTPRel && \"Invalid instruction\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 3089,
__extension__ __PRETTY_FUNCTION__))
;
3090 assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind")(static_cast <bool> (Inst.getOperand(2).isReg() &&
"Unexpected second operand kind") ? void (0) : __assert_fail
("Inst.getOperand(2).isReg() && \"Unexpected second operand kind\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 3090,
__extension__ __PRETTY_FUNCTION__))
;
3091 if (Inst.getOperand(2).getReg() != RISCV::X4) {
3092 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
3093 return Error(ErrorLoc, "the second input operand must be tp/x4 when using "
3094 "%tprel_add modifier");
3095 }
3096
3097 return false;
3098}
3099
3100std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
3101 return RISCVOperand::createReg(RISCV::NoRegister, llvm::SMLoc(),
3102 llvm::SMLoc());
3103}
3104
3105std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
3106 return RISCVOperand::createFRMArg(RISCVFPRndMode::RoundingMode::DYN,
3107 llvm::SMLoc());
3108}
3109
3110bool RISCVAsmParser::validateInstruction(MCInst &Inst,
3111 OperandVector &Operands) {
3112 unsigned Opcode = Inst.getOpcode();
3113
3114 if (Opcode == RISCV::PseudoVMSGEU_VX_M_T ||
3115 Opcode == RISCV::PseudoVMSGE_VX_M_T) {
3116 unsigned DestReg = Inst.getOperand(0).getReg();
3117 unsigned TempReg = Inst.getOperand(1).getReg();
3118 if (DestReg == TempReg) {
3119 SMLoc Loc = Operands.back()->getStartLoc();
3120 return Error(Loc, "The temporary vector register cannot be the same as "
3121 "the destination register.");
3122 }
3123 }
3124
3125 if (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_LWUD ||
3126 Opcode == RISCV::TH_LWD) {
3127 unsigned Rd1 = Inst.getOperand(0).getReg();
3128 unsigned Rd2 = Inst.getOperand(1).getReg();
3129 unsigned Rs1 = Inst.getOperand(2).getReg();
3130 // The encoding with rd1 == rd2 == rs1 is reserved for XTHead load pair.
3131 if (Rs1 == Rd1 && Rs1 == Rd2) {
3132 SMLoc Loc = Operands[1]->getStartLoc();
3133 return Error(Loc, "The source register and destination registers "
3134 "cannot be equal.");
3135 }
3136 }
3137
3138 if (Opcode == RISCV::CM_MVSA01) {
3139 unsigned Rd1 = Inst.getOperand(0).getReg();
3140 unsigned Rd2 = Inst.getOperand(1).getReg();
3141 if (Rd1 == Rd2) {
3142 SMLoc Loc = Operands[1]->getStartLoc();
3143 return Error(Loc, "'rs1' and 'rs2' must be different.");
3144 }
3145 }
3146
3147 bool IsTHeadMemPair32 = (Opcode == RISCV::TH_LWD ||
3148 Opcode == RISCV::TH_LWUD || Opcode == RISCV::TH_SWD);
3149 bool IsTHeadMemPair64 = (Opcode == RISCV::TH_LDD || Opcode == RISCV::TH_SDD);
3150 // The last operand of XTHeadMemPair instructions must be constant 3 or 4
3151 // depending on the data width.
3152 if (IsTHeadMemPair32 && Inst.getOperand(4).getImm() != 3) {
3153 SMLoc Loc = Operands.back()->getStartLoc();
3154 return Error(Loc, "Operand must be constant 3.");
3155 } else if (IsTHeadMemPair64 && Inst.getOperand(4).getImm() != 4) {
3156 SMLoc Loc = Operands.back()->getStartLoc();
3157 return Error(Loc, "Operand must be constant 4.");
3158 }
3159
3160 const MCInstrDesc &MCID = MII.get(Opcode);
3161 if (!(MCID.TSFlags & RISCVII::ConstraintMask))
3162 return false;
3163
3164 if (Opcode == RISCV::VC_V_XVW || Opcode == RISCV::VC_V_IVW ||
3165 Opcode == RISCV::VC_V_FVW || Opcode == RISCV::VC_V_VVW) {
3166 // Operands Opcode, Dst, uimm, Dst, Rs2, Rs1 for VC_V_XVW.
3167 unsigned VCIXDst = Inst.getOperand(0).getReg();
3168 SMLoc VCIXDstLoc = Operands[2]->getStartLoc();
3169 if (MCID.TSFlags & RISCVII::VS1Constraint) {
3170 unsigned VCIXRs1 = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
3171 if (VCIXDst == VCIXRs1)
3172 return Error(VCIXDstLoc, "The destination vector register group cannot"
3173 " overlap the source vector register group.");
3174 }
3175 if (MCID.TSFlags & RISCVII::VS2Constraint) {
3176 unsigned VCIXRs2 = Inst.getOperand(Inst.getNumOperands() - 2).getReg();
3177 if (VCIXDst == VCIXRs2)
3178 return Error(VCIXDstLoc, "The destination vector register group cannot"
3179 " overlap the source vector register group.");
3180 }
3181 return false;
3182 }
3183
3184 unsigned DestReg = Inst.getOperand(0).getReg();
3185 // Operands[1] will be the first operand, DestReg.
3186 SMLoc Loc = Operands[1]->getStartLoc();
3187 if (MCID.TSFlags & RISCVII::VS2Constraint) {
3188 unsigned CheckReg = Inst.getOperand(1).getReg();
3189 if (DestReg == CheckReg)
3190 return Error(Loc, "The destination vector register group cannot overlap"
3191 " the source vector register group.");
3192 }
3193 if ((MCID.TSFlags & RISCVII::VS1Constraint) && (Inst.getOperand(2).isReg())) {
3194 unsigned CheckReg = Inst.getOperand(2).getReg();
3195 if (DestReg == CheckReg)
3196 return Error(Loc, "The destination vector register group cannot overlap"
3197 " the source vector register group.");
3198 }
3199 if ((MCID.TSFlags & RISCVII::VMConstraint) && (DestReg == RISCV::V0)) {
3200 // vadc, vsbc are special cases. These instructions have no mask register.
3201 // The destination register could not be V0.
3202 if (Opcode == RISCV::VADC_VVM || Opcode == RISCV::VADC_VXM ||
3203 Opcode == RISCV::VADC_VIM || Opcode == RISCV::VSBC_VVM ||
3204 Opcode == RISCV::VSBC_VXM || Opcode == RISCV::VFMERGE_VFM ||
3205 Opcode == RISCV::VMERGE_VIM || Opcode == RISCV::VMERGE_VVM ||
3206 Opcode == RISCV::VMERGE_VXM)
3207 return Error(Loc, "The destination vector register group cannot be V0.");
3208
3209 // Regardless masked or unmasked version, the number of operands is the
3210 // same. For example, "viota.m v0, v2" is "viota.m v0, v2, NoRegister"
3211 // actually. We need to check the last operand to ensure whether it is
3212 // masked or not.
3213 unsigned CheckReg = Inst.getOperand(Inst.getNumOperands() - 1).getReg();
3214 assert((CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) &&(static_cast <bool> ((CheckReg == RISCV::V0 || CheckReg
== RISCV::NoRegister) && "Unexpected register for mask operand"
) ? void (0) : __assert_fail ("(CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) && \"Unexpected register for mask operand\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 3215,
__extension__ __PRETTY_FUNCTION__))
3215 "Unexpected register for mask operand")(static_cast <bool> ((CheckReg == RISCV::V0 || CheckReg
== RISCV::NoRegister) && "Unexpected register for mask operand"
) ? void (0) : __assert_fail ("(CheckReg == RISCV::V0 || CheckReg == RISCV::NoRegister) && \"Unexpected register for mask operand\""
, "llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp", 3215,
__extension__ __PRETTY_FUNCTION__))
;
3216
3217 if (DestReg == CheckReg)
3218 return Error(Loc, "The destination vector register group cannot overlap"
3219 " the mask register.");
3220 }
3221 return false;
3222}
3223
3224bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
3225 OperandVector &Operands,
3226 MCStreamer &Out) {
3227 Inst.setLoc(IDLoc);
3228
3229 switch (Inst.getOpcode()) {
3230 default:
3231 break;
3232 case RISCV::PseudoLI: {
3233 MCRegister Reg = Inst.getOperand(0).getReg();
3234 const MCOperand &Op1 = Inst.getOperand(1);
3235 if (Op1.isExpr()) {
3236 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
3237 // Just convert to an addi. This allows compatibility with gas.
3238 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
3239 .addReg(Reg)
3240 .addReg(RISCV::X0)
3241 .addExpr(Op1.getExpr()));
3242 return false;
3243 }
3244 int64_t Imm = Inst.getOperand(1).getImm();
3245 // On RV32 the immediate here can either be a signed or an unsigned
3246 // 32-bit number. Sign extension has to be performed to ensure that Imm
3247 // represents the expected signed 64-bit number.
3248 if (!isRV64())
3249 Imm = SignExtend64<32>(Imm);
3250 emitLoadImm(Reg, Imm, Out);
3251 return false;
3252 }
3253 case RISCV::PseudoLLA:
3254 emitLoadLocalAddress(Inst, IDLoc, Out);
3255 return false;
3256 case RISCV::PseudoLA:
3257 emitLoadAddress(Inst, IDLoc, Out);
3258 return false;
3259 case RISCV::PseudoLA_TLS_IE:
3260 emitLoadTLSIEAddress(Inst, IDLoc, Out);
3261 return false;
3262 case RISCV::PseudoLA_TLS_GD:
3263 emitLoadTLSGDAddress(Inst, IDLoc, Out);
3264 return false;
3265 case RISCV::PseudoLB:
3266 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
3267 return false;
3268 case RISCV::PseudoLBU:
3269 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
3270 return false;
3271 case RISCV::PseudoLH:
3272 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
3273 return false;
3274 case RISCV::PseudoLHU:
3275 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
3276 return false;
3277 case RISCV::PseudoLW:
3278 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
3279 return false;
3280 case RISCV::PseudoLWU:
3281 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
3282 return false;
3283 case RISCV::PseudoLD:
3284 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
3285 return false;
3286 case RISCV::PseudoFLH:
3287 emitLoadStoreSymbol(Inst, RISCV::FLH, IDLoc, Out, /*HasTmpReg=*/true);
3288 return false;
3289 case RISCV::PseudoFLW:
3290 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
3291 return false;
3292 case RISCV::PseudoFLD:
3293 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
3294 return false;
3295 case RISCV::PseudoSB:
3296 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
3297 return false;
3298 case RISCV::PseudoSH:
3299 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
3300 return false;
3301 case RISCV::PseudoSW:
3302 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
3303 return false;
3304 case RISCV::PseudoSD:
3305 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
3306 return false;
3307 case RISCV::PseudoFSH:
3308 emitLoadStoreSymbol(Inst, RISCV::FSH, IDLoc, Out, /*HasTmpReg=*/true);
3309 return false;
3310 case RISCV::PseudoFSW:
3311 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
3312 return false;
3313 case RISCV::PseudoFSD:
3314 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
3315 return false;
3316 case RISCV::PseudoAddTPRel:
3317 if (checkPseudoAddTPRel(Inst, Operands))
3318 return true;
3319 break;
3320 case RISCV::PseudoSEXT_B:
3321 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/8, IDLoc, Out);
3322 return false;
3323 case RISCV::PseudoSEXT_H:
3324 emitPseudoExtend(Inst, /*SignExtend=*/true, /*Width=*/16, IDLoc, Out);
3325 return false;
3326 case RISCV::PseudoZEXT_H:
3327 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/16, IDLoc, Out);
3328 return false;
3329 case RISCV::PseudoZEXT_W:
3330 emitPseudoExtend(Inst, /*SignExtend=*/false, /*Width=*/32, IDLoc, Out);
3331 return false;
3332 case RISCV::PseudoVMSGEU_VX:
3333 case RISCV::PseudoVMSGEU_VX_M:
3334 case RISCV::PseudoVMSGEU_VX_M_T:
3335 emitVMSGE(Inst, RISCV::VMSLTU_VX, IDLoc, Out);
3336 return false;
3337 case RISCV::PseudoVMSGE_VX:
3338 case RISCV::PseudoVMSGE_VX_M:
3339 case RISCV::PseudoVMSGE_VX_M_T:
3340 emitVMSGE(Inst, RISCV::VMSLT_VX, IDLoc, Out);
3341 return false;
3342 case RISCV::PseudoVMSGE_VI:
3343 case RISCV::PseudoVMSLT_VI: {
3344 // These instructions are signed and so is immediate so we can subtract one
3345 // and change the opcode.
3346 int64_t Imm = Inst.getOperand(2).getImm();
3347 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGE_VI ? RISCV::VMSGT_VI
3348 : RISCV::VMSLE_VI;
3349 emitToStreamer(Out, MCInstBuilder(Opc)
3350 .addOperand(Inst.getOperand(0))
3351 .addOperand(Inst.getOperand(1))
3352 .addImm(Imm - 1)
3353 .addOperand(Inst.getOperand(3)));
3354 return false;
3355 }
3356 case RISCV::PseudoVMSGEU_VI:
3357 case RISCV::PseudoVMSLTU_VI: {
3358 int64_t Imm = Inst.getOperand(2).getImm();
3359 // Unsigned comparisons are tricky because the immediate is signed. If the
3360 // immediate is 0 we can't just subtract one. vmsltu.vi v0, v1, 0 is always
3361 // false, but vmsle.vi v0, v1, -1 is always true. Instead we use
3362 // vmsne v0, v1, v1 which is always false.
3363 if (Imm == 0) {
3364 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3365 ? RISCV::VMSEQ_VV
3366 : RISCV::VMSNE_VV;
3367 emitToStreamer(Out, MCInstBuilder(Opc)
3368 .addOperand(Inst.getOperand(0))
3369 .addOperand(Inst.getOperand(1))
3370 .addOperand(Inst.getOperand(1))
3371 .addOperand(Inst.getOperand(3)));
3372 } else {
3373 // Other immediate values can subtract one like signed.
3374 unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI
3375 ? RISCV::VMSGTU_VI
3376 : RISCV::VMSLEU_VI;
3377 emitToStreamer(Out, MCInstBuilder(Opc)
3378 .addOperand(Inst.getOperand(0))
3379 .addOperand(Inst.getOperand(1))
3380 .addImm(Imm - 1)
3381 .addOperand(Inst.getOperand(3)));
3382 }
3383
3384 return false;
3385 }
3386 }
3387
3388 emitToStreamer(Out, Inst);
3389 return false;
3390}
3391
3392extern "C" LLVM_EXTERNAL_VISIBILITY__attribute__((visibility("default"))) void LLVMInitializeRISCVAsmParser() {
3393 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
3394 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
3395}