blob: 331eb2b361c8df4a38162b390c96e03c48eb4575 [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"
17#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 Bradbury04f06d92017-08-08 14:43:36 +000023#include "llvm/MC/MCParser/MCAsmLexer.h"
24#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
25#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000026#include "llvm/MC/MCRegisterInfo.h"
27#include "llvm/MC/MCStreamer.h"
28#include "llvm/MC/MCSubtargetInfo.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000029#include "llvm/Support/Casting.h"
Alex Bradbury6a4b5442018-06-07 15:35:47 +000030#include "llvm/Support/MathExtras.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000031#include "llvm/Support/TargetRegistry.h"
32
Alex Bradbury6a4b5442018-06-07 15:35:47 +000033#include <limits>
34
Alex Bradbury04f06d92017-08-08 14:43:36 +000035using namespace llvm;
36
Sameer AbuAsalc1b0e662018-04-06 21:07:05 +000037// Include the auto-generated portion of the compress emitter.
38#define GEN_COMPRESS_INSTR
39#include "RISCVGenCompressInstEmitter.inc"
40
Alex Bradbury04f06d92017-08-08 14:43:36 +000041namespace {
42struct RISCVOperand;
43
44class RISCVAsmParser : public MCTargetAsmParser {
45 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Alex Bradburya6e62482017-12-07 10:53:48 +000046 bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
Alex Bradbury04f06d92017-08-08 14:43:36 +000047
Alex Bradburybca0c3c2018-05-11 17:30:28 +000048 RISCVTargetStreamer &getTargetStreamer() {
49 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
50 return static_cast<RISCVTargetStreamer &>(TS);
51 }
52
Alex Bradbury7bc2a952017-12-07 10:46:23 +000053 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
54 unsigned Kind) override;
55
Alex Bradbury6758ecb2017-09-17 14:27:35 +000056 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
Alex Bradbury6a4b5442018-06-07 15:35:47 +000057 int64_t Lower, int64_t Upper, Twine Msg);
Alex Bradbury6758ecb2017-09-17 14:27:35 +000058
Alex Bradbury04f06d92017-08-08 14:43:36 +000059 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
60 OperandVector &Operands, MCStreamer &Out,
61 uint64_t &ErrorInfo,
62 bool MatchingInlineAsm) override;
63
64 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
65
66 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
67 SMLoc NameLoc, OperandVector &Operands) override;
68
69 bool ParseDirective(AsmToken DirectiveID) override;
70
Alex Bradbury6a4b5442018-06-07 15:35:47 +000071 // Helper to actually emit an instruction to the MCStreamer. Also, when
72 // possible, compression of the instruction is performed.
73 void emitToStreamer(MCStreamer &S, const MCInst &Inst);
74
75 // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
76 // synthesize the desired immedate value into the destination register.
77 void emitLoadImm(unsigned DestReg, int64_t Value, MCStreamer &Out);
78
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +000079 // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
80 void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
81
Alex Bradbury6a4b5442018-06-07 15:35:47 +000082 /// Helper for processing MC instructions that have been successfully matched
83 /// by MatchAndEmitInstruction. Modifications to the emitted instructions,
84 /// like the expansion of pseudo instructions (e.g., "li"), can be performed
85 /// in this method.
86 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
87
Alex Bradbury04f06d92017-08-08 14:43:36 +000088// Auto-generated instruction matching functions
89#define GET_ASSEMBLER_HEADER
90#include "RISCVGenAsmMatcher.inc"
91
Ana Pazos9d6c5532018-10-04 21:50:54 +000092 OperandMatchResultTy parseCSRSystemRegister(OperandVector &Operands);
Alex Bradbury04f06d92017-08-08 14:43:36 +000093 OperandMatchResultTy parseImmediate(OperandVector &Operands);
Alex Bradbury8c345c52017-11-09 15:00:03 +000094 OperandMatchResultTy parseRegister(OperandVector &Operands,
95 bool AllowParens = false);
Alex Bradbury6758ecb2017-09-17 14:27:35 +000096 OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
Alex Bradbury9d3f1252017-09-28 08:26:24 +000097 OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
Alex Bradbury68f73c12018-09-18 15:18:16 +000098 OperandMatchResultTy parseBareSymbol(OperandVector &Operands);
Alex Bradbury226f3ef2018-09-20 08:10:35 +000099 OperandMatchResultTy parseJALOffset(OperandVector &Operands);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000100
Alex Bradbury68f73c12018-09-18 15:18:16 +0000101 bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000102
Alex Bradburybca0c3c2018-05-11 17:30:28 +0000103 bool parseDirectiveOption();
104
105 void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
106 if (!(getSTI().getFeatureBits()[Feature])) {
107 MCSubtargetInfo &STI = copySTI();
108 setAvailableFeatures(
109 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
110 }
111 }
112
113 void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
114 if (getSTI().getFeatureBits()[Feature]) {
115 MCSubtargetInfo &STI = copySTI();
116 setAvailableFeatures(
117 ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
118 }
119 }
Ana Pazos9d6c5532018-10-04 21:50:54 +0000120
Alex Bradbury04f06d92017-08-08 14:43:36 +0000121public:
122 enum RISCVMatchResultTy {
123 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
124#define GET_OPERAND_DIAGNOSTIC_TYPES
125#include "RISCVGenAsmMatcher.inc"
126#undef GET_OPERAND_DIAGNOSTIC_TYPES
127 };
128
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000129 static bool classifySymbolRef(const MCExpr *Expr,
130 RISCVMCExpr::VariantKind &Kind,
131 int64_t &Addend);
132
Alex Bradbury04f06d92017-08-08 14:43:36 +0000133 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
134 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000135 : MCTargetAsmParser(Options, STI, MII) {
Alex Bradburycea6db02018-05-17 05:58:08 +0000136 Parser.addAliasForDirective(".half", ".2byte");
137 Parser.addAliasForDirective(".hword", ".2byte");
138 Parser.addAliasForDirective(".word", ".4byte");
139 Parser.addAliasForDirective(".dword", ".8byte");
Alex Bradbury04f06d92017-08-08 14:43:36 +0000140 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
141 }
142};
143
144/// RISCVOperand - Instances of this class represent a parsed machine
145/// instruction
146struct RISCVOperand : public MCParsedAsmOperand {
147
148 enum KindTy {
149 Token,
150 Register,
151 Immediate,
Ana Pazos9d6c5532018-10-04 21:50:54 +0000152 SystemRegister
Alex Bradbury04f06d92017-08-08 14:43:36 +0000153 } Kind;
154
Alex Bradburya6e62482017-12-07 10:53:48 +0000155 bool IsRV64;
156
Alex Bradbury04f06d92017-08-08 14:43:36 +0000157 struct RegOp {
158 unsigned RegNum;
159 };
160
161 struct ImmOp {
162 const MCExpr *Val;
163 };
164
Ana Pazos9d6c5532018-10-04 21:50:54 +0000165 struct SysRegOp {
166 const char *Data;
167 unsigned Length;
168 unsigned Encoding;
169 // FIXME: Add the Encoding parsed fields as needed for checks,
170 // e.g.: read/write or user/supervisor/machine privileges.
171 };
172
Alex Bradbury04f06d92017-08-08 14:43:36 +0000173 SMLoc StartLoc, EndLoc;
174 union {
175 StringRef Tok;
176 RegOp Reg;
177 ImmOp Imm;
Ana Pazos9d6c5532018-10-04 21:50:54 +0000178 struct SysRegOp SysReg;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000179 };
180
181 RISCVOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
182
183public:
184 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
185 Kind = o.Kind;
Alex Bradburya6e62482017-12-07 10:53:48 +0000186 IsRV64 = o.IsRV64;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000187 StartLoc = o.StartLoc;
188 EndLoc = o.EndLoc;
189 switch (Kind) {
190 case Register:
191 Reg = o.Reg;
192 break;
193 case Immediate:
194 Imm = o.Imm;
195 break;
196 case Token:
197 Tok = o.Tok;
198 break;
Ana Pazos9d6c5532018-10-04 21:50:54 +0000199 case SystemRegister:
200 SysReg = o.SysReg;
201 break;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000202 }
203 }
204
205 bool isToken() const override { return Kind == Token; }
206 bool isReg() const override { return Kind == Register; }
207 bool isImm() const override { return Kind == Immediate; }
208 bool isMem() const override { return false; }
Ana Pazos9d6c5532018-10-04 21:50:54 +0000209 bool isSystemRegister() const { return Kind == SystemRegister; }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000210
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000211 static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
212 RISCVMCExpr::VariantKind &VK) {
213 if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000214 VK = RE->getKind();
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000215 return RE->evaluateAsConstant(Imm);
216 }
217
218 if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000219 VK = RISCVMCExpr::VK_RISCV_None;
220 Imm = CE->getValue();
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000221 return true;
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000222 }
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000223
224 return false;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000225 }
226
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000227 // True if operand is a symbol with no modifiers, or a constant with no
228 // modifiers and isShiftedInt<N-1, 1>(Op).
229 template <int N> bool isBareSimmNLsb0() const {
230 int64_t Imm;
231 RISCVMCExpr::VariantKind VK;
Alex Bradbury3c941e72017-10-19 16:22:51 +0000232 if (!isImm())
233 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000234 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000235 bool IsValid;
236 if (!IsConstantImm)
237 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
238 else
239 IsValid = isShiftedInt<N - 1, 1>(Imm);
240 return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000241 }
242
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000243 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
244
Shiva Chen98f93892018-04-25 14:18:55 +0000245 bool isBareSymbol() const {
246 int64_t Imm;
247 RISCVMCExpr::VariantKind VK;
248 // Must be of 'immediate' type but not a constant.
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000249 if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
Shiva Chen98f93892018-04-25 14:18:55 +0000250 return false;
251 return RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm) &&
252 VK == RISCVMCExpr::VK_RISCV_None;
253 }
254
Ana Pazos9d6c5532018-10-04 21:50:54 +0000255 bool isCSRSystemRegister() const { return isSystemRegister(); }
256
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000257 /// Return true if the operand is a valid for the fence instruction e.g.
258 /// ('iorw').
259 bool isFenceArg() const {
260 if (!isImm())
261 return false;
262 const MCExpr *Val = getImm();
263 auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
264 if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
265 return false;
266
267 StringRef Str = SVal->getSymbol().getName();
268 // Letters must be unique, taken from 'iorw', and in ascending order. This
269 // holds as long as each individual character is one of 'iorw' and is
270 // greater than the previous character.
271 char Prev = '\0';
272 for (char c : Str) {
273 if (c != 'i' && c != 'o' && c != 'r' && c != 'w')
274 return false;
275 if (c <= Prev)
276 return false;
277 Prev = c;
278 }
279 return true;
280 }
281
Alex Bradbury0d6cf902017-12-07 10:26:05 +0000282 /// Return true if the operand is a valid floating point rounding mode.
283 bool isFRMArg() const {
284 if (!isImm())
285 return false;
286 const MCExpr *Val = getImm();
287 auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
288 if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
289 return false;
290
291 StringRef Str = SVal->getSymbol().getName();
292
293 return RISCVFPRndMode::stringToRoundingMode(Str) != RISCVFPRndMode::Invalid;
294 }
295
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000296 bool isImmXLen() const {
297 int64_t Imm;
298 RISCVMCExpr::VariantKind VK;
299 if (!isImm())
300 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000301 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000302 // Given only Imm, ensuring that the actually specified constant is either
303 // a signed or unsigned 64-bit number is unfortunately impossible.
304 bool IsInRange = isRV64() ? true : isInt<32>(Imm) || isUInt<32>(Imm);
305 return IsConstantImm && IsInRange && VK == RISCVMCExpr::VK_RISCV_None;
306 }
307
Alex Bradburya6e62482017-12-07 10:53:48 +0000308 bool isUImmLog2XLen() const {
309 int64_t Imm;
310 RISCVMCExpr::VariantKind VK;
311 if (!isImm())
312 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000313 if (!evaluateConstantImm(getImm(), Imm, VK) ||
314 VK != RISCVMCExpr::VK_RISCV_None)
Alex Bradburya6e62482017-12-07 10:53:48 +0000315 return false;
316 return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm);
317 }
318
Alex Bradbury0ad4c262017-12-15 10:20:51 +0000319 bool isUImmLog2XLenNonZero() const {
320 int64_t Imm;
321 RISCVMCExpr::VariantKind VK;
322 if (!isImm())
323 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000324 if (!evaluateConstantImm(getImm(), Imm, VK) ||
325 VK != RISCVMCExpr::VK_RISCV_None)
Alex Bradbury0ad4c262017-12-15 10:20:51 +0000326 return false;
327 if (Imm == 0)
328 return false;
329 return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm);
330 }
331
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000332 bool isUImm5() const {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000333 int64_t Imm;
334 RISCVMCExpr::VariantKind VK;
Alex Bradbury3c941e72017-10-19 16:22:51 +0000335 if (!isImm())
336 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000337 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000338 return IsConstantImm && isUInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000339 }
340
Alex Bradbury60714f92017-12-13 09:32:55 +0000341 bool isUImm5NonZero() const {
342 int64_t Imm;
343 RISCVMCExpr::VariantKind VK;
344 if (!isImm())
345 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000346 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury60714f92017-12-13 09:32:55 +0000347 return IsConstantImm && isUInt<5>(Imm) && (Imm != 0) &&
348 VK == RISCVMCExpr::VK_RISCV_None;
349 }
350
Alex Bradbury581d6b02017-12-13 09:41:21 +0000351 bool isSImm6() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000352 if (!isImm())
353 return false;
Alex Bradbury581d6b02017-12-13 09:41:21 +0000354 RISCVMCExpr::VariantKind VK;
355 int64_t Imm;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000356 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Ana Pazos065b0882018-09-13 18:37:23 +0000357 return IsConstantImm && isInt<6>(Imm) &&
358 VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury581d6b02017-12-13 09:41:21 +0000359 }
360
Shiva Chenb22c1d22018-02-02 02:43:23 +0000361 bool isSImm6NonZero() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000362 if (!isImm())
363 return false;
Shiva Chenb22c1d22018-02-02 02:43:23 +0000364 RISCVMCExpr::VariantKind VK;
365 int64_t Imm;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000366 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Ana Pazos065b0882018-09-13 18:37:23 +0000367 return IsConstantImm && isInt<6>(Imm) && (Imm != 0) &&
368 VK == RISCVMCExpr::VK_RISCV_None;
Shiva Chenb22c1d22018-02-02 02:43:23 +0000369 }
370
Shiva Chen7c172422018-02-22 15:02:28 +0000371 bool isCLUIImm() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000372 if (!isImm())
373 return false;
Alex Bradbury60714f92017-12-13 09:32:55 +0000374 int64_t Imm;
375 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000376 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Shiva Chen7c172422018-02-22 15:02:28 +0000377 return IsConstantImm && (Imm != 0) &&
378 (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
Ana Pazos9d6c5532018-10-04 21:50:54 +0000379 VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury60714f92017-12-13 09:32:55 +0000380 }
381
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000382 bool isUImm7Lsb00() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000383 if (!isImm())
384 return false;
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000385 int64_t Imm;
386 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000387 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000388 return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
389 VK == RISCVMCExpr::VK_RISCV_None;
390 }
391
392 bool isUImm8Lsb00() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000393 if (!isImm())
394 return false;
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000395 int64_t Imm;
396 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000397 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000398 return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
399 VK == RISCVMCExpr::VK_RISCV_None;
400 }
401
402 bool isUImm8Lsb000() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000403 if (!isImm())
404 return false;
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000405 int64_t Imm;
406 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000407 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000408 return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
409 VK == RISCVMCExpr::VK_RISCV_None;
410 }
411
Alex Bradburyf8f4b902017-12-07 13:19:57 +0000412 bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
413
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000414 bool isUImm9Lsb000() 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<6, 3>(Imm) &&
421 VK == RISCVMCExpr::VK_RISCV_None;
422 }
423
Alex Bradbury60714f92017-12-13 09:32:55 +0000424 bool isUImm10Lsb00NonZero() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000425 if (!isImm())
426 return false;
Alex Bradbury60714f92017-12-13 09:32:55 +0000427 int64_t Imm;
428 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000429 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury60714f92017-12-13 09:32:55 +0000430 return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
431 VK == RISCVMCExpr::VK_RISCV_None;
432 }
433
Alex Bradbury04f06d92017-08-08 14:43:36 +0000434 bool isSImm12() const {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000435 RISCVMCExpr::VariantKind VK;
436 int64_t Imm;
437 bool IsValid;
Alex Bradbury3c941e72017-10-19 16:22:51 +0000438 if (!isImm())
439 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000440 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000441 if (!IsConstantImm)
442 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
443 else
444 IsValid = isInt<12>(Imm);
Alex Bradbury7d0e18d2018-09-18 15:13:29 +0000445 return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
Ahmed Charles646ab872018-02-06 00:55:23 +0000446 VK == RISCVMCExpr::VK_RISCV_LO ||
447 VK == RISCVMCExpr::VK_RISCV_PCREL_LO);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000448 }
449
Alex Bradburyf8f4b902017-12-07 13:19:57 +0000450 bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
451
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000452 bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000453
Shiva Chenb22c1d22018-02-02 02:43:23 +0000454 bool isSImm10Lsb0000NonZero() const {
Ana Pazosecc65ed2018-08-24 23:47:49 +0000455 if (!isImm())
456 return false;
Alex Bradbury60714f92017-12-13 09:32:55 +0000457 int64_t Imm;
458 RISCVMCExpr::VariantKind VK;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000459 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Shiva Chenb22c1d22018-02-02 02:43:23 +0000460 return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) &&
Alex Bradbury60714f92017-12-13 09:32:55 +0000461 VK == RISCVMCExpr::VK_RISCV_None;
462 }
463
Alex Bradbury74340f12018-09-18 15:08:35 +0000464 bool isUImm20LUI() const {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000465 RISCVMCExpr::VariantKind VK;
466 int64_t Imm;
467 bool IsValid;
Alex Bradbury3c941e72017-10-19 16:22:51 +0000468 if (!isImm())
469 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000470 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury74340f12018-09-18 15:08:35 +0000471 if (!IsConstantImm) {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000472 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
Alex Bradbury74340f12018-09-18 15:08:35 +0000473 return IsValid && VK == RISCVMCExpr::VK_RISCV_HI;
474 } else {
475 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
476 VK == RISCVMCExpr::VK_RISCV_HI);
477 }
478 }
479
480 bool isUImm20AUIPC() const {
481 RISCVMCExpr::VariantKind VK;
482 int64_t Imm;
483 bool IsValid;
484 if (!isImm())
485 return false;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000486 bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
Alex Bradbury74340f12018-09-18 15:08:35 +0000487 if (!IsConstantImm) {
488 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
489 return IsValid && VK == RISCVMCExpr::VK_RISCV_PCREL_HI;
490 } else {
491 return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
492 VK == RISCVMCExpr::VK_RISCV_PCREL_HI);
493 }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000494 }
495
Alex Bradbury226f3ef2018-09-20 08:10:35 +0000496 bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000497
Alex Bradbury04f06d92017-08-08 14:43:36 +0000498 /// getStartLoc - Gets location of the first token of this operand
499 SMLoc getStartLoc() const override { return StartLoc; }
500 /// getEndLoc - Gets location of the last token of this operand
501 SMLoc getEndLoc() const override { return EndLoc; }
Alex Bradburya6e62482017-12-07 10:53:48 +0000502 /// True if this operand is for an RV64 instruction
503 bool isRV64() const { return IsRV64; }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000504
505 unsigned getReg() const override {
506 assert(Kind == Register && "Invalid type access!");
507 return Reg.RegNum;
508 }
509
Ana Pazos9d6c5532018-10-04 21:50:54 +0000510 StringRef getSysReg() const {
511 assert(Kind == SystemRegister && "Invalid access!");
512 return StringRef(SysReg.Data, SysReg.Length);
513 }
514
Alex Bradbury04f06d92017-08-08 14:43:36 +0000515 const MCExpr *getImm() const {
516 assert(Kind == Immediate && "Invalid type access!");
517 return Imm.Val;
518 }
519
520 StringRef getToken() const {
521 assert(Kind == Token && "Invalid type access!");
522 return Tok;
523 }
524
525 void print(raw_ostream &OS) const override {
526 switch (Kind) {
527 case Immediate:
528 OS << *getImm();
529 break;
530 case Register:
531 OS << "<register x";
532 OS << getReg() << ">";
533 break;
534 case Token:
535 OS << "'" << getToken() << "'";
536 break;
Ana Pazos9d6c5532018-10-04 21:50:54 +0000537 case SystemRegister:
538 OS << "<sysreg: " << getSysReg() << '>';
539 break;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000540 }
541 }
542
Alex Bradburya6e62482017-12-07 10:53:48 +0000543 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S,
544 bool IsRV64) {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000545 auto Op = make_unique<RISCVOperand>(Token);
546 Op->Tok = Str;
547 Op->StartLoc = S;
548 Op->EndLoc = S;
Alex Bradburya6e62482017-12-07 10:53:48 +0000549 Op->IsRV64 = IsRV64;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000550 return Op;
551 }
552
553 static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S,
Alex Bradburya6e62482017-12-07 10:53:48 +0000554 SMLoc E, bool IsRV64) {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000555 auto Op = make_unique<RISCVOperand>(Register);
556 Op->Reg.RegNum = RegNo;
557 Op->StartLoc = S;
558 Op->EndLoc = E;
Alex Bradburya6e62482017-12-07 10:53:48 +0000559 Op->IsRV64 = IsRV64;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000560 return Op;
561 }
562
563 static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
Alex Bradburya6e62482017-12-07 10:53:48 +0000564 SMLoc E, bool IsRV64) {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000565 auto Op = make_unique<RISCVOperand>(Immediate);
566 Op->Imm.Val = Val;
567 Op->StartLoc = S;
568 Op->EndLoc = E;
Alex Bradburya6e62482017-12-07 10:53:48 +0000569 Op->IsRV64 = IsRV64;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000570 return Op;
571 }
572
Ana Pazos9d6c5532018-10-04 21:50:54 +0000573 static std::unique_ptr<RISCVOperand>
574 createSysReg(StringRef Str, SMLoc S, unsigned Encoding, bool IsRV64) {
575 auto Op = make_unique<RISCVOperand>(SystemRegister);
576 Op->SysReg.Data = Str.data();
577 Op->SysReg.Length = Str.size();
578 Op->SysReg.Encoding = Encoding;
579 Op->StartLoc = S;
580 Op->IsRV64 = IsRV64;
581 return Op;
582 }
583
Alex Bradbury04f06d92017-08-08 14:43:36 +0000584 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
585 assert(Expr && "Expr shouldn't be null!");
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000586 int64_t Imm = 0;
Alex Bradbury96ed75d2018-09-20 11:40:43 +0000587 RISCVMCExpr::VariantKind VK;
588 bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000589
590 if (IsConstant)
591 Inst.addOperand(MCOperand::createImm(Imm));
Alex Bradbury04f06d92017-08-08 14:43:36 +0000592 else
593 Inst.addOperand(MCOperand::createExpr(Expr));
594 }
595
596 // Used by the TableGen Code
597 void addRegOperands(MCInst &Inst, unsigned N) const {
598 assert(N == 1 && "Invalid number of operands!");
599 Inst.addOperand(MCOperand::createReg(getReg()));
600 }
601
602 void addImmOperands(MCInst &Inst, unsigned N) const {
603 assert(N == 1 && "Invalid number of operands!");
604 addExpr(Inst, getImm());
605 }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000606
607 void addFenceArgOperands(MCInst &Inst, unsigned N) const {
608 assert(N == 1 && "Invalid number of operands!");
609 // isFenceArg has validated the operand, meaning this cast is safe
610 auto SE = cast<MCSymbolRefExpr>(getImm());
611
612 unsigned Imm = 0;
613 for (char c : SE->getSymbol().getName()) {
614 switch (c) {
Ana Pazos9d6c5532018-10-04 21:50:54 +0000615 default:
616 llvm_unreachable("FenceArg must contain only [iorw]");
617 case 'i': Imm |= RISCVFenceField::I; break;
618 case 'o': Imm |= RISCVFenceField::O; break;
619 case 'r': Imm |= RISCVFenceField::R; break;
620 case 'w': Imm |= RISCVFenceField::W; break;
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000621 }
622 }
623 Inst.addOperand(MCOperand::createImm(Imm));
624 }
Alex Bradbury0d6cf902017-12-07 10:26:05 +0000625
Ana Pazos9d6c5532018-10-04 21:50:54 +0000626 void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
627 assert(N == 1 && "Invalid number of operands!");
628 Inst.addOperand(MCOperand::createImm(SysReg.Encoding));
629 }
630
Alex Bradbury0d6cf902017-12-07 10:26:05 +0000631 // Returns the rounding mode represented by this RISCVOperand. Should only
632 // be called after checking isFRMArg.
633 RISCVFPRndMode::RoundingMode getRoundingMode() const {
634 // isFRMArg has validated the operand, meaning this cast is safe.
635 auto SE = cast<MCSymbolRefExpr>(getImm());
636 RISCVFPRndMode::RoundingMode FRM =
637 RISCVFPRndMode::stringToRoundingMode(SE->getSymbol().getName());
638 assert(FRM != RISCVFPRndMode::Invalid && "Invalid rounding mode");
639 return FRM;
640 }
641
642 void addFRMArgOperands(MCInst &Inst, unsigned N) const {
643 assert(N == 1 && "Invalid number of operands!");
644 Inst.addOperand(MCOperand::createImm(getRoundingMode()));
645 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000646};
647} // end anonymous namespace.
648
649#define GET_REGISTER_MATCHER
650#define GET_MATCHER_IMPLEMENTATION
Alex Bradbury04f06d92017-08-08 14:43:36 +0000651#include "RISCVGenAsmMatcher.inc"
652
Alex Bradbury7bc2a952017-12-07 10:46:23 +0000653// Return the matching FPR64 register for the given FPR32.
654// FIXME: Ideally this function could be removed in favour of using
655// information from TableGen.
656unsigned convertFPR32ToFPR64(unsigned Reg) {
657 switch (Reg) {
Ana Pazos9d6c5532018-10-04 21:50:54 +0000658 default:
659 llvm_unreachable("Not a recognised FPR32 register");
660 case RISCV::F0_32: return RISCV::F0_64;
661 case RISCV::F1_32: return RISCV::F1_64;
662 case RISCV::F2_32: return RISCV::F2_64;
663 case RISCV::F3_32: return RISCV::F3_64;
664 case RISCV::F4_32: return RISCV::F4_64;
665 case RISCV::F5_32: return RISCV::F5_64;
666 case RISCV::F6_32: return RISCV::F6_64;
667 case RISCV::F7_32: return RISCV::F7_64;
668 case RISCV::F8_32: return RISCV::F8_64;
669 case RISCV::F9_32: return RISCV::F9_64;
670 case RISCV::F10_32: return RISCV::F10_64;
671 case RISCV::F11_32: return RISCV::F11_64;
672 case RISCV::F12_32: return RISCV::F12_64;
673 case RISCV::F13_32: return RISCV::F13_64;
674 case RISCV::F14_32: return RISCV::F14_64;
675 case RISCV::F15_32: return RISCV::F15_64;
676 case RISCV::F16_32: return RISCV::F16_64;
677 case RISCV::F17_32: return RISCV::F17_64;
678 case RISCV::F18_32: return RISCV::F18_64;
679 case RISCV::F19_32: return RISCV::F19_64;
680 case RISCV::F20_32: return RISCV::F20_64;
681 case RISCV::F21_32: return RISCV::F21_64;
682 case RISCV::F22_32: return RISCV::F22_64;
683 case RISCV::F23_32: return RISCV::F23_64;
684 case RISCV::F24_32: return RISCV::F24_64;
685 case RISCV::F25_32: return RISCV::F25_64;
686 case RISCV::F26_32: return RISCV::F26_64;
687 case RISCV::F27_32: return RISCV::F27_64;
688 case RISCV::F28_32: return RISCV::F28_64;
689 case RISCV::F29_32: return RISCV::F29_64;
690 case RISCV::F30_32: return RISCV::F30_64;
691 case RISCV::F31_32: return RISCV::F31_64;
Alex Bradbury7bc2a952017-12-07 10:46:23 +0000692 }
693}
694
695unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
696 unsigned Kind) {
697 RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
698 if (!Op.isReg())
699 return Match_InvalidOperand;
700
701 unsigned Reg = Op.getReg();
702 bool IsRegFPR32 =
703 RISCVMCRegisterClasses[RISCV::FPR32RegClassID].contains(Reg);
Alex Bradbury60714f92017-12-13 09:32:55 +0000704 bool IsRegFPR32C =
705 RISCVMCRegisterClasses[RISCV::FPR32CRegClassID].contains(Reg);
Alex Bradbury7bc2a952017-12-07 10:46:23 +0000706
707 // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
Alex Bradbury60714f92017-12-13 09:32:55 +0000708 // register from FPR32 to FPR64 or FPR32C to FPR64C if necessary.
709 if ((IsRegFPR32 && Kind == MCK_FPR64) ||
710 (IsRegFPR32C && Kind == MCK_FPR64C)) {
Alex Bradbury7bc2a952017-12-07 10:46:23 +0000711 Op.Reg.RegNum = convertFPR32ToFPR64(Reg);
712 return Match_Success;
713 }
714 return Match_InvalidOperand;
715}
716
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000717bool RISCVAsmParser::generateImmOutOfRangeError(
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000718 OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000719 Twine Msg = "immediate must be an integer in the range") {
720 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
721 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
722}
723
Alex Bradbury04f06d92017-08-08 14:43:36 +0000724bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
725 OperandVector &Operands,
726 MCStreamer &Out,
727 uint64_t &ErrorInfo,
728 bool MatchingInlineAsm) {
729 MCInst Inst;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000730
Ana Pazos6b34051b2018-08-30 19:43:19 +0000731 auto Result =
732 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
733 switch (Result) {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000734 default:
735 break;
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000736 case Match_Success:
737 return processInstruction(Inst, IDLoc, Out);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000738 case Match_MissingFeature:
739 return Error(IDLoc, "instruction use requires an option to be enabled");
740 case Match_MnemonicFail:
741 return Error(IDLoc, "unrecognized instruction mnemonic");
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000742 case Match_InvalidOperand: {
743 SMLoc ErrorLoc = IDLoc;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000744 if (ErrorInfo != ~0U) {
745 if (ErrorInfo >= Operands.size())
746 return Error(ErrorLoc, "too few operands for instruction");
747
748 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
749 if (ErrorLoc == SMLoc())
750 ErrorLoc = IDLoc;
751 }
752 return Error(ErrorLoc, "invalid operand for instruction");
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000753 }
Ana Pazos6b34051b2018-08-30 19:43:19 +0000754 }
755
756 // Handle the case when the error message is of specific type
757 // other than the generic Match_InvalidOperand, and the
758 // corresponding operand is missing.
759 if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
760 SMLoc ErrorLoc = IDLoc;
761 if (ErrorInfo != ~0U && ErrorInfo >= Operands.size())
762 return Error(ErrorLoc, "too few operands for instruction");
763 }
764
765 switch(Result) {
766 default:
767 break;
Alex Bradbury6a4b5442018-06-07 15:35:47 +0000768 case Match_InvalidImmXLen:
769 if (isRV64()) {
770 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
771 return Error(ErrorLoc, "operand must be a constant 64-bit integer");
772 }
773 return generateImmOutOfRangeError(Operands, ErrorInfo,
774 std::numeric_limits<int32_t>::min(),
775 std::numeric_limits<uint32_t>::max());
Alex Bradburya6e62482017-12-07 10:53:48 +0000776 case Match_InvalidUImmLog2XLen:
777 if (isRV64())
778 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
779 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
Alex Bradbury0ad4c262017-12-15 10:20:51 +0000780 case Match_InvalidUImmLog2XLenNonZero:
781 if (isRV64())
782 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
783 return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000784 case Match_InvalidUImm5:
785 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
Alex Bradbury581d6b02017-12-13 09:41:21 +0000786 case Match_InvalidSImm6:
787 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
788 (1 << 5) - 1);
Shiva Chenb22c1d22018-02-02 02:43:23 +0000789 case Match_InvalidSImm6NonZero:
Ana Pazos9d6c5532018-10-04 21:50:54 +0000790 return generateImmOutOfRangeError(
791 Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,
Shiva Chenb22c1d22018-02-02 02:43:23 +0000792 "immediate must be non-zero in the range");
Shiva Chen7c172422018-02-22 15:02:28 +0000793 case Match_InvalidCLUIImm:
794 return generateImmOutOfRangeError(
795 Operands, ErrorInfo, 1, (1 << 5) - 1,
796 "immediate must be in [0xfffe0, 0xfffff] or");
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000797 case Match_InvalidUImm7Lsb00:
798 return generateImmOutOfRangeError(
799 Operands, ErrorInfo, 0, (1 << 7) - 4,
800 "immediate must be a multiple of 4 bytes in the range");
801 case Match_InvalidUImm8Lsb00:
802 return generateImmOutOfRangeError(
803 Operands, ErrorInfo, 0, (1 << 8) - 4,
804 "immediate must be a multiple of 4 bytes in the range");
805 case Match_InvalidUImm8Lsb000:
806 return generateImmOutOfRangeError(
807 Operands, ErrorInfo, 0, (1 << 8) - 8,
808 "immediate must be a multiple of 8 bytes in the range");
Alex Bradburyf8f4b902017-12-07 13:19:57 +0000809 case Match_InvalidSImm9Lsb0:
810 return generateImmOutOfRangeError(
811 Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
812 "immediate must be a multiple of 2 bytes in the range");
Alex Bradbury9f6aec42017-12-07 12:50:32 +0000813 case Match_InvalidUImm9Lsb000:
814 return generateImmOutOfRangeError(
815 Operands, ErrorInfo, 0, (1 << 9) - 8,
816 "immediate must be a multiple of 8 bytes in the range");
Alex Bradbury60714f92017-12-13 09:32:55 +0000817 case Match_InvalidUImm10Lsb00NonZero:
818 return generateImmOutOfRangeError(
819 Operands, ErrorInfo, 4, (1 << 10) - 4,
820 "immediate must be a multiple of 4 bytes in the range");
Shiva Chenb22c1d22018-02-02 02:43:23 +0000821 case Match_InvalidSImm10Lsb0000NonZero:
Alex Bradbury60714f92017-12-13 09:32:55 +0000822 return generateImmOutOfRangeError(
823 Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
Shiva Chenb22c1d22018-02-02 02:43:23 +0000824 "immediate must be a multiple of 16 bytes and non-zero in the range");
Alex Bradbury04f06d92017-08-08 14:43:36 +0000825 case Match_InvalidSImm12:
Alex Bradbury7d0e18d2018-09-18 15:13:29 +0000826 return generateImmOutOfRangeError(
827 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
828 "operand must be a symbol with %lo/%pcrel_lo modifier or an integer in "
829 "the range");
Alex Bradburyf8f4b902017-12-07 13:19:57 +0000830 case Match_InvalidSImm12Lsb0:
831 return generateImmOutOfRangeError(
832 Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
833 "immediate must be a multiple of 2 bytes in the range");
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000834 case Match_InvalidSImm13Lsb0:
835 return generateImmOutOfRangeError(
836 Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
837 "immediate must be a multiple of 2 bytes in the range");
Alex Bradbury74340f12018-09-18 15:08:35 +0000838 case Match_InvalidUImm20LUI:
839 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
840 "operand must be a symbol with %hi() "
841 "modifier or an integer in the range");
842 case Match_InvalidUImm20AUIPC:
843 return generateImmOutOfRangeError(
844 Operands, ErrorInfo, 0, (1 << 20) - 1,
845 "operand must be a symbol with %pcrel_hi() modifier or an integer in "
846 "the range");
Alex Bradbury226f3ef2018-09-20 08:10:35 +0000847 case Match_InvalidSImm21Lsb0JAL:
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000848 return generateImmOutOfRangeError(
849 Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
850 "immediate must be a multiple of 2 bytes in the range");
Ana Pazos9d6c5532018-10-04 21:50:54 +0000851 case Match_InvalidCSRSystemRegister: {
852 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,
853 "operand must be a valid system register "
854 "name or an integer in the range");
855 }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000856 case Match_InvalidFenceArg: {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000857 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000858 return Error(
859 ErrorLoc,
860 "operand must be formed of letters selected in-order from 'iorw'");
861 }
Alex Bradbury0d6cf902017-12-07 10:26:05 +0000862 case Match_InvalidFRMArg: {
863 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
864 return Error(
865 ErrorLoc,
866 "operand must be a valid floating point rounding mode mnemonic");
867 }
Shiva Chen98f93892018-04-25 14:18:55 +0000868 case Match_InvalidBareSymbol: {
869 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
870 return Error(ErrorLoc, "operand must be a bare symbol name");
871 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000872 }
873
874 llvm_unreachable("Unknown match type detected!");
875}
876
877bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
878 SMLoc &EndLoc) {
879 const AsmToken &Tok = getParser().getTok();
880 StartLoc = Tok.getLoc();
881 EndLoc = Tok.getEndLoc();
882 RegNo = 0;
883 StringRef Name = getLexer().getTok().getIdentifier();
884
885 if (!MatchRegisterName(Name) || !MatchRegisterAltName(Name)) {
886 getParser().Lex(); // Eat identifier token.
887 return false;
888 }
889
890 return Error(StartLoc, "invalid register name");
891}
892
Alex Bradbury8c345c52017-11-09 15:00:03 +0000893OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands,
894 bool AllowParens) {
895 SMLoc FirstS = getLoc();
896 bool HadParens = false;
897 AsmToken Buf[2];
898
899 // If this a parenthesised register name is allowed, parse it atomically
900 if (AllowParens && getLexer().is(AsmToken::LParen)) {
901 size_t ReadCount = getLexer().peekTokens(Buf);
902 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
903 HadParens = true;
904 getParser().Lex(); // Eat '('
905 }
906 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000907
908 switch (getLexer().getKind()) {
909 default:
910 return MatchOperand_NoMatch;
911 case AsmToken::Identifier:
912 StringRef Name = getLexer().getTok().getIdentifier();
913 unsigned RegNo = MatchRegisterName(Name);
914 if (RegNo == 0) {
915 RegNo = MatchRegisterAltName(Name);
Alex Bradbury8c345c52017-11-09 15:00:03 +0000916 if (RegNo == 0) {
917 if (HadParens)
918 getLexer().UnLex(Buf[0]);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000919 return MatchOperand_NoMatch;
Alex Bradbury8c345c52017-11-09 15:00:03 +0000920 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000921 }
Alex Bradbury8c345c52017-11-09 15:00:03 +0000922 if (HadParens)
Alex Bradburya6e62482017-12-07 10:53:48 +0000923 Operands.push_back(RISCVOperand::createToken("(", FirstS, isRV64()));
Alex Bradbury8c345c52017-11-09 15:00:03 +0000924 SMLoc S = getLoc();
925 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000926 getLexer().Lex();
Alex Bradburya6e62482017-12-07 10:53:48 +0000927 Operands.push_back(RISCVOperand::createReg(RegNo, S, E, isRV64()));
Alex Bradbury04f06d92017-08-08 14:43:36 +0000928 }
Alex Bradbury8c345c52017-11-09 15:00:03 +0000929
930 if (HadParens) {
931 getParser().Lex(); // Eat ')'
Alex Bradburya6e62482017-12-07 10:53:48 +0000932 Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
Alex Bradbury8c345c52017-11-09 15:00:03 +0000933 }
934
Alex Bradbury04f06d92017-08-08 14:43:36 +0000935 return MatchOperand_Success;
936}
937
Ana Pazos9d6c5532018-10-04 21:50:54 +0000938OperandMatchResultTy
939RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
940 SMLoc S = getLoc();
941 const MCExpr *Res;
942
943 switch (getLexer().getKind()) {
944 default:
945 return MatchOperand_NoMatch;
946 case AsmToken::LParen:
947 case AsmToken::Minus:
948 case AsmToken::Plus:
949 case AsmToken::Integer:
950 case AsmToken::String: {
951 if (getParser().parseExpression(Res))
952 return MatchOperand_ParseFail;
953
954 auto *CE = dyn_cast<MCConstantExpr>(Res);
955 if (CE) {
956 int64_t Imm = CE->getValue();
957 if (isUInt<12>(Imm)) {
958 auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
959 // Accept an immediate representing a named or un-named Sys Reg
960 // if the range is valid, regardless of the required features.
961 Operands.push_back(RISCVOperand::createSysReg(
962 SysReg ? SysReg->Name : "", S, Imm, isRV64()));
963 return MatchOperand_Success;
964 }
965 }
966
967 Twine Msg = "immediate must be an integer in the range";
968 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
969 return MatchOperand_ParseFail;
970 }
971 case AsmToken::Identifier: {
972 StringRef Identifier;
973 if (getParser().parseIdentifier(Identifier))
974 return MatchOperand_ParseFail;
975
976 auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
977 // Accept a named Sys Reg if the required features are present.
978 if (SysReg) {
979 if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits())) {
980 Error(S, "system register use requires an option to be enabled");
981 return MatchOperand_ParseFail;
982 }
983 Operands.push_back(RISCVOperand::createSysReg(
984 Identifier, S, SysReg->Encoding, isRV64()));
985 return MatchOperand_Success;
986 }
987
988 Twine Msg = "operand must be a valid system register name "
989 "or an integer in the range";
990 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
991 return MatchOperand_ParseFail;
992 }
993 case AsmToken::Percent: {
994 // Discard operand with modifier.
995 Twine Msg = "immediate must be an integer in the range";
996 Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
997 return MatchOperand_ParseFail;
998 }
999 }
1000
1001 return MatchOperand_NoMatch;
1002}
1003
Alex Bradbury04f06d92017-08-08 14:43:36 +00001004OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001005 SMLoc S = getLoc();
1006 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1007 const MCExpr *Res;
1008
Alex Bradbury04f06d92017-08-08 14:43:36 +00001009 switch (getLexer().getKind()) {
1010 default:
1011 return MatchOperand_NoMatch;
1012 case AsmToken::LParen:
1013 case AsmToken::Minus:
1014 case AsmToken::Plus:
1015 case AsmToken::Integer:
1016 case AsmToken::String:
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001017 if (getParser().parseExpression(Res))
1018 return MatchOperand_ParseFail;
1019 break;
1020 case AsmToken::Identifier: {
1021 StringRef Identifier;
1022 if (getParser().parseIdentifier(Identifier))
1023 return MatchOperand_ParseFail;
1024 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1025 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Alex Bradbury04f06d92017-08-08 14:43:36 +00001026 break;
1027 }
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001028 case AsmToken::Percent:
1029 return parseOperandWithModifier(Operands);
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001030 }
Alex Bradbury04f06d92017-08-08 14:43:36 +00001031
Alex Bradburya6e62482017-12-07 10:53:48 +00001032 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001033 return MatchOperand_Success;
1034}
1035
1036OperandMatchResultTy
1037RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
1038 SMLoc S = getLoc();
1039 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1040
1041 if (getLexer().getKind() != AsmToken::Percent) {
1042 Error(getLoc(), "expected '%' for operand modifier");
1043 return MatchOperand_ParseFail;
1044 }
1045
1046 getParser().Lex(); // Eat '%'
1047
1048 if (getLexer().getKind() != AsmToken::Identifier) {
1049 Error(getLoc(), "expected valid identifier for operand modifier");
1050 return MatchOperand_ParseFail;
1051 }
1052 StringRef Identifier = getParser().getTok().getIdentifier();
1053 RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier);
1054 if (VK == RISCVMCExpr::VK_RISCV_Invalid) {
1055 Error(getLoc(), "unrecognized operand modifier");
1056 return MatchOperand_ParseFail;
1057 }
1058
1059 getParser().Lex(); // Eat the identifier
1060 if (getLexer().getKind() != AsmToken::LParen) {
1061 Error(getLoc(), "expected '('");
1062 return MatchOperand_ParseFail;
1063 }
1064 getParser().Lex(); // Eat '('
1065
1066 const MCExpr *SubExpr;
1067 if (getParser().parseParenExpression(SubExpr, E)) {
1068 return MatchOperand_ParseFail;
1069 }
1070
1071 const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
Alex Bradburya6e62482017-12-07 10:53:48 +00001072 Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001073 return MatchOperand_Success;
1074}
1075
Alex Bradbury68f73c12018-09-18 15:18:16 +00001076OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
1077 SMLoc S = getLoc();
1078 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
1079 const MCExpr *Res;
1080
1081 if (getLexer().getKind() != AsmToken::Identifier)
1082 return MatchOperand_NoMatch;
1083
1084 StringRef Identifier;
1085 if (getParser().parseIdentifier(Identifier))
1086 return MatchOperand_ParseFail;
1087
1088 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1089 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1090 Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1091 return MatchOperand_Success;
1092}
1093
Alex Bradbury226f3ef2018-09-20 08:10:35 +00001094OperandMatchResultTy RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
1095 // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
1096 // both being acceptable forms. When parsing `jal ra, foo` this function
1097 // will be called for the `ra` register operand in an attempt to match the
1098 // single-operand alias. parseJALOffset must fail for this case. It would
1099 // seem logical to try parse the operand using parseImmediate and return
1100 // NoMatch if the next token is a comma (meaning we must be parsing a jal in
1101 // the second form rather than the first). We can't do this as there's no
1102 // way of rewinding the lexer state. Instead, return NoMatch if this operand
1103 // is an identifier and is followed by a comma.
1104 if (getLexer().is(AsmToken::Identifier) &&
1105 getLexer().peekTok().is(AsmToken::Comma))
1106 return MatchOperand_NoMatch;
1107
1108 return parseImmediate(Operands);
1109}
1110
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001111OperandMatchResultTy
1112RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
1113 if (getLexer().isNot(AsmToken::LParen)) {
1114 Error(getLoc(), "expected '('");
Alex Bradbury04f06d92017-08-08 14:43:36 +00001115 return MatchOperand_ParseFail;
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001116 }
Alex Bradbury04f06d92017-08-08 14:43:36 +00001117
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001118 getParser().Lex(); // Eat '('
Alex Bradburya6e62482017-12-07 10:53:48 +00001119 Operands.push_back(RISCVOperand::createToken("(", getLoc(), isRV64()));
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001120
1121 if (parseRegister(Operands) != MatchOperand_Success) {
1122 Error(getLoc(), "expected register");
1123 return MatchOperand_ParseFail;
1124 }
1125
1126 if (getLexer().isNot(AsmToken::RParen)) {
1127 Error(getLoc(), "expected ')'");
1128 return MatchOperand_ParseFail;
1129 }
1130
1131 getParser().Lex(); // Eat ')'
Alex Bradburya6e62482017-12-07 10:53:48 +00001132 Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001133
Alex Bradbury04f06d92017-08-08 14:43:36 +00001134 return MatchOperand_Success;
1135}
1136
Alex Bradburycd8688a2018-04-25 17:25:29 +00001137/// Looks at a token type and creates the relevant operand from this
1138/// information, adding to Operands. If operand was parsed, returns false, else
Alex Bradbury68f73c12018-09-18 15:18:16 +00001139/// true.
1140bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1141 // Check if the current operand has a custom associated parser, if so, try to
1142 // custom parse the operand, or fallback to the general approach.
1143 OperandMatchResultTy Result =
1144 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
1145 if (Result == MatchOperand_Success)
1146 return false;
1147 if (Result == MatchOperand_ParseFail)
1148 return true;
1149
1150 // Attempt to parse token as a register.
1151 if (parseRegister(Operands, true) == MatchOperand_Success)
Alex Bradbury04f06d92017-08-08 14:43:36 +00001152 return false;
1153
1154 // Attempt to parse token as an immediate
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001155 if (parseImmediate(Operands) == MatchOperand_Success) {
1156 // Parse memory base register if present
1157 if (getLexer().is(AsmToken::LParen))
1158 return parseMemOpBaseReg(Operands) != MatchOperand_Success;
Alex Bradbury04f06d92017-08-08 14:43:36 +00001159 return false;
Alex Bradbury6758ecb2017-09-17 14:27:35 +00001160 }
Alex Bradbury04f06d92017-08-08 14:43:36 +00001161
1162 // Finally we have exhausted all options and must declare defeat.
1163 Error(getLoc(), "unknown operand");
1164 return true;
1165}
1166
1167bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
1168 StringRef Name, SMLoc NameLoc,
1169 OperandVector &Operands) {
Alex Bradbury9c03e4c2018-11-12 14:25:07 +00001170 // Ensure that if the instruction occurs when relaxation is enabled,
1171 // relocations are forced for the file. Ideally this would be done when there
1172 // is enough information to reliably determine if the instruction itself may
1173 // cause relaxations. Unfortunately instruction processing stage occurs in the
1174 // same pass as relocation emission, so it's too late to set a 'sticky bit'
1175 // for the entire file.
1176 if (getSTI().getFeatureBits()[RISCV::FeatureRelax]) {
1177 auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
1178 if (Assembler != nullptr) {
1179 RISCVAsmBackend &MAB =
1180 static_cast<RISCVAsmBackend &>(Assembler->getBackend());
1181 MAB.setForceRelocs();
1182 }
1183 }
1184
Alex Bradbury04f06d92017-08-08 14:43:36 +00001185 // First operand is token for instruction
Alex Bradburya6e62482017-12-07 10:53:48 +00001186 Operands.push_back(RISCVOperand::createToken(Name, NameLoc, isRV64()));
Alex Bradbury04f06d92017-08-08 14:43:36 +00001187
1188 // If there are no more operands, then finish
1189 if (getLexer().is(AsmToken::EndOfStatement))
1190 return false;
1191
1192 // Parse first operand
Alex Bradbury68f73c12018-09-18 15:18:16 +00001193 if (parseOperand(Operands, Name))
Alex Bradbury04f06d92017-08-08 14:43:36 +00001194 return true;
1195
1196 // Parse until end of statement, consuming commas between operands
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001197 unsigned OperandIdx = 1;
Alex Bradbury04f06d92017-08-08 14:43:36 +00001198 while (getLexer().is(AsmToken::Comma)) {
1199 // Consume comma token
1200 getLexer().Lex();
1201
1202 // Parse next operand
Alex Bradbury68f73c12018-09-18 15:18:16 +00001203 if (parseOperand(Operands, Name))
Alex Bradbury04f06d92017-08-08 14:43:36 +00001204 return true;
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001205
1206 ++OperandIdx;
Alex Bradbury04f06d92017-08-08 14:43:36 +00001207 }
1208
1209 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1210 SMLoc Loc = getLexer().getLoc();
1211 getParser().eatToEndOfStatement();
1212 return Error(Loc, "unexpected token");
1213 }
1214
1215 getParser().Lex(); // Consume the EndOfStatement.
1216 return false;
1217}
1218
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001219bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
1220 RISCVMCExpr::VariantKind &Kind,
1221 int64_t &Addend) {
1222 Kind = RISCVMCExpr::VK_RISCV_None;
1223 Addend = 0;
1224
1225 if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
1226 Kind = RE->getKind();
1227 Expr = RE->getSubExpr();
1228 }
1229
1230 // It's a simple symbol reference or constant with no addend.
1231 if (isa<MCConstantExpr>(Expr) || isa<MCSymbolRefExpr>(Expr))
1232 return true;
1233
1234 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
1235 if (!BE)
1236 return false;
1237
1238 if (!isa<MCSymbolRefExpr>(BE->getLHS()))
1239 return false;
1240
1241 if (BE->getOpcode() != MCBinaryExpr::Add &&
1242 BE->getOpcode() != MCBinaryExpr::Sub)
1243 return false;
1244
1245 // We are able to support the subtraction of two symbol references
1246 if (BE->getOpcode() == MCBinaryExpr::Sub &&
1247 isa<MCSymbolRefExpr>(BE->getRHS()))
1248 return true;
1249
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00001250 // See if the addend is a constant, otherwise there's more going
Alex Bradbury9d3f1252017-09-28 08:26:24 +00001251 // on here than we can deal with.
1252 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
1253 if (!AddendExpr)
1254 return false;
1255
1256 Addend = AddendExpr->getValue();
1257 if (BE->getOpcode() == MCBinaryExpr::Sub)
1258 Addend = -Addend;
1259
1260 // It's some symbol reference + a constant addend
1261 return Kind != RISCVMCExpr::VK_RISCV_Invalid;
1262}
1263
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001264bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
1265 // This returns false if this function recognizes the directive
1266 // regardless of whether it is successfully handles or reports an
1267 // error. Otherwise it returns true to give the generic parser a
1268 // chance at recognizing it.
1269 StringRef IDVal = DirectiveID.getString();
1270
1271 if (IDVal == ".option")
1272 return parseDirectiveOption();
1273
1274 return true;
1275}
1276
1277bool RISCVAsmParser::parseDirectiveOption() {
1278 MCAsmParser &Parser = getParser();
1279 // Get the option token.
1280 AsmToken Tok = Parser.getTok();
1281 // At the moment only identifiers are supported.
1282 if (Tok.isNot(AsmToken::Identifier))
1283 return Error(Parser.getTok().getLoc(),
1284 "unexpected token, expected identifier");
1285
1286 StringRef Option = Tok.getIdentifier();
1287
1288 if (Option == "rvc") {
1289 getTargetStreamer().emitDirectiveOptionRVC();
1290
1291 Parser.Lex();
1292 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1293 return Error(Parser.getTok().getLoc(),
1294 "unexpected token, expected end of statement");
1295
1296 setFeatureBits(RISCV::FeatureStdExtC, "c");
1297 return false;
1298 }
1299
1300 if (Option == "norvc") {
1301 getTargetStreamer().emitDirectiveOptionNoRVC();
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 clearFeatureBits(RISCV::FeatureStdExtC, "c");
1309 return false;
1310 }
1311
Alex Bradbury9c03e4c2018-11-12 14:25:07 +00001312 if (Option == "relax") {
1313 getTargetStreamer().emitDirectiveOptionRelax();
1314
1315 Parser.Lex();
1316 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1317 return Error(Parser.getTok().getLoc(),
1318 "unexpected token, expected end of statement");
1319
1320 setFeatureBits(RISCV::FeatureRelax, "relax");
1321 return false;
1322 }
1323
1324 if (Option == "norelax") {
1325 getTargetStreamer().emitDirectiveOptionNoRelax();
1326
1327 Parser.Lex();
1328 if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1329 return Error(Parser.getTok().getLoc(),
1330 "unexpected token, expected end of statement");
1331
1332 clearFeatureBits(RISCV::FeatureRelax, "relax");
1333 return false;
1334 }
1335
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001336 // Unknown option.
1337 Warning(Parser.getTok().getLoc(),
Alex Bradbury9c03e4c2018-11-12 14:25:07 +00001338 "unknown option, expected 'rvc', 'norvc', 'relax' or 'norelax'");
Alex Bradburybca0c3c2018-05-11 17:30:28 +00001339 Parser.eatToEndOfStatement();
1340 return false;
1341}
Alex Bradbury04f06d92017-08-08 14:43:36 +00001342
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001343void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
1344 MCInst CInst;
1345 bool Res = compressInst(CInst, Inst, getSTI(), S.getContext());
1346 CInst.setLoc(Inst.getLoc());
1347 S.EmitInstruction((Res ? CInst : Inst), getSTI());
1348}
1349
1350void RISCVAsmParser::emitLoadImm(unsigned DestReg, int64_t Value,
1351 MCStreamer &Out) {
Alex Bradbury22c091f2018-11-15 10:11:31 +00001352 RISCVMatInt::InstSeq Seq;
1353 RISCVMatInt::generateInstSeq(Value, isRV64(), Seq);
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001354
Alex Bradbury22c091f2018-11-15 10:11:31 +00001355 unsigned SrcReg = RISCV::X0;
1356 for (RISCVMatInt::Inst &Inst : Seq) {
1357 if (Inst.Opc == RISCV::LUI) {
1358 emitToStreamer(
1359 Out, MCInstBuilder(RISCV::LUI).addReg(DestReg).addImm(Inst.Imm));
1360 } else {
1361 emitToStreamer(
1362 Out, MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm(
1363 Inst.Imm));
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001364 }
1365
Alex Bradbury22c091f2018-11-15 10:11:31 +00001366 // Only the first instruction has X0 as its source.
1367 SrcReg = DestReg;
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001368 }
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001369}
1370
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001371void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
1372 MCStreamer &Out) {
1373 // The local load address pseudo-instruction "lla" is used in PC-relative
1374 // addressing of symbols:
1375 // lla rdest, symbol
1376 // expands to
1377 // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
1378 // ADDI rdest, %pcrel_lo(TmpLabel)
1379 MCContext &Ctx = getContext();
1380
1381 MCSymbol *TmpLabel = Ctx.createTempSymbol(
1382 "pcrel_hi", /* AlwaysAddSuffix */ true, /* CanBeUnnamed */ false);
1383 Out.EmitLabel(TmpLabel);
1384
1385 MCOperand DestReg = Inst.getOperand(0);
1386 const RISCVMCExpr *Symbol = RISCVMCExpr::create(
1387 Inst.getOperand(1).getExpr(), RISCVMCExpr::VK_RISCV_PCREL_HI, Ctx);
1388
Roger Ferrer Ibanezc8f4dbb2018-08-14 08:30:42 +00001389 emitToStreamer(
1390 Out, MCInstBuilder(RISCV::AUIPC).addOperand(DestReg).addExpr(Symbol));
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001391
1392 const MCExpr *RefToLinkTmpLabel =
1393 RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),
1394 RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
1395
Roger Ferrer Ibanezc8f4dbb2018-08-14 08:30:42 +00001396 emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
1397 .addOperand(DestReg)
1398 .addOperand(DestReg)
1399 .addExpr(RefToLinkTmpLabel));
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001400}
1401
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001402bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1403 MCStreamer &Out) {
1404 Inst.setLoc(IDLoc);
1405
1406 if (Inst.getOpcode() == RISCV::PseudoLI) {
1407 auto Reg = Inst.getOperand(0).getReg();
1408 int64_t Imm = Inst.getOperand(1).getImm();
1409 // On RV32 the immediate here can either be a signed or an unsigned
1410 // 32-bit number. Sign extension has to be performed to ensure that Imm
1411 // represents the expected signed 64-bit number.
1412 if (!isRV64())
1413 Imm = SignExtend64<32>(Imm);
1414 emitLoadImm(Reg, Imm, Out);
1415 return false;
Roger Ferrer Ibanez577a97e2018-08-09 07:08:20 +00001416 } else if (Inst.getOpcode() == RISCV::PseudoLLA) {
1417 emitLoadLocalAddress(Inst, IDLoc, Out);
1418 return false;
Alex Bradbury6a4b5442018-06-07 15:35:47 +00001419 }
1420
1421 emitToStreamer(Out, Inst);
1422 return false;
1423}
1424
Alex Bradbury04f06d92017-08-08 14:43:36 +00001425extern "C" void LLVMInitializeRISCVAsmParser() {
1426 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
1427 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
1428}