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