1 //===-- 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/RISCVBaseInfo.h"
11 #include "MCTargetDesc/RISCVMCTargetDesc.h"
12 #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"
17 #include "llvm/MC/MCParser/MCAsmLexer.h"
18 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
19 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
20 #include "llvm/MC/MCRegisterInfo.h"
21 #include "llvm/MC/MCStreamer.h"
22 #include "llvm/MC/MCSubtargetInfo.h"
23 #include "llvm/Support/Casting.h"
24 #include "llvm/Support/TargetRegistry.h"
25 
26 using namespace llvm;
27 
28 namespace {
29 struct RISCVOperand;
30 
31 class RISCVAsmParser : public MCTargetAsmParser {
32   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
33 
34   bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
35                                   int Lower, int Upper, Twine Msg);
36 
37   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);
55   OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
56 
57   bool parseOperand(OperandVector &Operands);
58 
59 public:
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
76 struct 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 
101 public:
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 
133   // 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 
164   bool isSImm12() const {
165     return (isConstantImm() && isInt<12>(getConstantImm()));
166   }
167 
168   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 
184   /// 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   }
263 
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   }
281 };
282 } // end anonymous namespace.
283 
284 #define GET_REGISTER_MATCHER
285 #define GET_MATCHER_IMPLEMENTATION
286 #include "RISCVGenAsmMatcher.inc"
287 
288 bool 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 
295 bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
296                                              OperandVector &Operands,
297                                              MCStreamer &Out,
298                                              uint64_t &ErrorInfo,
299                                              bool MatchingInlineAsm) {
300   MCInst Inst;
301 
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");
313   case Match_InvalidOperand: {
314     SMLoc ErrorLoc = IDLoc;
315     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");
324   }
325   case Match_InvalidUImm5:
326     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
327   case Match_InvalidSImm12:
328     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: {
343     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
344     return Error(
345         ErrorLoc,
346         "operand must be formed of letters selected in-order from 'iorw'");
347   }
348   }
349 
350   llvm_unreachable("Unknown match type detected!");
351 }
352 
353 bool 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 
369 OperandMatchResultTy 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 
390 OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
391   SMLoc S = getLoc();
392   SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
393   const MCExpr *Res;
394 
395   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:
403     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());
412     break;
413   }
414   }
415 
416   Operands.push_back(RISCVOperand::createImm(Res, S, E));
417   return MatchOperand_Success;
418 }
419 
420 OperandMatchResultTy
421 RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
422   if (getLexer().isNot(AsmToken::LParen)) {
423     Error(getLoc(), "expected '('");
424     return MatchOperand_ParseFail;
425   }
426 
427   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 
443   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.
449 bool 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
455   if (parseImmediate(Operands) == MatchOperand_Success) {
456     // Parse memory base register if present
457     if (getLexer().is(AsmToken::LParen))
458       return parseMemOpBaseReg(Operands) != MatchOperand_Success;
459     return false;
460   }
461 
462   // Finally we have exhausted all options and must declare defeat.
463   Error(getLoc(), "unknown operand");
464   return true;
465 }
466 
467 bool 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 
501 bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) { return true; }
502 
503 extern "C" void LLVMInitializeRISCVAsmParser() {
504   RegisterMCAsmParser<RISCVAsmParser> X(getTheRISCV32Target());
505   RegisterMCAsmParser<RISCVAsmParser> Y(getTheRISCV64Target());
506 }
507