LLVM  16.0.0git
LanaiAsmParser.cpp
Go to the documentation of this file.
1 //===-- LanaiAsmParser.cpp - Parse Lanai assembly to MCInst instructions --===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "LanaiAluCode.h"
10 #include "LanaiCondCode.h"
11 #include "LanaiInstrInfo.h"
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/ADT/StringSwitch.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCInst.h"
24 #include "llvm/MC/MCStreamer.h"
26 #include "llvm/MC/MCSymbol.h"
27 #include "llvm/MC/TargetRegistry.h"
28 #include "llvm/Support/Casting.h"
31 #include "llvm/Support/SMLoc.h"
33 #include <algorithm>
34 #include <cassert>
35 #include <cstddef>
36 #include <cstdint>
37 #include <memory>
38 #include <optional>
39 
40 using namespace llvm;
41 
42 // Auto-generated by TableGen
43 static unsigned MatchRegisterName(StringRef Name);
44 
45 namespace {
46 
47 struct LanaiOperand;
48 
49 class LanaiAsmParser : public MCTargetAsmParser {
50  // Parse operands
51  std::unique_ptr<LanaiOperand> parseRegister(bool RestoreOnFailure = false);
52 
53  std::unique_ptr<LanaiOperand> parseImmediate();
54 
55  std::unique_ptr<LanaiOperand> parseIdentifier();
56 
57  unsigned parseAluOperator(bool PreOp, bool PostOp);
58 
59  // Split the mnemonic stripping conditional code and quantifiers
60  StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,
62 
63  bool parsePrePost(StringRef Type, int *OffsetValue);
64 
65  bool ParseDirective(AsmToken DirectiveID) override;
66 
67  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
68  SMLoc NameLoc, OperandVector &Operands) override;
69 
70  bool ParseRegister(unsigned &RegNum, SMLoc &StartLoc, SMLoc &EndLoc) override;
71  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
72  SMLoc &EndLoc) override;
73 
74  bool MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
77  bool MatchingInlineAsm) override;
78 
79 // Auto-generated instruction matching functions
80 #define GET_ASSEMBLER_HEADER
81 #include "LanaiGenAsmMatcher.inc"
82 
84  StringRef Mnemonic);
85 
86  OperandMatchResultTy parseMemoryOperand(OperandVector &Operands);
87 
88 public:
89  LanaiAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
90  const MCInstrInfo &MII, const MCTargetOptions &Options)
91  : MCTargetAsmParser(Options, STI, MII), Parser(Parser),
92  Lexer(Parser.getLexer()), SubtargetInfo(STI) {
93  setAvailableFeatures(
94  ComputeAvailableFeatures(SubtargetInfo.getFeatureBits()));
95  }
96 
97 private:
98  MCAsmParser &Parser;
99  MCAsmLexer &Lexer;
100 
101  const MCSubtargetInfo &SubtargetInfo;
102 };
103 
104 // LanaiOperand - Instances of this class represented a parsed machine
105 // instruction
106 struct LanaiOperand : public MCParsedAsmOperand {
107  enum KindTy {
108  TOKEN,
109  REGISTER,
110  IMMEDIATE,
111  MEMORY_IMM,
112  MEMORY_REG_IMM,
113  MEMORY_REG_REG,
114  } Kind;
115 
116  SMLoc StartLoc, EndLoc;
117 
118  struct Token {
119  const char *Data;
120  unsigned Length;
121  };
122 
123  struct RegOp {
124  unsigned RegNum;
125  };
126 
127  struct ImmOp {
128  const MCExpr *Value;
129  };
130 
131  struct MemOp {
132  unsigned BaseReg;
133  unsigned OffsetReg;
134  unsigned AluOp;
135  const MCExpr *Offset;
136  };
137 
138  union {
139  struct Token Tok;
140  struct RegOp Reg;
141  struct ImmOp Imm;
142  struct MemOp Mem;
143  };
144 
145  explicit LanaiOperand(KindTy Kind) : Kind(Kind) {}
146 
147 public:
148  // The functions below are used by the autogenerated ASM matcher and hence to
149  // be of the form expected.
150 
151  // getStartLoc - Gets location of the first token of this operand
152  SMLoc getStartLoc() const override { return StartLoc; }
153 
154  // getEndLoc - Gets location of the last token of this operand
155  SMLoc getEndLoc() const override { return EndLoc; }
156 
157  unsigned getReg() const override {
158  assert(isReg() && "Invalid type access!");
159  return Reg.RegNum;
160  }
161 
162  const MCExpr *getImm() const {
163  assert(isImm() && "Invalid type access!");
164  return Imm.Value;
165  }
166 
167  StringRef getToken() const {
168  assert(isToken() && "Invalid type access!");
169  return StringRef(Tok.Data, Tok.Length);
170  }
171 
172  unsigned getMemBaseReg() const {
173  assert(isMem() && "Invalid type access!");
174  return Mem.BaseReg;
175  }
176 
177  unsigned getMemOffsetReg() const {
178  assert(isMem() && "Invalid type access!");
179  return Mem.OffsetReg;
180  }
181 
182  const MCExpr *getMemOffset() const {
183  assert(isMem() && "Invalid type access!");
184  return Mem.Offset;
185  }
186 
187  unsigned getMemOp() const {
188  assert(isMem() && "Invalid type access!");
189  return Mem.AluOp;
190  }
191 
192  // Functions for testing operand type
193  bool isReg() const override { return Kind == REGISTER; }
194 
195  bool isImm() const override { return Kind == IMMEDIATE; }
196 
197  bool isMem() const override {
198  return isMemImm() || isMemRegImm() || isMemRegReg();
199  }
200 
201  bool isMemImm() const { return Kind == MEMORY_IMM; }
202 
203  bool isMemRegImm() const { return Kind == MEMORY_REG_IMM; }
204 
205  bool isMemRegReg() const { return Kind == MEMORY_REG_REG; }
206 
207  bool isMemSpls() const { return isMemRegImm() || isMemRegReg(); }
208 
209  bool isToken() const override { return Kind == TOKEN; }
210 
211  bool isBrImm() {
212  if (!isImm())
213  return false;
214 
215  // Constant case
216  const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm.Value);
217  if (!MCE)
218  return true;
219  int64_t Value = MCE->getValue();
220  // Check if value fits in 25 bits with 2 least significant bits 0.
221  return isShiftedUInt<23, 2>(static_cast<int32_t>(Value));
222  }
223 
224  bool isBrTarget() { return isBrImm() || isToken(); }
225 
226  bool isCallTarget() { return isImm() || isToken(); }
227 
228  bool isHiImm16() {
229  if (!isImm())
230  return false;
231 
232  // Constant case
233  if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
234  int64_t Value = ConstExpr->getValue();
235  return Value != 0 && isShiftedUInt<16, 16>(Value);
236  }
237 
238  // Symbolic reference expression
239  if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
240  return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
241 
242  // Binary expression
243  if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
244  if (const LanaiMCExpr *SymbolRefExpr =
245  dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
246  return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
247 
248  return false;
249  }
250 
251  bool isHiImm16And() {
252  if (!isImm())
253  return false;
254 
255  const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
256  if (ConstExpr) {
257  int64_t Value = ConstExpr->getValue();
258  // Check if in the form 0xXYZWffff
259  return (Value != 0) && ((Value & ~0xffff0000) == 0xffff);
260  }
261  return false;
262  }
263 
264  bool isLoImm16() {
265  if (!isImm())
266  return false;
267 
268  // Constant case
269  if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
270  int64_t Value = ConstExpr->getValue();
271  // Check if value fits in 16 bits
272  return isUInt<16>(static_cast<int32_t>(Value));
273  }
274 
275  // Symbolic reference expression
276  if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
277  return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
278 
279  // Binary expression
280  if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
281  if (const LanaiMCExpr *SymbolRefExpr =
282  dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
283  return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
284 
285  return false;
286  }
287 
288  bool isLoImm16Signed() {
289  if (!isImm())
290  return false;
291 
292  // Constant case
293  if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
294  int64_t Value = ConstExpr->getValue();
295  // Check if value fits in 16 bits or value of the form 0xffffxyzw
296  return isInt<16>(static_cast<int32_t>(Value));
297  }
298 
299  // Symbolic reference expression
300  if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
301  return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
302 
303  // Binary expression
304  if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
305  if (const LanaiMCExpr *SymbolRefExpr =
306  dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
307  return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
308 
309  return false;
310  }
311 
312  bool isLoImm16And() {
313  if (!isImm())
314  return false;
315 
316  const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
317  if (ConstExpr) {
318  int64_t Value = ConstExpr->getValue();
319  // Check if in the form 0xffffXYZW
320  return ((Value & ~0xffff) == 0xffff0000);
321  }
322  return false;
323  }
324 
325  bool isImmShift() {
326  if (!isImm())
327  return false;
328 
329  const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
330  if (!ConstExpr)
331  return false;
332  int64_t Value = ConstExpr->getValue();
333  return (Value >= -31) && (Value <= 31);
334  }
335 
336  bool isLoImm21() {
337  if (!isImm())
338  return false;
339 
340  // Constant case
341  if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
342  int64_t Value = ConstExpr->getValue();
343  return isUInt<21>(Value);
344  }
345 
346  // Symbolic reference expression
347  if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
348  return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
349  if (const MCSymbolRefExpr *SymbolRefExpr =
350  dyn_cast<MCSymbolRefExpr>(Imm.Value)) {
351  return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
352  }
353 
354  // Binary expression
355  if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) {
356  if (const LanaiMCExpr *SymbolRefExpr =
357  dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
358  return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
359  if (const MCSymbolRefExpr *SymbolRefExpr =
360  dyn_cast<MCSymbolRefExpr>(BinaryExpr->getLHS()))
361  return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
362  }
363 
364  return false;
365  }
366 
367  bool isImm10() {
368  if (!isImm())
369  return false;
370 
371  const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
372  if (!ConstExpr)
373  return false;
374  int64_t Value = ConstExpr->getValue();
375  return isInt<10>(Value);
376  }
377 
378  bool isCondCode() {
379  if (!isImm())
380  return false;
381 
382  const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
383  if (!ConstExpr)
384  return false;
385  uint64_t Value = ConstExpr->getValue();
386  // The condition codes are between 0 (ICC_T) and 15 (ICC_LE). If the
387  // unsigned value of the immediate is less than LPCC::UNKNOWN (16) then
388  // value corresponds to a valid condition code.
389  return Value < LPCC::UNKNOWN;
390  }
391 
392  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
393  // Add as immediates where possible. Null MCExpr = 0
394  if (Expr == nullptr)
396  else if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Expr))
397  Inst.addOperand(
398  MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
399  else
400  Inst.addOperand(MCOperand::createExpr(Expr));
401  }
402 
403  void addRegOperands(MCInst &Inst, unsigned N) const {
404  assert(N == 1 && "Invalid number of operands!");
406  }
407 
408  void addImmOperands(MCInst &Inst, unsigned N) const {
409  assert(N == 1 && "Invalid number of operands!");
410  addExpr(Inst, getImm());
411  }
412 
413  void addBrTargetOperands(MCInst &Inst, unsigned N) const {
414  assert(N == 1 && "Invalid number of operands!");
415  addExpr(Inst, getImm());
416  }
417 
418  void addCallTargetOperands(MCInst &Inst, unsigned N) const {
419  assert(N == 1 && "Invalid number of operands!");
420  addExpr(Inst, getImm());
421  }
422 
423  void addCondCodeOperands(MCInst &Inst, unsigned N) const {
424  assert(N == 1 && "Invalid number of operands!");
425  addExpr(Inst, getImm());
426  }
427 
428  void addMemImmOperands(MCInst &Inst, unsigned N) const {
429  assert(N == 1 && "Invalid number of operands!");
430  const MCExpr *Expr = getMemOffset();
431  addExpr(Inst, Expr);
432  }
433 
434  void addMemRegImmOperands(MCInst &Inst, unsigned N) const {
435  assert(N == 3 && "Invalid number of operands!");
436  Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
437  const MCExpr *Expr = getMemOffset();
438  addExpr(Inst, Expr);
439  Inst.addOperand(MCOperand::createImm(getMemOp()));
440  }
441 
442  void addMemRegRegOperands(MCInst &Inst, unsigned N) const {
443  assert(N == 3 && "Invalid number of operands!");
444  Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
445  assert(getMemOffsetReg() != 0 && "Invalid offset");
446  Inst.addOperand(MCOperand::createReg(getMemOffsetReg()));
447  Inst.addOperand(MCOperand::createImm(getMemOp()));
448  }
449 
450  void addMemSplsOperands(MCInst &Inst, unsigned N) const {
451  if (isMemRegImm())
452  addMemRegImmOperands(Inst, N);
453  if (isMemRegReg())
454  addMemRegRegOperands(Inst, N);
455  }
456 
457  void addImmShiftOperands(MCInst &Inst, unsigned N) const {
458  assert(N == 1 && "Invalid number of operands!");
459  addExpr(Inst, getImm());
460  }
461 
462  void addImm10Operands(MCInst &Inst, unsigned N) const {
463  assert(N == 1 && "Invalid number of operands!");
464  addExpr(Inst, getImm());
465  }
466 
467  void addLoImm16Operands(MCInst &Inst, unsigned N) const {
468  assert(N == 1 && "Invalid number of operands!");
469  if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
470  Inst.addOperand(
471  MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
472  else if (isa<LanaiMCExpr>(getImm())) {
473 #ifndef NDEBUG
474  const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
475  assert(SymbolRefExpr &&
476  SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO);
477 #endif
478  Inst.addOperand(MCOperand::createExpr(getImm()));
479  } else if (isa<MCBinaryExpr>(getImm())) {
480 #ifndef NDEBUG
481  const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
482  assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
483  cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
485 #endif
486  Inst.addOperand(MCOperand::createExpr(getImm()));
487  } else
488  assert(false && "Operand type not supported.");
489  }
490 
491  void addLoImm16AndOperands(MCInst &Inst, unsigned N) const {
492  assert(N == 1 && "Invalid number of operands!");
493  if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
494  Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff));
495  else
496  assert(false && "Operand type not supported.");
497  }
498 
499  void addHiImm16Operands(MCInst &Inst, unsigned N) const {
500  assert(N == 1 && "Invalid number of operands!");
501  if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
502  Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
503  else if (isa<LanaiMCExpr>(getImm())) {
504 #ifndef NDEBUG
505  const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
506  assert(SymbolRefExpr &&
507  SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI);
508 #endif
509  Inst.addOperand(MCOperand::createExpr(getImm()));
510  } else if (isa<MCBinaryExpr>(getImm())) {
511 #ifndef NDEBUG
512  const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
513  assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
514  cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
516 #endif
517  Inst.addOperand(MCOperand::createExpr(getImm()));
518  } else
519  assert(false && "Operand type not supported.");
520  }
521 
522  void addHiImm16AndOperands(MCInst &Inst, unsigned N) const {
523  assert(N == 1 && "Invalid number of operands!");
524  if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
525  Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
526  else
527  assert(false && "Operand type not supported.");
528  }
529 
530  void addLoImm21Operands(MCInst &Inst, unsigned N) const {
531  assert(N == 1 && "Invalid number of operands!");
532  if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
533  Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff));
534  else if (isa<LanaiMCExpr>(getImm())) {
535 #ifndef NDEBUG
536  const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
537  assert(SymbolRefExpr &&
538  SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
539 #endif
540  Inst.addOperand(MCOperand::createExpr(getImm()));
541  } else if (isa<MCSymbolRefExpr>(getImm())) {
542 #ifndef NDEBUG
543  const MCSymbolRefExpr *SymbolRefExpr =
544  dyn_cast<MCSymbolRefExpr>(getImm());
545  assert(SymbolRefExpr &&
546  SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None);
547 #endif
548  Inst.addOperand(MCOperand::createExpr(getImm()));
549  } else if (isa<MCBinaryExpr>(getImm())) {
550 #ifndef NDEBUG
551  const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
552  assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
553  cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
555 #endif
556  Inst.addOperand(MCOperand::createExpr(getImm()));
557  } else
558  assert(false && "Operand type not supported.");
559  }
560 
561  void print(raw_ostream &OS) const override {
562  switch (Kind) {
563  case IMMEDIATE:
564  OS << "Imm: " << getImm() << "\n";
565  break;
566  case TOKEN:
567  OS << "Token: " << getToken() << "\n";
568  break;
569  case REGISTER:
570  OS << "Reg: %r" << getReg() << "\n";
571  break;
572  case MEMORY_IMM:
573  OS << "MemImm: " << *getMemOffset() << "\n";
574  break;
575  case MEMORY_REG_IMM:
576  OS << "MemRegImm: " << getMemBaseReg() << "+" << *getMemOffset() << "\n";
577  break;
578  case MEMORY_REG_REG:
579  assert(getMemOffset() == nullptr);
580  OS << "MemRegReg: " << getMemBaseReg() << "+"
581  << "%r" << getMemOffsetReg() << "\n";
582  break;
583  }
584  }
585 
586  static std::unique_ptr<LanaiOperand> CreateToken(StringRef Str, SMLoc Start) {
587  auto Op = std::make_unique<LanaiOperand>(TOKEN);
588  Op->Tok.Data = Str.data();
589  Op->Tok.Length = Str.size();
590  Op->StartLoc = Start;
591  Op->EndLoc = Start;
592  return Op;
593  }
594 
595  static std::unique_ptr<LanaiOperand> createReg(unsigned RegNum, SMLoc Start,
596  SMLoc End) {
597  auto Op = std::make_unique<LanaiOperand>(REGISTER);
598  Op->Reg.RegNum = RegNum;
599  Op->StartLoc = Start;
600  Op->EndLoc = End;
601  return Op;
602  }
603 
604  static std::unique_ptr<LanaiOperand> createImm(const MCExpr *Value,
605  SMLoc Start, SMLoc End) {
606  auto Op = std::make_unique<LanaiOperand>(IMMEDIATE);
607  Op->Imm.Value = Value;
608  Op->StartLoc = Start;
609  Op->EndLoc = End;
610  return Op;
611  }
612 
613  static std::unique_ptr<LanaiOperand>
614  MorphToMemImm(std::unique_ptr<LanaiOperand> Op) {
615  const MCExpr *Imm = Op->getImm();
616  Op->Kind = MEMORY_IMM;
617  Op->Mem.BaseReg = 0;
618  Op->Mem.AluOp = LPAC::ADD;
619  Op->Mem.OffsetReg = 0;
620  Op->Mem.Offset = Imm;
621  return Op;
622  }
623 
624  static std::unique_ptr<LanaiOperand>
625  MorphToMemRegReg(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
626  unsigned AluOp) {
627  unsigned OffsetReg = Op->getReg();
628  Op->Kind = MEMORY_REG_REG;
629  Op->Mem.BaseReg = BaseReg;
630  Op->Mem.AluOp = AluOp;
631  Op->Mem.OffsetReg = OffsetReg;
632  Op->Mem.Offset = nullptr;
633  return Op;
634  }
635 
636  static std::unique_ptr<LanaiOperand>
637  MorphToMemRegImm(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
638  unsigned AluOp) {
639  const MCExpr *Imm = Op->getImm();
640  Op->Kind = MEMORY_REG_IMM;
641  Op->Mem.BaseReg = BaseReg;
642  Op->Mem.AluOp = AluOp;
643  Op->Mem.OffsetReg = 0;
644  Op->Mem.Offset = Imm;
645  return Op;
646  }
647 };
648 
649 } // end anonymous namespace
650 
651 bool LanaiAsmParser::ParseDirective(AsmToken /*DirectiveId*/) { return true; }
652 
653 bool LanaiAsmParser::MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
655  MCStreamer &Out,
657  bool MatchingInlineAsm) {
658  MCInst Inst;
659  SMLoc ErrorLoc;
660 
661  switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
662  case Match_Success:
663  Out.emitInstruction(Inst, SubtargetInfo);
664  Opcode = Inst.getOpcode();
665  return false;
666  case Match_MissingFeature:
667  return Error(IdLoc, "Instruction use requires option to be enabled");
668  case Match_MnemonicFail:
669  return Error(IdLoc, "Unrecognized instruction mnemonic");
670  case Match_InvalidOperand: {
671  ErrorLoc = IdLoc;
672  if (ErrorInfo != ~0U) {
673  if (ErrorInfo >= Operands.size())
674  return Error(IdLoc, "Too few operands for instruction");
675 
676  ErrorLoc = ((LanaiOperand &)*Operands[ErrorInfo]).getStartLoc();
677  if (ErrorLoc == SMLoc())
678  ErrorLoc = IdLoc;
679  }
680  return Error(ErrorLoc, "Invalid operand for instruction");
681  }
682  default:
683  break;
684  }
685 
686  llvm_unreachable("Unknown match type detected!");
687 }
688 
689 // Both '%rN' and 'rN' are parsed as valid registers. This was done to remain
690 // backwards compatible with GCC and the different ways inline assembly is
691 // handled.
692 // TODO: see if there isn't a better way to do this.
693 std::unique_ptr<LanaiOperand>
694 LanaiAsmParser::parseRegister(bool RestoreOnFailure) {
695  SMLoc Start = Parser.getTok().getLoc();
696  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
697  std::optional<AsmToken> PercentTok;
698 
699  unsigned RegNum;
700  // Eat the '%'.
701  if (Lexer.getKind() == AsmToken::Percent) {
702  PercentTok = Parser.getTok();
703  Parser.Lex();
704  }
705  if (Lexer.getKind() == AsmToken::Identifier) {
706  RegNum = MatchRegisterName(Lexer.getTok().getIdentifier());
707  if (RegNum == 0) {
708  if (PercentTok && RestoreOnFailure)
709  Lexer.UnLex(PercentTok.value());
710  return nullptr;
711  }
712  Parser.Lex(); // Eat identifier token
713  return LanaiOperand::createReg(RegNum, Start, End);
714  }
715  if (PercentTok && RestoreOnFailure)
716  Lexer.UnLex(PercentTok.value());
717  return nullptr;
718 }
719 
720 bool LanaiAsmParser::ParseRegister(unsigned &RegNum, SMLoc &StartLoc,
721  SMLoc &EndLoc) {
722  const AsmToken &Tok = getParser().getTok();
723  StartLoc = Tok.getLoc();
724  EndLoc = Tok.getEndLoc();
725  std::unique_ptr<LanaiOperand> Op = parseRegister(/*RestoreOnFailure=*/false);
726  if (Op != nullptr)
727  RegNum = Op->getReg();
728  return (Op == nullptr);
729 }
730 
731 OperandMatchResultTy LanaiAsmParser::tryParseRegister(unsigned &RegNum,
732  SMLoc &StartLoc,
733  SMLoc &EndLoc) {
734  const AsmToken &Tok = getParser().getTok();
735  StartLoc = Tok.getLoc();
736  EndLoc = Tok.getEndLoc();
737  std::unique_ptr<LanaiOperand> Op = parseRegister(/*RestoreOnFailure=*/true);
738  if (Op == nullptr)
739  return MatchOperand_NoMatch;
740  RegNum = Op->getReg();
741  return MatchOperand_Success;
742 }
743 
744 std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {
745  SMLoc Start = Parser.getTok().getLoc();
746  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
747  const MCExpr *Res, *RHS = nullptr;
749 
750  if (Lexer.getKind() != AsmToken::Identifier)
751  return nullptr;
752 
754  if (Parser.parseIdentifier(Identifier))
755  return nullptr;
756 
757  // Check if identifier has a modifier
758  if (Identifier.equals_insensitive("hi"))
760  else if (Identifier.equals_insensitive("lo"))
762 
763  // If the identifier corresponds to a variant then extract the real
764  // identifier.
766  if (Lexer.getKind() != AsmToken::LParen) {
767  Error(Lexer.getLoc(), "Expected '('");
768  return nullptr;
769  }
770  Lexer.Lex(); // lex '('
771 
772  // Parse identifier
773  if (Parser.parseIdentifier(Identifier))
774  return nullptr;
775  }
776 
777  // If addition parse the RHS.
778  if (Lexer.getKind() == AsmToken::Plus && Parser.parseExpression(RHS))
779  return nullptr;
780 
781  // For variants parse the final ')'
783  if (Lexer.getKind() != AsmToken::RParen) {
784  Error(Lexer.getLoc(), "Expected ')'");
785  return nullptr;
786  }
787  Lexer.Lex(); // lex ')'
788  }
789 
790  End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
791  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
792  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
793  Res = LanaiMCExpr::create(Kind, Expr, getContext());
794 
795  // Nest if this was an addition
796  if (RHS)
797  Res = MCBinaryExpr::createAdd(Res, RHS, getContext());
798 
799  return LanaiOperand::createImm(Res, Start, End);
800 }
801 
802 std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {
803  SMLoc Start = Parser.getTok().getLoc();
804  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
805 
806  const MCExpr *ExprVal;
807  switch (Lexer.getKind()) {
809  return parseIdentifier();
810  case AsmToken::Plus:
811  case AsmToken::Minus:
812  case AsmToken::Integer:
813  case AsmToken::Dot:
814  if (!Parser.parseExpression(ExprVal))
815  return LanaiOperand::createImm(ExprVal, Start, End);
816  [[fallthrough]];
817  default:
818  return nullptr;
819  }
820 }
821 
822 static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) {
823  if (PreOp)
824  return LPAC::makePreOp(AluCode);
825  if (PostOp)
826  return LPAC::makePostOp(AluCode);
827  return AluCode;
828 }
829 
830 unsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) {
831  StringRef IdString;
832  Parser.parseIdentifier(IdString);
833  unsigned AluCode = LPAC::stringToLanaiAluCode(IdString);
834  if (AluCode == LPAC::UNKNOWN) {
835  Error(Parser.getTok().getLoc(), "Can't parse ALU operator");
836  return 0;
837  }
838  return AluCode;
839 }
840 
841 static int SizeForSuffix(StringRef T) {
842  return StringSwitch<int>(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4);
843 }
844 
845 bool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) {
846  bool PreOrPost = false;
847  if (Lexer.getKind() == Lexer.peekTok(true).getKind()) {
848  PreOrPost = true;
849  if (Lexer.is(AsmToken::Minus))
850  *OffsetValue = -SizeForSuffix(Type);
851  else if (Lexer.is(AsmToken::Plus))
852  *OffsetValue = SizeForSuffix(Type);
853  else
854  return false;
855 
856  // Eat the '-' '-' or '+' '+'
857  Parser.Lex();
858  Parser.Lex();
859  } else if (Lexer.is(AsmToken::Star)) {
860  Parser.Lex(); // Eat the '*'
861  PreOrPost = true;
862  }
863 
864  return PreOrPost;
865 }
866 
867 bool shouldBeSls(const LanaiOperand &Op) {
868  // The instruction should be encoded as an SLS if the constant is word
869  // aligned and will fit in 21 bits
870  if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm())) {
871  int64_t Value = ConstExpr->getValue();
872  return (Value % 4 == 0) && (Value >= 0) && (Value <= 0x1fffff);
873  }
874  // The instruction should be encoded as an SLS if the operand is a symbolic
875  // reference with no variant.
876  if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Op.getImm()))
877  return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
878  // The instruction should be encoded as an SLS if the operand is a binary
879  // expression with the left-hand side being a symbolic reference with no
880  // variant.
881  if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Op.getImm())) {
882  const LanaiMCExpr *LHSSymbolRefExpr =
883  dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
884  return (LHSSymbolRefExpr &&
885  LHSSymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
886  }
887  return false;
888 }
889 
890 // Matches memory operand. Returns true if error encountered.
892 LanaiAsmParser::parseMemoryOperand(OperandVector &Operands) {
893  // Try to match a memory operand.
894  // The memory operands are of the form:
895  // (1) Register|Immediate|'' '[' '*'? Register '*'? ']' or
896  // ^
897  // (2) '[' '*'? Register '*'? AluOperator Register ']'
898  // ^
899  // (3) '[' '--'|'++' Register '--'|'++' ']'
900  //
901  // (4) '[' Immediate ']' (for SLS)
902 
903  // Store the type for use in parsing pre/post increment/decrement operators
904  StringRef Type;
905  if (Operands[0]->isToken())
906  Type = static_cast<LanaiOperand *>(Operands[0].get())->getToken();
907 
908  // Use 0 if no offset given
909  int OffsetValue = 0;
910  unsigned BaseReg = 0;
911  unsigned AluOp = LPAC::ADD;
912  bool PostOp = false, PreOp = false;
913 
914  // Try to parse the offset
915  std::unique_ptr<LanaiOperand> Op = parseRegister();
916  if (!Op)
917  Op = parseImmediate();
918 
919  // Only continue if next token is '['
920  if (Lexer.isNot(AsmToken::LBrac)) {
921  if (!Op)
922  return MatchOperand_NoMatch;
923 
924  // The start of this custom parsing overlaps with register/immediate so
925  // consider this as a successful match of an operand of that type as the
926  // token stream can't be rewound to allow them to match separately.
927  Operands.push_back(std::move(Op));
928  return MatchOperand_Success;
929  }
930 
931  Parser.Lex(); // Eat the '['.
932  std::unique_ptr<LanaiOperand> Offset = nullptr;
933  if (Op)
934  Offset.swap(Op);
935 
936  // Determine if a pre operation
937  PreOp = parsePrePost(Type, &OffsetValue);
938 
939  Op = parseRegister();
940  if (!Op) {
941  if (!Offset) {
942  if ((Op = parseImmediate()) && Lexer.is(AsmToken::RBrac)) {
943  Parser.Lex(); // Eat the ']'
944 
945  // Memory address operations aligned to word boundary are encoded as
946  // SLS, the rest as RM.
947  if (shouldBeSls(*Op)) {
948  Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op)));
949  } else {
950  if (!Op->isLoImm16Signed()) {
951  Error(Parser.getTok().getLoc(),
952  "Memory address is not word "
953  "aligned and larger than class RM can handle");
954  return MatchOperand_ParseFail;
955  }
956  Operands.push_back(LanaiOperand::MorphToMemRegImm(
957  Lanai::R0, std::move(Op), LPAC::ADD));
958  }
959  return MatchOperand_Success;
960  }
961  }
962 
963  Error(Parser.getTok().getLoc(),
964  "Unknown operand, expected register or immediate");
965  return MatchOperand_ParseFail;
966  }
967  BaseReg = Op->getReg();
968 
969  // Determine if a post operation
970  if (!PreOp)
971  PostOp = parsePrePost(Type, &OffsetValue);
972 
973  // If ] match form (1) else match form (2)
974  if (Lexer.is(AsmToken::RBrac)) {
975  Parser.Lex(); // Eat the ']'.
976  if (!Offset) {
977  SMLoc Start = Parser.getTok().getLoc();
978  SMLoc End =
979  SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
980  const MCConstantExpr *OffsetConstExpr =
981  MCConstantExpr::create(OffsetValue, getContext());
982  Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End);
983  }
984  } else {
985  if (Offset || OffsetValue != 0) {
986  Error(Parser.getTok().getLoc(), "Expected ']'");
987  return MatchOperand_ParseFail;
988  }
989 
990  // Parse operator
991  AluOp = parseAluOperator(PreOp, PostOp);
992 
993  // Second form requires offset register
994  Offset = parseRegister();
995  if (!BaseReg || Lexer.isNot(AsmToken::RBrac)) {
996  Error(Parser.getTok().getLoc(), "Expected ']'");
997  return MatchOperand_ParseFail;
998  }
999  Parser.Lex(); // Eat the ']'.
1000  }
1001 
1002  // First form has addition as operator. Add pre- or post-op indicator as
1003  // needed.
1004  AluOp = AluWithPrePost(AluOp, PreOp, PostOp);
1005 
1006  // Ensure immediate offset is not too large
1007  if (Offset->isImm() && !Offset->isLoImm16Signed()) {
1008  Error(Parser.getTok().getLoc(),
1009  "Memory address is not word "
1010  "aligned and larger than class RM can handle");
1011  return MatchOperand_ParseFail;
1012  }
1013 
1014  Operands.push_back(
1015  Offset->isImm()
1016  ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp)
1017  : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp));
1018 
1019  return MatchOperand_Success;
1020 }
1021 
1022 // Looks at a token type and creates the relevant operand from this
1023 // information, adding to operands.
1024 // If operand was parsed, returns false, else true.
1026 LanaiAsmParser::parseOperand(OperandVector *Operands, StringRef Mnemonic) {
1027  // Check if the current operand has a custom associated parser, if so, try to
1028  // custom parse the operand, or fallback to the general approach.
1029  OperandMatchResultTy Result = MatchOperandParserImpl(*Operands, Mnemonic);
1030 
1031  if (Result == MatchOperand_Success)
1032  return Result;
1033  if (Result == MatchOperand_ParseFail) {
1034  Parser.eatToEndOfStatement();
1035  return Result;
1036  }
1037 
1038  // Attempt to parse token as register
1039  std::unique_ptr<LanaiOperand> Op = parseRegister();
1040 
1041  // Attempt to parse token as immediate
1042  if (!Op)
1043  Op = parseImmediate();
1044 
1045  // If the token could not be parsed then fail
1046  if (!Op) {
1047  Error(Parser.getTok().getLoc(), "Unknown operand");
1048  Parser.eatToEndOfStatement();
1049  return MatchOperand_ParseFail;
1050  }
1051 
1052  // Push back parsed operand into list of operands
1053  Operands->push_back(std::move(Op));
1054 
1055  return MatchOperand_Success;
1056 }
1057 
1058 // Split the mnemonic into ASM operand, conditional code and instruction
1059 // qualifier (half-word, byte).
1060 StringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
1062  size_t Next = Name.find('.');
1063 
1064  StringRef Mnemonic = Name;
1065 
1066  bool IsBRR = false;
1067  if (Name.endswith(".r")) {
1068  Mnemonic = Name.substr(0, Name.size() - 2);
1069  IsBRR = true;
1070  }
1071 
1072  // Match b?? and s?? (BR, BRR, and SCC instruction classes).
1073  if (Mnemonic[0] == 'b' ||
1074  (Mnemonic[0] == 's' && !Mnemonic.startswith("sel") &&
1075  !Mnemonic.startswith("st"))) {
1076  // Parse instructions with a conditional code. For example, 'bne' is
1077  // converted into two operands 'b' and 'ne'.
1079  LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next));
1080  if (CondCode != LPCC::UNKNOWN) {
1081  Mnemonic = Mnemonic.slice(0, 1);
1082  Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1083  Operands->push_back(LanaiOperand::createImm(
1084  MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1085  if (IsBRR) {
1086  Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1087  }
1088  return Mnemonic;
1089  }
1090  }
1091 
1092  // Parse other instructions with condition codes (RR instructions).
1093  // We ignore .f here and assume they are flag-setting operations, not
1094  // conditional codes (except for select instructions where flag-setting
1095  // variants are not yet implemented).
1096  if (Mnemonic.startswith("sel") ||
1097  (!Mnemonic.endswith(".f") && !Mnemonic.startswith("st"))) {
1099  if (CondCode != LPCC::UNKNOWN) {
1100  size_t Next = Mnemonic.rfind('.', Name.size());
1101  // 'sel' doesn't use a predicate operand whose printer adds the period,
1102  // but instead has the period as part of the identifier (i.e., 'sel.' is
1103  // expected by the generated matcher). If the mnemonic starts with 'sel'
1104  // then include the period as part of the mnemonic, else don't include it
1105  // as part of the mnemonic.
1106  if (Mnemonic.startswith("sel")) {
1107  Mnemonic = Mnemonic.substr(0, Next + 1);
1108  } else {
1109  Mnemonic = Mnemonic.substr(0, Next);
1110  }
1111  Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1112  Operands->push_back(LanaiOperand::createImm(
1113  MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1114  return Mnemonic;
1115  }
1116  }
1117 
1118  Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1119  if (IsBRR) {
1120  Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1121  }
1122 
1123  return Mnemonic;
1124 }
1125 
1127  // Detects if a memory operation has an erroneous base register modification.
1128  // Memory operations are detected by matching the types of operands.
1129  //
1130  // TODO: This test is focussed on one specific instance (ld/st).
1131  // Extend it to handle more cases or be more robust.
1132  bool Modifies = false;
1133 
1134  int Offset = 0;
1135 
1136  if (Operands.size() < 5)
1137  return false;
1138  else if (Operands[0]->isToken() && Operands[1]->isReg() &&
1139  Operands[2]->isImm() && Operands[3]->isImm() && Operands[4]->isReg())
1140  Offset = 0;
1141  else if (Operands[0]->isToken() && Operands[1]->isToken() &&
1142  Operands[2]->isReg() && Operands[3]->isImm() &&
1143  Operands[4]->isImm() && Operands[5]->isReg())
1144  Offset = 1;
1145  else
1146  return false;
1147 
1148  int PossibleAluOpIdx = Offset + 3;
1149  int PossibleBaseIdx = Offset + 1;
1150  int PossibleDestIdx = Offset + 4;
1151  if (LanaiOperand *PossibleAluOp =
1152  static_cast<LanaiOperand *>(Operands[PossibleAluOpIdx].get()))
1153  if (PossibleAluOp->isImm())
1154  if (const MCConstantExpr *ConstExpr =
1155  dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))
1156  Modifies = LPAC::modifiesOp(ConstExpr->getValue());
1157  return Modifies && Operands[PossibleBaseIdx]->isReg() &&
1158  Operands[PossibleDestIdx]->isReg() &&
1159  Operands[PossibleBaseIdx]->getReg() ==
1160  Operands[PossibleDestIdx]->getReg();
1161 }
1162 
1163 static bool IsRegister(const MCParsedAsmOperand &op) {
1164  return static_cast<const LanaiOperand &>(op).isReg();
1165 }
1166 
1168  if (Operands.size() < 4 || !IsRegister(*Operands[1]) ||
1169  !IsRegister(*Operands[2]))
1170  return false;
1171  return StringSwitch<bool>(
1172  static_cast<const LanaiOperand &>(*Operands[0]).getToken())
1173  .StartsWith("addc", true)
1174  .StartsWith("add", true)
1175  .StartsWith("and", true)
1176  .StartsWith("sh", true)
1177  .StartsWith("subb", true)
1178  .StartsWith("sub", true)
1179  .StartsWith("or", true)
1180  .StartsWith("xor", true)
1181  .Default(false);
1182 }
1183 
1184 bool LanaiAsmParser::ParseInstruction(ParseInstructionInfo & /*Info*/,
1185  StringRef Name, SMLoc NameLoc,
1187  // First operand is token for instruction
1188  StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);
1189 
1190  // If there are no more operands, then finish
1191  if (Lexer.is(AsmToken::EndOfStatement))
1192  return false;
1193 
1194  // Parse first operand
1195  if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success)
1196  return true;
1197 
1198  // If it is a st instruction with one 1 operand then it is a "store true".
1199  // Transform <"st"> to <"s">, <LPCC:ICC_T>
1200  if (Lexer.is(AsmToken::EndOfStatement) && Name == "st" &&
1201  Operands.size() == 2) {
1202  Operands.erase(Operands.begin(), Operands.begin() + 1);
1203  Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc));
1204  Operands.insert(Operands.begin() + 1,
1205  LanaiOperand::createImm(
1206  MCConstantExpr::create(LPCC::ICC_T, getContext()),
1207  NameLoc, NameLoc));
1208  }
1209 
1210  // If the instruction is a bt instruction with 1 operand (in assembly) then it
1211  // is an unconditional branch instruction and the first two elements of
1212  // operands need to be merged.
1213  if (Lexer.is(AsmToken::EndOfStatement) && Name.startswith("bt") &&
1214  Operands.size() == 3) {
1215  Operands.erase(Operands.begin(), Operands.begin() + 2);
1216  Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc));
1217  }
1218 
1219  // Parse until end of statement, consuming commas between operands
1220  while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.is(AsmToken::Comma)) {
1221  // Consume comma token
1222  Lex();
1223 
1224  // Parse next operand
1225  if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success)
1226  return true;
1227  }
1228 
1230  Error(Parser.getTok().getLoc(),
1231  "the destination register can't equal the base register in an "
1232  "instruction that modifies the base register.");
1233  return true;
1234  }
1235 
1236  // Insert always true operand for instruction that may be predicated but
1237  // are not. Currently the autogenerated parser always expects a predicate.
1239  Operands.insert(Operands.begin() + 1,
1240  LanaiOperand::createImm(
1241  MCConstantExpr::create(LPCC::ICC_T, getContext()),
1242  NameLoc, NameLoc));
1243  }
1244 
1245  return false;
1246 }
1247 
1248 #define GET_REGISTER_MATCHER
1249 #define GET_MATCHER_IMPLEMENTATION
1250 #include "LanaiGenAsmMatcher.inc"
1251 
1254 }
SizeForSuffix
static int SizeForSuffix(StringRef T)
Definition: LanaiAsmParser.cpp:841
llvm::MCSymbolRefExpr::getKind
VariantKind getKind() const
Definition: MCExpr.h:401
llvm::MCAsmParser
Generic assembler parser interface, for use by target specific assembly parsers.
Definition: MCAsmParser.h:124
MatchRegisterName
static unsigned MatchRegisterName(StringRef Name)
llvm::LPAC::ADD
@ ADD
Definition: LanaiAluCode.h:23
AluWithPrePost
static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp)
Definition: LanaiAsmParser.cpp:822
llvm::StringSwitch::StartsWith
StringSwitch & StartsWith(StringLiteral S, T Value)
Definition: StringSwitch.h:84
LanaiAluCode.h
MathExtras.h
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::MCSymbol
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
llvm::LPAC::AluCode
AluCode
Definition: LanaiAluCode.h:22
llvm::lltok::Error
@ Error
Definition: LLToken.h:21
llvm::MCOperand::createExpr
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:162
llvm::MCAsmLexer
Generic assembler lexer interface, for use by target specific assembly lexers.
Definition: MCAsmLexer.h:37
llvm::StringRef::rfind
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
Definition: StringRef.h:350
llvm::MCParsedAsmOperand
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
Definition: MCParsedAsmOperand.h:24
T
llvm::MCOperand::createImm
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
llvm::AsmToken::LBrac
@ LBrac
Definition: MCAsmMacro.h:48
StringRef.h
llvm::AsmToken::Dot
@ Dot
Definition: MCAsmMacro.h:49
llvm::AsmToken::EndOfStatement
@ EndOfStatement
Definition: MCAsmMacro.h:42
llvm::MCConstantExpr::create
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
op
#define op(i)
llvm::LanaiMCExpr
Definition: LanaiMCExpr.h:17
llvm::StringSwitch::EndsWith
StringSwitch & EndsWith(StringLiteral S, T Value)
Definition: StringSwitch.h:77
MCParsedAsmOperand.h
llvm::LPAC::modifiesOp
static bool modifiesOp(unsigned AluOp)
Definition: LanaiAluCode.h:72
ErrorHandling.h
llvm::X86Disassembler::Reg
Reg
All possible values of the reg field in the ModR/M byte.
Definition: X86DisassemblerDecoder.h:462
llvm::MemOp
Definition: TargetLowering.h:111
IsRegister
static bool IsRegister(const MCParsedAsmOperand &op)
Definition: LanaiAsmParser.cpp:1163
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::AsmToken::Integer
@ Integer
Definition: MCAsmMacro.h:32
LLVMInitializeLanaiAsmParser
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLanaiAsmParser()
Definition: LanaiAsmParser.cpp:1252
llvm::StringRef::substr
StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:564
addCallTargetOperands
static bool addCallTargetOperands(MachineInstrBuilder &CallInst, MachineIRBuilder &MIRBuilder, AMDGPUCallLowering::CallLoweringInfo &Info)
Definition: AMDGPUCallLowering.cpp:955
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:80
STLExtras.h
llvm::MCInst
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
RHS
Value * RHS
Definition: X86PartialReduction.cpp:76
llvm::MCBinaryExpr
Binary assembler expressions.
Definition: MCExpr.h:481
MCAsmParser.h
MCTargetAsmParser.h
MaybePredicatedInst
static bool MaybePredicatedInst(const OperandVector &Operands)
Definition: LanaiAsmParser.cpp:1167
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::AsmToken
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:21
isImm
static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
Definition: SPIRVInstructionSelector.cpp:1218
llvm::AsmToken::Minus
@ Minus
Definition: MCAsmMacro.h:45
llvm::AsmToken::LParen
@ LParen
Definition: MCAsmMacro.h:48
TOKEN
TOKEN(Invalid) TOKEN(Int) TOKEN(String) TOKEN(Identifier) SHORT_TOKEN(BlockBegin
llvm::MCStreamer
Streaming machine code generation interface.
Definition: MCStreamer.h:212
IsMemoryAssignmentError
static bool IsMemoryAssignmentError(const OperandVector &Operands)
Definition: LanaiAsmParser.cpp:1126
llvm::getTheLanaiTarget
Target & getTheLanaiTarget()
Definition: LanaiTargetInfo.cpp:14
llvm::RegisterMCAsmParser
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...
Definition: TargetRegistry.h:1398
llvm::MatchOperand_Success
@ MatchOperand_Success
Definition: MCTargetAsmParser.h:127
llvm::SMLoc
Represents a location in source code.
Definition: SMLoc.h:23
llvm::StringRef::startswith
bool startswith(StringRef Prefix) const
Definition: StringRef.h:260
getReg
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
Definition: MipsDisassembler.cpp:517
llvm::LanaiMCExpr::create
static const LanaiMCExpr * create(VariantKind Kind, const MCExpr *Expr, MCContext &Ctx)
Definition: LanaiMCExpr.cpp:17
llvm::LPCC::CondCode
CondCode
Definition: LanaiCondCode.h:10
MCContext.h
llvm::LanaiMCExpr::VK_Lanai_ABS_HI
@ VK_Lanai_ABS_HI
Definition: LanaiMCExpr.h:19
MCSymbol.h
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
LanaiCondCode.h
MCInst.h
llvm::MCConstantExpr::getValue
int64_t getValue() const
Definition: MCExpr.h:173
llvm::LPAC::makePreOp
static unsigned makePreOp(unsigned AluOp)
Definition: LanaiAluCode.h:62
MCSubtargetInfo.h
llvm::AsmToken::Star
@ Star
Definition: MCAsmMacro.h:49
SMLoc.h
Options
const char LLVMTargetMachineRef LLVMPassBuilderOptionsRef Options
Definition: PassBuilderBindings.cpp:48
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
llvm::AsmToken::Percent
@ Percent
Definition: MCAsmMacro.h:52
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
llvm::MCInst::addOperand
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
llvm::StringRef::slice
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition: StringRef.h:676
Operands
mir Rename Register Operands
Definition: MIRNamerPass.cpp:74
llvm::LPCC::suffixToLanaiCondCode
static CondCode suffixToLanaiCondCode(StringRef S)
Definition: LanaiCondCode.h:73
llvm::MCConstantExpr
Definition: MCExpr.h:144
MCAsmLexer.h
Node::getKind
Kind getKind() const
Definition: ItaniumDemangle.h:249
llvm::AMDGPU::Hwreg::Offset
Offset
Definition: SIDefines.h:416
llvm::ParseInstructionInfo
Definition: MCTargetAsmParser.h:118
llvm::LanaiMCExpr::getKind
VariantKind getKind() const
Definition: LanaiMCExpr.h:33
uint64_t
LanaiTargetInfo.h
LLVM_EXTERNAL_VISIBILITY
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:127
shouldBeSls
bool shouldBeSls(const LanaiOperand &Op)
Definition: LanaiAsmParser.cpp:867
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::MCStreamer::emitInstruction
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Definition: MCStreamer.cpp:1096
llvm::MatchOperand_ParseFail
@ MatchOperand_ParseFail
Definition: MCTargetAsmParser.h:129
TemplateParamKind::Type
@ Type
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::ISD::CondCode
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
Definition: ISDOpcodes.h:1424
BinaryExpr
Definition: ItaniumDemangle.h:1697
llvm::ErrorInfo
Base class for user error types.
Definition: Error.h:347
llvm::MCTargetOptions
Definition: MCTargetOptions.h:37
llvm::MCSymbolRefExpr
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
isReg
static bool isReg(const MCInst &MI, unsigned OpNo)
Definition: MipsInstPrinter.cpp:31
llvm::AsmToken::Comma
@ Comma
Definition: MCAsmMacro.h:49
llvm::print
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr)
Definition: GCNRegPressure.cpp:138
llvm::MCBinaryExpr::createAdd
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:525
llvm::LPAC::makePostOp
static unsigned makePostOp(unsigned AluOp)
Definition: LanaiAluCode.h:67
llvm::MatchOperand_NoMatch
@ MatchOperand_NoMatch
Definition: MCTargetAsmParser.h:128
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::AsmToken::Plus
@ Plus
Definition: MCAsmMacro.h:45
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
llvm::MCOperand::createReg
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
llvm::AsmToken::RParen
@ RParen
Definition: MCAsmMacro.h:48
llvm::LPCC::UNKNOWN
@ UNKNOWN
Definition: LanaiCondCode.h:31
llvm::OperandMatchResultTy
OperandMatchResultTy
Definition: MCTargetAsmParser.h:126
llvm::LPAC::UNKNOWN
@ UNKNOWN
Definition: LanaiAluCode.h:40
llvm::LanaiMCExpr::VariantKind
VariantKind
Definition: LanaiMCExpr.h:19
llvm::MCInstrInfo
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
llvm::AsmToken::Identifier
@ Identifier
Definition: MCAsmMacro.h:28
get
Should compile to something r4 addze r3 instead we get
Definition: README.txt:24
llvm::LanaiMCExpr::VK_Lanai_None
@ VK_Lanai_None
Definition: LanaiMCExpr.h:19
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:348
llvm::StringRef::endswith
bool endswith(StringRef Suffix) const
Definition: StringRef.h:276
Casting.h
llvm::LPAC::stringToLanaiAluCode
static AluCode stringToLanaiAluCode(StringRef S)
Definition: LanaiAluCode.h:103
llvm::AsmToken::RBrac
@ RBrac
Definition: MCAsmMacro.h:48
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
x
TODO unsigned x
Definition: README.txt:10
llvm::MCInst::getOpcode
unsigned getOpcode() const
Definition: MCInst.h:198
llvm::MCTargetAsmParser
MCTargetAsmParser - Generic interface to target specific assembly parsers.
Definition: MCTargetAsmParser.h:314
parseImmediate
bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef< uint8_t > Bytes)
Definition: WebAssemblyDisassembler.cpp:109
llvm::object::Identifier
@ Identifier
Definition: COFFModuleDefinition.cpp:34
llvm::MCSymbolRefExpr::create
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:386
StringSwitch.h
llvm::RISCVMatInt::Imm
@ Imm
Definition: RISCVMatInt.h:23
N
#define N
MCStreamer.h
llvm::isMem
static bool isMem(const MachineInstr &MI, unsigned Op)
Definition: X86InstrInfo.h:131
LanaiMCExpr.h
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
llvm::SMLoc::getFromPointer
static SMLoc getFromPointer(const char *Ptr)
Definition: SMLoc.h:36
llvm::StringSwitch::Default
R Default(T Value)
Definition: StringSwitch.h:183
llvm::StringSwitch
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:45
llvm::MCSymbolRefExpr::VK_None
@ VK_None
Definition: MCExpr.h:195
LanaiInstrInfo.h
llvm::LPCC::ICC_T
@ ICC_T
Definition: LanaiCondCode.h:11
raw_ostream.h
llvm::AsmToken::getLoc
SMLoc getLoc() const
Definition: MCAsmLexer.cpp:26
llvm::AsmToken::getEndLoc
SMLoc getEndLoc() const
Definition: MCAsmLexer.cpp:30
TargetRegistry.h
MCExpr.h
llvm::MCSubtargetInfo
Generic base class for all target subtargets.
Definition: MCSubtargetInfo.h:76
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::MCExpr
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
llvm::LanaiMCExpr::VK_Lanai_ABS_LO
@ VK_Lanai_ABS_LO
Definition: LanaiMCExpr.h:19