brintos

brintos / llvm-project-archived public Read only

0
0
Text · 39.6 KiB · 0444c86 Raw
1234 lines · cpp
1//===-- LanaiAsmParser.cpp - Parse Lanai assembly to MCInst instructions --===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "LanaiAluCode.h"10#include "LanaiCondCode.h"11#include "LanaiInstrInfo.h"12#include "MCTargetDesc/LanaiMCAsmInfo.h"13#include "TargetInfo/LanaiTargetInfo.h"14#include "llvm/ADT/StringRef.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/MCParser/AsmLexer.h"20#include "llvm/MC/MCParser/MCAsmParser.h"21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"22#include "llvm/MC/MCParser/MCTargetAsmParser.h"23#include "llvm/MC/MCStreamer.h"24#include "llvm/MC/MCSubtargetInfo.h"25#include "llvm/MC/MCSymbol.h"26#include "llvm/MC/TargetRegistry.h"27#include "llvm/Support/Casting.h"28#include "llvm/Support/Compiler.h"29#include "llvm/Support/ErrorHandling.h"30#include "llvm/Support/MathExtras.h"31#include "llvm/Support/SMLoc.h"32#include "llvm/Support/raw_ostream.h"33#include <cassert>34#include <cstddef>35#include <cstdint>36#include <memory>37#include <optional>38 39using namespace llvm;40 41// Auto-generated by TableGen42static MCRegister MatchRegisterName(StringRef Name);43 44namespace {45 46struct LanaiOperand;47 48class LanaiAsmParser : public MCTargetAsmParser {49  // Parse operands50  std::unique_ptr<LanaiOperand> parseRegister(bool RestoreOnFailure = false);51 52  std::unique_ptr<LanaiOperand> parseImmediate();53 54  std::unique_ptr<LanaiOperand> parseIdentifier();55 56  unsigned parseAluOperator(bool PreOp, bool PostOp);57 58  // Split the mnemonic stripping conditional code and quantifiers59  StringRef splitMnemonic(StringRef Name, SMLoc NameLoc,60                          OperandVector *Operands);61 62  bool parsePrePost(StringRef Type, int *OffsetValue);63 64  bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,65                        SMLoc NameLoc, OperandVector &Operands) override;66 67  bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;68  ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,69                               SMLoc &EndLoc) override;70 71  bool matchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,72                               OperandVector &Operands, MCStreamer &Out,73                               uint64_t &ErrorInfo,74                               bool MatchingInlineAsm) override;75 76// Auto-generated instruction matching functions77#define GET_ASSEMBLER_HEADER78#include "LanaiGenAsmMatcher.inc"79 80  ParseStatus parseOperand(OperandVector *Operands, StringRef Mnemonic);81 82  ParseStatus parseMemoryOperand(OperandVector &Operands);83 84public:85  LanaiAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,86                 const MCInstrInfo &MII, const MCTargetOptions &Options)87      : MCTargetAsmParser(Options, STI, MII), Parser(Parser),88        Lexer(Parser.getLexer()), SubtargetInfo(STI) {89    setAvailableFeatures(90        ComputeAvailableFeatures(SubtargetInfo.getFeatureBits()));91  }92 93private:94  MCAsmParser &Parser;95  AsmLexer &Lexer;96 97  const MCSubtargetInfo &SubtargetInfo;98};99 100// LanaiOperand - Instances of this class represented a parsed machine101// instruction102struct LanaiOperand : public MCParsedAsmOperand {103  enum KindTy {104    TOKEN,105    REGISTER,106    IMMEDIATE,107    MEMORY_IMM,108    MEMORY_REG_IMM,109    MEMORY_REG_REG,110  } Kind;111 112  SMLoc StartLoc, EndLoc;113 114  struct Token {115    const char *Data;116    unsigned Length;117  };118 119  struct RegOp {120    MCRegister RegNum;121  };122 123  struct ImmOp {124    const MCExpr *Value;125  };126 127  struct MemOp {128    MCRegister BaseReg;129    MCRegister OffsetReg;130    unsigned AluOp;131    const MCExpr *Offset;132  };133 134  union {135    struct Token Tok;136    struct RegOp Reg;137    struct ImmOp Imm;138    struct MemOp Mem;139  };140 141  explicit LanaiOperand(KindTy Kind) : Kind(Kind) {}142 143public:144  // The functions below are used by the autogenerated ASM matcher and hence to145  // be of the form expected.146 147  // getStartLoc - Gets location of the first token of this operand148  SMLoc getStartLoc() const override { return StartLoc; }149 150  // getEndLoc - Gets location of the last token of this operand151  SMLoc getEndLoc() const override { return EndLoc; }152 153  MCRegister getReg() const override {154    assert(isReg() && "Invalid type access!");155    return Reg.RegNum;156  }157 158  const MCExpr *getImm() const {159    assert(isImm() && "Invalid type access!");160    return Imm.Value;161  }162 163  StringRef getToken() const {164    assert(isToken() && "Invalid type access!");165    return StringRef(Tok.Data, Tok.Length);166  }167 168  MCRegister getMemBaseReg() const {169    assert(isMem() && "Invalid type access!");170    return Mem.BaseReg;171  }172 173  MCRegister getMemOffsetReg() const {174    assert(isMem() && "Invalid type access!");175    return Mem.OffsetReg;176  }177 178  const MCExpr *getMemOffset() const {179    assert(isMem() && "Invalid type access!");180    return Mem.Offset;181  }182 183  unsigned getMemOp() const {184    assert(isMem() && "Invalid type access!");185    return Mem.AluOp;186  }187 188  // Functions for testing operand type189  bool isReg() const override { return Kind == REGISTER; }190 191  bool isImm() const override { return Kind == IMMEDIATE; }192 193  bool isMem() const override {194    return isMemImm() || isMemRegImm() || isMemRegReg();195  }196 197  bool isMemImm() const { return Kind == MEMORY_IMM; }198 199  bool isMemRegImm() const { return Kind == MEMORY_REG_IMM; }200 201  bool isMemRegReg() const { return Kind == MEMORY_REG_REG; }202 203  bool isMemSpls() const { return isMemRegImm() || isMemRegReg(); }204 205  bool isToken() const override { return Kind == TOKEN; }206 207  bool isBrImm() {208    if (!isImm())209      return false;210 211    // Constant case212    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm.Value);213    if (!MCE)214      return true;215    int64_t Value = MCE->getValue();216    // Check if value fits in 25 bits with 2 least significant bits 0.217    return isShiftedUInt<23, 2>(static_cast<int32_t>(Value));218  }219 220  bool isBrTarget() { return isBrImm() || isToken(); }221 222  bool isCallTarget() { return isImm() || isToken(); }223 224  bool isHiImm16() {225    if (!isImm())226      return false;227 228    // Constant case229    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {230      int64_t Value = ConstExpr->getValue();231      return Value != 0 && isShiftedUInt<16, 16>(Value);232    }233 234    // Symbolic reference expression235    if (const auto *SymbolRefExpr = dyn_cast<MCSpecifierExpr>(Imm.Value))236      return SymbolRefExpr->getSpecifier() == Lanai::S_ABS_HI;237 238    // Binary expression239    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))240      if (const auto *SymbolRefExpr =241              dyn_cast<MCSpecifierExpr>(BinaryExpr->getLHS()))242        return SymbolRefExpr->getSpecifier() == Lanai::S_ABS_HI;243 244    return false;245  }246 247  bool isHiImm16And() {248    if (!isImm())249      return false;250 251    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);252    if (ConstExpr) {253      int64_t Value = ConstExpr->getValue();254      // Check if in the form 0xXYZWffff255      return (Value != 0) && ((Value & ~0xffff0000) == 0xffff);256    }257    return false;258  }259 260  bool isLoImm16() {261    if (!isImm())262      return false;263 264    // Constant case265    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {266      int64_t Value = ConstExpr->getValue();267      // Check if value fits in 16 bits268      return isUInt<16>(static_cast<int32_t>(Value));269    }270 271    // Symbolic reference expression272    if (const auto *SymbolRefExpr = dyn_cast<MCSpecifierExpr>(Imm.Value))273      return SymbolRefExpr->getSpecifier() == Lanai::S_ABS_LO;274 275    // Binary expression276    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))277      if (const auto *SymbolRefExpr =278              dyn_cast<MCSpecifierExpr>(BinaryExpr->getLHS()))279        return SymbolRefExpr->getSpecifier() == Lanai::S_ABS_LO;280 281    return false;282  }283 284  bool isLoImm16Signed() {285    if (!isImm())286      return false;287 288    // Constant case289    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {290      int64_t Value = ConstExpr->getValue();291      // Check if value fits in 16 bits or value of the form 0xffffxyzw292      return isInt<16>(static_cast<int32_t>(Value));293    }294 295    // Symbolic reference expression296    if (const auto *SymbolRefExpr = dyn_cast<MCSpecifierExpr>(Imm.Value))297      return SymbolRefExpr->getSpecifier() == Lanai::S_ABS_LO;298 299    // Binary expression300    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value))301      if (const auto *SymbolRefExpr =302              dyn_cast<MCSpecifierExpr>(BinaryExpr->getLHS()))303        return SymbolRefExpr->getSpecifier() == Lanai::S_ABS_LO;304 305    return false;306  }307 308  bool isLoImm16And() {309    if (!isImm())310      return false;311 312    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);313    if (ConstExpr) {314      int64_t Value = ConstExpr->getValue();315      // Check if in the form 0xffffXYZW316      return ((Value & ~0xffff) == 0xffff0000);317    }318    return false;319  }320 321  bool isImmShift() {322    if (!isImm())323      return false;324 325    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);326    if (!ConstExpr)327      return false;328    int64_t Value = ConstExpr->getValue();329    return (Value >= -31) && (Value <= 31);330  }331 332  bool isLoImm21() {333    if (!isImm())334      return false;335 336    // Constant case337    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value)) {338      int64_t Value = ConstExpr->getValue();339      return isUInt<21>(Value);340    }341 342    // Symbolic reference expression343    if (const auto *SymbolRefExpr = dyn_cast<MCSpecifierExpr>(Imm.Value))344      return SymbolRefExpr->getSpecifier() == Lanai::S_None;345    if (const MCSymbolRefExpr *SymbolRefExpr =346            dyn_cast<MCSymbolRefExpr>(Imm.Value)) {347      return SymbolRefExpr->getSpecifier() == 0;348    }349 350    // Binary expression351    if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Imm.Value)) {352      if (const auto *SymbolRefExpr =353              dyn_cast<MCSpecifierExpr>(BinaryExpr->getLHS()))354        return SymbolRefExpr->getSpecifier() == Lanai::S_None;355      if (const MCSymbolRefExpr *SymbolRefExpr =356              dyn_cast<MCSymbolRefExpr>(BinaryExpr->getLHS()))357        return SymbolRefExpr->getSpecifier() == 0;358    }359 360    return false;361  }362 363  bool isImm10() {364    if (!isImm())365      return false;366 367    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);368    if (!ConstExpr)369      return false;370    int64_t Value = ConstExpr->getValue();371    return isInt<10>(Value);372  }373 374  bool isCondCode() {375    if (!isImm())376      return false;377 378    const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Imm.Value);379    if (!ConstExpr)380      return false;381    uint64_t Value = ConstExpr->getValue();382    // The condition codes are between 0 (ICC_T) and 15 (ICC_LE). If the383    // unsigned value of the immediate is less than LPCC::UNKNOWN (16) then384    // value corresponds to a valid condition code.385    return Value < LPCC::UNKNOWN;386  }387 388  void addExpr(MCInst &Inst, const MCExpr *Expr) const {389    // Add as immediates where possible. Null MCExpr = 0390    if (Expr == nullptr)391      Inst.addOperand(MCOperand::createImm(0));392    else if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Expr))393      Inst.addOperand(394          MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));395    else396      Inst.addOperand(MCOperand::createExpr(Expr));397  }398 399  void addRegOperands(MCInst &Inst, unsigned N) const {400    assert(N == 1 && "Invalid number of operands!");401    Inst.addOperand(MCOperand::createReg(getReg()));402  }403 404  void addImmOperands(MCInst &Inst, unsigned N) const {405    assert(N == 1 && "Invalid number of operands!");406    addExpr(Inst, getImm());407  }408 409  void addBrTargetOperands(MCInst &Inst, unsigned N) const {410    assert(N == 1 && "Invalid number of operands!");411    addExpr(Inst, getImm());412  }413 414  void addCallTargetOperands(MCInst &Inst, unsigned N) const {415    assert(N == 1 && "Invalid number of operands!");416    addExpr(Inst, getImm());417  }418 419  void addCondCodeOperands(MCInst &Inst, unsigned N) const {420    assert(N == 1 && "Invalid number of operands!");421    addExpr(Inst, getImm());422  }423 424  void addMemImmOperands(MCInst &Inst, unsigned N) const {425    assert(N == 1 && "Invalid number of operands!");426    const MCExpr *Expr = getMemOffset();427    addExpr(Inst, Expr);428  }429 430  void addMemRegImmOperands(MCInst &Inst, unsigned N) const {431    assert(N == 3 && "Invalid number of operands!");432    Inst.addOperand(MCOperand::createReg(getMemBaseReg()));433    const MCExpr *Expr = getMemOffset();434    addExpr(Inst, Expr);435    Inst.addOperand(MCOperand::createImm(getMemOp()));436  }437 438  void addMemRegRegOperands(MCInst &Inst, unsigned N) const {439    assert(N == 3 && "Invalid number of operands!");440    Inst.addOperand(MCOperand::createReg(getMemBaseReg()));441    assert(getMemOffsetReg() && "Invalid offset");442    Inst.addOperand(MCOperand::createReg(getMemOffsetReg()));443    Inst.addOperand(MCOperand::createImm(getMemOp()));444  }445 446  void addMemSplsOperands(MCInst &Inst, unsigned N) const {447    if (isMemRegImm())448      addMemRegImmOperands(Inst, N);449    if (isMemRegReg())450      addMemRegRegOperands(Inst, N);451  }452 453  void addImmShiftOperands(MCInst &Inst, unsigned N) const {454    assert(N == 1 && "Invalid number of operands!");455    addExpr(Inst, getImm());456  }457 458  void addImm10Operands(MCInst &Inst, unsigned N) const {459    assert(N == 1 && "Invalid number of operands!");460    addExpr(Inst, getImm());461  }462 463  void addLoImm16Operands(MCInst &Inst, unsigned N) const {464    assert(N == 1 && "Invalid number of operands!");465    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))466      Inst.addOperand(467          MCOperand::createImm(static_cast<int32_t>(ConstExpr->getValue())));468    else if (isa<MCSpecifierExpr>(getImm())) {469#ifndef NDEBUG470      const auto *SymbolRefExpr = dyn_cast<MCSpecifierExpr>(getImm());471      assert(SymbolRefExpr && SymbolRefExpr->getSpecifier() == Lanai::S_ABS_LO);472#endif473      Inst.addOperand(MCOperand::createExpr(getImm()));474    } else if (isa<MCBinaryExpr>(getImm())) {475#ifndef NDEBUG476      const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());477      assert(BinaryExpr && isa<MCSpecifierExpr>(BinaryExpr->getLHS()) &&478             cast<MCSpecifierExpr>(BinaryExpr->getLHS())->getSpecifier() ==479                 Lanai::S_ABS_LO);480#endif481      Inst.addOperand(MCOperand::createExpr(getImm()));482    } else483      assert(false && "Operand type not supported.");484  }485 486  void addLoImm16AndOperands(MCInst &Inst, unsigned N) const {487    assert(N == 1 && "Invalid number of operands!");488    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))489      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0xffff));490    else491      assert(false && "Operand type not supported.");492  }493 494  void addHiImm16Operands(MCInst &Inst, unsigned N) const {495    assert(N == 1 && "Invalid number of operands!");496    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))497      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));498    else if (isa<MCSpecifierExpr>(getImm())) {499#ifndef NDEBUG500      const auto *SymbolRefExpr = dyn_cast<MCSpecifierExpr>(getImm());501      assert(SymbolRefExpr && SymbolRefExpr->getSpecifier() == Lanai::S_ABS_HI);502#endif503      Inst.addOperand(MCOperand::createExpr(getImm()));504    } else if (isa<MCBinaryExpr>(getImm())) {505#ifndef NDEBUG506      const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());507      assert(BinaryExpr && isa<MCSpecifierExpr>(BinaryExpr->getLHS()) &&508             cast<MCSpecifierExpr>(BinaryExpr->getLHS())->getSpecifier() ==509                 Lanai::S_ABS_HI);510#endif511      Inst.addOperand(MCOperand::createExpr(getImm()));512    } else513      assert(false && "Operand type not supported.");514  }515 516  void addHiImm16AndOperands(MCInst &Inst, unsigned N) const {517    assert(N == 1 && "Invalid number of operands!");518    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))519      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() >> 16));520    else521      assert(false && "Operand type not supported.");522  }523 524  void addLoImm21Operands(MCInst &Inst, unsigned N) const {525    assert(N == 1 && "Invalid number of operands!");526    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(getImm()))527      Inst.addOperand(MCOperand::createImm(ConstExpr->getValue() & 0x1fffff));528    else if (isa<MCSpecifierExpr>(getImm())) {529#ifndef NDEBUG530      const auto *SymbolRefExpr = dyn_cast<MCSpecifierExpr>(getImm());531      assert(SymbolRefExpr && SymbolRefExpr->getSpecifier() == Lanai::S_None);532#endif533      Inst.addOperand(MCOperand::createExpr(getImm()));534    } else if (isa<MCSymbolRefExpr>(getImm())) {535#ifndef NDEBUG536      const MCSymbolRefExpr *SymbolRefExpr =537          dyn_cast<MCSymbolRefExpr>(getImm());538      assert(SymbolRefExpr && SymbolRefExpr->getSpecifier() == 0);539#endif540      Inst.addOperand(MCOperand::createExpr(getImm()));541    } else if (isa<MCBinaryExpr>(getImm())) {542#ifndef NDEBUG543      const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(getImm());544      assert(BinaryExpr && isa<MCSpecifierExpr>(BinaryExpr->getLHS()) &&545             cast<MCSpecifierExpr>(BinaryExpr->getLHS())->getSpecifier() ==546                 Lanai::S_None);547#endif548      Inst.addOperand(MCOperand::createExpr(getImm()));549    } else550      assert(false && "Operand type not supported.");551  }552 553  void print(raw_ostream &OS, const MCAsmInfo &MAI) const override {554    switch (Kind) {555    case IMMEDIATE:556      OS << "Imm: " << getImm() << "\n";557      break;558    case TOKEN:559      OS << "Token: " << getToken() << "\n";560      break;561    case REGISTER:562      OS << "Reg: %r" << getReg().id() << "\n";563      break;564    case MEMORY_IMM:565      OS << "MemImm: ";566      MAI.printExpr(OS, *getMemOffset());567      OS << '\n';568      break;569    case MEMORY_REG_IMM:570      OS << "MemRegImm: " << getMemBaseReg().id() << "+";571      MAI.printExpr(OS, *getMemOffset());572      OS << '\n';573      break;574    case MEMORY_REG_REG:575      assert(getMemOffset() == nullptr);576      OS << "MemRegReg: " << getMemBaseReg().id() << "+"577         << "%r" << getMemOffsetReg().id() << "\n";578      break;579    }580  }581 582  static std::unique_ptr<LanaiOperand> CreateToken(StringRef Str, SMLoc Start) {583    auto Op = std::make_unique<LanaiOperand>(TOKEN);584    Op->Tok.Data = Str.data();585    Op->Tok.Length = Str.size();586    Op->StartLoc = Start;587    Op->EndLoc = Start;588    return Op;589  }590 591  static std::unique_ptr<LanaiOperand> createReg(MCRegister Reg, SMLoc Start,592                                                 SMLoc End) {593    auto Op = std::make_unique<LanaiOperand>(REGISTER);594    Op->Reg.RegNum = Reg;595    Op->StartLoc = Start;596    Op->EndLoc = End;597    return Op;598  }599 600  static std::unique_ptr<LanaiOperand> createImm(const MCExpr *Value,601                                                 SMLoc Start, SMLoc End) {602    auto Op = std::make_unique<LanaiOperand>(IMMEDIATE);603    Op->Imm.Value = Value;604    Op->StartLoc = Start;605    Op->EndLoc = End;606    return Op;607  }608 609  static std::unique_ptr<LanaiOperand>610  MorphToMemImm(std::unique_ptr<LanaiOperand> Op) {611    const MCExpr *Imm = Op->getImm();612    Op->Kind = MEMORY_IMM;613    Op->Mem.BaseReg = MCRegister();614    Op->Mem.AluOp = LPAC::ADD;615    Op->Mem.OffsetReg = 0;616    Op->Mem.Offset = Imm;617    return Op;618  }619 620  static std::unique_ptr<LanaiOperand>621  MorphToMemRegReg(MCRegister BaseReg, std::unique_ptr<LanaiOperand> Op,622                   unsigned AluOp) {623    MCRegister OffsetReg = Op->getReg();624    Op->Kind = MEMORY_REG_REG;625    Op->Mem.BaseReg = BaseReg;626    Op->Mem.AluOp = AluOp;627    Op->Mem.OffsetReg = OffsetReg;628    Op->Mem.Offset = nullptr;629    return Op;630  }631 632  static std::unique_ptr<LanaiOperand>633  MorphToMemRegImm(MCRegister BaseReg, std::unique_ptr<LanaiOperand> Op,634                   unsigned AluOp) {635    const MCExpr *Imm = Op->getImm();636    Op->Kind = MEMORY_REG_IMM;637    Op->Mem.BaseReg = BaseReg;638    Op->Mem.AluOp = AluOp;639    Op->Mem.OffsetReg = 0;640    Op->Mem.Offset = Imm;641    return Op;642  }643};644 645} // end anonymous namespace646 647bool LanaiAsmParser::matchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,648                                             OperandVector &Operands,649                                             MCStreamer &Out,650                                             uint64_t &ErrorInfo,651                                             bool MatchingInlineAsm) {652  MCInst Inst;653  SMLoc ErrorLoc;654 655  switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {656  case Match_Success:657    Out.emitInstruction(Inst, SubtargetInfo);658    Opcode = Inst.getOpcode();659    return false;660  case Match_MissingFeature:661    return Error(IdLoc, "Instruction use requires option to be enabled");662  case Match_MnemonicFail:663    return Error(IdLoc, "Unrecognized instruction mnemonic");664  case Match_InvalidOperand: {665    ErrorLoc = IdLoc;666    if (ErrorInfo != ~0U) {667      if (ErrorInfo >= Operands.size())668        return Error(IdLoc, "Too few operands for instruction");669 670      ErrorLoc = ((LanaiOperand &)*Operands[ErrorInfo]).getStartLoc();671      if (ErrorLoc == SMLoc())672        ErrorLoc = IdLoc;673    }674    return Error(ErrorLoc, "Invalid operand for instruction");675  }676  default:677    break;678  }679 680  llvm_unreachable("Unknown match type detected!");681}682 683// Both '%rN' and 'rN' are parsed as valid registers. This was done to remain684// backwards compatible with GCC and the different ways inline assembly is685// handled.686// TODO: see if there isn't a better way to do this.687std::unique_ptr<LanaiOperand>688LanaiAsmParser::parseRegister(bool RestoreOnFailure) {689  SMLoc Start = Parser.getTok().getLoc();690  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);691  std::optional<AsmToken> PercentTok;692 693  MCRegister Reg;694  // Eat the '%'.695  if (Lexer.getKind() == AsmToken::Percent) {696    PercentTok = Parser.getTok();697    Parser.Lex();698  }699  if (Lexer.getKind() == AsmToken::Identifier) {700    Reg = MatchRegisterName(Lexer.getTok().getIdentifier());701    if (!Reg) {702      if (PercentTok && RestoreOnFailure)703        Lexer.UnLex(*PercentTok);704      return nullptr;705    }706    Parser.Lex(); // Eat identifier token707    return LanaiOperand::createReg(Reg, Start, End);708  }709  if (PercentTok && RestoreOnFailure)710    Lexer.UnLex(*PercentTok);711  return nullptr;712}713 714bool LanaiAsmParser::parseRegister(MCRegister &RegNum, SMLoc &StartLoc,715                                   SMLoc &EndLoc) {716  const AsmToken &Tok = getParser().getTok();717  StartLoc = Tok.getLoc();718  EndLoc = Tok.getEndLoc();719  std::unique_ptr<LanaiOperand> Op = parseRegister(/*RestoreOnFailure=*/false);720  if (Op != nullptr)721    RegNum = Op->getReg();722  return (Op == nullptr);723}724 725ParseStatus LanaiAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,726                                             SMLoc &EndLoc) {727  const AsmToken &Tok = getParser().getTok();728  StartLoc = Tok.getLoc();729  EndLoc = Tok.getEndLoc();730  std::unique_ptr<LanaiOperand> Op = parseRegister(/*RestoreOnFailure=*/true);731  if (Op == nullptr)732    return ParseStatus::NoMatch;733  Reg = Op->getReg();734  return ParseStatus::Success;735}736 737std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {738  SMLoc Start = Parser.getTok().getLoc();739  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);740  const MCExpr *Res, *RHS = nullptr;741  auto Kind = Lanai::S_None;742 743  if (Lexer.getKind() != AsmToken::Identifier)744    return nullptr;745 746  StringRef Identifier;747  if (Parser.parseIdentifier(Identifier))748    return nullptr;749 750  // Check if identifier has a modifier751  if (Identifier.equals_insensitive("hi"))752    Kind = Lanai::S_ABS_HI;753  else if (Identifier.equals_insensitive("lo"))754    Kind = Lanai::S_ABS_LO;755 756  // If the identifier corresponds to a variant then extract the real757  // identifier.758  if (Kind != Lanai::S_None) {759    if (Lexer.getKind() != AsmToken::LParen) {760      Error(Lexer.getLoc(), "Expected '('");761      return nullptr;762    }763    Lexer.Lex(); // lex '('764 765    // Parse identifier766    if (Parser.parseIdentifier(Identifier))767      return nullptr;768  }769 770  // If addition parse the RHS.771  if (Lexer.getKind() == AsmToken::Plus && Parser.parseExpression(RHS))772    return nullptr;773 774  // For variants parse the final ')'775  if (Kind != Lanai::S_None) {776    if (Lexer.getKind() != AsmToken::RParen) {777      Error(Lexer.getLoc(), "Expected ')'");778      return nullptr;779    }780    Lexer.Lex(); // lex ')'781  }782 783  End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);784  MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);785  Res = MCSpecifierExpr::create(Sym, Kind, getContext());786 787  // Nest if this was an addition788  if (RHS)789    Res = MCBinaryExpr::createAdd(Res, RHS, getContext());790 791  return LanaiOperand::createImm(Res, Start, End);792}793 794std::unique_ptr<LanaiOperand> LanaiAsmParser::parseImmediate() {795  SMLoc Start = Parser.getTok().getLoc();796  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);797 798  const MCExpr *ExprVal;799  switch (Lexer.getKind()) {800  case AsmToken::Identifier:801    return parseIdentifier();802  case AsmToken::Plus:803  case AsmToken::Minus:804  case AsmToken::Integer:805  case AsmToken::Dot:806    if (!Parser.parseExpression(ExprVal))807      return LanaiOperand::createImm(ExprVal, Start, End);808    [[fallthrough]];809  default:810    return nullptr;811  }812}813 814static unsigned AluWithPrePost(unsigned AluCode, bool PreOp, bool PostOp) {815  if (PreOp)816    return LPAC::makePreOp(AluCode);817  if (PostOp)818    return LPAC::makePostOp(AluCode);819  return AluCode;820}821 822unsigned LanaiAsmParser::parseAluOperator(bool PreOp, bool PostOp) {823  StringRef IdString;824  Parser.parseIdentifier(IdString);825  unsigned AluCode = LPAC::stringToLanaiAluCode(IdString);826  if (AluCode == LPAC::UNKNOWN) {827    Error(Parser.getTok().getLoc(), "Can't parse ALU operator");828    return 0;829  }830  return AluCode;831}832 833static int SizeForSuffix(StringRef T) {834  return StringSwitch<int>(T).EndsWith(".h", 2).EndsWith(".b", 1).Default(4);835}836 837bool LanaiAsmParser::parsePrePost(StringRef Type, int *OffsetValue) {838  bool PreOrPost = false;839  if (Lexer.getKind() == Lexer.peekTok(true).getKind()) {840    PreOrPost = true;841    if (Lexer.is(AsmToken::Minus))842      *OffsetValue = -SizeForSuffix(Type);843    else if (Lexer.is(AsmToken::Plus))844      *OffsetValue = SizeForSuffix(Type);845    else846      return false;847 848    // Eat the '-' '-' or '+' '+'849    Parser.Lex();850    Parser.Lex();851  } else if (Lexer.is(AsmToken::Star)) {852    Parser.Lex(); // Eat the '*'853    PreOrPost = true;854  }855 856  return PreOrPost;857}858 859bool shouldBeSls(const LanaiOperand &Op) {860  // The instruction should be encoded as an SLS if the constant is word861  // aligned and will fit in 21 bits862  if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(Op.getImm())) {863    int64_t Value = ConstExpr->getValue();864    return (Value % 4 == 0) && (Value >= 0) && (Value <= 0x1fffff);865  }866  // The instruction should be encoded as an SLS if the operand is a symbolic867  // reference with no variant.868  if (const auto *SymbolRefExpr = dyn_cast<MCSpecifierExpr>(Op.getImm()))869    return SymbolRefExpr->getSpecifier() == Lanai::S_None;870  // The instruction should be encoded as an SLS if the operand is a binary871  // expression with the left-hand side being a symbolic reference with no872  // variant.873  if (const MCBinaryExpr *BinaryExpr = dyn_cast<MCBinaryExpr>(Op.getImm())) {874    const auto *LHSSymbolRefExpr =875        dyn_cast<MCSpecifierExpr>(BinaryExpr->getLHS());876    return (LHSSymbolRefExpr &&877            LHSSymbolRefExpr->getSpecifier() == Lanai::S_None);878  }879  return false;880}881 882// Matches memory operand. Returns true if error encountered.883ParseStatus LanaiAsmParser::parseMemoryOperand(OperandVector &Operands) {884  // Try to match a memory operand.885  // The memory operands are of the form:886  //  (1)  Register|Immediate|'' '[' '*'? Register '*'? ']' or887  //                            ^888  //  (2)  '[' '*'? Register '*'? AluOperator Register ']'889  //      ^890  //  (3)  '[' '--'|'++' Register '--'|'++' ']'891  //892  //  (4) '[' Immediate ']' (for SLS)893 894  // Store the type for use in parsing pre/post increment/decrement operators895  StringRef Type;896  if (Operands[0]->isToken())897    Type = static_cast<LanaiOperand *>(Operands[0].get())->getToken();898 899  // Use 0 if no offset given900  int OffsetValue = 0;901  MCRegister BaseReg;902  unsigned AluOp = LPAC::ADD;903  bool PostOp = false, PreOp = false;904 905  // Try to parse the offset906  std::unique_ptr<LanaiOperand> Op = parseRegister();907  if (!Op)908    Op = parseImmediate();909 910  // Only continue if next token is '['911  if (Lexer.isNot(AsmToken::LBrac)) {912    if (!Op)913      return ParseStatus::NoMatch;914 915    // The start of this custom parsing overlaps with register/immediate so916    // consider this as a successful match of an operand of that type as the917    // token stream can't be rewound to allow them to match separately.918    Operands.push_back(std::move(Op));919    return ParseStatus::Success;920  }921 922  Parser.Lex(); // Eat the '['.923  std::unique_ptr<LanaiOperand> Offset = nullptr;924  if (Op)925    Offset.swap(Op);926 927  // Determine if a pre operation928  PreOp = parsePrePost(Type, &OffsetValue);929 930  Op = parseRegister();931  if (!Op) {932    if (!Offset) {933      if ((Op = parseImmediate()) && Lexer.is(AsmToken::RBrac)) {934        Parser.Lex(); // Eat the ']'935 936        // Memory address operations aligned to word boundary are encoded as937        // SLS, the rest as RM.938        if (shouldBeSls(*Op)) {939          Operands.push_back(LanaiOperand::MorphToMemImm(std::move(Op)));940        } else {941          if (!Op->isLoImm16Signed())942            return Error(Parser.getTok().getLoc(),943                         "Memory address is not word aligned and larger than "944                         "class RM can handle");945          Operands.push_back(LanaiOperand::MorphToMemRegImm(946              Lanai::R0, std::move(Op), LPAC::ADD));947        }948        return ParseStatus::Success;949      }950    }951 952    return Error(Parser.getTok().getLoc(),953                 "Unknown operand, expected register or immediate");954  }955  BaseReg = Op->getReg();956 957  // Determine if a post operation958  if (!PreOp)959    PostOp = parsePrePost(Type, &OffsetValue);960 961  // If ] match form (1) else match form (2)962  if (Lexer.is(AsmToken::RBrac)) {963    Parser.Lex(); // Eat the ']'.964    if (!Offset) {965      SMLoc Start = Parser.getTok().getLoc();966      SMLoc End =967          SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);968      const MCConstantExpr *OffsetConstExpr =969          MCConstantExpr::create(OffsetValue, getContext());970      Offset = LanaiOperand::createImm(OffsetConstExpr, Start, End);971    }972  } else {973    if (Offset || OffsetValue != 0)974      return Error(Parser.getTok().getLoc(), "Expected ']'");975 976    // Parse operator977    AluOp = parseAluOperator(PreOp, PostOp);978 979    // Second form requires offset register980    Offset = parseRegister();981    if (!BaseReg || Lexer.isNot(AsmToken::RBrac))982      return Error(Parser.getTok().getLoc(), "Expected ']'");983    Parser.Lex(); // Eat the ']'.984  }985 986  // First form has addition as operator. Add pre- or post-op indicator as987  // needed.988  AluOp = AluWithPrePost(AluOp, PreOp, PostOp);989 990  // Ensure immediate offset is not too large991  if (Offset->isImm() && !Offset->isLoImm16Signed())992    return Error(Parser.getTok().getLoc(),993                 "Memory address is not word aligned and larger than class RM "994                 "can handle");995 996  Operands.push_back(997      Offset->isImm()998          ? LanaiOperand::MorphToMemRegImm(BaseReg, std::move(Offset), AluOp)999          : LanaiOperand::MorphToMemRegReg(BaseReg, std::move(Offset), AluOp));1000 1001  return ParseStatus::Success;1002}1003 1004// Looks at a token type and creates the relevant operand from this1005// information, adding to operands.1006// If operand was parsed, returns false, else true.1007ParseStatus LanaiAsmParser::parseOperand(OperandVector *Operands,1008                                         StringRef Mnemonic) {1009  // Check if the current operand has a custom associated parser, if so, try to1010  // custom parse the operand, or fallback to the general approach.1011  ParseStatus Result = MatchOperandParserImpl(*Operands, Mnemonic);1012 1013  if (Result.isSuccess())1014    return Result;1015  if (Result.isFailure()) {1016    Parser.eatToEndOfStatement();1017    return Result;1018  }1019 1020  // Attempt to parse token as register1021  std::unique_ptr<LanaiOperand> Op = parseRegister();1022 1023  // Attempt to parse token as immediate1024  if (!Op)1025    Op = parseImmediate();1026 1027  // If the token could not be parsed then fail1028  if (!Op) {1029    Error(Parser.getTok().getLoc(), "Unknown operand");1030    Parser.eatToEndOfStatement();1031    return ParseStatus::Failure;1032  }1033 1034  // Push back parsed operand into list of operands1035  Operands->push_back(std::move(Op));1036 1037  return ParseStatus::Success;1038}1039 1040// Split the mnemonic into ASM operand, conditional code and instruction1041// qualifier (half-word, byte).1042StringRef LanaiAsmParser::splitMnemonic(StringRef Name, SMLoc NameLoc,1043                                        OperandVector *Operands) {1044  size_t Next = Name.find('.');1045 1046  StringRef Mnemonic = Name;1047 1048  bool IsBRR = Mnemonic.consume_back(".r");1049 1050  // Match b?? and s?? (BR, BRR, and SCC instruction classes).1051  if (Mnemonic[0] == 'b' ||1052      (Mnemonic[0] == 's' && !Mnemonic.starts_with("sel") &&1053       !Mnemonic.starts_with("st"))) {1054    // Parse instructions with a conditional code. For example, 'bne' is1055    // converted into two operands 'b' and 'ne'.1056    LPCC::CondCode CondCode =1057        LPCC::suffixToLanaiCondCode(Mnemonic.substr(1, Next));1058    if (CondCode != LPCC::UNKNOWN) {1059      Mnemonic = Mnemonic.slice(0, 1);1060      Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));1061      Operands->push_back(LanaiOperand::createImm(1062          MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));1063      if (IsBRR) {1064        Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));1065      }1066      return Mnemonic;1067    }1068  }1069 1070  // Parse other instructions with condition codes (RR instructions).1071  // We ignore .f here and assume they are flag-setting operations, not1072  // conditional codes (except for select instructions where flag-setting1073  // variants are not yet implemented).1074  if (Mnemonic.starts_with("sel") ||1075      (!Mnemonic.ends_with(".f") && !Mnemonic.starts_with("st"))) {1076    LPCC::CondCode CondCode = LPCC::suffixToLanaiCondCode(Mnemonic);1077    if (CondCode != LPCC::UNKNOWN) {1078      size_t Next = Mnemonic.rfind('.', Name.size());1079      // 'sel' doesn't use a predicate operand whose printer adds the period,1080      // but instead has the period as part of the identifier (i.e., 'sel.' is1081      // expected by the generated matcher). If the mnemonic starts with 'sel'1082      // then include the period as part of the mnemonic, else don't include it1083      // as part of the mnemonic.1084      if (Mnemonic.starts_with("sel")) {1085        Mnemonic = Mnemonic.substr(0, Next + 1);1086      } else {1087        Mnemonic = Mnemonic.substr(0, Next);1088      }1089      Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));1090      Operands->push_back(LanaiOperand::createImm(1091          MCConstantExpr::create(CondCode, getContext()), NameLoc, NameLoc));1092      return Mnemonic;1093    }1094  }1095 1096  Operands->push_back(LanaiOperand::CreateToken(Mnemonic, NameLoc));1097  if (IsBRR) {1098    Operands->push_back(LanaiOperand::CreateToken(".r", NameLoc));1099  }1100 1101  return Mnemonic;1102}1103 1104static bool IsMemoryAssignmentError(const OperandVector &Operands) {1105  // Detects if a memory operation has an erroneous base register modification.1106  // Memory operations are detected by matching the types of operands.1107  //1108  // TODO: This test is focussed on one specific instance (ld/st).1109  // Extend it to handle more cases or be more robust.1110  bool Modifies = false;1111 1112  int Offset = 0;1113 1114  if (Operands.size() < 5)1115    return false;1116  else if (Operands[0]->isToken() && Operands[1]->isReg() &&1117           Operands[2]->isImm() && Operands[3]->isImm() && Operands[4]->isReg())1118    Offset = 0;1119  else if (Operands[0]->isToken() && Operands[1]->isToken() &&1120           Operands[2]->isReg() && Operands[3]->isImm() &&1121           Operands[4]->isImm() && Operands[5]->isReg())1122    Offset = 1;1123  else1124    return false;1125 1126  int PossibleAluOpIdx = Offset + 3;1127  int PossibleBaseIdx = Offset + 1;1128  int PossibleDestIdx = Offset + 4;1129  if (LanaiOperand *PossibleAluOp =1130          static_cast<LanaiOperand *>(Operands[PossibleAluOpIdx].get()))1131    if (PossibleAluOp->isImm())1132      if (const MCConstantExpr *ConstExpr =1133              dyn_cast<MCConstantExpr>(PossibleAluOp->getImm()))1134        Modifies = LPAC::modifiesOp(ConstExpr->getValue());1135  return Modifies && Operands[PossibleBaseIdx]->isReg() &&1136         Operands[PossibleDestIdx]->isReg() &&1137         Operands[PossibleBaseIdx]->getReg() ==1138             Operands[PossibleDestIdx]->getReg();1139}1140 1141static bool IsRegister(const MCParsedAsmOperand &op) {1142  return static_cast<const LanaiOperand &>(op).isReg();1143}1144 1145static bool MaybePredicatedInst(const OperandVector &Operands) {1146  if (Operands.size() < 4 || !IsRegister(*Operands[1]) ||1147      !IsRegister(*Operands[2]))1148    return false;1149  return StringSwitch<bool>(1150             static_cast<const LanaiOperand &>(*Operands[0]).getToken())1151      .StartsWith("addc", true)1152      .StartsWith("add", true)1153      .StartsWith("and", true)1154      .StartsWith("sh", true)1155      .StartsWith("subb", true)1156      .StartsWith("sub", true)1157      .StartsWith("or", true)1158      .StartsWith("xor", true)1159      .Default(false);1160}1161 1162bool LanaiAsmParser::parseInstruction(ParseInstructionInfo & /*Info*/,1163                                      StringRef Name, SMLoc NameLoc,1164                                      OperandVector &Operands) {1165  // First operand is token for instruction1166  StringRef Mnemonic = splitMnemonic(Name, NameLoc, &Operands);1167 1168  // If there are no more operands, then finish1169  if (Lexer.is(AsmToken::EndOfStatement))1170    return false;1171 1172  // Parse first operand1173  if (!parseOperand(&Operands, Mnemonic).isSuccess())1174    return true;1175 1176  // If it is a st instruction with one 1 operand then it is a "store true".1177  // Transform <"st"> to <"s">, <LPCC:ICC_T>1178  if (Lexer.is(AsmToken::EndOfStatement) && Name == "st" &&1179      Operands.size() == 2) {1180    Operands.erase(Operands.begin(), Operands.begin() + 1);1181    Operands.insert(Operands.begin(), LanaiOperand::CreateToken("s", NameLoc));1182    Operands.insert(Operands.begin() + 1,1183                    LanaiOperand::createImm(1184                        MCConstantExpr::create(LPCC::ICC_T, getContext()),1185                        NameLoc, NameLoc));1186  }1187 1188  // If the instruction is a bt instruction with 1 operand (in assembly) then it1189  // is an unconditional branch instruction and the first two elements of1190  // operands need to be merged.1191  if (Lexer.is(AsmToken::EndOfStatement) && Name.starts_with("bt") &&1192      Operands.size() == 3) {1193    Operands.erase(Operands.begin(), Operands.begin() + 2);1194    Operands.insert(Operands.begin(), LanaiOperand::CreateToken("bt", NameLoc));1195  }1196 1197  // Parse until end of statement, consuming commas between operands1198  while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.is(AsmToken::Comma)) {1199    // Consume comma token1200    Lex();1201 1202    // Parse next operand1203    if (!parseOperand(&Operands, Mnemonic).isSuccess())1204      return true;1205  }1206 1207  if (IsMemoryAssignmentError(Operands)) {1208    Error(Parser.getTok().getLoc(),1209          "the destination register can't equal the base register in an "1210          "instruction that modifies the base register.");1211    return true;1212  }1213 1214  // Insert always true operand for instruction that may be predicated but1215  // are not. Currently the autogenerated parser always expects a predicate.1216  if (MaybePredicatedInst(Operands)) {1217    Operands.insert(Operands.begin() + 1,1218                    LanaiOperand::createImm(1219                        MCConstantExpr::create(LPCC::ICC_T, getContext()),1220                        NameLoc, NameLoc));1221  }1222 1223  return false;1224}1225 1226#define GET_REGISTER_MATCHER1227#define GET_MATCHER_IMPLEMENTATION1228#include "LanaiGenAsmMatcher.inc"1229 1230extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void1231LLVMInitializeLanaiAsmParser() {1232  RegisterMCAsmParser<LanaiAsmParser> x(getTheLanaiTarget());1233}1234