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