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