blob: 239f7c407f3880678e637534814ddace0cff7908 [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
911bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
912 SMLoc &EndLoc) {
913 const AsmToken &Tok = getParser().getTok();
914 StartLoc = Tok.getLoc();
915 EndLoc = Tok.getEndLoc();
916 RegNo = 0;
917 StringRef Name = getLexer().getTok().getIdentifier();
918
919 if (!MatchRegisterName(Name) || !MatchRegisterAltName(Name)) {
920 getParser().Lex(); // Eat identifier token.
921 return false;
922 }
923
924 return Error(StartLoc, "invalid register name");
925}
926
Alex Bradbury8c345c52017-11-09 15:00:03 +0000927OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands,
928 bool AllowParens) {
929 SMLoc FirstS = getLoc();
930 bool HadParens = false;
931 AsmToken Buf[2];
932
933 // If this a parenthesised register name is allowed, parse it atomically
934 if (AllowParens && getLexer().is(AsmToken::LParen)) {
935 size_t ReadCount = getLexer().peekTokens(Buf);
936 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
937 HadParens = true;
938 getParser().Lex(); // Eat '('
939 }
940 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000941
942 switch (getLexer().getKind()) {
943 default:
944 return MatchOperand_NoMatch;
945 case AsmToken::Identifier:
946 StringRef Name = getLexer().getTok().getIdentifier();
947 unsigned RegNo = MatchRegisterName(Name);
948 if (RegNo == 0) {
949 RegNo = MatchRegisterAltName(Name);
Alex Bradbury8c345c52017-11-09 15:00:03 +0000950 if (RegNo == 0) {
951 if (HadParens)
952 getLexer().UnLex(Buf[0]);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000953 return MatchOperand_NoMatch;
Alex Bradbury8c345c52017-11-09 15:00:03 +0000954 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000955 }
Alex Bradbury8c345c52017-11-09 15:00:03 +0000956 if (HadParens)
Alex Bradburya6e62482017-12-07 10:53:48 +0000957 Operands.push_back(RISCVOperand::createToken("(", FirstS, isRV64()));
Alex Bradbury8c345c52017-11-09 15:00:03 +0000958 SMLoc S = getLoc();
959 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000960 getLexer().Lex();
Alex Bradburya6e62482017-12-07 10:53:48 +0000961 Operands.push_back(RISCVOperand::createReg(RegNo, S, E, isRV64()));
Alex Bradbury04f06d92017-08-08 14:43:36 +0000962 }
Alex Bradbury8c345c52017-11-09 15:00:03 +0000963
964 if (HadParens) {
965 getParser().Lex(); // Eat ')'
Alex Bradburya6e62482017-12-07 10:53:48 +0000966 Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
Alex Bradbury8c345c52017-11-09 15:00:03 +0000967 }
968
Alex Bradbury04f06d92017-08-08 14:43:36 +0000969 return MatchOperand_Success;
970}
971
Ana Pazos9d6c5532018-10-04 21:50:54 +0000972OperandMatchResultTy
973RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
974 SMLoc S = getLoc();
975 const MCExpr *Res;
976
977 switch (getLexer().getKind()) {
978 default:
979 return MatchOperand_NoMatch;
980 case AsmToken::LParen:
981 case AsmToken::Minus:
982 case AsmToken::Plus:
983 case AsmToken::Integer:
984 case AsmToken::String: {
985 if (getParser().parseExpression(Res))
986 return MatchOperand_ParseFail;
987
988 auto *CE = dyn_cast<MCConstantExpr>(Res);
989 if (CE) {
990 int64_t Imm = CE->getValue();
991 if (isUInt<12>(Imm)) {
992 auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
993 // Accept an immediate representing a named or un-named Sys Reg
994 // if the range is valid, regardless of the required features.
995 Operands.push_back(RISCVOperand::createSysReg(
996 SysReg ? SysReg->Name : "", S, Imm, isRV64()));
997 return MatchOperand_Success;
998 }
999 }
1000
1001 Twine Msg = "immediate must be an integer in the range";
1002 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1003 return MatchOperand_ParseFail;
1004 }
1005 case AsmToken::Identifier: {
1006 StringRef Identifier;
1007 if (getParser().parseIdentifier(Identifier))
1008 return MatchOperand_ParseFail;
1009
1010 auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
1011 // Accept a named Sys Reg if the required features are present.
1012 if (SysReg) {
1013 if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits())) {
1014 Error(S, "system register use requires an option to be enabled");
1015 return MatchOperand_ParseFail;
1016 }
1017 Operands.push_back(RISCVOperand::createSysReg(
1018 Identifier, S, SysReg->Encoding, isRV64()));
1019 return MatchOperand_Success;
1020 }
1021
1022 Twine Msg = "operand must be a valid system register name "
1023 "or an integer in the range";
1024 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1025 return MatchOperand_ParseFail;
1026 }
1027 case AsmToken::Percent: {
1028 // Discard operand with modifier.
1029 Twine Msg = "immediate must be an integer in the range";
1030 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1031 return MatchOperand_ParseFail;
1032 }
1033 }
1034
1035 return MatchOperand_NoMatch;
1036}
1037
Alex Bradbury04f06d92017-08-08 14:43:36 +00001038OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001039 SMLoc S = getLoc();
1040 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1041 const MCExpr *Res;
1042
Alex Bradbury04f06d92017-08-08 14:43:36 +00001043 switch (getLexer().getKind()) {
1044 default:
1045 return MatchOperand_NoMatch;
1046 case AsmToken::LParen:
1047 case AsmToken::Minus:
1048 case AsmToken::Plus:
1049 case AsmToken::Integer:
1050 case AsmToken::String:
Alex Bradbury6f302b82019-01-10 15:33:17 +00001051 case AsmToken::Identifier:
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001052 if (getParser().parseExpression(Res))
1053 return MatchOperand_ParseFail;
1054 break;
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001055 case AsmToken::Percent:
1056 return parseOperandWithModifier(Operands);
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001057 }
Alex Bradbury04f06d92017-08-08 14:43:36 +00001058
Alex Bradburya6e62482017-12-07 10:53:48 +00001059 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001060 return MatchOperand_Success;
1061}
1062
1063OperandMatchResultTy
1064RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
1065 SMLoc S = getLoc();
1066 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1067
1068 if (getLexer().getKind() != AsmToken::Percent) {
1069 Error(getLoc(), "expected '%' for operand modifier");
1070 return MatchOperand_ParseFail;
1071 }
1072
1073 getParser().Lex(); // Eat '%'
1074
1075 if (getLexer().getKind() != AsmToken::Identifier) {
1076 Error(getLoc(), "expected valid identifier for operand modifier");
1077 return MatchOperand_ParseFail;
1078 }
1079 StringRef Identifier = getParser().getTok().getIdentifier();
1080 RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier);
1081 if (VK == RISCVMCExpr::VK_RISCV_Invalid) {
1082 Error(getLoc(), "unrecognized operand modifier");
1083 return MatchOperand_ParseFail;
1084 }
1085
1086 getParser().Lex(); // Eat the identifier
1087 if (getLexer().getKind() != AsmToken::LParen) {
1088 Error(getLoc(), "expected '('");
1089 return MatchOperand_ParseFail;
1090 }
1091 getParser().Lex(); // Eat '('
1092
1093 const MCExpr *SubExpr;
1094 if (getParser().parseParenExpression(SubExpr, E)) {
1095 return MatchOperand_ParseFail;
1096 }
1097
1098 const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
Alex Bradburya6e62482017-12-07 10:53:48 +00001099 Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001100 return MatchOperand_Success;
1101}
1102
Alex Bradbury68f73c12018-09-18 15:18:16 +00001103OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
1104 SMLoc S = getLoc();
1105 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1106 const MCExpr *Res;
1107
1108 if (getLexer().getKind() != AsmToken::Identifier)
1109 return MatchOperand_NoMatch;
1110
1111 StringRef Identifier;
Kito Cheng303217e2019-02-20 03:31:32 +00001112 AsmToken Tok = getLexer().getTok();
1113
Alex Bradbury68f73c12018-09-18 15:18:16 +00001114 if (getParser().parseIdentifier(Identifier))
1115 return MatchOperand_ParseFail;
1116
1117 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
Kito Cheng303217e2019-02-20 03:31:32 +00001118
1119 if (Sym->isVariable()) {
1120 const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
1121 if (!isa<MCSymbolRefExpr>(V)) {
1122 getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
1123 return MatchOperand_NoMatch;
1124 }
1125 Res = V;
1126 } else
1127 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Alex Bradbury68f73c12018-09-18 15:18:16 +00001128 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1129 return MatchOperand_Success;
1130}
1131
Alex Bradbury226f3ef2018-09-20 08:10:35 +00001132OperandMatchResultTy RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
1133 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
1134 // both being acceptable forms. When parsing `jal ra, foo` this function
1135 // will be called for the `ra` register operand in an attempt to match the
1136 // single-operand alias. parseJALOffset must fail for this case. It would
1137 // seem logical to try parse the operand using parseImmediate and return
1138 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
1139 // the second form rather than the first). We can't do this as there's no
1140 // way of rewinding the lexer state. Instead, return NoMatch if this operand
1141 // is an identifier and is followed by a comma.
1142 if (getLexer().is(AsmToken::Identifier) &&
1143 getLexer().peekTok().is(AsmToken::Comma))
1144 return MatchOperand_NoMatch;
1145
1146 return parseImmediate(Operands);
1147}
1148
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001149OperandMatchResultTy
1150RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
1151 if (getLexer().isNot(AsmToken::LParen)) {
1152 Error(getLoc(), "expected '('");
Alex Bradbury04f06d92017-08-08 14:43:36 +00001153 return MatchOperand_ParseFail;
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001154 }
Alex Bradbury04f06d92017-08-08 14:43:36 +00001155
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001156 getParser().Lex(); // Eat '('
Alex Bradburya6e62482017-12-07 10:53:48 +00001157 Operands.push_back(RISCVOperand::createToken("(", getLoc(), isRV64()));
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001158
1159 if (parseRegister(Operands) != MatchOperand_Success) {
1160 Error(getLoc(), "expected register");
1161 return MatchOperand_ParseFail;
1162 }
1163
1164 if (getLexer().isNot(AsmToken::RParen)) {
1165 Error(getLoc(), "expected ')'");
1166 return MatchOperand_ParseFail;
1167 }
1168
1169 getParser().Lex(); // Eat ')'
Alex Bradburya6e62482017-12-07 10:53:48 +00001170 Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001171
Alex Bradbury04f06d92017-08-08 14:43:36 +00001172 return MatchOperand_Success;
1173}
1174
Alex Bradburycd8688a2018-04-25 17:25:29 +00001175/// Looks at a token type and creates the relevant operand from this
1176/// information, adding to Operands. If operand was parsed, returns false, else
Alex Bradbury68f73c12018-09-18 15:18:16 +00001177/// true.
1178bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1179 // Check if the current operand has a custom associated parser, if so, try to
1180 // custom parse the operand, or fallback to the general approach.
1181 OperandMatchResultTy Result =
1182 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
1183 if (Result == MatchOperand_Success)
1184 return false;
1185 if (Result == MatchOperand_ParseFail)
1186 return true;
1187
1188 // Attempt to parse token as a register.
1189 if (parseRegister(Operands, true) == MatchOperand_Success)
Alex Bradbury04f06d92017-08-08 14:43:36 +00001190 return false;
1191
1192 // Attempt to parse token as an immediate
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001193 if (parseImmediate(Operands) == MatchOperand_Success) {
1194 // Parse memory base register if present
1195 if (getLexer().is(AsmToken::LParen))
1196 return parseMemOpBaseReg(Operands) != MatchOperand_Success;
Alex Bradbury04f06d92017-08-08 14:43:36 +00001197 return false;
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001198 }
Alex Bradbury04f06d92017-08-08 14:43:36 +00001199
1200 // Finally we have exhausted all options and must declare defeat.
1201 Error(getLoc(), "unknown operand");
1202 return true;
1203}
1204
1205bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
1206 StringRef Name, SMLoc NameLoc,
1207 OperandVector &Operands) {
Alex Bradbury9c03e4c2018-11-12 14:25:07 +00001208 // Ensure that if the instruction occurs when relaxation is enabled,
1209 // relocations are forced for the file. Ideally this would be done when there
1210 // is enough information to reliably determine if the instruction itself may
1211 // cause relaxations. Unfortunately instruction processing stage occurs in the
1212 // same pass as relocation emission, so it's too late to set a 'sticky bit'
1213 // for the entire file.
1214 if (getSTI().getFeatureBits()[RISCV::FeatureRelax]) {
1215 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
1216 if (Assembler != nullptr) {
1217 RISCVAsmBackend &MAB =
1218 static_cast<RISCVAsmBackend &>(Assembler->getBackend());
1219 MAB.setForceRelocs();
1220 }
1221 }
1222
Alex Bradbury04f06d92017-08-08 14:43:36 +00001223 // First operand is token for instruction
Alex Bradburya6e62482017-12-07 10:53:48 +00001224 Operands.push_back(RISCVOperand::createToken(Name, NameLoc, isRV64()));
Alex Bradbury04f06d92017-08-08 14:43:36 +00001225
1226 // If there are no more operands, then finish
1227 if (getLexer().is(AsmToken::EndOfStatement))
1228 return false;
1229
1230 // Parse first operand
Alex Bradbury68f73c12018-09-18 15:18:16 +00001231 if (parseOperand(Operands, Name))
Alex Bradbury04f06d92017-08-08 14:43:36 +00001232 return true;
1233
1234 // Parse until end of statement, consuming commas between operands
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001235 unsigned OperandIdx = 1;
Alex Bradbury04f06d92017-08-08 14:43:36 +00001236 while (getLexer().is(AsmToken::Comma)) {
1237 // Consume comma token
1238 getLexer().Lex();
1239
1240 // Parse next operand
Alex Bradbury68f73c12018-09-18 15:18:16 +00001241 if (parseOperand(Operands, Name))
Alex Bradbury04f06d92017-08-08 14:43:36 +00001242 return true;
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001243
1244 ++OperandIdx;
Alex Bradbury04f06d92017-08-08 14:43:36 +00001245 }
1246
1247 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1248 SMLoc Loc = getLexer().getLoc();
1249 getParser().eatToEndOfStatement();
1250 return Error(Loc, "unexpected token");
1251 }
1252
1253 getParser().Lex(); // Consume the EndOfStatement.
1254 return false;
1255}
1256
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001257bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
1258 RISCVMCExpr::VariantKind &Kind,
1259 int64_t &Addend) {
1260 Kind = RISCVMCExpr::VK_RISCV_None;
1261 Addend = 0;
1262
1263 if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
1264 Kind = RE->getKind();
1265 Expr = RE->getSubExpr();
1266 }
1267
1268 // It's a simple symbol reference or constant with no addend.
1269 if (isa<MCConstantExpr>(Expr) || isa<MCSymbolRefExpr>(Expr))
1270 return true;
1271
1272 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
1273 if (!BE)
1274 return false;
1275
1276 if (!isa<MCSymbolRefExpr>(BE->getLHS()))
1277 return false;
1278
1279 if (BE->getOpcode() != MCBinaryExpr::Add &&
1280 BE->getOpcode() != MCBinaryExpr::Sub)
1281 return false;
1282
1283 // We are able to support the subtraction of two symbol references
1284 if (BE->getOpcode() == MCBinaryExpr::Sub &&
1285 isa<MCSymbolRefExpr>(BE->getRHS()))
1286 return true;
1287
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00001288 // See if the addend is a constant, otherwise there's more going
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001289 // on here than we can deal with.
1290 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
1291 if (!AddendExpr)
1292 return false;
1293
1294 Addend = AddendExpr->getValue();
1295 if (BE->getOpcode() == MCBinaryExpr::Sub)
1296 Addend = -Addend;
1297
1298 // It's some symbol reference + a constant addend
1299 return Kind != RISCVMCExpr::VK_RISCV_Invalid;
1300}
1301
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001302bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
1303 // This returns false if this function recognizes the directive
1304 // regardless of whether it is successfully handles or reports an
1305 // error. Otherwise it returns true to give the generic parser a
1306 // chance at recognizing it.
1307 StringRef IDVal = DirectiveID.getString();
1308
1309 if (IDVal == ".option")
1310 return parseDirectiveOption();
1311
1312 return true;
1313}
1314
1315bool RISCVAsmParser::parseDirectiveOption() {
1316 MCAsmParser &Parser = getParser();
1317 // Get the option token.
1318 AsmToken Tok = Parser.getTok();
1319 // At the moment only identifiers are supported.
1320 if (Tok.isNot(AsmToken::Identifier))
1321 return Error(Parser.getTok().getLoc(),
1322 "unexpected token, expected identifier");
1323
1324 StringRef Option = Tok.getIdentifier();
1325
Alex Bradbury893e5bc2018-11-28 16:39:14 +00001326 if (Option == "push") {
1327 getTargetStreamer().emitDirectiveOptionPush();
1328
1329 Parser.Lex();
1330 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1331 return Error(Parser.getTok().getLoc(),
1332 "unexpected token, expected end of statement");
1333
1334 pushFeatureBits();
1335 return false;
1336 }
1337
1338 if (Option == "pop") {
1339 SMLoc StartLoc = Parser.getTok().getLoc();
1340 getTargetStreamer().emitDirectiveOptionPop();
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 if (popFeatureBits())
1348 return Error(StartLoc, ".option pop with no .option push");
1349
1350 return false;
1351 }
1352
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001353 if (Option == "rvc") {
1354 getTargetStreamer().emitDirectiveOptionRVC();
1355
1356 Parser.Lex();
1357 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1358 return Error(Parser.getTok().getLoc(),
1359 "unexpected token, expected end of statement");
1360
1361 setFeatureBits(RISCV::FeatureStdExtC, "c");
1362 return false;
1363 }
1364
1365 if (Option == "norvc") {
1366 getTargetStreamer().emitDirectiveOptionNoRVC();
1367
1368 Parser.Lex();
1369 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1370 return Error(Parser.getTok().getLoc(),
1371 "unexpected token, expected end of statement");
1372
1373 clearFeatureBits(RISCV::FeatureStdExtC, "c");
1374 return false;
1375 }
1376
Alex Bradbury9c03e4c2018-11-12 14:25:07 +00001377 if (Option == "relax") {
1378 getTargetStreamer().emitDirectiveOptionRelax();
1379
1380 Parser.Lex();
1381 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1382 return Error(Parser.getTok().getLoc(),
1383 "unexpected token, expected end of statement");
1384
1385 setFeatureBits(RISCV::FeatureRelax, "relax");
1386 return false;
1387 }
1388
1389 if (Option == "norelax") {
1390 getTargetStreamer().emitDirectiveOptionNoRelax();
1391
1392 Parser.Lex();
1393 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1394 return Error(Parser.getTok().getLoc(),
1395 "unexpected token, expected end of statement");
1396
1397 clearFeatureBits(RISCV::FeatureRelax, "relax");
1398 return false;
1399 }
1400
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001401 // Unknown option.
1402 Warning(Parser.getTok().getLoc(),
Alex Bradbury893e5bc2018-11-28 16:39:14 +00001403 "unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'relax' or "
1404 "'norelax'");
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001405 Parser.eatToEndOfStatement();
1406 return false;
1407}
Alex Bradbury04f06d92017-08-08 14:43:36 +00001408
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001409void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
1410 MCInst CInst;
1411 bool Res = compressInst(CInst, Inst, getSTI(), S.getContext());
1412 CInst.setLoc(Inst.getLoc());
1413 S.EmitInstruction((Res ? CInst : Inst), getSTI());
1414}
1415
1416void RISCVAsmParser::emitLoadImm(unsigned DestReg, int64_t Value,
1417 MCStreamer &Out) {
Alex Bradbury22c091f2018-11-15 10:11:31 +00001418 RISCVMatInt::InstSeq Seq;
1419 RISCVMatInt::generateInstSeq(Value, isRV64(), Seq);
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001420
Alex Bradbury22c091f2018-11-15 10:11:31 +00001421 unsigned SrcReg = RISCV::X0;
1422 for (RISCVMatInt::Inst &Inst : Seq) {
1423 if (Inst.Opc == RISCV::LUI) {
1424 emitToStreamer(
1425 Out, MCInstBuilder(RISCV::LUI).addReg(DestReg).addImm(Inst.Imm));
1426 } else {
1427 emitToStreamer(
1428 Out, MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm(
1429 Inst.Imm));
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001430 }
1431
Alex Bradbury22c091f2018-11-15 10:11:31 +00001432 // Only the first instruction has X0 as its source.
1433 SrcReg = DestReg;
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001434 }
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001435}
1436
Alex Bradbury22531c42019-02-15 09:53:32 +00001437void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
1438 const MCExpr *Symbol,
1439 RISCVMCExpr::VariantKind VKHi,
1440 unsigned SecondOpcode, SMLoc IDLoc,
1441 MCStreamer &Out) {
1442 // A pair of instructions for PC-relative addressing; expands to
1443 // TmpLabel: AUIPC TmpReg, VKHi(symbol)
1444 // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001445 MCContext &Ctx = getContext();
1446
1447 MCSymbol *TmpLabel = Ctx.createTempSymbol(
1448 "pcrel_hi", /* AlwaysAddSuffix */ true, /* CanBeUnnamed */ false);
1449 Out.EmitLabel(TmpLabel);
1450
Alex Bradbury22531c42019-02-15 09:53:32 +00001451 const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
Roger Ferrer Ibanezc8f4dbb2018-08-14 08:30:42 +00001452 emitToStreamer(
Alex Bradbury22531c42019-02-15 09:53:32 +00001453 Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001454
1455 const MCExpr *RefToLinkTmpLabel =
1456 RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),
1457 RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
1458
Alex Bradbury22531c42019-02-15 09:53:32 +00001459 emitToStreamer(Out, MCInstBuilder(SecondOpcode)
Roger Ferrer Ibanezc8f4dbb2018-08-14 08:30:42 +00001460 .addOperand(DestReg)
Alex Bradbury22531c42019-02-15 09:53:32 +00001461 .addOperand(TmpReg)
Roger Ferrer Ibanezc8f4dbb2018-08-14 08:30:42 +00001462 .addExpr(RefToLinkTmpLabel));
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001463}
1464
Alex Bradbury22531c42019-02-15 09:53:32 +00001465void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
1466 MCStreamer &Out) {
1467 // The load local address pseudo-instruction "lla" is used in PC-relative
1468 // addressing of local symbols:
1469 // lla rdest, symbol
1470 // expands to
1471 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
1472 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
1473 MCOperand DestReg = Inst.getOperand(0);
1474 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1475 emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
1476 RISCV::ADDI, IDLoc, Out);
1477}
1478
1479void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
1480 MCStreamer &Out) {
1481 // The load address pseudo-instruction "la" is used in PC-relative and
1482 // GOT-indirect addressing of global symbols:
1483 // la rdest, symbol
1484 // expands to either (for non-PIC)
1485 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
1486 // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
1487 // or (for PIC)
1488 // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
1489 // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
1490 MCOperand DestReg = Inst.getOperand(0);
1491 const MCExpr *Symbol = Inst.getOperand(1).getExpr();
1492 unsigned SecondOpcode;
1493 RISCVMCExpr::VariantKind VKHi;
1494 // FIXME: Should check .option (no)pic when implemented
1495 if (getContext().getObjectFileInfo()->isPositionIndependent()) {
1496 SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
1497 VKHi = RISCVMCExpr::VK_RISCV_GOT_HI;
1498 } else {
1499 SecondOpcode = RISCV::ADDI;
1500 VKHi = RISCVMCExpr::VK_RISCV_PCREL_HI;
1501 }
1502 emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out);
1503}
1504
Kito Cheng303217e2019-02-20 03:31:32 +00001505void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
1506 SMLoc IDLoc, MCStreamer &Out,
1507 bool HasTmpReg) {
1508 // The load/store pseudo-instruction does a pc-relative load with
1509 // a symbol.
1510 //
1511 // The expansion looks like this
1512 //
1513 // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
1514 // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
1515 MCOperand DestReg = Inst.getOperand(0);
1516 unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
1517 unsigned TmpRegOpIdx = HasTmpReg ? 1 : 0;
1518 MCOperand TmpReg = Inst.getOperand(TmpRegOpIdx);
1519 const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
1520 emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
1521 Opcode, IDLoc, Out);
1522}
1523
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001524bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1525 MCStreamer &Out) {
1526 Inst.setLoc(IDLoc);
1527
Alex Bradbury22531c42019-02-15 09:53:32 +00001528 switch (Inst.getOpcode()) {
1529 default:
1530 break;
1531 case RISCV::PseudoLI: {
Alex Bradbury2ba76be2019-01-03 14:41:41 +00001532 unsigned Reg = Inst.getOperand(0).getReg();
1533 const MCOperand &Op1 = Inst.getOperand(1);
1534 if (Op1.isExpr()) {
1535 // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
1536 // Just convert to an addi. This allows compatibility with gas.
1537 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
1538 .addReg(Reg)
1539 .addReg(RISCV::X0)
1540 .addExpr(Op1.getExpr()));
1541 return false;
1542 }
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001543 int64_t Imm = Inst.getOperand(1).getImm();
1544 // On RV32 the immediate here can either be a signed or an unsigned
1545 // 32-bit number. Sign extension has to be performed to ensure that Imm
1546 // represents the expected signed 64-bit number.
1547 if (!isRV64())
1548 Imm = SignExtend64<32>(Imm);
1549 emitLoadImm(Reg, Imm, Out);
1550 return false;
Alex Bradbury22531c42019-02-15 09:53:32 +00001551 }
1552 case RISCV::PseudoLLA:
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001553 emitLoadLocalAddress(Inst, IDLoc, Out);
1554 return false;
Alex Bradbury22531c42019-02-15 09:53:32 +00001555 case RISCV::PseudoLA:
1556 emitLoadAddress(Inst, IDLoc, Out);
1557 return false;
Kito Cheng303217e2019-02-20 03:31:32 +00001558 case RISCV::PseudoLB:
1559 emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
1560 return false;
1561 case RISCV::PseudoLBU:
1562 emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
1563 return false;
1564 case RISCV::PseudoLH:
1565 emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
1566 return false;
1567 case RISCV::PseudoLHU:
1568 emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
1569 return false;
1570 case RISCV::PseudoLW:
1571 emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
1572 return false;
1573 case RISCV::PseudoLWU:
1574 emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
1575 return false;
1576 case RISCV::PseudoLD:
1577 emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
1578 return false;
1579 case RISCV::PseudoFLW:
1580 emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
1581 return false;
1582 case RISCV::PseudoFLD:
1583 emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
1584 return false;
1585 case RISCV::PseudoSB:
1586 emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
1587 return false;
1588 case RISCV::PseudoSH:
1589 emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
1590 return false;
1591 case RISCV::PseudoSW:
1592 emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
1593 return false;
1594 case RISCV::PseudoSD:
1595 emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
1596 return false;
1597 case RISCV::PseudoFSW:
1598 emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
1599 return false;
1600 case RISCV::PseudoFSD:
1601 emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
1602 return false;
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001603 }
1604
1605 emitToStreamer(Out, Inst);
1606 return false;
1607}
1608
Alex Bradbury04f06d92017-08-08 14:43:36 +00001609extern "C" void LLVMInitializeRISCVAsmParser() {
1610 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
1611 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
1612}