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,
53 OperandVector &Operands, MCStreamer &Out,
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
383static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
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,
450 OperandVector &Operands,
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,
732 OperandVector &Operands) {
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,
793 OperandVector &Operands) {
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
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
void push_back(const T &Elt)
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:644
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:560
#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,...