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
11 #include "MCTargetDesc/XtensaMCExpr.h"
12 #include "MCTargetDesc/XtensaMCTargetDesc.h"
13 #include "MCTargetDesc/XtensaTargetStreamer.h"
14 #include "TargetInfo/XtensaTargetInfo.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/StringSwitch.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"
21 #include "llvm/MC/MCParser/MCAsmLexer.h"
22 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
23 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
24 #include "llvm/MC/MCRegisterInfo.h"
25 #include "llvm/MC/MCStreamer.h"
26 #include "llvm/MC/MCSubtargetInfo.h"
27 #include "llvm/MC/MCSymbol.h"
28 #include "llvm/MC/TargetRegistry.h"
29 #include "llvm/Support/Casting.h"
30
31 using namespace llvm;
32
33 #define DEBUG_TYPE "xtensa-asm-parser"
34
35 struct XtensaOperand;
36
37 class XtensaAsmParser : public MCTargetAsmParser {
38
getLoc() const39 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
40
getTargetStreamer()41 XtensaTargetStreamer &getTargetStreamer() {
42 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
43 return static_cast<XtensaTargetStreamer &>(TS);
44 }
45
46 ParseStatus parseDirective(AsmToken DirectiveID) override;
47 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
48 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
49 SMLoc NameLoc, OperandVector &Operands) override;
50 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
51 OperandVector &Operands, MCStreamer &Out,
52 uint64_t &ErrorInfo,
53 bool MatchingInlineAsm) override;
54 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
55 unsigned Kind) override;
56
57 bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
58 const MCSubtargetInfo *STI);
59
60 // Auto-generated instruction matching functions
61 #define GET_ASSEMBLER_HEADER
62 #include "XtensaGenAsmMatcher.inc"
63
64 ParseStatus parseImmediate(OperandVector &Operands);
65 ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false,
66 bool SR = false);
67 ParseStatus parseOperandWithModifier(OperandVector &Operands);
68 bool parseOperand(OperandVector &Operands, StringRef Mnemonic,
69 bool SR = false);
70 bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name,
71 SMLoc NameLoc, OperandVector &Operands);
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)72 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
73 SMLoc &EndLoc) override {
74 return ParseStatus::NoMatch;
75 }
76 ParseStatus parsePCRelTarget(OperandVector &Operands);
77 bool parseLiteralDirective(SMLoc L);
78
79 public:
80 enum XtensaMatchResultTy {
81 Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
82 #define GET_OPERAND_DIAGNOSTIC_TYPES
83 #include "XtensaGenAsmMatcher.inc"
84 #undef GET_OPERAND_DIAGNOSTIC_TYPES
85 };
86
XtensaAsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)87 XtensaAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
88 const MCInstrInfo &MII, const MCTargetOptions &Options)
89 : MCTargetAsmParser(Options, STI, MII) {
90 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
91 }
92 };
93
94 // Return true if Expr is in the range [MinValue, MaxValue].
inRange(const MCExpr * Expr,int64_t MinValue,int64_t MaxValue)95 static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) {
96 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
97 int64_t Value = CE->getValue();
98 return Value >= MinValue && Value <= MaxValue;
99 }
100 return false;
101 }
102
103 struct XtensaOperand : public MCParsedAsmOperand {
104
105 enum KindTy {
106 Token,
107 Register,
108 Immediate,
109 } Kind;
110
111 struct RegOp {
112 unsigned RegNum;
113 };
114
115 struct ImmOp {
116 const MCExpr *Val;
117 };
118
119 SMLoc StartLoc, EndLoc;
120 union {
121 StringRef Tok;
122 RegOp Reg;
123 ImmOp Imm;
124 };
125
XtensaOperandXtensaOperand126 XtensaOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
127
128 public:
XtensaOperandXtensaOperand129 XtensaOperand(const XtensaOperand &o) : MCParsedAsmOperand() {
130 Kind = o.Kind;
131 StartLoc = o.StartLoc;
132 EndLoc = o.EndLoc;
133 switch (Kind) {
134 case Register:
135 Reg = o.Reg;
136 break;
137 case Immediate:
138 Imm = o.Imm;
139 break;
140 case Token:
141 Tok = o.Tok;
142 break;
143 }
144 }
145
isTokenXtensaOperand146 bool isToken() const override { return Kind == Token; }
isRegXtensaOperand147 bool isReg() const override { return Kind == Register; }
isImmXtensaOperand148 bool isImm() const override { return Kind == Immediate; }
isMemXtensaOperand149 bool isMem() const override { return false; }
150
isImmXtensaOperand151 bool isImm(int64_t MinValue, int64_t MaxValue) const {
152 return Kind == Immediate && inRange(getImm(), MinValue, MaxValue);
153 }
154
isImm8XtensaOperand155 bool isImm8() const { return isImm(-128, 127); }
156
isImm8_sh8XtensaOperand157 bool isImm8_sh8() const {
158 return isImm(-32768, 32512) &&
159 ((cast<MCConstantExpr>(getImm())->getValue() & 0xFF) == 0);
160 }
161
isImm12XtensaOperand162 bool isImm12() const { return isImm(-2048, 2047); }
163
164 // Convert MOVI to literal load, when immediate is not in range (-2048, 2047)
isImm12mXtensaOperand165 bool isImm12m() const { return Kind == Immediate; }
166
isOffset4m32XtensaOperand167 bool isOffset4m32() const {
168 return isImm(0, 60) &&
169 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
170 }
171
isOffset8m8XtensaOperand172 bool isOffset8m8() const { return isImm(0, 255); }
173
isOffset8m16XtensaOperand174 bool isOffset8m16() const {
175 return isImm(0, 510) &&
176 ((cast<MCConstantExpr>(getImm())->getValue() & 0x1) == 0);
177 }
178
isOffset8m32XtensaOperand179 bool isOffset8m32() const {
180 return isImm(0, 1020) &&
181 ((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);
182 }
183
isUimm4XtensaOperand184 bool isUimm4() const { return isImm(0, 15); }
185
isUimm5XtensaOperand186 bool isUimm5() const { return isImm(0, 31); }
187
isImm8n_7XtensaOperand188 bool isImm8n_7() const { return isImm(-8, 7); }
189
isShimm1_31XtensaOperand190 bool isShimm1_31() const { return isImm(1, 31); }
191
isImm16_31XtensaOperand192 bool isImm16_31() const { return isImm(16, 31); }
193
isImm1_16XtensaOperand194 bool isImm1_16() const { return isImm(1, 16); }
195
isB4constXtensaOperand196 bool isB4const() const {
197 if (Kind != Immediate)
198 return false;
199 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
200 int64_t Value = CE->getValue();
201 switch (Value) {
202 case -1:
203 case 1:
204 case 2:
205 case 3:
206 case 4:
207 case 5:
208 case 6:
209 case 7:
210 case 8:
211 case 10:
212 case 12:
213 case 16:
214 case 32:
215 case 64:
216 case 128:
217 case 256:
218 return true;
219 default:
220 return false;
221 }
222 }
223 return false;
224 }
225
isB4constuXtensaOperand226 bool isB4constu() const {
227 if (Kind != Immediate)
228 return false;
229 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
230 int64_t Value = CE->getValue();
231 switch (Value) {
232 case 32768:
233 case 65536:
234 case 2:
235 case 3:
236 case 4:
237 case 5:
238 case 6:
239 case 7:
240 case 8:
241 case 10:
242 case 12:
243 case 16:
244 case 32:
245 case 64:
246 case 128:
247 case 256:
248 return true;
249 default:
250 return false;
251 }
252 }
253 return false;
254 }
255
256 /// getStartLoc - Gets location of the first token of this operand
getStartLocXtensaOperand257 SMLoc getStartLoc() const override { return StartLoc; }
258 /// getEndLoc - Gets location of the last token of this operand
getEndLocXtensaOperand259 SMLoc getEndLoc() const override { return EndLoc; }
260
getRegXtensaOperand261 MCRegister getReg() const override {
262 assert(Kind == Register && "Invalid type access!");
263 return Reg.RegNum;
264 }
265
getImmXtensaOperand266 const MCExpr *getImm() const {
267 assert(Kind == Immediate && "Invalid type access!");
268 return Imm.Val;
269 }
270
getTokenXtensaOperand271 StringRef getToken() const {
272 assert(Kind == Token && "Invalid type access!");
273 return Tok;
274 }
275
printXtensaOperand276 void print(raw_ostream &OS) const override {
277 switch (Kind) {
278 case Immediate:
279 OS << *getImm();
280 break;
281 case Register:
282 OS << "<register x";
283 OS << getReg() << ">";
284 break;
285 case Token:
286 OS << "'" << getToken() << "'";
287 break;
288 }
289 }
290
createTokenXtensaOperand291 static std::unique_ptr<XtensaOperand> createToken(StringRef Str, SMLoc S) {
292 auto Op = std::make_unique<XtensaOperand>(Token);
293 Op->Tok = Str;
294 Op->StartLoc = S;
295 Op->EndLoc = S;
296 return Op;
297 }
298
createRegXtensaOperand299 static std::unique_ptr<XtensaOperand> createReg(unsigned RegNo, SMLoc S,
300 SMLoc E) {
301 auto Op = std::make_unique<XtensaOperand>(Register);
302 Op->Reg.RegNum = RegNo;
303 Op->StartLoc = S;
304 Op->EndLoc = E;
305 return Op;
306 }
307
createImmXtensaOperand308 static std::unique_ptr<XtensaOperand> createImm(const MCExpr *Val, SMLoc S,
309 SMLoc E) {
310 auto Op = std::make_unique<XtensaOperand>(Immediate);
311 Op->Imm.Val = Val;
312 Op->StartLoc = S;
313 Op->EndLoc = E;
314 return Op;
315 }
316
addExprXtensaOperand317 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
318 assert(Expr && "Expr shouldn't be null!");
319 int64_t Imm = 0;
320 bool IsConstant = false;
321
322 if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {
323 IsConstant = true;
324 Imm = CE->getValue();
325 }
326
327 if (IsConstant)
328 Inst.addOperand(MCOperand::createImm(Imm));
329 else
330 Inst.addOperand(MCOperand::createExpr(Expr));
331 }
332
333 // Used by the TableGen Code
addRegOperandsXtensaOperand334 void addRegOperands(MCInst &Inst, unsigned N) const {
335 assert(N == 1 && "Invalid number of operands!");
336 Inst.addOperand(MCOperand::createReg(getReg()));
337 }
338
addImmOperandsXtensaOperand339 void addImmOperands(MCInst &Inst, unsigned N) const {
340 assert(N == 1 && "Invalid number of operands!");
341 addExpr(Inst, getImm());
342 }
343 };
344
345 #define GET_REGISTER_MATCHER
346 #define GET_MATCHER_IMPLEMENTATION
347 #include "XtensaGenAsmMatcher.inc"
348
validateTargetOperandClass(MCParsedAsmOperand & AsmOp,unsigned Kind)349 unsigned XtensaAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
350 unsigned Kind) {
351 return Match_InvalidOperand;
352 }
353
RefineErrorLoc(const SMLoc Loc,const OperandVector & Operands,uint64_t ErrorInfo)354 static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
355 uint64_t ErrorInfo) {
356 if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
357 SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
358 if (ErrorLoc == SMLoc())
359 return Loc;
360 return ErrorLoc;
361 }
362 return Loc;
363 }
364
processInstruction(MCInst & Inst,SMLoc IDLoc,MCStreamer & Out,const MCSubtargetInfo * STI)365 bool XtensaAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
366 MCStreamer &Out,
367 const MCSubtargetInfo *STI) {
368 Inst.setLoc(IDLoc);
369 const unsigned Opcode = Inst.getOpcode();
370 switch (Opcode) {
371 case Xtensa::L32R: {
372 const MCSymbolRefExpr *OpExpr =
373 static_cast<const MCSymbolRefExpr *>(Inst.getOperand(1).getExpr());
374 XtensaMCExpr::VariantKind Kind = XtensaMCExpr::VK_Xtensa_None;
375 const MCExpr *NewOpExpr = XtensaMCExpr::create(OpExpr, Kind, getContext());
376 Inst.getOperand(1).setExpr(NewOpExpr);
377 break;
378 }
379 case Xtensa::MOVI: {
380 XtensaTargetStreamer &TS = this->getTargetStreamer();
381
382 // Expand MOVI operand
383 if (!Inst.getOperand(1).isExpr()) {
384 uint64_t ImmOp64 = Inst.getOperand(1).getImm();
385 int32_t Imm = ImmOp64;
386 if (!isInt<12>(Imm)) {
387 XtensaTargetStreamer &TS = this->getTargetStreamer();
388 MCInst TmpInst;
389 TmpInst.setLoc(IDLoc);
390 TmpInst.setOpcode(Xtensa::L32R);
391 const MCExpr *Value = MCConstantExpr::create(ImmOp64, getContext());
392 MCSymbol *Sym = getContext().createTempSymbol();
393 const MCExpr *Expr = MCSymbolRefExpr::create(
394 Sym, MCSymbolRefExpr::VK_None, getContext());
395 const MCExpr *OpExpr = XtensaMCExpr::create(
396 Expr, XtensaMCExpr::VK_Xtensa_None, getContext());
397 TmpInst.addOperand(Inst.getOperand(0));
398 MCOperand Op1 = MCOperand::createExpr(OpExpr);
399 TmpInst.addOperand(Op1);
400 TS.emitLiteral(Sym, Value, true, IDLoc);
401 Inst = TmpInst;
402 }
403 } else {
404 MCInst TmpInst;
405 TmpInst.setLoc(IDLoc);
406 TmpInst.setOpcode(Xtensa::L32R);
407 const MCExpr *Value = Inst.getOperand(1).getExpr();
408 MCSymbol *Sym = getContext().createTempSymbol();
409 const MCExpr *Expr =
410 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
411 const MCExpr *OpExpr = XtensaMCExpr::create(
412 Expr, XtensaMCExpr::VK_Xtensa_None, getContext());
413 TmpInst.addOperand(Inst.getOperand(0));
414 MCOperand Op1 = MCOperand::createExpr(OpExpr);
415 TmpInst.addOperand(Op1);
416 Inst = TmpInst;
417 TS.emitLiteral(Sym, Value, true, IDLoc);
418 }
419 break;
420 }
421 default:
422 break;
423 }
424
425 return true;
426 }
427
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)428 bool XtensaAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
429 OperandVector &Operands,
430 MCStreamer &Out,
431 uint64_t &ErrorInfo,
432 bool MatchingInlineAsm) {
433 MCInst Inst;
434 auto Result =
435 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
436
437 switch (Result) {
438 default:
439 break;
440 case Match_Success:
441 processInstruction(Inst, IDLoc, Out, STI);
442 Inst.setLoc(IDLoc);
443 Out.emitInstruction(Inst, getSTI());
444 return false;
445 case Match_MissingFeature:
446 return Error(IDLoc, "instruction use requires an option to be enabled");
447 case Match_MnemonicFail:
448 return Error(IDLoc, "unrecognized instruction mnemonic");
449 case Match_InvalidOperand: {
450 SMLoc ErrorLoc = IDLoc;
451 if (ErrorInfo != ~0U) {
452 if (ErrorInfo >= Operands.size())
453 return Error(ErrorLoc, "too few operands for instruction");
454
455 ErrorLoc = ((XtensaOperand &)*Operands[ErrorInfo]).getStartLoc();
456 if (ErrorLoc == SMLoc())
457 ErrorLoc = IDLoc;
458 }
459 return Error(ErrorLoc, "invalid operand for instruction");
460 }
461 case Match_InvalidImm8:
462 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
463 "expected immediate in range [-128, 127]");
464 case Match_InvalidImm8_sh8:
465 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
466 "expected immediate in range [-32768, 32512], first 8 bits "
467 "should be zero");
468 case Match_InvalidB4const:
469 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
470 "expected b4const immediate");
471 case Match_InvalidB4constu:
472 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
473 "expected b4constu immediate");
474 case Match_InvalidImm12:
475 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
476 "expected immediate in range [-2048, 2047]");
477 case Match_InvalidImm12m:
478 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
479 "expected immediate in range [-2048, 2047]");
480 case Match_InvalidImm1_16:
481 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
482 "expected immediate in range [1, 16]");
483 case Match_InvalidShimm1_31:
484 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
485 "expected immediate in range [1, 31]");
486 case Match_InvalidUimm4:
487 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
488 "expected immediate in range [0, 15]");
489 case Match_InvalidUimm5:
490 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
491 "expected immediate in range [0, 31]");
492 case Match_InvalidOffset8m8:
493 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
494 "expected immediate in range [0, 255]");
495 case Match_InvalidOffset8m16:
496 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
497 "expected immediate in range [0, 510], first bit "
498 "should be zero");
499 case Match_InvalidOffset8m32:
500 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
501 "expected immediate in range [0, 1020], first 2 bits "
502 "should be zero");
503 case Match_InvalidOffset4m32:
504 return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
505 "expected immediate in range [0, 60], first 2 bits "
506 "should be zero");
507 }
508
509 report_fatal_error("Unknown match type detected!");
510 }
511
parsePCRelTarget(OperandVector & Operands)512 ParseStatus XtensaAsmParser::parsePCRelTarget(OperandVector &Operands) {
513 MCAsmParser &Parser = getParser();
514 LLVM_DEBUG(dbgs() << "parsePCRelTarget\n");
515
516 SMLoc S = getLexer().getLoc();
517
518 // Expressions are acceptable
519 const MCExpr *Expr = nullptr;
520 if (Parser.parseExpression(Expr)) {
521 // We have no way of knowing if a symbol was consumed so we must ParseFail
522 return ParseStatus::Failure;
523 }
524
525 // Currently not support constants
526 if (Expr->getKind() == MCExpr::ExprKind::Constant)
527 return Error(getLoc(), "unknown operand");
528
529 Operands.push_back(XtensaOperand::createImm(Expr, S, getLexer().getLoc()));
530 return ParseStatus::Success;
531 }
532
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)533 bool XtensaAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
534 SMLoc &EndLoc) {
535 const AsmToken &Tok = getParser().getTok();
536 StartLoc = Tok.getLoc();
537 EndLoc = Tok.getEndLoc();
538 Reg = Xtensa::NoRegister;
539 StringRef Name = getLexer().getTok().getIdentifier();
540
541 if (!MatchRegisterName(Name) && !MatchRegisterAltName(Name)) {
542 getParser().Lex(); // Eat identifier token.
543 return false;
544 }
545
546 return Error(StartLoc, "invalid register name");
547 }
548
parseRegister(OperandVector & Operands,bool AllowParens,bool SR)549 ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,
550 bool AllowParens, bool SR) {
551 SMLoc FirstS = getLoc();
552 bool HadParens = false;
553 AsmToken Buf[2];
554 StringRef RegName;
555
556 // If this a parenthesised register name is allowed, parse it atomically
557 if (AllowParens && getLexer().is(AsmToken::LParen)) {
558 size_t ReadCount = getLexer().peekTokens(Buf);
559 if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
560 if ((Buf[0].getKind() == AsmToken::Integer) && (!SR))
561 return ParseStatus::NoMatch;
562 HadParens = true;
563 getParser().Lex(); // Eat '('
564 }
565 }
566
567 unsigned RegNo = 0;
568
569 switch (getLexer().getKind()) {
570 default:
571 return ParseStatus::NoMatch;
572 case AsmToken::Integer:
573 if (!SR)
574 return ParseStatus::NoMatch;
575 RegName = getLexer().getTok().getString();
576 RegNo = MatchRegisterName(RegName);
577 if (RegNo == 0)
578 RegNo = MatchRegisterAltName(RegName);
579 break;
580 case AsmToken::Identifier:
581 RegName = getLexer().getTok().getIdentifier();
582 RegNo = MatchRegisterName(RegName);
583 if (RegNo == 0)
584 RegNo = MatchRegisterAltName(RegName);
585 break;
586 }
587
588 if (RegNo == 0) {
589 if (HadParens)
590 getLexer().UnLex(Buf[0]);
591 return ParseStatus::NoMatch;
592 }
593 if (HadParens)
594 Operands.push_back(XtensaOperand::createToken("(", FirstS));
595 SMLoc S = getLoc();
596 SMLoc E = getParser().getTok().getEndLoc();
597 getLexer().Lex();
598 Operands.push_back(XtensaOperand::createReg(RegNo, S, E));
599
600 if (HadParens) {
601 getParser().Lex(); // Eat ')'
602 Operands.push_back(XtensaOperand::createToken(")", getLoc()));
603 }
604
605 return ParseStatus::Success;
606 }
607
parseImmediate(OperandVector & Operands)608 ParseStatus XtensaAsmParser::parseImmediate(OperandVector &Operands) {
609 SMLoc S = getLoc();
610 SMLoc E;
611 const MCExpr *Res;
612
613 switch (getLexer().getKind()) {
614 default:
615 return ParseStatus::NoMatch;
616 case AsmToken::LParen:
617 case AsmToken::Minus:
618 case AsmToken::Plus:
619 case AsmToken::Tilde:
620 case AsmToken::Integer:
621 case AsmToken::String:
622 if (getParser().parseExpression(Res))
623 return ParseStatus::Failure;
624 break;
625 case AsmToken::Identifier: {
626 StringRef Identifier;
627 if (getParser().parseIdentifier(Identifier))
628 return ParseStatus::Failure;
629
630 MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
631 Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
632 break;
633 }
634 case AsmToken::Percent:
635 return parseOperandWithModifier(Operands);
636 }
637
638 E = SMLoc::getFromPointer(S.getPointer() - 1);
639 Operands.push_back(XtensaOperand::createImm(Res, S, E));
640 return ParseStatus::Success;
641 }
642
parseOperandWithModifier(OperandVector & Operands)643 ParseStatus XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) {
644 return ParseStatus::Failure;
645 }
646
647 /// Looks at a token type and creates the relevant operand
648 /// from this information, adding to Operands.
649 /// If operand was parsed, returns false, else true.
parseOperand(OperandVector & Operands,StringRef Mnemonic,bool SR)650 bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
651 bool SR) {
652 // Check if the current operand has a custom associated parser, if so, try to
653 // custom parse the operand, or fallback to the general approach.
654 ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);
655 if (Res.isSuccess())
656 return false;
657
658 // If there wasn't a custom match, try the generic matcher below. Otherwise,
659 // there was a match, but an error occurred, in which case, just return that
660 // the operand parsing failed.
661 if (Res.isFailure())
662 return true;
663
664 // Attempt to parse token as register
665 if (parseRegister(Operands, true, SR).isSuccess())
666 return false;
667
668 // Attempt to parse token as an immediate
669 if (parseImmediate(Operands).isSuccess())
670 return false;
671
672 // Finally we have exhausted all options and must declare defeat.
673 return Error(getLoc(), "unknown operand");
674 }
675
ParseInstructionWithSR(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)676 bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,
677 StringRef Name, SMLoc NameLoc,
678 OperandVector &Operands) {
679 if ((Name.starts_with("wsr.") || Name.starts_with("rsr.") ||
680 Name.starts_with("xsr.")) &&
681 (Name.size() > 4)) {
682 // Parse case when instruction name is concatenated with SR register
683 // name, like "wsr.sar a1"
684
685 // First operand is token for instruction
686 Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc));
687
688 StringRef RegName = Name.drop_front(4);
689 unsigned RegNo = MatchRegisterName(RegName);
690
691 if (RegNo == 0)
692 RegNo = MatchRegisterAltName(RegName);
693
694 if (RegNo == 0)
695 return Error(NameLoc, "invalid register name");
696
697 // Parse operand
698 if (parseOperand(Operands, Name))
699 return true;
700
701 SMLoc S = getLoc();
702 SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
703 Operands.push_back(XtensaOperand::createReg(RegNo, S, E));
704 } else {
705 // First operand is token for instruction
706 Operands.push_back(XtensaOperand::createToken(Name, NameLoc));
707
708 // Parse first operand
709 if (parseOperand(Operands, Name))
710 return true;
711
712 if (!parseOptionalToken(AsmToken::Comma)) {
713 SMLoc Loc = getLexer().getLoc();
714 getParser().eatToEndOfStatement();
715 return Error(Loc, "unexpected token");
716 }
717
718 // Parse second operand
719 if (parseOperand(Operands, Name, true))
720 return true;
721 }
722
723 if (getLexer().isNot(AsmToken::EndOfStatement)) {
724 SMLoc Loc = getLexer().getLoc();
725 getParser().eatToEndOfStatement();
726 return Error(Loc, "unexpected token");
727 }
728
729 getParser().Lex(); // Consume the EndOfStatement.
730 return false;
731 }
732
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)733 bool XtensaAsmParser::ParseInstruction(ParseInstructionInfo &Info,
734 StringRef Name, SMLoc NameLoc,
735 OperandVector &Operands) {
736 if (Name.starts_with("wsr") || Name.starts_with("rsr") ||
737 Name.starts_with("xsr")) {
738 return ParseInstructionWithSR(Info, Name, NameLoc, Operands);
739 }
740
741 // First operand is token for instruction
742 Operands.push_back(XtensaOperand::createToken(Name, NameLoc));
743
744 // If there are no more operands, then finish
745 if (getLexer().is(AsmToken::EndOfStatement))
746 return false;
747
748 // Parse first operand
749 if (parseOperand(Operands, Name))
750 return true;
751
752 // Parse until end of statement, consuming commas between operands
753 while (parseOptionalToken(AsmToken::Comma))
754 if (parseOperand(Operands, Name))
755 return true;
756
757 if (getLexer().isNot(AsmToken::EndOfStatement)) {
758 SMLoc Loc = getLexer().getLoc();
759 getParser().eatToEndOfStatement();
760 return Error(Loc, "unexpected token");
761 }
762
763 getParser().Lex(); // Consume the EndOfStatement.
764 return false;
765 }
766
parseLiteralDirective(SMLoc L)767 bool XtensaAsmParser::parseLiteralDirective(SMLoc L) {
768 MCAsmParser &Parser = getParser();
769 const MCExpr *Value;
770 SMLoc LiteralLoc = getLexer().getLoc();
771 XtensaTargetStreamer &TS = this->getTargetStreamer();
772
773 if (Parser.parseExpression(Value))
774 return true;
775
776 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Value);
777
778 if (!SE)
779 return Error(LiteralLoc, "literal label must be a symbol");
780
781 if (Parser.parseComma())
782 return true;
783
784 SMLoc OpcodeLoc = getLexer().getLoc();
785 if (parseOptionalToken(AsmToken::EndOfStatement))
786 return Error(OpcodeLoc, "expected value");
787
788 if (Parser.parseExpression(Value))
789 return true;
790
791 if (parseEOL())
792 return true;
793
794 MCSymbol *Sym = getContext().getOrCreateSymbol(SE->getSymbol().getName());
795
796 TS.emitLiteral(Sym, Value, true, LiteralLoc);
797
798 return false;
799 }
800
parseDirective(AsmToken DirectiveID)801 ParseStatus XtensaAsmParser::parseDirective(AsmToken DirectiveID) {
802 StringRef IDVal = DirectiveID.getString();
803 SMLoc Loc = getLexer().getLoc();
804
805 if (IDVal == ".literal_position") {
806 XtensaTargetStreamer &TS = this->getTargetStreamer();
807 TS.emitLiteralPosition();
808 return parseEOL();
809 }
810
811 if (IDVal == ".literal") {
812 return parseLiteralDirective(Loc);
813 }
814
815 return ParseStatus::NoMatch;
816 }
817
818 // Force static initialization.
LLVMInitializeXtensaAsmParser()819 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() {
820 RegisterMCAsmParser<XtensaAsmParser> X(getTheXtensaTarget());
821 }
822