Bug Summary

File:llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Warning:line 1991, 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 -disable-llvm-verifier -discard-value-names -main-file-name RISCVAsmParser.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/build-llvm/lib/Target/RISCV/AsmParser -resource-dir /usr/lib/llvm-13/lib/clang/13.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/build-llvm/lib/Target/RISCV/AsmParser -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Target/RISCV/AsmParser -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Target/RISCV -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/build-llvm/lib/Target/RISCV -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/build-llvm/include -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include -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-13/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -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 -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/build-llvm/lib/Target/RISCV/AsmParser -fdebug-prefix-map=/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c=. -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -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-2021-07-26-235520-9401-1 -x c++ /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

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

/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include/llvm/MC/MCAsmMacro.h

1//===- MCAsmMacro.h - Assembly Macros ---------------------------*- C++ -*-===//
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#ifndef LLVM_MC_MCASMMACRO_H
10#define LLVM_MC_MCASMMACRO_H
11
12#include "llvm/ADT/APInt.h"
13#include "llvm/ADT/StringRef.h"
14#include "llvm/Support/Debug.h"
15#include "llvm/Support/SMLoc.h"
16#include <vector>
17
18namespace llvm {
19
20/// Target independent representation for an assembler token.
21class AsmToken {
22public:
23 enum TokenKind {
24 // Markers
25 Eof, Error,
26
27 // String values.
28 Identifier,
29 String,
30
31 // Integer values.
32 Integer,
33 BigNum, // larger than 64 bits
34
35 // Real values.
36 Real,
37
38 // Comments
39 Comment,
40 HashDirective,
41 // No-value.
42 EndOfStatement,
43 Colon,
44 Space,
45 Plus, Minus, Tilde,
46 Slash, // '/'
47 BackSlash, // '\'
48 LParen, RParen, LBrac, RBrac, LCurly, RCurly,
49 Star, Dot, Comma, Dollar, Equal, EqualEqual,
50
51 Pipe, PipePipe, Caret,
52 Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash,
53 Less, LessEqual, LessLess, LessGreater,
54 Greater, GreaterEqual, GreaterGreater, At, MinusGreater,
55
56 // MIPS unary expression operators such as %neg.
57 PercentCall16, PercentCall_Hi, PercentCall_Lo, PercentDtprel_Hi,
58 PercentDtprel_Lo, PercentGot, PercentGot_Disp, PercentGot_Hi, PercentGot_Lo,
59 PercentGot_Ofst, PercentGot_Page, PercentGottprel, PercentGp_Rel, PercentHi,
60 PercentHigher, PercentHighest, PercentLo, PercentNeg, PercentPcrel_Hi,
61 PercentPcrel_Lo, PercentTlsgd, PercentTlsldm, PercentTprel_Hi,
62 PercentTprel_Lo
63 };
64
65private:
66 TokenKind Kind;
67
68 /// A reference to the entire token contents; this is always a pointer into
69 /// a memory buffer owned by the source manager.
70 StringRef Str;
71
72 APInt IntVal;
73
74public:
75 AsmToken() = default;
76 AsmToken(TokenKind Kind, StringRef Str, APInt IntVal)
77 : Kind(Kind), Str(Str), IntVal(std::move(IntVal)) {}
78 AsmToken(TokenKind Kind, StringRef Str, int64_t IntVal = 0)
79 : Kind(Kind), Str(Str), IntVal(64, IntVal, true) {}
80
81 TokenKind getKind() const { return Kind; }
82 bool is(TokenKind K) const { return Kind == K; }
2
Assuming 'K' is not equal to field 'Kind'
3
Returning zero, which participates in a condition later
83 bool isNot(TokenKind K) const { return Kind != K; }
84
85 SMLoc getLoc() const;
86 SMLoc getEndLoc() const;
87 SMRange getLocRange() const;
88
89 /// Get the contents of a string token (without quotes).
90 StringRef getStringContents() const {
91 assert(Kind == String && "This token isn't a string!")(static_cast <bool> (Kind == String && "This token isn't a string!"
) ? void (0) : __assert_fail ("Kind == String && \"This token isn't a string!\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include/llvm/MC/MCAsmMacro.h"
, 91, __extension__ __PRETTY_FUNCTION__))
;
92 return Str.slice(1, Str.size() - 1);
93 }
94
95 /// Get the identifier string for the current token, which should be an
96 /// identifier or a string. This gets the portion of the string which should
97 /// be used as the identifier, e.g., it does not include the quotes on
98 /// strings.
99 StringRef getIdentifier() const {
100 if (Kind == Identifier)
101 return getString();
102 return getStringContents();
103 }
104
105 /// Get the string for the current token, this includes all characters (for
106 /// example, the quotes on strings) in the token.
107 ///
108 /// The returned StringRef points into the source manager's memory buffer, and
109 /// is safe to store across calls to Lex().
110 StringRef getString() const { return Str; }
111
112 // FIXME: Don't compute this in advance, it makes every token larger, and is
113 // also not generally what we want (it is nicer for recovery etc. to lex 123br
114 // as a single token, then diagnose as an invalid number).
115 int64_t getIntVal() const {
116 assert(Kind == Integer && "This token isn't an integer!")(static_cast <bool> (Kind == Integer && "This token isn't an integer!"
) ? void (0) : __assert_fail ("Kind == Integer && \"This token isn't an integer!\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include/llvm/MC/MCAsmMacro.h"
, 116, __extension__ __PRETTY_FUNCTION__))
;
117 return IntVal.getZExtValue();
118 }
119
120 APInt getAPIntVal() const {
121 assert((Kind == Integer || Kind == BigNum) &&(static_cast <bool> ((Kind == Integer || Kind == BigNum
) && "This token isn't an integer!") ? void (0) : __assert_fail
("(Kind == Integer || Kind == BigNum) && \"This token isn't an integer!\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include/llvm/MC/MCAsmMacro.h"
, 122, __extension__ __PRETTY_FUNCTION__))
122 "This token isn't an integer!")(static_cast <bool> ((Kind == Integer || Kind == BigNum
) && "This token isn't an integer!") ? void (0) : __assert_fail
("(Kind == Integer || Kind == BigNum) && \"This token isn't an integer!\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include/llvm/MC/MCAsmMacro.h"
, 122, __extension__ __PRETTY_FUNCTION__))
;
123 return IntVal;
124 }
125
126 void dump(raw_ostream &OS) const;
127};
128
129struct MCAsmMacroParameter {
130 StringRef Name;
131 std::vector<AsmToken> Value;
132 bool Required = false;
133 bool Vararg = false;
134
135#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
136 void dump() const { dump(dbgs()); }
137 LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void dump(raw_ostream &OS) const;
138#endif
139};
140
141typedef std::vector<MCAsmMacroParameter> MCAsmMacroParameters;
142struct MCAsmMacro {
143 StringRef Name;
144 StringRef Body;
145 MCAsmMacroParameters Parameters;
146 std::vector<std::string> Locals;
147 bool IsFunction = false;
148
149public:
150 MCAsmMacro(StringRef N, StringRef B, MCAsmMacroParameters P)
151 : Name(N), Body(B), Parameters(std::move(P)) {}
152 MCAsmMacro(StringRef N, StringRef B, MCAsmMacroParameters P,
153 std::vector<std::string> L, bool F)
154 : Name(N), Body(B), Parameters(std::move(P)), Locals(std::move(L)),
155 IsFunction(F) {}
156
157#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
158 void dump() const { dump(dbgs()); }
159 LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void dump(raw_ostream &OS) const;
160#endif
161};
162} // namespace llvm
163
164#endif