//===-- LanaiAsmParser.cpp - Parse Lanai assembly to MCInst instructions --===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "Lanai.h"
#include "LanaiAluCode.h"
#include "LanaiCondCode.h"
#include "MCTargetDesc/LanaiMCExpr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>

using namespace llvm;

// Auto-generated by TableGen
static unsigned MatchRegisterName(StringRef Name);

namespace {

struct LanaiOperand;

class LanaiAsmParser : public MCTargetAsmParser {
  // Parse operands
  std::unique_ptr<LanaiOperand> parseRegister();

  std::unique_ptr<LanaiOperand> parseImmediate();

  std::unique_ptr<LanaiOperand> parseIdentifier();

  unsigned parseAluOperator(bool PreOp, bool PostOp);

  // Split the mnemonic stripping conditional code and quantifiers
  StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,
                          OperandVector *Operands);

  bool parsePrePost(StringRef Type, int *OffsetValue);

  bool ParseDirective(AsmToken DirectiveID) override;

  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                        SMLoc NameLoc, OperandVector &Operands) override;

  bool ParseRegister(unsigned &RegNum, SMLoc &StartLoc, SMLoc &EndLoc) override;

  bool MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
                               OperandVector &Operands, MCStreamer &Out,
                               uint64_t &ErrorInfo,
                               bool MatchingInlineAsm) override;

// Auto-generated instruction matching functions
#define GET_ASSEMBLER_HEADER
#include "LanaiGenAsmMatcher.inc"

  OperandMatchResultTy parseOperand(OperandVector *Operands,
                                    StringRef Mnemonic);

  OperandMatchResultTy parseMemoryOperand(OperandVector &Operands);

public:
  LanaiAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
                 const MCInstrInfo &MII, const MCTargetOptions &Options)
      : MCTargetAsmParser(Options, STI, MII), Parser(Parser),
        Lexer(Parser.getLexer()), SubtargetInfo(STI) {
    setAvailableFeatures(
        ComputeAvailableFeatures(SubtargetInfo.getFeatureBits()));
  }

private:
  MCAsmParser &Parser;
  MCAsmLexer &Lexer;

  const MCSubtargetInfo &SubtargetInfo;
};

// LanaiOperand - Instances of this class represented a parsed machine
// instruction
struct LanaiOperand : public MCParsedAsmOperand {
  enum KindTy {
    TOKEN,
    REGISTER,
    IMMEDIATE,
    MEMORY_IMM,
    MEMORY_REG_IMM,
    MEMORY_REG_REG,
  } Kind;

  SMLoc StartLoc, EndLoc;

  struct Token {
    const char *Data;
    unsigned Length;
  };

  struct RegOp {
    unsigned RegNum;
  };

  struct ImmOp {
    const MCExpr *Value;
  };

  struct MemOp {
    unsigned BaseReg;
    unsigned OffsetReg;
    unsigned AluOp;
    const MCExpr *Offset;
  };

  union {
    struct Token Tok;
    struct RegOp Reg;
    struct ImmOp Imm;
    struct MemOp Mem;
  };

  explicit LanaiOperand(KindTy Kind) : MCParsedAsmOperand(), Kind(Kind) {}

public:
  // The functions below are used by the autogenerated ASM matcher and hence to
  // be of the form expected.

  // getStartLoc - Gets location of the first token of this operand
  SMLoc getStartLoc() const override { return StartLoc; }

  // getEndLoc - Gets location of the last token of this operand
  SMLoc getEndLoc() const override { return EndLoc; }

  unsigned getReg() const override {
    assert(isReg() && "Invalid type access!");
    return Reg.RegNum;
  }

  const MCExpr *getImm() const {
    assert(isImm() && "Invalid type access!");
    return Imm.Value;
  }

  StringRef getToken() const {
    assert(isToken() && "Invalid type access!");
    return StringRef(Tok.Data, Tok.Length);
  }

  unsigned getMemBaseReg() const {
    assert(isMem() && "Invalid type access!");
    return Mem.BaseReg;
  }

  unsigned getMemOffsetReg() const {
    assert(isMem() && "Invalid type access!");
    return Mem.OffsetReg;
  }

  const MCExpr *getMemOffset() const {
    assert(isMem() && "Invalid type access!");
    return Mem.Offset;
  }

  unsigned getMemOp() const {
    assert(isMem() && "Invalid type access!");
    return Mem.AluOp;
  }

  // Functions for testing operand type
  bool isReg() const override { return Kind == REGISTER; }

  bool isImm() const override { return Kind == IMMEDIATE; }

  bool isMem() const override {
    return isMemImm() || isMemRegImm() || isMemRegReg();
  }

  bool isMemImm() const { return Kind == MEMORY_IMM; }

  bool isMemRegImm() const { return Kind == MEMORY_REG_IMM; }

  bool isMemRegReg() const { return Kind == MEMORY_REG_REG; }

  bool isMemSpls() const { return isMemRegImm() || isMemRegReg(); }

  bool isToken() const override { return Kind == TOKEN; }

  bool isBrImm() {
    if (!isImm())
      return false;

    // Constant case
    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm.Value);
    if (!MCE)
      return true;
    int64_t Value = MCE->getValue();
    // Check if value fits in 25 bits with 2 least significant bits 0.
    return isShiftedUInt<23, 2>(static_cast<int32_t>(Value));
  }

  bool isBrTarget() { return isBrImm() || isToken(); }

  bool isCallTarget() { return isImm() || isToken(); }

  bool isHiImm16() {
    if (!isImm())
      return false;

    // Constant case
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
      int64_t Value = ConstExpr->getValue();
      return Value != 0 && isShiftedUInt<16, 16>(Value);
    }

    // Symbolic reference expression
    if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
      return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;

    // Binary expression
    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
      if (const LanaiMCExpr *SymbolRefExpr =
              dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
        return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI;

    return false;
  }

  bool isHiImm16And() {
    if (!isImm())
      return false;

    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
    if (ConstExpr) {
      int64_t Value = ConstExpr->getValue();
      // Check if in the form 0xXYZWffff
      return (Value != 0) && ((Value & ~0xffff0000) == 0xffff);
    }
    return false;
  }

  bool isLoImm16() {
    if (!isImm())
      return false;

    // Constant case
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
      int64_t Value = ConstExpr->getValue();
      // Check if value fits in 16 bits
      return isUInt<16>(static_cast<int32_t>(Value));
    }

    // Symbolic reference expression
    if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
      return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;

    // Binary expression
    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
      if (const LanaiMCExpr *SymbolRefExpr =
              dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
        return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;

    return false;
  }

  bool isLoImm16Signed() {
    if (!isImm())
      return false;

    // Constant case
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
      int64_t Value = ConstExpr->getValue();
      // Check if value fits in 16 bits or value of the form 0xffffxyzw
      return isInt<16>(static_cast<int32_t>(Value));
    }

    // Symbolic reference expression
    if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
      return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;

    // Binary expression
    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))
      if (const LanaiMCExpr *SymbolRefExpr =
              dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
        return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO;

    return false;
  }

  bool isLoImm16And() {
    if (!isImm())
      return false;

    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
    if (ConstExpr) {
      int64_t Value = ConstExpr->getValue();
      // Check if in the form 0xffffXYZW
      return ((Value & ~0xffff) == 0xffff0000);
    }
    return false;
  }

  bool isImmShift() {
    if (!isImm())
      return false;

    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
    if (!ConstExpr)
      return false;
    int64_t Value = ConstExpr->getValue();
    return (Value >= -31) && (Value <= 31);
  }

  bool isLoImm21() {
    if (!isImm())
      return false;

    // Constant case
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {
      int64_t Value = ConstExpr->getValue();
      return isUInt<21>(Value);
    }

    // Symbolic reference expression
    if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Imm.Value))
      return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
    if (const MCSymbolRefExpr *SymbolRefExpr =
            dyn_cast<MCSymbolRefExpr>(Imm.Value)) {
      return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
    }

    // Binary expression
    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) {
      if (const LanaiMCExpr *SymbolRefExpr =
              dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS()))
        return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
      if (const MCSymbolRefExpr *SymbolRefExpr =
              dyn_cast<MCSymbolRefExpr>(BinaryExpr->getLHS()))
        return SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None;
    }

    return false;
  }

  bool isImm10() {
    if (!isImm())
      return false;

    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
    if (!ConstExpr)
      return false;
    int64_t Value = ConstExpr->getValue();
    return isInt<10>(Value);
  }

  bool isCondCode() {
    if (!isImm())
      return false;

    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);
    if (!ConstExpr)
      return false;
    uint64_t Value = ConstExpr->getValue();
    // The condition codes are between 0 (ICC_T) and 15 (ICC_LE). If the
    // unsigned value of the immediate is less than LPCC::UNKNOWN (16) then
    // value corresponds to a valid condition code.
    return Value < LPCC::UNKNOWN;
  }

  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
    // Add as immediates where possible. Null MCExpr = 0
    if (Expr == nullptr)
      Inst.addOperand(MCOperand::createImm(0));
    else if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Expr))
      Inst.addOperand(
          MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
    else
      Inst.addOperand(MCOperand::createExpr(Expr));
  }

  void addRegOperands(MCInst &Inst, unsigned N) const {
    assert(N == 1 && "Invalid number of operands!");
    Inst.addOperand(MCOperand::createReg(getReg()));
  }

  void addImmOperands(MCInst &Inst, unsigned N) const {
    assert(N == 1 && "Invalid number of operands!");
    addExpr(Inst, getImm());
  }

  void addBrTargetOperands(MCInst &Inst, unsigned N) const {
    assert(N == 1 && "Invalid number of operands!");
    addExpr(Inst, getImm());
  }

  void addCallTargetOperands(MCInst &Inst, unsigned N) const {
    assert(N == 1 && "Invalid number of operands!");
    addExpr(Inst, getImm());
  }

  void addCondCodeOperands(MCInst &Inst, unsigned N) const {
    assert(N == 1 && "Invalid number of operands!");
    addExpr(Inst, getImm());
  }

  void addMemImmOperands(MCInst &Inst, unsigned N) const {
    assert(N == 1 && "Invalid number of operands!");
    const MCExpr *Expr = getMemOffset();
    addExpr(Inst, Expr);
  }

  void addMemRegImmOperands(MCInst &Inst, unsigned N) const {
    assert(N == 3 && "Invalid number of operands!");
    Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
    const MCExpr *Expr = getMemOffset();
    addExpr(Inst, Expr);
    Inst.addOperand(MCOperand::createImm(getMemOp()));
  }

  void addMemRegRegOperands(MCInst &Inst, unsigned N) const {
    assert(N == 3 && "Invalid number of operands!");
    Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
    assert(getMemOffsetReg() != 0 && "Invalid offset");
    Inst.addOperand(MCOperand::createReg(getMemOffsetReg()));
    Inst.addOperand(MCOperand::createImm(getMemOp()));
  }

  void addMemSplsOperands(MCInst &Inst, unsigned N) const {
    if (isMemRegImm())
      addMemRegImmOperands(Inst, N);
    if (isMemRegReg())
      addMemRegRegOperands(Inst, N);
  }

  void addImmShiftOperands(MCInst &Inst, unsigned N) const {
    assert(N == 1 && "Invalid number of operands!");
    addExpr(Inst, getImm());
  }

  void addImm10Operands(MCInst &Inst, unsigned N) const {
    assert(N == 1 && "Invalid number of operands!");
    addExpr(Inst, getImm());
  }

  void addLoImm16Operands(MCInst &Inst, unsigned N) const {
    assert(N == 1 && "Invalid number of operands!");
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
      Inst.addOperand(
          MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));
    else if (isa<LanaiMCExpr>(getImm())) {
#ifndef NDEBUG
      const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
      assert(SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_LO);
#endif
      Inst.addOperand(MCOperand::createExpr(getImm()));
    } else if (isa<MCBinaryExpr>(getImm())) {
#ifndef NDEBUG
      const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
      assert(isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
             cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
                 LanaiMCExpr::VK_Lanai_ABS_LO);
#endif
      Inst.addOperand(MCOperand::createExpr(getImm()));
    } else
      assert(false && "Operand type not supported.");
  }

  void addLoImm16AndOperands(MCInst &Inst, unsigned N) const {
    assert(N == 1 && "Invalid number of operands!");
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff));
    else
      assert(false && "Operand type not supported.");
  }

  void addHiImm16Operands(MCInst &Inst, unsigned N) const {
    assert(N == 1 && "Invalid number of operands!");
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
    else if (isa<LanaiMCExpr>(getImm())) {
#ifndef NDEBUG
      const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
      assert(SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_ABS_HI);
#endif
      Inst.addOperand(MCOperand::createExpr(getImm()));
    } else if (isa<MCBinaryExpr>(getImm())) {
#ifndef NDEBUG
      const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
      assert(isa<LanaiMCExpr>(BinaryExpr->getLHS()) &&
             cast<LanaiMCExpr>(BinaryExpr->getLHS())->getKind() ==
                 LanaiMCExpr::VK_Lanai_ABS_HI);
#endif
      Inst.addOperand(MCOperand::createExpr(getImm()));
    } else
      assert(false && "Operand type not supported.");
  }

  void addHiImm16AndOperands(MCInst &Inst, unsigned N) const {
    assert(N == 1 && "Invalid number of operands!");
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));
    else
      assert(false && "Operand type not supported.");
  }

  void addLoImm21Operands(MCInst &Inst, unsigned N) const {
    assert(N == 1 && "Invalid number of operands!");
    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))
      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff));
    else if (isa<LanaiMCExpr>(getImm())) {
#ifndef NDEBUG
      const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(getImm());
      assert(SymbolRefExpr &&
             SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
#endif
      Inst.addOperand(MCOperand::createExpr(getImm()));
    } else if (isa<MCSymbolRefExpr>(getImm())) {
#ifndef NDEBUG
      const MCSymbolRefExpr *SymbolRefExpr =
          dyn_cast<MCSymbolRefExpr>(getImm());
      assert(SymbolRefExpr &&
             SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None);
#endif
      Inst.addOperand(MCOperand::createExpr(getImm()));
    } else if (isa<MCBinaryExpr>(getImm())) {
#ifndef NDEBUG
      const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());
      const LanaiMCExpr *SymbolRefExpr =
          dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
      assert(SymbolRefExpr &&
             SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
#endif
      Inst.addOperand(MCOperand::createExpr(getImm()));
    } else
      assert(false && "Operand type not supported.");
  }

  void print(raw_ostream &OS) const override {
    switch (Kind) {
    case IMMEDIATE:
      OS << "Imm: " << getImm() << "\n";
      break;
    case TOKEN:
      OS << "Token: " << getToken() << "\n";
      break;
    case REGISTER:
      OS << "Reg: %r" << getReg() << "\n";
      break;
    case MEMORY_IMM:
      OS << "MemImm: " << *getMemOffset() << "\n";
      break;
    case MEMORY_REG_IMM:
      OS << "MemRegImm: " << getMemBaseReg() << "+" << *getMemOffset() << "\n";
      break;
    case MEMORY_REG_REG:
      assert(getMemOffset() == nullptr);
      OS << "MemRegReg: " << getMemBaseReg() << "+"
         << "%r" << getMemOffsetReg() << "\n";
      break;
    }
  }

  static std::unique_ptr<LanaiOperand> CreateToken(StringRef Str, SMLoc Start) {
    auto Op = make_unique<LanaiOperand>(TOKEN);
    Op->Tok.Data = Str.data();
    Op->Tok.Length = Str.size();
    Op->StartLoc = Start;
    Op->EndLoc = Start;
    return Op;
  }

  static std::unique_ptr<LanaiOperand> createReg(unsigned RegNum, SMLoc Start,
                                                 SMLoc End) {
    auto Op = make_unique<LanaiOperand>(REGISTER);
    Op->Reg.RegNum = RegNum;
    Op->StartLoc = Start;
    Op->EndLoc = End;
    return Op;
  }

  static std::unique_ptr<LanaiOperand> createImm(const MCExpr *Value,
                                                 SMLoc Start, SMLoc End) {
    auto Op = make_unique<LanaiOperand>(IMMEDIATE);
    Op->Imm.Value = Value;
    Op->StartLoc = Start;
    Op->EndLoc = End;
    return Op;
  }

  static std::unique_ptr<LanaiOperand>
  MorphToMemImm(std::unique_ptr<LanaiOperand> Op) {
    const MCExpr *Imm = Op->getImm();
    Op->Kind = MEMORY_IMM;
    Op->Mem.BaseReg = 0;
    Op->Mem.AluOp = LPAC::ADD;
    Op->Mem.OffsetReg = 0;
    Op->Mem.Offset = Imm;
    return Op;
  }

  static std::unique_ptr<LanaiOperand>
  MorphToMemRegReg(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
                   unsigned AluOp) {
    unsigned OffsetReg = Op->getReg();
    Op->Kind = MEMORY_REG_REG;
    Op->Mem.BaseReg = BaseReg;
    Op->Mem.AluOp = AluOp;
    Op->Mem.OffsetReg = OffsetReg;
    Op->Mem.Offset = nullptr;
    return Op;
  }

  static std::unique_ptr<LanaiOperand>
  MorphToMemRegImm(unsigned BaseReg, std::unique_ptr<LanaiOperand> Op,
                   unsigned AluOp) {
    const MCExpr *Imm = Op->getImm();
    Op->Kind = MEMORY_REG_IMM;
    Op->Mem.BaseReg = BaseReg;
    Op->Mem.AluOp = AluOp;
    Op->Mem.OffsetReg = 0;
    Op->Mem.Offset = Imm;
    return Op;
  }
};

} // end anonymous namespace

bool LanaiAsmParser::ParseDirective(AsmToken /*DirectiveId*/) { return true; }

bool LanaiAsmParser::MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
                                             OperandVector &Operands,
                                             MCStreamer &Out,
                                             uint64_t &ErrorInfo,
                                             bool MatchingInlineAsm) {
  MCInst Inst;
  SMLoc ErrorLoc;

  switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
  case Match_Success:
    Out.EmitInstruction(Inst, SubtargetInfo);
    Opcode = Inst.getOpcode();
    return false;
  case Match_MissingFeature:
    return Error(IdLoc, "Instruction use requires option to be enabled");
  case Match_MnemonicFail:
    return Error(IdLoc, "Unrecognized instruction mnemonic");
  case Match_InvalidOperand: {
    ErrorLoc = IdLoc;
    if (ErrorInfo != ~0U) {
      if (ErrorInfo >= Operands.size())
        return Error(IdLoc, "Too few operands for instruction");

      ErrorLoc = ((LanaiOperand &)*Operands[ErrorInfo]).getStartLoc();
      if (ErrorLoc == SMLoc())
        ErrorLoc = IdLoc;
    }
    return Error(ErrorLoc, "Invalid operand for instruction");
  }
  default:
    break;
  }

  llvm_unreachable("Unknown match type detected!");
}

// Both '%rN' and 'rN' are parsed as valid registers. This was done to remain
// backwards compatible with GCC and the different ways inline assembly is
// handled.
// TODO: see if there isn't a better way to do this.
std::unique_ptr<LanaiOperand> LanaiAsmParser::parseRegister() {
  SMLoc Start = Parser.getTok().getLoc();
  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);

  unsigned RegNum;
  // Eat the '%'.
  if (Lexer.getKind() == AsmToken::Percent)
    Parser.Lex();
  if (Lexer.getKind() == AsmToken::Identifier) {
    RegNum = MatchRegisterName(Lexer.getTok().getIdentifier());
    if (RegNum == 0)
      return nullptr;
    Parser.Lex(); // Eat identifier token
    return LanaiOperand::createReg(RegNum, Start, End);
  }
  return nullptr;
}

bool LanaiAsmParser::ParseRegister(unsigned &RegNum, SMLoc &StartLoc,
                                   SMLoc &EndLoc) {
  const AsmToken &Tok = getParser().getTok();
  StartLoc = Tok.getLoc();
  EndLoc = Tok.getEndLoc();
  std::unique_ptr<LanaiOperand> Op = parseRegister();
  if (Op != nullptr)
    RegNum = Op->getReg();
  return (Op == nullptr);
}

std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {
  SMLoc Start = Parser.getTok().getLoc();
  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
  const MCExpr *Res, *RHS = nullptr;
  LanaiMCExpr::VariantKind Kind = LanaiMCExpr::VK_Lanai_None;

  if (Lexer.getKind() != AsmToken::Identifier)
    return nullptr;

  StringRef Identifier;
  if (Parser.parseIdentifier(Identifier))
    return nullptr;

  // Check if identifier has a modifier
  if (Identifier.equals_lower("hi"))
    Kind = LanaiMCExpr::VK_Lanai_ABS_HI;
  else if (Identifier.equals_lower("lo"))
    Kind = LanaiMCExpr::VK_Lanai_ABS_LO;

  // If the identifier corresponds to a variant then extract the real
  // identifier.
  if (Kind != LanaiMCExpr::VK_Lanai_None) {
    if (Lexer.getKind() != AsmToken::LParen) {
      Error(Lexer.getLoc(), "Expected '('");
      return nullptr;
    }
    Lexer.Lex(); // lex '('

    // Parse identifier
    if (Parser.parseIdentifier(Identifier))
      return nullptr;
  }

  // If addition parse the RHS.
  if (Lexer.getKind() == AsmToken::Plus && Parser.parseExpression(RHS))
    return nullptr;

  // For variants parse the final ')'
  if (Kind != LanaiMCExpr::VK_Lanai_None) {
    if (Lexer.getKind() != AsmToken::RParen) {
      Error(Lexer.getLoc(), "Expected ')'");
      return nullptr;
    }
    Lexer.Lex(); // lex ')'
  }

  End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
  Res = LanaiMCExpr::create(Kind, Expr, getContext());

  // Nest if this was an addition
  if (RHS)
    Res = MCBinaryExpr::createAdd(Res, RHS, getContext());

  return LanaiOperand::createImm(Res, Start, End);
}

std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {
  SMLoc Start = Parser.getTok().getLoc();
  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);

  const MCExpr *ExprVal;
  switch (Lexer.getKind()) {
  case AsmToken::Identifier:
    return parseIdentifier();
  case AsmToken::Plus:
  case AsmToken::Minus:
  case AsmToken::Integer:
  case AsmToken::Dot:
    if (!Parser.parseExpression(ExprVal))
      return LanaiOperand::createImm(ExprVal, Start, End);
    LLVM_FALLTHROUGH;
  default:
    return nullptr;
  }
}

static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) {
  if (PreOp)
    return LPAC::makePreOp(AluCode);
  if (PostOp)
    return LPAC::makePostOp(AluCode);
  return AluCode;
}

unsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) {
  StringRef IdString;
  Parser.parseIdentifier(IdString);
  unsigned AluCode = LPAC::stringToLanaiAluCode(IdString);
  if (AluCode == LPAC::UNKNOWN) {
    Error(Parser.getTok().getLoc(), "Can't parse ALU operator");
    return 0;
  }
  return AluCode;
}

static int SizeForSuffix(StringRef T) {
  return StringSwitch<int>(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4);
}

bool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) {
  bool PreOrPost = false;
  if (Lexer.getKind() == Lexer.peekTok(true).getKind()) {
    PreOrPost = true;
    if (Lexer.is(AsmToken::Minus))
      *OffsetValue = -SizeForSuffix(Type);
    else if (Lexer.is(AsmToken::Plus))
      *OffsetValue = SizeForSuffix(Type);
    else
      return false;

    // Eat the '-' '-' or '+' '+'
    Parser.Lex();
    Parser.Lex();
  } else if (Lexer.is(AsmToken::Star)) {
    Parser.Lex(); // Eat the '*'
    PreOrPost = true;
  }

  return PreOrPost;
}

bool shouldBeSls(const LanaiOperand &Op) {
  // The instruction should be encoded as an SLS if the constant is word
  // aligned and will fit in 21 bits
  if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm())) {
    int64_t Value = ConstExpr->getValue();
    return (Value % 4 == 0) && (Value >= 0) && (Value <= 0x1fffff);
  }
  // The instruction should be encoded as an SLS if the operand is a symbolic
  // reference with no variant.
  if (const LanaiMCExpr *SymbolRefExpr = dyn_cast<LanaiMCExpr>(Op.getImm()))
    return SymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None;
  // The instruction should be encoded as an SLS if the operand is a binary
  // expression with the left-hand side being a symbolic reference with no
  // variant.
  if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Op.getImm())) {
    const LanaiMCExpr *LHSSymbolRefExpr =
        dyn_cast<LanaiMCExpr>(BinaryExpr->getLHS());
    return (LHSSymbolRefExpr &&
            LHSSymbolRefExpr->getKind() == LanaiMCExpr::VK_Lanai_None);
  }
  return false;
}

// Matches memory operand. Returns true if error encountered.
OperandMatchResultTy
LanaiAsmParser::parseMemoryOperand(OperandVector &Operands) {
  // Try to match a memory operand.
  // The memory operands are of the form:
  //  (1)  Register|Immediate|'' '[' '*'? Register '*'? ']' or
  //                            ^
  //  (2)  '[' '*'? Register '*'? AluOperator Register ']'
  //      ^
  //  (3)  '[' '--'|'++' Register '--'|'++' ']'
  //
  //  (4) '[' Immediate ']' (for SLS)

  // Store the type for use in parsing pre/post increment/decrement operators
  StringRef Type;
  if (Operands[0]->isToken())
    Type = static_cast<LanaiOperand *>(Operands[0].get())->getToken();

  // Use 0 if no offset given
  int OffsetValue = 0;
  unsigned BaseReg = 0;
  unsigned AluOp = LPAC::ADD;
  bool PostOp = false, PreOp = false;

  // Try to parse the offset
  std::unique_ptr<LanaiOperand> Op = parseRegister();
  if (!Op)
    Op = parseImmediate();

  // Only continue if next token is '['
  if (Lexer.isNot(AsmToken::LBrac)) {
    if (!Op)
      return MatchOperand_NoMatch;

    // The start of this custom parsing overlaps with register/immediate so
    // consider this as a successful match of an operand of that type as the
    // token stream can't be rewound to allow them to match separately.
    Operands.push_back(std::move(Op));
    return MatchOperand_Success;
  }

  Parser.Lex(); // Eat the '['.
  std::unique_ptr<LanaiOperand> Offset = nullptr;
  if (Op)
    Offset.swap(Op);

  // Determine if a pre operation
  PreOp = parsePrePost(Type, &OffsetValue);

  Op = parseRegister();
  if (!Op) {
    if (!Offset) {
      if ((Op = parseImmediate()) && Lexer.is(AsmToken::RBrac)) {
        Parser.Lex(); // Eat the ']'

        // Memory address operations aligned to word boundary are encoded as
        // SLS, the rest as RM.
        if (shouldBeSls(*Op)) {
          Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op)));
        } else {
          if (!Op->isLoImm16Signed()) {
            Error(Parser.getTok().getLoc(),
                  "Memory address is not word "
                  "aligned and larger than class RM can handle");
            return MatchOperand_ParseFail;
          }
          Operands.push_back(LanaiOperand::MorphToMemRegImm(
              Lanai::R0, std::move(Op), LPAC::ADD));
        }
        return MatchOperand_Success;
      }
    }

    Error(Parser.getTok().getLoc(),
          "Unknown operand, expected register or immediate");
    return MatchOperand_ParseFail;
  }
  BaseReg = Op->getReg();

  // Determine if a post operation
  if (!PreOp)
    PostOp = parsePrePost(Type, &OffsetValue);

  // If ] match form (1) else match form (2)
  if (Lexer.is(AsmToken::RBrac)) {
    Parser.Lex(); // Eat the ']'.
    if (!Offset) {
      SMLoc Start = Parser.getTok().getLoc();
      SMLoc End =
          SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
      const MCConstantExpr *OffsetConstExpr =
          MCConstantExpr::create(OffsetValue, getContext());
      Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End);
    }
  } else {
    if (Offset || OffsetValue != 0) {
      Error(Parser.getTok().getLoc(), "Expected ']'");
      return MatchOperand_ParseFail;
    }

    // Parse operator
    AluOp = parseAluOperator(PreOp, PostOp);

    // Second form requires offset register
    Offset = parseRegister();
    if (!BaseReg || Lexer.isNot(AsmToken::RBrac)) {
      Error(Parser.getTok().getLoc(), "Expected ']'");
      return MatchOperand_ParseFail;
    }
    Parser.Lex(); // Eat the ']'.
  }

  // First form has addition as operator. Add pre- or post-op indicator as
  // needed.
  AluOp = AluWithPrePost(AluOp, PreOp, PostOp);

  // Ensure immediate offset is not too large
  if (Offset->isImm() && !Offset->isLoImm16Signed()) {
    Error(Parser.getTok().getLoc(),
          "Memory address is not word "
          "aligned and larger than class RM can handle");
    return MatchOperand_ParseFail;
  }

  Operands.push_back(
      Offset->isImm()
          ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp)
          : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp));

  return MatchOperand_Success;
}

// Looks at a token type and creates the relevant operand from this
// information, adding to operands.
// If operand was parsed, returns false, else true.
OperandMatchResultTy
LanaiAsmParser::parseOperand(OperandVector *Operands, StringRef Mnemonic) {
  // Check if the current operand has a custom associated parser, if so, try to
  // custom parse the operand, or fallback to the general approach.
  OperandMatchResultTy Result = MatchOperandParserImpl(*Operands, Mnemonic);

  if (Result == MatchOperand_Success)
    return Result;
  if (Result == MatchOperand_ParseFail) {
    Parser.eatToEndOfStatement();
    return Result;
  }

  // Attempt to parse token as register
  std::unique_ptr<LanaiOperand> Op = parseRegister();

  // Attempt to parse token as immediate
  if (!Op)
    Op = parseImmediate();

  // If the token could not be parsed then fail
  if (!Op) {
    Error(Parser.getTok().getLoc(), "Unknown operand");
    Parser.eatToEndOfStatement();
    return MatchOperand_ParseFail;
  }

  // Push back parsed operand into list of operands
  Operands->push_back(std::move(Op));

  return MatchOperand_Success;
}

// Split the mnemonic into ASM operand, conditional code and instruction
// qualifier (half-word, byte).
StringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,
                                        OperandVector *Operands) {
  size_t Next = Name.find('.');

  StringRef Mnemonic = Name;

  bool IsBRR = false;
  if (Name.endswith(".r")) {
    Mnemonic = Name.substr(0, Name.size() - 2);
    IsBRR = true;
  }

  // Match b?? and s?? (BR, BRR, and SCC instruction classes).
  if (Mnemonic[0] == 'b' ||
      (Mnemonic[0] == 's' && !Mnemonic.startswith("sel") &&
       !Mnemonic.startswith("st"))) {
    // Parse instructions with a conditional code. For example, 'bne' is
    // converted into two operands 'b' and 'ne'.
    LPCC::CondCode CondCode =
        LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next));
    if (CondCode != LPCC::UNKNOWN) {
      Mnemonic = Mnemonic.slice(0, 1);
      Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
      Operands->push_back(LanaiOperand::createImm(
          MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
      if (IsBRR) {
        Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
      }
      return Mnemonic;
    }
  }

  // Parse other instructions with condition codes (RR instructions).
  // We ignore .f here and assume they are flag-setting operations, not
  // conditional codes (except for select instructions where flag-setting
  // variants are not yet implemented).
  if (Mnemonic.startswith("sel") ||
      (!Mnemonic.endswith(".f") && !Mnemonic.startswith("st"))) {
    LPCC::CondCode CondCode = LPCC::suffixToLanaiCondCode(Mnemonic);
    if (CondCode != LPCC::UNKNOWN) {
      size_t Next = Mnemonic.rfind('.', Name.size());
      // 'sel' doesn't use a predicate operand whose printer adds the period,
      // but instead has the period as part of the identifier (i.e., 'sel.' is
      // expected by the generated matcher). If the mnemonic starts with 'sel'
      // then include the period as part of the mnemonic, else don't include it
      // as part of the mnemonic.
      if (Mnemonic.startswith("sel")) {
        Mnemonic = Mnemonic.substr(0, Next + 1);
      } else {
        Mnemonic = Mnemonic.substr(0, Next);
      }
      Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
      Operands->push_back(LanaiOperand::createImm(
          MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));
      return Mnemonic;
    }
  }

  Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));
  if (IsBRR) {
    Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));
  }

  return Mnemonic;
}

static bool IsMemoryAssignmentError(const OperandVector &Operands) {
  // Detects if a memory operation has an erroneous base register modification.
  // Memory operations are detected by matching the types of operands.
  //
  // TODO: This test is focussed on one specific instance (ld/st).
  // Extend it to handle more cases or be more robust.
  bool Modifies = false;

  int Offset = 0;

  if (Operands.size() < 5)
    return false;
  else if (Operands[0]->isToken() && Operands[1]->isReg() &&
           Operands[2]->isImm() && Operands[3]->isImm() && Operands[4]->isReg())
    Offset = 0;
  else if (Operands[0]->isToken() && Operands[1]->isToken() &&
           Operands[2]->isReg() && Operands[3]->isImm() &&
           Operands[4]->isImm() && Operands[5]->isReg())
    Offset = 1;
  else
    return false;

  int PossibleAluOpIdx = Offset + 3;
  int PossibleBaseIdx = Offset + 1;
  int PossibleDestIdx = Offset + 4;
  if (LanaiOperand *PossibleAluOp =
          static_cast<LanaiOperand *>(Operands[PossibleAluOpIdx].get()))
    if (PossibleAluOp->isImm())
      if (const MCConstantExpr *ConstExpr =
              dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))
        Modifies = LPAC::modifiesOp(ConstExpr->getValue());
  return Modifies && Operands[PossibleBaseIdx]->isReg() &&
         Operands[PossibleDestIdx]->isReg() &&
         Operands[PossibleBaseIdx]->getReg() ==
             Operands[PossibleDestIdx]->getReg();
}

static bool IsRegister(const MCParsedAsmOperand &op) {
  return static_cast<const LanaiOperand &>(op).isReg();
}

static bool MaybePredicatedInst(const OperandVector &Operands) {
  if (Operands.size() < 4 || !IsRegister(*Operands[1]) ||
      !IsRegister(*Operands[2]))
    return false;
  return StringSwitch<bool>(
             static_cast<const LanaiOperand &>(*Operands[0]).getToken())
      .StartsWith("addc", true)
      .StartsWith("add", true)
      .StartsWith("and", true)
      .StartsWith("sh", true)
      .StartsWith("subb", true)
      .StartsWith("sub", true)
      .StartsWith("or", true)
      .StartsWith("xor", true)
      .Default(false);
}

bool LanaiAsmParser::ParseInstruction(ParseInstructionInfo & /*Info*/,
                                      StringRef Name, SMLoc NameLoc,
                                      OperandVector &Operands) {
  // First operand is token for instruction
  StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);

  // If there are no more operands, then finish
  if (Lexer.is(AsmToken::EndOfStatement))
    return false;

  // Parse first operand
  if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success)
    return true;

  // If it is a st instruction with one 1 operand then it is a "store true".
  // Transform <"st"> to <"s">, <LPCC:ICC_T>
  if (Lexer.is(AsmToken::EndOfStatement) && Name == "st" &&
      Operands.size() == 2) {
    Operands.erase(Operands.begin(), Operands.begin() + 1);
    Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc));
    Operands.insert(Operands.begin() + 1,
                    LanaiOperand::createImm(
                        MCConstantExpr::create(LPCC::ICC_T, getContext()),
                        NameLoc, NameLoc));
  }

  // If the instruction is a bt instruction with 1 operand (in assembly) then it
  // is an unconditional branch instruction and the first two elements of
  // operands need to be merged.
  if (Lexer.is(AsmToken::EndOfStatement) && Name.startswith("bt") &&
      Operands.size() == 3) {
    Operands.erase(Operands.begin(), Operands.begin() + 2);
    Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc));
  }

  // Parse until end of statement, consuming commas between operands
  while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.is(AsmToken::Comma)) {
    // Consume comma token
    Lex();

    // Parse next operand
    if (parseOperand(&Operands, Mnemonic) != MatchOperand_Success)
      return true;
  }

  if (IsMemoryAssignmentError(Operands)) {
    Error(Parser.getTok().getLoc(),
          "the destination register can't equal the base register in an "
          "instruction that modifies the base register.");
    return true;
  }

  // Insert always true operand for instruction that may be predicated but
  // are not. Currently the autogenerated parser always expects a predicate.
  if (MaybePredicatedInst(Operands)) {
    Operands.insert(Operands.begin() + 1,
                    LanaiOperand::createImm(
                        MCConstantExpr::create(LPCC::ICC_T, getContext()),
                        NameLoc, NameLoc));
  }

  return false;
}

#define GET_REGISTER_MATCHER
#define GET_MATCHER_IMPLEMENTATION
#include "LanaiGenAsmMatcher.inc"

extern "C" void LLVMInitializeLanaiAsmParser() {
  RegisterMCAsmParser<LanaiAsmParser> x(getTheLanaiTarget());
}
