Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / lib / Target / Lanai / AsmParser / LanaiAsmParser.cpp
blobe60dd6f7b2c9dbf90b09798172951068cc4e014e
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 "Lanai.h"
10 #include "LanaiAluCode.h"
11 #include "LanaiCondCode.h"
12 #include "MCTargetDesc/LanaiMCExpr.h"
13 #include "llvm/ADT/STLExtras.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/MCAsmLexer.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/Support/Casting.h"
27 #include "llvm/Support/ErrorHandling.h"
28 #include "llvm/Support/MathExtras.h"
29 #include "llvm/Support/SMLoc.h"
30 #include "llvm/Support/TargetRegistry.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include <algorithm>
33 #include <cassert>
34 #include <cstddef>
35 #include <cstdint>
36 #include <memory>
38 using namespace llvm;
40 // Auto-generated by TableGen
41 static unsigned MatchRegisterName(StringRef Name);
43 namespace {
45 struct LanaiOperand;
47 class LanaiAsmParser : public MCTargetAsmParser {
48 // Parse operands
49 std::unique_ptr<LanaiOperand> parseRegister();
51 std::unique_ptr<LanaiOperand> parseImmediate();
53 std::unique_ptr<LanaiOperand> parseIdentifier();
55 unsigned parseAluOperator(bool PreOp, bool PostOp);
57 // Split the mnemonic stripping conditional code and quantifiers
58 StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,
59 OperandVector *Operands);
61 bool parsePrePost(StringRef Type, int *OffsetValue);
63 bool ParseDirective(AsmToken DirectiveID) override;
65 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
66 SMLoc NameLoc, OperandVector &Operands) override;
68 bool ParseRegister(unsigned &RegNum, SMLoc &StartLoc, SMLoc &EndLoc) override;
70 bool MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
71 OperandVector &Operands, MCStreamer &Out,
72 uint64_t &ErrorInfo,
73 bool MatchingInlineAsm) override;
75 // Auto-generated instruction matching functions
76 #define GET_ASSEMBLER_HEADER
77 #include "LanaiGenAsmMatcher.inc"
79 OperandMatchResultTy parseOperand(OperandVector *Operands,
80 StringRef Mnemonic);
82 OperandMatchResultTy parseMemoryOperand(OperandVector &Operands);
84 public:
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(SubtargetInfo.getFeatureBits()));
93 private:
94 MCAsmParser &Parser;
95 MCAsmLexer &Lexer;
97 const MCSubtargetInfo &SubtargetInfo;
100 // LanaiOperand - Instances of this class represented a parsed machine
101 // instruction
102 struct 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;
112 SMLoc StartLoc, EndLoc;
114 struct Token {
115 const char *Data;
116 unsigned Length;
119 struct RegOp {
120 unsigned RegNum;
123 struct ImmOp {
124 const MCExpr *Value;
127 struct MemOp {
128 unsigned BaseReg;
129 unsigned OffsetReg;
130 unsigned AluOp;
131 const MCExpr *Offset;
134 union {
135 struct Token Tok;
136 struct RegOp Reg;
137 struct ImmOp Imm;
138 struct MemOp Mem;
141 explicit LanaiOperand(KindTy Kind) : MCParsedAsmOperand(), Kind(Kind) {}
143 public:
144 // The functions below are used by the autogenerated ASM matcher and hence to
145 // be of the form expected.
147 // getStartLoc - Gets location of the first token of this operand
148 SMLoc getStartLoc() const override { return StartLoc; }
150 // getEndLoc - Gets location of the last token of this operand
151 SMLoc getEndLoc() const override { return EndLoc; }
153 unsigned getReg() const override {
154 assert(isReg() && "Invalid type access!");
155 return Reg.RegNum;
158 const MCExpr *getImm() const {
159 assert(isImm() && "Invalid type access!");
160 return Imm.Value;
163 StringRef getToken() const {
164 assert(isToken() && "Invalid type access!");
165 return StringRef(Tok.Data, Tok.Length);
168 unsigned getMemBaseReg() const {
169 assert(isMem() && "Invalid type access!");
170 return Mem.BaseReg;
173 unsigned getMemOffsetReg() const {
174 assert(isMem() && "Invalid type access!");
175 return Mem.OffsetReg;
178 const MCExpr *getMemOffset() const {
179 assert(isMem() && "Invalid type access!");
180 return Mem.Offset;
183 unsigned getMemOp() const {
184 assert(isMem() && "Invalid type access!");
185 return Mem.AluOp;
188 // Functions for testing operand type
189 bool isReg() const override { return Kind == REGISTER; }
191 bool isImm() const override { return Kind == IMMEDIATE; }
193 bool isMem() const override {
194 return isMemImm() || isMemRegImm() || isMemRegReg();
197 bool isMemImm() const { return Kind == MEMORY_IMM; }
199 bool isMemRegImm() const { return Kind == MEMORY_REG_IMM; }
201 bool isMemRegReg() const { return Kind == MEMORY_REG_REG; }
203 bool isMemSpls() const { return isMemRegImm() || isMemRegReg(); }
205 bool isToken() const override { return Kind == TOKEN; }
207 bool isBrImm() {
208 if (!isImm())
209 return false;
211 // Constant case
212 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(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>(static_cast<int32_t>(Value));
220 bool isBrTarget() { return isBrImm() || isToken(); }
222 bool isCallTarget() { return isImm() || isToken(); }
224 bool isHiImm16() {
225 if (!isImm())
226 return false;
228 // Constant case
229 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
230 int64_t Value = ConstExpr->getValue();
231 return Value != 0 && isShiftedUInt<16, 16>(Value);
234 // Symbolic reference expression
235 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
236 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
238 // Binary expression
239 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
240 if (const LanaiMCExpr *SymbolRefExpr =
241 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
242 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
244 return false;
247 bool isHiImm16And() {
248 if (!isImm())
249 return false;
251 const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(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);
257 return false;
260 bool isLoImm16() {
261 if (!isImm())
262 return false;
264 // Constant case
265 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
266 int64_t Value = ConstExpr->getValue();
267 // Check if value fits in 16 bits
268 return isUInt<16>(static_cast<int32_t>(Value));
271 // Symbolic reference expression
272 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
273 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
275 // Binary expression
276 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
277 if (const LanaiMCExpr *SymbolRefExpr =
278 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
279 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
281 return false;
284 bool isLoImm16Signed() {
285 if (!isImm())
286 return false;
288 // Constant case
289 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(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>(static_cast<int32_t>(Value));
295 // Symbolic reference expression
296 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
297 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
299 // Binary expression
300 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
301 if (const LanaiMCExpr *SymbolRefExpr =
302 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
303 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
305 return false;
308 bool isLoImm16And() {
309 if (!isImm())
310 return false;
312 const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
313 if (ConstExpr) {
314 int64_t Value = ConstExpr->getValue();
315 // Check if in the form 0xffffXYZW
316 return ((Value & ~0xffff) == 0xffff0000);
318 return false;
321 bool isImmShift() {
322 if (!isImm())
323 return false;
325 const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
326 if (!ConstExpr)
327 return false;
328 int64_t Value = ConstExpr->getValue();
329 return (Value >= -31) && (Value <= 31);
332 bool isLoImm21() {
333 if (!isImm())
334 return false;
336 // Constant case
337 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
338 int64_t Value = ConstExpr->getValue();
339 return isUInt<21>(Value);
342 // Symbolic reference expression
343 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
344 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
345 if (const MCSymbolRefExpr *SymbolRefExpr =
346 dyn_cast<MCSymbolRefExpr>(Imm.Value)) {
347 return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
350 // Binary expression
351 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) {
352 if (const LanaiMCExpr *SymbolRefExpr =
353 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
354 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
355 if (const MCSymbolRefExpr *SymbolRefExpr =
356 dyn_cast<MCSymbolRefExpr>(BinaryExpr->getLHS()))
357 return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
360 return false;
363 bool isImm10() {
364 if (!isImm())
365 return false;
367 const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
368 if (!ConstExpr)
369 return false;
370 int64_t Value = ConstExpr->getValue();
371 return isInt<10>(Value);
374 bool isCondCode() {
375 if (!isImm())
376 return false;
378 const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(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;
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(MCOperand::createImm(0));
392 else if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Expr))
393 Inst.addOperand(
394 MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
395 else
396 Inst.addOperand(MCOperand::createExpr(Expr));
399 void addRegOperands(MCInst &Inst, unsigned N) const {
400 assert(N == 1 && "Invalid number of operands!");
401 Inst.addOperand(MCOperand::createReg(getReg()));
404 void addImmOperands(MCInst &Inst, unsigned N) const {
405 assert(N == 1 && "Invalid number of operands!");
406 addExpr(Inst, getImm());
409 void addBrTargetOperands(MCInst &Inst, unsigned N) const {
410 assert(N == 1 && "Invalid number of operands!");
411 addExpr(Inst, getImm());
414 void addCallTargetOperands(MCInst &Inst, unsigned N) const {
415 assert(N == 1 && "Invalid number of operands!");
416 addExpr(Inst, getImm());
419 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
420 assert(N == 1 && "Invalid number of operands!");
421 addExpr(Inst, getImm());
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);
430 void addMemRegImmOperands(MCInst &Inst, unsigned N) const {
431 assert(N == 3 && "Invalid number of operands!");
432 Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
433 const MCExpr *Expr = getMemOffset();
434 addExpr(Inst, Expr);
435 Inst.addOperand(MCOperand::createImm(getMemOp()));
438 void addMemRegRegOperands(MCInst &Inst, unsigned N) const {
439 assert(N == 3 && "Invalid number of operands!");
440 Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
441 assert(getMemOffsetReg() != 0 && "Invalid offset");
442 Inst.addOperand(MCOperand::createReg(getMemOffsetReg()));
443 Inst.addOperand(MCOperand::createImm(getMemOp()));
446 void addMemSplsOperands(MCInst &Inst, unsigned N) const {
447 if (isMemRegImm())
448 addMemRegImmOperands(Inst, N);
449 if (isMemRegReg())
450 addMemRegRegOperands(Inst, N);
453 void addImmShiftOperands(MCInst &Inst, unsigned N) const {
454 assert(N == 1 && "Invalid number of operands!");
455 addExpr(Inst, getImm());
458 void addImm10Operands(MCInst &Inst, unsigned N) const {
459 assert(N == 1 && "Invalid number of operands!");
460 addExpr(Inst, getImm());
463 void addLoImm16Operands(MCInst &Inst, unsigned N) const {
464 assert(N == 1 && "Invalid number of operands!");
465 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
466 Inst.addOperand(
467 MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
468 else if (isa<LanaiMCExpr>(getImm())) {
469 #ifndef NDEBUG
470 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
471 assert(SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO);
472 #endif
473 Inst.addOperand(MCOperand::createExpr(getImm()));
474 } else if (isa<MCBinaryExpr>(getImm())) {
475 #ifndef NDEBUG
476 const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
477 assert(isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
478 cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
479 LanaiMCExpr::VK_Lanai_ABS_LO);
480 #endif
481 Inst.addOperand(MCOperand::createExpr(getImm()));
482 } else
483 assert(false && "Operand type not supported.");
486 void addLoImm16AndOperands(MCInst &Inst, unsigned N) const {
487 assert(N == 1 && "Invalid number of operands!");
488 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
489 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff));
490 else
491 assert(false && "Operand type not supported.");
494 void addHiImm16Operands(MCInst &Inst, unsigned N) const {
495 assert(N == 1 && "Invalid number of operands!");
496 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
497 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
498 else if (isa<LanaiMCExpr>(getImm())) {
499 #ifndef NDEBUG
500 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
501 assert(SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI);
502 #endif
503 Inst.addOperand(MCOperand::createExpr(getImm()));
504 } else if (isa<MCBinaryExpr>(getImm())) {
505 #ifndef NDEBUG
506 const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
507 assert(isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
508 cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
509 LanaiMCExpr::VK_Lanai_ABS_HI);
510 #endif
511 Inst.addOperand(MCOperand::createExpr(getImm()));
512 } else
513 assert(false && "Operand type not supported.");
516 void addHiImm16AndOperands(MCInst &Inst, unsigned N) const {
517 assert(N == 1 && "Invalid number of operands!");
518 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
519 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
520 else
521 assert(false && "Operand type not supported.");
524 void addLoImm21Operands(MCInst &Inst, unsigned N) const {
525 assert(N == 1 && "Invalid number of operands!");
526 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
527 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff));
528 else if (isa<LanaiMCExpr>(getImm())) {
529 #ifndef NDEBUG
530 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
531 assert(SymbolRefExpr &&
532 SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
533 #endif
534 Inst.addOperand(MCOperand::createExpr(getImm()));
535 } else if (isa<MCSymbolRefExpr>(getImm())) {
536 #ifndef NDEBUG
537 const MCSymbolRefExpr *SymbolRefExpr =
538 dyn_cast<MCSymbolRefExpr>(getImm());
539 assert(SymbolRefExpr &&
540 SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None);
541 #endif
542 Inst.addOperand(MCOperand::createExpr(getImm()));
543 } else if (isa<MCBinaryExpr>(getImm())) {
544 #ifndef NDEBUG
545 const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
546 const LanaiMCExpr *SymbolRefExpr =
547 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
548 assert(SymbolRefExpr &&
549 SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
550 #endif
551 Inst.addOperand(MCOperand::createExpr(getImm()));
552 } else
553 assert(false && "Operand type not supported.");
556 void print(raw_ostream &OS) const override {
557 switch (Kind) {
558 case IMMEDIATE:
559 OS << "Imm: " << getImm() << "\n";
560 break;
561 case TOKEN:
562 OS << "Token: " << getToken() << "\n";
563 break;
564 case REGISTER:
565 OS << "Reg: %r" << getReg() << "\n";
566 break;
567 case MEMORY_IMM:
568 OS << "MemImm: " << *getMemOffset() << "\n";
569 break;
570 case MEMORY_REG_IMM:
571 OS << "MemRegImm: " << getMemBaseReg() << "+" << *getMemOffset() << "\n";
572 break;
573 case MEMORY_REG_REG:
574 assert(getMemOffset() == nullptr);
575 OS << "MemRegReg: " << getMemBaseReg() << "+"
576 << "%r" << getMemOffsetReg() << "\n";
577 break;
581 static std::unique_ptr<LanaiOperand> CreateToken(StringRef Str, SMLoc Start) {
582 auto Op = make_unique<LanaiOperand>(TOKEN);
583 Op->Tok.Data = Str.data();
584 Op->Tok.Length = Str.size();
585 Op->StartLoc = Start;
586 Op->EndLoc = Start;
587 return Op;
590 static std::unique_ptr<LanaiOperand> createReg(unsigned RegNum, SMLoc Start,
591 SMLoc End) {
592 auto Op = make_unique<LanaiOperand>(REGISTER);
593 Op->Reg.RegNum = RegNum;
594 Op->StartLoc = Start;
595 Op->EndLoc = End;
596 return Op;
599 static std::unique_ptr<LanaiOperand> createImm(const MCExpr *Value,
600 SMLoc Start, SMLoc End) {
601 auto Op = make_unique<LanaiOperand>(IMMEDIATE);
602 Op->Imm.Value = Value;
603 Op->StartLoc = Start;
604 Op->EndLoc = End;
605 return Op;
608 static std::unique_ptr<LanaiOperand>
609 MorphToMemImm(std::unique_ptr<LanaiOperand> Op) {
610 const MCExpr *Imm = Op->getImm();
611 Op->Kind = MEMORY_IMM;
612 Op->Mem.BaseReg = 0;
613 Op->Mem.AluOp = LPAC::ADD;
614 Op->Mem.OffsetReg = 0;
615 Op->Mem.Offset = Imm;
616 return Op;
619 static std::unique_ptr<LanaiOperand>
620 MorphToMemRegReg(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
621 unsigned AluOp) {
622 unsigned OffsetReg = Op->getReg();
623 Op->Kind = MEMORY_REG_REG;
624 Op->Mem.BaseReg = BaseReg;
625 Op->Mem.AluOp = AluOp;
626 Op->Mem.OffsetReg = OffsetReg;
627 Op->Mem.Offset = nullptr;
628 return Op;
631 static std::unique_ptr<LanaiOperand>
632 MorphToMemRegImm(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
633 unsigned AluOp) {
634 const MCExpr *Imm = Op->getImm();
635 Op->Kind = MEMORY_REG_IMM;
636 Op->Mem.BaseReg = BaseReg;
637 Op->Mem.AluOp = AluOp;
638 Op->Mem.OffsetReg = 0;
639 Op->Mem.Offset = Imm;
640 return Op;
644 } // end anonymous namespace
646 bool LanaiAsmParser::ParseDirective(AsmToken /*DirectiveId*/) { return true; }
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;
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");
671 ErrorLoc = ((LanaiOperand &)*Operands[ErrorInfo]).getStartLoc();
672 if (ErrorLoc == SMLoc())
673 ErrorLoc = IdLoc;
675 return Error(ErrorLoc, "Invalid operand for instruction");
677 default:
678 break;
681 llvm_unreachable("Unknown match type detected!");
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> LanaiAsmParser::parseRegister() {
689 SMLoc Start = Parser.getTok().getLoc();
690 SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
692 unsigned RegNum;
693 // Eat the '%'.
694 if (Lexer.getKind() == AsmToken::Percent)
695 Parser.Lex();
696 if (Lexer.getKind() == AsmToken::Identifier) {
697 RegNum = MatchRegisterName(Lexer.getTok().getIdentifier());
698 if (RegNum == 0)
699 return nullptr;
700 Parser.Lex(); // Eat identifier token
701 return LanaiOperand::createReg(RegNum, Start, End);
703 return nullptr;
706 bool LanaiAsmParser::ParseRegister(unsigned &RegNum, SMLoc &StartLoc,
707 SMLoc &EndLoc) {
708 const AsmToken &Tok = getParser().getTok();
709 StartLoc = Tok.getLoc();
710 EndLoc = Tok.getEndLoc();
711 std::unique_ptr<LanaiOperand> Op = parseRegister();
712 if (Op != nullptr)
713 RegNum = Op->getReg();
714 return (Op == nullptr);
717 std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {
718 SMLoc Start = Parser.getTok().getLoc();
719 SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
720 const MCExpr *Res, *RHS = nullptr;
721 LanaiMCExpr::VariantKind Kind = LanaiMCExpr::VK_Lanai_None;
723 if (Lexer.getKind() != AsmToken::Identifier)
724 return nullptr;
726 StringRef Identifier;
727 if (Parser.parseIdentifier(Identifier))
728 return nullptr;
730 // Check if identifier has a modifier
731 if (Identifier.equals_lower("hi"))
732 Kind = LanaiMCExpr::VK_Lanai_ABS_HI;
733 else if (Identifier.equals_lower("lo"))
734 Kind = LanaiMCExpr::VK_Lanai_ABS_LO;
736 // If the identifier corresponds to a variant then extract the real
737 // identifier.
738 if (Kind != LanaiMCExpr::VK_Lanai_None) {
739 if (Lexer.getKind() != AsmToken::LParen) {
740 Error(Lexer.getLoc(), "Expected '('");
741 return nullptr;
743 Lexer.Lex(); // lex '('
745 // Parse identifier
746 if (Parser.parseIdentifier(Identifier))
747 return nullptr;
750 // If addition parse the RHS.
751 if (Lexer.getKind() == AsmToken::Plus && Parser.parseExpression(RHS))
752 return nullptr;
754 // For variants parse the final ')'
755 if (Kind != LanaiMCExpr::VK_Lanai_None) {
756 if (Lexer.getKind() != AsmToken::RParen) {
757 Error(Lexer.getLoc(), "Expected ')'");
758 return nullptr;
760 Lexer.Lex(); // lex ')'
763 End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
764 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
765 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
766 Res = LanaiMCExpr::create(Kind, Expr, getContext());
768 // Nest if this was an addition
769 if (RHS)
770 Res = MCBinaryExpr::createAdd(Res, RHS, getContext());
772 return LanaiOperand::createImm(Res, Start, End);
775 std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {
776 SMLoc Start = Parser.getTok().getLoc();
777 SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
779 const MCExpr *ExprVal;
780 switch (Lexer.getKind()) {
781 case AsmToken::Identifier:
782 return parseIdentifier();
783 case AsmToken::Plus:
784 case AsmToken::Minus:
785 case AsmToken::Integer:
786 case AsmToken::Dot:
787 if (!Parser.parseExpression(ExprVal))
788 return LanaiOperand::createImm(ExprVal, Start, End);
789 LLVM_FALLTHROUGH;
790 default:
791 return nullptr;
795 static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) {
796 if (PreOp)
797 return LPAC::makePreOp(AluCode);
798 if (PostOp)
799 return LPAC::makePostOp(AluCode);
800 return AluCode;
803 unsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) {
804 StringRef IdString;
805 Parser.parseIdentifier(IdString);
806 unsigned AluCode = LPAC::stringToLanaiAluCode(IdString);
807 if (AluCode == LPAC::UNKNOWN) {
808 Error(Parser.getTok().getLoc(), "Can't parse ALU operator");
809 return 0;
811 return AluCode;
814 static int SizeForSuffix(StringRef T) {
815 return StringSwitch<int>(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4);
818 bool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) {
819 bool PreOrPost = false;
820 if (Lexer.getKind() == Lexer.peekTok(true).getKind()) {
821 PreOrPost = true;
822 if (Lexer.is(AsmToken::Minus))
823 *OffsetValue = -SizeForSuffix(Type);
824 else if (Lexer.is(AsmToken::Plus))
825 *OffsetValue = SizeForSuffix(Type);
826 else
827 return false;
829 // Eat the '-' '-' or '+' '+'
830 Parser.Lex();
831 Parser.Lex();
832 } else if (Lexer.is(AsmToken::Star)) {
833 Parser.Lex(); // Eat the '*'
834 PreOrPost = true;
837 return PreOrPost;
840 bool shouldBeSls(const LanaiOperand &Op) {
841 // The instruction should be encoded as an SLS if the constant is word
842 // aligned and will fit in 21 bits
843 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm())) {
844 int64_t Value = ConstExpr->getValue();
845 return (Value % 4 == 0) && (Value >= 0) && (Value <= 0x1fffff);
847 // The instruction should be encoded as an SLS if the operand is a symbolic
848 // reference with no variant.
849 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Op.getImm()))
850 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
851 // The instruction should be encoded as an SLS if the operand is a binary
852 // expression with the left-hand side being a symbolic reference with no
853 // variant.
854 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Op.getImm())) {
855 const LanaiMCExpr *LHSSymbolRefExpr =
856 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
857 return (LHSSymbolRefExpr &&
858 LHSSymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
860 return false;
863 // Matches memory operand. Returns true if error encountered.
864 OperandMatchResultTy
865 LanaiAsmParser::parseMemoryOperand(OperandVector &Operands) {
866 // Try to match a memory operand.
867 // The memory operands are of the form:
868 // (1) Register|Immediate|'' '[' '*'? Register '*'? ']' or
869 // ^
870 // (2) '[' '*'? Register '*'? AluOperator Register ']'
871 // ^
872 // (3) '[' '--'|'++' Register '--'|'++' ']'
874 // (4) '[' Immediate ']' (for SLS)
876 // Store the type for use in parsing pre/post increment/decrement operators
877 StringRef Type;
878 if (Operands[0]->isToken())
879 Type = static_cast<LanaiOperand *>(Operands[0].get())->getToken();
881 // Use 0 if no offset given
882 int OffsetValue = 0;
883 unsigned BaseReg = 0;
884 unsigned AluOp = LPAC::ADD;
885 bool PostOp = false, PreOp = false;
887 // Try to parse the offset
888 std::unique_ptr<LanaiOperand> Op = parseRegister();
889 if (!Op)
890 Op = parseImmediate();
892 // Only continue if next token is '['
893 if (Lexer.isNot(AsmToken::LBrac)) {
894 if (!Op)
895 return MatchOperand_NoMatch;
897 // The start of this custom parsing overlaps with register/immediate so
898 // consider this as a successful match of an operand of that type as the
899 // token stream can't be rewound to allow them to match separately.
900 Operands.push_back(std::move(Op));
901 return MatchOperand_Success;
904 Parser.Lex(); // Eat the '['.
905 std::unique_ptr<LanaiOperand> Offset = nullptr;
906 if (Op)
907 Offset.swap(Op);
909 // Determine if a pre operation
910 PreOp = parsePrePost(Type, &OffsetValue);
912 Op = parseRegister();
913 if (!Op) {
914 if (!Offset) {
915 if ((Op = parseImmediate()) && Lexer.is(AsmToken::RBrac)) {
916 Parser.Lex(); // Eat the ']'
918 // Memory address operations aligned to word boundary are encoded as
919 // SLS, the rest as RM.
920 if (shouldBeSls(*Op)) {
921 Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op)));
922 } else {
923 if (!Op->isLoImm16Signed()) {
924 Error(Parser.getTok().getLoc(),
925 "Memory address is not word "
926 "aligned and larger than class RM can handle");
927 return MatchOperand_ParseFail;
929 Operands.push_back(LanaiOperand::MorphToMemRegImm(
930 Lanai::R0, std::move(Op), LPAC::ADD));
932 return MatchOperand_Success;
936 Error(Parser.getTok().getLoc(),
937 "Unknown operand, expected register or immediate");
938 return MatchOperand_ParseFail;
940 BaseReg = Op->getReg();
942 // Determine if a post operation
943 if (!PreOp)
944 PostOp = parsePrePost(Type, &OffsetValue);
946 // If ] match form (1) else match form (2)
947 if (Lexer.is(AsmToken::RBrac)) {
948 Parser.Lex(); // Eat the ']'.
949 if (!Offset) {
950 SMLoc Start = Parser.getTok().getLoc();
951 SMLoc End =
952 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
953 const MCConstantExpr *OffsetConstExpr =
954 MCConstantExpr::create(OffsetValue, getContext());
955 Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End);
957 } else {
958 if (Offset || OffsetValue != 0) {
959 Error(Parser.getTok().getLoc(), "Expected ']'");
960 return MatchOperand_ParseFail;
963 // Parse operator
964 AluOp = parseAluOperator(PreOp, PostOp);
966 // Second form requires offset register
967 Offset = parseRegister();
968 if (!BaseReg || Lexer.isNot(AsmToken::RBrac)) {
969 Error(Parser.getTok().getLoc(), "Expected ']'");
970 return MatchOperand_ParseFail;
972 Parser.Lex(); // Eat the ']'.
975 // First form has addition as operator. Add pre- or post-op indicator as
976 // needed.
977 AluOp = AluWithPrePost(AluOp, PreOp, PostOp);
979 // Ensure immediate offset is not too large
980 if (Offset->isImm() && !Offset->isLoImm16Signed()) {
981 Error(Parser.getTok().getLoc(),
982 "Memory address is not word "
983 "aligned and larger than class RM can handle");
984 return MatchOperand_ParseFail;
987 Operands.push_back(
988 Offset->isImm()
989 ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp)
990 : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp));
992 return MatchOperand_Success;
995 // Looks at a token type and creates the relevant operand from this
996 // information, adding to operands.
997 // If operand was parsed, returns false, else true.
998 OperandMatchResultTy
999 LanaiAsmParser::parseOperand(OperandVector *Operands, StringRef Mnemonic) {
1000 // Check if the current operand has a custom associated parser, if so, try to
1001 // custom parse the operand, or fallback to the general approach.
1002 OperandMatchResultTy Result = MatchOperandParserImpl(*Operands, Mnemonic);
1004 if (Result == MatchOperand_Success)
1005 return Result;
1006 if (Result == MatchOperand_ParseFail) {
1007 Parser.eatToEndOfStatement();
1008 return Result;
1011 // Attempt to parse token as register
1012 std::unique_ptr<LanaiOperand> Op = parseRegister();
1014 // Attempt to parse token as immediate
1015 if (!Op)
1016 Op = parseImmediate();
1018 // If the token could not be parsed then fail
1019 if (!Op) {
1020 Error(Parser.getTok().getLoc(), "Unknown operand");
1021 Parser.eatToEndOfStatement();
1022 return MatchOperand_ParseFail;
1025 // Push back parsed operand into list of operands
1026 Operands->push_back(std::move(Op));
1028 return MatchOperand_Success;
1031 // Split the mnemonic into ASM operand, conditional code and instruction
1032 // qualifier (half-word, byte).
1033 StringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
1034 OperandVector *Operands) {
1035 size_t Next = Name.find('.');
1037 StringRef Mnemonic = Name;
1039 bool IsBRR = false;
1040 if (Name.endswith(".r")) {
1041 Mnemonic = Name.substr(0, Name.size() - 2);
1042 IsBRR = true;
1045 // Match b?? and s?? (BR, BRR, and SCC instruction classes).
1046 if (Mnemonic[0] == 'b' ||
1047 (Mnemonic[0] == 's' && !Mnemonic.startswith("sel") &&
1048 !Mnemonic.startswith("st"))) {
1049 // Parse instructions with a conditional code. For example, 'bne' is
1050 // converted into two operands 'b' and 'ne'.
1051 LPCC::CondCode CondCode =
1052 LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next));
1053 if (CondCode != LPCC::UNKNOWN) {
1054 Mnemonic = Mnemonic.slice(0, 1);
1055 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1056 Operands->push_back(LanaiOperand::createImm(
1057 MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1058 if (IsBRR) {
1059 Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1061 return Mnemonic;
1065 // Parse other instructions with condition codes (RR instructions).
1066 // We ignore .f here and assume they are flag-setting operations, not
1067 // conditional codes (except for select instructions where flag-setting
1068 // variants are not yet implemented).
1069 if (Mnemonic.startswith("sel") ||
1070 (!Mnemonic.endswith(".f") && !Mnemonic.startswith("st"))) {
1071 LPCC::CondCode CondCode = LPCC::suffixToLanaiCondCode(Mnemonic);
1072 if (CondCode != LPCC::UNKNOWN) {
1073 size_t Next = Mnemonic.rfind('.', Name.size());
1074 // 'sel' doesn't use a predicate operand whose printer adds the period,
1075 // but instead has the period as part of the identifier (i.e., 'sel.' is
1076 // expected by the generated matcher). If the mnemonic starts with 'sel'
1077 // then include the period as part of the mnemonic, else don't include it
1078 // as part of the mnemonic.
1079 if (Mnemonic.startswith("sel")) {
1080 Mnemonic = Mnemonic.substr(0, Next + 1);
1081 } else {
1082 Mnemonic = Mnemonic.substr(0, Next);
1084 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1085 Operands->push_back(LanaiOperand::createImm(
1086 MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1087 return Mnemonic;
1091 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1092 if (IsBRR) {
1093 Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1096 return Mnemonic;
1099 static bool IsMemoryAssignmentError(const OperandVector &Operands) {
1100 // Detects if a memory operation has an erroneous base register modification.
1101 // Memory operations are detected by matching the types of operands.
1103 // TODO: This test is focussed on one specific instance (ld/st).
1104 // Extend it to handle more cases or be more robust.
1105 bool Modifies = false;
1107 int Offset = 0;
1109 if (Operands.size() < 5)
1110 return false;
1111 else if (Operands[0]->isToken() && Operands[1]->isReg() &&
1112 Operands[2]->isImm() && Operands[3]->isImm() && Operands[4]->isReg())
1113 Offset = 0;
1114 else if (Operands[0]->isToken() && Operands[1]->isToken() &&
1115 Operands[2]->isReg() && Operands[3]->isImm() &&
1116 Operands[4]->isImm() && Operands[5]->isReg())
1117 Offset = 1;
1118 else
1119 return false;
1121 int PossibleAluOpIdx = Offset + 3;
1122 int PossibleBaseIdx = Offset + 1;
1123 int PossibleDestIdx = Offset + 4;
1124 if (LanaiOperand *PossibleAluOp =
1125 static_cast<LanaiOperand *>(Operands[PossibleAluOpIdx].get()))
1126 if (PossibleAluOp->isImm())
1127 if (const MCConstantExpr *ConstExpr =
1128 dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))
1129 Modifies = LPAC::modifiesOp(ConstExpr->getValue());
1130 return Modifies && Operands[PossibleBaseIdx]->isReg() &&
1131 Operands[PossibleDestIdx]->isReg() &&
1132 Operands[PossibleBaseIdx]->getReg() ==
1133 Operands[PossibleDestIdx]->getReg();
1136 static bool IsRegister(const MCParsedAsmOperand &op) {
1137 return static_cast<const LanaiOperand &>(op).isReg();
1140 static bool MaybePredicatedInst(const OperandVector &Operands) {
1141 if (Operands.size() < 4 || !IsRegister(*Operands[1]) ||
1142 !IsRegister(*Operands[2]))
1143 return false;
1144 return StringSwitch<bool>(
1145 static_cast<const LanaiOperand &>(*Operands[0]).getToken())
1146 .StartsWith("addc", true)
1147 .StartsWith("add", true)
1148 .StartsWith("and", true)
1149 .StartsWith("sh", true)
1150 .StartsWith("subb", true)
1151 .StartsWith("sub", true)
1152 .StartsWith("or", true)
1153 .StartsWith("xor", true)
1154 .Default(false);
1157 bool LanaiAsmParser::ParseInstruction(ParseInstructionInfo & /*Info*/,
1158 StringRef Name, SMLoc NameLoc,
1159 OperandVector &Operands) {
1160 // First operand is token for instruction
1161 StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);
1163 // If there are no more operands, then finish
1164 if (Lexer.is(AsmToken::EndOfStatement))
1165 return false;
1167 // Parse first operand
1168 if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success)
1169 return true;
1171 // If it is a st instruction with one 1 operand then it is a "store true".
1172 // Transform <"st"> to <"s">, <LPCC:ICC_T>
1173 if (Lexer.is(AsmToken::EndOfStatement) && Name == "st" &&
1174 Operands.size() == 2) {
1175 Operands.erase(Operands.begin(), Operands.begin() + 1);
1176 Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc));
1177 Operands.insert(Operands.begin() + 1,
1178 LanaiOperand::createImm(
1179 MCConstantExpr::create(LPCC::ICC_T, getContext()),
1180 NameLoc, NameLoc));
1183 // If the instruction is a bt instruction with 1 operand (in assembly) then it
1184 // is an unconditional branch instruction and the first two elements of
1185 // operands need to be merged.
1186 if (Lexer.is(AsmToken::EndOfStatement) && Name.startswith("bt") &&
1187 Operands.size() == 3) {
1188 Operands.erase(Operands.begin(), Operands.begin() + 2);
1189 Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc));
1192 // Parse until end of statement, consuming commas between operands
1193 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.is(AsmToken::Comma)) {
1194 // Consume comma token
1195 Lex();
1197 // Parse next operand
1198 if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success)
1199 return true;
1202 if (IsMemoryAssignmentError(Operands)) {
1203 Error(Parser.getTok().getLoc(),
1204 "the destination register can't equal the base register in an "
1205 "instruction that modifies the base register.");
1206 return true;
1209 // Insert always true operand for instruction that may be predicated but
1210 // are not. Currently the autogenerated parser always expects a predicate.
1211 if (MaybePredicatedInst(Operands)) {
1212 Operands.insert(Operands.begin() + 1,
1213 LanaiOperand::createImm(
1214 MCConstantExpr::create(LPCC::ICC_T, getContext()),
1215 NameLoc, NameLoc));
1218 return false;
1221 #define GET_REGISTER_MATCHER
1222 #define GET_MATCHER_IMPLEMENTATION
1223 #include "LanaiGenAsmMatcher.inc"
1225 extern "C" void LLVMInitializeLanaiAsmParser() {
1226 RegisterMCAsmParser<LanaiAsmParser> x(getTheLanaiTarget());