blob: 4b1eec9ec86df07a8121d46272bb00f4cbce13e9 [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 Bradbury04f06d92017-08-08 14:43:36 +000011#include "MCTargetDesc/RISCVMCTargetDesc.h"
Alex Bradbury4f7f0da2017-09-06 09:21:21 +000012#include "llvm/ADT/STLExtras.h"
13#include "llvm/ADT/StringSwitch.h"
14#include "llvm/MC/MCContext.h"
15#include "llvm/MC/MCExpr.h"
16#include "llvm/MC/MCInst.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000017#include "llvm/MC/MCParser/MCAsmLexer.h"
18#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
19#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000020#include "llvm/MC/MCRegisterInfo.h"
21#include "llvm/MC/MCStreamer.h"
22#include "llvm/MC/MCSubtargetInfo.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000023#include "llvm/Support/Casting.h"
24#include "llvm/Support/TargetRegistry.h"
25
26using namespace llvm;
27
28namespace {
29struct RISCVOperand;
30
31class RISCVAsmParser : public MCTargetAsmParser {
32 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
33
Alex Bradbury6758ecb2017-09-17 14:27:35 +000034 bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
35 int Lower, int Upper, Twine Msg);
36
Alex Bradbury04f06d92017-08-08 14:43:36 +000037 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
38 OperandVector &Operands, MCStreamer &Out,
39 uint64_t &ErrorInfo,
40 bool MatchingInlineAsm) override;
41
42 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
43
44 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
45 SMLoc NameLoc, OperandVector &Operands) override;
46
47 bool ParseDirective(AsmToken DirectiveID) override;
48
49// Auto-generated instruction matching functions
50#define GET_ASSEMBLER_HEADER
51#include "RISCVGenAsmMatcher.inc"
52
53 OperandMatchResultTy parseImmediate(OperandVector &Operands);
54 OperandMatchResultTy parseRegister(OperandVector &Operands);
Alex Bradbury6758ecb2017-09-17 14:27:35 +000055 OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
Alex Bradbury04f06d92017-08-08 14:43:36 +000056
57 bool parseOperand(OperandVector &Operands);
58
59public:
60 enum RISCVMatchResultTy {
61 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
62#define GET_OPERAND_DIAGNOSTIC_TYPES
63#include "RISCVGenAsmMatcher.inc"
64#undef GET_OPERAND_DIAGNOSTIC_TYPES
65 };
66
67 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
68 const MCInstrInfo &MII, const MCTargetOptions &Options)
69 : MCTargetAsmParser(Options, STI) {
70 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
71 }
72};
73
74/// RISCVOperand - Instances of this class represent a parsed machine
75/// instruction
76struct RISCVOperand : public MCParsedAsmOperand {
77
78 enum KindTy {
79 Token,
80 Register,
81 Immediate,
82 } Kind;
83
84 struct RegOp {
85 unsigned RegNum;
86 };
87
88 struct ImmOp {
89 const MCExpr *Val;
90 };
91
92 SMLoc StartLoc, EndLoc;
93 union {
94 StringRef Tok;
95 RegOp Reg;
96 ImmOp Imm;
97 };
98
99 RISCVOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
100
101public:
102 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
103 Kind = o.Kind;
104 StartLoc = o.StartLoc;
105 EndLoc = o.EndLoc;
106 switch (Kind) {
107 case Register:
108 Reg = o.Reg;
109 break;
110 case Immediate:
111 Imm = o.Imm;
112 break;
113 case Token:
114 Tok = o.Tok;
115 break;
116 }
117 }
118
119 bool isToken() const override { return Kind == Token; }
120 bool isReg() const override { return Kind == Register; }
121 bool isImm() const override { return Kind == Immediate; }
122 bool isMem() const override { return false; }
123
124 bool isConstantImm() const {
125 return isImm() && dyn_cast<MCConstantExpr>(getImm());
126 }
127
128 int64_t getConstantImm() const {
129 const MCExpr *Val = getImm();
130 return static_cast<const MCConstantExpr *>(Val)->getValue();
131 }
132
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000133 // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
134
135 /// Return true if the operand is a valid for the fence instruction e.g.
136 /// ('iorw').
137 bool isFenceArg() const {
138 if (!isImm())
139 return false;
140 const MCExpr *Val = getImm();
141 auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
142 if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
143 return false;
144
145 StringRef Str = SVal->getSymbol().getName();
146 // Letters must be unique, taken from 'iorw', and in ascending order. This
147 // holds as long as each individual character is one of 'iorw' and is
148 // greater than the previous character.
149 char Prev = '\0';
150 for (char c : Str) {
151 if (c != 'i' && c != 'o' && c != 'r' && c != 'w')
152 return false;
153 if (c <= Prev)
154 return false;
155 Prev = c;
156 }
157 return true;
158 }
159
160 bool isUImm5() const {
161 return (isConstantImm() && isUInt<5>(getConstantImm()));
162 }
163
Alex Bradbury04f06d92017-08-08 14:43:36 +0000164 bool isSImm12() const {
165 return (isConstantImm() && isInt<12>(getConstantImm()));
166 }
167
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000168 bool isUImm12() const {
169 return (isConstantImm() && isUInt<12>(getConstantImm()));
170 }
171
172 bool isSImm13Lsb0() const {
173 return (isConstantImm() && isShiftedInt<12, 1>(getConstantImm()));
174 }
175
176 bool isUImm20() const {
177 return (isConstantImm() && isUInt<20>(getConstantImm()));
178 }
179
180 bool isSImm21Lsb0() const {
181 return (isConstantImm() && isShiftedInt<20, 1>(getConstantImm()));
182 }
183
Alex Bradbury04f06d92017-08-08 14:43:36 +0000184 /// getStartLoc - Gets location of the first token of this operand
185 SMLoc getStartLoc() const override { return StartLoc; }
186 /// getEndLoc - Gets location of the last token of this operand
187 SMLoc getEndLoc() const override { return EndLoc; }
188
189 unsigned getReg() const override {
190 assert(Kind == Register && "Invalid type access!");
191 return Reg.RegNum;
192 }
193
194 const MCExpr *getImm() const {
195 assert(Kind == Immediate && "Invalid type access!");
196 return Imm.Val;
197 }
198
199 StringRef getToken() const {
200 assert(Kind == Token && "Invalid type access!");
201 return Tok;
202 }
203
204 void print(raw_ostream &OS) const override {
205 switch (Kind) {
206 case Immediate:
207 OS << *getImm();
208 break;
209 case Register:
210 OS << "<register x";
211 OS << getReg() << ">";
212 break;
213 case Token:
214 OS << "'" << getToken() << "'";
215 break;
216 }
217 }
218
219 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {
220 auto Op = make_unique<RISCVOperand>(Token);
221 Op->Tok = Str;
222 Op->StartLoc = S;
223 Op->EndLoc = S;
224 return Op;
225 }
226
227 static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S,
228 SMLoc E) {
229 auto Op = make_unique<RISCVOperand>(Register);
230 Op->Reg.RegNum = RegNo;
231 Op->StartLoc = S;
232 Op->EndLoc = E;
233 return Op;
234 }
235
236 static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
237 SMLoc E) {
238 auto Op = make_unique<RISCVOperand>(Immediate);
239 Op->Imm.Val = Val;
240 Op->StartLoc = S;
241 Op->EndLoc = E;
242 return Op;
243 }
244
245 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
246 assert(Expr && "Expr shouldn't be null!");
247 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
248 Inst.addOperand(MCOperand::createImm(CE->getValue()));
249 else
250 Inst.addOperand(MCOperand::createExpr(Expr));
251 }
252
253 // Used by the TableGen Code
254 void addRegOperands(MCInst &Inst, unsigned N) const {
255 assert(N == 1 && "Invalid number of operands!");
256 Inst.addOperand(MCOperand::createReg(getReg()));
257 }
258
259 void addImmOperands(MCInst &Inst, unsigned N) const {
260 assert(N == 1 && "Invalid number of operands!");
261 addExpr(Inst, getImm());
262 }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000263
264 void addFenceArgOperands(MCInst &Inst, unsigned N) const {
265 assert(N == 1 && "Invalid number of operands!");
266 // isFenceArg has validated the operand, meaning this cast is safe
267 auto SE = cast<MCSymbolRefExpr>(getImm());
268
269 unsigned Imm = 0;
270 for (char c : SE->getSymbol().getName()) {
271 switch (c) {
272 default: llvm_unreachable("FenceArg must contain only [iorw]");
273 case 'i': Imm |= RISCVFenceField::I; break;
274 case 'o': Imm |= RISCVFenceField::O; break;
275 case 'r': Imm |= RISCVFenceField::R; break;
276 case 'w': Imm |= RISCVFenceField::W; break;
277 }
278 }
279 Inst.addOperand(MCOperand::createImm(Imm));
280 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000281};
282} // end anonymous namespace.
283
284#define GET_REGISTER_MATCHER
285#define GET_MATCHER_IMPLEMENTATION
Alex Bradbury04f06d92017-08-08 14:43:36 +0000286#include "RISCVGenAsmMatcher.inc"
287
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000288bool RISCVAsmParser::generateImmOutOfRangeError(
289 OperandVector &Operands, uint64_t ErrorInfo, int Lower, int Upper,
290 Twine Msg = "immediate must be an integer in the range") {
291 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
292 return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
293}
294
Alex Bradbury04f06d92017-08-08 14:43:36 +0000295bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
296 OperandVector &Operands,
297 MCStreamer &Out,
298 uint64_t &ErrorInfo,
299 bool MatchingInlineAsm) {
300 MCInst Inst;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000301
302 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
303 default:
304 break;
305 case Match_Success:
306 Inst.setLoc(IDLoc);
307 Out.EmitInstruction(Inst, getSTI());
308 return false;
309 case Match_MissingFeature:
310 return Error(IDLoc, "instruction use requires an option to be enabled");
311 case Match_MnemonicFail:
312 return Error(IDLoc, "unrecognized instruction mnemonic");
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000313 case Match_InvalidOperand: {
314 SMLoc ErrorLoc = IDLoc;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000315 if (ErrorInfo != ~0U) {
316 if (ErrorInfo >= Operands.size())
317 return Error(ErrorLoc, "too few operands for instruction");
318
319 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
320 if (ErrorLoc == SMLoc())
321 ErrorLoc = IDLoc;
322 }
323 return Error(ErrorLoc, "invalid operand for instruction");
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000324 }
325 case Match_InvalidUImm5:
326 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
Alex Bradbury04f06d92017-08-08 14:43:36 +0000327 case Match_InvalidSImm12:
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000328 return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 11),
329 (1 << 11) - 1);
330 case Match_InvalidUImm12:
331 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
332 case Match_InvalidSImm13Lsb0:
333 return generateImmOutOfRangeError(
334 Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
335 "immediate must be a multiple of 2 bytes in the range");
336 case Match_InvalidUImm20:
337 return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1);
338 case Match_InvalidSImm21Lsb0:
339 return generateImmOutOfRangeError(
340 Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
341 "immediate must be a multiple of 2 bytes in the range");
342 case Match_InvalidFenceArg: {
Alex Bradbury04f06d92017-08-08 14:43:36 +0000343 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000344 return Error(
345 ErrorLoc,
346 "operand must be formed of letters selected in-order from 'iorw'");
347 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000348 }
349
350 llvm_unreachable("Unknown match type detected!");
351}
352
353bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
354 SMLoc &EndLoc) {
355 const AsmToken &Tok = getParser().getTok();
356 StartLoc = Tok.getLoc();
357 EndLoc = Tok.getEndLoc();
358 RegNo = 0;
359 StringRef Name = getLexer().getTok().getIdentifier();
360
361 if (!MatchRegisterName(Name) || !MatchRegisterAltName(Name)) {
362 getParser().Lex(); // Eat identifier token.
363 return false;
364 }
365
366 return Error(StartLoc, "invalid register name");
367}
368
369OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands) {
370 SMLoc S = getLoc();
371 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
372
373 switch (getLexer().getKind()) {
374 default:
375 return MatchOperand_NoMatch;
376 case AsmToken::Identifier:
377 StringRef Name = getLexer().getTok().getIdentifier();
378 unsigned RegNo = MatchRegisterName(Name);
379 if (RegNo == 0) {
380 RegNo = MatchRegisterAltName(Name);
381 if (RegNo == 0)
382 return MatchOperand_NoMatch;
383 }
384 getLexer().Lex();
385 Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
386 }
387 return MatchOperand_Success;
388}
389
390OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000391 SMLoc S = getLoc();
392 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
393 const MCExpr *Res;
394
Alex Bradbury04f06d92017-08-08 14:43:36 +0000395 switch (getLexer().getKind()) {
396 default:
397 return MatchOperand_NoMatch;
398 case AsmToken::LParen:
399 case AsmToken::Minus:
400 case AsmToken::Plus:
401 case AsmToken::Integer:
402 case AsmToken::String:
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000403 if (getParser().parseExpression(Res))
404 return MatchOperand_ParseFail;
405 break;
406 case AsmToken::Identifier: {
407 StringRef Identifier;
408 if (getParser().parseIdentifier(Identifier))
409 return MatchOperand_ParseFail;
410 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
411 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Alex Bradbury04f06d92017-08-08 14:43:36 +0000412 break;
413 }
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000414 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000415
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000416 Operands.push_back(RISCVOperand::createImm(Res, S, E));
417 return MatchOperand_Success;
418}
419
420OperandMatchResultTy
421RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
422 if (getLexer().isNot(AsmToken::LParen)) {
423 Error(getLoc(), "expected '('");
Alex Bradbury04f06d92017-08-08 14:43:36 +0000424 return MatchOperand_ParseFail;
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000425 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000426
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000427 getParser().Lex(); // Eat '('
428 Operands.push_back(RISCVOperand::createToken("(", getLoc()));
429
430 if (parseRegister(Operands) != MatchOperand_Success) {
431 Error(getLoc(), "expected register");
432 return MatchOperand_ParseFail;
433 }
434
435 if (getLexer().isNot(AsmToken::RParen)) {
436 Error(getLoc(), "expected ')'");
437 return MatchOperand_ParseFail;
438 }
439
440 getParser().Lex(); // Eat ')'
441 Operands.push_back(RISCVOperand::createToken(")", getLoc()));
442
Alex Bradbury04f06d92017-08-08 14:43:36 +0000443 return MatchOperand_Success;
444}
445
446/// Looks at a token type and creates the relevant operand
447/// from this information, adding to Operands.
448/// If operand was parsed, returns false, else true.
449bool RISCVAsmParser::parseOperand(OperandVector &Operands) {
450 // Attempt to parse token as register
451 if (parseRegister(Operands) == MatchOperand_Success)
452 return false;
453
454 // Attempt to parse token as an immediate
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000455 if (parseImmediate(Operands) == MatchOperand_Success) {
456 // Parse memory base register if present
457 if (getLexer().is(AsmToken::LParen))
458 return parseMemOpBaseReg(Operands) != MatchOperand_Success;
Alex Bradbury04f06d92017-08-08 14:43:36 +0000459 return false;
Alex Bradbury6758ecb2017-09-17 14:27:35 +0000460 }
Alex Bradbury04f06d92017-08-08 14:43:36 +0000461
462 // Finally we have exhausted all options and must declare defeat.
463 Error(getLoc(), "unknown operand");
464 return true;
465}
466
467bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
468 StringRef Name, SMLoc NameLoc,
469 OperandVector &Operands) {
470 // First operand is token for instruction
471 Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
472
473 // If there are no more operands, then finish
474 if (getLexer().is(AsmToken::EndOfStatement))
475 return false;
476
477 // Parse first operand
478 if (parseOperand(Operands))
479 return true;
480
481 // Parse until end of statement, consuming commas between operands
482 while (getLexer().is(AsmToken::Comma)) {
483 // Consume comma token
484 getLexer().Lex();
485
486 // Parse next operand
487 if (parseOperand(Operands))
488 return true;
489 }
490
491 if (getLexer().isNot(AsmToken::EndOfStatement)) {
492 SMLoc Loc = getLexer().getLoc();
493 getParser().eatToEndOfStatement();
494 return Error(Loc, "unexpected token");
495 }
496
497 getParser().Lex(); // Consume the EndOfStatement.
498 return false;
499}
500
501bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
502
503extern "C" void LLVMInitializeRISCVAsmParser() {
504 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
505 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
506}