brintos

brintos / llvm-project-archived public Read only

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