blob: 4202d5bfe19c521cf0896c60ea8212c273953200 [file] [log] [blame]
Alex Bradbury04f06d92017-08-08 14:43:36 +00001//===-- RISCVAsmParser.cpp - Parse RISCV assembly to MCInst instructions --===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Alex Bradbury04f06d92017-08-08 14:43:36 +00006//
7//===----------------------------------------------------------------------===//
8
Alex Bradbury9c03e4c2018-11-12 14:25:07 +00009#include "MCTargetDesc/RISCVAsmBackend.h"
Alex Bradbury9d3f1252017-09-28 08:26:24 +000010#include "MCTargetDesc/RISCVMCExpr.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000011#include "MCTargetDesc/RISCVMCTargetDesc.h"
Alex Bradburybca0c3c2018-05-11 17:30:28 +000012#include "MCTargetDesc/RISCVTargetStreamer.h"
Ana Pazos9d6c5532018-10-04 21:50:54 +000013#include "Utils/RISCVBaseInfo.h"
Alex Bradbury22c091f2018-11-15 10:11:31 +000014#include "Utils/RISCVMatInt.h"
Alex Bradbury4f7f0da2017-09-06 09:21:21 +000015#include "llvm/ADT/STLExtras.h"
Alex Bradbury893e5bc2018-11-28 16:39:14 +000016#include "llvm/ADT/SmallVector.h"
Alex Bradbury4f7f0da2017-09-06 09:21:21 +000017#include "llvm/ADT/StringSwitch.h"
Alex Bradbury9c03e4c2018-11-12 14:25:07 +000018#include "llvm/MC/MCAssembler.h"
Alex Bradbury4f7f0da2017-09-06 09:21:21 +000019#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCExpr.h"
21#include "llvm/MC/MCInst.h"
Alex Bradbury6a4b5442018-06-07 15:35:47 +000022#include "llvm/MC/MCInstBuilder.h"
Alex Bradbury22531c42019-02-15 09:53:32 +000023#include "llvm/MC/MCObjectFileInfo.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000024#include "llvm/MC/MCParser/MCAsmLexer.h"
25#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
26#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000027#include "llvm/MC/MCRegisterInfo.h"
28#include "llvm/MC/MCStreamer.h"
29#include "llvm/MC/MCSubtargetInfo.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000030#include "llvm/Support/Casting.h"
Alex Bradbury6a4b5442018-06-07 15:35:47 +000031#include "llvm/Support/MathExtras.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000032#include "llvm/Support/TargetRegistry.h"
33
Alex Bradbury6a4b5442018-06-07 15:35:47 +000034#include <limits>
35
Alex Bradbury04f06d92017-08-08 14:43:36 +000036using namespace llvm;
37
Sameer AbuAsalc1b0e662018-04-06 21:07:05 +000038// Include the auto-generated portion of the compress emitter.
39#define GEN_COMPRESS_INSTR
40#include "RISCVGenCompressInstEmitter.inc"
41
Alex Bradbury04f06d92017-08-08 14:43:36 +000042namespace {
43struct RISCVOperand;
44
45class RISCVAsmParser : public MCTargetAsmParser {
Alex Bradbury893e5bc2018-11-28 16:39:14 +000046 SmallVector<FeatureBitset, 4> FeatureBitStack;
47
Alex Bradbury04f06d92017-08-08 14:43:36 +000048 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Alex Bradburya6e62482017-12-07 10:53:48 +000049 bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
Alex Bradbury04f06d92017-08-08 14:43:36 +000050
Alex Bradburybca0c3c2018-05-11 17:30:28 +000051 RISCVTargetStreamer &getTargetStreamer() {
52 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
53 return static_cast<RISCVTargetStreamer &>(TS);
54 }
55
Alex Bradbury7bc2a952017-12-07 10:46:23 +000056 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
57 unsigned Kind) override;
58
Alex Bradbury6758ecb2017-09-17 14:27:35 +000059 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
Alex Bradbury6a4b5442018-06-07 15:35:47 +000060 int64_t Lower, int64_t Upper, Twine Msg);
Alex Bradbury6758ecb2017-09-17 14:27:35 +000061
Alex Bradbury04f06d92017-08-08 14:43:36 +000062 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
63 OperandVector &Operands, MCStreamer &Out,
64 uint64_t &ErrorInfo,
65 bool MatchingInlineAsm) override;
66
67 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
68
69 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
70 SMLoc NameLoc, OperandVector &Operands) override;
71
72 bool ParseDirective(AsmToken DirectiveID) override;
73
Alex Bradbury6a4b5442018-06-07 15:35:47 +000074 // Helper to actually emit an instruction to the MCStreamer. Also, when
75 // possible, compression of the instruction is performed.
76 void emitToStreamer(MCStreamer &S, const MCInst &Inst);
77
78 // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
79 // synthesize the desired immedate value into the destination register.
80 void emitLoadImm(unsigned DestReg, int64_t Value, MCStreamer &Out);
81
Alex Bradbury22531c42019-02-15 09:53:32 +000082 // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
83 // helpers such as emitLoadLocalAddress and emitLoadAddress.
84 void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
85 const MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi,
86 unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
87
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +000088 // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
89 void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
90
Alex Bradbury22531c42019-02-15 09:53:32 +000091 // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
92 void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
93
Kito Cheng303217e2019-02-20 03:31:32 +000094 // Helper to emit pseudo load/store instruction with a symbol.
95 void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
96 MCStreamer &Out, bool HasTmpReg);
97
Alex Bradbury6a4b5442018-06-07 15:35:47 +000098 /// Helper for processing MC instructions that have been successfully matched
99 /// by MatchAndEmitInstruction. Modifications to the emitted instructions,
100 /// like the expansion of pseudo instructions (e.g., "li"), can be performed
101 /// in this method.
102 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
103
Alex Bradbury04f06d92017-08-08 14:43:36 +0000104// Auto-generated instruction matching functions
105#define GET_ASSEMBLER_HEADER
106#include "RISCVGenAsmMatcher.inc"
107
Ana Pazos9d6c5532018-10-04 21:50:54 +0000108 OperandMatchResultTy parseCSRSystemRegister(OperandVector &Operands);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000109 OperandMatchResultTy parseImmediate(OperandVector &Operands);
Alex Bradbury8c345c52017-11-09 15:00:03 +0000110 OperandMatchResultTy parseRegister(OperandVector &Operands,
111 bool AllowParens = false);
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000112 OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000113 OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
Alex Bradbury68f73c12018-09-18 15:18:16 +0000114 OperandMatchResultTy parseBareSymbol(OperandVector &Operands);
Alex Bradbury226f3ef2018-09-20 08:10:35 +0000115 OperandMatchResultTy parseJALOffset(OperandVector &Operands);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000116
Alex Bradbury68f73c12018-09-18 15:18:16 +0000117 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000118
Alex Bradburybca0c3c2018-05-11 17:30:28 +0000119 bool parseDirectiveOption();
120
121 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
122 if (!(getSTI().getFeatureBits()[Feature])) {
123 MCSubtargetInfo &STI = copySTI();
124 setAvailableFeatures(
125 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
126 }
127 }
128
129 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
130 if (getSTI().getFeatureBits()[Feature]) {
131 MCSubtargetInfo &STI = copySTI();
132 setAvailableFeatures(
133 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
134 }
135 }
Ana Pazos9d6c5532018-10-04 21:50:54 +0000136
Alex Bradbury893e5bc2018-11-28 16:39:14 +0000137 void pushFeatureBits() {
138 FeatureBitStack.push_back(getSTI().getFeatureBits());
139 }
140
141 bool popFeatureBits() {
142 if (FeatureBitStack.empty())
143 return true;
144
145 FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
146 copySTI().setFeatureBits(FeatureBits);
147 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
148
149 return false;
150 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000151public:
152 enum RISCVMatchResultTy {
153 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
154#define GET_OPERAND_DIAGNOSTIC_TYPES
155#include "RISCVGenAsmMatcher.inc"
156#undef GET_OPERAND_DIAGNOSTIC_TYPES
157 };
158
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000159 static bool classifySymbolRef(const MCExpr *Expr,
160 RISCVMCExpr::VariantKind &Kind,
161 int64_t &Addend);
162
Alex Bradbury04f06d92017-08-08 14:43:36 +0000163 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
164 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000165 : MCTargetAsmParser(Options, STI, MII) {
Alex Bradburycea6db02018-05-17 05:58:08 +0000166 Parser.addAliasForDirective(".half", ".2byte");
167 Parser.addAliasForDirective(".hword", ".2byte");
168 Parser.addAliasForDirective(".word", ".4byte");
169 Parser.addAliasForDirective(".dword", ".8byte");
Alex Bradbury04f06d92017-08-08 14:43:36 +0000170 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
171 }
172};
173
174/// RISCVOperand - Instances of this class represent a parsed machine
175/// instruction
176struct RISCVOperand : public MCParsedAsmOperand {
177
178 enum KindTy {
179 Token,
180 Register,
181 Immediate,
Ana Pazos9d6c5532018-10-04 21:50:54 +0000182 SystemRegister
Alex Bradbury04f06d92017-08-08 14:43:36 +0000183 } Kind;
184
Alex Bradburya6e62482017-12-07 10:53:48 +0000185 bool IsRV64;
186
Alex Bradbury04f06d92017-08-08 14:43:36 +0000187 struct RegOp {
188 unsigned RegNum;
189 };
190
191 struct ImmOp {
192 const MCExpr *Val;
193 };
194
Ana Pazos9d6c5532018-10-04 21:50:54 +0000195 struct SysRegOp {
196 const char *Data;
197 unsigned Length;
198 unsigned Encoding;
199 // FIXME: Add the Encoding parsed fields as needed for checks,
200 // e.g.: read/write or user/supervisor/machine privileges.
201 };
202
Alex Bradbury04f06d92017-08-08 14:43:36 +0000203 SMLoc StartLoc, EndLoc;
204 union {
205 StringRef Tok;
206 RegOp Reg;
207 ImmOp Imm;
Ana Pazos9d6c5532018-10-04 21:50:54 +0000208 struct SysRegOp SysReg;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000209 };
210
211 RISCVOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
212
213public:
214 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
215 Kind = o.Kind;
Alex Bradburya6e62482017-12-07 10:53:48 +0000216 IsRV64 = o.IsRV64;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000217 StartLoc = o.StartLoc;
218 EndLoc = o.EndLoc;
219 switch (Kind) {
220 case Register:
221 Reg = o.Reg;
222 break;
223 case Immediate:
224 Imm = o.Imm;
225 break;
226 case Token:
227 Tok = o.Tok;
228 break;
Ana Pazos9d6c5532018-10-04 21:50:54 +0000229 case SystemRegister:
230 SysReg = o.SysReg;
231 break;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000232 }
233 }
234
235 bool isToken() const override { return Kind == Token; }
236 bool isReg() const override { return Kind == Register; }
237 bool isImm() const override { return Kind == Immediate; }
238 bool isMem() const override { return false; }
Ana Pazos9d6c5532018-10-04 21:50:54 +0000239 bool isSystemRegister() const { return Kind == SystemRegister; }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000240
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000241 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
242 RISCVMCExpr::VariantKind &VK) {
243 if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000244 VK = RE->getKind();
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000245 return RE->evaluateAsConstant(Imm);
246 }
247
248 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000249 VK = RISCVMCExpr::VK_RISCV_None;
250 Imm = CE->getValue();
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000251 return true;
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000252 }
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000253
254 return false;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000255 }
256
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000257 // True if operand is a symbol with no modifiers, or a constant with no
258 // modifiers and isShiftedInt<N-1, 1>(Op).
259 template <int N> bool isBareSimmNLsb0() const {
260 int64_t Imm;
261 RISCVMCExpr::VariantKind VK;
Alex Bradbury3c941e72017-10-19 16:22:51 +0000262 if (!isImm())
263 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000264 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000265 bool IsValid;
266 if (!IsConstantImm)
267 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
268 else
269 IsValid = isShiftedInt<N - 1, 1>(Imm);
270 return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000271 }
272
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000273 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
274
Shiva Chen98f93892018-04-25 14:18:55 +0000275 bool isBareSymbol() const {
276 int64_t Imm;
277 RISCVMCExpr::VariantKind VK;
278 // Must be of 'immediate' type but not a constant.
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000279 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
Shiva Chen98f93892018-04-25 14:18:55 +0000280 return false;
281 return RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm) &&
282 VK == RISCVMCExpr::VK_RISCV_None;
283 }
284
Ana Pazos9d6c5532018-10-04 21:50:54 +0000285 bool isCSRSystemRegister() const { return isSystemRegister(); }
286
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000287 /// Return true if the operand is a valid for the fence instruction e.g.
288 /// ('iorw').
289 bool isFenceArg() const {
290 if (!isImm())
291 return false;
292 const MCExpr *Val = getImm();
293 auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
294 if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
295 return false;
296
297 StringRef Str = SVal->getSymbol().getName();
298 // Letters must be unique, taken from 'iorw', and in ascending order. This
299 // holds as long as each individual character is one of 'iorw' and is
300 // greater than the previous character.
301 char Prev = '\0';
302 for (char c : Str) {
303 if (c != 'i' && c != 'o' && c != 'r' && c != 'w')
304 return false;
305 if (c <= Prev)
306 return false;
307 Prev = c;
308 }
309 return true;
310 }
311
Alex Bradbury0d6cf902017-12-07 10:26:05 +0000312 /// Return true if the operand is a valid floating point rounding mode.
313 bool isFRMArg() const {
314 if (!isImm())
315 return false;
316 const MCExpr *Val = getImm();
317 auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
318 if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
319 return false;
320
321 StringRef Str = SVal->getSymbol().getName();
322
323 return RISCVFPRndMode::stringToRoundingMode(Str) != RISCVFPRndMode::Invalid;
324 }
325
Alex Bradbury2ba76be2019-01-03 14:41:41 +0000326 bool isImmXLenLI() const {
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000327 int64_t Imm;
328 RISCVMCExpr::VariantKind VK;
329 if (!isImm())
330 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000331 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury2ba76be2019-01-03 14:41:41 +0000332 if (VK == RISCVMCExpr::VK_RISCV_LO || VK == RISCVMCExpr::VK_RISCV_PCREL_LO)
333 return true;
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000334 // Given only Imm, ensuring that the actually specified constant is either
335 // a signed or unsigned 64-bit number is unfortunately impossible.
336 bool IsInRange = isRV64() ? true : isInt<32>(Imm) || isUInt<32>(Imm);
337 return IsConstantImm && IsInRange && VK == RISCVMCExpr::VK_RISCV_None;
338 }
339
Alex Bradburya6e62482017-12-07 10:53:48 +0000340 bool isUImmLog2XLen() const {
341 int64_t Imm;
342 RISCVMCExpr::VariantKind VK;
343 if (!isImm())
344 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000345 if (!evaluateConstantImm(getImm(), Imm, VK) ||
346 VK != RISCVMCExpr::VK_RISCV_None)
Alex Bradburya6e62482017-12-07 10:53:48 +0000347 return false;
348 return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm);
349 }
350
Alex Bradbury0ad4c262017-12-15 10:20:51 +0000351 bool isUImmLog2XLenNonZero() const {
352 int64_t Imm;
353 RISCVMCExpr::VariantKind VK;
354 if (!isImm())
355 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000356 if (!evaluateConstantImm(getImm(), Imm, VK) ||
357 VK != RISCVMCExpr::VK_RISCV_None)
Alex Bradbury0ad4c262017-12-15 10:20:51 +0000358 return false;
359 if (Imm == 0)
360 return false;
361 return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm);
362 }
363
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000364 bool isUImm5() const {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000365 int64_t Imm;
366 RISCVMCExpr::VariantKind VK;
Alex Bradbury3c941e72017-10-19 16:22:51 +0000367 if (!isImm())
368 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000369 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000370 return IsConstantImm && isUInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000371 }
372
Alex Bradbury60714f92017-12-13 09:32:55 +0000373 bool isUImm5NonZero() const {
374 int64_t Imm;
375 RISCVMCExpr::VariantKind VK;
376 if (!isImm())
377 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000378 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury60714f92017-12-13 09:32:55 +0000379 return IsConstantImm && isUInt<5>(Imm) && (Imm != 0) &&
380 VK == RISCVMCExpr::VK_RISCV_None;
381 }
382
Alex Bradbury581d6b02017-12-13 09:41:21 +0000383 bool isSImm6() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000384 if (!isImm())
385 return false;
Alex Bradbury581d6b02017-12-13 09:41:21 +0000386 RISCVMCExpr::VariantKind VK;
387 int64_t Imm;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000388 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Ana Pazos065b0882018-09-13 18:37:23 +0000389 return IsConstantImm && isInt<6>(Imm) &&
390 VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury581d6b02017-12-13 09:41:21 +0000391 }
392
Shiva Chenb22c1d22018-02-02 02:43:23 +0000393 bool isSImm6NonZero() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000394 if (!isImm())
395 return false;
Shiva Chenb22c1d22018-02-02 02:43:23 +0000396 RISCVMCExpr::VariantKind VK;
397 int64_t Imm;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000398 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Ana Pazos065b0882018-09-13 18:37:23 +0000399 return IsConstantImm && isInt<6>(Imm) && (Imm != 0) &&
400 VK == RISCVMCExpr::VK_RISCV_None;
Shiva Chenb22c1d22018-02-02 02:43:23 +0000401 }
402
Shiva Chen7c172422018-02-22 15:02:28 +0000403 bool isCLUIImm() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000404 if (!isImm())
405 return false;
Alex Bradbury60714f92017-12-13 09:32:55 +0000406 int64_t Imm;
407 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000408 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Shiva Chen7c172422018-02-22 15:02:28 +0000409 return IsConstantImm && (Imm != 0) &&
410 (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
Ana Pazos9d6c5532018-10-04 21:50:54 +0000411 VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury60714f92017-12-13 09:32:55 +0000412 }
413
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000414 bool isUImm7Lsb00() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000415 if (!isImm())
416 return false;
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000417 int64_t Imm;
418 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000419 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000420 return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
421 VK == RISCVMCExpr::VK_RISCV_None;
422 }
423
424 bool isUImm8Lsb00() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000425 if (!isImm())
426 return false;
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000427 int64_t Imm;
428 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000429 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000430 return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
431 VK == RISCVMCExpr::VK_RISCV_None;
432 }
433
434 bool isUImm8Lsb000() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000435 if (!isImm())
436 return false;
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000437 int64_t Imm;
438 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000439 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000440 return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
441 VK == RISCVMCExpr::VK_RISCV_None;
442 }
443
Alex Bradburyf8f4b902017-12-07 13:19:57 +0000444 bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
445
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000446 bool isUImm9Lsb000() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000447 if (!isImm())
448 return false;
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000449 int64_t Imm;
450 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000451 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000452 return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
453 VK == RISCVMCExpr::VK_RISCV_None;
454 }
455
Alex Bradbury60714f92017-12-13 09:32:55 +0000456 bool isUImm10Lsb00NonZero() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000457 if (!isImm())
458 return false;
Alex Bradbury60714f92017-12-13 09:32:55 +0000459 int64_t Imm;
460 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000461 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury60714f92017-12-13 09:32:55 +0000462 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
463 VK == RISCVMCExpr::VK_RISCV_None;
464 }
465
Alex Bradbury04f06d92017-08-08 14:43:36 +0000466 bool isSImm12() const {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000467 RISCVMCExpr::VariantKind VK;
468 int64_t Imm;
469 bool IsValid;
Alex Bradbury3c941e72017-10-19 16:22:51 +0000470 if (!isImm())
471 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000472 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000473 if (!IsConstantImm)
474 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
475 else
476 IsValid = isInt<12>(Imm);
Alex Bradbury7d0e18d2018-09-18 15:13:29 +0000477 return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
Ahmed Charles646ab872018-02-06 00:55:23 +0000478 VK == RISCVMCExpr::VK_RISCV_LO ||
479 VK == RISCVMCExpr::VK_RISCV_PCREL_LO);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000480 }
481
Alex Bradburyf8f4b902017-12-07 13:19:57 +0000482 bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
483
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000484 bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000485
Shiva Chenb22c1d22018-02-02 02:43:23 +0000486 bool isSImm10Lsb0000NonZero() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000487 if (!isImm())
488 return false;
Alex Bradbury60714f92017-12-13 09:32:55 +0000489 int64_t Imm;
490 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000491 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Shiva Chenb22c1d22018-02-02 02:43:23 +0000492 return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) &&
Alex Bradbury60714f92017-12-13 09:32:55 +0000493 VK == RISCVMCExpr::VK_RISCV_None;
494 }
495
Alex Bradbury74340f12018-09-18 15:08:35 +0000496 bool isUImm20LUI() const {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000497 RISCVMCExpr::VariantKind VK;
498 int64_t Imm;
499 bool IsValid;
Alex Bradbury3c941e72017-10-19 16:22:51 +0000500 if (!isImm())
501 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000502 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury74340f12018-09-18 15:08:35 +0000503 if (!IsConstantImm) {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000504 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
Alex Bradbury74340f12018-09-18 15:08:35 +0000505 return IsValid && VK == RISCVMCExpr::VK_RISCV_HI;
506 } else {
507 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
508 VK == RISCVMCExpr::VK_RISCV_HI);
509 }
510 }
511
512 bool isUImm20AUIPC() const {
513 RISCVMCExpr::VariantKind VK;
514 int64_t Imm;
515 bool IsValid;
516 if (!isImm())
517 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000518 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury74340f12018-09-18 15:08:35 +0000519 if (!IsConstantImm) {
520 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
Alex Bradbury8eb87e52019-02-15 09:43:46 +0000521 return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
522 VK == RISCVMCExpr::VK_RISCV_GOT_HI);
Alex Bradbury74340f12018-09-18 15:08:35 +0000523 } else {
524 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
Alex Bradbury8eb87e52019-02-15 09:43:46 +0000525 VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
526 VK == RISCVMCExpr::VK_RISCV_GOT_HI);
Alex Bradbury74340f12018-09-18 15:08:35 +0000527 }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000528 }
529
Alex Bradbury226f3ef2018-09-20 08:10:35 +0000530 bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000531
Alex Bradbury04f06d92017-08-08 14:43:36 +0000532 /// getStartLoc - Gets location of the first token of this operand
533 SMLoc getStartLoc() const override { return StartLoc; }
534 /// getEndLoc - Gets location of the last token of this operand
535 SMLoc getEndLoc() const override { return EndLoc; }
Alex Bradburya6e62482017-12-07 10:53:48 +0000536 /// True if this operand is for an RV64 instruction
537 bool isRV64() const { return IsRV64; }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000538
539 unsigned getReg() const override {
540 assert(Kind == Register && "Invalid type access!");
541 return Reg.RegNum;
542 }
543
Ana Pazos9d6c5532018-10-04 21:50:54 +0000544 StringRef getSysReg() const {
545 assert(Kind == SystemRegister && "Invalid access!");
546 return StringRef(SysReg.Data, SysReg.Length);
547 }
548
Alex Bradbury04f06d92017-08-08 14:43:36 +0000549 const MCExpr *getImm() const {
550 assert(Kind == Immediate && "Invalid type access!");
551 return Imm.Val;
552 }
553
554 StringRef getToken() const {
555 assert(Kind == Token && "Invalid type access!");
556 return Tok;
557 }
558
559 void print(raw_ostream &OS) const override {
560 switch (Kind) {
561 case Immediate:
562 OS << *getImm();
563 break;
564 case Register:
565 OS << "<register x";
566 OS << getReg() << ">";
567 break;
568 case Token:
569 OS << "'" << getToken() << "'";
570 break;
Ana Pazos9d6c5532018-10-04 21:50:54 +0000571 case SystemRegister:
572 OS << "<sysreg: " << getSysReg() << '>';
573 break;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000574 }
575 }
576
Alex Bradburya6e62482017-12-07 10:53:48 +0000577 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S,
578 bool IsRV64) {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000579 auto Op = make_unique<RISCVOperand>(Token);
580 Op->Tok = Str;
581 Op->StartLoc = S;
582 Op->EndLoc = S;
Alex Bradburya6e62482017-12-07 10:53:48 +0000583 Op->IsRV64 = IsRV64;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000584 return Op;
585 }
586
587 static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S,
Alex Bradburya6e62482017-12-07 10:53:48 +0000588 SMLoc E, bool IsRV64) {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000589 auto Op = make_unique<RISCVOperand>(Register);
590 Op->Reg.RegNum = RegNo;
591 Op->StartLoc = S;
592 Op->EndLoc = E;
Alex Bradburya6e62482017-12-07 10:53:48 +0000593 Op->IsRV64 = IsRV64;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000594 return Op;
595 }
596
597 static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
Alex Bradburya6e62482017-12-07 10:53:48 +0000598 SMLoc E, bool IsRV64) {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000599 auto Op = make_unique<RISCVOperand>(Immediate);
600 Op->Imm.Val = Val;
601 Op->StartLoc = S;
602 Op->EndLoc = E;
Alex Bradburya6e62482017-12-07 10:53:48 +0000603 Op->IsRV64 = IsRV64;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000604 return Op;
605 }
606
Ana Pazos9d6c5532018-10-04 21:50:54 +0000607 static std::unique_ptr<RISCVOperand>
608 createSysReg(StringRef Str, SMLoc S, unsigned Encoding, bool IsRV64) {
609 auto Op = make_unique<RISCVOperand>(SystemRegister);
610 Op->SysReg.Data = Str.data();
611 Op->SysReg.Length = Str.size();
612 Op->SysReg.Encoding = Encoding;
613 Op->StartLoc = S;
614 Op->IsRV64 = IsRV64;
615 return Op;
616 }
617
Alex Bradbury04f06d92017-08-08 14:43:36 +0000618 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
619 assert(Expr && "Expr shouldn't be null!");
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000620 int64_t Imm = 0;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000621 RISCVMCExpr::VariantKind VK;
622 bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000623
624 if (IsConstant)
625 Inst.addOperand(MCOperand::createImm(Imm));
Alex Bradbury04f06d92017-08-08 14:43:36 +0000626 else
627 Inst.addOperand(MCOperand::createExpr(Expr));
628 }
629
630 // Used by the TableGen Code
631 void addRegOperands(MCInst &Inst, unsigned N) const {
632 assert(N == 1 && "Invalid number of operands!");
633 Inst.addOperand(MCOperand::createReg(getReg()));
634 }
635
636 void addImmOperands(MCInst &Inst, unsigned N) const {
637 assert(N == 1 && "Invalid number of operands!");
638 addExpr(Inst, getImm());
639 }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000640
641 void addFenceArgOperands(MCInst &Inst, unsigned N) const {
642 assert(N == 1 && "Invalid number of operands!");
643 // isFenceArg has validated the operand, meaning this cast is safe
644 auto SE = cast<MCSymbolRefExpr>(getImm());
645
646 unsigned Imm = 0;
647 for (char c : SE->getSymbol().getName()) {
648 switch (c) {
Ana Pazos9d6c5532018-10-04 21:50:54 +0000649 default:
650 llvm_unreachable("FenceArg must contain only [iorw]");
651 case 'i': Imm |= RISCVFenceField::I; break;
652 case 'o': Imm |= RISCVFenceField::O; break;
653 case 'r': Imm |= RISCVFenceField::R; break;
654 case 'w': Imm |= RISCVFenceField::W; break;
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000655 }
656 }
657 Inst.addOperand(MCOperand::createImm(Imm));
658 }
Alex Bradbury0d6cf902017-12-07 10:26:05 +0000659
Ana Pazos9d6c5532018-10-04 21:50:54 +0000660 void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
661 assert(N == 1 && "Invalid number of operands!");
662 Inst.addOperand(MCOperand::createImm(SysReg.Encoding));
663 }
664
Alex Bradbury0d6cf902017-12-07 10:26:05 +0000665 // Returns the rounding mode represented by this RISCVOperand. Should only
666 // be called after checking isFRMArg.
667 RISCVFPRndMode::RoundingMode getRoundingMode() const {
668 // isFRMArg has validated the operand, meaning this cast is safe.
669 auto SE = cast<MCSymbolRefExpr>(getImm());
670 RISCVFPRndMode::RoundingMode FRM =
671 RISCVFPRndMode::stringToRoundingMode(SE->getSymbol().getName());
672 assert(FRM != RISCVFPRndMode::Invalid && "Invalid rounding mode");
673 return FRM;
674 }
675
676 void addFRMArgOperands(MCInst &Inst, unsigned N) const {
677 assert(N == 1 && "Invalid number of operands!");
678 Inst.addOperand(MCOperand::createImm(getRoundingMode()));
679 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000680};
681} // end anonymous namespace.
682
683#define GET_REGISTER_MATCHER
684#define GET_MATCHER_IMPLEMENTATION
Alex Bradbury04f06d92017-08-08 14:43:36 +0000685#include "RISCVGenAsmMatcher.inc"
686
Alex Bradbury7bc2a952017-12-07 10:46:23 +0000687// Return the matching FPR64 register for the given FPR32.
688// FIXME: Ideally this function could be removed in favour of using
689// information from TableGen.
690unsigned convertFPR32ToFPR64(unsigned Reg) {
691 switch (Reg) {
Ana Pazos9d6c5532018-10-04 21:50:54 +0000692 default:
693 llvm_unreachable("Not a recognised FPR32 register");
694 case RISCV::F0_32: return RISCV::F0_64;
695 case RISCV::F1_32: return RISCV::F1_64;
696 case RISCV::F2_32: return RISCV::F2_64;
697 case RISCV::F3_32: return RISCV::F3_64;
698 case RISCV::F4_32: return RISCV::F4_64;
699 case RISCV::F5_32: return RISCV::F5_64;
700 case RISCV::F6_32: return RISCV::F6_64;
701 case RISCV::F7_32: return RISCV::F7_64;
702 case RISCV::F8_32: return RISCV::F8_64;
703 case RISCV::F9_32: return RISCV::F9_64;
704 case RISCV::F10_32: return RISCV::F10_64;
705 case RISCV::F11_32: return RISCV::F11_64;
706 case RISCV::F12_32: return RISCV::F12_64;
707 case RISCV::F13_32: return RISCV::F13_64;
708 case RISCV::F14_32: return RISCV::F14_64;
709 case RISCV::F15_32: return RISCV::F15_64;
710 case RISCV::F16_32: return RISCV::F16_64;
711 case RISCV::F17_32: return RISCV::F17_64;
712 case RISCV::F18_32: return RISCV::F18_64;
713 case RISCV::F19_32: return RISCV::F19_64;
714 case RISCV::F20_32: return RISCV::F20_64;
715 case RISCV::F21_32: return RISCV::F21_64;
716 case RISCV::F22_32: return RISCV::F22_64;
717 case RISCV::F23_32: return RISCV::F23_64;
718 case RISCV::F24_32: return RISCV::F24_64;
719 case RISCV::F25_32: return RISCV::F25_64;
720 case RISCV::F26_32: return RISCV::F26_64;
721 case RISCV::F27_32: return RISCV::F27_64;
722 case RISCV::F28_32: return RISCV::F28_64;
723 case RISCV::F29_32: return RISCV::F29_64;
724 case RISCV::F30_32: return RISCV::F30_64;
725 case RISCV::F31_32: return RISCV::F31_64;
Alex Bradbury7bc2a952017-12-07 10:46:23 +0000726 }
727}
728
729unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
730 unsigned Kind) {
731 RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
732 if (!Op.isReg())
733 return Match_InvalidOperand;
734
735 unsigned Reg = Op.getReg();
736 bool IsRegFPR32 =
737 RISCVMCRegisterClasses[RISCV::FPR32RegClassID].contains(Reg);
Alex Bradbury60714f92017-12-13 09:32:55 +0000738 bool IsRegFPR32C =
739 RISCVMCRegisterClasses[RISCV::FPR32CRegClassID].contains(Reg);
Alex Bradbury7bc2a952017-12-07 10:46:23 +0000740
741 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
Alex Bradbury60714f92017-12-13 09:32:55 +0000742 // register from FPR32 to FPR64 or FPR32C to FPR64C if necessary.
743 if ((IsRegFPR32 && Kind == MCK_FPR64) ||
744 (IsRegFPR32C && Kind == MCK_FPR64C)) {
Alex Bradbury7bc2a952017-12-07 10:46:23 +0000745 Op.Reg.RegNum = convertFPR32ToFPR64(Reg);
746 return Match_Success;
747 }
748 return Match_InvalidOperand;
749}
750
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000751bool RISCVAsmParser::generateImmOutOfRangeError(
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000752 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000753 Twine Msg = "immediate must be an integer in the range") {
754 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
755 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
756}
757
Alex Bradbury04f06d92017-08-08 14:43:36 +0000758bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
759 OperandVector &Operands,
760 MCStreamer &Out,
761 uint64_t &ErrorInfo,
762 bool MatchingInlineAsm) {
763 MCInst Inst;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000764
Ana Pazos6b34051b2018-08-30 19:43:19 +0000765 auto Result =
766 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
767 switch (Result) {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000768 default:
769 break;
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000770 case Match_Success:
771 return processInstruction(Inst, IDLoc, Out);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000772 case Match_MissingFeature:
773 return Error(IDLoc, "instruction use requires an option to be enabled");
774 case Match_MnemonicFail:
775 return Error(IDLoc, "unrecognized instruction mnemonic");
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000776 case Match_InvalidOperand: {
777 SMLoc ErrorLoc = IDLoc;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000778 if (ErrorInfo != ~0U) {
779 if (ErrorInfo >= Operands.size())
780 return Error(ErrorLoc, "too few operands for instruction");
781
782 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
783 if (ErrorLoc == SMLoc())
784 ErrorLoc = IDLoc;
785 }
786 return Error(ErrorLoc, "invalid operand for instruction");
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000787 }
Ana Pazos6b34051b2018-08-30 19:43:19 +0000788 }
789
790 // Handle the case when the error message is of specific type
791 // other than the generic Match_InvalidOperand, and the
792 // corresponding operand is missing.
793 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
794 SMLoc ErrorLoc = IDLoc;
795 if (ErrorInfo != ~0U && ErrorInfo >= Operands.size())
796 return Error(ErrorLoc, "too few operands for instruction");
797 }
798
799 switch(Result) {
800 default:
801 break;
Alex Bradbury2ba76be2019-01-03 14:41:41 +0000802 case Match_InvalidImmXLenLI:
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000803 if (isRV64()) {
804 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
805 return Error(ErrorLoc, "operand must be a constant 64-bit integer");
806 }
807 return generateImmOutOfRangeError(Operands, ErrorInfo,
808 std::numeric_limits<int32_t>::min(),
809 std::numeric_limits<uint32_t>::max());
Alex Bradburya6e62482017-12-07 10:53:48 +0000810 case Match_InvalidUImmLog2XLen:
811 if (isRV64())
812 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
813 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
Alex Bradbury0ad4c262017-12-15 10:20:51 +0000814 case Match_InvalidUImmLog2XLenNonZero:
815 if (isRV64())
816 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
817 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000818 case Match_InvalidUImm5:
819 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
Alex Bradbury581d6b02017-12-13 09:41:21 +0000820 case Match_InvalidSImm6:
821 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
822 (1 << 5) - 1);
Shiva Chenb22c1d22018-02-02 02:43:23 +0000823 case Match_InvalidSImm6NonZero:
Ana Pazos9d6c5532018-10-04 21:50:54 +0000824 return generateImmOutOfRangeError(
825 Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,
Shiva Chenb22c1d22018-02-02 02:43:23 +0000826 "immediate must be non-zero in the range");
Shiva Chen7c172422018-02-22 15:02:28 +0000827 case Match_InvalidCLUIImm:
828 return generateImmOutOfRangeError(
829 Operands, ErrorInfo, 1, (1 << 5) - 1,
830 "immediate must be in [0xfffe0, 0xfffff] or");
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000831 case Match_InvalidUImm7Lsb00:
832 return generateImmOutOfRangeError(
833 Operands, ErrorInfo, 0, (1 << 7) - 4,
834 "immediate must be a multiple of 4 bytes in the range");
835 case Match_InvalidUImm8Lsb00:
836 return generateImmOutOfRangeError(
837 Operands, ErrorInfo, 0, (1 << 8) - 4,
838 "immediate must be a multiple of 4 bytes in the range");
839 case Match_InvalidUImm8Lsb000:
840 return generateImmOutOfRangeError(
841 Operands, ErrorInfo, 0, (1 << 8) - 8,
842 "immediate must be a multiple of 8 bytes in the range");
Alex Bradburyf8f4b902017-12-07 13:19:57 +0000843 case Match_InvalidSImm9Lsb0:
844 return generateImmOutOfRangeError(
845 Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
846 "immediate must be a multiple of 2 bytes in the range");
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000847 case Match_InvalidUImm9Lsb000:
848 return generateImmOutOfRangeError(
849 Operands, ErrorInfo, 0, (1 << 9) - 8,
850 "immediate must be a multiple of 8 bytes in the range");
Alex Bradbury60714f92017-12-13 09:32:55 +0000851 case Match_InvalidUImm10Lsb00NonZero:
852 return generateImmOutOfRangeError(
853 Operands, ErrorInfo, 4, (1 << 10) - 4,
854 "immediate must be a multiple of 4 bytes in the range");
Shiva Chenb22c1d22018-02-02 02:43:23 +0000855 case Match_InvalidSImm10Lsb0000NonZero:
Alex Bradbury60714f92017-12-13 09:32:55 +0000856 return generateImmOutOfRangeError(
857 Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
Shiva Chenb22c1d22018-02-02 02:43:23 +0000858 "immediate must be a multiple of 16 bytes and non-zero in the range");
Alex Bradbury04f06d92017-08-08 14:43:36 +0000859 case Match_InvalidSImm12:
Alex Bradbury7d0e18d2018-09-18 15:13:29 +0000860 return generateImmOutOfRangeError(
861 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
862 "operand must be a symbol with %lo/%pcrel_lo modifier or an integer in "
863 "the range");
Alex Bradburyf8f4b902017-12-07 13:19:57 +0000864 case Match_InvalidSImm12Lsb0:
865 return generateImmOutOfRangeError(
866 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
867 "immediate must be a multiple of 2 bytes in the range");
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000868 case Match_InvalidSImm13Lsb0:
869 return generateImmOutOfRangeError(
870 Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
871 "immediate must be a multiple of 2 bytes in the range");
Alex Bradbury74340f12018-09-18 15:08:35 +0000872 case Match_InvalidUImm20LUI:
873 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
874 "operand must be a symbol with %hi() "
875 "modifier or an integer in the range");
876 case Match_InvalidUImm20AUIPC:
877 return generateImmOutOfRangeError(
878 Operands, ErrorInfo, 0, (1 << 20) - 1,
Alex Bradbury8eb87e52019-02-15 09:43:46 +0000879 "operand must be a symbol with a %pcrel_hi/%got_pcrel_hi modifier "
880 "or an integer in the range");
Alex Bradbury226f3ef2018-09-20 08:10:35 +0000881 case Match_InvalidSImm21Lsb0JAL:
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000882 return generateImmOutOfRangeError(
883 Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
884 "immediate must be a multiple of 2 bytes in the range");
Ana Pazos9d6c5532018-10-04 21:50:54 +0000885 case Match_InvalidCSRSystemRegister: {
886 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,
887 "operand must be a valid system register "
888 "name or an integer in the range");
889 }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000890 case Match_InvalidFenceArg: {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000891 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000892 return Error(
893 ErrorLoc,
894 "operand must be formed of letters selected in-order from 'iorw'");
895 }
Alex Bradbury0d6cf902017-12-07 10:26:05 +0000896 case Match_InvalidFRMArg: {
897 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
898 return Error(
899 ErrorLoc,
900 "operand must be a valid floating point rounding mode mnemonic");
901 }
Shiva Chen98f93892018-04-25 14:18:55 +0000902 case Match_InvalidBareSymbol: {
903 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
904 return Error(ErrorLoc, "operand must be a bare symbol name");
905 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000906 }
907
908 llvm_unreachable("Unknown match type detected!");
909}
910
Alex Bradbury99794792019-03-17 12:02:32 +0000911// Attempts to match Name as a register (either using the default name or
912// alternative ABI names), setting RegNo to the matching register. Upon
913// failure, returns true and sets RegNo to 0.
914static bool matchRegisterNameHelper(unsigned &RegNo, StringRef Name) {
915 RegNo = MatchRegisterName(Name);
916 if (RegNo == 0)
917 RegNo = MatchRegisterAltName(Name);
918 return RegNo == 0;
919}
920
Alex Bradbury04f06d92017-08-08 14:43:36 +0000921bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
922 SMLoc &EndLoc) {
923 const AsmToken &Tok = getParser().getTok();
924 StartLoc = Tok.getLoc();
925 EndLoc = Tok.getEndLoc();
926 RegNo = 0;
927 StringRef Name = getLexer().getTok().getIdentifier();
928
Alex Bradbury99794792019-03-17 12:02:32 +0000929 if (matchRegisterNameHelper(RegNo, Name))
Alex Bradburyb18e3142019-03-17 12:00:58 +0000930 return Error(StartLoc, "invalid register name");
Alex Bradbury04f06d92017-08-08 14:43:36 +0000931
Alex Bradburyb18e3142019-03-17 12:00:58 +0000932 getParser().Lex(); // Eat identifier token.
933 return false;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000934}
935
Alex Bradbury8c345c52017-11-09 15:00:03 +0000936OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands,
937 bool AllowParens) {
938 SMLoc FirstS = getLoc();
939 bool HadParens = false;
940 AsmToken Buf[2];
941
942 // If this a parenthesised register name is allowed, parse it atomically
943 if (AllowParens && getLexer().is(AsmToken::LParen)) {
944 size_t ReadCount = getLexer().peekTokens(Buf);
945 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
946 HadParens = true;
947 getParser().Lex(); // Eat '('
948 }
949 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000950
951 switch (getLexer().getKind()) {
952 default:
953 return MatchOperand_NoMatch;
954 case AsmToken::Identifier:
955 StringRef Name = getLexer().getTok().getIdentifier();
Alex Bradbury99794792019-03-17 12:02:32 +0000956 unsigned RegNo;
957 matchRegisterNameHelper(RegNo, Name);
958
Alex Bradbury04f06d92017-08-08 14:43:36 +0000959 if (RegNo == 0) {
Alex Bradbury99794792019-03-17 12:02:32 +0000960 if (HadParens)
961 getLexer().UnLex(Buf[0]);
962 return MatchOperand_NoMatch;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000963 }
Alex Bradbury8c345c52017-11-09 15:00:03 +0000964 if (HadParens)
Alex Bradburya6e62482017-12-07 10:53:48 +0000965 Operands.push_back(RISCVOperand::createToken("(", FirstS, isRV64()));
Alex Bradbury8c345c52017-11-09 15:00:03 +0000966 SMLoc S = getLoc();
967 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000968 getLexer().Lex();
Alex Bradburya6e62482017-12-07 10:53:48 +0000969 Operands.push_back(RISCVOperand::createReg(RegNo, S, E, isRV64()));
Alex Bradbury04f06d92017-08-08 14:43:36 +0000970 }
Alex Bradbury8c345c52017-11-09 15:00:03 +0000971
972 if (HadParens) {
973 getParser().Lex(); // Eat ')'
Alex Bradburya6e62482017-12-07 10:53:48 +0000974 Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
Alex Bradbury8c345c52017-11-09 15:00:03 +0000975 }
976
Alex Bradbury04f06d92017-08-08 14:43:36 +0000977 return MatchOperand_Success;
978}
979
Ana Pazos9d6c5532018-10-04 21:50:54 +0000980OperandMatchResultTy
981RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
982 SMLoc S = getLoc();
983 const MCExpr *Res;
984
985 switch (getLexer().getKind()) {
986 default:
987 return MatchOperand_NoMatch;
988 case AsmToken::LParen:
989 case AsmToken::Minus:
990 case AsmToken::Plus:
991 case AsmToken::Integer:
992 case AsmToken::String: {
993 if (getParser().parseExpression(Res))
994 return MatchOperand_ParseFail;
995
996 auto *CE = dyn_cast<MCConstantExpr>(Res);
997 if (CE) {
998 int64_t Imm = CE->getValue();
999 if (isUInt<12>(Imm)) {
1000 auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
1001 // Accept an immediate representing a named or un-named Sys Reg
1002 // if the range is valid, regardless of the required features.
1003 Operands.push_back(RISCVOperand::createSysReg(
1004 SysReg ? SysReg->Name : "", S, Imm, isRV64()));
1005 return MatchOperand_Success;
1006 }
1007 }
1008
1009 Twine Msg = "immediate must be an integer in the range";
1010 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1011 return MatchOperand_ParseFail;
1012 }
1013 case AsmToken::Identifier: {
1014 StringRef Identifier;
1015 if (getParser().parseIdentifier(Identifier))
1016 return MatchOperand_ParseFail;
1017
1018 auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1019 // Accept a named Sys Reg if the required features are present.
1020 if (SysReg) {
1021 if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits())) {
1022 Error(S, "system register use requires an option to be enabled");
1023 return MatchOperand_ParseFail;
1024 }
1025 Operands.push_back(RISCVOperand::createSysReg(
1026 Identifier, S, SysReg->Encoding, isRV64()));
1027 return MatchOperand_Success;
1028 }
1029
1030 Twine Msg = "operand must be a valid system register name "
1031 "or an integer in the range";
1032 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1033 return MatchOperand_ParseFail;
1034 }
1035 case AsmToken::Percent: {
1036 // Discard operand with modifier.
1037 Twine Msg = "immediate must be an integer in the range";
1038 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1039 return MatchOperand_ParseFail;
1040 }
1041 }
1042
1043 return MatchOperand_NoMatch;
1044}
1045
Alex Bradbury04f06d92017-08-08 14:43:36 +00001046OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001047 SMLoc S = getLoc();
1048 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1049 const MCExpr *Res;
1050
Alex Bradbury04f06d92017-08-08 14:43:36 +00001051 switch (getLexer().getKind()) {
1052 default:
1053 return MatchOperand_NoMatch;
1054 case AsmToken::LParen:
1055 case AsmToken::Minus:
1056 case AsmToken::Plus:
1057 case AsmToken::Integer:
1058 case AsmToken::String:
Alex Bradbury6f302b82019-01-10 15:33:17 +00001059 case AsmToken::Identifier:
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001060 if (getParser().parseExpression(Res))
1061 return MatchOperand_ParseFail;
1062 break;
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001063 case AsmToken::Percent:
1064 return parseOperandWithModifier(Operands);
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001065 }
Alex Bradbury04f06d92017-08-08 14:43:36 +00001066
Alex Bradburya6e62482017-12-07 10:53:48 +00001067 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001068 return MatchOperand_Success;
1069}
1070
1071OperandMatchResultTy
1072RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
1073 SMLoc S = getLoc();
1074 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1075
1076 if (getLexer().getKind() != AsmToken::Percent) {
1077 Error(getLoc(), "expected '%' for operand modifier");
1078 return MatchOperand_ParseFail;
1079 }
1080
1081 getParser().Lex(); // Eat '%'
1082
1083 if (getLexer().getKind() != AsmToken::Identifier) {
1084 Error(getLoc(), "expected valid identifier for operand modifier");
1085 return MatchOperand_ParseFail;
1086 }
1087 StringRef Identifier = getParser().getTok().getIdentifier();
1088 RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier);
1089 if (VK == RISCVMCExpr::VK_RISCV_Invalid) {
1090 Error(getLoc(), "unrecognized operand modifier");
1091 return MatchOperand_ParseFail;
1092 }
1093
1094 getParser().Lex(); // Eat the identifier
1095 if (getLexer().getKind() != AsmToken::LParen) {
1096 Error(getLoc(), "expected '('");
1097 return MatchOperand_ParseFail;
1098 }
1099 getParser().Lex(); // Eat '('
1100
1101 const MCExpr *SubExpr;
1102 if (getParser().parseParenExpression(SubExpr, E)) {
1103 return MatchOperand_ParseFail;
1104 }
1105
1106 const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
Alex Bradburya6e62482017-12-07 10:53:48 +00001107 Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001108 return MatchOperand_Success;
1109}
1110
Alex Bradbury68f73c12018-09-18 15:18:16 +00001111OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
1112 SMLoc S = getLoc();
1113 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1114 const MCExpr *Res;
1115
1116 if (getLexer().getKind() != AsmToken::Identifier)
1117 return MatchOperand_NoMatch;
1118
1119 StringRef Identifier;
Kito Cheng303217e2019-02-20 03:31:32 +00001120 AsmToken Tok = getLexer().getTok();
1121
Alex Bradbury68f73c12018-09-18 15:18:16 +00001122 if (getParser().parseIdentifier(Identifier))
1123 return MatchOperand_ParseFail;
1124
1125 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
Kito Cheng303217e2019-02-20 03:31:32 +00001126
1127 if (Sym->isVariable()) {
1128 const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1129 if (!isa<MCSymbolRefExpr>(V)) {
1130 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1131 return MatchOperand_NoMatch;
1132 }
1133 Res = V;
1134 } else
1135 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Alex Bradbury68f73c12018-09-18 15:18:16 +00001136 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1137 return MatchOperand_Success;
1138}
1139
Alex Bradbury226f3ef2018-09-20 08:10:35 +00001140OperandMatchResultTy RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
1141 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
1142 // both being acceptable forms. When parsing `jal ra, foo` this function
1143 // will be called for the `ra` register operand in an attempt to match the
1144 // single-operand alias. parseJALOffset must fail for this case. It would
1145 // seem logical to try parse the operand using parseImmediate and return
1146 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
1147 // the second form rather than the first). We can't do this as there's no
1148 // way of rewinding the lexer state. Instead, return NoMatch if this operand
1149 // is an identifier and is followed by a comma.
1150 if (getLexer().is(AsmToken::Identifier) &&
1151 getLexer().peekTok().is(AsmToken::Comma))
1152 return MatchOperand_NoMatch;
1153
1154 return parseImmediate(Operands);
1155}
1156
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001157OperandMatchResultTy
1158RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
1159 if (getLexer().isNot(AsmToken::LParen)) {
1160 Error(getLoc(), "expected '('");
Alex Bradbury04f06d92017-08-08 14:43:36 +00001161 return MatchOperand_ParseFail;
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001162 }
Alex Bradbury04f06d92017-08-08 14:43:36 +00001163
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001164 getParser().Lex(); // Eat '('
Alex Bradburya6e62482017-12-07 10:53:48 +00001165 Operands.push_back(RISCVOperand::createToken("(", getLoc(), isRV64()));
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001166
1167 if (parseRegister(Operands) != MatchOperand_Success) {
1168 Error(getLoc(), "expected register");
1169 return MatchOperand_ParseFail;
1170 }
1171
1172 if (getLexer().isNot(AsmToken::RParen)) {
1173 Error(getLoc(), "expected ')'");
1174 return MatchOperand_ParseFail;
1175 }
1176
1177 getParser().Lex(); // Eat ')'
Alex Bradburya6e62482017-12-07 10:53:48 +00001178 Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001179
Alex Bradbury04f06d92017-08-08 14:43:36 +00001180 return MatchOperand_Success;
1181}
1182
Alex Bradburycd8688a2018-04-25 17:25:29 +00001183/// Looks at a token type and creates the relevant operand from this
1184/// information, adding to Operands. If operand was parsed, returns false, else
Alex Bradbury68f73c12018-09-18 15:18:16 +00001185/// true.
1186bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1187 // Check if the current operand has a custom associated parser, if so, try to
1188 // custom parse the operand, or fallback to the general approach.
1189 OperandMatchResultTy Result =
1190 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
1191 if (Result == MatchOperand_Success)
1192 return false;
1193 if (Result == MatchOperand_ParseFail)
1194 return true;
1195
1196 // Attempt to parse token as a register.
1197 if (parseRegister(Operands, true) == MatchOperand_Success)
Alex Bradbury04f06d92017-08-08 14:43:36 +00001198 return false;
1199
1200 // Attempt to parse token as an immediate
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001201 if (parseImmediate(Operands) == MatchOperand_Success) {
1202 // Parse memory base register if present
1203 if (getLexer().is(AsmToken::LParen))
1204 return parseMemOpBaseReg(Operands) != MatchOperand_Success;
Alex Bradbury04f06d92017-08-08 14:43:36 +00001205 return false;
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001206 }
Alex Bradbury04f06d92017-08-08 14:43:36 +00001207
1208 // Finally we have exhausted all options and must declare defeat.
1209 Error(getLoc(), "unknown operand");
1210 return true;
1211}
1212
1213bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
1214 StringRef Name, SMLoc NameLoc,
1215 OperandVector &Operands) {
Alex Bradbury9c03e4c2018-11-12 14:25:07 +00001216 // Ensure that if the instruction occurs when relaxation is enabled,
1217 // relocations are forced for the file. Ideally this would be done when there
1218 // is enough information to reliably determine if the instruction itself may
1219 // cause relaxations. Unfortunately instruction processing stage occurs in the
1220 // same pass as relocation emission, so it's too late to set a 'sticky bit'
1221 // for the entire file.
1222 if (getSTI().getFeatureBits()[RISCV::FeatureRelax]) {
1223 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
1224 if (Assembler != nullptr) {
1225 RISCVAsmBackend &MAB =
1226 static_cast<RISCVAsmBackend &>(Assembler->getBackend());
1227 MAB.setForceRelocs();
1228 }
1229 }
1230
Alex Bradbury04f06d92017-08-08 14:43:36 +00001231 // First operand is token for instruction
Alex Bradburya6e62482017-12-07 10:53:48 +00001232 Operands.push_back(RISCVOperand::createToken(Name, NameLoc, isRV64()));
Alex Bradbury04f06d92017-08-08 14:43:36 +00001233
1234 // If there are no more operands, then finish
1235 if (getLexer().is(AsmToken::EndOfStatement))
1236 return false;
1237
1238 // Parse first operand
Alex Bradbury68f73c12018-09-18 15:18:16 +00001239 if (parseOperand(Operands, Name))
Alex Bradbury04f06d92017-08-08 14:43:36 +00001240 return true;
1241
1242 // Parse until end of statement, consuming commas between operands
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001243 unsigned OperandIdx = 1;
Alex Bradbury04f06d92017-08-08 14:43:36 +00001244 while (getLexer().is(AsmToken::Comma)) {
1245 // Consume comma token
1246 getLexer().Lex();
1247
1248 // Parse next operand
Alex Bradbury68f73c12018-09-18 15:18:16 +00001249 if (parseOperand(Operands, Name))
Alex Bradbury04f06d92017-08-08 14:43:36 +00001250 return true;
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001251
1252 ++OperandIdx;
Alex Bradbury04f06d92017-08-08 14:43:36 +00001253 }
1254
1255 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1256 SMLoc Loc = getLexer().getLoc();
1257 getParser().eatToEndOfStatement();
1258 return Error(Loc, "unexpected token");
1259 }
1260
1261 getParser().Lex(); // Consume the EndOfStatement.
1262 return false;
1263}
1264
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001265bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
1266 RISCVMCExpr::VariantKind &Kind,
1267 int64_t &Addend) {
1268 Kind = RISCVMCExpr::VK_RISCV_None;
1269 Addend = 0;
1270
1271 if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
1272 Kind = RE->getKind();
1273 Expr = RE->getSubExpr();
1274 }
1275
1276 // It's a simple symbol reference or constant with no addend.
1277 if (isa<MCConstantExpr>(Expr) || isa<MCSymbolRefExpr>(Expr))
1278 return true;
1279
1280 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
1281 if (!BE)
1282 return false;
1283
1284 if (!isa<MCSymbolRefExpr>(BE->getLHS()))
1285 return false;
1286
1287 if (BE->getOpcode() != MCBinaryExpr::Add &&
1288 BE->getOpcode() != MCBinaryExpr::Sub)
1289 return false;
1290
1291 // We are able to support the subtraction of two symbol references
1292 if (BE->getOpcode() == MCBinaryExpr::Sub &&
1293 isa<MCSymbolRefExpr>(BE->getRHS()))
1294 return true;
1295
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00001296 // See if the addend is a constant, otherwise there's more going
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001297 // on here than we can deal with.
1298 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
1299 if (!AddendExpr)
1300 return false;
1301
1302 Addend = AddendExpr->getValue();
1303 if (BE->getOpcode() == MCBinaryExpr::Sub)
1304 Addend = -Addend;
1305
1306 // It's some symbol reference + a constant addend
1307 return Kind != RISCVMCExpr::VK_RISCV_Invalid;
1308}
1309
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001310bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
1311 // This returns false if this function recognizes the directive
1312 // regardless of whether it is successfully handles or reports an
1313 // error. Otherwise it returns true to give the generic parser a
1314 // chance at recognizing it.
1315 StringRef IDVal = DirectiveID.getString();
1316
1317 if (IDVal == ".option")
1318 return parseDirectiveOption();
1319
1320 return true;
1321}
1322
1323bool RISCVAsmParser::parseDirectiveOption() {
1324 MCAsmParser &Parser = getParser();
1325 // Get the option token.
1326 AsmToken Tok = Parser.getTok();
1327 // At the moment only identifiers are supported.
1328 if (Tok.isNot(AsmToken::Identifier))
1329 return Error(Parser.getTok().getLoc(),
1330 "unexpected token, expected identifier");
1331
1332 StringRef Option = Tok.getIdentifier();
1333
Alex Bradbury893e5bc2018-11-28 16:39:14 +00001334 if (Option == "push") {
1335 getTargetStreamer().emitDirectiveOptionPush();
1336
1337 Parser.Lex();
1338 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1339 return Error(Parser.getTok().getLoc(),
1340 "unexpected token, expected end of statement");
1341
1342 pushFeatureBits();
1343 return false;
1344 }
1345
1346 if (Option == "pop") {
1347 SMLoc StartLoc = Parser.getTok().getLoc();
1348 getTargetStreamer().emitDirectiveOptionPop();
1349
1350 Parser.Lex();
1351 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1352 return Error(Parser.getTok().getLoc(),
1353 "unexpected token, expected end of statement");
1354
1355 if (popFeatureBits())
1356 return Error(StartLoc, ".option pop with no .option push");
1357
1358 return false;
1359 }
1360
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001361 if (Option == "rvc") {
1362 getTargetStreamer().emitDirectiveOptionRVC();
1363
1364 Parser.Lex();
1365 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1366 return Error(Parser.getTok().getLoc(),
1367 "unexpected token, expected end of statement");
1368
1369 setFeatureBits(RISCV::FeatureStdExtC, "c");
1370 return false;
1371 }
1372
1373 if (Option == "norvc") {
1374 getTargetStreamer().emitDirectiveOptionNoRVC();
1375
1376 Parser.Lex();
1377 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1378 return Error(Parser.getTok().getLoc(),
1379 "unexpected token, expected end of statement");
1380
1381 clearFeatureBits(RISCV::FeatureStdExtC, "c");
1382 return false;
1383 }
1384
Alex Bradbury9c03e4c2018-11-12 14:25:07 +00001385 if (Option == "relax") {
1386 getTargetStreamer().emitDirectiveOptionRelax();
1387
1388 Parser.Lex();
1389 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1390 return Error(Parser.getTok().getLoc(),
1391 "unexpected token, expected end of statement");
1392
1393 setFeatureBits(RISCV::FeatureRelax, "relax");
1394 return false;
1395 }
1396
1397 if (Option == "norelax") {
1398 getTargetStreamer().emitDirectiveOptionNoRelax();
1399
1400 Parser.Lex();
1401 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1402 return Error(Parser.getTok().getLoc(),
1403 "unexpected token, expected end of statement");
1404
1405 clearFeatureBits(RISCV::FeatureRelax, "relax");
1406 return false;
1407 }
1408
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001409 // Unknown option.
1410 Warning(Parser.getTok().getLoc(),
Alex Bradbury893e5bc2018-11-28 16:39:14 +00001411 "unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'relax' or "
1412 "'norelax'");
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001413 Parser.eatToEndOfStatement();
1414 return false;
1415}
Alex Bradbury04f06d92017-08-08 14:43:36 +00001416
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001417void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
1418 MCInst CInst;
1419 bool Res = compressInst(CInst, Inst, getSTI(), S.getContext());
1420 CInst.setLoc(Inst.getLoc());
1421 S.EmitInstruction((Res ? CInst : Inst), getSTI());
1422}
1423
1424void RISCVAsmParser::emitLoadImm(unsigned DestReg, int64_t Value,
1425 MCStreamer &Out) {
Alex Bradbury22c091f2018-11-15 10:11:31 +00001426 RISCVMatInt::InstSeq Seq;
1427 RISCVMatInt::generateInstSeq(Value, isRV64(), Seq);
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001428
Alex Bradbury22c091f2018-11-15 10:11:31 +00001429 unsigned SrcReg = RISCV::X0;
1430 for (RISCVMatInt::Inst &Inst : Seq) {
1431 if (Inst.Opc == RISCV::LUI) {
1432 emitToStreamer(
1433 Out, MCInstBuilder(RISCV::LUI).addReg(DestReg).addImm(Inst.Imm));
1434 } else {
1435 emitToStreamer(
1436 Out, MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm(
1437 Inst.Imm));
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001438 }
1439
Alex Bradbury22c091f2018-11-15 10:11:31 +00001440 // Only the first instruction has X0 as its source.
1441 SrcReg = DestReg;
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001442 }
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001443}
1444
Alex Bradbury22531c42019-02-15 09:53:32 +00001445void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
1446 const MCExpr *Symbol,
1447 RISCVMCExpr::VariantKind VKHi,
1448 unsigned SecondOpcode, SMLoc IDLoc,
1449 MCStreamer &Out) {
1450 // A pair of instructions for PC-relative addressing; expands to
1451 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
1452 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001453 MCContext &Ctx = getContext();
1454
1455 MCSymbol *TmpLabel = Ctx.createTempSymbol(
1456 "pcrel_hi", /* AlwaysAddSuffix */ true, /* CanBeUnnamed */ false);
1457 Out.EmitLabel(TmpLabel);
1458
Alex Bradbury22531c42019-02-15 09:53:32 +00001459 const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
Roger Ferrer Ibanezc8f4dbb2018-08-14 08:30:42 +00001460 emitToStreamer(
Alex Bradbury22531c42019-02-15 09:53:32 +00001461 Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001462
1463 const MCExpr *RefToLinkTmpLabel =
1464 RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),
1465 RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
1466
Alex Bradbury22531c42019-02-15 09:53:32 +00001467 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
Roger Ferrer Ibanezc8f4dbb2018-08-14 08:30:42 +00001468 .addOperand(DestReg)
Alex Bradbury22531c42019-02-15 09:53:32 +00001469 .addOperand(TmpReg)
Roger Ferrer Ibanezc8f4dbb2018-08-14 08:30:42 +00001470 .addExpr(RefToLinkTmpLabel));
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001471}
1472
Alex Bradbury22531c42019-02-15 09:53:32 +00001473void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
1474 MCStreamer &Out) {
1475 // The load local address pseudo-instruction "lla" is used in PC-relative
1476 // addressing of local symbols:
1477 // lla rdest, symbol
1478 // expands to
1479 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
1480 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
1481 MCOperand DestReg = Inst.getOperand(0);
1482 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1483 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
1484 RISCV::ADDI, IDLoc, Out);
1485}
1486
1487void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
1488 MCStreamer &Out) {
1489 // The load address pseudo-instruction "la" is used in PC-relative and
1490 // GOT-indirect addressing of global symbols:
1491 // la rdest, symbol
1492 // expands to either (for non-PIC)
1493 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
1494 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
1495 // or (for PIC)
1496 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
1497 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
1498 MCOperand DestReg = Inst.getOperand(0);
1499 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1500 unsigned SecondOpcode;
1501 RISCVMCExpr::VariantKind VKHi;
1502 // FIXME: Should check .option (no)pic when implemented
1503 if (getContext().getObjectFileInfo()->isPositionIndependent()) {
1504 SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
1505 VKHi = RISCVMCExpr::VK_RISCV_GOT_HI;
1506 } else {
1507 SecondOpcode = RISCV::ADDI;
1508 VKHi = RISCVMCExpr::VK_RISCV_PCREL_HI;
1509 }
1510 emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out);
1511}
1512
Kito Cheng303217e2019-02-20 03:31:32 +00001513void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
1514 SMLoc IDLoc, MCStreamer &Out,
1515 bool HasTmpReg) {
1516 // The load/store pseudo-instruction does a pc-relative load with
1517 // a symbol.
1518 //
1519 // The expansion looks like this
1520 //
1521 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
1522 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
1523 MCOperand DestReg = Inst.getOperand(0);
1524 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
1525 unsigned TmpRegOpIdx = HasTmpReg ? 1 : 0;
1526 MCOperand TmpReg = Inst.getOperand(TmpRegOpIdx);
1527 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
1528 emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
1529 Opcode, IDLoc, Out);
1530}
1531
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001532bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1533 MCStreamer &Out) {
1534 Inst.setLoc(IDLoc);
1535
Alex Bradbury22531c42019-02-15 09:53:32 +00001536 switch (Inst.getOpcode()) {
1537 default:
1538 break;
1539 case RISCV::PseudoLI: {
Alex Bradbury2ba76be2019-01-03 14:41:41 +00001540 unsigned Reg = Inst.getOperand(0).getReg();
1541 const MCOperand &Op1 = Inst.getOperand(1);
1542 if (Op1.isExpr()) {
1543 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
1544 // Just convert to an addi. This allows compatibility with gas.
1545 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
1546 .addReg(Reg)
1547 .addReg(RISCV::X0)
1548 .addExpr(Op1.getExpr()));
1549 return false;
1550 }
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001551 int64_t Imm = Inst.getOperand(1).getImm();
1552 // On RV32 the immediate here can either be a signed or an unsigned
1553 // 32-bit number. Sign extension has to be performed to ensure that Imm
1554 // represents the expected signed 64-bit number.
1555 if (!isRV64())
1556 Imm = SignExtend64<32>(Imm);
1557 emitLoadImm(Reg, Imm, Out);
1558 return false;
Alex Bradbury22531c42019-02-15 09:53:32 +00001559 }
1560 case RISCV::PseudoLLA:
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001561 emitLoadLocalAddress(Inst, IDLoc, Out);
1562 return false;
Alex Bradbury22531c42019-02-15 09:53:32 +00001563 case RISCV::PseudoLA:
1564 emitLoadAddress(Inst, IDLoc, Out);
1565 return false;
Kito Cheng303217e2019-02-20 03:31:32 +00001566 case RISCV::PseudoLB:
1567 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
1568 return false;
1569 case RISCV::PseudoLBU:
1570 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
1571 return false;
1572 case RISCV::PseudoLH:
1573 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
1574 return false;
1575 case RISCV::PseudoLHU:
1576 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
1577 return false;
1578 case RISCV::PseudoLW:
1579 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
1580 return false;
1581 case RISCV::PseudoLWU:
1582 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
1583 return false;
1584 case RISCV::PseudoLD:
1585 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
1586 return false;
1587 case RISCV::PseudoFLW:
1588 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
1589 return false;
1590 case RISCV::PseudoFLD:
1591 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
1592 return false;
1593 case RISCV::PseudoSB:
1594 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
1595 return false;
1596 case RISCV::PseudoSH:
1597 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
1598 return false;
1599 case RISCV::PseudoSW:
1600 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
1601 return false;
1602 case RISCV::PseudoSD:
1603 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
1604 return false;
1605 case RISCV::PseudoFSW:
1606 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
1607 return false;
1608 case RISCV::PseudoFSD:
1609 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
1610 return false;
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001611 }
1612
1613 emitToStreamer(Out, Inst);
1614 return false;
1615}
1616
Alex Bradbury04f06d92017-08-08 14:43:36 +00001617extern "C" void LLVMInitializeRISCVAsmParser() {
1618 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
1619 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
1620}