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"
12 #include "MCTargetDesc/LanaiMCExpr.h"
13 #include "TargetInfo/LanaiTargetInfo.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"
20 #include "llvm/MC/MCParser/MCAsmLexer.h"
21 #include "llvm/MC/MCParser/MCAsmParser.h"
22 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
23 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
24 #include "llvm/MC/MCStreamer.h"
25 #include "llvm/MC/MCSubtargetInfo.h"
26 #include "llvm/MC/MCSymbol.h"
27 #include "llvm/MC/TargetRegistry.h"
28 #include "llvm/Support/Casting.h"
29 #include "llvm/Support/ErrorHandling.h"
30 #include "llvm/Support/MathExtras.h"
31 #include "llvm/Support/SMLoc.h"
32 #include "llvm/Support/raw_ostream.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,
61                           OperandVector *Operands);
62 
63   bool parsePrePost(StringRef Type, int *OffsetValue);
64 
65   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
66                         SMLoc NameLoc, OperandVector &Operands) override;
67 
68   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
69   ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
70                                SMLoc &EndLoc) override;
71 
72   bool MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
73                                OperandVector &Operands, MCStreamer &Out,
74                                uint64_t &ErrorInfo,
75                                bool MatchingInlineAsm) override;
76 
77 // Auto-generated instruction matching functions
78 #define GET_ASSEMBLER_HEADER
79 #include "LanaiGenAsmMatcher.inc"
80 
81   ParseStatus parseOperand(OperandVector *Operands, StringRef Mnemonic);
82 
83   ParseStatus parseMemoryOperand(OperandVector &Operands);
84 
85 public:
LanaiAsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)86   LanaiAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
87                  const MCInstrInfo &MII, const MCTargetOptions &Options)
88       : MCTargetAsmParser(Options, STI, MII), Parser(Parser),
89         Lexer(Parser.getLexer()), SubtargetInfo(STI) {
90     setAvailableFeatures(
91         ComputeAvailableFeatures(SubtargetInfo.getFeatureBits()));
92   }
93 
94 private:
95   MCAsmParser &Parser;
96   MCAsmLexer &Lexer;
97 
98   const MCSubtargetInfo &SubtargetInfo;
99 };
100 
101 // LanaiOperand - Instances of this class represented a parsed machine
102 // instruction
103 struct LanaiOperand : public MCParsedAsmOperand {
104   enum KindTy {
105     TOKEN,
106     REGISTER,
107     IMMEDIATE,
108     MEMORY_IMM,
109     MEMORY_REG_IMM,
110     MEMORY_REG_REG,
111   } Kind;
112 
113   SMLoc StartLoc, EndLoc;
114 
115   struct Token {
116     const char *Data;
117     unsigned Length;
118   };
119 
120   struct RegOp {
121     unsigned RegNum;
122   };
123 
124   struct ImmOp {
125     const MCExpr *Value;
126   };
127 
128   struct MemOp {
129     unsigned BaseReg;
130     unsigned OffsetReg;
131     unsigned AluOp;
132     const MCExpr *Offset;
133   };
134 
135   union {
136     struct Token Tok;
137     struct RegOp Reg;
138     struct ImmOp Imm;
139     struct MemOp Mem;
140   };
141 
LanaiOperand__anonf75f2c320111::LanaiOperand142   explicit LanaiOperand(KindTy Kind) : Kind(Kind) {}
143 
144 public:
145   // The functions below are used by the autogenerated ASM matcher and hence to
146   // be of the form expected.
147 
148   // getStartLoc - Gets location of the first token of this operand
getStartLoc__anonf75f2c320111::LanaiOperand149   SMLoc getStartLoc() const override { return StartLoc; }
150 
151   // getEndLoc - Gets location of the last token of this operand
getEndLoc__anonf75f2c320111::LanaiOperand152   SMLoc getEndLoc() const override { return EndLoc; }
153 
getReg__anonf75f2c320111::LanaiOperand154   unsigned getReg() const override {
155     assert(isReg() && "Invalid type access!");
156     return Reg.RegNum;
157   }
158 
getImm__anonf75f2c320111::LanaiOperand159   const MCExpr *getImm() const {
160     assert(isImm() && "Invalid type access!");
161     return Imm.Value;
162   }
163 
getToken__anonf75f2c320111::LanaiOperand164   StringRef getToken() const {
165     assert(isToken() && "Invalid type access!");
166     return StringRef(Tok.Data, Tok.Length);
167   }
168 
getMemBaseReg__anonf75f2c320111::LanaiOperand169   unsigned getMemBaseReg() const {
170     assert(isMem() && "Invalid type access!");
171     return Mem.BaseReg;
172   }
173 
getMemOffsetReg__anonf75f2c320111::LanaiOperand174   unsigned getMemOffsetReg() const {
175     assert(isMem() && "Invalid type access!");
176     return Mem.OffsetReg;
177   }
178 
getMemOffset__anonf75f2c320111::LanaiOperand179   const MCExpr *getMemOffset() const {
180     assert(isMem() && "Invalid type access!");
181     return Mem.Offset;
182   }
183 
getMemOp__anonf75f2c320111::LanaiOperand184   unsigned getMemOp() const {
185     assert(isMem() && "Invalid type access!");
186     return Mem.AluOp;
187   }
188 
189   // Functions for testing operand type
isReg__anonf75f2c320111::LanaiOperand190   bool isReg() const override { return Kind == REGISTER; }
191 
isImm__anonf75f2c320111::LanaiOperand192   bool isImm() const override { return Kind == IMMEDIATE; }
193 
isMem__anonf75f2c320111::LanaiOperand194   bool isMem() const override {
195     return isMemImm() || isMemRegImm() || isMemRegReg();
196   }
197 
isMemImm__anonf75f2c320111::LanaiOperand198   bool isMemImm() const { return Kind == MEMORY_IMM; }
199 
isMemRegImm__anonf75f2c320111::LanaiOperand200   bool isMemRegImm() const { return Kind == MEMORY_REG_IMM; }
201 
isMemRegReg__anonf75f2c320111::LanaiOperand202   bool isMemRegReg() const { return Kind == MEMORY_REG_REG; }
203 
isMemSpls__anonf75f2c320111::LanaiOperand204   bool isMemSpls() const { return isMemRegImm() || isMemRegReg(); }
205 
isToken__anonf75f2c320111::LanaiOperand206   bool isToken() const override { return Kind == TOKEN; }
207 
isBrImm__anonf75f2c320111::LanaiOperand208   bool isBrImm() {
209     if (!isImm())
210       return false;
211 
212     // Constant case
213     const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm.Value);
214     if (!MCE)
215       return true;
216     int64_t Value = MCE->getValue();
217     // Check if value fits in 25 bits with 2 least significant bits 0.
218     return isShiftedUInt<23, 2>(static_cast<int32_t>(Value));
219   }
220 
isBrTarget__anonf75f2c320111::LanaiOperand221   bool isBrTarget() { return isBrImm() || isToken(); }
222 
isCallTarget__anonf75f2c320111::LanaiOperand223   bool isCallTarget() { return isImm() || isToken(); }
224 
isHiImm16__anonf75f2c320111::LanaiOperand225   bool isHiImm16() {
226     if (!isImm())
227       return false;
228 
229     // Constant case
230     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
231       int64_t Value = ConstExpr->getValue();
232       return Value != 0 && isShiftedUInt<16, 16>(Value);
233     }
234 
235     // Symbolic reference expression
236     if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
237       return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
238 
239     // Binary expression
240     if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
241       if (const LanaiMCExpr *SymbolRefExpr =
242               dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
243         return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
244 
245     return false;
246   }
247 
isHiImm16And__anonf75f2c320111::LanaiOperand248   bool isHiImm16And() {
249     if (!isImm())
250       return false;
251 
252     const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
253     if (ConstExpr) {
254       int64_t Value = ConstExpr->getValue();
255       // Check if in the form 0xXYZWffff
256       return (Value != 0) && ((Value & ~0xffff0000) == 0xffff);
257     }
258     return false;
259   }
260 
isLoImm16__anonf75f2c320111::LanaiOperand261   bool isLoImm16() {
262     if (!isImm())
263       return false;
264 
265     // Constant case
266     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
267       int64_t Value = ConstExpr->getValue();
268       // Check if value fits in 16 bits
269       return isUInt<16>(static_cast<int32_t>(Value));
270     }
271 
272     // Symbolic reference expression
273     if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
274       return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
275 
276     // Binary expression
277     if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
278       if (const LanaiMCExpr *SymbolRefExpr =
279               dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
280         return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
281 
282     return false;
283   }
284 
isLoImm16Signed__anonf75f2c320111::LanaiOperand285   bool isLoImm16Signed() {
286     if (!isImm())
287       return false;
288 
289     // Constant case
290     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
291       int64_t Value = ConstExpr->getValue();
292       // Check if value fits in 16 bits or value of the form 0xffffxyzw
293       return isInt<16>(static_cast<int32_t>(Value));
294     }
295 
296     // Symbolic reference expression
297     if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
298       return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
299 
300     // Binary expression
301     if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
302       if (const LanaiMCExpr *SymbolRefExpr =
303               dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
304         return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
305 
306     return false;
307   }
308 
isLoImm16And__anonf75f2c320111::LanaiOperand309   bool isLoImm16And() {
310     if (!isImm())
311       return false;
312 
313     const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
314     if (ConstExpr) {
315       int64_t Value = ConstExpr->getValue();
316       // Check if in the form 0xffffXYZW
317       return ((Value & ~0xffff) == 0xffff0000);
318     }
319     return false;
320   }
321 
isImmShift__anonf75f2c320111::LanaiOperand322   bool isImmShift() {
323     if (!isImm())
324       return false;
325 
326     const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
327     if (!ConstExpr)
328       return false;
329     int64_t Value = ConstExpr->getValue();
330     return (Value >= -31) && (Value <= 31);
331   }
332 
isLoImm21__anonf75f2c320111::LanaiOperand333   bool isLoImm21() {
334     if (!isImm())
335       return false;
336 
337     // Constant case
338     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
339       int64_t Value = ConstExpr->getValue();
340       return isUInt<21>(Value);
341     }
342 
343     // Symbolic reference expression
344     if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
345       return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
346     if (const MCSymbolRefExpr *SymbolRefExpr =
347             dyn_cast<MCSymbolRefExpr>(Imm.Value)) {
348       return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
349     }
350 
351     // Binary expression
352     if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) {
353       if (const LanaiMCExpr *SymbolRefExpr =
354               dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
355         return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
356       if (const MCSymbolRefExpr *SymbolRefExpr =
357               dyn_cast<MCSymbolRefExpr>(BinaryExpr->getLHS()))
358         return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
359     }
360 
361     return false;
362   }
363 
isImm10__anonf75f2c320111::LanaiOperand364   bool isImm10() {
365     if (!isImm())
366       return false;
367 
368     const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
369     if (!ConstExpr)
370       return false;
371     int64_t Value = ConstExpr->getValue();
372     return isInt<10>(Value);
373   }
374 
isCondCode__anonf75f2c320111::LanaiOperand375   bool isCondCode() {
376     if (!isImm())
377       return false;
378 
379     const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
380     if (!ConstExpr)
381       return false;
382     uint64_t Value = ConstExpr->getValue();
383     // The condition codes are between 0 (ICC_T) and 15 (ICC_LE). If the
384     // unsigned value of the immediate is less than LPCC::UNKNOWN (16) then
385     // value corresponds to a valid condition code.
386     return Value < LPCC::UNKNOWN;
387   }
388 
addExpr__anonf75f2c320111::LanaiOperand389   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
390     // Add as immediates where possible. Null MCExpr = 0
391     if (Expr == nullptr)
392       Inst.addOperand(MCOperand::createImm(0));
393     else if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Expr))
394       Inst.addOperand(
395           MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
396     else
397       Inst.addOperand(MCOperand::createExpr(Expr));
398   }
399 
addRegOperands__anonf75f2c320111::LanaiOperand400   void addRegOperands(MCInst &Inst, unsigned N) const {
401     assert(N == 1 && "Invalid number of operands!");
402     Inst.addOperand(MCOperand::createReg(getReg()));
403   }
404 
addImmOperands__anonf75f2c320111::LanaiOperand405   void addImmOperands(MCInst &Inst, unsigned N) const {
406     assert(N == 1 && "Invalid number of operands!");
407     addExpr(Inst, getImm());
408   }
409 
addBrTargetOperands__anonf75f2c320111::LanaiOperand410   void addBrTargetOperands(MCInst &Inst, unsigned N) const {
411     assert(N == 1 && "Invalid number of operands!");
412     addExpr(Inst, getImm());
413   }
414 
addCallTargetOperands__anonf75f2c320111::LanaiOperand415   void addCallTargetOperands(MCInst &Inst, unsigned N) const {
416     assert(N == 1 && "Invalid number of operands!");
417     addExpr(Inst, getImm());
418   }
419 
addCondCodeOperands__anonf75f2c320111::LanaiOperand420   void addCondCodeOperands(MCInst &Inst, unsigned N) const {
421     assert(N == 1 && "Invalid number of operands!");
422     addExpr(Inst, getImm());
423   }
424 
addMemImmOperands__anonf75f2c320111::LanaiOperand425   void addMemImmOperands(MCInst &Inst, unsigned N) const {
426     assert(N == 1 && "Invalid number of operands!");
427     const MCExpr *Expr = getMemOffset();
428     addExpr(Inst, Expr);
429   }
430 
addMemRegImmOperands__anonf75f2c320111::LanaiOperand431   void addMemRegImmOperands(MCInst &Inst, unsigned N) const {
432     assert(N == 3 && "Invalid number of operands!");
433     Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
434     const MCExpr *Expr = getMemOffset();
435     addExpr(Inst, Expr);
436     Inst.addOperand(MCOperand::createImm(getMemOp()));
437   }
438 
addMemRegRegOperands__anonf75f2c320111::LanaiOperand439   void addMemRegRegOperands(MCInst &Inst, unsigned N) const {
440     assert(N == 3 && "Invalid number of operands!");
441     Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
442     assert(getMemOffsetReg() != 0 && "Invalid offset");
443     Inst.addOperand(MCOperand::createReg(getMemOffsetReg()));
444     Inst.addOperand(MCOperand::createImm(getMemOp()));
445   }
446 
addMemSplsOperands__anonf75f2c320111::LanaiOperand447   void addMemSplsOperands(MCInst &Inst, unsigned N) const {
448     if (isMemRegImm())
449       addMemRegImmOperands(Inst, N);
450     if (isMemRegReg())
451       addMemRegRegOperands(Inst, N);
452   }
453 
addImmShiftOperands__anonf75f2c320111::LanaiOperand454   void addImmShiftOperands(MCInst &Inst, unsigned N) const {
455     assert(N == 1 && "Invalid number of operands!");
456     addExpr(Inst, getImm());
457   }
458 
addImm10Operands__anonf75f2c320111::LanaiOperand459   void addImm10Operands(MCInst &Inst, unsigned N) const {
460     assert(N == 1 && "Invalid number of operands!");
461     addExpr(Inst, getImm());
462   }
463 
addLoImm16Operands__anonf75f2c320111::LanaiOperand464   void addLoImm16Operands(MCInst &Inst, unsigned N) const {
465     assert(N == 1 && "Invalid number of operands!");
466     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
467       Inst.addOperand(
468           MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
469     else if (isa<LanaiMCExpr>(getImm())) {
470 #ifndef NDEBUG
471       const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
472       assert(SymbolRefExpr &&
473              SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO);
474 #endif
475       Inst.addOperand(MCOperand::createExpr(getImm()));
476     } else if (isa<MCBinaryExpr>(getImm())) {
477 #ifndef NDEBUG
478       const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
479       assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
480              cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
481                  LanaiMCExpr::VK_Lanai_ABS_LO);
482 #endif
483       Inst.addOperand(MCOperand::createExpr(getImm()));
484     } else
485       assert(false && "Operand type not supported.");
486   }
487 
addLoImm16AndOperands__anonf75f2c320111::LanaiOperand488   void addLoImm16AndOperands(MCInst &Inst, unsigned N) const {
489     assert(N == 1 && "Invalid number of operands!");
490     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
491       Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff));
492     else
493       assert(false && "Operand type not supported.");
494   }
495 
addHiImm16Operands__anonf75f2c320111::LanaiOperand496   void addHiImm16Operands(MCInst &Inst, unsigned N) const {
497     assert(N == 1 && "Invalid number of operands!");
498     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
499       Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
500     else if (isa<LanaiMCExpr>(getImm())) {
501 #ifndef NDEBUG
502       const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
503       assert(SymbolRefExpr &&
504              SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI);
505 #endif
506       Inst.addOperand(MCOperand::createExpr(getImm()));
507     } else if (isa<MCBinaryExpr>(getImm())) {
508 #ifndef NDEBUG
509       const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
510       assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
511              cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
512                  LanaiMCExpr::VK_Lanai_ABS_HI);
513 #endif
514       Inst.addOperand(MCOperand::createExpr(getImm()));
515     } else
516       assert(false && "Operand type not supported.");
517   }
518 
addHiImm16AndOperands__anonf75f2c320111::LanaiOperand519   void addHiImm16AndOperands(MCInst &Inst, unsigned N) const {
520     assert(N == 1 && "Invalid number of operands!");
521     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
522       Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
523     else
524       assert(false && "Operand type not supported.");
525   }
526 
addLoImm21Operands__anonf75f2c320111::LanaiOperand527   void addLoImm21Operands(MCInst &Inst, unsigned N) const {
528     assert(N == 1 && "Invalid number of operands!");
529     if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
530       Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff));
531     else if (isa<LanaiMCExpr>(getImm())) {
532 #ifndef NDEBUG
533       const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
534       assert(SymbolRefExpr &&
535              SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
536 #endif
537       Inst.addOperand(MCOperand::createExpr(getImm()));
538     } else if (isa<MCSymbolRefExpr>(getImm())) {
539 #ifndef NDEBUG
540       const MCSymbolRefExpr *SymbolRefExpr =
541           dyn_cast<MCSymbolRefExpr>(getImm());
542       assert(SymbolRefExpr &&
543              SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None);
544 #endif
545       Inst.addOperand(MCOperand::createExpr(getImm()));
546     } else if (isa<MCBinaryExpr>(getImm())) {
547 #ifndef NDEBUG
548       const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
549       assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
550              cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
551                  LanaiMCExpr::VK_Lanai_None);
552 #endif
553       Inst.addOperand(MCOperand::createExpr(getImm()));
554     } else
555       assert(false && "Operand type not supported.");
556   }
557 
print__anonf75f2c320111::LanaiOperand558   void print(raw_ostream &OS) const override {
559     switch (Kind) {
560     case IMMEDIATE:
561       OS << "Imm: " << getImm() << "\n";
562       break;
563     case TOKEN:
564       OS << "Token: " << getToken() << "\n";
565       break;
566     case REGISTER:
567       OS << "Reg: %r" << getReg() << "\n";
568       break;
569     case MEMORY_IMM:
570       OS << "MemImm: " << *getMemOffset() << "\n";
571       break;
572     case MEMORY_REG_IMM:
573       OS << "MemRegImm: " << getMemBaseReg() << "+" << *getMemOffset() << "\n";
574       break;
575     case MEMORY_REG_REG:
576       assert(getMemOffset() == nullptr);
577       OS << "MemRegReg: " << getMemBaseReg() << "+"
578          << "%r" << getMemOffsetReg() << "\n";
579       break;
580     }
581   }
582 
CreateToken__anonf75f2c320111::LanaiOperand583   static std::unique_ptr<LanaiOperand> CreateToken(StringRef Str, SMLoc Start) {
584     auto Op = std::make_unique<LanaiOperand>(TOKEN);
585     Op->Tok.Data = Str.data();
586     Op->Tok.Length = Str.size();
587     Op->StartLoc = Start;
588     Op->EndLoc = Start;
589     return Op;
590   }
591 
createReg__anonf75f2c320111::LanaiOperand592   static std::unique_ptr<LanaiOperand> createReg(unsigned RegNum, SMLoc Start,
593                                                  SMLoc End) {
594     auto Op = std::make_unique<LanaiOperand>(REGISTER);
595     Op->Reg.RegNum = RegNum;
596     Op->StartLoc = Start;
597     Op->EndLoc = End;
598     return Op;
599   }
600 
createImm__anonf75f2c320111::LanaiOperand601   static std::unique_ptr<LanaiOperand> createImm(const MCExpr *Value,
602                                                  SMLoc Start, SMLoc End) {
603     auto Op = std::make_unique<LanaiOperand>(IMMEDIATE);
604     Op->Imm.Value = Value;
605     Op->StartLoc = Start;
606     Op->EndLoc = End;
607     return Op;
608   }
609 
610   static std::unique_ptr<LanaiOperand>
MorphToMemImm__anonf75f2c320111::LanaiOperand611   MorphToMemImm(std::unique_ptr<LanaiOperand> Op) {
612     const MCExpr *Imm = Op->getImm();
613     Op->Kind = MEMORY_IMM;
614     Op->Mem.BaseReg = 0;
615     Op->Mem.AluOp = LPAC::ADD;
616     Op->Mem.OffsetReg = 0;
617     Op->Mem.Offset = Imm;
618     return Op;
619   }
620 
621   static std::unique_ptr<LanaiOperand>
MorphToMemRegReg__anonf75f2c320111::LanaiOperand622   MorphToMemRegReg(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
623                    unsigned AluOp) {
624     unsigned OffsetReg = Op->getReg();
625     Op->Kind = MEMORY_REG_REG;
626     Op->Mem.BaseReg = BaseReg;
627     Op->Mem.AluOp = AluOp;
628     Op->Mem.OffsetReg = OffsetReg;
629     Op->Mem.Offset = nullptr;
630     return Op;
631   }
632 
633   static std::unique_ptr<LanaiOperand>
MorphToMemRegImm__anonf75f2c320111::LanaiOperand634   MorphToMemRegImm(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
635                    unsigned AluOp) {
636     const MCExpr *Imm = Op->getImm();
637     Op->Kind = MEMORY_REG_IMM;
638     Op->Mem.BaseReg = BaseReg;
639     Op->Mem.AluOp = AluOp;
640     Op->Mem.OffsetReg = 0;
641     Op->Mem.Offset = Imm;
642     return Op;
643   }
644 };
645 
646 } // end anonymous namespace
647 
MatchAndEmitInstruction(SMLoc IdLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)648 bool LanaiAsmParser::MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
649                                              OperandVector &Operands,
650                                              MCStreamer &Out,
651                                              uint64_t &ErrorInfo,
652                                              bool MatchingInlineAsm) {
653   MCInst Inst;
654   SMLoc ErrorLoc;
655 
656   switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
657   case Match_Success:
658     Out.emitInstruction(Inst, SubtargetInfo);
659     Opcode = Inst.getOpcode();
660     return false;
661   case Match_MissingFeature:
662     return Error(IdLoc, "Instruction use requires option to be enabled");
663   case Match_MnemonicFail:
664     return Error(IdLoc, "Unrecognized instruction mnemonic");
665   case Match_InvalidOperand: {
666     ErrorLoc = IdLoc;
667     if (ErrorInfo != ~0U) {
668       if (ErrorInfo >= Operands.size())
669         return Error(IdLoc, "Too few operands for instruction");
670 
671       ErrorLoc = ((LanaiOperand &)*Operands[ErrorInfo]).getStartLoc();
672       if (ErrorLoc == SMLoc())
673         ErrorLoc = IdLoc;
674     }
675     return Error(ErrorLoc, "Invalid operand for instruction");
676   }
677   default:
678     break;
679   }
680 
681   llvm_unreachable("Unknown match type detected!");
682 }
683 
684 // Both '%rN' and 'rN' are parsed as valid registers. This was done to remain
685 // backwards compatible with GCC and the different ways inline assembly is
686 // handled.
687 // TODO: see if there isn't a better way to do this.
688 std::unique_ptr<LanaiOperand>
parseRegister(bool RestoreOnFailure)689 LanaiAsmParser::parseRegister(bool RestoreOnFailure) {
690   SMLoc Start = Parser.getTok().getLoc();
691   SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
692   std::optional<AsmToken> PercentTok;
693 
694   unsigned RegNum;
695   // Eat the '%'.
696   if (Lexer.getKind() == AsmToken::Percent) {
697     PercentTok = Parser.getTok();
698     Parser.Lex();
699   }
700   if (Lexer.getKind() == AsmToken::Identifier) {
701     RegNum = MatchRegisterName(Lexer.getTok().getIdentifier());
702     if (RegNum == 0) {
703       if (PercentTok && RestoreOnFailure)
704         Lexer.UnLex(*PercentTok);
705       return nullptr;
706     }
707     Parser.Lex(); // Eat identifier token
708     return LanaiOperand::createReg(RegNum, Start, End);
709   }
710   if (PercentTok && RestoreOnFailure)
711     Lexer.UnLex(*PercentTok);
712   return nullptr;
713 }
714 
parseRegister(MCRegister & RegNum,SMLoc & StartLoc,SMLoc & EndLoc)715 bool LanaiAsmParser::parseRegister(MCRegister &RegNum, SMLoc &StartLoc,
716                                    SMLoc &EndLoc) {
717   const AsmToken &Tok = getParser().getTok();
718   StartLoc = Tok.getLoc();
719   EndLoc = Tok.getEndLoc();
720   std::unique_ptr<LanaiOperand> Op = parseRegister(/*RestoreOnFailure=*/false);
721   if (Op != nullptr)
722     RegNum = Op->getReg();
723   return (Op == nullptr);
724 }
725 
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)726 ParseStatus LanaiAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
727                                              SMLoc &EndLoc) {
728   const AsmToken &Tok = getParser().getTok();
729   StartLoc = Tok.getLoc();
730   EndLoc = Tok.getEndLoc();
731   std::unique_ptr<LanaiOperand> Op = parseRegister(/*RestoreOnFailure=*/true);
732   if (Op == nullptr)
733     return ParseStatus::NoMatch;
734   Reg = Op->getReg();
735   return ParseStatus::Success;
736 }
737 
parseIdentifier()738 std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {
739   SMLoc Start = Parser.getTok().getLoc();
740   SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
741   const MCExpr *Res, *RHS = nullptr;
742   LanaiMCExpr::VariantKind Kind = LanaiMCExpr::VK_Lanai_None;
743 
744   if (Lexer.getKind() != AsmToken::Identifier)
745     return nullptr;
746 
747   StringRef Identifier;
748   if (Parser.parseIdentifier(Identifier))
749     return nullptr;
750 
751   // Check if identifier has a modifier
752   if (Identifier.equals_insensitive("hi"))
753     Kind = LanaiMCExpr::VK_Lanai_ABS_HI;
754   else if (Identifier.equals_insensitive("lo"))
755     Kind = LanaiMCExpr::VK_Lanai_ABS_LO;
756 
757   // If the identifier corresponds to a variant then extract the real
758   // identifier.
759   if (Kind != LanaiMCExpr::VK_Lanai_None) {
760     if (Lexer.getKind() != AsmToken::LParen) {
761       Error(Lexer.getLoc(), "Expected '('");
762       return nullptr;
763     }
764     Lexer.Lex(); // lex '('
765 
766     // Parse identifier
767     if (Parser.parseIdentifier(Identifier))
768       return nullptr;
769   }
770 
771   // If addition parse the RHS.
772   if (Lexer.getKind() == AsmToken::Plus && Parser.parseExpression(RHS))
773     return nullptr;
774 
775   // For variants parse the final ')'
776   if (Kind != LanaiMCExpr::VK_Lanai_None) {
777     if (Lexer.getKind() != AsmToken::RParen) {
778       Error(Lexer.getLoc(), "Expected ')'");
779       return nullptr;
780     }
781     Lexer.Lex(); // lex ')'
782   }
783 
784   End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
785   MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
786   const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
787   Res = LanaiMCExpr::create(Kind, Expr, getContext());
788 
789   // Nest if this was an addition
790   if (RHS)
791     Res = MCBinaryExpr::createAdd(Res, RHS, getContext());
792 
793   return LanaiOperand::createImm(Res, Start, End);
794 }
795 
parseImmediate()796 std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {
797   SMLoc Start = Parser.getTok().getLoc();
798   SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
799 
800   const MCExpr *ExprVal;
801   switch (Lexer.getKind()) {
802   case AsmToken::Identifier:
803     return parseIdentifier();
804   case AsmToken::Plus:
805   case AsmToken::Minus:
806   case AsmToken::Integer:
807   case AsmToken::Dot:
808     if (!Parser.parseExpression(ExprVal))
809       return LanaiOperand::createImm(ExprVal, Start, End);
810     [[fallthrough]];
811   default:
812     return nullptr;
813   }
814 }
815 
AluWithPrePost(unsigned AluCode,bool PreOp,bool PostOp)816 static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) {
817   if (PreOp)
818     return LPAC::makePreOp(AluCode);
819   if (PostOp)
820     return LPAC::makePostOp(AluCode);
821   return AluCode;
822 }
823 
parseAluOperator(bool PreOp,bool PostOp)824 unsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) {
825   StringRef IdString;
826   Parser.parseIdentifier(IdString);
827   unsigned AluCode = LPAC::stringToLanaiAluCode(IdString);
828   if (AluCode == LPAC::UNKNOWN) {
829     Error(Parser.getTok().getLoc(), "Can't parse ALU operator");
830     return 0;
831   }
832   return AluCode;
833 }
834 
SizeForSuffix(StringRef T)835 static int SizeForSuffix(StringRef T) {
836   return StringSwitch<int>(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4);
837 }
838 
parsePrePost(StringRef Type,int * OffsetValue)839 bool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) {
840   bool PreOrPost = false;
841   if (Lexer.getKind() == Lexer.peekTok(true).getKind()) {
842     PreOrPost = true;
843     if (Lexer.is(AsmToken::Minus))
844       *OffsetValue = -SizeForSuffix(Type);
845     else if (Lexer.is(AsmToken::Plus))
846       *OffsetValue = SizeForSuffix(Type);
847     else
848       return false;
849 
850     // Eat the '-' '-' or '+' '+'
851     Parser.Lex();
852     Parser.Lex();
853   } else if (Lexer.is(AsmToken::Star)) {
854     Parser.Lex(); // Eat the '*'
855     PreOrPost = true;
856   }
857 
858   return PreOrPost;
859 }
860 
shouldBeSls(const LanaiOperand & Op)861 bool shouldBeSls(const LanaiOperand &Op) {
862   // The instruction should be encoded as an SLS if the constant is word
863   // aligned and will fit in 21 bits
864   if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm())) {
865     int64_t Value = ConstExpr->getValue();
866     return (Value % 4 == 0) && (Value >= 0) && (Value <= 0x1fffff);
867   }
868   // The instruction should be encoded as an SLS if the operand is a symbolic
869   // reference with no variant.
870   if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Op.getImm()))
871     return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
872   // The instruction should be encoded as an SLS if the operand is a binary
873   // expression with the left-hand side being a symbolic reference with no
874   // variant.
875   if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Op.getImm())) {
876     const LanaiMCExpr *LHSSymbolRefExpr =
877         dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
878     return (LHSSymbolRefExpr &&
879             LHSSymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
880   }
881   return false;
882 }
883 
884 // Matches memory operand. Returns true if error encountered.
parseMemoryOperand(OperandVector & Operands)885 ParseStatus LanaiAsmParser::parseMemoryOperand(OperandVector &Operands) {
886   // Try to match a memory operand.
887   // The memory operands are of the form:
888   //  (1)  Register|Immediate|'' '[' '*'? Register '*'? ']' or
889   //                            ^
890   //  (2)  '[' '*'? Register '*'? AluOperator Register ']'
891   //      ^
892   //  (3)  '[' '--'|'++' Register '--'|'++' ']'
893   //
894   //  (4) '[' Immediate ']' (for SLS)
895 
896   // Store the type for use in parsing pre/post increment/decrement operators
897   StringRef Type;
898   if (Operands[0]->isToken())
899     Type = static_cast<LanaiOperand *>(Operands[0].get())->getToken();
900 
901   // Use 0 if no offset given
902   int OffsetValue = 0;
903   unsigned BaseReg = 0;
904   unsigned AluOp = LPAC::ADD;
905   bool PostOp = false, PreOp = false;
906 
907   // Try to parse the offset
908   std::unique_ptr<LanaiOperand> Op = parseRegister();
909   if (!Op)
910     Op = parseImmediate();
911 
912   // Only continue if next token is '['
913   if (Lexer.isNot(AsmToken::LBrac)) {
914     if (!Op)
915       return ParseStatus::NoMatch;
916 
917     // The start of this custom parsing overlaps with register/immediate so
918     // consider this as a successful match of an operand of that type as the
919     // token stream can't be rewound to allow them to match separately.
920     Operands.push_back(std::move(Op));
921     return ParseStatus::Success;
922   }
923 
924   Parser.Lex(); // Eat the '['.
925   std::unique_ptr<LanaiOperand> Offset = nullptr;
926   if (Op)
927     Offset.swap(Op);
928 
929   // Determine if a pre operation
930   PreOp = parsePrePost(Type, &OffsetValue);
931 
932   Op = parseRegister();
933   if (!Op) {
934     if (!Offset) {
935       if ((Op = parseImmediate()) && Lexer.is(AsmToken::RBrac)) {
936         Parser.Lex(); // Eat the ']'
937 
938         // Memory address operations aligned to word boundary are encoded as
939         // SLS, the rest as RM.
940         if (shouldBeSls(*Op)) {
941           Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op)));
942         } else {
943           if (!Op->isLoImm16Signed())
944             return Error(Parser.getTok().getLoc(),
945                          "Memory address is not word aligned and larger than "
946                          "class RM can handle");
947           Operands.push_back(LanaiOperand::MorphToMemRegImm(
948               Lanai::R0, std::move(Op), LPAC::ADD));
949         }
950         return ParseStatus::Success;
951       }
952     }
953 
954     return Error(Parser.getTok().getLoc(),
955                  "Unknown operand, expected register or immediate");
956   }
957   BaseReg = Op->getReg();
958 
959   // Determine if a post operation
960   if (!PreOp)
961     PostOp = parsePrePost(Type, &OffsetValue);
962 
963   // If ] match form (1) else match form (2)
964   if (Lexer.is(AsmToken::RBrac)) {
965     Parser.Lex(); // Eat the ']'.
966     if (!Offset) {
967       SMLoc Start = Parser.getTok().getLoc();
968       SMLoc End =
969           SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
970       const MCConstantExpr *OffsetConstExpr =
971           MCConstantExpr::create(OffsetValue, getContext());
972       Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End);
973     }
974   } else {
975     if (Offset || OffsetValue != 0)
976       return Error(Parser.getTok().getLoc(), "Expected ']'");
977 
978     // Parse operator
979     AluOp = parseAluOperator(PreOp, PostOp);
980 
981     // Second form requires offset register
982     Offset = parseRegister();
983     if (!BaseReg || Lexer.isNot(AsmToken::RBrac))
984       return Error(Parser.getTok().getLoc(), "Expected ']'");
985     Parser.Lex(); // Eat the ']'.
986   }
987 
988   // First form has addition as operator. Add pre- or post-op indicator as
989   // needed.
990   AluOp = AluWithPrePost(AluOp, PreOp, PostOp);
991 
992   // Ensure immediate offset is not too large
993   if (Offset->isImm() && !Offset->isLoImm16Signed())
994     return Error(Parser.getTok().getLoc(),
995                  "Memory address is not word aligned and larger than class RM "
996                  "can handle");
997 
998   Operands.push_back(
999       Offset->isImm()
1000           ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp)
1001           : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp));
1002 
1003   return ParseStatus::Success;
1004 }
1005 
1006 // Looks at a token type and creates the relevant operand from this
1007 // information, adding to operands.
1008 // If operand was parsed, returns false, else true.
parseOperand(OperandVector * Operands,StringRef Mnemonic)1009 ParseStatus LanaiAsmParser::parseOperand(OperandVector *Operands,
1010                                          StringRef Mnemonic) {
1011   // Check if the current operand has a custom associated parser, if so, try to
1012   // custom parse the operand, or fallback to the general approach.
1013   ParseStatus Result = MatchOperandParserImpl(*Operands, Mnemonic);
1014 
1015   if (Result.isSuccess())
1016     return Result;
1017   if (Result.isFailure()) {
1018     Parser.eatToEndOfStatement();
1019     return Result;
1020   }
1021 
1022   // Attempt to parse token as register
1023   std::unique_ptr<LanaiOperand> Op = parseRegister();
1024 
1025   // Attempt to parse token as immediate
1026   if (!Op)
1027     Op = parseImmediate();
1028 
1029   // If the token could not be parsed then fail
1030   if (!Op) {
1031     Error(Parser.getTok().getLoc(), "Unknown operand");
1032     Parser.eatToEndOfStatement();
1033     return ParseStatus::Failure;
1034   }
1035 
1036   // Push back parsed operand into list of operands
1037   Operands->push_back(std::move(Op));
1038 
1039   return ParseStatus::Success;
1040 }
1041 
1042 // Split the mnemonic into ASM operand, conditional code and instruction
1043 // qualifier (half-word, byte).
splitMnemonic(StringRef Name,SMLoc NameLoc,OperandVector * Operands)1044 StringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
1045                                         OperandVector *Operands) {
1046   size_t Next = Name.find('.');
1047 
1048   StringRef Mnemonic = Name;
1049 
1050   bool IsBRR = false;
1051   if (Name.ends_with(".r")) {
1052     Mnemonic = Name.substr(0, Name.size() - 2);
1053     IsBRR = true;
1054   }
1055 
1056   // Match b?? and s?? (BR, BRR, and SCC instruction classes).
1057   if (Mnemonic[0] == 'b' ||
1058       (Mnemonic[0] == 's' && !Mnemonic.starts_with("sel") &&
1059        !Mnemonic.starts_with("st"))) {
1060     // Parse instructions with a conditional code. For example, 'bne' is
1061     // converted into two operands 'b' and 'ne'.
1062     LPCC::CondCode CondCode =
1063         LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next));
1064     if (CondCode != LPCC::UNKNOWN) {
1065       Mnemonic = Mnemonic.slice(0, 1);
1066       Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1067       Operands->push_back(LanaiOperand::createImm(
1068           MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1069       if (IsBRR) {
1070         Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1071       }
1072       return Mnemonic;
1073     }
1074   }
1075 
1076   // Parse other instructions with condition codes (RR instructions).
1077   // We ignore .f here and assume they are flag-setting operations, not
1078   // conditional codes (except for select instructions where flag-setting
1079   // variants are not yet implemented).
1080   if (Mnemonic.starts_with("sel") ||
1081       (!Mnemonic.ends_with(".f") && !Mnemonic.starts_with("st"))) {
1082     LPCC::CondCode CondCode = LPCC::suffixToLanaiCondCode(Mnemonic);
1083     if (CondCode != LPCC::UNKNOWN) {
1084       size_t Next = Mnemonic.rfind('.', Name.size());
1085       // 'sel' doesn't use a predicate operand whose printer adds the period,
1086       // but instead has the period as part of the identifier (i.e., 'sel.' is
1087       // expected by the generated matcher). If the mnemonic starts with 'sel'
1088       // then include the period as part of the mnemonic, else don't include it
1089       // as part of the mnemonic.
1090       if (Mnemonic.starts_with("sel")) {
1091         Mnemonic = Mnemonic.substr(0, Next + 1);
1092       } else {
1093         Mnemonic = Mnemonic.substr(0, Next);
1094       }
1095       Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1096       Operands->push_back(LanaiOperand::createImm(
1097           MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1098       return Mnemonic;
1099     }
1100   }
1101 
1102   Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1103   if (IsBRR) {
1104     Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1105   }
1106 
1107   return Mnemonic;
1108 }
1109 
IsMemoryAssignmentError(const OperandVector & Operands)1110 static bool IsMemoryAssignmentError(const OperandVector &Operands) {
1111   // Detects if a memory operation has an erroneous base register modification.
1112   // Memory operations are detected by matching the types of operands.
1113   //
1114   // TODO: This test is focussed on one specific instance (ld/st).
1115   // Extend it to handle more cases or be more robust.
1116   bool Modifies = false;
1117 
1118   int Offset = 0;
1119 
1120   if (Operands.size() < 5)
1121     return false;
1122   else if (Operands[0]->isToken() && Operands[1]->isReg() &&
1123            Operands[2]->isImm() && Operands[3]->isImm() && Operands[4]->isReg())
1124     Offset = 0;
1125   else if (Operands[0]->isToken() && Operands[1]->isToken() &&
1126            Operands[2]->isReg() && Operands[3]->isImm() &&
1127            Operands[4]->isImm() && Operands[5]->isReg())
1128     Offset = 1;
1129   else
1130     return false;
1131 
1132   int PossibleAluOpIdx = Offset + 3;
1133   int PossibleBaseIdx = Offset + 1;
1134   int PossibleDestIdx = Offset + 4;
1135   if (LanaiOperand *PossibleAluOp =
1136           static_cast<LanaiOperand *>(Operands[PossibleAluOpIdx].get()))
1137     if (PossibleAluOp->isImm())
1138       if (const MCConstantExpr *ConstExpr =
1139               dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))
1140         Modifies = LPAC::modifiesOp(ConstExpr->getValue());
1141   return Modifies && Operands[PossibleBaseIdx]->isReg() &&
1142          Operands[PossibleDestIdx]->isReg() &&
1143          Operands[PossibleBaseIdx]->getReg() ==
1144              Operands[PossibleDestIdx]->getReg();
1145 }
1146 
IsRegister(const MCParsedAsmOperand & op)1147 static bool IsRegister(const MCParsedAsmOperand &op) {
1148   return static_cast<const LanaiOperand &>(op).isReg();
1149 }
1150 
MaybePredicatedInst(const OperandVector & Operands)1151 static bool MaybePredicatedInst(const OperandVector &Operands) {
1152   if (Operands.size() < 4 || !IsRegister(*Operands[1]) ||
1153       !IsRegister(*Operands[2]))
1154     return false;
1155   return StringSwitch<bool>(
1156              static_cast<const LanaiOperand &>(*Operands[0]).getToken())
1157       .StartsWith("addc", true)
1158       .StartsWith("add", true)
1159       .StartsWith("and", true)
1160       .StartsWith("sh", true)
1161       .StartsWith("subb", true)
1162       .StartsWith("sub", true)
1163       .StartsWith("or", true)
1164       .StartsWith("xor", true)
1165       .Default(false);
1166 }
1167 
ParseInstruction(ParseInstructionInfo &,StringRef Name,SMLoc NameLoc,OperandVector & Operands)1168 bool LanaiAsmParser::ParseInstruction(ParseInstructionInfo & /*Info*/,
1169                                       StringRef Name, SMLoc NameLoc,
1170                                       OperandVector &Operands) {
1171   // First operand is token for instruction
1172   StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);
1173 
1174   // If there are no more operands, then finish
1175   if (Lexer.is(AsmToken::EndOfStatement))
1176     return false;
1177 
1178   // Parse first operand
1179   if (!parseOperand(&Operands, Mnemonic).isSuccess())
1180     return true;
1181 
1182   // If it is a st instruction with one 1 operand then it is a "store true".
1183   // Transform <"st"> to <"s">, <LPCC:ICC_T>
1184   if (Lexer.is(AsmToken::EndOfStatement) && Name == "st" &&
1185       Operands.size() == 2) {
1186     Operands.erase(Operands.begin(), Operands.begin() + 1);
1187     Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc));
1188     Operands.insert(Operands.begin() + 1,
1189                     LanaiOperand::createImm(
1190                         MCConstantExpr::create(LPCC::ICC_T, getContext()),
1191                         NameLoc, NameLoc));
1192   }
1193 
1194   // If the instruction is a bt instruction with 1 operand (in assembly) then it
1195   // is an unconditional branch instruction and the first two elements of
1196   // operands need to be merged.
1197   if (Lexer.is(AsmToken::EndOfStatement) && Name.starts_with("bt") &&
1198       Operands.size() == 3) {
1199     Operands.erase(Operands.begin(), Operands.begin() + 2);
1200     Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc));
1201   }
1202 
1203   // Parse until end of statement, consuming commas between operands
1204   while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.is(AsmToken::Comma)) {
1205     // Consume comma token
1206     Lex();
1207 
1208     // Parse next operand
1209     if (!parseOperand(&Operands, Mnemonic).isSuccess())
1210       return true;
1211   }
1212 
1213   if (IsMemoryAssignmentError(Operands)) {
1214     Error(Parser.getTok().getLoc(),
1215           "the destination register can't equal the base register in an "
1216           "instruction that modifies the base register.");
1217     return true;
1218   }
1219 
1220   // Insert always true operand for instruction that may be predicated but
1221   // are not. Currently the autogenerated parser always expects a predicate.
1222   if (MaybePredicatedInst(Operands)) {
1223     Operands.insert(Operands.begin() + 1,
1224                     LanaiOperand::createImm(
1225                         MCConstantExpr::create(LPCC::ICC_T, getContext()),
1226                         NameLoc, NameLoc));
1227   }
1228 
1229   return false;
1230 }
1231 
1232 #define GET_REGISTER_MATCHER
1233 #define GET_MATCHER_IMPLEMENTATION
1234 #include "LanaiGenAsmMatcher.inc"
1235 
LLVMInitializeLanaiAsmParser()1236 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLanaiAsmParser() {
1237   RegisterMCAsmParser<LanaiAsmParser> x(getTheLanaiTarget());
1238 }
1239