Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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