blob: 1d1112cc512499ff2efe6948c219ab3ccb862e31 [file] [log] [blame]
Alex Bradbury04f06d92017-08-08 14:43:36 +00001//===-- RISCVAsmParser.cpp - Parse RISCV assembly to MCInst instructions --===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Alex Bradbury9c03e4c2018-11-12 14:25:07 +000010#include "MCTargetDesc/RISCVAsmBackend.h"
Alex Bradbury9d3f1252017-09-28 08:26:24 +000011#include "MCTargetDesc/RISCVMCExpr.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000012#include "MCTargetDesc/RISCVMCTargetDesc.h"
Alex Bradburybca0c3c2018-05-11 17:30:28 +000013#include "MCTargetDesc/RISCVTargetStreamer.h"
Ana Pazos9d6c5532018-10-04 21:50:54 +000014#include "Utils/RISCVBaseInfo.h"
Alex Bradbury22c091f2018-11-15 10:11:31 +000015#include "Utils/RISCVMatInt.h"
Alex Bradbury4f7f0da2017-09-06 09:21:21 +000016#include "llvm/ADT/STLExtras.h"
Alex Bradbury893e5bc2018-11-28 16:39:14 +000017#include "llvm/ADT/SmallVector.h"
Alex Bradbury4f7f0da2017-09-06 09:21:21 +000018#include "llvm/ADT/StringSwitch.h"
Alex Bradbury9c03e4c2018-11-12 14:25:07 +000019#include "llvm/MC/MCAssembler.h"
Alex Bradbury4f7f0da2017-09-06 09:21:21 +000020#include "llvm/MC/MCContext.h"
21#include "llvm/MC/MCExpr.h"
22#include "llvm/MC/MCInst.h"
Alex Bradbury6a4b5442018-06-07 15:35:47 +000023#include "llvm/MC/MCInstBuilder.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
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +000082 // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
83 void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
84
Alex Bradbury6a4b5442018-06-07 15:35:47 +000085 /// Helper for processing MC instructions that have been successfully matched
86 /// by MatchAndEmitInstruction. Modifications to the emitted instructions,
87 /// like the expansion of pseudo instructions (e.g., "li"), can be performed
88 /// in this method.
89 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
90
Alex Bradbury04f06d92017-08-08 14:43:36 +000091// Auto-generated instruction matching functions
92#define GET_ASSEMBLER_HEADER
93#include "RISCVGenAsmMatcher.inc"
94
Ana Pazos9d6c5532018-10-04 21:50:54 +000095 OperandMatchResultTy parseCSRSystemRegister(OperandVector &Operands);
Alex Bradbury04f06d92017-08-08 14:43:36 +000096 OperandMatchResultTy parseImmediate(OperandVector &Operands);
Alex Bradbury8c345c52017-11-09 15:00:03 +000097 OperandMatchResultTy parseRegister(OperandVector &Operands,
98 bool AllowParens = false);
Alex Bradbury6758ecb2017-09-17 14:27:35 +000099 OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000100 OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
Alex Bradbury68f73c12018-09-18 15:18:16 +0000101 OperandMatchResultTy parseBareSymbol(OperandVector &Operands);
Alex Bradbury226f3ef2018-09-20 08:10:35 +0000102 OperandMatchResultTy parseJALOffset(OperandVector &Operands);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000103
Alex Bradbury68f73c12018-09-18 15:18:16 +0000104 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000105
Alex Bradburybca0c3c2018-05-11 17:30:28 +0000106 bool parseDirectiveOption();
107
108 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
109 if (!(getSTI().getFeatureBits()[Feature])) {
110 MCSubtargetInfo &STI = copySTI();
111 setAvailableFeatures(
112 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
113 }
114 }
115
116 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
117 if (getSTI().getFeatureBits()[Feature]) {
118 MCSubtargetInfo &STI = copySTI();
119 setAvailableFeatures(
120 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
121 }
122 }
Ana Pazos9d6c5532018-10-04 21:50:54 +0000123
Alex Bradbury893e5bc2018-11-28 16:39:14 +0000124 void pushFeatureBits() {
125 FeatureBitStack.push_back(getSTI().getFeatureBits());
126 }
127
128 bool popFeatureBits() {
129 if (FeatureBitStack.empty())
130 return true;
131
132 FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
133 copySTI().setFeatureBits(FeatureBits);
134 setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
135
136 return false;
137 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000138public:
139 enum RISCVMatchResultTy {
140 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
141#define GET_OPERAND_DIAGNOSTIC_TYPES
142#include "RISCVGenAsmMatcher.inc"
143#undef GET_OPERAND_DIAGNOSTIC_TYPES
144 };
145
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000146 static bool classifySymbolRef(const MCExpr *Expr,
147 RISCVMCExpr::VariantKind &Kind,
148 int64_t &Addend);
149
Alex Bradbury04f06d92017-08-08 14:43:36 +0000150 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
151 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000152 : MCTargetAsmParser(Options, STI, MII) {
Alex Bradburycea6db02018-05-17 05:58:08 +0000153 Parser.addAliasForDirective(".half", ".2byte");
154 Parser.addAliasForDirective(".hword", ".2byte");
155 Parser.addAliasForDirective(".word", ".4byte");
156 Parser.addAliasForDirective(".dword", ".8byte");
Alex Bradbury04f06d92017-08-08 14:43:36 +0000157 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
158 }
159};
160
161/// RISCVOperand - Instances of this class represent a parsed machine
162/// instruction
163struct RISCVOperand : public MCParsedAsmOperand {
164
165 enum KindTy {
166 Token,
167 Register,
168 Immediate,
Ana Pazos9d6c5532018-10-04 21:50:54 +0000169 SystemRegister
Alex Bradbury04f06d92017-08-08 14:43:36 +0000170 } Kind;
171
Alex Bradburya6e62482017-12-07 10:53:48 +0000172 bool IsRV64;
173
Alex Bradbury04f06d92017-08-08 14:43:36 +0000174 struct RegOp {
175 unsigned RegNum;
176 };
177
178 struct ImmOp {
179 const MCExpr *Val;
180 };
181
Ana Pazos9d6c5532018-10-04 21:50:54 +0000182 struct SysRegOp {
183 const char *Data;
184 unsigned Length;
185 unsigned Encoding;
186 // FIXME: Add the Encoding parsed fields as needed for checks,
187 // e.g.: read/write or user/supervisor/machine privileges.
188 };
189
Alex Bradbury04f06d92017-08-08 14:43:36 +0000190 SMLoc StartLoc, EndLoc;
191 union {
192 StringRef Tok;
193 RegOp Reg;
194 ImmOp Imm;
Ana Pazos9d6c5532018-10-04 21:50:54 +0000195 struct SysRegOp SysReg;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000196 };
197
198 RISCVOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
199
200public:
201 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
202 Kind = o.Kind;
Alex Bradburya6e62482017-12-07 10:53:48 +0000203 IsRV64 = o.IsRV64;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000204 StartLoc = o.StartLoc;
205 EndLoc = o.EndLoc;
206 switch (Kind) {
207 case Register:
208 Reg = o.Reg;
209 break;
210 case Immediate:
211 Imm = o.Imm;
212 break;
213 case Token:
214 Tok = o.Tok;
215 break;
Ana Pazos9d6c5532018-10-04 21:50:54 +0000216 case SystemRegister:
217 SysReg = o.SysReg;
218 break;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000219 }
220 }
221
222 bool isToken() const override { return Kind == Token; }
223 bool isReg() const override { return Kind == Register; }
224 bool isImm() const override { return Kind == Immediate; }
225 bool isMem() const override { return false; }
Ana Pazos9d6c5532018-10-04 21:50:54 +0000226 bool isSystemRegister() const { return Kind == SystemRegister; }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000227
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000228 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
229 RISCVMCExpr::VariantKind &VK) {
230 if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000231 VK = RE->getKind();
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000232 return RE->evaluateAsConstant(Imm);
233 }
234
235 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000236 VK = RISCVMCExpr::VK_RISCV_None;
237 Imm = CE->getValue();
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000238 return true;
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000239 }
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000240
241 return false;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000242 }
243
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000244 // True if operand is a symbol with no modifiers, or a constant with no
245 // modifiers and isShiftedInt<N-1, 1>(Op).
246 template <int N> bool isBareSimmNLsb0() const {
247 int64_t Imm;
248 RISCVMCExpr::VariantKind VK;
Alex Bradbury3c941e72017-10-19 16:22:51 +0000249 if (!isImm())
250 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000251 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000252 bool IsValid;
253 if (!IsConstantImm)
254 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
255 else
256 IsValid = isShiftedInt<N - 1, 1>(Imm);
257 return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000258 }
259
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000260 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
261
Shiva Chen98f93892018-04-25 14:18:55 +0000262 bool isBareSymbol() const {
263 int64_t Imm;
264 RISCVMCExpr::VariantKind VK;
265 // Must be of 'immediate' type but not a constant.
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000266 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
Shiva Chen98f93892018-04-25 14:18:55 +0000267 return false;
268 return RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm) &&
269 VK == RISCVMCExpr::VK_RISCV_None;
270 }
271
Ana Pazos9d6c5532018-10-04 21:50:54 +0000272 bool isCSRSystemRegister() const { return isSystemRegister(); }
273
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000274 /// Return true if the operand is a valid for the fence instruction e.g.
275 /// ('iorw').
276 bool isFenceArg() const {
277 if (!isImm())
278 return false;
279 const MCExpr *Val = getImm();
280 auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
281 if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
282 return false;
283
284 StringRef Str = SVal->getSymbol().getName();
285 // Letters must be unique, taken from 'iorw', and in ascending order. This
286 // holds as long as each individual character is one of 'iorw' and is
287 // greater than the previous character.
288 char Prev = '\0';
289 for (char c : Str) {
290 if (c != 'i' && c != 'o' && c != 'r' && c != 'w')
291 return false;
292 if (c <= Prev)
293 return false;
294 Prev = c;
295 }
296 return true;
297 }
298
Alex Bradbury0d6cf902017-12-07 10:26:05 +0000299 /// Return true if the operand is a valid floating point rounding mode.
300 bool isFRMArg() const {
301 if (!isImm())
302 return false;
303 const MCExpr *Val = getImm();
304 auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
305 if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
306 return false;
307
308 StringRef Str = SVal->getSymbol().getName();
309
310 return RISCVFPRndMode::stringToRoundingMode(Str) != RISCVFPRndMode::Invalid;
311 }
312
Alex Bradbury2ba76be2019-01-03 14:41:41 +0000313 bool isImmXLenLI() const {
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000314 int64_t Imm;
315 RISCVMCExpr::VariantKind VK;
316 if (!isImm())
317 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000318 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury2ba76be2019-01-03 14:41:41 +0000319 if (VK == RISCVMCExpr::VK_RISCV_LO || VK == RISCVMCExpr::VK_RISCV_PCREL_LO)
320 return true;
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000321 // Given only Imm, ensuring that the actually specified constant is either
322 // a signed or unsigned 64-bit number is unfortunately impossible.
323 bool IsInRange = isRV64() ? true : isInt<32>(Imm) || isUInt<32>(Imm);
324 return IsConstantImm && IsInRange && VK == RISCVMCExpr::VK_RISCV_None;
325 }
326
Alex Bradburya6e62482017-12-07 10:53:48 +0000327 bool isUImmLog2XLen() const {
328 int64_t Imm;
329 RISCVMCExpr::VariantKind VK;
330 if (!isImm())
331 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000332 if (!evaluateConstantImm(getImm(), Imm, VK) ||
333 VK != RISCVMCExpr::VK_RISCV_None)
Alex Bradburya6e62482017-12-07 10:53:48 +0000334 return false;
335 return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm);
336 }
337
Alex Bradbury0ad4c262017-12-15 10:20:51 +0000338 bool isUImmLog2XLenNonZero() const {
339 int64_t Imm;
340 RISCVMCExpr::VariantKind VK;
341 if (!isImm())
342 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000343 if (!evaluateConstantImm(getImm(), Imm, VK) ||
344 VK != RISCVMCExpr::VK_RISCV_None)
Alex Bradbury0ad4c262017-12-15 10:20:51 +0000345 return false;
346 if (Imm == 0)
347 return false;
348 return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm);
349 }
350
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000351 bool isUImm5() const {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000352 int64_t Imm;
353 RISCVMCExpr::VariantKind VK;
Alex Bradbury3c941e72017-10-19 16:22:51 +0000354 if (!isImm())
355 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000356 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000357 return IsConstantImm && isUInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000358 }
359
Alex Bradbury60714f92017-12-13 09:32:55 +0000360 bool isUImm5NonZero() const {
361 int64_t Imm;
362 RISCVMCExpr::VariantKind VK;
363 if (!isImm())
364 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000365 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury60714f92017-12-13 09:32:55 +0000366 return IsConstantImm && isUInt<5>(Imm) && (Imm != 0) &&
367 VK == RISCVMCExpr::VK_RISCV_None;
368 }
369
Alex Bradbury581d6b02017-12-13 09:41:21 +0000370 bool isSImm6() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000371 if (!isImm())
372 return false;
Alex Bradbury581d6b02017-12-13 09:41:21 +0000373 RISCVMCExpr::VariantKind VK;
374 int64_t Imm;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000375 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Ana Pazos065b0882018-09-13 18:37:23 +0000376 return IsConstantImm && isInt<6>(Imm) &&
377 VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury581d6b02017-12-13 09:41:21 +0000378 }
379
Shiva Chenb22c1d22018-02-02 02:43:23 +0000380 bool isSImm6NonZero() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000381 if (!isImm())
382 return false;
Shiva Chenb22c1d22018-02-02 02:43:23 +0000383 RISCVMCExpr::VariantKind VK;
384 int64_t Imm;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000385 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Ana Pazos065b0882018-09-13 18:37:23 +0000386 return IsConstantImm && isInt<6>(Imm) && (Imm != 0) &&
387 VK == RISCVMCExpr::VK_RISCV_None;
Shiva Chenb22c1d22018-02-02 02:43:23 +0000388 }
389
Shiva Chen7c172422018-02-22 15:02:28 +0000390 bool isCLUIImm() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000391 if (!isImm())
392 return false;
Alex Bradbury60714f92017-12-13 09:32:55 +0000393 int64_t Imm;
394 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000395 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Shiva Chen7c172422018-02-22 15:02:28 +0000396 return IsConstantImm && (Imm != 0) &&
397 (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
Ana Pazos9d6c5532018-10-04 21:50:54 +0000398 VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury60714f92017-12-13 09:32:55 +0000399 }
400
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000401 bool isUImm7Lsb00() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000402 if (!isImm())
403 return false;
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000404 int64_t Imm;
405 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000406 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000407 return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
408 VK == RISCVMCExpr::VK_RISCV_None;
409 }
410
411 bool isUImm8Lsb00() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000412 if (!isImm())
413 return false;
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000414 int64_t Imm;
415 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000416 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000417 return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
418 VK == RISCVMCExpr::VK_RISCV_None;
419 }
420
421 bool isUImm8Lsb000() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000422 if (!isImm())
423 return false;
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000424 int64_t Imm;
425 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000426 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000427 return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
428 VK == RISCVMCExpr::VK_RISCV_None;
429 }
430
Alex Bradburyf8f4b902017-12-07 13:19:57 +0000431 bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
432
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000433 bool isUImm9Lsb000() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000434 if (!isImm())
435 return false;
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000436 int64_t Imm;
437 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000438 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000439 return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
440 VK == RISCVMCExpr::VK_RISCV_None;
441 }
442
Alex Bradbury60714f92017-12-13 09:32:55 +0000443 bool isUImm10Lsb00NonZero() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000444 if (!isImm())
445 return false;
Alex Bradbury60714f92017-12-13 09:32:55 +0000446 int64_t Imm;
447 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000448 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury60714f92017-12-13 09:32:55 +0000449 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
450 VK == RISCVMCExpr::VK_RISCV_None;
451 }
452
Alex Bradbury04f06d92017-08-08 14:43:36 +0000453 bool isSImm12() const {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000454 RISCVMCExpr::VariantKind VK;
455 int64_t Imm;
456 bool IsValid;
Alex Bradbury3c941e72017-10-19 16:22:51 +0000457 if (!isImm())
458 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000459 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000460 if (!IsConstantImm)
461 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
462 else
463 IsValid = isInt<12>(Imm);
Alex Bradbury7d0e18d2018-09-18 15:13:29 +0000464 return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
Ahmed Charles646ab872018-02-06 00:55:23 +0000465 VK == RISCVMCExpr::VK_RISCV_LO ||
466 VK == RISCVMCExpr::VK_RISCV_PCREL_LO);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000467 }
468
Alex Bradburyf8f4b902017-12-07 13:19:57 +0000469 bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
470
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000471 bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000472
Shiva Chenb22c1d22018-02-02 02:43:23 +0000473 bool isSImm10Lsb0000NonZero() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000474 if (!isImm())
475 return false;
Alex Bradbury60714f92017-12-13 09:32:55 +0000476 int64_t Imm;
477 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000478 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Shiva Chenb22c1d22018-02-02 02:43:23 +0000479 return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) &&
Alex Bradbury60714f92017-12-13 09:32:55 +0000480 VK == RISCVMCExpr::VK_RISCV_None;
481 }
482
Alex Bradbury74340f12018-09-18 15:08:35 +0000483 bool isUImm20LUI() const {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000484 RISCVMCExpr::VariantKind VK;
485 int64_t Imm;
486 bool IsValid;
Alex Bradbury3c941e72017-10-19 16:22:51 +0000487 if (!isImm())
488 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000489 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury74340f12018-09-18 15:08:35 +0000490 if (!IsConstantImm) {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000491 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
Alex Bradbury74340f12018-09-18 15:08:35 +0000492 return IsValid && VK == RISCVMCExpr::VK_RISCV_HI;
493 } else {
494 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
495 VK == RISCVMCExpr::VK_RISCV_HI);
496 }
497 }
498
499 bool isUImm20AUIPC() const {
500 RISCVMCExpr::VariantKind VK;
501 int64_t Imm;
502 bool IsValid;
503 if (!isImm())
504 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000505 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury74340f12018-09-18 15:08:35 +0000506 if (!IsConstantImm) {
507 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
508 return IsValid && VK == RISCVMCExpr::VK_RISCV_PCREL_HI;
509 } else {
510 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
511 VK == RISCVMCExpr::VK_RISCV_PCREL_HI);
512 }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000513 }
514
Alex Bradbury226f3ef2018-09-20 08:10:35 +0000515 bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000516
Alex Bradbury04f06d92017-08-08 14:43:36 +0000517 /// getStartLoc - Gets location of the first token of this operand
518 SMLoc getStartLoc() const override { return StartLoc; }
519 /// getEndLoc - Gets location of the last token of this operand
520 SMLoc getEndLoc() const override { return EndLoc; }
Alex Bradburya6e62482017-12-07 10:53:48 +0000521 /// True if this operand is for an RV64 instruction
522 bool isRV64() const { return IsRV64; }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000523
524 unsigned getReg() const override {
525 assert(Kind == Register && "Invalid type access!");
526 return Reg.RegNum;
527 }
528
Ana Pazos9d6c5532018-10-04 21:50:54 +0000529 StringRef getSysReg() const {
530 assert(Kind == SystemRegister && "Invalid access!");
531 return StringRef(SysReg.Data, SysReg.Length);
532 }
533
Alex Bradbury04f06d92017-08-08 14:43:36 +0000534 const MCExpr *getImm() const {
535 assert(Kind == Immediate && "Invalid type access!");
536 return Imm.Val;
537 }
538
539 StringRef getToken() const {
540 assert(Kind == Token && "Invalid type access!");
541 return Tok;
542 }
543
544 void print(raw_ostream &OS) const override {
545 switch (Kind) {
546 case Immediate:
547 OS << *getImm();
548 break;
549 case Register:
550 OS << "<register x";
551 OS << getReg() << ">";
552 break;
553 case Token:
554 OS << "'" << getToken() << "'";
555 break;
Ana Pazos9d6c5532018-10-04 21:50:54 +0000556 case SystemRegister:
557 OS << "<sysreg: " << getSysReg() << '>';
558 break;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000559 }
560 }
561
Alex Bradburya6e62482017-12-07 10:53:48 +0000562 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S,
563 bool IsRV64) {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000564 auto Op = make_unique<RISCVOperand>(Token);
565 Op->Tok = Str;
566 Op->StartLoc = S;
567 Op->EndLoc = S;
Alex Bradburya6e62482017-12-07 10:53:48 +0000568 Op->IsRV64 = IsRV64;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000569 return Op;
570 }
571
572 static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S,
Alex Bradburya6e62482017-12-07 10:53:48 +0000573 SMLoc E, bool IsRV64) {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000574 auto Op = make_unique<RISCVOperand>(Register);
575 Op->Reg.RegNum = RegNo;
576 Op->StartLoc = S;
577 Op->EndLoc = E;
Alex Bradburya6e62482017-12-07 10:53:48 +0000578 Op->IsRV64 = IsRV64;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000579 return Op;
580 }
581
582 static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
Alex Bradburya6e62482017-12-07 10:53:48 +0000583 SMLoc E, bool IsRV64) {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000584 auto Op = make_unique<RISCVOperand>(Immediate);
585 Op->Imm.Val = Val;
586 Op->StartLoc = S;
587 Op->EndLoc = E;
Alex Bradburya6e62482017-12-07 10:53:48 +0000588 Op->IsRV64 = IsRV64;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000589 return Op;
590 }
591
Ana Pazos9d6c5532018-10-04 21:50:54 +0000592 static std::unique_ptr<RISCVOperand>
593 createSysReg(StringRef Str, SMLoc S, unsigned Encoding, bool IsRV64) {
594 auto Op = make_unique<RISCVOperand>(SystemRegister);
595 Op->SysReg.Data = Str.data();
596 Op->SysReg.Length = Str.size();
597 Op->SysReg.Encoding = Encoding;
598 Op->StartLoc = S;
599 Op->IsRV64 = IsRV64;
600 return Op;
601 }
602
Alex Bradbury04f06d92017-08-08 14:43:36 +0000603 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
604 assert(Expr && "Expr shouldn't be null!");
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000605 int64_t Imm = 0;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000606 RISCVMCExpr::VariantKind VK;
607 bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000608
609 if (IsConstant)
610 Inst.addOperand(MCOperand::createImm(Imm));
Alex Bradbury04f06d92017-08-08 14:43:36 +0000611 else
612 Inst.addOperand(MCOperand::createExpr(Expr));
613 }
614
615 // Used by the TableGen Code
616 void addRegOperands(MCInst &Inst, unsigned N) const {
617 assert(N == 1 && "Invalid number of operands!");
618 Inst.addOperand(MCOperand::createReg(getReg()));
619 }
620
621 void addImmOperands(MCInst &Inst, unsigned N) const {
622 assert(N == 1 && "Invalid number of operands!");
623 addExpr(Inst, getImm());
624 }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000625
626 void addFenceArgOperands(MCInst &Inst, unsigned N) const {
627 assert(N == 1 && "Invalid number of operands!");
628 // isFenceArg has validated the operand, meaning this cast is safe
629 auto SE = cast<MCSymbolRefExpr>(getImm());
630
631 unsigned Imm = 0;
632 for (char c : SE->getSymbol().getName()) {
633 switch (c) {
Ana Pazos9d6c5532018-10-04 21:50:54 +0000634 default:
635 llvm_unreachable("FenceArg must contain only [iorw]");
636 case 'i': Imm |= RISCVFenceField::I; break;
637 case 'o': Imm |= RISCVFenceField::O; break;
638 case 'r': Imm |= RISCVFenceField::R; break;
639 case 'w': Imm |= RISCVFenceField::W; break;
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000640 }
641 }
642 Inst.addOperand(MCOperand::createImm(Imm));
643 }
Alex Bradbury0d6cf902017-12-07 10:26:05 +0000644
Ana Pazos9d6c5532018-10-04 21:50:54 +0000645 void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
646 assert(N == 1 && "Invalid number of operands!");
647 Inst.addOperand(MCOperand::createImm(SysReg.Encoding));
648 }
649
Alex Bradbury0d6cf902017-12-07 10:26:05 +0000650 // Returns the rounding mode represented by this RISCVOperand. Should only
651 // be called after checking isFRMArg.
652 RISCVFPRndMode::RoundingMode getRoundingMode() const {
653 // isFRMArg has validated the operand, meaning this cast is safe.
654 auto SE = cast<MCSymbolRefExpr>(getImm());
655 RISCVFPRndMode::RoundingMode FRM =
656 RISCVFPRndMode::stringToRoundingMode(SE->getSymbol().getName());
657 assert(FRM != RISCVFPRndMode::Invalid && "Invalid rounding mode");
658 return FRM;
659 }
660
661 void addFRMArgOperands(MCInst &Inst, unsigned N) const {
662 assert(N == 1 && "Invalid number of operands!");
663 Inst.addOperand(MCOperand::createImm(getRoundingMode()));
664 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000665};
666} // end anonymous namespace.
667
668#define GET_REGISTER_MATCHER
669#define GET_MATCHER_IMPLEMENTATION
Alex Bradbury04f06d92017-08-08 14:43:36 +0000670#include "RISCVGenAsmMatcher.inc"
671
Alex Bradbury7bc2a952017-12-07 10:46:23 +0000672// Return the matching FPR64 register for the given FPR32.
673// FIXME: Ideally this function could be removed in favour of using
674// information from TableGen.
675unsigned convertFPR32ToFPR64(unsigned Reg) {
676 switch (Reg) {
Ana Pazos9d6c5532018-10-04 21:50:54 +0000677 default:
678 llvm_unreachable("Not a recognised FPR32 register");
679 case RISCV::F0_32: return RISCV::F0_64;
680 case RISCV::F1_32: return RISCV::F1_64;
681 case RISCV::F2_32: return RISCV::F2_64;
682 case RISCV::F3_32: return RISCV::F3_64;
683 case RISCV::F4_32: return RISCV::F4_64;
684 case RISCV::F5_32: return RISCV::F5_64;
685 case RISCV::F6_32: return RISCV::F6_64;
686 case RISCV::F7_32: return RISCV::F7_64;
687 case RISCV::F8_32: return RISCV::F8_64;
688 case RISCV::F9_32: return RISCV::F9_64;
689 case RISCV::F10_32: return RISCV::F10_64;
690 case RISCV::F11_32: return RISCV::F11_64;
691 case RISCV::F12_32: return RISCV::F12_64;
692 case RISCV::F13_32: return RISCV::F13_64;
693 case RISCV::F14_32: return RISCV::F14_64;
694 case RISCV::F15_32: return RISCV::F15_64;
695 case RISCV::F16_32: return RISCV::F16_64;
696 case RISCV::F17_32: return RISCV::F17_64;
697 case RISCV::F18_32: return RISCV::F18_64;
698 case RISCV::F19_32: return RISCV::F19_64;
699 case RISCV::F20_32: return RISCV::F20_64;
700 case RISCV::F21_32: return RISCV::F21_64;
701 case RISCV::F22_32: return RISCV::F22_64;
702 case RISCV::F23_32: return RISCV::F23_64;
703 case RISCV::F24_32: return RISCV::F24_64;
704 case RISCV::F25_32: return RISCV::F25_64;
705 case RISCV::F26_32: return RISCV::F26_64;
706 case RISCV::F27_32: return RISCV::F27_64;
707 case RISCV::F28_32: return RISCV::F28_64;
708 case RISCV::F29_32: return RISCV::F29_64;
709 case RISCV::F30_32: return RISCV::F30_64;
710 case RISCV::F31_32: return RISCV::F31_64;
Alex Bradbury7bc2a952017-12-07 10:46:23 +0000711 }
712}
713
714unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
715 unsigned Kind) {
716 RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
717 if (!Op.isReg())
718 return Match_InvalidOperand;
719
720 unsigned Reg = Op.getReg();
721 bool IsRegFPR32 =
722 RISCVMCRegisterClasses[RISCV::FPR32RegClassID].contains(Reg);
Alex Bradbury60714f92017-12-13 09:32:55 +0000723 bool IsRegFPR32C =
724 RISCVMCRegisterClasses[RISCV::FPR32CRegClassID].contains(Reg);
Alex Bradbury7bc2a952017-12-07 10:46:23 +0000725
726 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
Alex Bradbury60714f92017-12-13 09:32:55 +0000727 // register from FPR32 to FPR64 or FPR32C to FPR64C if necessary.
728 if ((IsRegFPR32 && Kind == MCK_FPR64) ||
729 (IsRegFPR32C && Kind == MCK_FPR64C)) {
Alex Bradbury7bc2a952017-12-07 10:46:23 +0000730 Op.Reg.RegNum = convertFPR32ToFPR64(Reg);
731 return Match_Success;
732 }
733 return Match_InvalidOperand;
734}
735
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000736bool RISCVAsmParser::generateImmOutOfRangeError(
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000737 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000738 Twine Msg = "immediate must be an integer in the range") {
739 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
740 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
741}
742
Alex Bradbury04f06d92017-08-08 14:43:36 +0000743bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
744 OperandVector &Operands,
745 MCStreamer &Out,
746 uint64_t &ErrorInfo,
747 bool MatchingInlineAsm) {
748 MCInst Inst;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000749
Ana Pazos6b34051b2018-08-30 19:43:19 +0000750 auto Result =
751 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
752 switch (Result) {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000753 default:
754 break;
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000755 case Match_Success:
756 return processInstruction(Inst, IDLoc, Out);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000757 case Match_MissingFeature:
758 return Error(IDLoc, "instruction use requires an option to be enabled");
759 case Match_MnemonicFail:
760 return Error(IDLoc, "unrecognized instruction mnemonic");
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000761 case Match_InvalidOperand: {
762 SMLoc ErrorLoc = IDLoc;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000763 if (ErrorInfo != ~0U) {
764 if (ErrorInfo >= Operands.size())
765 return Error(ErrorLoc, "too few operands for instruction");
766
767 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
768 if (ErrorLoc == SMLoc())
769 ErrorLoc = IDLoc;
770 }
771 return Error(ErrorLoc, "invalid operand for instruction");
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000772 }
Ana Pazos6b34051b2018-08-30 19:43:19 +0000773 }
774
775 // Handle the case when the error message is of specific type
776 // other than the generic Match_InvalidOperand, and the
777 // corresponding operand is missing.
778 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
779 SMLoc ErrorLoc = IDLoc;
780 if (ErrorInfo != ~0U && ErrorInfo >= Operands.size())
781 return Error(ErrorLoc, "too few operands for instruction");
782 }
783
784 switch(Result) {
785 default:
786 break;
Alex Bradbury2ba76be2019-01-03 14:41:41 +0000787 case Match_InvalidImmXLenLI:
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000788 if (isRV64()) {
789 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
790 return Error(ErrorLoc, "operand must be a constant 64-bit integer");
791 }
792 return generateImmOutOfRangeError(Operands, ErrorInfo,
793 std::numeric_limits<int32_t>::min(),
794 std::numeric_limits<uint32_t>::max());
Alex Bradburya6e62482017-12-07 10:53:48 +0000795 case Match_InvalidUImmLog2XLen:
796 if (isRV64())
797 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
798 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
Alex Bradbury0ad4c262017-12-15 10:20:51 +0000799 case Match_InvalidUImmLog2XLenNonZero:
800 if (isRV64())
801 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
802 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000803 case Match_InvalidUImm5:
804 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
Alex Bradbury581d6b02017-12-13 09:41:21 +0000805 case Match_InvalidSImm6:
806 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
807 (1 << 5) - 1);
Shiva Chenb22c1d22018-02-02 02:43:23 +0000808 case Match_InvalidSImm6NonZero:
Ana Pazos9d6c5532018-10-04 21:50:54 +0000809 return generateImmOutOfRangeError(
810 Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,
Shiva Chenb22c1d22018-02-02 02:43:23 +0000811 "immediate must be non-zero in the range");
Shiva Chen7c172422018-02-22 15:02:28 +0000812 case Match_InvalidCLUIImm:
813 return generateImmOutOfRangeError(
814 Operands, ErrorInfo, 1, (1 << 5) - 1,
815 "immediate must be in [0xfffe0, 0xfffff] or");
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000816 case Match_InvalidUImm7Lsb00:
817 return generateImmOutOfRangeError(
818 Operands, ErrorInfo, 0, (1 << 7) - 4,
819 "immediate must be a multiple of 4 bytes in the range");
820 case Match_InvalidUImm8Lsb00:
821 return generateImmOutOfRangeError(
822 Operands, ErrorInfo, 0, (1 << 8) - 4,
823 "immediate must be a multiple of 4 bytes in the range");
824 case Match_InvalidUImm8Lsb000:
825 return generateImmOutOfRangeError(
826 Operands, ErrorInfo, 0, (1 << 8) - 8,
827 "immediate must be a multiple of 8 bytes in the range");
Alex Bradburyf8f4b902017-12-07 13:19:57 +0000828 case Match_InvalidSImm9Lsb0:
829 return generateImmOutOfRangeError(
830 Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
831 "immediate must be a multiple of 2 bytes in the range");
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000832 case Match_InvalidUImm9Lsb000:
833 return generateImmOutOfRangeError(
834 Operands, ErrorInfo, 0, (1 << 9) - 8,
835 "immediate must be a multiple of 8 bytes in the range");
Alex Bradbury60714f92017-12-13 09:32:55 +0000836 case Match_InvalidUImm10Lsb00NonZero:
837 return generateImmOutOfRangeError(
838 Operands, ErrorInfo, 4, (1 << 10) - 4,
839 "immediate must be a multiple of 4 bytes in the range");
Shiva Chenb22c1d22018-02-02 02:43:23 +0000840 case Match_InvalidSImm10Lsb0000NonZero:
Alex Bradbury60714f92017-12-13 09:32:55 +0000841 return generateImmOutOfRangeError(
842 Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
Shiva Chenb22c1d22018-02-02 02:43:23 +0000843 "immediate must be a multiple of 16 bytes and non-zero in the range");
Alex Bradbury04f06d92017-08-08 14:43:36 +0000844 case Match_InvalidSImm12:
Alex Bradbury7d0e18d2018-09-18 15:13:29 +0000845 return generateImmOutOfRangeError(
846 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
847 "operand must be a symbol with %lo/%pcrel_lo modifier or an integer in "
848 "the range");
Alex Bradburyf8f4b902017-12-07 13:19:57 +0000849 case Match_InvalidSImm12Lsb0:
850 return generateImmOutOfRangeError(
851 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
852 "immediate must be a multiple of 2 bytes in the range");
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000853 case Match_InvalidSImm13Lsb0:
854 return generateImmOutOfRangeError(
855 Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
856 "immediate must be a multiple of 2 bytes in the range");
Alex Bradbury74340f12018-09-18 15:08:35 +0000857 case Match_InvalidUImm20LUI:
858 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
859 "operand must be a symbol with %hi() "
860 "modifier or an integer in the range");
861 case Match_InvalidUImm20AUIPC:
862 return generateImmOutOfRangeError(
863 Operands, ErrorInfo, 0, (1 << 20) - 1,
864 "operand must be a symbol with %pcrel_hi() modifier or an integer in "
865 "the range");
Alex Bradbury226f3ef2018-09-20 08:10:35 +0000866 case Match_InvalidSImm21Lsb0JAL:
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000867 return generateImmOutOfRangeError(
868 Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
869 "immediate must be a multiple of 2 bytes in the range");
Ana Pazos9d6c5532018-10-04 21:50:54 +0000870 case Match_InvalidCSRSystemRegister: {
871 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,
872 "operand must be a valid system register "
873 "name or an integer in the range");
874 }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000875 case Match_InvalidFenceArg: {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000876 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000877 return Error(
878 ErrorLoc,
879 "operand must be formed of letters selected in-order from 'iorw'");
880 }
Alex Bradbury0d6cf902017-12-07 10:26:05 +0000881 case Match_InvalidFRMArg: {
882 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
883 return Error(
884 ErrorLoc,
885 "operand must be a valid floating point rounding mode mnemonic");
886 }
Shiva Chen98f93892018-04-25 14:18:55 +0000887 case Match_InvalidBareSymbol: {
888 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
889 return Error(ErrorLoc, "operand must be a bare symbol name");
890 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000891 }
892
893 llvm_unreachable("Unknown match type detected!");
894}
895
896bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
897 SMLoc &EndLoc) {
898 const AsmToken &Tok = getParser().getTok();
899 StartLoc = Tok.getLoc();
900 EndLoc = Tok.getEndLoc();
901 RegNo = 0;
902 StringRef Name = getLexer().getTok().getIdentifier();
903
904 if (!MatchRegisterName(Name) || !MatchRegisterAltName(Name)) {
905 getParser().Lex(); // Eat identifier token.
906 return false;
907 }
908
909 return Error(StartLoc, "invalid register name");
910}
911
Alex Bradbury8c345c52017-11-09 15:00:03 +0000912OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands,
913 bool AllowParens) {
914 SMLoc FirstS = getLoc();
915 bool HadParens = false;
916 AsmToken Buf[2];
917
918 // If this a parenthesised register name is allowed, parse it atomically
919 if (AllowParens && getLexer().is(AsmToken::LParen)) {
920 size_t ReadCount = getLexer().peekTokens(Buf);
921 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
922 HadParens = true;
923 getParser().Lex(); // Eat '('
924 }
925 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000926
927 switch (getLexer().getKind()) {
928 default:
929 return MatchOperand_NoMatch;
930 case AsmToken::Identifier:
931 StringRef Name = getLexer().getTok().getIdentifier();
932 unsigned RegNo = MatchRegisterName(Name);
933 if (RegNo == 0) {
934 RegNo = MatchRegisterAltName(Name);
Alex Bradbury8c345c52017-11-09 15:00:03 +0000935 if (RegNo == 0) {
936 if (HadParens)
937 getLexer().UnLex(Buf[0]);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000938 return MatchOperand_NoMatch;
Alex Bradbury8c345c52017-11-09 15:00:03 +0000939 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000940 }
Alex Bradbury8c345c52017-11-09 15:00:03 +0000941 if (HadParens)
Alex Bradburya6e62482017-12-07 10:53:48 +0000942 Operands.push_back(RISCVOperand::createToken("(", FirstS, isRV64()));
Alex Bradbury8c345c52017-11-09 15:00:03 +0000943 SMLoc S = getLoc();
944 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000945 getLexer().Lex();
Alex Bradburya6e62482017-12-07 10:53:48 +0000946 Operands.push_back(RISCVOperand::createReg(RegNo, S, E, isRV64()));
Alex Bradbury04f06d92017-08-08 14:43:36 +0000947 }
Alex Bradbury8c345c52017-11-09 15:00:03 +0000948
949 if (HadParens) {
950 getParser().Lex(); // Eat ')'
Alex Bradburya6e62482017-12-07 10:53:48 +0000951 Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
Alex Bradbury8c345c52017-11-09 15:00:03 +0000952 }
953
Alex Bradbury04f06d92017-08-08 14:43:36 +0000954 return MatchOperand_Success;
955}
956
Ana Pazos9d6c5532018-10-04 21:50:54 +0000957OperandMatchResultTy
958RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
959 SMLoc S = getLoc();
960 const MCExpr *Res;
961
962 switch (getLexer().getKind()) {
963 default:
964 return MatchOperand_NoMatch;
965 case AsmToken::LParen:
966 case AsmToken::Minus:
967 case AsmToken::Plus:
968 case AsmToken::Integer:
969 case AsmToken::String: {
970 if (getParser().parseExpression(Res))
971 return MatchOperand_ParseFail;
972
973 auto *CE = dyn_cast<MCConstantExpr>(Res);
974 if (CE) {
975 int64_t Imm = CE->getValue();
976 if (isUInt<12>(Imm)) {
977 auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
978 // Accept an immediate representing a named or un-named Sys Reg
979 // if the range is valid, regardless of the required features.
980 Operands.push_back(RISCVOperand::createSysReg(
981 SysReg ? SysReg->Name : "", S, Imm, isRV64()));
982 return MatchOperand_Success;
983 }
984 }
985
986 Twine Msg = "immediate must be an integer in the range";
987 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
988 return MatchOperand_ParseFail;
989 }
990 case AsmToken::Identifier: {
991 StringRef Identifier;
992 if (getParser().parseIdentifier(Identifier))
993 return MatchOperand_ParseFail;
994
995 auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
996 // Accept a named Sys Reg if the required features are present.
997 if (SysReg) {
998 if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits())) {
999 Error(S, "system register use requires an option to be enabled");
1000 return MatchOperand_ParseFail;
1001 }
1002 Operands.push_back(RISCVOperand::createSysReg(
1003 Identifier, S, SysReg->Encoding, isRV64()));
1004 return MatchOperand_Success;
1005 }
1006
1007 Twine Msg = "operand must be a valid system register name "
1008 "or an integer in the range";
1009 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1010 return MatchOperand_ParseFail;
1011 }
1012 case AsmToken::Percent: {
1013 // Discard operand with modifier.
1014 Twine Msg = "immediate must be an integer in the range";
1015 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1016 return MatchOperand_ParseFail;
1017 }
1018 }
1019
1020 return MatchOperand_NoMatch;
1021}
1022
Alex Bradbury04f06d92017-08-08 14:43:36 +00001023OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001024 SMLoc S = getLoc();
1025 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1026 const MCExpr *Res;
1027
Alex Bradbury04f06d92017-08-08 14:43:36 +00001028 switch (getLexer().getKind()) {
1029 default:
1030 return MatchOperand_NoMatch;
1031 case AsmToken::LParen:
1032 case AsmToken::Minus:
1033 case AsmToken::Plus:
1034 case AsmToken::Integer:
1035 case AsmToken::String:
Alex Bradbury6f302b82019-01-10 15:33:17 +00001036 case AsmToken::Identifier:
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001037 if (getParser().parseExpression(Res))
1038 return MatchOperand_ParseFail;
1039 break;
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001040 case AsmToken::Percent:
1041 return parseOperandWithModifier(Operands);
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001042 }
Alex Bradbury04f06d92017-08-08 14:43:36 +00001043
Alex Bradburya6e62482017-12-07 10:53:48 +00001044 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001045 return MatchOperand_Success;
1046}
1047
1048OperandMatchResultTy
1049RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
1050 SMLoc S = getLoc();
1051 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1052
1053 if (getLexer().getKind() != AsmToken::Percent) {
1054 Error(getLoc(), "expected '%' for operand modifier");
1055 return MatchOperand_ParseFail;
1056 }
1057
1058 getParser().Lex(); // Eat '%'
1059
1060 if (getLexer().getKind() != AsmToken::Identifier) {
1061 Error(getLoc(), "expected valid identifier for operand modifier");
1062 return MatchOperand_ParseFail;
1063 }
1064 StringRef Identifier = getParser().getTok().getIdentifier();
1065 RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier);
1066 if (VK == RISCVMCExpr::VK_RISCV_Invalid) {
1067 Error(getLoc(), "unrecognized operand modifier");
1068 return MatchOperand_ParseFail;
1069 }
1070
1071 getParser().Lex(); // Eat the identifier
1072 if (getLexer().getKind() != AsmToken::LParen) {
1073 Error(getLoc(), "expected '('");
1074 return MatchOperand_ParseFail;
1075 }
1076 getParser().Lex(); // Eat '('
1077
1078 const MCExpr *SubExpr;
1079 if (getParser().parseParenExpression(SubExpr, E)) {
1080 return MatchOperand_ParseFail;
1081 }
1082
1083 const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
Alex Bradburya6e62482017-12-07 10:53:48 +00001084 Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001085 return MatchOperand_Success;
1086}
1087
Alex Bradbury68f73c12018-09-18 15:18:16 +00001088OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
1089 SMLoc S = getLoc();
1090 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1091 const MCExpr *Res;
1092
1093 if (getLexer().getKind() != AsmToken::Identifier)
1094 return MatchOperand_NoMatch;
1095
1096 StringRef Identifier;
1097 if (getParser().parseIdentifier(Identifier))
1098 return MatchOperand_ParseFail;
1099
1100 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1101 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1102 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1103 return MatchOperand_Success;
1104}
1105
Alex Bradbury226f3ef2018-09-20 08:10:35 +00001106OperandMatchResultTy RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
1107 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
1108 // both being acceptable forms. When parsing `jal ra, foo` this function
1109 // will be called for the `ra` register operand in an attempt to match the
1110 // single-operand alias. parseJALOffset must fail for this case. It would
1111 // seem logical to try parse the operand using parseImmediate and return
1112 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
1113 // the second form rather than the first). We can't do this as there's no
1114 // way of rewinding the lexer state. Instead, return NoMatch if this operand
1115 // is an identifier and is followed by a comma.
1116 if (getLexer().is(AsmToken::Identifier) &&
1117 getLexer().peekTok().is(AsmToken::Comma))
1118 return MatchOperand_NoMatch;
1119
1120 return parseImmediate(Operands);
1121}
1122
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001123OperandMatchResultTy
1124RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
1125 if (getLexer().isNot(AsmToken::LParen)) {
1126 Error(getLoc(), "expected '('");
Alex Bradbury04f06d92017-08-08 14:43:36 +00001127 return MatchOperand_ParseFail;
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001128 }
Alex Bradbury04f06d92017-08-08 14:43:36 +00001129
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001130 getParser().Lex(); // Eat '('
Alex Bradburya6e62482017-12-07 10:53:48 +00001131 Operands.push_back(RISCVOperand::createToken("(", getLoc(), isRV64()));
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001132
1133 if (parseRegister(Operands) != MatchOperand_Success) {
1134 Error(getLoc(), "expected register");
1135 return MatchOperand_ParseFail;
1136 }
1137
1138 if (getLexer().isNot(AsmToken::RParen)) {
1139 Error(getLoc(), "expected ')'");
1140 return MatchOperand_ParseFail;
1141 }
1142
1143 getParser().Lex(); // Eat ')'
Alex Bradburya6e62482017-12-07 10:53:48 +00001144 Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001145
Alex Bradbury04f06d92017-08-08 14:43:36 +00001146 return MatchOperand_Success;
1147}
1148
Alex Bradburycd8688a2018-04-25 17:25:29 +00001149/// Looks at a token type and creates the relevant operand from this
1150/// information, adding to Operands. If operand was parsed, returns false, else
Alex Bradbury68f73c12018-09-18 15:18:16 +00001151/// true.
1152bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1153 // Check if the current operand has a custom associated parser, if so, try to
1154 // custom parse the operand, or fallback to the general approach.
1155 OperandMatchResultTy Result =
1156 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
1157 if (Result == MatchOperand_Success)
1158 return false;
1159 if (Result == MatchOperand_ParseFail)
1160 return true;
1161
1162 // Attempt to parse token as a register.
1163 if (parseRegister(Operands, true) == MatchOperand_Success)
Alex Bradbury04f06d92017-08-08 14:43:36 +00001164 return false;
1165
1166 // Attempt to parse token as an immediate
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001167 if (parseImmediate(Operands) == MatchOperand_Success) {
1168 // Parse memory base register if present
1169 if (getLexer().is(AsmToken::LParen))
1170 return parseMemOpBaseReg(Operands) != MatchOperand_Success;
Alex Bradbury04f06d92017-08-08 14:43:36 +00001171 return false;
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001172 }
Alex Bradbury04f06d92017-08-08 14:43:36 +00001173
1174 // Finally we have exhausted all options and must declare defeat.
1175 Error(getLoc(), "unknown operand");
1176 return true;
1177}
1178
1179bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
1180 StringRef Name, SMLoc NameLoc,
1181 OperandVector &Operands) {
Alex Bradbury9c03e4c2018-11-12 14:25:07 +00001182 // Ensure that if the instruction occurs when relaxation is enabled,
1183 // relocations are forced for the file. Ideally this would be done when there
1184 // is enough information to reliably determine if the instruction itself may
1185 // cause relaxations. Unfortunately instruction processing stage occurs in the
1186 // same pass as relocation emission, so it's too late to set a 'sticky bit'
1187 // for the entire file.
1188 if (getSTI().getFeatureBits()[RISCV::FeatureRelax]) {
1189 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
1190 if (Assembler != nullptr) {
1191 RISCVAsmBackend &MAB =
1192 static_cast<RISCVAsmBackend &>(Assembler->getBackend());
1193 MAB.setForceRelocs();
1194 }
1195 }
1196
Alex Bradbury04f06d92017-08-08 14:43:36 +00001197 // First operand is token for instruction
Alex Bradburya6e62482017-12-07 10:53:48 +00001198 Operands.push_back(RISCVOperand::createToken(Name, NameLoc, isRV64()));
Alex Bradbury04f06d92017-08-08 14:43:36 +00001199
1200 // If there are no more operands, then finish
1201 if (getLexer().is(AsmToken::EndOfStatement))
1202 return false;
1203
1204 // Parse first operand
Alex Bradbury68f73c12018-09-18 15:18:16 +00001205 if (parseOperand(Operands, Name))
Alex Bradbury04f06d92017-08-08 14:43:36 +00001206 return true;
1207
1208 // Parse until end of statement, consuming commas between operands
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001209 unsigned OperandIdx = 1;
Alex Bradbury04f06d92017-08-08 14:43:36 +00001210 while (getLexer().is(AsmToken::Comma)) {
1211 // Consume comma token
1212 getLexer().Lex();
1213
1214 // Parse next operand
Alex Bradbury68f73c12018-09-18 15:18:16 +00001215 if (parseOperand(Operands, Name))
Alex Bradbury04f06d92017-08-08 14:43:36 +00001216 return true;
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001217
1218 ++OperandIdx;
Alex Bradbury04f06d92017-08-08 14:43:36 +00001219 }
1220
1221 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1222 SMLoc Loc = getLexer().getLoc();
1223 getParser().eatToEndOfStatement();
1224 return Error(Loc, "unexpected token");
1225 }
1226
1227 getParser().Lex(); // Consume the EndOfStatement.
1228 return false;
1229}
1230
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001231bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
1232 RISCVMCExpr::VariantKind &Kind,
1233 int64_t &Addend) {
1234 Kind = RISCVMCExpr::VK_RISCV_None;
1235 Addend = 0;
1236
1237 if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
1238 Kind = RE->getKind();
1239 Expr = RE->getSubExpr();
1240 }
1241
1242 // It's a simple symbol reference or constant with no addend.
1243 if (isa<MCConstantExpr>(Expr) || isa<MCSymbolRefExpr>(Expr))
1244 return true;
1245
1246 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
1247 if (!BE)
1248 return false;
1249
1250 if (!isa<MCSymbolRefExpr>(BE->getLHS()))
1251 return false;
1252
1253 if (BE->getOpcode() != MCBinaryExpr::Add &&
1254 BE->getOpcode() != MCBinaryExpr::Sub)
1255 return false;
1256
1257 // We are able to support the subtraction of two symbol references
1258 if (BE->getOpcode() == MCBinaryExpr::Sub &&
1259 isa<MCSymbolRefExpr>(BE->getRHS()))
1260 return true;
1261
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00001262 // See if the addend is a constant, otherwise there's more going
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001263 // on here than we can deal with.
1264 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
1265 if (!AddendExpr)
1266 return false;
1267
1268 Addend = AddendExpr->getValue();
1269 if (BE->getOpcode() == MCBinaryExpr::Sub)
1270 Addend = -Addend;
1271
1272 // It's some symbol reference + a constant addend
1273 return Kind != RISCVMCExpr::VK_RISCV_Invalid;
1274}
1275
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001276bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
1277 // This returns false if this function recognizes the directive
1278 // regardless of whether it is successfully handles or reports an
1279 // error. Otherwise it returns true to give the generic parser a
1280 // chance at recognizing it.
1281 StringRef IDVal = DirectiveID.getString();
1282
1283 if (IDVal == ".option")
1284 return parseDirectiveOption();
1285
1286 return true;
1287}
1288
1289bool RISCVAsmParser::parseDirectiveOption() {
1290 MCAsmParser &Parser = getParser();
1291 // Get the option token.
1292 AsmToken Tok = Parser.getTok();
1293 // At the moment only identifiers are supported.
1294 if (Tok.isNot(AsmToken::Identifier))
1295 return Error(Parser.getTok().getLoc(),
1296 "unexpected token, expected identifier");
1297
1298 StringRef Option = Tok.getIdentifier();
1299
Alex Bradbury893e5bc2018-11-28 16:39:14 +00001300 if (Option == "push") {
1301 getTargetStreamer().emitDirectiveOptionPush();
1302
1303 Parser.Lex();
1304 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1305 return Error(Parser.getTok().getLoc(),
1306 "unexpected token, expected end of statement");
1307
1308 pushFeatureBits();
1309 return false;
1310 }
1311
1312 if (Option == "pop") {
1313 SMLoc StartLoc = Parser.getTok().getLoc();
1314 getTargetStreamer().emitDirectiveOptionPop();
1315
1316 Parser.Lex();
1317 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1318 return Error(Parser.getTok().getLoc(),
1319 "unexpected token, expected end of statement");
1320
1321 if (popFeatureBits())
1322 return Error(StartLoc, ".option pop with no .option push");
1323
1324 return false;
1325 }
1326
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001327 if (Option == "rvc") {
1328 getTargetStreamer().emitDirectiveOptionRVC();
1329
1330 Parser.Lex();
1331 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1332 return Error(Parser.getTok().getLoc(),
1333 "unexpected token, expected end of statement");
1334
1335 setFeatureBits(RISCV::FeatureStdExtC, "c");
1336 return false;
1337 }
1338
1339 if (Option == "norvc") {
1340 getTargetStreamer().emitDirectiveOptionNoRVC();
1341
1342 Parser.Lex();
1343 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1344 return Error(Parser.getTok().getLoc(),
1345 "unexpected token, expected end of statement");
1346
1347 clearFeatureBits(RISCV::FeatureStdExtC, "c");
1348 return false;
1349 }
1350
Alex Bradbury9c03e4c2018-11-12 14:25:07 +00001351 if (Option == "relax") {
1352 getTargetStreamer().emitDirectiveOptionRelax();
1353
1354 Parser.Lex();
1355 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1356 return Error(Parser.getTok().getLoc(),
1357 "unexpected token, expected end of statement");
1358
1359 setFeatureBits(RISCV::FeatureRelax, "relax");
1360 return false;
1361 }
1362
1363 if (Option == "norelax") {
1364 getTargetStreamer().emitDirectiveOptionNoRelax();
1365
1366 Parser.Lex();
1367 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1368 return Error(Parser.getTok().getLoc(),
1369 "unexpected token, expected end of statement");
1370
1371 clearFeatureBits(RISCV::FeatureRelax, "relax");
1372 return false;
1373 }
1374
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001375 // Unknown option.
1376 Warning(Parser.getTok().getLoc(),
Alex Bradbury893e5bc2018-11-28 16:39:14 +00001377 "unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'relax' or "
1378 "'norelax'");
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001379 Parser.eatToEndOfStatement();
1380 return false;
1381}
Alex Bradbury04f06d92017-08-08 14:43:36 +00001382
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001383void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
1384 MCInst CInst;
1385 bool Res = compressInst(CInst, Inst, getSTI(), S.getContext());
1386 CInst.setLoc(Inst.getLoc());
1387 S.EmitInstruction((Res ? CInst : Inst), getSTI());
1388}
1389
1390void RISCVAsmParser::emitLoadImm(unsigned DestReg, int64_t Value,
1391 MCStreamer &Out) {
Alex Bradbury22c091f2018-11-15 10:11:31 +00001392 RISCVMatInt::InstSeq Seq;
1393 RISCVMatInt::generateInstSeq(Value, isRV64(), Seq);
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001394
Alex Bradbury22c091f2018-11-15 10:11:31 +00001395 unsigned SrcReg = RISCV::X0;
1396 for (RISCVMatInt::Inst &Inst : Seq) {
1397 if (Inst.Opc == RISCV::LUI) {
1398 emitToStreamer(
1399 Out, MCInstBuilder(RISCV::LUI).addReg(DestReg).addImm(Inst.Imm));
1400 } else {
1401 emitToStreamer(
1402 Out, MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm(
1403 Inst.Imm));
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001404 }
1405
Alex Bradbury22c091f2018-11-15 10:11:31 +00001406 // Only the first instruction has X0 as its source.
1407 SrcReg = DestReg;
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001408 }
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001409}
1410
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001411void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
1412 MCStreamer &Out) {
1413 // The local load address pseudo-instruction "lla" is used in PC-relative
1414 // addressing of symbols:
1415 // lla rdest, symbol
1416 // expands to
1417 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
1418 // ADDI rdest, %pcrel_lo(TmpLabel)
1419 MCContext &Ctx = getContext();
1420
1421 MCSymbol *TmpLabel = Ctx.createTempSymbol(
1422 "pcrel_hi", /* AlwaysAddSuffix */ true, /* CanBeUnnamed */ false);
1423 Out.EmitLabel(TmpLabel);
1424
1425 MCOperand DestReg = Inst.getOperand(0);
1426 const RISCVMCExpr *Symbol = RISCVMCExpr::create(
1427 Inst.getOperand(1).getExpr(), RISCVMCExpr::VK_RISCV_PCREL_HI, Ctx);
1428
Roger Ferrer Ibanezc8f4dbb2018-08-14 08:30:42 +00001429 emitToStreamer(
1430 Out, MCInstBuilder(RISCV::AUIPC).addOperand(DestReg).addExpr(Symbol));
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001431
1432 const MCExpr *RefToLinkTmpLabel =
1433 RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),
1434 RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
1435
Roger Ferrer Ibanezc8f4dbb2018-08-14 08:30:42 +00001436 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
1437 .addOperand(DestReg)
1438 .addOperand(DestReg)
1439 .addExpr(RefToLinkTmpLabel));
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001440}
1441
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001442bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1443 MCStreamer &Out) {
1444 Inst.setLoc(IDLoc);
1445
1446 if (Inst.getOpcode() == RISCV::PseudoLI) {
Alex Bradbury2ba76be2019-01-03 14:41:41 +00001447 unsigned Reg = Inst.getOperand(0).getReg();
1448 const MCOperand &Op1 = Inst.getOperand(1);
1449 if (Op1.isExpr()) {
1450 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
1451 // Just convert to an addi. This allows compatibility with gas.
1452 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
1453 .addReg(Reg)
1454 .addReg(RISCV::X0)
1455 .addExpr(Op1.getExpr()));
1456 return false;
1457 }
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001458 int64_t Imm = Inst.getOperand(1).getImm();
1459 // On RV32 the immediate here can either be a signed or an unsigned
1460 // 32-bit number. Sign extension has to be performed to ensure that Imm
1461 // represents the expected signed 64-bit number.
1462 if (!isRV64())
1463 Imm = SignExtend64<32>(Imm);
1464 emitLoadImm(Reg, Imm, Out);
1465 return false;
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001466 } else if (Inst.getOpcode() == RISCV::PseudoLLA) {
1467 emitLoadLocalAddress(Inst, IDLoc, Out);
1468 return false;
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001469 }
1470
1471 emitToStreamer(Out, Inst);
1472 return false;
1473}
1474
Alex Bradbury04f06d92017-08-08 14:43:36 +00001475extern "C" void LLVMInitializeRISCVAsmParser() {
1476 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
1477 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
1478}