Path: blob/main/contrib/llvm-project/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp
35295 views
//===- XtensaAsmParser.cpp - Parse Xtensa assembly to MCInst instructions -===//1//2// The LLVM Compiler Infrastructure3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//910#include "MCTargetDesc/XtensaMCExpr.h"11#include "MCTargetDesc/XtensaMCTargetDesc.h"12#include "MCTargetDesc/XtensaTargetStreamer.h"13#include "TargetInfo/XtensaTargetInfo.h"14#include "llvm/ADT/STLExtras.h"15#include "llvm/ADT/StringSwitch.h"16#include "llvm/MC/MCContext.h"17#include "llvm/MC/MCExpr.h"18#include "llvm/MC/MCInst.h"19#include "llvm/MC/MCInstrInfo.h"20#include "llvm/MC/MCParser/MCAsmLexer.h"21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"22#include "llvm/MC/MCParser/MCTargetAsmParser.h"23#include "llvm/MC/MCRegisterInfo.h"24#include "llvm/MC/MCStreamer.h"25#include "llvm/MC/MCSubtargetInfo.h"26#include "llvm/MC/MCSymbol.h"27#include "llvm/MC/TargetRegistry.h"28#include "llvm/Support/Casting.h"2930using namespace llvm;3132#define DEBUG_TYPE "xtensa-asm-parser"3334struct XtensaOperand;3536class XtensaAsmParser : public MCTargetAsmParser {3738SMLoc getLoc() const { return getParser().getTok().getLoc(); }3940XtensaTargetStreamer &getTargetStreamer() {41MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();42return static_cast<XtensaTargetStreamer &>(TS);43}4445ParseStatus parseDirective(AsmToken DirectiveID) override;46bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;47bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,48SMLoc NameLoc, OperandVector &Operands) override;49bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,50OperandVector &Operands, MCStreamer &Out,51uint64_t &ErrorInfo,52bool MatchingInlineAsm) override;53unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,54unsigned Kind) override;5556bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,57const MCSubtargetInfo *STI);5859// Auto-generated instruction matching functions60#define GET_ASSEMBLER_HEADER61#include "XtensaGenAsmMatcher.inc"6263ParseStatus parseImmediate(OperandVector &Operands);64ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false,65bool SR = false);66ParseStatus parseOperandWithModifier(OperandVector &Operands);67bool parseOperand(OperandVector &Operands, StringRef Mnemonic,68bool SR = false);69bool ParseInstructionWithSR(ParseInstructionInfo &Info, StringRef Name,70SMLoc NameLoc, OperandVector &Operands);71ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,72SMLoc &EndLoc) override {73return ParseStatus::NoMatch;74}75ParseStatus parsePCRelTarget(OperandVector &Operands);76bool parseLiteralDirective(SMLoc L);7778public:79enum XtensaMatchResultTy {80Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,81#define GET_OPERAND_DIAGNOSTIC_TYPES82#include "XtensaGenAsmMatcher.inc"83#undef GET_OPERAND_DIAGNOSTIC_TYPES84};8586XtensaAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,87const MCInstrInfo &MII, const MCTargetOptions &Options)88: MCTargetAsmParser(Options, STI, MII) {89setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));90}91};9293// Return true if Expr is in the range [MinValue, MaxValue].94static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) {95if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {96int64_t Value = CE->getValue();97return Value >= MinValue && Value <= MaxValue;98}99return false;100}101102struct XtensaOperand : public MCParsedAsmOperand {103104enum KindTy {105Token,106Register,107Immediate,108} Kind;109110struct RegOp {111unsigned RegNum;112};113114struct ImmOp {115const MCExpr *Val;116};117118SMLoc StartLoc, EndLoc;119union {120StringRef Tok;121RegOp Reg;122ImmOp Imm;123};124125XtensaOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}126127public:128XtensaOperand(const XtensaOperand &o) : MCParsedAsmOperand() {129Kind = o.Kind;130StartLoc = o.StartLoc;131EndLoc = o.EndLoc;132switch (Kind) {133case Register:134Reg = o.Reg;135break;136case Immediate:137Imm = o.Imm;138break;139case Token:140Tok = o.Tok;141break;142}143}144145bool isToken() const override { return Kind == Token; }146bool isReg() const override { return Kind == Register; }147bool isImm() const override { return Kind == Immediate; }148bool isMem() const override { return false; }149150bool isImm(int64_t MinValue, int64_t MaxValue) const {151return Kind == Immediate && inRange(getImm(), MinValue, MaxValue);152}153154bool isImm8() const { return isImm(-128, 127); }155156bool isImm8_sh8() const {157return isImm(-32768, 32512) &&158((cast<MCConstantExpr>(getImm())->getValue() & 0xFF) == 0);159}160161bool isImm12() const { return isImm(-2048, 2047); }162163// Convert MOVI to literal load, when immediate is not in range (-2048, 2047)164bool isImm12m() const { return Kind == Immediate; }165166bool isOffset4m32() const {167return isImm(0, 60) &&168((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);169}170171bool isOffset8m8() const { return isImm(0, 255); }172173bool isOffset8m16() const {174return isImm(0, 510) &&175((cast<MCConstantExpr>(getImm())->getValue() & 0x1) == 0);176}177178bool isOffset8m32() const {179return isImm(0, 1020) &&180((cast<MCConstantExpr>(getImm())->getValue() & 0x3) == 0);181}182183bool isUimm4() const { return isImm(0, 15); }184185bool isUimm5() const { return isImm(0, 31); }186187bool isImm8n_7() const { return isImm(-8, 7); }188189bool isShimm1_31() const { return isImm(1, 31); }190191bool isImm16_31() const { return isImm(16, 31); }192193bool isImm1_16() const { return isImm(1, 16); }194195bool isB4const() const {196if (Kind != Immediate)197return false;198if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {199int64_t Value = CE->getValue();200switch (Value) {201case -1:202case 1:203case 2:204case 3:205case 4:206case 5:207case 6:208case 7:209case 8:210case 10:211case 12:212case 16:213case 32:214case 64:215case 128:216case 256:217return true;218default:219return false;220}221}222return false;223}224225bool isB4constu() const {226if (Kind != Immediate)227return false;228if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {229int64_t Value = CE->getValue();230switch (Value) {231case 32768:232case 65536:233case 2:234case 3:235case 4:236case 5:237case 6:238case 7:239case 8:240case 10:241case 12:242case 16:243case 32:244case 64:245case 128:246case 256:247return true;248default:249return false;250}251}252return false;253}254255/// getStartLoc - Gets location of the first token of this operand256SMLoc getStartLoc() const override { return StartLoc; }257/// getEndLoc - Gets location of the last token of this operand258SMLoc getEndLoc() const override { return EndLoc; }259260MCRegister getReg() const override {261assert(Kind == Register && "Invalid type access!");262return Reg.RegNum;263}264265const MCExpr *getImm() const {266assert(Kind == Immediate && "Invalid type access!");267return Imm.Val;268}269270StringRef getToken() const {271assert(Kind == Token && "Invalid type access!");272return Tok;273}274275void print(raw_ostream &OS) const override {276switch (Kind) {277case Immediate:278OS << *getImm();279break;280case Register:281OS << "<register x";282OS << getReg() << ">";283break;284case Token:285OS << "'" << getToken() << "'";286break;287}288}289290static std::unique_ptr<XtensaOperand> createToken(StringRef Str, SMLoc S) {291auto Op = std::make_unique<XtensaOperand>(Token);292Op->Tok = Str;293Op->StartLoc = S;294Op->EndLoc = S;295return Op;296}297298static std::unique_ptr<XtensaOperand> createReg(unsigned RegNo, SMLoc S,299SMLoc E) {300auto Op = std::make_unique<XtensaOperand>(Register);301Op->Reg.RegNum = RegNo;302Op->StartLoc = S;303Op->EndLoc = E;304return Op;305}306307static std::unique_ptr<XtensaOperand> createImm(const MCExpr *Val, SMLoc S,308SMLoc E) {309auto Op = std::make_unique<XtensaOperand>(Immediate);310Op->Imm.Val = Val;311Op->StartLoc = S;312Op->EndLoc = E;313return Op;314}315316void addExpr(MCInst &Inst, const MCExpr *Expr) const {317assert(Expr && "Expr shouldn't be null!");318int64_t Imm = 0;319bool IsConstant = false;320321if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) {322IsConstant = true;323Imm = CE->getValue();324}325326if (IsConstant)327Inst.addOperand(MCOperand::createImm(Imm));328else329Inst.addOperand(MCOperand::createExpr(Expr));330}331332// Used by the TableGen Code333void addRegOperands(MCInst &Inst, unsigned N) const {334assert(N == 1 && "Invalid number of operands!");335Inst.addOperand(MCOperand::createReg(getReg()));336}337338void addImmOperands(MCInst &Inst, unsigned N) const {339assert(N == 1 && "Invalid number of operands!");340addExpr(Inst, getImm());341}342};343344#define GET_REGISTER_MATCHER345#define GET_MATCHER_IMPLEMENTATION346#include "XtensaGenAsmMatcher.inc"347348unsigned XtensaAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,349unsigned Kind) {350return Match_InvalidOperand;351}352353static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,354uint64_t ErrorInfo) {355if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {356SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();357if (ErrorLoc == SMLoc())358return Loc;359return ErrorLoc;360}361return Loc;362}363364bool XtensaAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,365MCStreamer &Out,366const MCSubtargetInfo *STI) {367Inst.setLoc(IDLoc);368const unsigned Opcode = Inst.getOpcode();369switch (Opcode) {370case Xtensa::L32R: {371const MCSymbolRefExpr *OpExpr =372static_cast<const MCSymbolRefExpr *>(Inst.getOperand(1).getExpr());373XtensaMCExpr::VariantKind Kind = XtensaMCExpr::VK_Xtensa_None;374const MCExpr *NewOpExpr = XtensaMCExpr::create(OpExpr, Kind, getContext());375Inst.getOperand(1).setExpr(NewOpExpr);376break;377}378case Xtensa::MOVI: {379XtensaTargetStreamer &TS = this->getTargetStreamer();380381// Expand MOVI operand382if (!Inst.getOperand(1).isExpr()) {383uint64_t ImmOp64 = Inst.getOperand(1).getImm();384int32_t Imm = ImmOp64;385if (!isInt<12>(Imm)) {386XtensaTargetStreamer &TS = this->getTargetStreamer();387MCInst TmpInst;388TmpInst.setLoc(IDLoc);389TmpInst.setOpcode(Xtensa::L32R);390const MCExpr *Value = MCConstantExpr::create(ImmOp64, getContext());391MCSymbol *Sym = getContext().createTempSymbol();392const MCExpr *Expr = MCSymbolRefExpr::create(393Sym, MCSymbolRefExpr::VK_None, getContext());394const MCExpr *OpExpr = XtensaMCExpr::create(395Expr, XtensaMCExpr::VK_Xtensa_None, getContext());396TmpInst.addOperand(Inst.getOperand(0));397MCOperand Op1 = MCOperand::createExpr(OpExpr);398TmpInst.addOperand(Op1);399TS.emitLiteral(Sym, Value, true, IDLoc);400Inst = TmpInst;401}402} else {403MCInst TmpInst;404TmpInst.setLoc(IDLoc);405TmpInst.setOpcode(Xtensa::L32R);406const MCExpr *Value = Inst.getOperand(1).getExpr();407MCSymbol *Sym = getContext().createTempSymbol();408const MCExpr *Expr =409MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());410const MCExpr *OpExpr = XtensaMCExpr::create(411Expr, XtensaMCExpr::VK_Xtensa_None, getContext());412TmpInst.addOperand(Inst.getOperand(0));413MCOperand Op1 = MCOperand::createExpr(OpExpr);414TmpInst.addOperand(Op1);415Inst = TmpInst;416TS.emitLiteral(Sym, Value, true, IDLoc);417}418break;419}420default:421break;422}423424return true;425}426427bool XtensaAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,428OperandVector &Operands,429MCStreamer &Out,430uint64_t &ErrorInfo,431bool MatchingInlineAsm) {432MCInst Inst;433auto Result =434MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);435436switch (Result) {437default:438break;439case Match_Success:440processInstruction(Inst, IDLoc, Out, STI);441Inst.setLoc(IDLoc);442Out.emitInstruction(Inst, getSTI());443return false;444case Match_MissingFeature:445return Error(IDLoc, "instruction use requires an option to be enabled");446case Match_MnemonicFail:447return Error(IDLoc, "unrecognized instruction mnemonic");448case Match_InvalidOperand: {449SMLoc ErrorLoc = IDLoc;450if (ErrorInfo != ~0U) {451if (ErrorInfo >= Operands.size())452return Error(ErrorLoc, "too few operands for instruction");453454ErrorLoc = ((XtensaOperand &)*Operands[ErrorInfo]).getStartLoc();455if (ErrorLoc == SMLoc())456ErrorLoc = IDLoc;457}458return Error(ErrorLoc, "invalid operand for instruction");459}460case Match_InvalidImm8:461return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),462"expected immediate in range [-128, 127]");463case Match_InvalidImm8_sh8:464return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),465"expected immediate in range [-32768, 32512], first 8 bits "466"should be zero");467case Match_InvalidB4const:468return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),469"expected b4const immediate");470case Match_InvalidB4constu:471return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),472"expected b4constu immediate");473case Match_InvalidImm12:474return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),475"expected immediate in range [-2048, 2047]");476case Match_InvalidImm12m:477return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),478"expected immediate in range [-2048, 2047]");479case Match_InvalidImm1_16:480return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),481"expected immediate in range [1, 16]");482case Match_InvalidShimm1_31:483return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),484"expected immediate in range [1, 31]");485case Match_InvalidUimm4:486return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),487"expected immediate in range [0, 15]");488case Match_InvalidUimm5:489return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),490"expected immediate in range [0, 31]");491case Match_InvalidOffset8m8:492return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),493"expected immediate in range [0, 255]");494case Match_InvalidOffset8m16:495return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),496"expected immediate in range [0, 510], first bit "497"should be zero");498case Match_InvalidOffset8m32:499return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),500"expected immediate in range [0, 1020], first 2 bits "501"should be zero");502case Match_InvalidOffset4m32:503return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),504"expected immediate in range [0, 60], first 2 bits "505"should be zero");506}507508report_fatal_error("Unknown match type detected!");509}510511ParseStatus XtensaAsmParser::parsePCRelTarget(OperandVector &Operands) {512MCAsmParser &Parser = getParser();513LLVM_DEBUG(dbgs() << "parsePCRelTarget\n");514515SMLoc S = getLexer().getLoc();516517// Expressions are acceptable518const MCExpr *Expr = nullptr;519if (Parser.parseExpression(Expr)) {520// We have no way of knowing if a symbol was consumed so we must ParseFail521return ParseStatus::Failure;522}523524// Currently not support constants525if (Expr->getKind() == MCExpr::ExprKind::Constant)526return Error(getLoc(), "unknown operand");527528Operands.push_back(XtensaOperand::createImm(Expr, S, getLexer().getLoc()));529return ParseStatus::Success;530}531532bool XtensaAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,533SMLoc &EndLoc) {534const AsmToken &Tok = getParser().getTok();535StartLoc = Tok.getLoc();536EndLoc = Tok.getEndLoc();537Reg = Xtensa::NoRegister;538StringRef Name = getLexer().getTok().getIdentifier();539540if (!MatchRegisterName(Name) && !MatchRegisterAltName(Name)) {541getParser().Lex(); // Eat identifier token.542return false;543}544545return Error(StartLoc, "invalid register name");546}547548ParseStatus XtensaAsmParser::parseRegister(OperandVector &Operands,549bool AllowParens, bool SR) {550SMLoc FirstS = getLoc();551bool HadParens = false;552AsmToken Buf[2];553StringRef RegName;554555// If this a parenthesised register name is allowed, parse it atomically556if (AllowParens && getLexer().is(AsmToken::LParen)) {557size_t ReadCount = getLexer().peekTokens(Buf);558if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {559if ((Buf[0].getKind() == AsmToken::Integer) && (!SR))560return ParseStatus::NoMatch;561HadParens = true;562getParser().Lex(); // Eat '('563}564}565566unsigned RegNo = 0;567568switch (getLexer().getKind()) {569default:570return ParseStatus::NoMatch;571case AsmToken::Integer:572if (!SR)573return ParseStatus::NoMatch;574RegName = getLexer().getTok().getString();575RegNo = MatchRegisterName(RegName);576if (RegNo == 0)577RegNo = MatchRegisterAltName(RegName);578break;579case AsmToken::Identifier:580RegName = getLexer().getTok().getIdentifier();581RegNo = MatchRegisterName(RegName);582if (RegNo == 0)583RegNo = MatchRegisterAltName(RegName);584break;585}586587if (RegNo == 0) {588if (HadParens)589getLexer().UnLex(Buf[0]);590return ParseStatus::NoMatch;591}592if (HadParens)593Operands.push_back(XtensaOperand::createToken("(", FirstS));594SMLoc S = getLoc();595SMLoc E = getParser().getTok().getEndLoc();596getLexer().Lex();597Operands.push_back(XtensaOperand::createReg(RegNo, S, E));598599if (HadParens) {600getParser().Lex(); // Eat ')'601Operands.push_back(XtensaOperand::createToken(")", getLoc()));602}603604return ParseStatus::Success;605}606607ParseStatus XtensaAsmParser::parseImmediate(OperandVector &Operands) {608SMLoc S = getLoc();609SMLoc E;610const MCExpr *Res;611612switch (getLexer().getKind()) {613default:614return ParseStatus::NoMatch;615case AsmToken::LParen:616case AsmToken::Minus:617case AsmToken::Plus:618case AsmToken::Tilde:619case AsmToken::Integer:620case AsmToken::String:621if (getParser().parseExpression(Res))622return ParseStatus::Failure;623break;624case AsmToken::Identifier: {625StringRef Identifier;626if (getParser().parseIdentifier(Identifier))627return ParseStatus::Failure;628629MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);630Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());631break;632}633case AsmToken::Percent:634return parseOperandWithModifier(Operands);635}636637E = SMLoc::getFromPointer(S.getPointer() - 1);638Operands.push_back(XtensaOperand::createImm(Res, S, E));639return ParseStatus::Success;640}641642ParseStatus XtensaAsmParser::parseOperandWithModifier(OperandVector &Operands) {643return ParseStatus::Failure;644}645646/// Looks at a token type and creates the relevant operand647/// from this information, adding to Operands.648/// If operand was parsed, returns false, else true.649bool XtensaAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,650bool SR) {651// Check if the current operand has a custom associated parser, if so, try to652// custom parse the operand, or fallback to the general approach.653ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);654if (Res.isSuccess())655return false;656657// If there wasn't a custom match, try the generic matcher below. Otherwise,658// there was a match, but an error occurred, in which case, just return that659// the operand parsing failed.660if (Res.isFailure())661return true;662663// Attempt to parse token as register664if (parseRegister(Operands, true, SR).isSuccess())665return false;666667// Attempt to parse token as an immediate668if (parseImmediate(Operands).isSuccess())669return false;670671// Finally we have exhausted all options and must declare defeat.672return Error(getLoc(), "unknown operand");673}674675bool XtensaAsmParser::ParseInstructionWithSR(ParseInstructionInfo &Info,676StringRef Name, SMLoc NameLoc,677OperandVector &Operands) {678if ((Name.starts_with("wsr.") || Name.starts_with("rsr.") ||679Name.starts_with("xsr.")) &&680(Name.size() > 4)) {681// Parse case when instruction name is concatenated with SR register682// name, like "wsr.sar a1"683684// First operand is token for instruction685Operands.push_back(XtensaOperand::createToken(Name.take_front(3), NameLoc));686687StringRef RegName = Name.drop_front(4);688unsigned RegNo = MatchRegisterName(RegName);689690if (RegNo == 0)691RegNo = MatchRegisterAltName(RegName);692693if (RegNo == 0)694return Error(NameLoc, "invalid register name");695696// Parse operand697if (parseOperand(Operands, Name))698return true;699700SMLoc S = getLoc();701SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);702Operands.push_back(XtensaOperand::createReg(RegNo, S, E));703} else {704// First operand is token for instruction705Operands.push_back(XtensaOperand::createToken(Name, NameLoc));706707// Parse first operand708if (parseOperand(Operands, Name))709return true;710711if (!parseOptionalToken(AsmToken::Comma)) {712SMLoc Loc = getLexer().getLoc();713getParser().eatToEndOfStatement();714return Error(Loc, "unexpected token");715}716717// Parse second operand718if (parseOperand(Operands, Name, true))719return true;720}721722if (getLexer().isNot(AsmToken::EndOfStatement)) {723SMLoc Loc = getLexer().getLoc();724getParser().eatToEndOfStatement();725return Error(Loc, "unexpected token");726}727728getParser().Lex(); // Consume the EndOfStatement.729return false;730}731732bool XtensaAsmParser::ParseInstruction(ParseInstructionInfo &Info,733StringRef Name, SMLoc NameLoc,734OperandVector &Operands) {735if (Name.starts_with("wsr") || Name.starts_with("rsr") ||736Name.starts_with("xsr")) {737return ParseInstructionWithSR(Info, Name, NameLoc, Operands);738}739740// First operand is token for instruction741Operands.push_back(XtensaOperand::createToken(Name, NameLoc));742743// If there are no more operands, then finish744if (getLexer().is(AsmToken::EndOfStatement))745return false;746747// Parse first operand748if (parseOperand(Operands, Name))749return true;750751// Parse until end of statement, consuming commas between operands752while (parseOptionalToken(AsmToken::Comma))753if (parseOperand(Operands, Name))754return true;755756if (getLexer().isNot(AsmToken::EndOfStatement)) {757SMLoc Loc = getLexer().getLoc();758getParser().eatToEndOfStatement();759return Error(Loc, "unexpected token");760}761762getParser().Lex(); // Consume the EndOfStatement.763return false;764}765766bool XtensaAsmParser::parseLiteralDirective(SMLoc L) {767MCAsmParser &Parser = getParser();768const MCExpr *Value;769SMLoc LiteralLoc = getLexer().getLoc();770XtensaTargetStreamer &TS = this->getTargetStreamer();771772if (Parser.parseExpression(Value))773return true;774775const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Value);776777if (!SE)778return Error(LiteralLoc, "literal label must be a symbol");779780if (Parser.parseComma())781return true;782783SMLoc OpcodeLoc = getLexer().getLoc();784if (parseOptionalToken(AsmToken::EndOfStatement))785return Error(OpcodeLoc, "expected value");786787if (Parser.parseExpression(Value))788return true;789790if (parseEOL())791return true;792793MCSymbol *Sym = getContext().getOrCreateSymbol(SE->getSymbol().getName());794795TS.emitLiteral(Sym, Value, true, LiteralLoc);796797return false;798}799800ParseStatus XtensaAsmParser::parseDirective(AsmToken DirectiveID) {801StringRef IDVal = DirectiveID.getString();802SMLoc Loc = getLexer().getLoc();803804if (IDVal == ".literal_position") {805XtensaTargetStreamer &TS = this->getTargetStreamer();806TS.emitLiteralPosition();807return parseEOL();808}809810if (IDVal == ".literal") {811return parseLiteralDirective(Loc);812}813814return ParseStatus::NoMatch;815}816817// Force static initialization.818extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmParser() {819RegisterMCAsmParser<XtensaAsmParser> X(getTheXtensaTarget());820}821822823