LLVM 22.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() {
45 return static_cast<XtensaTargetStreamer &>(TS);
46 }
47
48 ParseStatus parseDirective(AsmToken DirectiveID) override;
49 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
50 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
51 SMLoc NameLoc, OperandVector &Operands) override;
52 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
55 bool MatchingInlineAsm) override;
56 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
57 unsigned Kind) override;
58
59 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
60 const MCSubtargetInfo *STI);
61
62// Auto-generated instruction matching functions
63#define GET_ASSEMBLER_HEADER
64#include "XtensaGenAsmMatcher.inc"
65
68 parseRegister(OperandVector &Operands, bool AllowParens = false,
69 XtensaRegisterType SR = Xtensa_Generic,
71 ParseStatus parseOperandWithModifier(OperandVector &Operands);
72 bool
73 parseOperand(OperandVector &Operands, StringRef Mnemonic,
74 XtensaRegisterType SR = Xtensa_Generic,
76 bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name,
77 SMLoc NameLoc, OperandVector &Operands);
78 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
79 SMLoc &EndLoc) override {
81 }
82
83 ParseStatus parsePCRelTarget(OperandVector &Operands);
84 bool parseLiteralDirective(SMLoc L);
85
86public:
89#define GET_OPERAND_DIAGNOSTIC_TYPES
90#include "XtensaGenAsmMatcher.inc"
91#undef GET_OPERAND_DIAGNOSTIC_TYPES
92 };
93
97 MRI(*Parser.getContext().getRegisterInfo()) {
98 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
99 }
100
101 bool hasWindowed() const {
102 return getSTI().getFeatureBits()[Xtensa::FeatureWindowed];
103 };
104};
105
106// Return true if Expr is in the range [MinValue, MaxValue].
107static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) {
108 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
109 int64_t Value = CE->getValue();
110 return Value >= MinValue && Value <= MaxValue;
111 }
112 return false;
113}
114
116
122
123 struct RegOp {
124 unsigned RegNum;
125 };
126
127 struct ImmOp {
128 const MCExpr *Val;
129 };
130
132 union {
136 };
137
139
140public:
142 Kind = o.Kind;
143 StartLoc = o.StartLoc;
144 EndLoc = o.EndLoc;
145 switch (Kind) {
146 case Register:
147 Reg = o.Reg;
148 break;
149 case Immediate:
150 Imm = o.Imm;
151 break;
152 case Token:
153 Tok = o.Tok;
154 break;
155 }
156 }
157
158 bool isToken() const override { return Kind == Token; }
159 bool isReg() const override { return Kind == Register; }
160 bool isImm() const override { return Kind == Immediate; }
161 bool isMem() const override { return false; }
162
163 bool isImm(int64_t MinValue, int64_t MaxValue) const {
164 return Kind == Immediate && inRange(getImm(), MinValue, MaxValue);
165 }
166
167 bool isImm8() const { return isImm(-128, 127); }
168
169 bool isImm8_sh8() const {
170 return isImm(-32768, 32512) &&
171 ((cast<MCConstantExpr>(getImm())->getValue() & 0xFF) == 0);
172 }
173
174 bool isImm12() const { return isImm(-2048, 2047); }
175
176 // Convert MOVI to literal load, when immediate is not in range (-2048, 2047)
177 bool isImm12m() const { return Kind == Immediate; }
178
179 bool isOffset4m32() const {
180 return isImm(0, 60) &&
181 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
182 }
183
184 bool isOffset8m8() const { return isImm(0, 255); }
185
186 bool isOffset8m16() const {
187 return isImm(0, 510) &&
188 ((cast<MCConstantExpr>(getImm())->getValue() & 0x1) == 0);
189 }
190
191 bool isOffset8m32() const {
192 return isImm(0, 1020) &&
193 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
194 }
195
196 bool isentry_imm12() const {
197 return isImm(0, 32760) &&
198 ((cast<MCConstantExpr>(getImm())->getValue() % 8) == 0);
199 }
200
201 bool isUimm4() const { return isImm(0, 15); }
202
203 bool isUimm5() const { return isImm(0, 31); }
204
205 bool isImm8n_7() const { return isImm(-8, 7); }
206
207 bool isShimm1_31() const { return isImm(1, 31); }
208
209 bool isImm16_31() const { return isImm(16, 31); }
210
211 bool isImm1_16() const { return isImm(1, 16); }
212
213 // Check that value is either equals (-1) or from [1,15] range.
214 bool isImm1n_15() const { return isImm(1, 15) || isImm(-1, -1); }
215
216 bool isImm32n_95() const { return isImm(-32, 95); }
217
218 bool isImm64n_4n() const {
219 return isImm(-64, -4) &&
220 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
221 }
222
223 bool isB4const() const {
224 if (Kind != Immediate)
225 return false;
226 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
227 int64_t Value = CE->getValue();
228 switch (Value) {
229 case -1:
230 case 1:
231 case 2:
232 case 3:
233 case 4:
234 case 5:
235 case 6:
236 case 7:
237 case 8:
238 case 10:
239 case 12:
240 case 16:
241 case 32:
242 case 64:
243 case 128:
244 case 256:
245 return true;
246 default:
247 return false;
248 }
249 }
250 return false;
251 }
252
253 bool isB4constu() const {
254 if (Kind != Immediate)
255 return false;
256 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
257 int64_t Value = CE->getValue();
258 switch (Value) {
259 case 32768:
260 case 65536:
261 case 2:
262 case 3:
263 case 4:
264 case 5:
265 case 6:
266 case 7:
267 case 8:
268 case 10:
269 case 12:
270 case 16:
271 case 32:
272 case 64:
273 case 128:
274 case 256:
275 return true;
276 default:
277 return false;
278 }
279 }
280 return false;
281 }
282
283 bool isimm7_22() const { return isImm(7, 22); }
284
285 /// getStartLoc - Gets location of the first token of this operand
286 SMLoc getStartLoc() const override { return StartLoc; }
287 /// getEndLoc - Gets location of the last token of this operand
288 SMLoc getEndLoc() const override { return EndLoc; }
289
290 MCRegister getReg() const override {
291 assert(Kind == Register && "Invalid type access!");
292 return Reg.RegNum;
293 }
294
295 const MCExpr *getImm() const {
296 assert(Kind == Immediate && "Invalid type access!");
297 return Imm.Val;
298 }
299
301 assert(Kind == Token && "Invalid type access!");
302 return Tok;
303 }
304
305 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {
306 switch (Kind) {
307 case Immediate:
308 MAI.printExpr(OS, *getImm());
309 break;
310 case Register:
311 OS << "<register x";
312 OS << getReg() << ">";
313 break;
314 case Token:
315 OS << "'" << getToken() << "'";
316 break;
317 }
318 }
319
320 static std::unique_ptr<XtensaOperand> createToken(StringRef Str, SMLoc S) {
321 auto Op = std::make_unique<XtensaOperand>(Token);
322 Op->Tok = Str;
323 Op->StartLoc = S;
324 Op->EndLoc = S;
325 return Op;
326 }
327
328 static std::unique_ptr<XtensaOperand> createReg(unsigned RegNo, SMLoc S,
329 SMLoc E) {
330 auto Op = std::make_unique<XtensaOperand>(Register);
331 Op->Reg.RegNum = RegNo;
332 Op->StartLoc = S;
333 Op->EndLoc = E;
334 return Op;
335 }
336
337 static std::unique_ptr<XtensaOperand> createImm(const MCExpr *Val, SMLoc S,
338 SMLoc E) {
339 auto Op = std::make_unique<XtensaOperand>(Immediate);
340 Op->Imm.Val = Val;
341 Op->StartLoc = S;
342 Op->EndLoc = E;
343 return Op;
344 }
345
346 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
347 assert(Expr && "Expr shouldn't be null!");
348 int64_t Imm = 0;
349 bool IsConstant = false;
350
351 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
352 IsConstant = true;
353 Imm = CE->getValue();
354 }
355
356 if (IsConstant)
358 else
360 }
361
362 // Used by the TableGen Code
363 void addRegOperands(MCInst &Inst, unsigned N) const {
364 assert(N == 1 && "Invalid number of operands!");
366 }
367
368 void addImmOperands(MCInst &Inst, unsigned N) const {
369 assert(N == 1 && "Invalid number of operands!");
370 addExpr(Inst, getImm());
371 }
372};
373
374#define GET_REGISTER_MATCHER
375#define GET_MATCHER_IMPLEMENTATION
376#include "XtensaGenAsmMatcher.inc"
377
378unsigned XtensaAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
379 unsigned Kind) {
381}
382
385 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
386 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
387 if (ErrorLoc == SMLoc())
388 return Loc;
389 return ErrorLoc;
390 }
391 return Loc;
392}
393
394bool XtensaAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
395 MCStreamer &Out,
396 const MCSubtargetInfo *STI) {
397 Inst.setLoc(IDLoc);
398 const unsigned Opcode = Inst.getOpcode();
399 switch (Opcode) {
400 case Xtensa::L32R: {
401 const MCSymbolRefExpr *OpExpr =
402 static_cast<const MCSymbolRefExpr *>(Inst.getOperand(1).getExpr());
403 Inst.getOperand(1).setExpr(OpExpr);
404 break;
405 }
406 case Xtensa::MOVI: {
407 XtensaTargetStreamer &TS = this->getTargetStreamer();
408
409 // Expand MOVI operand
410 if (!Inst.getOperand(1).isExpr()) {
411 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
412 int32_t Imm = ImmOp64;
413 if (!isInt<12>(Imm)) {
414 XtensaTargetStreamer &TS = this->getTargetStreamer();
415 MCInst TmpInst;
416 TmpInst.setLoc(IDLoc);
417 TmpInst.setOpcode(Xtensa::L32R);
418 const MCExpr *Value = MCConstantExpr::create(ImmOp64, getContext());
420 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
421 TmpInst.addOperand(Inst.getOperand(0));
422 MCOperand Op1 = MCOperand::createExpr(Expr);
423 TmpInst.addOperand(Op1);
424 TS.emitLiteral(Sym, Value, true, IDLoc);
425 Inst = TmpInst;
426 }
427 } else {
428 MCInst TmpInst;
429 TmpInst.setLoc(IDLoc);
430 TmpInst.setOpcode(Xtensa::L32R);
431 const MCExpr *Value = Inst.getOperand(1).getExpr();
433 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
434 TmpInst.addOperand(Inst.getOperand(0));
435 MCOperand Op1 = MCOperand::createExpr(Expr);
436 TmpInst.addOperand(Op1);
437 Inst = TmpInst;
438 TS.emitLiteral(Sym, Value, true, IDLoc);
439 }
440 break;
441 }
442 default:
443 break;
444 }
445
446 return true;
447}
448
449bool XtensaAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
451 MCStreamer &Out,
453 bool MatchingInlineAsm) {
454 MCInst Inst;
455 auto Result =
456 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
457
458 switch (Result) {
459 default:
460 break;
461 case Match_Success:
462 processInstruction(Inst, IDLoc, Out, STI);
463 Inst.setLoc(IDLoc);
464 Out.emitInstruction(Inst, getSTI());
465 return false;
467 return Error(IDLoc, "instruction use requires an option to be enabled");
469 return Error(IDLoc, "unrecognized instruction mnemonic");
471 SMLoc ErrorLoc = IDLoc;
472 if (ErrorInfo != ~0U) {
473 if (ErrorInfo >= Operands.size())
474 return Error(ErrorLoc, "too few operands for instruction");
475
476 ErrorLoc = ((XtensaOperand &)*Operands[ErrorInfo]).getStartLoc();
477 if (ErrorLoc == SMLoc())
478 ErrorLoc = IDLoc;
479 }
480 return Error(ErrorLoc, "invalid operand for instruction");
481 }
482 case Match_InvalidImm8:
483 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
484 "expected immediate in range [-128, 127]");
485 case Match_InvalidImm8_sh8:
486 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
487 "expected immediate in range [-32768, 32512], first 8 bits "
488 "should be zero");
489 case Match_InvalidB4const:
490 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
491 "expected b4const immediate");
492 case Match_InvalidB4constu:
493 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
494 "expected b4constu immediate");
495 case Match_InvalidImm12:
496 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
497 "expected immediate in range [-2048, 2047]");
498 case Match_InvalidImm12m:
499 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
500 "expected immediate in range [-2048, 2047]");
501 case Match_InvalidImm1_16:
502 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
503 "expected immediate in range [1, 16]");
504 case Match_InvalidImm1n_15:
505 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
506 "expected immediate in range [-1, 15] except 0");
507 case Match_InvalidImm32n_95:
508 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
509 "expected immediate in range [-32, 95]");
510 case Match_InvalidImm64n_4n:
511 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
512 "expected immediate in range [-64, -4]");
513 case Match_InvalidImm8n_7:
514 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
515 "expected immediate in range [-8, 7]");
516 case Match_InvalidShimm1_31:
517 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
518 "expected immediate in range [1, 31]");
519 case Match_InvalidUimm4:
520 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
521 "expected immediate in range [0, 15]");
522 case Match_InvalidUimm5:
523 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
524 "expected immediate in range [0, 31]");
525 case Match_InvalidOffset8m8:
526 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
527 "expected immediate in range [0, 255]");
528 case Match_InvalidOffset8m16:
529 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
530 "expected immediate in range [0, 510], first bit "
531 "should be zero");
532 case Match_InvalidOffset8m32:
533 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
534 "expected immediate in range [0, 1020], first 2 bits "
535 "should be zero");
536 case Match_InvalidOffset4m32:
537 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
538 "expected immediate in range [0, 60], first 2 bits "
539 "should be zero");
540 case Match_Invalidentry_imm12:
541 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
542 "expected immediate in range [0, 32760], first 3 bits "
543 "should be zero");
544 case Match_Invalidimm7_22:
545 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
546 "expected immediate in range [7, 22]");
547 }
548
549 report_fatal_error("Unknown match type detected!");
550}
551
552ParseStatus XtensaAsmParser::parsePCRelTarget(OperandVector &Operands) {
553 MCAsmParser &Parser = getParser();
554 LLVM_DEBUG(dbgs() << "parsePCRelTarget\n");
555
556 SMLoc S = getLexer().getLoc();
557
558 // Expressions are acceptable
559 const MCExpr *Expr = nullptr;
560 if (Parser.parseExpression(Expr)) {
561 // We have no way of knowing if a symbol was consumed so we must ParseFail
563 }
564
565 // Currently not support constants
566 if (Expr->getKind() == MCExpr::ExprKind::Constant)
567 return Error(getLoc(), "unknown operand");
568
569 Operands.push_back(XtensaOperand::createImm(Expr, S, getLexer().getLoc()));
571}
572
573bool XtensaAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
574 SMLoc &EndLoc) {
575 const AsmToken &Tok = getParser().getTok();
576 StartLoc = Tok.getLoc();
577 EndLoc = Tok.getEndLoc();
578 Reg = Xtensa::NoRegister;
579 StringRef Name = getLexer().getTok().getIdentifier();
580
581 if (!MatchRegisterName(Name) && !MatchRegisterAltName(Name)) {
582 getParser().Lex(); // Eat identifier token.
583 return false;
584 }
585
586 return Error(StartLoc, "invalid register name");
587}
588
589ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
590 bool AllowParens,
591 XtensaRegisterType RegType,
593 SMLoc FirstS = getLoc();
594 bool HadParens = false;
595 AsmToken Buf[2];
596 StringRef RegName;
597
598 // If this a parenthesised register name is allowed, parse it atomically
599 if (AllowParens && getLexer().is(AsmToken::LParen)) {
600 size_t ReadCount = getLexer().peekTokens(Buf);
601 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
602 if (Buf[0].getKind() == AsmToken::Integer && RegType == Xtensa_Generic)
604 HadParens = true;
605 getParser().Lex(); // Eat '('
606 }
607 }
608
609 MCRegister RegNo = 0;
610
611 switch (getLexer().getKind()) {
612 default:
615 if (RegType == Xtensa_Generic)
617
618 // Parse case when we expect UR register code as special case,
619 // because SR and UR registers may have the same number
620 // and such situation may lead to confilct
621 if (RegType == Xtensa_UR) {
622 int64_t RegCode = getLexer().getTok().getIntVal();
623 RegNo = Xtensa::getUserRegister(RegCode, MRI);
624 } else {
627 }
628 break;
631 RegNo = MatchRegisterName(RegName);
632 if (RegNo == 0)
634 break;
635 }
636
637 if (RegNo == 0) {
638 if (HadParens)
639 getLexer().UnLex(Buf[0]);
641 }
642
643 if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits(), RAType))
645
646 if (HadParens)
647 Operands.push_back(XtensaOperand::createToken("(", FirstS));
648 SMLoc S = getLoc();
649 SMLoc E = getParser().getTok().getEndLoc();
650 getLexer().Lex();
651 Operands.push_back(XtensaOperand::createReg(RegNo, S, E));
652
653 if (HadParens) {
654 getParser().Lex(); // Eat ')'
655 Operands.push_back(XtensaOperand::createToken(")", getLoc()));
656 }
657
659}
660
661ParseStatus XtensaAsmParser::parseImmediate(OperandVector &Operands) {
662 SMLoc S = getLoc();
663 SMLoc E;
664 const MCExpr *Res;
665
666 switch (getLexer().getKind()) {
667 default:
669 case AsmToken::LParen:
670 case AsmToken::Minus:
671 case AsmToken::Plus:
672 case AsmToken::Tilde:
674 case AsmToken::String:
675 if (getParser().parseExpression(Res))
677 break;
679 StringRef Identifier;
680 if (getParser().parseIdentifier(Identifier))
682
683 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
685 break;
686 }
688 return parseOperandWithModifier(Operands);
689 }
690
692 Operands.push_back(XtensaOperand::createImm(Res, S, E));
694}
695
696ParseStatus XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) {
698}
699
700/// Looks at a token type and creates the relevant operand
701/// from this information, adding to Operands.
702/// If operand was parsed, returns false, else true.
703bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
704 XtensaRegisterType RegType,
706 // Check if the current operand has a custom associated parser, if so, try to
707 // custom parse the operand, or fallback to the general approach.
708 ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);
709 if (Res.isSuccess())
710 return false;
711
712 // If there wasn't a custom match, try the generic matcher below. Otherwise,
713 // there was a match, but an error occurred, in which case, just return that
714 // the operand parsing failed.
715 if (Res.isFailure())
716 return true;
717
718 // Attempt to parse token as register
719 if (parseRegister(Operands, true, RegType, RAType).isSuccess())
720 return false;
721
722 // Attempt to parse token as an immediate
723 if (parseImmediate(Operands).isSuccess())
724 return false;
725
726 // Finally we have exhausted all options and must declare defeat.
727 return Error(getLoc(), "unknown operand");
728}
729
730bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
731 StringRef Name, SMLoc NameLoc,
734 Name[0] == 'w' ? Xtensa::REGISTER_WRITE
735 : (Name[0] == 'r' ? Xtensa::REGISTER_READ
737
738 if ((Name.size() > 4) && Name[3] == '.') {
739 // Parse case when instruction name is concatenated with SR/UR register
740 // name, like "wsr.sar a1" or "wur.fcr a1"
741
742 // First operand is token for instruction
743 Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc));
744
745 StringRef RegName = Name.drop_front(4);
746 unsigned RegNo = MatchRegisterName(RegName);
747
748 if (RegNo == 0)
750
751 if (!Xtensa::checkRegister(RegNo, getSTI().getFeatureBits(), RAType))
752 return Error(NameLoc, "invalid register name");
753
754 // Parse operand
755 if (parseOperand(Operands, Name))
756 return true;
757
758 SMLoc S = getLoc();
759 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
760 Operands.push_back(XtensaOperand::createReg(RegNo, S, E));
761 } else {
762 // First operand is token for instruction
763 Operands.push_back(XtensaOperand::createToken(Name, NameLoc));
764
765 // Parse first operand
766 if (parseOperand(Operands, Name))
767 return true;
768
770 SMLoc Loc = getLexer().getLoc();
772 return Error(Loc, "unexpected token");
773 }
774
775 // Parse second operand
776 if (parseOperand(Operands, Name, Name[1] == 's' ? Xtensa_SR : Xtensa_UR,
777 RAType))
778 return true;
779 }
780
782 SMLoc Loc = getLexer().getLoc();
784 return Error(Loc, "unexpected token");
785 }
786
787 getParser().Lex(); // Consume the EndOfStatement.
788 return false;
789}
790
791bool XtensaAsmParser::parseInstruction(ParseInstructionInfo &Info,
792 StringRef Name, SMLoc NameLoc,
794 if (Name.starts_with("wsr") || Name.starts_with("rsr") ||
795 Name.starts_with("xsr") || Name.starts_with("rur") ||
796 Name.starts_with("wur")) {
797 return ParseInstructionWithSR(Info, Name, NameLoc, Operands);
798 }
799
800 // First operand is token for instruction
801 Operands.push_back(XtensaOperand::createToken(Name, NameLoc));
802
803 // If there are no more operands, then finish
805 return false;
806
807 // Parse first operand
808 if (parseOperand(Operands, Name))
809 return true;
810
811 // Parse until end of statement, consuming commas between operands
813 if (parseOperand(Operands, Name))
814 return true;
815
817 SMLoc Loc = getLexer().getLoc();
819 return Error(Loc, "unexpected token");
820 }
821
822 getParser().Lex(); // Consume the EndOfStatement.
823 return false;
824}
825
826bool XtensaAsmParser::parseLiteralDirective(SMLoc L) {
827 MCAsmParser &Parser = getParser();
828 const MCExpr *Value;
829 SMLoc LiteralLoc = getLexer().getLoc();
830 XtensaTargetStreamer &TS = this->getTargetStreamer();
831
832 if (Parser.parseExpression(Value))
833 return true;
834
835 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Value);
836
837 if (!SE)
838 return Error(LiteralLoc, "literal label must be a symbol");
839
840 if (Parser.parseComma())
841 return true;
842
843 SMLoc OpcodeLoc = getLexer().getLoc();
845 return Error(OpcodeLoc, "expected value");
846
847 if (Parser.parseExpression(Value))
848 return true;
849
850 if (parseEOL())
851 return true;
852
854
855 TS.emitLiteral(Sym, Value, true, LiteralLoc);
856
857 return false;
858}
859
860ParseStatus XtensaAsmParser::parseDirective(AsmToken DirectiveID) {
861 StringRef IDVal = DirectiveID.getString();
862 SMLoc Loc = getLexer().getLoc();
863
864 if (IDVal == ".literal_position") {
865 XtensaTargetStreamer &TS = this->getTargetStreamer();
867 return parseEOL();
868 }
869
870 if (IDVal == ".literal") {
871 return parseLiteralDirective(Loc);
872 }
873
875}
876
877// Force static initialization.
static MCRegister MatchRegisterName(StringRef Name)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
Definition CSEInfo.cpp:27
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
#define RegName(no)
static LVOptions Options
Definition LVOptions.cpp:25
mir Rename Register Operands
Register Reg
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:114
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
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, const MCTargetOptions &Options)
bool hasWindowed() const
SMLoc getLoc() const
Get the current source location.
Definition AsmLexer.h:115
void UnLex(AsmToken const &Token)
Definition AsmLexer.h:106
const AsmToken & getTok() const
Get the current (last) lexed token.
Definition AsmLexer.h:118
const AsmToken & Lex()
Consume the next token from the input stream and return it.
Definition AsmLexer.h:92
LLVM_ABI size_t peekTokens(MutableArrayRef< AsmToken > Buf, bool ShouldSkipSpace=true)
Look ahead an arbitrary number of tokens.
Definition AsmLexer.cpp:764
Target independent representation for an assembler token.
Definition MCAsmMacro.h:22
LLVM_ABI SMLoc getLoc() const
Definition AsmLexer.cpp:32
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:34
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:64
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:33
Streaming machine code generation interface.
Definition MCStreamer.h:220
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
MCTargetStreamer * getTargetStreamer()
Definition MCStreamer.h:324
Generic base class for all target subtargets.
const FeatureBitset & getFeatureBits() const
const MCSymbol & getSymbol() const
Definition MCExpr.h:227
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:214
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
MCTargetAsmParser(MCTargetOptions const &, const MCSubtargetInfo &STI, const MCInstrInfo &MII)
const MCInstrInfo & MII
void setAvailableFeatures(const FeatureBitset &Value)
const MCSubtargetInfo & getSTI() const
const MCSubtargetInfo * STI
Current STI.
Target specific streamer interface.
Definition MCStreamer.h:93
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:23
static SMLoc getFromPointer(const char *Ptr)
Definition SMLoc.h:36
constexpr const char * getPointer() const
Definition SMLoc.h:34
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
LLVM Value Representation.
Definition Value.h:75
virtual void emitLiteralPosition()=0
virtual void emitLiteral(MCSymbol *LblSym, const MCExpr *Value, bool SwitchLiteralSection, SMLoc L=SMLoc())=0
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.
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:174
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
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:207
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
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:565
#define N
bool isImm12() 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
void addExpr(MCInst &Inst, const MCExpr *Expr) const
void addImmOperands(MCInst &Inst, unsigned N) const
StringRef getToken() 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 isImm8() 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 isimm7_22() const
SMLoc getEndLoc() const override
getEndLoc - Gets location of the last token of this operand
bool isImm32n_95() const
const MCExpr * getImm() const
bool isUimm5() 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 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,...