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