LLVM  8.0.1
RISCVAsmParser.cpp
Go to the documentation of this file.
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 
14 #include "Utils/RISCVBaseInfo.h"
15 #include "Utils/RISCVMatInt.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringSwitch.h"
19 #include "llvm/MC/MCAssembler.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCExpr.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/MC/MCInstBuilder.h"
27 #include "llvm/MC/MCRegisterInfo.h"
28 #include "llvm/MC/MCStreamer.h"
30 #include "llvm/Support/Casting.h"
33 
34 #include <limits>
35 
36 using namespace llvm;
37 
38 // Include the auto-generated portion of the compress emitter.
39 #define GEN_COMPRESS_INSTR
40 #include "RISCVGenCompressInstEmitter.inc"
41 
42 namespace {
43 struct RISCVOperand;
44 
45 class RISCVAsmParser : public MCTargetAsmParser {
46  SmallVector<FeatureBitset, 4> FeatureBitStack;
47 
48  SMLoc getLoc() const { return getParser().getTok().getLoc(); }
49  bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
50 
51  RISCVTargetStreamer &getTargetStreamer() {
52  MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
53  return static_cast<RISCVTargetStreamer &>(TS);
54  }
55 
56  unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
57  unsigned Kind) override;
58 
59  bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
60  int64_t Lower, int64_t Upper, Twine Msg);
61 
62  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
63  OperandVector &Operands, MCStreamer &Out,
64  uint64_t &ErrorInfo,
65  bool MatchingInlineAsm) override;
66 
67  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
68 
69  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
70  SMLoc NameLoc, OperandVector &Operands) override;
71 
72  bool ParseDirective(AsmToken DirectiveID) override;
73 
74  // Helper to actually emit an instruction to the MCStreamer. Also, when
75  // possible, compression of the instruction is performed.
76  void emitToStreamer(MCStreamer &S, const MCInst &Inst);
77 
78  // Helper to emit a combination of LUI, ADDI(W), and SLLI instructions that
79  // synthesize the desired immedate value into the destination register.
80  void emitLoadImm(unsigned DestReg, int64_t Value, MCStreamer &Out);
81 
82  // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
83  void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
84 
85  /// Helper for processing MC instructions that have been successfully matched
86  /// by MatchAndEmitInstruction. Modifications to the emitted instructions,
87  /// like the expansion of pseudo instructions (e.g., "li"), can be performed
88  /// in this method.
89  bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
90 
91 // Auto-generated instruction matching functions
92 #define GET_ASSEMBLER_HEADER
93 #include "RISCVGenAsmMatcher.inc"
94 
95  OperandMatchResultTy parseCSRSystemRegister(OperandVector &Operands);
97  OperandMatchResultTy parseRegister(OperandVector &Operands,
98  bool AllowParens = false);
99  OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
100  OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
101  OperandMatchResultTy parseBareSymbol(OperandVector &Operands);
102  OperandMatchResultTy parseJALOffset(OperandVector &Operands);
103 
104  bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
105 
106  bool parseDirectiveOption();
107 
108  void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
109  if (!(getSTI().getFeatureBits()[Feature])) {
110  MCSubtargetInfo &STI = copySTI();
111  setAvailableFeatures(
112  ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
113  }
114  }
115 
116  void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
117  if (getSTI().getFeatureBits()[Feature]) {
118  MCSubtargetInfo &STI = copySTI();
119  setAvailableFeatures(
120  ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
121  }
122  }
123 
124  void pushFeatureBits() {
125  FeatureBitStack.push_back(getSTI().getFeatureBits());
126  }
127 
128  bool popFeatureBits() {
129  if (FeatureBitStack.empty())
130  return true;
131 
132  FeatureBitset FeatureBits = FeatureBitStack.pop_back_val();
133  copySTI().setFeatureBits(FeatureBits);
134  setAvailableFeatures(ComputeAvailableFeatures(FeatureBits));
135 
136  return false;
137  }
138 public:
139  enum RISCVMatchResultTy {
140  Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
141 #define GET_OPERAND_DIAGNOSTIC_TYPES
142 #include "RISCVGenAsmMatcher.inc"
143 #undef GET_OPERAND_DIAGNOSTIC_TYPES
144  };
145 
146  static bool classifySymbolRef(const MCExpr *Expr,
148  int64_t &Addend);
149 
150  RISCVAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
151  const MCInstrInfo &MII, const MCTargetOptions &Options)
152  : MCTargetAsmParser(Options, STI, MII) {
153  Parser.addAliasForDirective(".half", ".2byte");
154  Parser.addAliasForDirective(".hword", ".2byte");
155  Parser.addAliasForDirective(".word", ".4byte");
156  Parser.addAliasForDirective(".dword", ".8byte");
157  setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
158  }
159 };
160 
161 /// RISCVOperand - Instances of this class represent a parsed machine
162 /// instruction
163 struct RISCVOperand : public MCParsedAsmOperand {
164 
165  enum KindTy {
166  Token,
167  Register,
168  Immediate,
169  SystemRegister
170  } Kind;
171 
172  bool IsRV64;
173 
174  struct RegOp {
175  unsigned RegNum;
176  };
177 
178  struct ImmOp {
179  const MCExpr *Val;
180  };
181 
182  struct SysRegOp {
183  const char *Data;
184  unsigned Length;
185  unsigned Encoding;
186  // FIXME: Add the Encoding parsed fields as needed for checks,
187  // e.g.: read/write or user/supervisor/machine privileges.
188  };
189 
190  SMLoc StartLoc, EndLoc;
191  union {
192  StringRef Tok;
193  RegOp Reg;
194  ImmOp Imm;
195  struct SysRegOp SysReg;
196  };
197 
198  RISCVOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
199 
200 public:
201  RISCVOperand(const RISCVOperand &o) : MCParsedAsmOperand() {
202  Kind = o.Kind;
203  IsRV64 = o.IsRV64;
204  StartLoc = o.StartLoc;
205  EndLoc = o.EndLoc;
206  switch (Kind) {
207  case Register:
208  Reg = o.Reg;
209  break;
210  case Immediate:
211  Imm = o.Imm;
212  break;
213  case Token:
214  Tok = o.Tok;
215  break;
216  case SystemRegister:
217  SysReg = o.SysReg;
218  break;
219  }
220  }
221 
222  bool isToken() const override { return Kind == Token; }
223  bool isReg() const override { return Kind == Register; }
224  bool isImm() const override { return Kind == Immediate; }
225  bool isMem() const override { return false; }
226  bool isSystemRegister() const { return Kind == SystemRegister; }
227 
228  static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
230  if (auto *RE = dyn_cast<RISCVMCExpr>(Expr)) {
231  VK = RE->getKind();
232  return RE->evaluateAsConstant(Imm);
233  }
234 
235  if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
237  Imm = CE->getValue();
238  return true;
239  }
240 
241  return false;
242  }
243 
244  // True if operand is a symbol with no modifiers, or a constant with no
245  // modifiers and isShiftedInt<N-1, 1>(Op).
246  template <int N> bool isBareSimmNLsb0() const {
247  int64_t Imm;
249  if (!isImm())
250  return false;
251  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
252  bool IsValid;
253  if (!IsConstantImm)
254  IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
255  else
256  IsValid = isShiftedInt<N - 1, 1>(Imm);
257  return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
258  }
259 
260  // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
261 
262  bool isBareSymbol() const {
263  int64_t Imm;
265  // Must be of 'immediate' type but not a constant.
266  if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
267  return false;
268  return RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm) &&
270  }
271 
272  bool isCSRSystemRegister() const { return isSystemRegister(); }
273 
274  /// Return true if the operand is a valid for the fence instruction e.g.
275  /// ('iorw').
276  bool isFenceArg() const {
277  if (!isImm())
278  return false;
279  const MCExpr *Val = getImm();
280  auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
281  if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
282  return false;
283 
284  StringRef Str = SVal->getSymbol().getName();
285  // Letters must be unique, taken from 'iorw', and in ascending order. This
286  // holds as long as each individual character is one of 'iorw' and is
287  // greater than the previous character.
288  char Prev = '\0';
289  for (char c : Str) {
290  if (c != 'i' && c != 'o' && c != 'r' && c != 'w')
291  return false;
292  if (c <= Prev)
293  return false;
294  Prev = c;
295  }
296  return true;
297  }
298 
299  /// Return true if the operand is a valid floating point rounding mode.
300  bool isFRMArg() const {
301  if (!isImm())
302  return false;
303  const MCExpr *Val = getImm();
304  auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
305  if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
306  return false;
307 
308  StringRef Str = SVal->getSymbol().getName();
309 
311  }
312 
313  bool isImmXLenLI() const {
314  int64_t Imm;
316  if (!isImm())
317  return false;
318  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
320  return true;
321  // Given only Imm, ensuring that the actually specified constant is either
322  // a signed or unsigned 64-bit number is unfortunately impossible.
323  bool IsInRange = isRV64() ? true : isInt<32>(Imm) || isUInt<32>(Imm);
324  return IsConstantImm && IsInRange && VK == RISCVMCExpr::VK_RISCV_None;
325  }
326 
327  bool isUImmLog2XLen() const {
328  int64_t Imm;
330  if (!isImm())
331  return false;
332  if (!evaluateConstantImm(getImm(), Imm, VK) ||
334  return false;
335  return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm);
336  }
337 
338  bool isUImmLog2XLenNonZero() const {
339  int64_t Imm;
341  if (!isImm())
342  return false;
343  if (!evaluateConstantImm(getImm(), Imm, VK) ||
345  return false;
346  if (Imm == 0)
347  return false;
348  return (isRV64() && isUInt<6>(Imm)) || isUInt<5>(Imm);
349  }
350 
351  bool isUImm5() const {
352  int64_t Imm;
354  if (!isImm())
355  return false;
356  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
357  return IsConstantImm && isUInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
358  }
359 
360  bool isUImm5NonZero() const {
361  int64_t Imm;
363  if (!isImm())
364  return false;
365  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
366  return IsConstantImm && isUInt<5>(Imm) && (Imm != 0) &&
368  }
369 
370  bool isSImm6() const {
371  if (!isImm())
372  return false;
374  int64_t Imm;
375  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
376  return IsConstantImm && isInt<6>(Imm) &&
378  }
379 
380  bool isSImm6NonZero() const {
381  if (!isImm())
382  return false;
384  int64_t Imm;
385  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
386  return IsConstantImm && isInt<6>(Imm) && (Imm != 0) &&
388  }
389 
390  bool isCLUIImm() const {
391  if (!isImm())
392  return false;
393  int64_t Imm;
395  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
396  return IsConstantImm && (Imm != 0) &&
397  (isUInt<5>(Imm) || (Imm >= 0xfffe0 && Imm <= 0xfffff)) &&
399  }
400 
401  bool isUImm7Lsb00() const {
402  if (!isImm())
403  return false;
404  int64_t Imm;
406  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
407  return IsConstantImm && isShiftedUInt<5, 2>(Imm) &&
409  }
410 
411  bool isUImm8Lsb00() const {
412  if (!isImm())
413  return false;
414  int64_t Imm;
416  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
417  return IsConstantImm && isShiftedUInt<6, 2>(Imm) &&
419  }
420 
421  bool isUImm8Lsb000() const {
422  if (!isImm())
423  return false;
424  int64_t Imm;
426  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
427  return IsConstantImm && isShiftedUInt<5, 3>(Imm) &&
429  }
430 
431  bool isSImm9Lsb0() const { return isBareSimmNLsb0<9>(); }
432 
433  bool isUImm9Lsb000() const {
434  if (!isImm())
435  return false;
436  int64_t Imm;
438  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
439  return IsConstantImm && isShiftedUInt<6, 3>(Imm) &&
441  }
442 
443  bool isUImm10Lsb00NonZero() const {
444  if (!isImm())
445  return false;
446  int64_t Imm;
448  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
449  return IsConstantImm && isShiftedUInt<8, 2>(Imm) && (Imm != 0) &&
451  }
452 
453  bool isSImm12() const {
455  int64_t Imm;
456  bool IsValid;
457  if (!isImm())
458  return false;
459  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
460  if (!IsConstantImm)
461  IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
462  else
463  IsValid = isInt<12>(Imm);
464  return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
465  VK == RISCVMCExpr::VK_RISCV_LO ||
467  }
468 
469  bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
470 
471  bool isSImm13Lsb0() const { return isBareSimmNLsb0<13>(); }
472 
473  bool isSImm10Lsb0000NonZero() const {
474  if (!isImm())
475  return false;
476  int64_t Imm;
478  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
479  return IsConstantImm && (Imm != 0) && isShiftedInt<6, 4>(Imm) &&
481  }
482 
483  bool isUImm20LUI() const {
485  int64_t Imm;
486  bool IsValid;
487  if (!isImm())
488  return false;
489  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
490  if (!IsConstantImm) {
491  IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
492  return IsValid && VK == RISCVMCExpr::VK_RISCV_HI;
493  } else {
494  return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
496  }
497  }
498 
499  bool isUImm20AUIPC() const {
501  int64_t Imm;
502  bool IsValid;
503  if (!isImm())
504  return false;
505  bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
506  if (!IsConstantImm) {
507  IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
508  return IsValid && VK == RISCVMCExpr::VK_RISCV_PCREL_HI;
509  } else {
510  return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
512  }
513  }
514 
515  bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
516 
517  /// getStartLoc - Gets location of the first token of this operand
518  SMLoc getStartLoc() const override { return StartLoc; }
519  /// getEndLoc - Gets location of the last token of this operand
520  SMLoc getEndLoc() const override { return EndLoc; }
521  /// True if this operand is for an RV64 instruction
522  bool isRV64() const { return IsRV64; }
523 
524  unsigned getReg() const override {
525  assert(Kind == Register && "Invalid type access!");
526  return Reg.RegNum;
527  }
528 
529  StringRef getSysReg() const {
530  assert(Kind == SystemRegister && "Invalid access!");
531  return StringRef(SysReg.Data, SysReg.Length);
532  }
533 
534  const MCExpr *getImm() const {
535  assert(Kind == Immediate && "Invalid type access!");
536  return Imm.Val;
537  }
538 
539  StringRef getToken() const {
540  assert(Kind == Token && "Invalid type access!");
541  return Tok;
542  }
543 
544  void print(raw_ostream &OS) const override {
545  switch (Kind) {
546  case Immediate:
547  OS << *getImm();
548  break;
549  case Register:
550  OS << "<register x";
551  OS << getReg() << ">";
552  break;
553  case Token:
554  OS << "'" << getToken() << "'";
555  break;
556  case SystemRegister:
557  OS << "<sysreg: " << getSysReg() << '>';
558  break;
559  }
560  }
561 
562  static std::unique_ptr<RISCVOperand> createToken(StringRef Str, SMLoc S,
563  bool IsRV64) {
564  auto Op = make_unique<RISCVOperand>(Token);
565  Op->Tok = Str;
566  Op->StartLoc = S;
567  Op->EndLoc = S;
568  Op->IsRV64 = IsRV64;
569  return Op;
570  }
571 
572  static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S,
573  SMLoc E, bool IsRV64) {
574  auto Op = make_unique<RISCVOperand>(Register);
575  Op->Reg.RegNum = RegNo;
576  Op->StartLoc = S;
577  Op->EndLoc = E;
578  Op->IsRV64 = IsRV64;
579  return Op;
580  }
581 
582  static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
583  SMLoc E, bool IsRV64) {
584  auto Op = make_unique<RISCVOperand>(Immediate);
585  Op->Imm.Val = Val;
586  Op->StartLoc = S;
587  Op->EndLoc = E;
588  Op->IsRV64 = IsRV64;
589  return Op;
590  }
591 
592  static std::unique_ptr<RISCVOperand>
593  createSysReg(StringRef Str, SMLoc S, unsigned Encoding, bool IsRV64) {
594  auto Op = make_unique<RISCVOperand>(SystemRegister);
595  Op->SysReg.Data = Str.data();
596  Op->SysReg.Length = Str.size();
597  Op->SysReg.Encoding = Encoding;
598  Op->StartLoc = S;
599  Op->IsRV64 = IsRV64;
600  return Op;
601  }
602 
603  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
604  assert(Expr && "Expr shouldn't be null!");
605  int64_t Imm = 0;
607  bool IsConstant = evaluateConstantImm(Expr, Imm, VK);
608 
609  if (IsConstant)
610  Inst.addOperand(MCOperand::createImm(Imm));
611  else
612  Inst.addOperand(MCOperand::createExpr(Expr));
613  }
614 
615  // Used by the TableGen Code
616  void addRegOperands(MCInst &Inst, unsigned N) const {
617  assert(N == 1 && "Invalid number of operands!");
619  }
620 
621  void addImmOperands(MCInst &Inst, unsigned N) const {
622  assert(N == 1 && "Invalid number of operands!");
623  addExpr(Inst, getImm());
624  }
625 
626  void addFenceArgOperands(MCInst &Inst, unsigned N) const {
627  assert(N == 1 && "Invalid number of operands!");
628  // isFenceArg has validated the operand, meaning this cast is safe
629  auto SE = cast<MCSymbolRefExpr>(getImm());
630 
631  unsigned Imm = 0;
632  for (char c : SE->getSymbol().getName()) {
633  switch (c) {
634  default:
635  llvm_unreachable("FenceArg must contain only [iorw]");
636  case 'i': Imm |= RISCVFenceField::I; break;
637  case 'o': Imm |= RISCVFenceField::O; break;
638  case 'r': Imm |= RISCVFenceField::R; break;
639  case 'w': Imm |= RISCVFenceField::W; break;
640  }
641  }
642  Inst.addOperand(MCOperand::createImm(Imm));
643  }
644 
645  void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
646  assert(N == 1 && "Invalid number of operands!");
647  Inst.addOperand(MCOperand::createImm(SysReg.Encoding));
648  }
649 
650  // Returns the rounding mode represented by this RISCVOperand. Should only
651  // be called after checking isFRMArg.
652  RISCVFPRndMode::RoundingMode getRoundingMode() const {
653  // isFRMArg has validated the operand, meaning this cast is safe.
654  auto SE = cast<MCSymbolRefExpr>(getImm());
656  RISCVFPRndMode::stringToRoundingMode(SE->getSymbol().getName());
657  assert(FRM != RISCVFPRndMode::Invalid && "Invalid rounding mode");
658  return FRM;
659  }
660 
661  void addFRMArgOperands(MCInst &Inst, unsigned N) const {
662  assert(N == 1 && "Invalid number of operands!");
663  Inst.addOperand(MCOperand::createImm(getRoundingMode()));
664  }
665 };
666 } // end anonymous namespace.
667 
668 #define GET_REGISTER_MATCHER
669 #define GET_MATCHER_IMPLEMENTATION
670 #include "RISCVGenAsmMatcher.inc"
671 
672 // Return the matching FPR64 register for the given FPR32.
673 // FIXME: Ideally this function could be removed in favour of using
674 // information from TableGen.
675 unsigned convertFPR32ToFPR64(unsigned Reg) {
676  switch (Reg) {
677  default:
678  llvm_unreachable("Not a recognised FPR32 register");
679  case RISCV::F0_32: return RISCV::F0_64;
680  case RISCV::F1_32: return RISCV::F1_64;
681  case RISCV::F2_32: return RISCV::F2_64;
682  case RISCV::F3_32: return RISCV::F3_64;
683  case RISCV::F4_32: return RISCV::F4_64;
684  case RISCV::F5_32: return RISCV::F5_64;
685  case RISCV::F6_32: return RISCV::F6_64;
686  case RISCV::F7_32: return RISCV::F7_64;
687  case RISCV::F8_32: return RISCV::F8_64;
688  case RISCV::F9_32: return RISCV::F9_64;
689  case RISCV::F10_32: return RISCV::F10_64;
690  case RISCV::F11_32: return RISCV::F11_64;
691  case RISCV::F12_32: return RISCV::F12_64;
692  case RISCV::F13_32: return RISCV::F13_64;
693  case RISCV::F14_32: return RISCV::F14_64;
694  case RISCV::F15_32: return RISCV::F15_64;
695  case RISCV::F16_32: return RISCV::F16_64;
696  case RISCV::F17_32: return RISCV::F17_64;
697  case RISCV::F18_32: return RISCV::F18_64;
698  case RISCV::F19_32: return RISCV::F19_64;
699  case RISCV::F20_32: return RISCV::F20_64;
700  case RISCV::F21_32: return RISCV::F21_64;
701  case RISCV::F22_32: return RISCV::F22_64;
702  case RISCV::F23_32: return RISCV::F23_64;
703  case RISCV::F24_32: return RISCV::F24_64;
704  case RISCV::F25_32: return RISCV::F25_64;
705  case RISCV::F26_32: return RISCV::F26_64;
706  case RISCV::F27_32: return RISCV::F27_64;
707  case RISCV::F28_32: return RISCV::F28_64;
708  case RISCV::F29_32: return RISCV::F29_64;
709  case RISCV::F30_32: return RISCV::F30_64;
710  case RISCV::F31_32: return RISCV::F31_64;
711  }
712 }
713 
714 unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
715  unsigned Kind) {
716  RISCVOperand &Op = static_cast<RISCVOperand &>(AsmOp);
717  if (!Op.isReg())
718  return Match_InvalidOperand;
719 
720  unsigned Reg = Op.getReg();
721  bool IsRegFPR32 =
722  RISCVMCRegisterClasses[RISCV::FPR32RegClassID].contains(Reg);
723  bool IsRegFPR32C =
724  RISCVMCRegisterClasses[RISCV::FPR32CRegClassID].contains(Reg);
725 
726  // As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
727  // register from FPR32 to FPR64 or FPR32C to FPR64C if necessary.
728  if ((IsRegFPR32 && Kind == MCK_FPR64) ||
729  (IsRegFPR32C && Kind == MCK_FPR64C)) {
730  Op.Reg.RegNum = convertFPR32ToFPR64(Reg);
731  return Match_Success;
732  }
733  return Match_InvalidOperand;
734 }
735 
736 bool RISCVAsmParser::generateImmOutOfRangeError(
737  OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
738  Twine Msg = "immediate must be an integer in the range") {
739  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
740  return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
741 }
742 
743 bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
744  OperandVector &Operands,
745  MCStreamer &Out,
746  uint64_t &ErrorInfo,
747  bool MatchingInlineAsm) {
748  MCInst Inst;
749 
750  auto Result =
751  MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
752  switch (Result) {
753  default:
754  break;
755  case Match_Success:
756  return processInstruction(Inst, IDLoc, Out);
757  case Match_MissingFeature:
758  return Error(IDLoc, "instruction use requires an option to be enabled");
759  case Match_MnemonicFail:
760  return Error(IDLoc, "unrecognized instruction mnemonic");
761  case Match_InvalidOperand: {
762  SMLoc ErrorLoc = IDLoc;
763  if (ErrorInfo != ~0U) {
764  if (ErrorInfo >= Operands.size())
765  return Error(ErrorLoc, "too few operands for instruction");
766 
767  ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
768  if (ErrorLoc == SMLoc())
769  ErrorLoc = IDLoc;
770  }
771  return Error(ErrorLoc, "invalid operand for instruction");
772  }
773  }
774 
775  // Handle the case when the error message is of specific type
776  // other than the generic Match_InvalidOperand, and the
777  // corresponding operand is missing.
778  if (Result > FIRST_TARGET_MATCH_RESULT_TY) {
779  SMLoc ErrorLoc = IDLoc;
780  if (ErrorInfo != ~0U && ErrorInfo >= Operands.size())
781  return Error(ErrorLoc, "too few operands for instruction");
782  }
783 
784  switch(Result) {
785  default:
786  break;
787  case Match_InvalidImmXLenLI:
788  if (isRV64()) {
789  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
790  return Error(ErrorLoc, "operand must be a constant 64-bit integer");
791  }
792  return generateImmOutOfRangeError(Operands, ErrorInfo,
793  std::numeric_limits<int32_t>::min(),
795  case Match_InvalidUImmLog2XLen:
796  if (isRV64())
797  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
798  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
799  case Match_InvalidUImmLog2XLenNonZero:
800  if (isRV64())
801  return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 6) - 1);
802  return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5) - 1);
803  case Match_InvalidUImm5:
804  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
805  case Match_InvalidSImm6:
806  return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
807  (1 << 5) - 1);
808  case Match_InvalidSImm6NonZero:
809  return generateImmOutOfRangeError(
810  Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1,
811  "immediate must be non-zero in the range");
812  case Match_InvalidCLUIImm:
813  return generateImmOutOfRangeError(
814  Operands, ErrorInfo, 1, (1 << 5) - 1,
815  "immediate must be in [0xfffe0, 0xfffff] or");
816  case Match_InvalidUImm7Lsb00:
817  return generateImmOutOfRangeError(
818  Operands, ErrorInfo, 0, (1 << 7) - 4,
819  "immediate must be a multiple of 4 bytes in the range");
820  case Match_InvalidUImm8Lsb00:
821  return generateImmOutOfRangeError(
822  Operands, ErrorInfo, 0, (1 << 8) - 4,
823  "immediate must be a multiple of 4 bytes in the range");
824  case Match_InvalidUImm8Lsb000:
825  return generateImmOutOfRangeError(
826  Operands, ErrorInfo, 0, (1 << 8) - 8,
827  "immediate must be a multiple of 8 bytes in the range");
828  case Match_InvalidSImm9Lsb0:
829  return generateImmOutOfRangeError(
830  Operands, ErrorInfo, -(1 << 8), (1 << 8) - 2,
831  "immediate must be a multiple of 2 bytes in the range");
832  case Match_InvalidUImm9Lsb000:
833  return generateImmOutOfRangeError(
834  Operands, ErrorInfo, 0, (1 << 9) - 8,
835  "immediate must be a multiple of 8 bytes in the range");
836  case Match_InvalidUImm10Lsb00NonZero:
837  return generateImmOutOfRangeError(
838  Operands, ErrorInfo, 4, (1 << 10) - 4,
839  "immediate must be a multiple of 4 bytes in the range");
840  case Match_InvalidSImm10Lsb0000NonZero:
841  return generateImmOutOfRangeError(
842  Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
843  "immediate must be a multiple of 16 bytes and non-zero in the range");
844  case Match_InvalidSImm12:
845  return generateImmOutOfRangeError(
846  Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
847  "operand must be a symbol with %lo/%pcrel_lo modifier or an integer in "
848  "the range");
849  case Match_InvalidSImm12Lsb0:
850  return generateImmOutOfRangeError(
851  Operands, ErrorInfo, -(1 << 11), (1 << 11) - 2,
852  "immediate must be a multiple of 2 bytes in the range");
853  case Match_InvalidSImm13Lsb0:
854  return generateImmOutOfRangeError(
855  Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
856  "immediate must be a multiple of 2 bytes in the range");
857  case Match_InvalidUImm20LUI:
858  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
859  "operand must be a symbol with %hi() "
860  "modifier or an integer in the range");
861  case Match_InvalidUImm20AUIPC:
862  return generateImmOutOfRangeError(
863  Operands, ErrorInfo, 0, (1 << 20) - 1,
864  "operand must be a symbol with %pcrel_hi() modifier or an integer in "
865  "the range");
866  case Match_InvalidSImm21Lsb0JAL:
867  return generateImmOutOfRangeError(
868  Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
869  "immediate must be a multiple of 2 bytes in the range");
870  case Match_InvalidCSRSystemRegister: {
871  return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1,
872  "operand must be a valid system register "
873  "name or an integer in the range");
874  }
875  case Match_InvalidFenceArg: {
876  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
877  return Error(
878  ErrorLoc,
879  "operand must be formed of letters selected in-order from 'iorw'");
880  }
881  case Match_InvalidFRMArg: {
882  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
883  return Error(
884  ErrorLoc,
885  "operand must be a valid floating point rounding mode mnemonic");
886  }
887  case Match_InvalidBareSymbol: {
888  SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
889  return Error(ErrorLoc, "operand must be a bare symbol name");
890  }
891  }
892 
893  llvm_unreachable("Unknown match type detected!");
894 }
895 
896 bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
897  SMLoc &EndLoc) {
898  const AsmToken &Tok = getParser().getTok();
899  StartLoc = Tok.getLoc();
900  EndLoc = Tok.getEndLoc();
901  RegNo = 0;
902  StringRef Name = getLexer().getTok().getIdentifier();
903 
904  if (!MatchRegisterName(Name) || !MatchRegisterAltName(Name)) {
905  getParser().Lex(); // Eat identifier token.
906  return false;
907  }
908 
909  return Error(StartLoc, "invalid register name");
910 }
911 
912 OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands,
913  bool AllowParens) {
914  SMLoc FirstS = getLoc();
915  bool HadParens = false;
916  AsmToken Buf[2];
917 
918  // If this a parenthesised register name is allowed, parse it atomically
919  if (AllowParens && getLexer().is(AsmToken::LParen)) {
920  size_t ReadCount = getLexer().peekTokens(Buf);
921  if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
922  HadParens = true;
923  getParser().Lex(); // Eat '('
924  }
925  }
926 
927  switch (getLexer().getKind()) {
928  default:
929  return MatchOperand_NoMatch;
931  StringRef Name = getLexer().getTok().getIdentifier();
932  unsigned RegNo = MatchRegisterName(Name);
933  if (RegNo == 0) {
934  RegNo = MatchRegisterAltName(Name);
935  if (RegNo == 0) {
936  if (HadParens)
937  getLexer().UnLex(Buf[0]);
938  return MatchOperand_NoMatch;
939  }
940  }
941  if (HadParens)
942  Operands.push_back(RISCVOperand::createToken("(", FirstS, isRV64()));
943  SMLoc S = getLoc();
945  getLexer().Lex();
946  Operands.push_back(RISCVOperand::createReg(RegNo, S, E, isRV64()));
947  }
948 
949  if (HadParens) {
950  getParser().Lex(); // Eat ')'
951  Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
952  }
953 
954  return MatchOperand_Success;
955 }
956 
958 RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
959  SMLoc S = getLoc();
960  const MCExpr *Res;
961 
962  switch (getLexer().getKind()) {
963  default:
964  return MatchOperand_NoMatch;
965  case AsmToken::LParen:
966  case AsmToken::Minus:
967  case AsmToken::Plus:
968  case AsmToken::Integer:
969  case AsmToken::String: {
970  if (getParser().parseExpression(Res))
971  return MatchOperand_ParseFail;
972 
973  auto *CE = dyn_cast<MCConstantExpr>(Res);
974  if (CE) {
975  int64_t Imm = CE->getValue();
976  if (isUInt<12>(Imm)) {
977  auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
978  // Accept an immediate representing a named or un-named Sys Reg
979  // if the range is valid, regardless of the required features.
980  Operands.push_back(RISCVOperand::createSysReg(
981  SysReg ? SysReg->Name : "", S, Imm, isRV64()));
982  return MatchOperand_Success;
983  }
984  }
985 
986  Twine Msg = "immediate must be an integer in the range";
987  Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
988  return MatchOperand_ParseFail;
989  }
990  case AsmToken::Identifier: {
992  if (getParser().parseIdentifier(Identifier))
993  return MatchOperand_ParseFail;
994 
995  auto SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
996  // Accept a named Sys Reg if the required features are present.
997  if (SysReg) {
998  if (!SysReg->haveRequiredFeatures(getSTI().getFeatureBits())) {
999  Error(S, "system register use requires an option to be enabled");
1000  return MatchOperand_ParseFail;
1001  }
1002  Operands.push_back(RISCVOperand::createSysReg(
1003  Identifier, S, SysReg->Encoding, isRV64()));
1004  return MatchOperand_Success;
1005  }
1006 
1007  Twine Msg = "operand must be a valid system register name "
1008  "or an integer in the range";
1009  Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1010  return MatchOperand_ParseFail;
1011  }
1012  case AsmToken::Percent: {
1013  // Discard operand with modifier.
1014  Twine Msg = "immediate must be an integer in the range";
1015  Error(S, Msg + " [" + Twine(0) + ", " + Twine((1 << 12) - 1) + "]");
1016  return MatchOperand_ParseFail;
1017  }
1018  }
1019 
1020  return MatchOperand_NoMatch;
1021 }
1022 
1024  SMLoc S = getLoc();
1026  const MCExpr *Res;
1027 
1028  switch (getLexer().getKind()) {
1029  default:
1030  return MatchOperand_NoMatch;
1031  case AsmToken::LParen:
1032  case AsmToken::Minus:
1033  case AsmToken::Plus:
1034  case AsmToken::Integer:
1035  case AsmToken::String:
1036  case AsmToken::Identifier:
1037  if (getParser().parseExpression(Res))
1038  return MatchOperand_ParseFail;
1039  break;
1040  case AsmToken::Percent:
1041  return parseOperandWithModifier(Operands);
1042  }
1043 
1044  Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1045  return MatchOperand_Success;
1046 }
1047 
1049 RISCVAsmParser::parseOperandWithModifier(OperandVector &Operands) {
1050  SMLoc S = getLoc();
1052 
1053  if (getLexer().getKind() != AsmToken::Percent) {
1054  Error(getLoc(), "expected '%' for operand modifier");
1055  return MatchOperand_ParseFail;
1056  }
1057 
1058  getParser().Lex(); // Eat '%'
1059 
1060  if (getLexer().getKind() != AsmToken::Identifier) {
1061  Error(getLoc(), "expected valid identifier for operand modifier");
1062  return MatchOperand_ParseFail;
1063  }
1064  StringRef Identifier = getParser().getTok().getIdentifier();
1066  if (VK == RISCVMCExpr::VK_RISCV_Invalid) {
1067  Error(getLoc(), "unrecognized operand modifier");
1068  return MatchOperand_ParseFail;
1069  }
1070 
1071  getParser().Lex(); // Eat the identifier
1072  if (getLexer().getKind() != AsmToken::LParen) {
1073  Error(getLoc(), "expected '('");
1074  return MatchOperand_ParseFail;
1075  }
1076  getParser().Lex(); // Eat '('
1077 
1078  const MCExpr *SubExpr;
1079  if (getParser().parseParenExpression(SubExpr, E)) {
1080  return MatchOperand_ParseFail;
1081  }
1082 
1083  const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, VK, getContext());
1084  Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
1085  return MatchOperand_Success;
1086 }
1087 
1088 OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
1089  SMLoc S = getLoc();
1091  const MCExpr *Res;
1092 
1093  if (getLexer().getKind() != AsmToken::Identifier)
1094  return MatchOperand_NoMatch;
1095 
1097  if (getParser().parseIdentifier(Identifier))
1098  return MatchOperand_ParseFail;
1099 
1100  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
1101  Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
1102  Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
1103  return MatchOperand_Success;
1104 }
1105 
1106 OperandMatchResultTy RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
1107  // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
1108  // both being acceptable forms. When parsing `jal ra, foo` this function
1109  // will be called for the `ra` register operand in an attempt to match the
1110  // single-operand alias. parseJALOffset must fail for this case. It would
1111  // seem logical to try parse the operand using parseImmediate and return
1112  // NoMatch if the next token is a comma (meaning we must be parsing a jal in
1113  // the second form rather than the first). We can't do this as there's no
1114  // way of rewinding the lexer state. Instead, return NoMatch if this operand
1115  // is an identifier and is followed by a comma.
1116  if (getLexer().is(AsmToken::Identifier) &&
1117  getLexer().peekTok().is(AsmToken::Comma))
1118  return MatchOperand_NoMatch;
1119 
1120  return parseImmediate(Operands);
1121 }
1122 
1124 RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
1125  if (getLexer().isNot(AsmToken::LParen)) {
1126  Error(getLoc(), "expected '('");
1127  return MatchOperand_ParseFail;
1128  }
1129 
1130  getParser().Lex(); // Eat '('
1131  Operands.push_back(RISCVOperand::createToken("(", getLoc(), isRV64()));
1132 
1133  if (parseRegister(Operands) != MatchOperand_Success) {
1134  Error(getLoc(), "expected register");
1135  return MatchOperand_ParseFail;
1136  }
1137 
1138  if (getLexer().isNot(AsmToken::RParen)) {
1139  Error(getLoc(), "expected ')'");
1140  return MatchOperand_ParseFail;
1141  }
1142 
1143  getParser().Lex(); // Eat ')'
1144  Operands.push_back(RISCVOperand::createToken(")", getLoc(), isRV64()));
1145 
1146  return MatchOperand_Success;
1147 }
1148 
1149 /// Looks at a token type and creates the relevant operand from this
1150 /// information, adding to Operands. If operand was parsed, returns false, else
1151 /// true.
1152 bool RISCVAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1153  // Check if the current operand has a custom associated parser, if so, try to
1154  // custom parse the operand, or fallback to the general approach.
1155  OperandMatchResultTy Result =
1156  MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
1157  if (Result == MatchOperand_Success)
1158  return false;
1159  if (Result == MatchOperand_ParseFail)
1160  return true;
1161 
1162  // Attempt to parse token as a register.
1163  if (parseRegister(Operands, true) == MatchOperand_Success)
1164  return false;
1165 
1166  // Attempt to parse token as an immediate
1167  if (parseImmediate(Operands) == MatchOperand_Success) {
1168  // Parse memory base register if present
1169  if (getLexer().is(AsmToken::LParen))
1170  return parseMemOpBaseReg(Operands) != MatchOperand_Success;
1171  return false;
1172  }
1173 
1174  // Finally we have exhausted all options and must declare defeat.
1175  Error(getLoc(), "unknown operand");
1176  return true;
1177 }
1178 
1179 bool RISCVAsmParser::ParseInstruction(ParseInstructionInfo &Info,
1180  StringRef Name, SMLoc NameLoc,
1181  OperandVector &Operands) {
1182  // Ensure that if the instruction occurs when relaxation is enabled,
1183  // relocations are forced for the file. Ideally this would be done when there
1184  // is enough information to reliably determine if the instruction itself may
1185  // cause relaxations. Unfortunately instruction processing stage occurs in the
1186  // same pass as relocation emission, so it's too late to set a 'sticky bit'
1187  // for the entire file.
1188  if (getSTI().getFeatureBits()[RISCV::FeatureRelax]) {
1189  auto *Assembler = getTargetStreamer().getStreamer().getAssemblerPtr();
1190  if (Assembler != nullptr) {
1191  RISCVAsmBackend &MAB =
1192  static_cast<RISCVAsmBackend &>(Assembler->getBackend());
1193  MAB.setForceRelocs();
1194  }
1195  }
1196 
1197  // First operand is token for instruction
1198  Operands.push_back(RISCVOperand::createToken(Name, NameLoc, isRV64()));
1199 
1200  // If there are no more operands, then finish
1201  if (getLexer().is(AsmToken::EndOfStatement))
1202  return false;
1203 
1204  // Parse first operand
1205  if (parseOperand(Operands, Name))
1206  return true;
1207 
1208  // Parse until end of statement, consuming commas between operands
1209  unsigned OperandIdx = 1;
1210  while (getLexer().is(AsmToken::Comma)) {
1211  // Consume comma token
1212  getLexer().Lex();
1213 
1214  // Parse next operand
1215  if (parseOperand(Operands, Name))
1216  return true;
1217 
1218  ++OperandIdx;
1219  }
1220 
1221  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1222  SMLoc Loc = getLexer().getLoc();
1223  getParser().eatToEndOfStatement();
1224  return Error(Loc, "unexpected token");
1225  }
1226 
1227  getParser().Lex(); // Consume the EndOfStatement.
1228  return false;
1229 }
1230 
1231 bool RISCVAsmParser::classifySymbolRef(const MCExpr *Expr,
1233  int64_t &Addend) {
1235  Addend = 0;
1236 
1237  if (const RISCVMCExpr *RE = dyn_cast<RISCVMCExpr>(Expr)) {
1238  Kind = RE->getKind();
1239  Expr = RE->getSubExpr();
1240  }
1241 
1242  // It's a simple symbol reference or constant with no addend.
1243  if (isa<MCConstantExpr>(Expr) || isa<MCSymbolRefExpr>(Expr))
1244  return true;
1245 
1246  const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
1247  if (!BE)
1248  return false;
1249 
1250  if (!isa<MCSymbolRefExpr>(BE->getLHS()))
1251  return false;
1252 
1253  if (BE->getOpcode() != MCBinaryExpr::Add &&
1254  BE->getOpcode() != MCBinaryExpr::Sub)
1255  return false;
1256 
1257  // We are able to support the subtraction of two symbol references
1258  if (BE->getOpcode() == MCBinaryExpr::Sub &&
1259  isa<MCSymbolRefExpr>(BE->getRHS()))
1260  return true;
1261 
1262  // See if the addend is a constant, otherwise there's more going
1263  // on here than we can deal with.
1264  auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
1265  if (!AddendExpr)
1266  return false;
1267 
1268  Addend = AddendExpr->getValue();
1269  if (BE->getOpcode() == MCBinaryExpr::Sub)
1270  Addend = -Addend;
1271 
1272  // It's some symbol reference + a constant addend
1273  return Kind != RISCVMCExpr::VK_RISCV_Invalid;
1274 }
1275 
1276 bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
1277  // This returns false if this function recognizes the directive
1278  // regardless of whether it is successfully handles or reports an
1279  // error. Otherwise it returns true to give the generic parser a
1280  // chance at recognizing it.
1281  StringRef IDVal = DirectiveID.getString();
1282 
1283  if (IDVal == ".option")
1284  return parseDirectiveOption();
1285 
1286  return true;
1287 }
1288 
1289 bool RISCVAsmParser::parseDirectiveOption() {
1290  MCAsmParser &Parser = getParser();
1291  // Get the option token.
1292  AsmToken Tok = Parser.getTok();
1293  // At the moment only identifiers are supported.
1294  if (Tok.isNot(AsmToken::Identifier))
1295  return Error(Parser.getTok().getLoc(),
1296  "unexpected token, expected identifier");
1297 
1298  StringRef Option = Tok.getIdentifier();
1299 
1300  if (Option == "push") {
1301  getTargetStreamer().emitDirectiveOptionPush();
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  pushFeatureBits();
1309  return false;
1310  }
1311 
1312  if (Option == "pop") {
1313  SMLoc StartLoc = Parser.getTok().getLoc();
1314  getTargetStreamer().emitDirectiveOptionPop();
1315 
1316  Parser.Lex();
1317  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1318  return Error(Parser.getTok().getLoc(),
1319  "unexpected token, expected end of statement");
1320 
1321  if (popFeatureBits())
1322  return Error(StartLoc, ".option pop with no .option push");
1323 
1324  return false;
1325  }
1326 
1327  if (Option == "rvc") {
1328  getTargetStreamer().emitDirectiveOptionRVC();
1329 
1330  Parser.Lex();
1331  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1332  return Error(Parser.getTok().getLoc(),
1333  "unexpected token, expected end of statement");
1334 
1335  setFeatureBits(RISCV::FeatureStdExtC, "c");
1336  return false;
1337  }
1338 
1339  if (Option == "norvc") {
1340  getTargetStreamer().emitDirectiveOptionNoRVC();
1341 
1342  Parser.Lex();
1343  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1344  return Error(Parser.getTok().getLoc(),
1345  "unexpected token, expected end of statement");
1346 
1347  clearFeatureBits(RISCV::FeatureStdExtC, "c");
1348  return false;
1349  }
1350 
1351  if (Option == "relax") {
1352  getTargetStreamer().emitDirectiveOptionRelax();
1353 
1354  Parser.Lex();
1355  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1356  return Error(Parser.getTok().getLoc(),
1357  "unexpected token, expected end of statement");
1358 
1359  setFeatureBits(RISCV::FeatureRelax, "relax");
1360  return false;
1361  }
1362 
1363  if (Option == "norelax") {
1364  getTargetStreamer().emitDirectiveOptionNoRelax();
1365 
1366  Parser.Lex();
1367  if (Parser.getTok().isNot(AsmToken::EndOfStatement))
1368  return Error(Parser.getTok().getLoc(),
1369  "unexpected token, expected end of statement");
1370 
1371  clearFeatureBits(RISCV::FeatureRelax, "relax");
1372  return false;
1373  }
1374 
1375  // Unknown option.
1376  Warning(Parser.getTok().getLoc(),
1377  "unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'relax' or "
1378  "'norelax'");
1379  Parser.eatToEndOfStatement();
1380  return false;
1381 }
1382 
1383 void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
1384  MCInst CInst;
1385  bool Res = compressInst(CInst, Inst, getSTI(), S.getContext());
1386  CInst.setLoc(Inst.getLoc());
1387  S.EmitInstruction((Res ? CInst : Inst), getSTI());
1388 }
1389 
1390 void RISCVAsmParser::emitLoadImm(unsigned DestReg, int64_t Value,
1391  MCStreamer &Out) {
1393  RISCVMatInt::generateInstSeq(Value, isRV64(), Seq);
1394 
1395  unsigned SrcReg = RISCV::X0;
1396  for (RISCVMatInt::Inst &Inst : Seq) {
1397  if (Inst.Opc == RISCV::LUI) {
1398  emitToStreamer(
1399  Out, MCInstBuilder(RISCV::LUI).addReg(DestReg).addImm(Inst.Imm));
1400  } else {
1401  emitToStreamer(
1402  Out, MCInstBuilder(Inst.Opc).addReg(DestReg).addReg(SrcReg).addImm(
1403  Inst.Imm));
1404  }
1405 
1406  // Only the first instruction has X0 as its source.
1407  SrcReg = DestReg;
1408  }
1409 }
1410 
1411 void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
1412  MCStreamer &Out) {
1413  // The local load address pseudo-instruction "lla" is used in PC-relative
1414  // addressing of symbols:
1415  // lla rdest, symbol
1416  // expands to
1417  // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
1418  // ADDI rdest, %pcrel_lo(TmpLabel)
1419  MCContext &Ctx = getContext();
1420 
1421  MCSymbol *TmpLabel = Ctx.createTempSymbol(
1422  "pcrel_hi", /* AlwaysAddSuffix */ true, /* CanBeUnnamed */ false);
1423  Out.EmitLabel(TmpLabel);
1424 
1425  MCOperand DestReg = Inst.getOperand(0);
1428 
1429  emitToStreamer(
1430  Out, MCInstBuilder(RISCV::AUIPC).addOperand(DestReg).addExpr(Symbol));
1431 
1432  const MCExpr *RefToLinkTmpLabel =
1435 
1436  emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
1437  .addOperand(DestReg)
1438  .addOperand(DestReg)
1439  .addExpr(RefToLinkTmpLabel));
1440 }
1441 
1442 bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
1443  MCStreamer &Out) {
1444  Inst.setLoc(IDLoc);
1445 
1446  if (Inst.getOpcode() == RISCV::PseudoLI) {
1447  unsigned Reg = Inst.getOperand(0).getReg();
1448  const MCOperand &Op1 = Inst.getOperand(1);
1449  if (Op1.isExpr()) {
1450  // We must have li reg, %lo(sym) or li reg, %pcrel_lo(sym) or similar.
1451  // Just convert to an addi. This allows compatibility with gas.
1452  emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
1453  .addReg(Reg)
1454  .addReg(RISCV::X0)
1455  .addExpr(Op1.getExpr()));
1456  return false;
1457  }
1458  int64_t Imm = Inst.getOperand(1).getImm();
1459  // On RV32 the immediate here can either be a signed or an unsigned
1460  // 32-bit number. Sign extension has to be performed to ensure that Imm
1461  // represents the expected signed 64-bit number.
1462  if (!isRV64())
1463  Imm = SignExtend64<32>(Imm);
1464  emitLoadImm(Reg, Imm, Out);
1465  return false;
1466  } else if (Inst.getOpcode() == RISCV::PseudoLLA) {
1467  emitLoadLocalAddress(Inst, IDLoc, Out);
1468  return false;
1469  }
1470 
1471  emitToStreamer(Out, Inst);
1472  return false;
1473 }
1474 
1475 extern "C" void LLVMInitializeRISCVAsmParser() {
1478 }
static bool isReg(const MCInst &MI, unsigned OpNo)
constexpr bool isUInt< 32 >(uint64_t x)
Definition: MathExtras.h:349
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition: MCAsmMacro.h:111
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:323
This class represents lattice values for constants.
Definition: AllocatorList.h:24
static unsigned MatchRegisterName(StringRef Name)
unsigned convertFPR32ToFPR64(unsigned Reg)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
Generic assembler parser interface, for use by target specific assembly parsers.
Definition: MCAsmParser.h:110
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:137
MCTargetAsmParser - Generic interface to target specific assembly parsers.
static RoundingMode stringToRoundingMode(StringRef Str)
Definition: RISCVBaseInfo.h:99
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
Target specific streamer interface.
Definition: MCStreamer.h:84
unsigned Reg
bool isNot(TokenKind K) const
Definition: MCAsmMacro.h:84
const MCExpr * getLHS() const
Get the left-hand side expression of the binary operator.
Definition: MCExpr.h:564
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
block Block Frequency true
const AsmToken & getTok() const
Get the current AsmToken from the stream.
Definition: MCAsmParser.cpp:34
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:128
virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, bool PrintSchedInfo=false)
Emit the given Instruction into the current section.
Definition: MCStreamer.cpp:956
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
MCContext & getContext() const
Definition: MCStreamer.h:251
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string...
Definition: MCAsmMacro.h:100
amdgpu Simplify well known AMD library false Value Value const Twine & Name
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:116
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
const FeatureBitset & getFeatureBits() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:36
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:22
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:166
Target & getTheRISCV32Target()
static bool isMem(const MachineInstr &MI, unsigned Op)
Definition: X86InstrInfo.h:161
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand...
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:65
Context object for machine code objects.
Definition: MCContext.h:63
std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \\\)
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
RegisterMCAsmParser - Helper template for registering a target specific assembly parser, for use in the target machine initialization function.
const MCExpr * getRHS() const
Get the right-hand side expression of the binary operator.
Definition: MCExpr.h:567
SMLoc getLoc() const
Definition: MCAsmLexer.cpp:28
const MCExpr * getExpr() const
Definition: MCInst.h:96
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:161
Analysis containing CSE Info
Definition: CSEInfo.cpp:21
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
virtual void addAliasForDirective(StringRef Directive, StringRef Alias)=0
FeatureBitset ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
int64_t getImm() const
Definition: MCInst.h:76
const char * getPointer() const
Definition: SMLoc.h:35
int64_t getValue() const
Definition: MCExpr.h:152
Streaming machine code generation interface.
Definition: MCStreamer.h:189
MCInstBuilder & addReg(unsigned Reg)
Add a new register operand.
Definition: MCInstBuilder.h:32
MCSymbol * createTempSymbol(bool CanBeUnnamed=true)
Create and return a new assembler temporary symbol with a unique but unspecified name.
Definition: MCContext.cpp:217
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:258
Container class for subtarget features.
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
Definition: MathExtras.h:315
SMLoc getEndLoc() const
Definition: MCAsmLexer.cpp:32
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Target & getTheRISCV64Target()
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:24
bool isExpr() const
Definition: MCInst.h:61
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:38
Binary assembler expressions.
Definition: MCExpr.h:417
size_t size() const
Definition: SmallVector.h:53
void setLoc(SMLoc loc)
Definition: MCInst.h:179
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static unsigned MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
MCStreamer & getStreamer()
Definition: MCStreamer.h:92
constexpr bool isInt< 32 >(int64_t x)
Definition: MathExtras.h:309
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
void LLVMInitializeRISCVAsmParser()
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:182
Promote Memory to Register
Definition: Mem2Reg.cpp:110
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:381
SMLoc getLoc() const
Definition: MCInst.h:180
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
const SysReg * lookupSysRegByName(StringRef)
Base class for user error types.
Definition: Error.h:345
static SMLoc getFromPointer(const char *Ptr)
Definition: SMLoc.h:37
static VariantKind getVariantKindForName(StringRef name)
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:56
#define N
Generic base class for all target subtargets.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:323
Opcode getOpcode() const
Get the kind of this binary expression.
Definition: MCExpr.h:561
const unsigned Kind
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:73
const SysReg * lookupSysRegByEncoding(uint16_t)
virtual void EmitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:347
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
Subtraction.
Definition: MCExpr.h:441
void addOperand(const MCOperand &Op)
Definition: MCInst.h:186
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
void generateInstSeq(int64_t Val, bool Is64Bit, InstSeq &Res)
Definition: RISCVMatInt.cpp:20
Represents a location in source code.
Definition: SMLoc.h:24
unsigned getOpcode() const
Definition: MCInst.h:174
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:35
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:123
static const RISCVMCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx)
Definition: RISCVMCExpr.cpp:29
bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef< uint8_t > Bytes)