blob: b0db5f4d8fbd00dd5c5c1e3d7671360eea8e5aa7 [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 Bradbury6758ecb2017-09-17 14:27:35 +000010#include "MCTargetDesc/RISCVBaseInfo.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 Bradbury4f7f0da2017-09-06 09:21:21 +000013#include "llvm/ADT/STLExtras.h"
14#include "llvm/ADT/StringSwitch.h"
15#include "llvm/MC/MCContext.h"
16#include "llvm/MC/MCExpr.h"
17#include "llvm/MC/MCInst.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000018#include "llvm/MC/MCParser/MCAsmLexer.h"
19#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
20#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000021#include "llvm/MC/MCRegisterInfo.h"
22#include "llvm/MC/MCStreamer.h"
23#include "llvm/MC/MCSubtargetInfo.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000024#include "llvm/Support/Casting.h"
25#include "llvm/Support/TargetRegistry.h"
26
27using namespace llvm;
28
29namespace {
30struct RISCVOperand;
31
32class RISCVAsmParser : public MCTargetAsmParser {
33 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
34
Alex Bradbury6758ecb2017-09-17 14:27:35 +000035 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
36 int Lower, int Upper, Twine Msg);
37
Alex Bradbury04f06d92017-08-08 14:43:36 +000038 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
39 OperandVector &Operands, MCStreamer &Out,
40 uint64_t &ErrorInfo,
41 bool MatchingInlineAsm) override;
42
43 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
44
45 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
46 SMLoc NameLoc, OperandVector &Operands) override;
47
48 bool ParseDirective(AsmToken DirectiveID) override;
49
50// Auto-generated instruction matching functions
51#define GET_ASSEMBLER_HEADER
52#include "RISCVGenAsmMatcher.inc"
53
54 OperandMatchResultTy parseImmediate(OperandVector &Operands);
55 OperandMatchResultTy parseRegister(OperandVector &Operands);
Alex Bradbury6758ecb2017-09-17 14:27:35 +000056 OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
Alex Bradbury9d3f1252017-09-28 08:26:24 +000057 OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
Alex Bradbury04f06d92017-08-08 14:43:36 +000058
59 bool parseOperand(OperandVector &Operands);
60
61public:
62 enum RISCVMatchResultTy {
63 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
64#define GET_OPERAND_DIAGNOSTIC_TYPES
65#include "RISCVGenAsmMatcher.inc"
66#undef GET_OPERAND_DIAGNOSTIC_TYPES
67 };
68
Alex Bradbury9d3f1252017-09-28 08:26:24 +000069 static bool classifySymbolRef(const MCExpr *Expr,
70 RISCVMCExpr::VariantKind &Kind,
71 int64_t &Addend);
72
Alex Bradbury04f06d92017-08-08 14:43:36 +000073 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
74 const MCInstrInfo &MII, const MCTargetOptions &Options)
75 : MCTargetAsmParser(Options, STI) {
76 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
77 }
78};
79
80/// RISCVOperand - Instances of this class represent a parsed machine
81/// instruction
82struct RISCVOperand : public MCParsedAsmOperand {
83
84 enum KindTy {
85 Token,
86 Register,
87 Immediate,
88 } Kind;
89
90 struct RegOp {
91 unsigned RegNum;
92 };
93
94 struct ImmOp {
95 const MCExpr *Val;
96 };
97
98 SMLoc StartLoc, EndLoc;
99 union {
100 StringRef Tok;
101 RegOp Reg;
102 ImmOp Imm;
103 };
104
105 RISCVOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
106
107public:
108 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
109 Kind = o.Kind;
110 StartLoc = o.StartLoc;
111 EndLoc = o.EndLoc;
112 switch (Kind) {
113 case Register:
114 Reg = o.Reg;
115 break;
116 case Immediate:
117 Imm = o.Imm;
118 break;
119 case Token:
120 Tok = o.Tok;
121 break;
122 }
123 }
124
125 bool isToken() const override { return Kind == Token; }
126 bool isReg() const override { return Kind == Register; }
127 bool isImm() const override { return Kind == Immediate; }
128 bool isMem() const override { return false; }
129
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000130 bool evaluateConstantImm(int64_t &Imm, RISCVMCExpr::VariantKind &VK) const {
131 const MCExpr *Val = getImm();
132 bool Ret = false;
133 if (auto *RE = dyn_cast<RISCVMCExpr>(Val)) {
134 Ret = RE->evaluateAsConstant(Imm);
135 VK = RE->getKind();
136 } else if (auto CE = dyn_cast<MCConstantExpr>(Val)) {
137 Ret = true;
138 VK = RISCVMCExpr::VK_RISCV_None;
139 Imm = CE->getValue();
140 }
141 return Ret;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000142 }
143
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000144 // True if operand is a symbol with no modifiers, or a constant with no
145 // modifiers and isShiftedInt<N-1, 1>(Op).
146 template <int N> bool isBareSimmNLsb0() const {
147 int64_t Imm;
148 RISCVMCExpr::VariantKind VK;
149 bool IsConstantImm = evaluateConstantImm(Imm, VK);
150 bool IsValid;
151 if (!IsConstantImm)
152 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
153 else
154 IsValid = isShiftedInt<N - 1, 1>(Imm);
155 return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000156 }
157
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000158 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
159
160 /// Return true if the operand is a valid for the fence instruction e.g.
161 /// ('iorw').
162 bool isFenceArg() const {
163 if (!isImm())
164 return false;
165 const MCExpr *Val = getImm();
166 auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
167 if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
168 return false;
169
170 StringRef Str = SVal->getSymbol().getName();
171 // Letters must be unique, taken from 'iorw', and in ascending order. This
172 // holds as long as each individual character is one of 'iorw' and is
173 // greater than the previous character.
174 char Prev = '\0';
175 for (char c : Str) {
176 if (c != 'i' && c != 'o' && c != 'r' && c != 'w')
177 return false;
178 if (c <= Prev)
179 return false;
180 Prev = c;
181 }
182 return true;
183 }
184
185 bool isUImm5() const {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000186 int64_t Imm;
187 RISCVMCExpr::VariantKind VK;
188 bool IsConstantImm = evaluateConstantImm(Imm, VK);
189 return IsConstantImm && isUInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000190 }
191
Alex Bradbury04f06d92017-08-08 14:43:36 +0000192 bool isSImm12() const {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000193 RISCVMCExpr::VariantKind VK;
194 int64_t Imm;
195 bool IsValid;
196 bool IsConstantImm = evaluateConstantImm(Imm, VK);
197 if (!IsConstantImm)
198 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
199 else
200 IsValid = isInt<12>(Imm);
201 return IsValid &&
202 (VK == RISCVMCExpr::VK_RISCV_None || VK == RISCVMCExpr::VK_RISCV_LO);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000203 }
204
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000205 bool isUImm12() const {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000206 int64_t Imm;
207 RISCVMCExpr::VariantKind VK;
208 bool IsConstantImm = evaluateConstantImm(Imm, VK);
209 return IsConstantImm && isUInt<12>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000210 }
211
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000212 bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000213
214 bool isUImm20() const {
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000215 RISCVMCExpr::VariantKind VK;
216 int64_t Imm;
217 bool IsValid;
218 bool IsConstantImm = evaluateConstantImm(Imm, VK);
219 if (!IsConstantImm)
220 IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
221 else
222 IsValid = isUInt<20>(Imm);
223 return IsValid && (VK == RISCVMCExpr::VK_RISCV_None ||
224 VK == RISCVMCExpr::VK_RISCV_HI ||
225 VK == RISCVMCExpr::VK_RISCV_PCREL_HI);
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000226 }
227
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000228 bool isSImm21Lsb0() const { return isBareSimmNLsb0<21>(); }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000229
Alex Bradbury04f06d92017-08-08 14:43:36 +0000230 /// getStartLoc - Gets location of the first token of this operand
231 SMLoc getStartLoc() const override { return StartLoc; }
232 /// getEndLoc - Gets location of the last token of this operand
233 SMLoc getEndLoc() const override { return EndLoc; }
234
235 unsigned getReg() const override {
236 assert(Kind == Register && "Invalid type access!");
237 return Reg.RegNum;
238 }
239
240 const MCExpr *getImm() const {
241 assert(Kind == Immediate && "Invalid type access!");
242 return Imm.Val;
243 }
244
245 StringRef getToken() const {
246 assert(Kind == Token && "Invalid type access!");
247 return Tok;
248 }
249
250 void print(raw_ostream &OS) const override {
251 switch (Kind) {
252 case Immediate:
253 OS << *getImm();
254 break;
255 case Register:
256 OS << "<register x";
257 OS << getReg() << ">";
258 break;
259 case Token:
260 OS << "'" << getToken() << "'";
261 break;
262 }
263 }
264
265 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {
266 auto Op = make_unique<RISCVOperand>(Token);
267 Op->Tok = Str;
268 Op->StartLoc = S;
269 Op->EndLoc = S;
270 return Op;
271 }
272
273 static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S,
274 SMLoc E) {
275 auto Op = make_unique<RISCVOperand>(Register);
276 Op->Reg.RegNum = RegNo;
277 Op->StartLoc = S;
278 Op->EndLoc = E;
279 return Op;
280 }
281
282 static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000283 SMLoc E, MCContext &Ctx) {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000284 auto Op = make_unique<RISCVOperand>(Immediate);
285 Op->Imm.Val = Val;
286 Op->StartLoc = S;
287 Op->EndLoc = E;
288 return Op;
289 }
290
291 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
292 assert(Expr && "Expr shouldn't be null!");
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000293 int64_t Imm = 0;
294 bool IsConstant = false;
295 if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
296 IsConstant = RE->evaluateAsConstant(Imm);
297 } else if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
298 IsConstant = true;
299 Imm = CE->getValue();
300 }
301
302 if (IsConstant)
303 Inst.addOperand(MCOperand::createImm(Imm));
Alex Bradbury04f06d92017-08-08 14:43:36 +0000304 else
305 Inst.addOperand(MCOperand::createExpr(Expr));
306 }
307
308 // Used by the TableGen Code
309 void addRegOperands(MCInst &Inst, unsigned N) const {
310 assert(N == 1 && "Invalid number of operands!");
311 Inst.addOperand(MCOperand::createReg(getReg()));
312 }
313
314 void addImmOperands(MCInst &Inst, unsigned N) const {
315 assert(N == 1 && "Invalid number of operands!");
316 addExpr(Inst, getImm());
317 }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000318
319 void addFenceArgOperands(MCInst &Inst, unsigned N) const {
320 assert(N == 1 && "Invalid number of operands!");
321 // isFenceArg has validated the operand, meaning this cast is safe
322 auto SE = cast<MCSymbolRefExpr>(getImm());
323
324 unsigned Imm = 0;
325 for (char c : SE->getSymbol().getName()) {
326 switch (c) {
327 default: llvm_unreachable("FenceArg must contain only [iorw]");
328 case 'i': Imm |= RISCVFenceField::I; break;
329 case 'o': Imm |= RISCVFenceField::O; break;
330 case 'r': Imm |= RISCVFenceField::R; break;
331 case 'w': Imm |= RISCVFenceField::W; break;
332 }
333 }
334 Inst.addOperand(MCOperand::createImm(Imm));
335 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000336};
337} // end anonymous namespace.
338
339#define GET_REGISTER_MATCHER
340#define GET_MATCHER_IMPLEMENTATION
Alex Bradbury04f06d92017-08-08 14:43:36 +0000341#include "RISCVGenAsmMatcher.inc"
342
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000343bool RISCVAsmParser::generateImmOutOfRangeError(
344 OperandVector &Operands, uint64_t ErrorInfo, int Lower, int Upper,
345 Twine Msg = "immediate must be an integer in the range") {
346 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
347 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
348}
349
Alex Bradbury04f06d92017-08-08 14:43:36 +0000350bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
351 OperandVector &Operands,
352 MCStreamer &Out,
353 uint64_t &ErrorInfo,
354 bool MatchingInlineAsm) {
355 MCInst Inst;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000356
357 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
358 default:
359 break;
360 case Match_Success:
361 Inst.setLoc(IDLoc);
362 Out.EmitInstruction(Inst, getSTI());
363 return false;
364 case Match_MissingFeature:
365 return Error(IDLoc, "instruction use requires an option to be enabled");
366 case Match_MnemonicFail:
367 return Error(IDLoc, "unrecognized instruction mnemonic");
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000368 case Match_InvalidOperand: {
369 SMLoc ErrorLoc = IDLoc;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000370 if (ErrorInfo != ~0U) {
371 if (ErrorInfo >= Operands.size())
372 return Error(ErrorLoc, "too few operands for instruction");
373
374 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
375 if (ErrorLoc == SMLoc())
376 ErrorLoc = IDLoc;
377 }
378 return Error(ErrorLoc, "invalid operand for instruction");
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000379 }
380 case Match_InvalidUImm5:
381 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000382 case Match_InvalidSImm12:
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000383 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 11),
384 (1 << 11) - 1);
385 case Match_InvalidUImm12:
386 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
387 case Match_InvalidSImm13Lsb0:
388 return generateImmOutOfRangeError(
389 Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
390 "immediate must be a multiple of 2 bytes in the range");
391 case Match_InvalidUImm20:
392 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1);
393 case Match_InvalidSImm21Lsb0:
394 return generateImmOutOfRangeError(
395 Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
396 "immediate must be a multiple of 2 bytes in the range");
397 case Match_InvalidFenceArg: {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000398 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000399 return Error(
400 ErrorLoc,
401 "operand must be formed of letters selected in-order from 'iorw'");
402 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000403 }
404
405 llvm_unreachable("Unknown match type detected!");
406}
407
408bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
409 SMLoc &EndLoc) {
410 const AsmToken &Tok = getParser().getTok();
411 StartLoc = Tok.getLoc();
412 EndLoc = Tok.getEndLoc();
413 RegNo = 0;
414 StringRef Name = getLexer().getTok().getIdentifier();
415
416 if (!MatchRegisterName(Name) || !MatchRegisterAltName(Name)) {
417 getParser().Lex(); // Eat identifier token.
418 return false;
419 }
420
421 return Error(StartLoc, "invalid register name");
422}
423
424OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands) {
425 SMLoc S = getLoc();
426 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
427
428 switch (getLexer().getKind()) {
429 default:
430 return MatchOperand_NoMatch;
431 case AsmToken::Identifier:
432 StringRef Name = getLexer().getTok().getIdentifier();
433 unsigned RegNo = MatchRegisterName(Name);
434 if (RegNo == 0) {
435 RegNo = MatchRegisterAltName(Name);
436 if (RegNo == 0)
437 return MatchOperand_NoMatch;
438 }
439 getLexer().Lex();
440 Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
441 }
442 return MatchOperand_Success;
443}
444
445OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000446 SMLoc S = getLoc();
447 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
448 const MCExpr *Res;
449
Alex Bradbury04f06d92017-08-08 14:43:36 +0000450 switch (getLexer().getKind()) {
451 default:
452 return MatchOperand_NoMatch;
453 case AsmToken::LParen:
454 case AsmToken::Minus:
455 case AsmToken::Plus:
456 case AsmToken::Integer:
457 case AsmToken::String:
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000458 if (getParser().parseExpression(Res))
459 return MatchOperand_ParseFail;
460 break;
461 case AsmToken::Identifier: {
462 StringRef Identifier;
463 if (getParser().parseIdentifier(Identifier))
464 return MatchOperand_ParseFail;
465 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
466 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Alex Bradbury04f06d92017-08-08 14:43:36 +0000467 break;
468 }
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000469 case AsmToken::Percent:
470 return parseOperandWithModifier(Operands);
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000471 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000472
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000473 Operands.push_back(RISCVOperand::createImm(Res, S, E, getContext()));
474 return MatchOperand_Success;
475}
476
477OperandMatchResultTy
478RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
479 SMLoc S = getLoc();
480 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
481
482 if (getLexer().getKind() != AsmToken::Percent) {
483 Error(getLoc(), "expected '%' for operand modifier");
484 return MatchOperand_ParseFail;
485 }
486
487 getParser().Lex(); // Eat '%'
488
489 if (getLexer().getKind() != AsmToken::Identifier) {
490 Error(getLoc(), "expected valid identifier for operand modifier");
491 return MatchOperand_ParseFail;
492 }
493 StringRef Identifier = getParser().getTok().getIdentifier();
494 RISCVMCExpr::VariantKind VK = RISCVMCExpr::getVariantKindForName(Identifier);
495 if (VK == RISCVMCExpr::VK_RISCV_Invalid) {
496 Error(getLoc(), "unrecognized operand modifier");
497 return MatchOperand_ParseFail;
498 }
499
500 getParser().Lex(); // Eat the identifier
501 if (getLexer().getKind() != AsmToken::LParen) {
502 Error(getLoc(), "expected '('");
503 return MatchOperand_ParseFail;
504 }
505 getParser().Lex(); // Eat '('
506
507 const MCExpr *SubExpr;
508 if (getParser().parseParenExpression(SubExpr, E)) {
509 return MatchOperand_ParseFail;
510 }
511
512 const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
513 Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, getContext()));
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000514 return MatchOperand_Success;
515}
516
517OperandMatchResultTy
518RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
519 if (getLexer().isNot(AsmToken::LParen)) {
520 Error(getLoc(), "expected '('");
Alex Bradbury04f06d92017-08-08 14:43:36 +0000521 return MatchOperand_ParseFail;
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000522 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000523
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000524 getParser().Lex(); // Eat '('
525 Operands.push_back(RISCVOperand::createToken("(", getLoc()));
526
527 if (parseRegister(Operands) != MatchOperand_Success) {
528 Error(getLoc(), "expected register");
529 return MatchOperand_ParseFail;
530 }
531
532 if (getLexer().isNot(AsmToken::RParen)) {
533 Error(getLoc(), "expected ')'");
534 return MatchOperand_ParseFail;
535 }
536
537 getParser().Lex(); // Eat ')'
538 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
539
Alex Bradbury04f06d92017-08-08 14:43:36 +0000540 return MatchOperand_Success;
541}
542
543/// Looks at a token type and creates the relevant operand
544/// from this information, adding to Operands.
545/// If operand was parsed, returns false, else true.
546bool RISCVAsmParser::parseOperand(OperandVector &Operands) {
547 // Attempt to parse token as register
548 if (parseRegister(Operands) == MatchOperand_Success)
549 return false;
550
551 // Attempt to parse token as an immediate
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000552 if (parseImmediate(Operands) == MatchOperand_Success) {
553 // Parse memory base register if present
554 if (getLexer().is(AsmToken::LParen))
555 return parseMemOpBaseReg(Operands) != MatchOperand_Success;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000556 return false;
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000557 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000558
559 // Finally we have exhausted all options and must declare defeat.
560 Error(getLoc(), "unknown operand");
561 return true;
562}
563
564bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
565 StringRef Name, SMLoc NameLoc,
566 OperandVector &Operands) {
567 // First operand is token for instruction
568 Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
569
570 // If there are no more operands, then finish
571 if (getLexer().is(AsmToken::EndOfStatement))
572 return false;
573
574 // Parse first operand
575 if (parseOperand(Operands))
576 return true;
577
578 // Parse until end of statement, consuming commas between operands
579 while (getLexer().is(AsmToken::Comma)) {
580 // Consume comma token
581 getLexer().Lex();
582
583 // Parse next operand
584 if (parseOperand(Operands))
585 return true;
586 }
587
588 if (getLexer().isNot(AsmToken::EndOfStatement)) {
589 SMLoc Loc = getLexer().getLoc();
590 getParser().eatToEndOfStatement();
591 return Error(Loc, "unexpected token");
592 }
593
594 getParser().Lex(); // Consume the EndOfStatement.
595 return false;
596}
597
Alex Bradbury9d3f1252017-09-28 08:26:24 +0000598bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
599 RISCVMCExpr::VariantKind &Kind,
600 int64_t &Addend) {
601 Kind = RISCVMCExpr::VK_RISCV_None;
602 Addend = 0;
603
604 if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
605 Kind = RE->getKind();
606 Expr = RE->getSubExpr();
607 }
608
609 // It's a simple symbol reference or constant with no addend.
610 if (isa<MCConstantExpr>(Expr) || isa<MCSymbolRefExpr>(Expr))
611 return true;
612
613 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
614 if (!BE)
615 return false;
616
617 if (!isa<MCSymbolRefExpr>(BE->getLHS()))
618 return false;
619
620 if (BE->getOpcode() != MCBinaryExpr::Add &&
621 BE->getOpcode() != MCBinaryExpr::Sub)
622 return false;
623
624 // We are able to support the subtraction of two symbol references
625 if (BE->getOpcode() == MCBinaryExpr::Sub &&
626 isa<MCSymbolRefExpr>(BE->getRHS()))
627 return true;
628
629 // See if the addend is is a constant, otherwise there's more going
630 // on here than we can deal with.
631 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
632 if (!AddendExpr)
633 return false;
634
635 Addend = AddendExpr->getValue();
636 if (BE->getOpcode() == MCBinaryExpr::Sub)
637 Addend = -Addend;
638
639 // It's some symbol reference + a constant addend
640 return Kind != RISCVMCExpr::VK_RISCV_Invalid;
641}
642
Alex Bradbury04f06d92017-08-08 14:43:36 +0000643bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
644
645extern "C" void LLVMInitializeRISCVAsmParser() {
646 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
647 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
648}