LLVM 20.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/STLExtras.h"
15#include "llvm/ADT/StringRef.h"
17#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
24#include "llvm/MC/MCStreamer.h"
26#include "llvm/MC/MCSymbol.h"
31#include "llvm/Support/SMLoc.h"
33#include <algorithm>
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
66 SMLoc NameLoc, OperandVector &Operands) override;
67
68 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
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, const MCTargetOptions &Options)
88 : MCTargetAsmParser(Options, STI, MII), Parser(Parser),
89 Lexer(Parser.getLexer()), SubtargetInfo(STI) {
91 ComputeAvailableFeatures(SubtargetInfo.getFeatureBits()));
92 }
93
94private:
95 MCAsmParser &Parser;
96 MCAsmLexer &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 unsigned RegNum;
122 };
123
124 struct ImmOp {
125 const MCExpr *Value;
126 };
127
128 struct MemOp {
129 unsigned BaseReg;
130 unsigned 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 unsigned getMemBaseReg() const {
170 assert(isMem() && "Invalid type access!");
171 return Mem.BaseReg;
172 }
173
174 unsigned 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 LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
237 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
238
239 // Binary expression
240 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
241 if (const LanaiMCExpr *SymbolRefExpr =
242 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
243 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;
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 LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
274 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
275
276 // Binary expression
277 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
278 if (const LanaiMCExpr *SymbolRefExpr =
279 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
280 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
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 LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
298 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
299
300 // Binary expression
301 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
302 if (const LanaiMCExpr *SymbolRefExpr =
303 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
304 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;
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 LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
345 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
346 if (const MCSymbolRefExpr *SymbolRefExpr =
347 dyn_cast<MCSymbolRefExpr>(Imm.Value)) {
348 return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
349 }
350
351 // Binary expression
352 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) {
353 if (const LanaiMCExpr *SymbolRefExpr =
354 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
355 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
356 if (const MCSymbolRefExpr *SymbolRefExpr =
357 dyn_cast<MCSymbolRefExpr>(BinaryExpr->getLHS()))
358 return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
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() != 0 && "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<LanaiMCExpr>(getImm())) {
470#ifndef NDEBUG
471 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
472 assert(SymbolRefExpr &&
473 SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO);
474#endif
475 Inst.addOperand(MCOperand::createExpr(getImm()));
476 } else if (isa<MCBinaryExpr>(getImm())) {
477#ifndef NDEBUG
478 const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
479 assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
480 cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
482#endif
483 Inst.addOperand(MCOperand::createExpr(getImm()));
484 } else
485 assert(false && "Operand type not supported.");
486 }
487
488 void addLoImm16AndOperands(MCInst &Inst, unsigned N) const {
489 assert(N == 1 && "Invalid number of operands!");
490 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
491 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff));
492 else
493 assert(false && "Operand type not supported.");
494 }
495
496 void addHiImm16Operands(MCInst &Inst, unsigned N) const {
497 assert(N == 1 && "Invalid number of operands!");
498 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
499 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
500 else if (isa<LanaiMCExpr>(getImm())) {
501#ifndef NDEBUG
502 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
503 assert(SymbolRefExpr &&
504 SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI);
505#endif
506 Inst.addOperand(MCOperand::createExpr(getImm()));
507 } else if (isa<MCBinaryExpr>(getImm())) {
508#ifndef NDEBUG
509 const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
510 assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
511 cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
513#endif
514 Inst.addOperand(MCOperand::createExpr(getImm()));
515 } else
516 assert(false && "Operand type not supported.");
517 }
518
519 void addHiImm16AndOperands(MCInst &Inst, unsigned N) const {
520 assert(N == 1 && "Invalid number of operands!");
521 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
522 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
523 else
524 assert(false && "Operand type not supported.");
525 }
526
527 void addLoImm21Operands(MCInst &Inst, unsigned N) const {
528 assert(N == 1 && "Invalid number of operands!");
529 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
530 Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff));
531 else if (isa<LanaiMCExpr>(getImm())) {
532#ifndef NDEBUG
533 const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
534 assert(SymbolRefExpr &&
535 SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
536#endif
537 Inst.addOperand(MCOperand::createExpr(getImm()));
538 } else if (isa<MCSymbolRefExpr>(getImm())) {
539#ifndef NDEBUG
540 const MCSymbolRefExpr *SymbolRefExpr =
541 dyn_cast<MCSymbolRefExpr>(getImm());
542 assert(SymbolRefExpr &&
543 SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None);
544#endif
545 Inst.addOperand(MCOperand::createExpr(getImm()));
546 } else if (isa<MCBinaryExpr>(getImm())) {
547#ifndef NDEBUG
548 const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
549 assert(BinaryExpr && isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
550 cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
552#endif
553 Inst.addOperand(MCOperand::createExpr(getImm()));
554 } else
555 assert(false && "Operand type not supported.");
556 }
557
558 void print(raw_ostream &OS) const override {
559 switch (Kind) {
560 case IMMEDIATE:
561 OS << "Imm: " << getImm() << "\n";
562 break;
563 case TOKEN:
564 OS << "Token: " << getToken() << "\n";
565 break;
566 case REGISTER:
567 OS << "Reg: %r" << getReg() << "\n";
568 break;
569 case MEMORY_IMM:
570 OS << "MemImm: " << *getMemOffset() << "\n";
571 break;
572 case MEMORY_REG_IMM:
573 OS << "MemRegImm: " << getMemBaseReg() << "+" << *getMemOffset() << "\n";
574 break;
575 case MEMORY_REG_REG:
576 assert(getMemOffset() == nullptr);
577 OS << "MemRegReg: " << getMemBaseReg() << "+"
578 << "%r" << getMemOffsetReg() << "\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(unsigned RegNum, SMLoc Start,
593 SMLoc End) {
594 auto Op = std::make_unique<LanaiOperand>(REGISTER);
595 Op->Reg.RegNum = RegNum;
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 = 0;
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(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
623 unsigned AluOp) {
624 unsigned 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(unsigned 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 unsigned RegNum;
695 // Eat the '%'.
696 if (Lexer.getKind() == AsmToken::Percent) {
697 PercentTok = Parser.getTok();
698 Parser.Lex();
699 }
700 if (Lexer.getKind() == AsmToken::Identifier) {
701 RegNum = MatchRegisterName(Lexer.getTok().getIdentifier());
702 if (RegNum == 0) {
703 if (PercentTok && RestoreOnFailure)
704 Lexer.UnLex(*PercentTok);
705 return nullptr;
706 }
707 Parser.Lex(); // Eat identifier token
708 return LanaiOperand::createReg(RegNum, 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;
743
744 if (Lexer.getKind() != AsmToken::Identifier)
745 return nullptr;
746
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 != LanaiMCExpr::VK_Lanai_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 != LanaiMCExpr::VK_Lanai_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 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
787 Res = LanaiMCExpr::create(Kind, Expr, getContext());
788
789 // Nest if this was an addition
790 if (RHS)
791 Res = MCBinaryExpr::createAdd(Res, RHS, getContext());
792
793 return LanaiOperand::createImm(Res, Start, End);
794}
795
796std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {
797 SMLoc Start = Parser.getTok().getLoc();
798 SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
799
800 const MCExpr *ExprVal;
801 switch (Lexer.getKind()) {
803 return parseIdentifier();
804 case AsmToken::Plus:
805 case AsmToken::Minus:
807 case AsmToken::Dot:
808 if (!Parser.parseExpression(ExprVal))
809 return LanaiOperand::createImm(ExprVal, Start, End);
810 [[fallthrough]];
811 default:
812 return nullptr;
813 }
814}
815
816static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) {
817 if (PreOp)
818 return LPAC::makePreOp(AluCode);
819 if (PostOp)
820 return LPAC::makePostOp(AluCode);
821 return AluCode;
822}
823
824unsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) {
825 StringRef IdString;
826 Parser.parseIdentifier(IdString);
827 unsigned AluCode = LPAC::stringToLanaiAluCode(IdString);
828 if (AluCode == LPAC::UNKNOWN) {
829 Error(Parser.getTok().getLoc(), "Can't parse ALU operator");
830 return 0;
831 }
832 return AluCode;
833}
834
836 return StringSwitch<int>(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4);
837}
838
839bool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) {
840 bool PreOrPost = false;
841 if (Lexer.getKind() == Lexer.peekTok(true).getKind()) {
842 PreOrPost = true;
843 if (Lexer.is(AsmToken::Minus))
844 *OffsetValue = -SizeForSuffix(Type);
845 else if (Lexer.is(AsmToken::Plus))
846 *OffsetValue = SizeForSuffix(Type);
847 else
848 return false;
849
850 // Eat the '-' '-' or '+' '+'
851 Parser.Lex();
852 Parser.Lex();
853 } else if (Lexer.is(AsmToken::Star)) {
854 Parser.Lex(); // Eat the '*'
855 PreOrPost = true;
856 }
857
858 return PreOrPost;
859}
860
861bool shouldBeSls(const LanaiOperand &Op) {
862 // The instruction should be encoded as an SLS if the constant is word
863 // aligned and will fit in 21 bits
864 if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm())) {
865 int64_t Value = ConstExpr->getValue();
866 return (Value % 4 == 0) && (Value >= 0) && (Value <= 0x1fffff);
867 }
868 // The instruction should be encoded as an SLS if the operand is a symbolic
869 // reference with no variant.
870 if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Op.getImm()))
871 return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
872 // The instruction should be encoded as an SLS if the operand is a binary
873 // expression with the left-hand side being a symbolic reference with no
874 // variant.
875 if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Op.getImm())) {
876 const LanaiMCExpr *LHSSymbolRefExpr =
877 dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
878 return (LHSSymbolRefExpr &&
879 LHSSymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
880 }
881 return false;
882}
883
884// Matches memory operand. Returns true if error encountered.
885ParseStatus LanaiAsmParser::parseMemoryOperand(OperandVector &Operands) {
886 // Try to match a memory operand.
887 // The memory operands are of the form:
888 // (1) Register|Immediate|'' '[' '*'? Register '*'? ']' or
889 // ^
890 // (2) '[' '*'? Register '*'? AluOperator Register ']'
891 // ^
892 // (3) '[' '--'|'++' Register '--'|'++' ']'
893 //
894 // (4) '[' Immediate ']' (for SLS)
895
896 // Store the type for use in parsing pre/post increment/decrement operators
898 if (Operands[0]->isToken())
899 Type = static_cast<LanaiOperand *>(Operands[0].get())->getToken();
900
901 // Use 0 if no offset given
902 int OffsetValue = 0;
903 unsigned BaseReg = 0;
904 unsigned AluOp = LPAC::ADD;
905 bool PostOp = false, PreOp = false;
906
907 // Try to parse the offset
908 std::unique_ptr<LanaiOperand> Op = parseRegister();
909 if (!Op)
910 Op = parseImmediate();
911
912 // Only continue if next token is '['
913 if (Lexer.isNot(AsmToken::LBrac)) {
914 if (!Op)
916
917 // The start of this custom parsing overlaps with register/immediate so
918 // consider this as a successful match of an operand of that type as the
919 // token stream can't be rewound to allow them to match separately.
920 Operands.push_back(std::move(Op));
922 }
923
924 Parser.Lex(); // Eat the '['.
925 std::unique_ptr<LanaiOperand> Offset = nullptr;
926 if (Op)
927 Offset.swap(Op);
928
929 // Determine if a pre operation
930 PreOp = parsePrePost(Type, &OffsetValue);
931
932 Op = parseRegister();
933 if (!Op) {
934 if (!Offset) {
935 if ((Op = parseImmediate()) && Lexer.is(AsmToken::RBrac)) {
936 Parser.Lex(); // Eat the ']'
937
938 // Memory address operations aligned to word boundary are encoded as
939 // SLS, the rest as RM.
940 if (shouldBeSls(*Op)) {
941 Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op)));
942 } else {
943 if (!Op->isLoImm16Signed())
944 return Error(Parser.getTok().getLoc(),
945 "Memory address is not word aligned and larger than "
946 "class RM can handle");
947 Operands.push_back(LanaiOperand::MorphToMemRegImm(
948 Lanai::R0, std::move(Op), LPAC::ADD));
949 }
951 }
952 }
953
954 return Error(Parser.getTok().getLoc(),
955 "Unknown operand, expected register or immediate");
956 }
957 BaseReg = Op->getReg();
958
959 // Determine if a post operation
960 if (!PreOp)
961 PostOp = parsePrePost(Type, &OffsetValue);
962
963 // If ] match form (1) else match form (2)
964 if (Lexer.is(AsmToken::RBrac)) {
965 Parser.Lex(); // Eat the ']'.
966 if (!Offset) {
967 SMLoc Start = Parser.getTok().getLoc();
968 SMLoc End =
969 SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
970 const MCConstantExpr *OffsetConstExpr =
971 MCConstantExpr::create(OffsetValue, getContext());
972 Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End);
973 }
974 } else {
975 if (Offset || OffsetValue != 0)
976 return Error(Parser.getTok().getLoc(), "Expected ']'");
977
978 // Parse operator
979 AluOp = parseAluOperator(PreOp, PostOp);
980
981 // Second form requires offset register
982 Offset = parseRegister();
983 if (!BaseReg || Lexer.isNot(AsmToken::RBrac))
984 return Error(Parser.getTok().getLoc(), "Expected ']'");
985 Parser.Lex(); // Eat the ']'.
986 }
987
988 // First form has addition as operator. Add pre- or post-op indicator as
989 // needed.
990 AluOp = AluWithPrePost(AluOp, PreOp, PostOp);
991
992 // Ensure immediate offset is not too large
993 if (Offset->isImm() && !Offset->isLoImm16Signed())
994 return Error(Parser.getTok().getLoc(),
995 "Memory address is not word aligned and larger than class RM "
996 "can handle");
997
998 Operands.push_back(
999 Offset->isImm()
1000 ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp)
1001 : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp));
1002
1003 return ParseStatus::Success;
1004}
1005
1006// Looks at a token type and creates the relevant operand from this
1007// information, adding to operands.
1008// If operand was parsed, returns false, else true.
1009ParseStatus LanaiAsmParser::parseOperand(OperandVector *Operands,
1010 StringRef Mnemonic) {
1011 // Check if the current operand has a custom associated parser, if so, try to
1012 // custom parse the operand, or fallback to the general approach.
1013 ParseStatus Result = MatchOperandParserImpl(*Operands, Mnemonic);
1014
1015 if (Result.isSuccess())
1016 return Result;
1017 if (Result.isFailure()) {
1018 Parser.eatToEndOfStatement();
1019 return Result;
1020 }
1021
1022 // Attempt to parse token as register
1023 std::unique_ptr<LanaiOperand> Op = parseRegister();
1024
1025 // Attempt to parse token as immediate
1026 if (!Op)
1027 Op = parseImmediate();
1028
1029 // If the token could not be parsed then fail
1030 if (!Op) {
1031 Error(Parser.getTok().getLoc(), "Unknown operand");
1032 Parser.eatToEndOfStatement();
1033 return ParseStatus::Failure;
1034 }
1035
1036 // Push back parsed operand into list of operands
1037 Operands->push_back(std::move(Op));
1038
1039 return ParseStatus::Success;
1040}
1041
1042// Split the mnemonic into ASM operand, conditional code and instruction
1043// qualifier (half-word, byte).
1044StringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
1046 size_t Next = Name.find('.');
1047
1048 StringRef Mnemonic = Name;
1049
1050 bool IsBRR = Mnemonic.consume_back(".r");
1051
1052 // Match b?? and s?? (BR, BRR, and SCC instruction classes).
1053 if (Mnemonic[0] == 'b' ||
1054 (Mnemonic[0] == 's' && !Mnemonic.starts_with("sel") &&
1055 !Mnemonic.starts_with("st"))) {
1056 // Parse instructions with a conditional code. For example, 'bne' is
1057 // converted into two operands 'b' and 'ne'.
1059 LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next));
1060 if (CondCode != LPCC::UNKNOWN) {
1061 Mnemonic = Mnemonic.slice(0, 1);
1062 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1063 Operands->push_back(LanaiOperand::createImm(
1064 MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1065 if (IsBRR) {
1066 Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1067 }
1068 return Mnemonic;
1069 }
1070 }
1071
1072 // Parse other instructions with condition codes (RR instructions).
1073 // We ignore .f here and assume they are flag-setting operations, not
1074 // conditional codes (except for select instructions where flag-setting
1075 // variants are not yet implemented).
1076 if (Mnemonic.starts_with("sel") ||
1077 (!Mnemonic.ends_with(".f") && !Mnemonic.starts_with("st"))) {
1079 if (CondCode != LPCC::UNKNOWN) {
1080 size_t Next = Mnemonic.rfind('.', Name.size());
1081 // 'sel' doesn't use a predicate operand whose printer adds the period,
1082 // but instead has the period as part of the identifier (i.e., 'sel.' is
1083 // expected by the generated matcher). If the mnemonic starts with 'sel'
1084 // then include the period as part of the mnemonic, else don't include it
1085 // as part of the mnemonic.
1086 if (Mnemonic.starts_with("sel")) {
1087 Mnemonic = Mnemonic.substr(0, Next + 1);
1088 } else {
1089 Mnemonic = Mnemonic.substr(0, Next);
1090 }
1091 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1092 Operands->push_back(LanaiOperand::createImm(
1093 MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
1094 return Mnemonic;
1095 }
1096 }
1097
1098 Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
1099 if (IsBRR) {
1100 Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
1101 }
1102
1103 return Mnemonic;
1104}
1105
1107 // Detects if a memory operation has an erroneous base register modification.
1108 // Memory operations are detected by matching the types of operands.
1109 //
1110 // TODO: This test is focussed on one specific instance (ld/st).
1111 // Extend it to handle more cases or be more robust.
1112 bool Modifies = false;
1113
1114 int Offset = 0;
1115
1116 if (Operands.size() < 5)
1117 return false;
1118 else if (Operands[0]->isToken() && Operands[1]->isReg() &&
1119 Operands[2]->isImm() && Operands[3]->isImm() && Operands[4]->isReg())
1120 Offset = 0;
1121 else if (Operands[0]->isToken() && Operands[1]->isToken() &&
1122 Operands[2]->isReg() && Operands[3]->isImm() &&
1123 Operands[4]->isImm() && Operands[5]->isReg())
1124 Offset = 1;
1125 else
1126 return false;
1127
1128 int PossibleAluOpIdx = Offset + 3;
1129 int PossibleBaseIdx = Offset + 1;
1130 int PossibleDestIdx = Offset + 4;
1131 if (LanaiOperand *PossibleAluOp =
1132 static_cast<LanaiOperand *>(Operands[PossibleAluOpIdx].get()))
1133 if (PossibleAluOp->isImm())
1134 if (const MCConstantExpr *ConstExpr =
1135 dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))
1136 Modifies = LPAC::modifiesOp(ConstExpr->getValue());
1137 return Modifies && Operands[PossibleBaseIdx]->isReg() &&
1138 Operands[PossibleDestIdx]->isReg() &&
1139 Operands[PossibleBaseIdx]->getReg() ==
1140 Operands[PossibleDestIdx]->getReg();
1141}
1142
1143static bool IsRegister(const MCParsedAsmOperand &op) {
1144 return static_cast<const LanaiOperand &>(op).isReg();
1145}
1146
1148 if (Operands.size() < 4 || !IsRegister(*Operands[1]) ||
1149 !IsRegister(*Operands[2]))
1150 return false;
1151 return StringSwitch<bool>(
1152 static_cast<const LanaiOperand &>(*Operands[0]).getToken())
1153 .StartsWith("addc", true)
1154 .StartsWith("add", true)
1155 .StartsWith("and", true)
1156 .StartsWith("sh", true)
1157 .StartsWith("subb", true)
1158 .StartsWith("sub", true)
1159 .StartsWith("or", true)
1160 .StartsWith("xor", true)
1161 .Default(false);
1162}
1163
1164bool LanaiAsmParser::ParseInstruction(ParseInstructionInfo & /*Info*/,
1165 StringRef Name, SMLoc NameLoc,
1167 // First operand is token for instruction
1168 StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);
1169
1170 // If there are no more operands, then finish
1171 if (Lexer.is(AsmToken::EndOfStatement))
1172 return false;
1173
1174 // Parse first operand
1175 if (!parseOperand(&Operands, Mnemonic).isSuccess())
1176 return true;
1177
1178 // If it is a st instruction with one 1 operand then it is a "store true".
1179 // Transform <"st"> to <"s">, <LPCC:ICC_T>
1180 if (Lexer.is(AsmToken::EndOfStatement) && Name == "st" &&
1181 Operands.size() == 2) {
1182 Operands.erase(Operands.begin(), Operands.begin() + 1);
1183 Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc));
1184 Operands.insert(Operands.begin() + 1,
1185 LanaiOperand::createImm(
1186 MCConstantExpr::create(LPCC::ICC_T, getContext()),
1187 NameLoc, NameLoc));
1188 }
1189
1190 // If the instruction is a bt instruction with 1 operand (in assembly) then it
1191 // is an unconditional branch instruction and the first two elements of
1192 // operands need to be merged.
1193 if (Lexer.is(AsmToken::EndOfStatement) && Name.starts_with("bt") &&
1194 Operands.size() == 3) {
1195 Operands.erase(Operands.begin(), Operands.begin() + 2);
1196 Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc));
1197 }
1198
1199 // Parse until end of statement, consuming commas between operands
1200 while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.is(AsmToken::Comma)) {
1201 // Consume comma token
1202 Lex();
1203
1204 // Parse next operand
1205 if (!parseOperand(&Operands, Mnemonic).isSuccess())
1206 return true;
1207 }
1208
1210 Error(Parser.getTok().getLoc(),
1211 "the destination register can't equal the base register in an "
1212 "instruction that modifies the base register.");
1213 return true;
1214 }
1215
1216 // Insert always true operand for instruction that may be predicated but
1217 // are not. Currently the autogenerated parser always expects a predicate.
1219 Operands.insert(Operands.begin() + 1,
1220 LanaiOperand::createImm(
1221 MCConstantExpr::create(LPCC::ICC_T, getContext()),
1222 NameLoc, NameLoc));
1223 }
1224
1225 return false;
1226}
1227
1228#define GET_REGISTER_MATCHER
1229#define GET_MATCHER_IMPLEMENTATION
1230#include "LanaiGenAsmMatcher.inc"
1231
1234}
static bool addCallTargetOperands(MachineInstrBuilder &CallInst, MachineIRBuilder &MIRBuilder, AMDGPUCallLowering::CallLoweringInfo &Info)
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:131
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)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLanaiAsmParser()
static MCRegister MatchRegisterName(StringRef Name)
static bool MaybePredicatedInst(const OperandVector &Operands)
static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp)
static bool IsRegister(const MCParsedAsmOperand &op)
mir Rename Register Operands
unsigned Reg
static bool isReg(const MCInst &MI, unsigned OpNo)
#define TOKEN(Name)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI)
This file contains some templates that are useful if you are working with the STL at all.
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
Kind getKind() const
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:21
SMLoc getLoc() const
Definition: MCAsmLexer.cpp:26
SMLoc getEndLoc() const
Definition: MCAsmLexer.cpp:30
This class represents an Operation in the Expression.
Base class for user error types.
Definition: Error.h:355
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
VariantKind getKind() const
Definition: LanaiMCExpr.h:33
static const LanaiMCExpr * create(VariantKind Kind, const MCExpr *Expr, MCContext &Ctx)
Definition: LanaiMCExpr.cpp:17
Generic assembler lexer interface, for use by target specific assembly lexers.
Definition: MCAsmLexer.h:37
Generic assembler parser interface, for use by target specific assembly parsers.
Definition: MCAsmParser.h:123
Binary assembler expressions.
Definition: MCExpr.h:488
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:532
int64_t getValue() const
Definition: MCExpr.h:169
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:193
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:184
unsigned getOpcode() const
Definition: MCInst.h:198
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:162
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
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 void print(raw_ostream &OS) const =0
print - Print a debug representation of the operand to the given stream.
virtual bool isToken() const =0
isToken - Is this a token operand?
virtual bool isImm() const =0
isImm - Is this an immediate operand?
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
Streaming machine code generation interface.
Definition: MCStreamer.h:213
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:188
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:393
VariantKind getKind() const
Definition: MCExpr.h:408
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
MCTargetAsmParser - Generic interface to target specific assembly parsers.
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
void setAvailableFeatures(const FeatureBitset &Value)
virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands)=0
ParseInstruction - Parse one assembly instruction.
virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm)=0
MatchAndEmitInstruction - Recognize a series of operands of a parsed instruction as an actual MCInst ...
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:586
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool consume_back(StringRef Suffix)
Returns true if this StringRef has the given suffix and removes that suffix.
Definition: StringRef.h:640
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:556
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:250
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition: StringRef.h:669
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
Definition: StringRef.h:332
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition: StringRef.h:262
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
R Default(T Value)
Definition: StringSwitch.h:182
StringSwitch & StartsWith(StringLiteral S, T Value)
Definition: StringSwitch.h:83
StringSwitch & EndsWith(StringLiteral S, T Value)
Definition: StringSwitch.h:76
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:74
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#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:1603
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.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
@ Length
Definition: DWP.cpp:480
Target & getTheLanaiTarget()
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,...