LLVM 24.0.0git
XtensaAsmParser.cpp
Go to the documentation of this file.
1//===- XtensaAsmParser.cpp - Parse Xtensa assembly to MCInst instructions -===//
2//
3// The LLVM Compiler Infrastructure
4//
5// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6// See https://llvm.org/LICENSE.txt for license information.
7// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8//
9//===----------------------------------------------------------------------===//
10
15#include "llvm/ADT/STLExtras.h"
17#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
20#include "llvm/MC/MCInstrInfo.h"
25#include "llvm/MC/MCStreamer.h"
27#include "llvm/MC/MCSymbol.h"
30
31using namespace llvm;
32
33#define DEBUG_TYPE "xtensa-asm-parser"
34
35struct XtensaOperand;
36
38 const MCRegisterInfo &MRI;
39
40 enum XtensaRegisterType { Xtensa_Generic, Xtensa_SR, Xtensa_UR };
41 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
42
43 XtensaTargetStreamer &getTargetStreamer() {
44 assert(getParser().getStreamer().getTargetStreamer() &&
45 "do not have a target streamer");
47 return static_cast<XtensaTargetStreamer &>(TS);
48 }
49
50 ParseStatus parseDirective(AsmToken DirectiveID) override;
51 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
52 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
53 SMLoc NameLoc, OperandVector &Operands) override;
54 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
56 uint64_t &ErrorInfo,
57 bool MatchingInlineAsm) override;
58 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
59 unsigned Kind) override;
60
61 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
62 const MCSubtargetInfo *STI);
63
64// Auto-generated instruction matching functions
65#define GET_ASSEMBLER_HEADER
66#include "XtensaGenAsmMatcher.inc"
67
68 MCRegister getRegisterByName(StringRef RegName);
71 parseRegister(OperandVector &Operands, bool AllowParens = false,
72 XtensaRegisterType SR = Xtensa_Generic,
74 ParseStatus parseOperandWithModifier(OperandVector &Operands);
75 bool
76 parseOperand(OperandVector &Operands, StringRef Mnemonic,
77 XtensaRegisterType SR = Xtensa_Generic,
79 bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name,
80 SMLoc NameLoc, OperandVector &Operands);
81 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
82 SMLoc &EndLoc) override {
84 }
85
86 ParseStatus parsePCRelTarget(OperandVector &Operands);
87 bool parseLiteralDirective(SMLoc L);
88
89public:
92#define GET_OPERAND_DIAGNOSTIC_TYPES
93#include "XtensaGenAsmMatcher.inc"
94#undef GET_OPERAND_DIAGNOSTIC_TYPES
95 };
96
98 const MCInstrInfo &MII)
100 MRI(*Parser.getContext().getRegisterInfo()) {
101 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
102 }
103
104 bool hasWindowed() const {
105 return getSTI().getFeatureBits()[Xtensa::FeatureWindowed];
106 };
107};
108
109// Return true if Expr is in the range [MinValue, MaxValue].
110static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) {
111 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
112 int64_t Value = CE->getValue();
113 return Value >= MinValue && Value <= MaxValue;
114 }
115 return false;
116}
117
119
125
126 struct RegOp {
127 unsigned RegNum;
128 };
129
130 struct ImmOp {
131 const MCExpr *Val;
132 };
133
135 union {
139 };
140
142
143public:
145 Kind = o.Kind;
146 StartLoc = o.StartLoc;
147 EndLoc = o.EndLoc;
148 switch (Kind) {
149 case Register:
150 Reg = o.Reg;
151 break;
152 case Immediate:
153 Imm = o.Imm;
154 break;
155 case Token:
156 Tok = o.Tok;
157 break;
158 }
159 }
160
161 bool isToken() const override { return Kind == Token; }
162 bool isReg() const override { return Kind == Register; }
163 bool isImm() const override { return Kind == Immediate; }
164 bool isMem() const override { return false; }
165
166 bool isImm(int64_t MinValue, int64_t MaxValue) const {
167 return Kind == Immediate && inRange(getImm(), MinValue, MaxValue);
168 }
169
170 bool isImm8() const { return isImm(-128, 127); }
171
172 bool isImm8_sh8() const {
173 return isImm(-32768, 32512) &&
174 ((cast<MCConstantExpr>(getImm())->getValue() & 0xFF) == 0);
175 }
176
177 bool isImm12() const { return isImm(-2048, 2047); }
178
179 // Convert MOVI to literal load, when immediate is not in range (-2048, 2047)
180 bool isImm12m() const { return Kind == Immediate; }
181
182 bool isOffset4m32() const {
183 return isImm(0, 60) &&
184 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
185 }
186
187 bool isOffset8m8() const { return isImm(0, 255); }
188
189 bool isOffset8m16() const {
190 return isImm(0, 510) &&
191 ((cast<MCConstantExpr>(getImm())->getValue() & 0x1) == 0);
192 }
193
194 bool isOffset8m32() const {
195 return isImm(0, 1020) &&
196 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
197 }
198
199 bool isentry_imm12() const {
200 return isImm(0, 32760) &&
201 ((cast<MCConstantExpr>(getImm())->getValue() % 8) == 0);
202 }
203
204 bool isUimm4() const { return isImm(0, 15); }
205
206 bool isUimm5() const { return isImm(0, 31); }
207
208 bool isImm8n_7() const { return isImm(-8, 7); }
209
210 bool isShimm1_31() const { return isImm(1, 31); }
211
212 bool isImm16_31() const { return isImm(16, 31); }
213
214 bool isImm1_16() const { return isImm(1, 16); }
215
216 // Check that value is either equals (-1) or from [1,15] range.
217 bool isImm1n_15() const { return isImm(1, 15) || isImm(-1, -1); }
218
219 bool isImm32n_95() const { return isImm(-32, 95); }
220
221 bool isImm64n_4n() const {
222 return isImm(-64, -4) &&
223 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
224 }
225
226 bool isB4const() const {
227 if (Kind != Immediate)
228 return false;
229 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
230 int64_t Value = CE->getValue();
231 switch (Value) {
232 case -1:
233 case 1:
234 case 2:
235 case 3:
236 case 4:
237 case 5:
238 case 6:
239 case 7:
240 case 8:
241 case 10:
242 case 12:
243 case 16:
244 case 32:
245 case 64:
246 case 128:
247 case 256:
248 return true;
249 default:
250 return false;
251 }
252 }
253 return false;
254 }
255
256 bool isB4constu() const {
257 if (Kind != Immediate)
258 return false;
259 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
260 int64_t Value = CE->getValue();
261 switch (Value) {
262 case 32768:
263 case 65536:
264 case 2:
265 case 3:
266 case 4:
267 case 5:
268 case 6:
269 case 7:
270 case 8:
271 case 10:
272 case 12:
273 case 16:
274 case 32:
275 case 64:
276 case 128:
277 case 256:
278 return true;
279 default:
280 return false;
281 }
282 }
283 return false;
284 }
285
286 bool isimm7_22() const { return isImm(7, 22); }
287
288 bool isSelect_2() const { return isImm(0, 1); }
289
290 bool isSelect_4() const { return isImm(0, 3); }
291
292 bool isSelect_8() const { return isImm(0, 7); }
293
294 bool isSelect_16() const { return isImm(0, 16); }
295
296 bool isSelect_256() const { return isImm(0, 255); }
297
298 bool isOffset_16_16() const {
299 return isImm(-128, 112) &&
300 ((cast<MCConstantExpr>(getImm())->getValue() & 0xf) == 0);
301 }
302
303 bool isOffset_256_8() const {
304 return isImm(-1024, 1016) &&
305 ((cast<MCConstantExpr>(getImm())->getValue() & 0x7) == 0);
306 }
307
308 bool isOffset_256_16() const {
309 return isImm(-2048, 2032) &&
310 ((cast<MCConstantExpr>(getImm())->getValue() & 0xf) == 0);
311 }
312
313 bool isOffset_256_4() const {
314 return isImm(-512, 508) &&
315 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
316 }
317
318 bool isOffset_128_2() const {
319 return isImm(0, 254) &&
320 ((cast<MCConstantExpr>(getImm())->getValue() & 0x1) == 0);
321 }
322
323 bool isOffset_128_1() const { return isImm(0, 127); }
324
325 bool isOffset_64_16() const {
326 return isImm(-512, 496) &&
327 ((cast<MCConstantExpr>(getImm())->getValue() & 0xf) == 0);
328 }
329
330 /// getStartLoc - Gets location of the first token of this operand
331 SMLoc getStartLoc() const override { return StartLoc; }
332 /// getEndLoc - Gets location of the last token of this operand
333 SMLoc getEndLoc() const override { return EndLoc; }
334
335 MCRegister getReg() const override {
336 assert(Kind == Register && "Invalid type access!");
337 return Reg.RegNum;
338 }
339
340 const MCExpr *getImm() const {
341 assert(Kind == Immediate && "Invalid type access!");
342 return Imm.Val;
343 }
344
346 assert(Kind == Token && "Invalid type access!");
347 return Tok;
348 }
349
350 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {
351 switch (Kind) {
352 case Immediate:
353 MAI.printExpr(OS, *getImm());
354 break;
355 case Register:
356 OS << "<register x";
357 OS << getReg() << ">";
358 break;
359 case Token:
360 OS << "'" << getToken() << "'";
361 break;
362 }
363 }
364
365 static std::unique_ptr<XtensaOperand> createToken(StringRef Str, SMLoc S) {
366 auto Op = std::make_unique<XtensaOperand>(Token);
367 Op->Tok = Str;
368 Op->StartLoc = S;
369 Op->EndLoc = S;
370 return Op;
371 }
372
373 static std::unique_ptr<XtensaOperand> createReg(unsigned RegNo, SMLoc S,
374 SMLoc E) {
375 auto Op = std::make_unique<XtensaOperand>(Register);
376 Op->Reg.RegNum = RegNo;
377 Op->StartLoc = S;
378 Op->EndLoc = E;
379 return Op;
380 }
381
382 static std::unique_ptr<XtensaOperand> createImm(const MCExpr *Val, SMLoc S,
383 SMLoc E) {
384 auto Op = std::make_unique<XtensaOperand>(Immediate);
385 Op->Imm.Val = Val;
386 Op->StartLoc = S;
387 Op->EndLoc = E;
388 return Op;
389 }
390
391 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
392 assert(Expr && "Expr shouldn't be null!");
393 int64_t Imm = 0;
394 bool IsConstant = false;
395
396 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
397 IsConstant = true;
398 Imm = CE->getValue();
399 }
400
401 if (IsConstant)
403 else
405 }
406
407 // Used by the TableGen Code
408 void addRegOperands(MCInst &Inst, unsigned N) const {
409 assert(N == 1 && "Invalid number of operands!");
411 }
412
413 void addImmOperands(MCInst &Inst, unsigned N) const {
414 assert(N == 1 && "Invalid number of operands!");
415 addExpr(Inst, getImm());
416 }
417};
418
419#define GET_REGISTER_MATCHER
420#define GET_MATCHER_IMPLEMENTATION
421#include "XtensaGenAsmMatcher.inc"
422
423unsigned XtensaAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
424 unsigned Kind) {
426}
427
430 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
431 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
432 if (ErrorLoc == SMLoc())
433 return Loc;
434 return ErrorLoc;
435 }
436 return Loc;
437}
438
439bool XtensaAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
440 MCStreamer &Out,
441 const MCSubtargetInfo *STI) {
442 Inst.setLoc(IDLoc);
443 const unsigned Opcode = Inst.getOpcode();
444 switch (Opcode) {
445 case Xtensa::L32R: {
446 const MCSymbolRefExpr *OpExpr =
447 static_cast<const MCSymbolRefExpr *>(Inst.getOperand(1).getExpr());
448 Inst.getOperand(1).setExpr(OpExpr);
449 break;
450 }
451 case Xtensa::MOVI: {
452 XtensaTargetStreamer &TS = this->getTargetStreamer();
453
454 // Expand MOVI operand
455 if (!Inst.getOperand(1).isExpr()) {
456 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
457 int32_t Imm = ImmOp64;
458 if (!isInt<12>(Imm)) {
459 XtensaTargetStreamer &TS = this->getTargetStreamer();
460 MCInst TmpInst;
461 TmpInst.setLoc(IDLoc);
462 TmpInst.setOpcode(Xtensa::L32R);
463 const MCExpr *Value = MCConstantExpr::create(ImmOp64, getContext());
465 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
466 TmpInst.addOperand(Inst.getOperand(0));
467 MCOperand Op1 = MCOperand::createExpr(Expr);
468 TmpInst.addOperand(Op1);
469 TS.emitLiteral(Sym, Value, true, IDLoc);
470 Inst = TmpInst;
471 }
472 } else {
473 MCInst TmpInst;
474 TmpInst.setLoc(IDLoc);
475 TmpInst.setOpcode(Xtensa::L32R);
476 const MCExpr *Value = Inst.getOperand(1).getExpr();
478 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
479 TmpInst.addOperand(Inst.getOperand(0));
480 MCOperand Op1 = MCOperand::createExpr(Expr);
481 TmpInst.addOperand(Op1);
482 Inst = TmpInst;
483 TS.emitLiteral(Sym, Value, true, IDLoc);
484 }
485 break;
486 }
487 default:
488 break;
489 }
490
491 return true;
492}
493
494bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
496 MCStreamer &Out,
498 bool MatchingInlineAsm) {
499 MCInst Inst;
500 auto Result =
501 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
502
503 switch (Result) {
504 default:
505 break;
506 case Match_Success:
507 processInstruction(Inst, IDLoc, Out, STI);
508 Inst.setLoc(IDLoc);
509 Out.emitInstruction(Inst, getSTI());
510 return false;
512 return Error(IDLoc, "instruction use requires an option to be enabled");
514 return Error(IDLoc, "unrecognized instruction mnemonic");
516 SMLoc ErrorLoc = IDLoc;
517 if (ErrorInfo != ~0U) {
518 if (ErrorInfo >= Operands.size())
519 return Error(ErrorLoc, "too few operands for instruction");
520
521 ErrorLoc = ((XtensaOperand &)*Operands[ErrorInfo]).getStartLoc();
522 if (ErrorLoc == SMLoc())
523 ErrorLoc = IDLoc;
524 }
525 return Error(ErrorLoc, "invalid operand for instruction");
526 }
527 case Match_InvalidImm8:
528 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
529 "expected immediate in range [-128, 127]");
530 case Match_InvalidImm8_sh8:
531 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
532 "expected immediate in range [-32768, 32512], first 8 bits "
533 "should be zero");
534 case Match_InvalidB4const:
535 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
536 "expected b4const immediate");
537 case Match_InvalidB4constu:
538 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
539 "expected b4constu immediate");
540 case Match_InvalidImm12:
541 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
542 "expected immediate in range [-2048, 2047]");
543 case Match_InvalidImm12m:
544 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
545 "expected immediate in range [-2048, 2047]");
546 case Match_InvalidImm1_16:
547 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
548 "expected immediate in range [1, 16]");
549 case Match_InvalidImm1n_15:
550 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
551 "expected immediate in range [-1, 15] except 0");
552 case Match_InvalidImm32n_95:
553 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
554 "expected immediate in range [-32, 95]");
555 case Match_InvalidImm64n_4n:
556 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
557 "expected immediate in range [-64, -4]");
558 case Match_InvalidImm8n_7:
559 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
560 "expected immediate in range [-8, 7]");
561 case Match_InvalidShimm1_31:
562 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
563 "expected immediate in range [1, 31]");
564 case Match_InvalidUimm4:
565 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
566 "expected immediate in range [0, 15]");
567 case Match_InvalidUimm5:
568 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
569 "expected immediate in range [0, 31]");
570 case Match_InvalidOffset8m8:
571 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
572 "expected immediate in range [0, 255]");
573 case Match_InvalidOffset8m16:
574 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
575 "expected immediate in range [0, 510], first bit "
576 "should be zero");
577 case Match_InvalidOffset8m32:
578 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
579 "expected immediate in range [0, 1020], first 2 bits "
580 "should be zero");
581 case Match_InvalidOffset4m32:
582 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
583 "expected immediate in range [0, 60], first 2 bits "
584 "should be zero");
585 case Match_Invalidentry_imm12:
586 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
587 "expected immediate in range [0, 32760], first 3 bits "
588 "should be zero");
589 case Match_Invalidimm7_22:
590 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
591 "expected immediate in range [7, 22]");
592 case Match_InvalidSelect_2:
593 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
594 "expected immediate in range [0, 1]");
595 case Match_InvalidSelect_4:
596 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
597 "expected immediate in range [0, 3]");
598 case Match_InvalidSelect_8:
599 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
600 "expected immediate in range [0, 7]");
601 case Match_InvalidSelect_16:
602 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
603 "expected immediate in range [0, 15]");
604 case Match_InvalidSelect_256:
605 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
606 "expected immediate in range [0, 255]");
607 case Match_InvalidOffset_16_16:
608 return Error(
609 RefineErrorLoc(IDLoc, Operands, ErrorInfo),
610 "expected immediate in range [-128, 112], first 4 bits should be zero");
611 case Match_InvalidOffset_256_8:
612 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
613 "expected immediate in range [-1024, 1016], first 3 bits "
614 "should be zero");
615 case Match_InvalidOffset_256_16:
616 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
617 "expected immediate in range [-2048, 2032], first 4 bits "
618 "should be zero");
619 case Match_InvalidOffset_256_4:
620 return Error(
621 RefineErrorLoc(IDLoc, Operands, ErrorInfo),
622 "expected immediate in range [-512, 508], first 2 bits should be zero");
623 case Match_InvalidOffset_128_2:
624 return Error(
625 RefineErrorLoc(IDLoc, Operands, ErrorInfo),
626 "expected immediate in range [0, 254], first bit should be zero");
627 case Match_InvalidOffset_128_1:
628 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
629 "expected immediate in range [0, 127]");
630 case Match_InvalidOffset_64_16:
631 return Error(
632 RefineErrorLoc(IDLoc, Operands, ErrorInfo),
633 "expected immediate in range [-512, 496], first 4 bits should be zero");
634 }
635
636 report_fatal_error("Unknown match type detected!");
637}
638
639ParseStatus XtensaAsmParser::parsePCRelTarget(OperandVector &Operands) {
640 MCAsmParser &Parser = getParser();
641 LLVM_DEBUG(dbgs() << "parsePCRelTarget\n");
642
643 SMLoc S = getLexer().getLoc();
644
645 // Expressions are acceptable
646 const MCExpr *Expr = nullptr;
647 if (Parser.parseExpression(Expr)) {
648 // We have no way of knowing if a symbol was consumed so we must ParseFail
650 }
651
652 // Currently not support constants
653 if (Expr->getKind() == MCExpr::ExprKind::Constant)
654 return Error(getLoc(), "unknown operand");
655
656 Operands.push_back(XtensaOperand::createImm(Expr, S, getLexer().getLoc()));
658}
659
660MCRegister XtensaAsmParser::getRegisterByName(StringRef RegName) {
661 MCRegister RegNo = MatchRegisterName(RegName);
662 if (RegNo == 0)
664
665 if (RegNo == Xtensa::GPIO_OUT_S2 &&
666 getSTI().getFeatureBits()[Xtensa::FeatureESP32S3Ops])
667 RegNo = Xtensa::GPIO_OUT_S3;
668
669 return RegNo;
670}
671
672bool XtensaAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
673 SMLoc &EndLoc) {
674 const AsmToken &Tok = getParser().getTok();
675 StartLoc = Tok.getLoc();
676 EndLoc = Tok.getEndLoc();
677 Reg = Xtensa::NoRegister;
678 StringRef Name = getLexer().getTok().getIdentifier();
679
680 if (!MatchRegisterName(Name) && !MatchRegisterAltName(Name)) {
681 getParser().Lex(); // Eat identifier token.
682 return false;
683 }
684
685 return Error(StartLoc, "invalid register name");
686}
687
688ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
689 bool AllowParens,
690 XtensaRegisterType RegType,
692 SMLoc FirstS = getLoc();
693 bool HadParens = false;
694 AsmToken Buf[2];
695 StringRef RegName;
696
697 // If this a parenthesised register name is allowed, parse it atomically
698 if (AllowParens && getLexer().is(AsmToken::LParen)) {
699 size_t ReadCount = getLexer().peekTokens(Buf);
700 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
701 if (Buf[0].getKind() == AsmToken::Integer && RegType == Xtensa_Generic)
703 HadParens = true;
704 getParser().Lex(); // Eat '('
705 }
706 }
707
708 MCRegister RegNo = 0;
709
710 switch (getLexer().getKind()) {
711 default:
714 if (RegType == Xtensa_Generic)
716
717 // Parse case when we expect UR register code as special case,
718 // because SR and UR registers may have the same number
719 // and such situation may lead to confilct
720 if (RegType == Xtensa_UR) {
721 int64_t RegCode = getLexer().getTok().getIntVal();
722 RegNo = Xtensa::getUserRegister(RegCode, MRI);
723 } else {
726 }
727 break;
730 RegNo = getRegisterByName(RegName);
731 break;
732 }
733
734 if (RegNo == 0) {
735 if (HadParens)
736 getLexer().UnLex(Buf[0]);
738 }
739
740 if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits(), RAType))
742
743 if (HadParens)
744 Operands.push_back(XtensaOperand::createToken("(", FirstS));
745 SMLoc S = getLoc();
746 SMLoc E = getParser().getTok().getEndLoc();
747 getLexer().Lex();
748 Operands.push_back(XtensaOperand::createReg(RegNo, S, E));
749
750 if (HadParens) {
751 getParser().Lex(); // Eat ')'
752 Operands.push_back(XtensaOperand::createToken(")", getLoc()));
753 }
754
756}
757
758ParseStatus XtensaAsmParser::parseImmediate(OperandVector &Operands) {
759 SMLoc S = getLoc();
760 SMLoc E;
761 const MCExpr *Res;
762
763 switch (getLexer().getKind()) {
764 default:
766 case AsmToken::LParen:
767 case AsmToken::Minus:
768 case AsmToken::Plus:
769 case AsmToken::Tilde:
771 case AsmToken::String:
772 if (getParser().parseExpression(Res))
774 break;
776 if (getParser().parseExpression(Res))
778 break;
779 }
781 return parseOperandWithModifier(Operands);
782 }
783
785 Operands.push_back(XtensaOperand::createImm(Res, S, E));
787}
788
789ParseStatus XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) {
791}
792
793/// Looks at a token type and creates the relevant operand
794/// from this information, adding to Operands.
795/// If operand was parsed, returns false, else true.
796bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
797 XtensaRegisterType RegType,
799 // Check if the current operand has a custom associated parser, if so, try to
800 // custom parse the operand, or fallback to the general approach.
801 ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);
802 if (Res.isSuccess())
803 return false;
804
805 // If there wasn't a custom match, try the generic matcher below. Otherwise,
806 // there was a match, but an error occurred, in which case, just return that
807 // the operand parsing failed.
808 if (Res.isFailure())
809 return true;
810
811 // Attempt to parse token as register
812 if (parseRegister(Operands, true, RegType, RAType).isSuccess())
813 return false;
814
815 // Attempt to parse token as an immediate
816 if (parseImmediate(Operands).isSuccess())
817 return false;
818
819 // Finally we have exhausted all options and must declare defeat.
820 return Error(getLoc(), "unknown operand");
821}
822
823bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
824 StringRef Name, SMLoc NameLoc,
827 Name[0] == 'w' ? Xtensa::REGISTER_WRITE
828 : (Name[0] == 'r' ? Xtensa::REGISTER_READ
830
831 if ((Name.size() > 4) && Name[3] == '.') {
832 // Parse case when instruction name is concatenated with SR/UR register
833 // name, like "wsr.sar a1" or "wur.fcr a1"
834
835 // First operand is token for instruction
836 Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc));
837
838 StringRef RegName = Name.drop_front(4);
839 MCRegister RegNo = getRegisterByName(RegName);
840
841 if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits(), RAType))
842 return Error(NameLoc, "invalid register name");
843
844 // Parse operand
845 if (parseOperand(Operands, Name))
846 return true;
847
848 SMLoc S = getLoc();
849 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
850 Operands.push_back(XtensaOperand::createReg(RegNo, S, E));
851 } else {
852 // First operand is token for instruction
853 Operands.push_back(XtensaOperand::createToken(Name, NameLoc));
854
855 // Parse first operand
856 if (parseOperand(Operands, Name))
857 return true;
858
860 SMLoc Loc = getLexer().getLoc();
862 return Error(Loc, "unexpected token");
863 }
864
865 // Parse second operand
866 if (parseOperand(Operands, Name, Name[1] == 's' ? Xtensa_SR : Xtensa_UR,
867 RAType))
868 return true;
869 }
870
872 SMLoc Loc = getLexer().getLoc();
874 return Error(Loc, "unexpected token");
875 }
876
877 getParser().Lex(); // Consume the EndOfStatement.
878 return false;
879}
880
881bool XtensaAsmParser::parseInstruction(ParseInstructionInfo &Info,
882 StringRef Name, SMLoc NameLoc,
884 if (Name.starts_with("wsr") || Name.starts_with("rsr") ||
885 Name.starts_with("xsr") || Name.starts_with("rur") ||
886 Name.starts_with("wur")) {
887 return ParseInstructionWithSR(Info, Name, NameLoc, Operands);
888 }
889
890 // First operand is token for instruction
891 Operands.push_back(XtensaOperand::createToken(Name, NameLoc));
892
893 // If there are no more operands, then finish
895 return false;
896
897 // Parse first operand
898 if (parseOperand(Operands, Name))
899 return true;
900
901 // Parse until end of statement, consuming commas between operands
903 if (parseOperand(Operands, Name))
904 return true;
905
907 SMLoc Loc = getLexer().getLoc();
909 return Error(Loc, "unexpected token");
910 }
911
912 getParser().Lex(); // Consume the EndOfStatement.
913 return false;
914}
915
916bool XtensaAsmParser::parseLiteralDirective(SMLoc L) {
917 MCAsmParser &Parser = getParser();
918 const MCExpr *Value;
919 SMLoc LiteralLoc = getLexer().getLoc();
920 XtensaTargetStreamer &TS = this->getTargetStreamer();
921
922 if (Parser.parseExpression(Value))
923 return true;
924
925 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Value);
926
927 if (!SE)
928 return Error(LiteralLoc, "literal label must be a symbol");
929
930 if (Parser.parseComma())
931 return true;
932
933 SMLoc OpcodeLoc = getLexer().getLoc();
935 return Error(OpcodeLoc, "expected value");
936
937 if (Parser.parseExpression(Value))
938 return true;
939
940 if (parseEOL())
941 return true;
942
944
945 TS.emitLiteral(Sym, Value, true, LiteralLoc);
946
947 return false;
948}
949
950ParseStatus XtensaAsmParser::parseDirective(AsmToken DirectiveID) {
951 StringRef IDVal = DirectiveID.getString();
952 SMLoc Loc = getLexer().getLoc();
953
954 if (IDVal == ".literal_position") {
955 XtensaTargetStreamer &TS = this->getTargetStreamer();
957 return parseEOL();
958 }
959
960 if (IDVal == ".literal") {
961 return parseLiteralDirective(Loc);
962 }
963
965}
966
967// Force static initialization.
static MCRegister MatchRegisterName(StringRef Name)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned Imm
unsigned uint64_t
static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static MCRegister MatchRegisterAltName(StringRef Name)
Maps from the set of all alternative registernames to a register number.
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
#define RegName(no)
Register Reg
SI Fold Operands
This file contains some templates that are useful if you are working with the STL at all.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define LLVM_DEBUG(...)
Definition Debug.h:119
bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef< uint8_t > Bytes)
static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser()
static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands, uint64_t ErrorInfo)
XtensaAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, const MCInstrInfo &MII)
bool hasWindowed() const
SMLoc getLoc() const
Get the current source location.
Definition AsmLexer.h:116
void UnLex(AsmToken const &Token)
Definition AsmLexer.h:107
const AsmToken & getTok() const
Get the current (last) lexed token.
Definition AsmLexer.h:119
const AsmToken & Lex()
Consume the next token from the input stream and return it.
Definition AsmLexer.h:93
LLVM_ABI size_t peekTokens(MutableArrayRef< AsmToken > Buf, bool ShouldSkipSpace=true)
Look ahead an arbitrary number of tokens.
Definition AsmLexer.cpp:762
Target independent representation for an assembler token.
Definition MCAsmMacro.h:22
LLVM_ABI SMLoc getLoc() const
Definition AsmLexer.cpp:31
int64_t getIntVal() const
Definition MCAsmMacro.h:108
StringRef getString() const
Get the string for the current token, this includes all characters (for example, the quotes on string...
Definition MCAsmMacro.h:103
LLVM_ABI SMLoc getEndLoc() const
Definition AsmLexer.cpp:33
StringRef getIdentifier() const
Get the identifier string for the current token, which should be an identifier or a string.
Definition MCAsmMacro.h:92
Base class for user error types.
Definition Error.h:354
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition MCAsmInfo.h:67
void printExpr(raw_ostream &, const MCExpr &) const
bool parseOptionalToken(AsmToken::TokenKind T)
Generic assembler parser interface, for use by target specific assembly parsers.
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
const AsmToken & getTok() const
Get the current AsmToken from the stream.
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
MCStreamer & getStreamer()
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
ExprKind getKind() const
Definition MCExpr.h:85
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void setLoc(SMLoc loc)
Definition MCInst.h:207
unsigned getOpcode() const
Definition MCInst.h:202
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
Interface to description of machine instruction set.
Definition MCInstrInfo.h:27
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
void setExpr(const MCExpr *Val)
Definition MCInst.h:123
int64_t getImm() const
Definition MCInst.h:84
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
Streaming machine code generation interface.
Definition MCStreamer.h:222
MCTargetStreamer * getTargetStreamer()
Definition MCStreamer.h:336
Generic base class for all target subtargets.
const FeatureBitset & getFeatureBits() const
const MCSymbol & getSymbol() const
Definition MCExpr.h:226
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
const MCInstrInfo & MII
MCTargetAsmParser(const MCSubtargetInfo &STI, const MCInstrInfo &MII)
void setAvailableFeatures(const FeatureBitset &Value)
const MCSubtargetInfo & getSTI() const
const MCSubtargetInfo * STI
Current STI.
Target specific streamer interface.
Definition MCStreamer.h:95
Ternary parse status returned by various parse* methods.
constexpr bool isFailure() const
static constexpr StatusTy Failure
constexpr bool isSuccess() const
static constexpr StatusTy Success
static constexpr StatusTy NoMatch
Represents a location in source code.
Definition SMLoc.h:22
static SMLoc getFromPointer(const char *Ptr)
Definition SMLoc.h:35
constexpr const char * getPointer() const
Definition SMLoc.h:33
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
LLVM Value Representation.
Definition Value.h:75
virtual void emitLiteral(MCSymbol *LblSym, const MCExpr *Value, bool SwitchLiteralSection, SMLoc L=SMLoc())
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
MCExpr const & getExpr(MCExpr const &Expr)
bool checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits, RegisterAccessType RA)
MCRegister getUserRegister(unsigned Code, const MCRegisterInfo &MRI)
This is an optimization pass for GlobalISel generic memory operations.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
Target & getTheXtensaTarget()
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
#define N
bool isSelect_4() const
bool isImm12() const
bool isOffset_256_8() const
bool isOffset4m32() const
bool isOffset8m16() const
static std::unique_ptr< XtensaOperand > createToken(StringRef Str, SMLoc S)
bool isImm8_sh8() const
void addRegOperands(MCInst &Inst, unsigned N) const
bool isOffset_64_16() const
void addExpr(MCInst &Inst, const MCExpr *Expr) const
void addImmOperands(MCInst &Inst, unsigned N) const
StringRef getToken() const
bool isOffset_256_16() const
enum XtensaOperand::KindTy Kind
bool isMem() const override
isMem - Is this a memory operand?
bool isImm16_31() const
bool isImm8n_7() const
bool isToken() const override
isToken - Is this a token operand?
bool isImm1n_15() const
MCRegister getReg() const override
SMLoc getStartLoc() const override
getStartLoc - Gets location of the first token of this operand
bool isSelect_256() const
bool isImm8() const
bool isSelect_16() const
bool isImm(int64_t MinValue, int64_t MaxValue) const
bool isImm12m() const
bool isReg() const override
isReg - Is this a register operand?
XtensaOperand(KindTy K)
bool isB4constu() const
bool isImm64n_4n() const
bool isImm() const override
isImm - Is this an immediate operand?
bool isUimm4() const
bool isentry_imm12() const
static std::unique_ptr< XtensaOperand > createReg(unsigned RegNo, SMLoc S, SMLoc E)
bool isSelect_8() const
bool isimm7_22() const
SMLoc getEndLoc() const override
getEndLoc - Gets location of the last token of this operand
bool isOffset_16_16() const
bool isImm32n_95() const
bool isSelect_2() const
const MCExpr * getImm() const
bool isUimm5() const
bool isOffset_256_4() const
bool isOffset8m8() const
void print(raw_ostream &OS, const MCAsmInfo &MAI) const override
print - Print a debug representation of the operand to the given stream.
XtensaOperand(const XtensaOperand &o)
bool isImm1_16() const
bool isOffset_128_1() const
bool isOffset_128_2() const
bool isB4const() const
static std::unique_ptr< XtensaOperand > createImm(const MCExpr *Val, SMLoc S, SMLoc E)
bool isOffset8m32() const
bool isShimm1_31() const
RegisterMCAsmParser - Helper template for registering a target specific assembly parser,...