Bug Summary

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