Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / lib / Target / Xtensa / AsmParser / XtensaAsmParser.cpp
blob76c7328b547cd47ce748afc4c532643af9dc5462
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 //===----------------------------------------------------------------------===//
11 #include "MCTargetDesc/XtensaMCTargetDesc.h"
12 #include "TargetInfo/XtensaTargetInfo.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/ADT/StringSwitch.h"
15 #include "llvm/MC/MCContext.h"
16 #include "llvm/MC/MCExpr.h"
17 #include "llvm/MC/MCInst.h"
18 #include "llvm/MC/MCInstrInfo.h"
19 #include "llvm/MC/MCParser/MCAsmLexer.h"
20 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
22 #include "llvm/MC/MCRegisterInfo.h"
23 #include "llvm/MC/MCStreamer.h"
24 #include "llvm/MC/MCSubtargetInfo.h"
25 #include "llvm/MC/TargetRegistry.h"
26 #include "llvm/Support/Casting.h"
28 using namespace llvm;
30 #define DEBUG_TYPE "xtensa-asm-parser"
32 struct XtensaOperand;
34 class XtensaAsmParser : public MCTargetAsmParser {
36 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
38 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
39 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
40 SMLoc NameLoc, OperandVector &Operands) override;
41 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
42 OperandVector &Operands, MCStreamer &Out,
43 uint64_t &ErrorInfo,
44 bool MatchingInlineAsm) override;
45 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
46 unsigned Kind) override;
48 // Auto-generated instruction matching functions
49 #define GET_ASSEMBLER_HEADER
50 #include "XtensaGenAsmMatcher.inc"
52 ParseStatus parseImmediate(OperandVector &Operands);
53 ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false,
54 bool SR = false);
55 ParseStatus parseOperandWithModifier(OperandVector &Operands);
56 bool parseOperand(OperandVector &Operands, StringRef Mnemonic,
57 bool SR = false);
58 bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name,
59 SMLoc NameLoc, OperandVector &Operands);
60 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
61 SMLoc &EndLoc) override {
62 return ParseStatus::NoMatch;
64 ParseStatus parsePCRelTarget(OperandVector &Operands);
66 public:
67 enum XtensaMatchResultTy {
68 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
69 #define GET_OPERAND_DIAGNOSTIC_TYPES
70 #include "XtensaGenAsmMatcher.inc"
71 #undef GET_OPERAND_DIAGNOSTIC_TYPES
74 XtensaAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
75 const MCInstrInfo &MII, const MCTargetOptions &Options)
76 : MCTargetAsmParser(Options, STI, MII) {
77 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
81 // Return true if Expr is in the range [MinValue, MaxValue].
82 static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) {
83 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
84 int64_t Value = CE->getValue();
85 return Value >= MinValue && Value <= MaxValue;
87 return false;
90 struct XtensaOperand : public MCParsedAsmOperand {
92 enum KindTy {
93 Token,
94 Register,
95 Immediate,
96 } Kind;
98 struct RegOp {
99 unsigned RegNum;
102 struct ImmOp {
103 const MCExpr *Val;
106 SMLoc StartLoc, EndLoc;
107 union {
108 StringRef Tok;
109 RegOp Reg;
110 ImmOp Imm;
113 XtensaOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
115 public:
116 XtensaOperand(const XtensaOperand &o) : MCParsedAsmOperand() {
117 Kind = o.Kind;
118 StartLoc = o.StartLoc;
119 EndLoc = o.EndLoc;
120 switch (Kind) {
121 case Register:
122 Reg = o.Reg;
123 break;
124 case Immediate:
125 Imm = o.Imm;
126 break;
127 case Token:
128 Tok = o.Tok;
129 break;
133 bool isToken() const override { return Kind == Token; }
134 bool isReg() const override { return Kind == Register; }
135 bool isImm() const override { return Kind == Immediate; }
136 bool isMem() const override { return false; }
138 bool isImm(int64_t MinValue, int64_t MaxValue) const {
139 return Kind == Immediate && inRange(getImm(), MinValue, MaxValue);
142 bool isImm8() const { return isImm(-128, 127); }
144 bool isImm8_sh8() const {
145 return isImm(-32768, 32512) &&
146 ((cast<MCConstantExpr>(getImm())->getValue() & 0xFF) == 0);
149 bool isImm12() const { return isImm(-2048, 2047); }
151 bool isImm12m() const { return isImm(-2048, 2047); }
153 bool isOffset4m32() const {
154 return isImm(0, 60) &&
155 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
158 bool isOffset8m8() const { return isImm(0, 255); }
160 bool isOffset8m16() const {
161 return isImm(0, 510) &&
162 ((cast<MCConstantExpr>(getImm())->getValue() & 0x1) == 0);
165 bool isOffset8m32() const {
166 return isImm(0, 1020) &&
167 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
170 bool isUimm4() const { return isImm(0, 15); }
172 bool isUimm5() const { return isImm(0, 31); }
174 bool isImm8n_7() const { return isImm(-8, 7); }
176 bool isShimm1_31() const { return isImm(1, 31); }
178 bool isImm16_31() const { return isImm(16, 31); }
180 bool isImm1_16() const { return isImm(1, 16); }
182 bool isB4const() const {
183 if (Kind != Immediate)
184 return false;
185 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
186 int64_t Value = CE->getValue();
187 switch (Value) {
188 case -1:
189 case 1:
190 case 2:
191 case 3:
192 case 4:
193 case 5:
194 case 6:
195 case 7:
196 case 8:
197 case 10:
198 case 12:
199 case 16:
200 case 32:
201 case 64:
202 case 128:
203 case 256:
204 return true;
205 default:
206 return false;
209 return false;
212 bool isB4constu() const {
213 if (Kind != Immediate)
214 return false;
215 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
216 int64_t Value = CE->getValue();
217 switch (Value) {
218 case 32768:
219 case 65536:
220 case 2:
221 case 3:
222 case 4:
223 case 5:
224 case 6:
225 case 7:
226 case 8:
227 case 10:
228 case 12:
229 case 16:
230 case 32:
231 case 64:
232 case 128:
233 case 256:
234 return true;
235 default:
236 return false;
239 return false;
242 /// getStartLoc - Gets location of the first token of this operand
243 SMLoc getStartLoc() const override { return StartLoc; }
244 /// getEndLoc - Gets location of the last token of this operand
245 SMLoc getEndLoc() const override { return EndLoc; }
247 unsigned getReg() const override {
248 assert(Kind == Register && "Invalid type access!");
249 return Reg.RegNum;
252 const MCExpr *getImm() const {
253 assert(Kind == Immediate && "Invalid type access!");
254 return Imm.Val;
257 StringRef getToken() const {
258 assert(Kind == Token && "Invalid type access!");
259 return Tok;
262 void print(raw_ostream &OS) const override {
263 switch (Kind) {
264 case Immediate:
265 OS << *getImm();
266 break;
267 case Register:
268 OS << "<register x";
269 OS << getReg() << ">";
270 break;
271 case Token:
272 OS << "'" << getToken() << "'";
273 break;
277 static std::unique_ptr<XtensaOperand> createToken(StringRef Str, SMLoc S) {
278 auto Op = std::make_unique<XtensaOperand>(Token);
279 Op->Tok = Str;
280 Op->StartLoc = S;
281 Op->EndLoc = S;
282 return Op;
285 static std::unique_ptr<XtensaOperand> createReg(unsigned RegNo, SMLoc S,
286 SMLoc E) {
287 auto Op = std::make_unique<XtensaOperand>(Register);
288 Op->Reg.RegNum = RegNo;
289 Op->StartLoc = S;
290 Op->EndLoc = E;
291 return Op;
294 static std::unique_ptr<XtensaOperand> createImm(const MCExpr *Val, SMLoc S,
295 SMLoc E) {
296 auto Op = std::make_unique<XtensaOperand>(Immediate);
297 Op->Imm.Val = Val;
298 Op->StartLoc = S;
299 Op->EndLoc = E;
300 return Op;
303 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
304 assert(Expr && "Expr shouldn't be null!");
305 int64_t Imm = 0;
306 bool IsConstant = false;
308 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
309 IsConstant = true;
310 Imm = CE->getValue();
313 if (IsConstant)
314 Inst.addOperand(MCOperand::createImm(Imm));
315 else
316 Inst.addOperand(MCOperand::createExpr(Expr));
319 // Used by the TableGen Code
320 void addRegOperands(MCInst &Inst, unsigned N) const {
321 assert(N == 1 && "Invalid number of operands!");
322 Inst.addOperand(MCOperand::createReg(getReg()));
325 void addImmOperands(MCInst &Inst, unsigned N) const {
326 assert(N == 1 && "Invalid number of operands!");
327 addExpr(Inst, getImm());
331 #define GET_REGISTER_MATCHER
332 #define GET_MATCHER_IMPLEMENTATION
333 #include "XtensaGenAsmMatcher.inc"
335 unsigned XtensaAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
336 unsigned Kind) {
337 return Match_InvalidOperand;
340 static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
341 uint64_t ErrorInfo) {
342 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
343 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
344 if (ErrorLoc == SMLoc())
345 return Loc;
346 return ErrorLoc;
348 return Loc;
351 bool XtensaAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
352 OperandVector &Operands,
353 MCStreamer &Out,
354 uint64_t &ErrorInfo,
355 bool MatchingInlineAsm) {
356 MCInst Inst;
357 auto Result =
358 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
360 switch (Result) {
361 default:
362 break;
363 case Match_Success:
364 Inst.setLoc(IDLoc);
365 Out.emitInstruction(Inst, getSTI());
366 return false;
367 case Match_MissingFeature:
368 return Error(IDLoc, "instruction use requires an option to be enabled");
369 case Match_MnemonicFail:
370 return Error(IDLoc, "unrecognized instruction mnemonic");
371 case Match_InvalidOperand: {
372 SMLoc ErrorLoc = IDLoc;
373 if (ErrorInfo != ~0U) {
374 if (ErrorInfo >= Operands.size())
375 return Error(ErrorLoc, "too few operands for instruction");
377 ErrorLoc = ((XtensaOperand &)*Operands[ErrorInfo]).getStartLoc();
378 if (ErrorLoc == SMLoc())
379 ErrorLoc = IDLoc;
381 return Error(ErrorLoc, "invalid operand for instruction");
383 case Match_InvalidImm8:
384 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
385 "expected immediate in range [-128, 127]");
386 case Match_InvalidImm8_sh8:
387 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
388 "expected immediate in range [-32768, 32512], first 8 bits "
389 "should be zero");
390 case Match_InvalidB4const:
391 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
392 "expected b4const immediate");
393 case Match_InvalidB4constu:
394 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
395 "expected b4constu immediate");
396 case Match_InvalidImm12:
397 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
398 "expected immediate in range [-2048, 2047]");
399 case Match_InvalidImm12m:
400 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
401 "expected immediate in range [-2048, 2047]");
402 case Match_InvalidImm1_16:
403 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
404 "expected immediate in range [1, 16]");
405 case Match_InvalidShimm1_31:
406 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
407 "expected immediate in range [1, 31]");
408 case Match_InvalidUimm4:
409 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
410 "expected immediate in range [0, 15]");
411 case Match_InvalidUimm5:
412 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
413 "expected immediate in range [0, 31]");
414 case Match_InvalidOffset8m8:
415 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
416 "expected immediate in range [0, 255]");
417 case Match_InvalidOffset8m16:
418 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
419 "expected immediate in range [0, 510], first bit "
420 "should be zero");
421 case Match_InvalidOffset8m32:
422 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
423 "expected immediate in range [0, 1020], first 2 bits "
424 "should be zero");
425 case Match_InvalidOffset4m32:
426 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
427 "expected immediate in range [0, 60], first 2 bits "
428 "should be zero");
431 report_fatal_error("Unknown match type detected!");
434 ParseStatus XtensaAsmParser::parsePCRelTarget(OperandVector &Operands) {
435 MCAsmParser &Parser = getParser();
436 LLVM_DEBUG(dbgs() << "parsePCRelTarget\n");
438 SMLoc S = getLexer().getLoc();
440 // Expressions are acceptable
441 const MCExpr *Expr = nullptr;
442 if (Parser.parseExpression(Expr)) {
443 // We have no way of knowing if a symbol was consumed so we must ParseFail
444 return ParseStatus::Failure;
447 // Currently not support constants
448 if (Expr->getKind() == MCExpr::ExprKind::Constant)
449 return Error(getLoc(), "unknown operand");
451 Operands.push_back(XtensaOperand::createImm(Expr, S, getLexer().getLoc()));
452 return ParseStatus::Success;
455 bool XtensaAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
456 SMLoc &EndLoc) {
457 const AsmToken &Tok = getParser().getTok();
458 StartLoc = Tok.getLoc();
459 EndLoc = Tok.getEndLoc();
460 Reg = Xtensa::NoRegister;
461 StringRef Name = getLexer().getTok().getIdentifier();
463 if (!MatchRegisterName(Name) && !MatchRegisterAltName(Name)) {
464 getParser().Lex(); // Eat identifier token.
465 return false;
468 return Error(StartLoc, "invalid register name");
471 ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
472 bool AllowParens, bool SR) {
473 SMLoc FirstS = getLoc();
474 bool HadParens = false;
475 AsmToken Buf[2];
476 StringRef RegName;
478 // If this a parenthesised register name is allowed, parse it atomically
479 if (AllowParens && getLexer().is(AsmToken::LParen)) {
480 size_t ReadCount = getLexer().peekTokens(Buf);
481 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
482 if ((Buf[0].getKind() == AsmToken::Integer) && (!SR))
483 return ParseStatus::NoMatch;
484 HadParens = true;
485 getParser().Lex(); // Eat '('
489 unsigned RegNo = 0;
491 switch (getLexer().getKind()) {
492 default:
493 return ParseStatus::NoMatch;
494 case AsmToken::Integer:
495 if (!SR)
496 return ParseStatus::NoMatch;
497 RegName = StringRef(std::to_string(getLexer().getTok().getIntVal()));
498 RegNo = MatchRegisterName(RegName);
499 if (RegNo == 0)
500 RegNo = MatchRegisterAltName(RegName);
501 break;
502 case AsmToken::Identifier:
503 RegName = getLexer().getTok().getIdentifier();
504 RegNo = MatchRegisterName(RegName);
505 if (RegNo == 0)
506 RegNo = MatchRegisterAltName(RegName);
507 break;
510 if (RegNo == 0) {
511 if (HadParens)
512 getLexer().UnLex(Buf[0]);
513 return ParseStatus::NoMatch;
515 if (HadParens)
516 Operands.push_back(XtensaOperand::createToken("(", FirstS));
517 SMLoc S = getLoc();
518 SMLoc E = getParser().getTok().getEndLoc();
519 getLexer().Lex();
520 Operands.push_back(XtensaOperand::createReg(RegNo, S, E));
522 if (HadParens) {
523 getParser().Lex(); // Eat ')'
524 Operands.push_back(XtensaOperand::createToken(")", getLoc()));
527 return ParseStatus::Success;
530 ParseStatus XtensaAsmParser::parseImmediate(OperandVector &Operands) {
531 SMLoc S = getLoc();
532 SMLoc E;
533 const MCExpr *Res;
535 switch (getLexer().getKind()) {
536 default:
537 return ParseStatus::NoMatch;
538 case AsmToken::LParen:
539 case AsmToken::Minus:
540 case AsmToken::Plus:
541 case AsmToken::Tilde:
542 case AsmToken::Integer:
543 case AsmToken::String:
544 if (getParser().parseExpression(Res))
545 return ParseStatus::Failure;
546 break;
547 case AsmToken::Identifier: {
548 StringRef Identifier;
549 if (getParser().parseIdentifier(Identifier))
550 return ParseStatus::Failure;
552 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
553 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
554 break;
556 case AsmToken::Percent:
557 return parseOperandWithModifier(Operands);
560 E = SMLoc::getFromPointer(S.getPointer() - 1);
561 Operands.push_back(XtensaOperand::createImm(Res, S, E));
562 return ParseStatus::Success;
565 ParseStatus XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) {
566 return ParseStatus::Failure;
569 /// Looks at a token type and creates the relevant operand
570 /// from this information, adding to Operands.
571 /// If operand was parsed, returns false, else true.
572 bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
573 bool SR) {
574 // Check if the current operand has a custom associated parser, if so, try to
575 // custom parse the operand, or fallback to the general approach.
576 ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);
577 if (Res.isSuccess())
578 return false;
580 // If there wasn't a custom match, try the generic matcher below. Otherwise,
581 // there was a match, but an error occurred, in which case, just return that
582 // the operand parsing failed.
583 if (Res.isFailure())
584 return true;
586 // Attempt to parse token as register
587 if (parseRegister(Operands, true, SR).isSuccess())
588 return false;
590 // Attempt to parse token as an immediate
591 if (parseImmediate(Operands).isSuccess())
592 return false;
594 // Finally we have exhausted all options and must declare defeat.
595 return Error(getLoc(), "unknown operand");
598 bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
599 StringRef Name, SMLoc NameLoc,
600 OperandVector &Operands) {
601 if ((Name.startswith("wsr.") || Name.startswith("rsr.") ||
602 Name.startswith("xsr.")) &&
603 (Name.size() > 4)) {
604 // Parse case when instruction name is concatenated with SR register
605 // name, like "wsr.sar a1"
607 // First operand is token for instruction
608 Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc));
610 StringRef RegName = Name.drop_front(4);
611 unsigned RegNo = MatchRegisterName(RegName);
613 if (RegNo == 0)
614 RegNo = MatchRegisterAltName(RegName);
616 if (RegNo == 0)
617 return Error(NameLoc, "invalid register name");
619 // Parse operand
620 if (parseOperand(Operands, Name))
621 return true;
623 SMLoc S = getLoc();
624 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
625 Operands.push_back(XtensaOperand::createReg(RegNo, S, E));
626 } else {
627 // First operand is token for instruction
628 Operands.push_back(XtensaOperand::createToken(Name, NameLoc));
630 // Parse first operand
631 if (parseOperand(Operands, Name))
632 return true;
634 if (!parseOptionalToken(AsmToken::Comma)) {
635 SMLoc Loc = getLexer().getLoc();
636 getParser().eatToEndOfStatement();
637 return Error(Loc, "unexpected token");
640 // Parse second operand
641 if (parseOperand(Operands, Name, true))
642 return true;
645 if (getLexer().isNot(AsmToken::EndOfStatement)) {
646 SMLoc Loc = getLexer().getLoc();
647 getParser().eatToEndOfStatement();
648 return Error(Loc, "unexpected token");
651 getParser().Lex(); // Consume the EndOfStatement.
652 return false;
655 bool XtensaAsmParser::ParseInstruction(ParseInstructionInfo &Info,
656 StringRef Name, SMLoc NameLoc,
657 OperandVector &Operands) {
658 if (Name.startswith("wsr") || Name.startswith("rsr") ||
659 Name.startswith("xsr")) {
660 return ParseInstructionWithSR(Info, Name, NameLoc, Operands);
663 // First operand is token for instruction
664 Operands.push_back(XtensaOperand::createToken(Name, NameLoc));
666 // If there are no more operands, then finish
667 if (getLexer().is(AsmToken::EndOfStatement))
668 return false;
670 // Parse first operand
671 if (parseOperand(Operands, Name))
672 return true;
674 // Parse until end of statement, consuming commas between operands
675 while (parseOptionalToken(AsmToken::Comma))
676 if (parseOperand(Operands, Name))
677 return true;
679 if (getLexer().isNot(AsmToken::EndOfStatement)) {
680 SMLoc Loc = getLexer().getLoc();
681 getParser().eatToEndOfStatement();
682 return Error(Loc, "unexpected token");
685 getParser().Lex(); // Consume the EndOfStatement.
686 return false;
689 // Force static initialization.
690 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() {
691 RegisterMCAsmParser<XtensaAsmParser> X(getTheXtensaTarget());