[AMDGPU] Check for immediate SrcC in mfma in AsmParser
[llvm-core.git] / lib / Target / Lanai / AsmParser / LanaiAsmParser.cpp
blobb629a24a99f3d4541ffc2fc417bd658a49d24ce5
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 //===----------------------------------------------------------------------===//
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/Support/Casting.h"
28 #include "llvm/Support/ErrorHandling.h"
29 #include "llvm/Support/MathExtras.h"
30 #include "llvm/Support/SMLoc.h"
31 #include "llvm/Support/TargetRegistry.h"
32 #include "llvm/Support/raw_ostream.h"
33 #include <algorithm>
34 #include <cassert>
35 #include <cstddef>
36 #include <cstdint>
37 #include <memory>
39 using namespace llvm;
41 // Auto-generated by TableGen
42 static unsigned MatchRegisterName(StringRef Name);
44 namespace {
46 struct LanaiOperand;
48 class LanaiAsmParser : public MCTargetAsmParser {
49 // Parse operands
50 std::unique_ptr<LanaiOperand> parseRegister();
52 std::unique_ptr<LanaiOperand> parseImmediate();
54 std::unique_ptr<LanaiOperand> parseIdentifier();
56 unsigned parseAluOperator(bool PreOp, bool PostOp);
58 // Split the mnemonic stripping conditional code and quantifiers
59 StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,
60 OperandVector *Operands);
62 bool parsePrePost(StringRef Type, int *OffsetValue);
64 bool ParseDirective(AsmToken DirectiveID) override;
66 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
67 SMLoc NameLoc, OperandVector &Operands) override;
69 bool ParseRegister(unsigned &RegNum, SMLoc &StartLoc, SMLoc &EndLoc) override;
71 bool MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
72 OperandVector &Operands, MCStreamer &Out,
73 uint64_t &ErrorInfo,
74 bool MatchingInlineAsm) override;
76 // Auto-generated instruction matching functions
77 #define GET_ASSEMBLER_HEADER
78 #include "LanaiGenAsmMatcher.inc"
80 OperandMatchResultTy parseOperand(OperandVector *Operands,
81 StringRef Mnemonic);
83 OperandMatchResultTy parseMemoryOperand(OperandVector &Operands);
85 public:
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()));
94 private:
95 MCAsmParser &Parser;
96 MCAsmLexer &Lexer;
98 const MCSubtargetInfo &SubtargetInfo;
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;
113 SMLoc StartLoc, EndLoc;
115 struct Token {
116 const char *Data;
117 unsigned Length;
120 struct RegOp {
121 unsigned RegNum;
124 struct ImmOp {
125 const MCExpr *Value;
128 struct MemOp {
129 unsigned BaseReg;
130 unsigned OffsetReg;
131 unsigned AluOp;
132 const MCExpr *Offset;
135 union {
136 struct Token Tok;
137 struct RegOp Reg;
138 struct ImmOp Imm;
139 struct MemOp Mem;
142 explicit LanaiOperand(KindTy Kind) : MCParsedAsmOperand(), Kind(Kind) {}
144 public:
145 // The functions below are used by the autogenerated ASM matcher and hence to
146 // be of the form expected.
148 // getStartLoc - Gets location of the first token of this operand
149 SMLoc getStartLoc() const override { return StartLoc; }
151 // getEndLoc - Gets location of the last token of this operand
152 SMLoc getEndLoc() const override { return EndLoc; }
154 unsigned getReg() const override {
155 assert(isReg() && "Invalid type access!");
156 return Reg.RegNum;
159 const MCExpr *getImm() const {
160 assert(isImm() && "Invalid type access!");
161 return Imm.Value;
164 StringRef getToken() const {
165 assert(isToken() && "Invalid type access!");
166 return StringRef(Tok.Data, Tok.Length);
169 unsigned getMemBaseReg() const {
170 assert(isMem() && "Invalid type access!");
171 return Mem.BaseReg;
174 unsigned getMemOffsetReg() const {
175 assert(isMem() && "Invalid type access!");
176 return Mem.OffsetReg;
179 const MCExpr *getMemOffset() const {
180 assert(isMem() && "Invalid type access!");
181 return Mem.Offset;
184 unsigned getMemOp() const {
185 assert(isMem() && "Invalid type access!");
186 return Mem.AluOp;
189 // Functions for testing operand type
190 bool isReg() const override { return Kind == REGISTER; }
192 bool isImm() const override { return Kind == IMMEDIATE; }
194 bool isMem() const override {
195 return isMemImm() || isMemRegImm() || isMemRegReg();
198 bool isMemImm() const { return Kind == MEMORY_IMM; }
200 bool isMemRegImm() const { return Kind == MEMORY_REG_IMM; }
202 bool isMemRegReg() const { return Kind == MEMORY_REG_REG; }
204 bool isMemSpls() const { return isMemRegImm() || isMemRegReg(); }
206 bool isToken() const override { return Kind == TOKEN; }
208 bool isBrImm() {
209 if (!isImm())
210 return false;
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));
221 bool isBrTarget() { return isBrImm() || isToken(); }
223 bool isCallTarget() { return isImm() || isToken(); }
225 bool isHiImm16() {
226 if (!isImm())
227 return false;
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);
235 // Symbolic reference expression
236 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
237 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
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;
245 return false;
248 bool isHiImm16And() {
249 if (!isImm())
250 return false;
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);
258 return false;
261 bool isLoImm16() {
262 if (!isImm())
263 return false;
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));
272 // Symbolic reference expression
273 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
274 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
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;
282 return false;
285 bool isLoImm16Signed() {
286 if (!isImm())
287 return false;
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));
296 // Symbolic reference expression
297 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
298 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
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;
306 return false;
309 bool isLoImm16And() {
310 if (!isImm())
311 return false;
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);
319 return false;
322 bool isImmShift() {
323 if (!isImm())
324 return false;
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);
333 bool isLoImm21() {
334 if (!isImm())
335 return false;
337 // Constant case
338 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
339 int64_t Value = ConstExpr->getValue();
340 return isUInt<21>(Value);
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;
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;
361 return false;
364 bool isImm10() {
365 if (!isImm())
366 return false;
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);
375 bool isCondCode() {
376 if (!isImm())
377 return false;
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;
389 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));
400 void addRegOperands(MCInst &Inst, unsigned N) const {
401 assert(N == 1 && "Invalid number of operands!");
402 Inst.addOperand(MCOperand::createReg(getReg()));
405 void addImmOperands(MCInst &Inst, unsigned N) const {
406 assert(N == 1 && "Invalid number of operands!");
407 addExpr(Inst, getImm());
410 void addBrTargetOperands(MCInst &Inst, unsigned N) const {
411 assert(N == 1 && "Invalid number of operands!");
412 addExpr(Inst, getImm());
415 void addCallTargetOperands(MCInst &Inst, unsigned N) const {
416 assert(N == 1 && "Invalid number of operands!");
417 addExpr(Inst, getImm());
420 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
421 assert(N == 1 && "Invalid number of operands!");
422 addExpr(Inst, getImm());
425 void addMemImmOperands(MCInst &Inst, unsigned N) const {
426 assert(N == 1 && "Invalid number of operands!");
427 const MCExpr *Expr = getMemOffset();
428 addExpr(Inst, Expr);
431 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()));
439 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()));
447 void addMemSplsOperands(MCInst &Inst, unsigned N) const {
448 if (isMemRegImm())
449 addMemRegImmOperands(Inst, N);
450 if (isMemRegReg())
451 addMemRegRegOperands(Inst, N);
454 void addImmShiftOperands(MCInst &Inst, unsigned N) const {
455 assert(N == 1 && "Invalid number of operands!");
456 addExpr(Inst, getImm());
459 void addImm10Operands(MCInst &Inst, unsigned N) const {
460 assert(N == 1 && "Invalid number of operands!");
461 addExpr(Inst, getImm());
464 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->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO);
473 #endif
474 Inst.addOperand(MCOperand::createExpr(getImm()));
475 } else if (isa<MCBinaryExpr>(getImm())) {
476 #ifndef NDEBUG
477 const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
478 assert(isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
479 cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
480 LanaiMCExpr::VK_Lanai_ABS_LO);
481 #endif
482 Inst.addOperand(MCOperand::createExpr(getImm()));
483 } else
484 assert(false && "Operand type not supported.");
487 void addLoImm16AndOperands(MCInst &Inst, unsigned N) const {
488 assert(N == 1 && "Invalid number of operands!");
489 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
490 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff));
491 else
492 assert(false && "Operand type not supported.");
495 void addHiImm16Operands(MCInst &Inst, unsigned N) const {
496 assert(N == 1 && "Invalid number of operands!");
497 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
498 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
499 else if (isa<LanaiMCExpr>(getImm())) {
500 #ifndef NDEBUG
501 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
502 assert(SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI);
503 #endif
504 Inst.addOperand(MCOperand::createExpr(getImm()));
505 } else if (isa<MCBinaryExpr>(getImm())) {
506 #ifndef NDEBUG
507 const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
508 assert(isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
509 cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
510 LanaiMCExpr::VK_Lanai_ABS_HI);
511 #endif
512 Inst.addOperand(MCOperand::createExpr(getImm()));
513 } else
514 assert(false && "Operand type not supported.");
517 void addHiImm16AndOperands(MCInst &Inst, unsigned N) const {
518 assert(N == 1 && "Invalid number of operands!");
519 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
520 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
521 else
522 assert(false && "Operand type not supported.");
525 void addLoImm21Operands(MCInst &Inst, unsigned N) const {
526 assert(N == 1 && "Invalid number of operands!");
527 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
528 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff));
529 else if (isa<LanaiMCExpr>(getImm())) {
530 #ifndef NDEBUG
531 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
532 assert(SymbolRefExpr &&
533 SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
534 #endif
535 Inst.addOperand(MCOperand::createExpr(getImm()));
536 } else if (isa<MCSymbolRefExpr>(getImm())) {
537 #ifndef NDEBUG
538 const MCSymbolRefExpr *SymbolRefExpr =
539 dyn_cast<MCSymbolRefExpr>(getImm());
540 assert(SymbolRefExpr &&
541 SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None);
542 #endif
543 Inst.addOperand(MCOperand::createExpr(getImm()));
544 } else if (isa<MCBinaryExpr>(getImm())) {
545 #ifndef NDEBUG
546 const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
547 const LanaiMCExpr *SymbolRefExpr =
548 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
549 assert(SymbolRefExpr &&
550 SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
551 #endif
552 Inst.addOperand(MCOperand::createExpr(getImm()));
553 } else
554 assert(false && "Operand type not supported.");
557 void print(raw_ostream &OS) const override {
558 switch (Kind) {
559 case IMMEDIATE:
560 OS << "Imm: " << getImm() << "\n";
561 break;
562 case TOKEN:
563 OS << "Token: " << getToken() << "\n";
564 break;
565 case REGISTER:
566 OS << "Reg: %r" << getReg() << "\n";
567 break;
568 case MEMORY_IMM:
569 OS << "MemImm: " << *getMemOffset() << "\n";
570 break;
571 case MEMORY_REG_IMM:
572 OS << "MemRegImm: " << getMemBaseReg() << "+" << *getMemOffset() << "\n";
573 break;
574 case MEMORY_REG_REG:
575 assert(getMemOffset() == nullptr);
576 OS << "MemRegReg: " << getMemBaseReg() << "+"
577 << "%r" << getMemOffsetReg() << "\n";
578 break;
582 static std::unique_ptr<LanaiOperand> CreateToken(StringRef Str, SMLoc Start) {
583 auto Op = std::make_unique<LanaiOperand>(TOKEN);
584 Op->Tok.Data = Str.data();
585 Op->Tok.Length = Str.size();
586 Op->StartLoc = Start;
587 Op->EndLoc = Start;
588 return Op;
591 static std::unique_ptr<LanaiOperand> createReg(unsigned RegNum, SMLoc Start,
592 SMLoc End) {
593 auto Op = std::make_unique<LanaiOperand>(REGISTER);
594 Op->Reg.RegNum = RegNum;
595 Op->StartLoc = Start;
596 Op->EndLoc = End;
597 return Op;
600 static std::unique_ptr<LanaiOperand> createImm(const MCExpr *Value,
601 SMLoc Start, SMLoc End) {
602 auto Op = std::make_unique<LanaiOperand>(IMMEDIATE);
603 Op->Imm.Value = Value;
604 Op->StartLoc = Start;
605 Op->EndLoc = End;
606 return Op;
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 = 0;
614 Op->Mem.AluOp = LPAC::ADD;
615 Op->Mem.OffsetReg = 0;
616 Op->Mem.Offset = Imm;
617 return Op;
620 static std::unique_ptr<LanaiOperand>
621 MorphToMemRegReg(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
622 unsigned AluOp) {
623 unsigned 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;
632 static std::unique_ptr<LanaiOperand>
633 MorphToMemRegImm(unsigned 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;
645 } // end anonymous namespace
647 bool LanaiAsmParser::ParseDirective(AsmToken /*DirectiveId*/) { return true; }
649 bool LanaiAsmParser::MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
650 OperandVector &Operands,
651 MCStreamer &Out,
652 uint64_t &ErrorInfo,
653 bool MatchingInlineAsm) {
654 MCInst Inst;
655 SMLoc ErrorLoc;
657 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
658 case Match_Success:
659 Out.EmitInstruction(Inst, SubtargetInfo);
660 Opcode = Inst.getOpcode();
661 return false;
662 case Match_MissingFeature:
663 return Error(IdLoc, "Instruction use requires option to be enabled");
664 case Match_MnemonicFail:
665 return Error(IdLoc, "Unrecognized instruction mnemonic");
666 case Match_InvalidOperand: {
667 ErrorLoc = IdLoc;
668 if (ErrorInfo != ~0U) {
669 if (ErrorInfo >= Operands.size())
670 return Error(IdLoc, "Too few operands for instruction");
672 ErrorLoc = ((LanaiOperand &)*Operands[ErrorInfo]).getStartLoc();
673 if (ErrorLoc == SMLoc())
674 ErrorLoc = IdLoc;
676 return Error(ErrorLoc, "Invalid operand for instruction");
678 default:
679 break;
682 llvm_unreachable("Unknown match type detected!");
685 // Both '%rN' and 'rN' are parsed as valid registers. This was done to remain
686 // backwards compatible with GCC and the different ways inline assembly is
687 // handled.
688 // TODO: see if there isn't a better way to do this.
689 std::unique_ptr<LanaiOperand> LanaiAsmParser::parseRegister() {
690 SMLoc Start = Parser.getTok().getLoc();
691 SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
693 unsigned RegNum;
694 // Eat the '%'.
695 if (Lexer.getKind() == AsmToken::Percent)
696 Parser.Lex();
697 if (Lexer.getKind() == AsmToken::Identifier) {
698 RegNum = MatchRegisterName(Lexer.getTok().getIdentifier());
699 if (RegNum == 0)
700 return nullptr;
701 Parser.Lex(); // Eat identifier token
702 return LanaiOperand::createReg(RegNum, Start, End);
704 return nullptr;
707 bool LanaiAsmParser::ParseRegister(unsigned &RegNum, SMLoc &StartLoc,
708 SMLoc &EndLoc) {
709 const AsmToken &Tok = getParser().getTok();
710 StartLoc = Tok.getLoc();
711 EndLoc = Tok.getEndLoc();
712 std::unique_ptr<LanaiOperand> Op = parseRegister();
713 if (Op != nullptr)
714 RegNum = Op->getReg();
715 return (Op == nullptr);
718 std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {
719 SMLoc Start = Parser.getTok().getLoc();
720 SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
721 const MCExpr *Res, *RHS = nullptr;
722 LanaiMCExpr::VariantKind Kind = LanaiMCExpr::VK_Lanai_None;
724 if (Lexer.getKind() != AsmToken::Identifier)
725 return nullptr;
727 StringRef Identifier;
728 if (Parser.parseIdentifier(Identifier))
729 return nullptr;
731 // Check if identifier has a modifier
732 if (Identifier.equals_lower("hi"))
733 Kind = LanaiMCExpr::VK_Lanai_ABS_HI;
734 else if (Identifier.equals_lower("lo"))
735 Kind = LanaiMCExpr::VK_Lanai_ABS_LO;
737 // If the identifier corresponds to a variant then extract the real
738 // identifier.
739 if (Kind != LanaiMCExpr::VK_Lanai_None) {
740 if (Lexer.getKind() != AsmToken::LParen) {
741 Error(Lexer.getLoc(), "Expected '('");
742 return nullptr;
744 Lexer.Lex(); // lex '('
746 // Parse identifier
747 if (Parser.parseIdentifier(Identifier))
748 return nullptr;
751 // If addition parse the RHS.
752 if (Lexer.getKind() == AsmToken::Plus && Parser.parseExpression(RHS))
753 return nullptr;
755 // For variants parse the final ')'
756 if (Kind != LanaiMCExpr::VK_Lanai_None) {
757 if (Lexer.getKind() != AsmToken::RParen) {
758 Error(Lexer.getLoc(), "Expected ')'");
759 return nullptr;
761 Lexer.Lex(); // lex ')'
764 End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
765 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
766 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
767 Res = LanaiMCExpr::create(Kind, Expr, getContext());
769 // Nest if this was an addition
770 if (RHS)
771 Res = MCBinaryExpr::createAdd(Res, RHS, getContext());
773 return LanaiOperand::createImm(Res, Start, End);
776 std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {
777 SMLoc Start = Parser.getTok().getLoc();
778 SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
780 const MCExpr *ExprVal;
781 switch (Lexer.getKind()) {
782 case AsmToken::Identifier:
783 return parseIdentifier();
784 case AsmToken::Plus:
785 case AsmToken::Minus:
786 case AsmToken::Integer:
787 case AsmToken::Dot:
788 if (!Parser.parseExpression(ExprVal))
789 return LanaiOperand::createImm(ExprVal, Start, End);
790 LLVM_FALLTHROUGH;
791 default:
792 return nullptr;
796 static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) {
797 if (PreOp)
798 return LPAC::makePreOp(AluCode);
799 if (PostOp)
800 return LPAC::makePostOp(AluCode);
801 return AluCode;
804 unsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) {
805 StringRef IdString;
806 Parser.parseIdentifier(IdString);
807 unsigned AluCode = LPAC::stringToLanaiAluCode(IdString);
808 if (AluCode == LPAC::UNKNOWN) {
809 Error(Parser.getTok().getLoc(), "Can't parse ALU operator");
810 return 0;
812 return AluCode;
815 static int SizeForSuffix(StringRef T) {
816 return StringSwitch<int>(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4);
819 bool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) {
820 bool PreOrPost = false;
821 if (Lexer.getKind() == Lexer.peekTok(true).getKind()) {
822 PreOrPost = true;
823 if (Lexer.is(AsmToken::Minus))
824 *OffsetValue = -SizeForSuffix(Type);
825 else if (Lexer.is(AsmToken::Plus))
826 *OffsetValue = SizeForSuffix(Type);
827 else
828 return false;
830 // Eat the '-' '-' or '+' '+'
831 Parser.Lex();
832 Parser.Lex();
833 } else if (Lexer.is(AsmToken::Star)) {
834 Parser.Lex(); // Eat the '*'
835 PreOrPost = true;
838 return PreOrPost;
841 bool shouldBeSls(const LanaiOperand &Op) {
842 // The instruction should be encoded as an SLS if the constant is word
843 // aligned and will fit in 21 bits
844 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm())) {
845 int64_t Value = ConstExpr->getValue();
846 return (Value % 4 == 0) && (Value >= 0) && (Value <= 0x1fffff);
848 // The instruction should be encoded as an SLS if the operand is a symbolic
849 // reference with no variant.
850 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Op.getImm()))
851 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
852 // The instruction should be encoded as an SLS if the operand is a binary
853 // expression with the left-hand side being a symbolic reference with no
854 // variant.
855 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Op.getImm())) {
856 const LanaiMCExpr *LHSSymbolRefExpr =
857 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
858 return (LHSSymbolRefExpr &&
859 LHSSymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
861 return false;
864 // Matches memory operand. Returns true if error encountered.
865 OperandMatchResultTy
866 LanaiAsmParser::parseMemoryOperand(OperandVector &Operands) {
867 // Try to match a memory operand.
868 // The memory operands are of the form:
869 // (1) Register|Immediate|'' '[' '*'? Register '*'? ']' or
870 // ^
871 // (2) '[' '*'? Register '*'? AluOperator Register ']'
872 // ^
873 // (3) '[' '--'|'++' Register '--'|'++' ']'
875 // (4) '[' Immediate ']' (for SLS)
877 // Store the type for use in parsing pre/post increment/decrement operators
878 StringRef Type;
879 if (Operands[0]->isToken())
880 Type = static_cast<LanaiOperand *>(Operands[0].get())->getToken();
882 // Use 0 if no offset given
883 int OffsetValue = 0;
884 unsigned BaseReg = 0;
885 unsigned AluOp = LPAC::ADD;
886 bool PostOp = false, PreOp = false;
888 // Try to parse the offset
889 std::unique_ptr<LanaiOperand> Op = parseRegister();
890 if (!Op)
891 Op = parseImmediate();
893 // Only continue if next token is '['
894 if (Lexer.isNot(AsmToken::LBrac)) {
895 if (!Op)
896 return MatchOperand_NoMatch;
898 // The start of this custom parsing overlaps with register/immediate so
899 // consider this as a successful match of an operand of that type as the
900 // token stream can't be rewound to allow them to match separately.
901 Operands.push_back(std::move(Op));
902 return MatchOperand_Success;
905 Parser.Lex(); // Eat the '['.
906 std::unique_ptr<LanaiOperand> Offset = nullptr;
907 if (Op)
908 Offset.swap(Op);
910 // Determine if a pre operation
911 PreOp = parsePrePost(Type, &OffsetValue);
913 Op = parseRegister();
914 if (!Op) {
915 if (!Offset) {
916 if ((Op = parseImmediate()) && Lexer.is(AsmToken::RBrac)) {
917 Parser.Lex(); // Eat the ']'
919 // Memory address operations aligned to word boundary are encoded as
920 // SLS, the rest as RM.
921 if (shouldBeSls(*Op)) {
922 Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op)));
923 } else {
924 if (!Op->isLoImm16Signed()) {
925 Error(Parser.getTok().getLoc(),
926 "Memory address is not word "
927 "aligned and larger than class RM can handle");
928 return MatchOperand_ParseFail;
930 Operands.push_back(LanaiOperand::MorphToMemRegImm(
931 Lanai::R0, std::move(Op), LPAC::ADD));
933 return MatchOperand_Success;
937 Error(Parser.getTok().getLoc(),
938 "Unknown operand, expected register or immediate");
939 return MatchOperand_ParseFail;
941 BaseReg = Op->getReg();
943 // Determine if a post operation
944 if (!PreOp)
945 PostOp = parsePrePost(Type, &OffsetValue);
947 // If ] match form (1) else match form (2)
948 if (Lexer.is(AsmToken::RBrac)) {
949 Parser.Lex(); // Eat the ']'.
950 if (!Offset) {
951 SMLoc Start = Parser.getTok().getLoc();
952 SMLoc End =
953 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
954 const MCConstantExpr *OffsetConstExpr =
955 MCConstantExpr::create(OffsetValue, getContext());
956 Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End);
958 } else {
959 if (Offset || OffsetValue != 0) {
960 Error(Parser.getTok().getLoc(), "Expected ']'");
961 return MatchOperand_ParseFail;
964 // Parse operator
965 AluOp = parseAluOperator(PreOp, PostOp);
967 // Second form requires offset register
968 Offset = parseRegister();
969 if (!BaseReg || Lexer.isNot(AsmToken::RBrac)) {
970 Error(Parser.getTok().getLoc(), "Expected ']'");
971 return MatchOperand_ParseFail;
973 Parser.Lex(); // Eat the ']'.
976 // First form has addition as operator. Add pre- or post-op indicator as
977 // needed.
978 AluOp = AluWithPrePost(AluOp, PreOp, PostOp);
980 // Ensure immediate offset is not too large
981 if (Offset->isImm() && !Offset->isLoImm16Signed()) {
982 Error(Parser.getTok().getLoc(),
983 "Memory address is not word "
984 "aligned and larger than class RM can handle");
985 return MatchOperand_ParseFail;
988 Operands.push_back(
989 Offset->isImm()
990 ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp)
991 : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp));
993 return MatchOperand_Success;
996 // Looks at a token type and creates the relevant operand from this
997 // information, adding to operands.
998 // If operand was parsed, returns false, else true.
999 OperandMatchResultTy
1000 LanaiAsmParser::parseOperand(OperandVector *Operands, StringRef Mnemonic) {
1001 // Check if the current operand has a custom associated parser, if so, try to
1002 // custom parse the operand, or fallback to the general approach.
1003 OperandMatchResultTy Result = MatchOperandParserImpl(*Operands, Mnemonic);
1005 if (Result == MatchOperand_Success)
1006 return Result;
1007 if (Result == MatchOperand_ParseFail) {
1008 Parser.eatToEndOfStatement();
1009 return Result;
1012 // Attempt to parse token as register
1013 std::unique_ptr<LanaiOperand> Op = parseRegister();
1015 // Attempt to parse token as immediate
1016 if (!Op)
1017 Op = parseImmediate();
1019 // If the token could not be parsed then fail
1020 if (!Op) {
1021 Error(Parser.getTok().getLoc(), "Unknown operand");
1022 Parser.eatToEndOfStatement();
1023 return MatchOperand_ParseFail;
1026 // Push back parsed operand into list of operands
1027 Operands->push_back(std::move(Op));
1029 return MatchOperand_Success;
1032 // Split the mnemonic into ASM operand, conditional code and instruction
1033 // qualifier (half-word, byte).
1034 StringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
1035 OperandVector *Operands) {
1036 size_t Next = Name.find('.');
1038 StringRef Mnemonic = Name;
1040 bool IsBRR = false;
1041 if (Name.endswith(".r")) {
1042 Mnemonic = Name.substr(0, Name.size() - 2);
1043 IsBRR = true;
1046 // Match b?? and s?? (BR, BRR, and SCC instruction classes).
1047 if (Mnemonic[0] == 'b' ||
1048 (Mnemonic[0] == 's' && !Mnemonic.startswith("sel") &&
1049 !Mnemonic.startswith("st"))) {
1050 // Parse instructions with a conditional code. For example, 'bne' is
1051 // converted into two operands 'b' and 'ne'.
1052 LPCC::CondCode CondCode =
1053 LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next));
1054 if (CondCode != LPCC::UNKNOWN) {
1055 Mnemonic = Mnemonic.slice(0, 1);
1056 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1057 Operands->push_back(LanaiOperand::createImm(
1058 MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1059 if (IsBRR) {
1060 Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1062 return Mnemonic;
1066 // Parse other instructions with condition codes (RR instructions).
1067 // We ignore .f here and assume they are flag-setting operations, not
1068 // conditional codes (except for select instructions where flag-setting
1069 // variants are not yet implemented).
1070 if (Mnemonic.startswith("sel") ||
1071 (!Mnemonic.endswith(".f") && !Mnemonic.startswith("st"))) {
1072 LPCC::CondCode CondCode = LPCC::suffixToLanaiCondCode(Mnemonic);
1073 if (CondCode != LPCC::UNKNOWN) {
1074 size_t Next = Mnemonic.rfind('.', Name.size());
1075 // 'sel' doesn't use a predicate operand whose printer adds the period,
1076 // but instead has the period as part of the identifier (i.e., 'sel.' is
1077 // expected by the generated matcher). If the mnemonic starts with 'sel'
1078 // then include the period as part of the mnemonic, else don't include it
1079 // as part of the mnemonic.
1080 if (Mnemonic.startswith("sel")) {
1081 Mnemonic = Mnemonic.substr(0, Next + 1);
1082 } else {
1083 Mnemonic = Mnemonic.substr(0, Next);
1085 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1086 Operands->push_back(LanaiOperand::createImm(
1087 MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1088 return Mnemonic;
1092 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1093 if (IsBRR) {
1094 Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1097 return Mnemonic;
1100 static bool IsMemoryAssignmentError(const OperandVector &Operands) {
1101 // Detects if a memory operation has an erroneous base register modification.
1102 // Memory operations are detected by matching the types of operands.
1104 // TODO: This test is focussed on one specific instance (ld/st).
1105 // Extend it to handle more cases or be more robust.
1106 bool Modifies = false;
1108 int Offset = 0;
1110 if (Operands.size() < 5)
1111 return false;
1112 else if (Operands[0]->isToken() && Operands[1]->isReg() &&
1113 Operands[2]->isImm() && Operands[3]->isImm() && Operands[4]->isReg())
1114 Offset = 0;
1115 else if (Operands[0]->isToken() && Operands[1]->isToken() &&
1116 Operands[2]->isReg() && Operands[3]->isImm() &&
1117 Operands[4]->isImm() && Operands[5]->isReg())
1118 Offset = 1;
1119 else
1120 return false;
1122 int PossibleAluOpIdx = Offset + 3;
1123 int PossibleBaseIdx = Offset + 1;
1124 int PossibleDestIdx = Offset + 4;
1125 if (LanaiOperand *PossibleAluOp =
1126 static_cast<LanaiOperand *>(Operands[PossibleAluOpIdx].get()))
1127 if (PossibleAluOp->isImm())
1128 if (const MCConstantExpr *ConstExpr =
1129 dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))
1130 Modifies = LPAC::modifiesOp(ConstExpr->getValue());
1131 return Modifies && Operands[PossibleBaseIdx]->isReg() &&
1132 Operands[PossibleDestIdx]->isReg() &&
1133 Operands[PossibleBaseIdx]->getReg() ==
1134 Operands[PossibleDestIdx]->getReg();
1137 static bool IsRegister(const MCParsedAsmOperand &op) {
1138 return static_cast<const LanaiOperand &>(op).isReg();
1141 static bool MaybePredicatedInst(const OperandVector &Operands) {
1142 if (Operands.size() < 4 || !IsRegister(*Operands[1]) ||
1143 !IsRegister(*Operands[2]))
1144 return false;
1145 return StringSwitch<bool>(
1146 static_cast<const LanaiOperand &>(*Operands[0]).getToken())
1147 .StartsWith("addc", true)
1148 .StartsWith("add", true)
1149 .StartsWith("and", true)
1150 .StartsWith("sh", true)
1151 .StartsWith("subb", true)
1152 .StartsWith("sub", true)
1153 .StartsWith("or", true)
1154 .StartsWith("xor", true)
1155 .Default(false);
1158 bool LanaiAsmParser::ParseInstruction(ParseInstructionInfo & /*Info*/,
1159 StringRef Name, SMLoc NameLoc,
1160 OperandVector &Operands) {
1161 // First operand is token for instruction
1162 StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);
1164 // If there are no more operands, then finish
1165 if (Lexer.is(AsmToken::EndOfStatement))
1166 return false;
1168 // Parse first operand
1169 if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success)
1170 return true;
1172 // If it is a st instruction with one 1 operand then it is a "store true".
1173 // Transform <"st"> to <"s">, <LPCC:ICC_T>
1174 if (Lexer.is(AsmToken::EndOfStatement) && Name == "st" &&
1175 Operands.size() == 2) {
1176 Operands.erase(Operands.begin(), Operands.begin() + 1);
1177 Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc));
1178 Operands.insert(Operands.begin() + 1,
1179 LanaiOperand::createImm(
1180 MCConstantExpr::create(LPCC::ICC_T, getContext()),
1181 NameLoc, NameLoc));
1184 // If the instruction is a bt instruction with 1 operand (in assembly) then it
1185 // is an unconditional branch instruction and the first two elements of
1186 // operands need to be merged.
1187 if (Lexer.is(AsmToken::EndOfStatement) && Name.startswith("bt") &&
1188 Operands.size() == 3) {
1189 Operands.erase(Operands.begin(), Operands.begin() + 2);
1190 Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc));
1193 // Parse until end of statement, consuming commas between operands
1194 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.is(AsmToken::Comma)) {
1195 // Consume comma token
1196 Lex();
1198 // Parse next operand
1199 if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success)
1200 return true;
1203 if (IsMemoryAssignmentError(Operands)) {
1204 Error(Parser.getTok().getLoc(),
1205 "the destination register can't equal the base register in an "
1206 "instruction that modifies the base register.");
1207 return true;
1210 // Insert always true operand for instruction that may be predicated but
1211 // are not. Currently the autogenerated parser always expects a predicate.
1212 if (MaybePredicatedInst(Operands)) {
1213 Operands.insert(Operands.begin() + 1,
1214 LanaiOperand::createImm(
1215 MCConstantExpr::create(LPCC::ICC_T, getContext()),
1216 NameLoc, NameLoc));
1219 return false;
1222 #define GET_REGISTER_MATCHER
1223 #define GET_MATCHER_IMPLEMENTATION
1224 #include "LanaiGenAsmMatcher.inc"
1226 extern "C" void LLVMInitializeLanaiAsmParser() {
1227 RegisterMCAsmParser<LanaiAsmParser> x(getTheLanaiTarget());