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