Bug Summary

File:llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Warning:line 2021, 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-14~++20210926122410+d23fd8ae8906/build-llvm -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I lib/Target/RISCV/AsmParser -I /build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/RISCV/AsmParser -I /build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/RISCV -I lib/Target/RISCV -I include -I /build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/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-14/lib/clang/14.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-command-line-argument -Wno-unknown-warning-option -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-14~++20210926122410+d23fd8ae8906/build-llvm -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2021-09-26-234817-15343-1 -x c++ /build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

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

/build/llvm-toolchain-snapshot-14~++20210926122410+d23fd8ae8906/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-14~++20210926122410+d23fd8ae8906/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-14~++20210926122410+d23fd8ae8906/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-14~++20210926122410+d23fd8ae8906/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-14~++20210926122410+d23fd8ae8906/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