LLVM 24.0.0git
XtensaAsmParser.cpp
Go to the documentation of this file.
1//===- XtensaAsmParser.cpp - Parse Xtensa assembly to MCInst instructions -===//
2//
3// The LLVM Compiler Infrastructure
4//
5// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6// See https://llvm.org/LICENSE.txt for license information.
7// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8//
9//===----------------------------------------------------------------------===//
10
15#include "llvm/ADT/STLExtras.h"
17#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
20#include "llvm/MC/MCInstrInfo.h"
25#include "llvm/MC/MCStreamer.h"
27#include "llvm/MC/MCSymbol.h"
30
31using namespace llvm;
32
33#define DEBUG_TYPE "xtensa-asm-parser"
34
35struct XtensaOperand;
36
38 const MCRegisterInfo &MRI;
39
40 enum XtensaRegisterType { Xtensa_Generic, Xtensa_SR, Xtensa_UR };
41 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
42
43 XtensaTargetStreamer &getTargetStreamer() {
44 assert(getParser().getStreamer().getTargetStreamer() &&
45 "do not have a target streamer");
47 return static_cast<XtensaTargetStreamer &>(TS);
48 }
49
50 ParseStatus parseDirective(AsmToken DirectiveID) override;
51 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
52 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
53 SMLoc NameLoc, OperandVector &Operands) override;
54 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
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
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,
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,
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,
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
SI Fold Operands
This file contains some templates that are useful if you are working with the STL at all.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define LLVM_DEBUG(...)
Definition Debug.h:119
bool parseImmediate(MCInst &MI, uint64_t &Size, ArrayRef< uint8_t > Bytes)
static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser()
static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands, uint64_t ErrorInfo)
XtensaAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, const MCInstrInfo &MII)
bool hasWindowed() const
SMLoc getLoc() const
Get the current source location.
Definition AsmLexer.h: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:67
void printExpr(raw_ostream &, const MCExpr &) const
bool parseOptionalToken(AsmToken::TokenKind T)
Generic assembler parser interface, for use by target specific assembly parsers.
virtual void eatToEndOfStatement()=0
Skip to the end of the current statement, for error recovery.
const AsmToken & getTok() const
Get the current AsmToken from the stream.
virtual const AsmToken & Lex()=0
Get the next AsmToken in the stream, possibly handling file inclusion first.
MCStreamer & getStreamer()
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
ExprKind getKind() const
Definition MCExpr.h:85
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void setLoc(SMLoc loc)
Definition MCInst.h:207
unsigned getOpcode() const
Definition MCInst.h:202
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
Interface to description of machine instruction set.
Definition MCInstrInfo.h:27
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
void setExpr(const MCExpr *Val)
Definition MCInst.h:123
int64_t getImm() const
Definition MCInst.h:84
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
MCParsedAsmOperand - This abstract class represents a source-level assembly instruction operand.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
Streaming machine code generation interface.
Definition MCStreamer.h:222
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
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
LLVM Value Representation.
Definition Value.h:75
virtual void emitLiteral(MCSymbol *LblSym, const MCExpr *Value, bool SwitchLiteralSection, SMLoc L=SMLoc())
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
MCExpr const & getExpr(MCExpr const &Expr)
bool checkRegister(MCRegister RegNo, const FeatureBitset &FeatureBits, RegisterAccessType RA)
MCRegister getUserRegister(unsigned Code, const MCRegisterInfo &MRI)
This is an optimization pass for GlobalISel generic memory operations.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
SmallVectorImpl< std::unique_ptr< MCParsedAsmOperand > > OperandVector
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
Target & getTheXtensaTarget()
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
#define N
bool 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,...