blob: cb820379bbbbaacdab0ac313cfe84fb2beab6d53 [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
10#include "MCTargetDesc/RISCVMCTargetDesc.h"
Alex Bradbury4f7f0da2017-09-06 09:21:21 +000011#include "llvm/ADT/STLExtras.h"
12#include "llvm/ADT/StringSwitch.h"
13#include "llvm/MC/MCContext.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCInst.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000016#include "llvm/MC/MCParser/MCAsmLexer.h"
17#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
18#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000019#include "llvm/MC/MCRegisterInfo.h"
20#include "llvm/MC/MCStreamer.h"
21#include "llvm/MC/MCSubtargetInfo.h"
Alex Bradbury04f06d92017-08-08 14:43:36 +000022#include "llvm/Support/Casting.h"
23#include "llvm/Support/TargetRegistry.h"
24
25using namespace llvm;
26
27namespace {
28struct RISCVOperand;
29
30class RISCVAsmParser : public MCTargetAsmParser {
31 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
32
33 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
34 OperandVector &Operands, MCStreamer &Out,
35 uint64_t &ErrorInfo,
36 bool MatchingInlineAsm) override;
37
38 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
39
40 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
41 SMLoc NameLoc, OperandVector &Operands) override;
42
43 bool ParseDirective(AsmToken DirectiveID) override;
44
45// Auto-generated instruction matching functions
46#define GET_ASSEMBLER_HEADER
47#include "RISCVGenAsmMatcher.inc"
48
49 OperandMatchResultTy parseImmediate(OperandVector &Operands);
50 OperandMatchResultTy parseRegister(OperandVector &Operands);
51
52 bool parseOperand(OperandVector &Operands);
53
54public:
55 enum RISCVMatchResultTy {
56 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
57#define GET_OPERAND_DIAGNOSTIC_TYPES
58#include "RISCVGenAsmMatcher.inc"
59#undef GET_OPERAND_DIAGNOSTIC_TYPES
60 };
61
62 RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
63 const MCInstrInfo &MII, const MCTargetOptions &Options)
64 : MCTargetAsmParser(Options, STI) {
65 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
66 }
67};
68
69/// RISCVOperand - Instances of this class represent a parsed machine
70/// instruction
71struct RISCVOperand : public MCParsedAsmOperand {
72
73 enum KindTy {
74 Token,
75 Register,
76 Immediate,
77 } Kind;
78
79 struct RegOp {
80 unsigned RegNum;
81 };
82
83 struct ImmOp {
84 const MCExpr *Val;
85 };
86
87 SMLoc StartLoc, EndLoc;
88 union {
89 StringRef Tok;
90 RegOp Reg;
91 ImmOp Imm;
92 };
93
94 RISCVOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
95
96public:
97 RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
98 Kind = o.Kind;
99 StartLoc = o.StartLoc;
100 EndLoc = o.EndLoc;
101 switch (Kind) {
102 case Register:
103 Reg = o.Reg;
104 break;
105 case Immediate:
106 Imm = o.Imm;
107 break;
108 case Token:
109 Tok = o.Tok;
110 break;
111 }
112 }
113
114 bool isToken() const override { return Kind == Token; }
115 bool isReg() const override { return Kind == Register; }
116 bool isImm() const override { return Kind == Immediate; }
117 bool isMem() const override { return false; }
118
119 bool isConstantImm() const {
120 return isImm() && dyn_cast<MCConstantExpr>(getImm());
121 }
122
123 int64_t getConstantImm() const {
124 const MCExpr *Val = getImm();
125 return static_cast<const MCConstantExpr *>(Val)->getValue();
126 }
127
128 bool isSImm12() const {
129 return (isConstantImm() && isInt<12>(getConstantImm()));
130 }
131
132 /// getStartLoc - Gets location of the first token of this operand
133 SMLoc getStartLoc() const override { return StartLoc; }
134 /// getEndLoc - Gets location of the last token of this operand
135 SMLoc getEndLoc() const override { return EndLoc; }
136
137 unsigned getReg() const override {
138 assert(Kind == Register && "Invalid type access!");
139 return Reg.RegNum;
140 }
141
142 const MCExpr *getImm() const {
143 assert(Kind == Immediate && "Invalid type access!");
144 return Imm.Val;
145 }
146
147 StringRef getToken() const {
148 assert(Kind == Token && "Invalid type access!");
149 return Tok;
150 }
151
152 void print(raw_ostream &OS) const override {
153 switch (Kind) {
154 case Immediate:
155 OS << *getImm();
156 break;
157 case Register:
158 OS << "<register x";
159 OS << getReg() << ">";
160 break;
161 case Token:
162 OS << "'" << getToken() << "'";
163 break;
164 }
165 }
166
167 static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S) {
168 auto Op = make_unique<RISCVOperand>(Token);
169 Op->Tok = Str;
170 Op->StartLoc = S;
171 Op->EndLoc = S;
172 return Op;
173 }
174
175 static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S,
176 SMLoc E) {
177 auto Op = make_unique<RISCVOperand>(Register);
178 Op->Reg.RegNum = RegNo;
179 Op->StartLoc = S;
180 Op->EndLoc = E;
181 return Op;
182 }
183
184 static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
185 SMLoc E) {
186 auto Op = make_unique<RISCVOperand>(Immediate);
187 Op->Imm.Val = Val;
188 Op->StartLoc = S;
189 Op->EndLoc = E;
190 return Op;
191 }
192
193 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
194 assert(Expr && "Expr shouldn't be null!");
195 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
196 Inst.addOperand(MCOperand::createImm(CE->getValue()));
197 else
198 Inst.addOperand(MCOperand::createExpr(Expr));
199 }
200
201 // Used by the TableGen Code
202 void addRegOperands(MCInst &Inst, unsigned N) const {
203 assert(N == 1 && "Invalid number of operands!");
204 Inst.addOperand(MCOperand::createReg(getReg()));
205 }
206
207 void addImmOperands(MCInst &Inst, unsigned N) const {
208 assert(N == 1 && "Invalid number of operands!");
209 addExpr(Inst, getImm());
210 }
211};
212} // end anonymous namespace.
213
214#define GET_REGISTER_MATCHER
215#define GET_MATCHER_IMPLEMENTATION
Alex Bradbury04f06d92017-08-08 14:43:36 +0000216#include "RISCVGenAsmMatcher.inc"
217
218bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
219 OperandVector &Operands,
220 MCStreamer &Out,
221 uint64_t &ErrorInfo,
222 bool MatchingInlineAsm) {
223 MCInst Inst;
224 SMLoc ErrorLoc;
225
226 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
227 default:
228 break;
229 case Match_Success:
230 Inst.setLoc(IDLoc);
231 Out.EmitInstruction(Inst, getSTI());
232 return false;
233 case Match_MissingFeature:
234 return Error(IDLoc, "instruction use requires an option to be enabled");
235 case Match_MnemonicFail:
236 return Error(IDLoc, "unrecognized instruction mnemonic");
237 case Match_InvalidOperand:
238 ErrorLoc = IDLoc;
239 if (ErrorInfo != ~0U) {
240 if (ErrorInfo >= Operands.size())
241 return Error(ErrorLoc, "too few operands for instruction");
242
243 ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
244 if (ErrorLoc == SMLoc())
245 ErrorLoc = IDLoc;
246 }
247 return Error(ErrorLoc, "invalid operand for instruction");
248 case Match_InvalidSImm12:
249 SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
250 return Error(ErrorLoc,
251 "immediate must be an integer in the range [-2048, 2047]");
252 }
253
254 llvm_unreachable("Unknown match type detected!");
255}
256
257bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
258 SMLoc &EndLoc) {
259 const AsmToken &Tok = getParser().getTok();
260 StartLoc = Tok.getLoc();
261 EndLoc = Tok.getEndLoc();
262 RegNo = 0;
263 StringRef Name = getLexer().getTok().getIdentifier();
264
265 if (!MatchRegisterName(Name) || !MatchRegisterAltName(Name)) {
266 getParser().Lex(); // Eat identifier token.
267 return false;
268 }
269
270 return Error(StartLoc, "invalid register name");
271}
272
273OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands) {
274 SMLoc S = getLoc();
275 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
276
277 switch (getLexer().getKind()) {
278 default:
279 return MatchOperand_NoMatch;
280 case AsmToken::Identifier:
281 StringRef Name = getLexer().getTok().getIdentifier();
282 unsigned RegNo = MatchRegisterName(Name);
283 if (RegNo == 0) {
284 RegNo = MatchRegisterAltName(Name);
285 if (RegNo == 0)
286 return MatchOperand_NoMatch;
287 }
288 getLexer().Lex();
289 Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
290 }
291 return MatchOperand_Success;
292}
293
294OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
295 switch (getLexer().getKind()) {
296 default:
297 return MatchOperand_NoMatch;
298 case AsmToken::LParen:
299 case AsmToken::Minus:
300 case AsmToken::Plus:
301 case AsmToken::Integer:
302 case AsmToken::String:
303 break;
304 }
305
306 const MCExpr *IdVal;
307 SMLoc S = getLoc();
308 if (getParser().parseExpression(IdVal))
309 return MatchOperand_ParseFail;
310
311 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
312 Operands.push_back(RISCVOperand::createImm(IdVal, S, E));
313 return MatchOperand_Success;
314}
315
316/// Looks at a token type and creates the relevant operand
317/// from this information, adding to Operands.
318/// If operand was parsed, returns false, else true.
319bool RISCVAsmParser::parseOperand(OperandVector &Operands) {
320 // Attempt to parse token as register
321 if (parseRegister(Operands) == MatchOperand_Success)
322 return false;
323
324 // Attempt to parse token as an immediate
325 if (parseImmediate(Operands) == MatchOperand_Success)
326 return false;
327
328 // Finally we have exhausted all options and must declare defeat.
329 Error(getLoc(), "unknown operand");
330 return true;
331}
332
333bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
334 StringRef Name, SMLoc NameLoc,
335 OperandVector &Operands) {
336 // First operand is token for instruction
337 Operands.push_back(RISCVOperand::createToken(Name, NameLoc));
338
339 // If there are no more operands, then finish
340 if (getLexer().is(AsmToken::EndOfStatement))
341 return false;
342
343 // Parse first operand
344 if (parseOperand(Operands))
345 return true;
346
347 // Parse until end of statement, consuming commas between operands
348 while (getLexer().is(AsmToken::Comma)) {
349 // Consume comma token
350 getLexer().Lex();
351
352 // Parse next operand
353 if (parseOperand(Operands))
354 return true;
355 }
356
357 if (getLexer().isNot(AsmToken::EndOfStatement)) {
358 SMLoc Loc = getLexer().getLoc();
359 getParser().eatToEndOfStatement();
360 return Error(Loc, "unexpected token");
361 }
362
363 getParser().Lex(); // Consume the EndOfStatement.
364 return false;
365}
366
367bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
368
369extern "C" void LLVMInitializeRISCVAsmParser() {
370 RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
371 RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
372}