Home | History | Annotate | Download | only in AsmParser
      1 //===-- MBlazeAsmParser.cpp - Parse MBlaze asm to MCInst instructions -----===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "MCTargetDesc/MBlazeBaseInfo.h"
     11 #include "llvm/MC/MCParser/MCAsmLexer.h"
     12 #include "llvm/MC/MCParser/MCAsmParser.h"
     13 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
     14 #include "llvm/MC/MCStreamer.h"
     15 #include "llvm/MC/MCExpr.h"
     16 #include "llvm/MC/MCInst.h"
     17 #include "llvm/MC/MCTargetAsmParser.h"
     18 #include "llvm/Support/SourceMgr.h"
     19 #include "llvm/Support/TargetRegistry.h"
     20 #include "llvm/Support/raw_ostream.h"
     21 #include "llvm/ADT/SmallVector.h"
     22 #include "llvm/ADT/Twine.h"
     23 using namespace llvm;
     24 
     25 namespace {
     26 struct MBlazeOperand;
     27 
     28 class MBlazeAsmParser : public MCTargetAsmParser {
     29   MCAsmParser &Parser;
     30 
     31   MCAsmParser &getParser() const { return Parser; }
     32   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
     33 
     34   void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
     35   bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
     36 
     37   MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
     38   MBlazeOperand *ParseRegister(unsigned &RegNo);
     39   MBlazeOperand *ParseImmediate();
     40   MBlazeOperand *ParseFsl();
     41   MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
     42 
     43   virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
     44 
     45   bool ParseDirectiveWord(unsigned Size, SMLoc L);
     46 
     47   bool MatchAndEmitInstruction(SMLoc IDLoc,
     48                                SmallVectorImpl<MCParsedAsmOperand*> &Operands,
     49                                MCStreamer &Out);
     50 
     51   /// @name Auto-generated Match Functions
     52   /// {
     53 
     54 #define GET_ASSEMBLER_HEADER
     55 #include "MBlazeGenAsmMatcher.inc"
     56 
     57   /// }
     58 
     59   unsigned getMCInstOperandNum(unsigned Kind, MCInst &Inst,
     60                     const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
     61                                unsigned OperandNum, unsigned &NumMCOperands) {
     62     return getMCInstOperandNumImpl(Kind, Inst, Operands, OperandNum,
     63                                    NumMCOperands);
     64   }
     65 
     66 public:
     67   MBlazeAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
     68     : MCTargetAsmParser(), Parser(_Parser) {}
     69 
     70   virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
     71                                 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
     72 
     73   virtual bool ParseDirective(AsmToken DirectiveID);
     74 };
     75 
     76 /// MBlazeOperand - Instances of this class represent a parsed MBlaze machine
     77 /// instruction.
     78 struct MBlazeOperand : public MCParsedAsmOperand {
     79   enum KindTy {
     80     Token,
     81     Immediate,
     82     Register,
     83     Memory,
     84     Fsl
     85   } Kind;
     86 
     87   SMLoc StartLoc, EndLoc;
     88 
     89   union {
     90     struct {
     91       const char *Data;
     92       unsigned Length;
     93     } Tok;
     94 
     95     struct {
     96       unsigned RegNum;
     97     } Reg;
     98 
     99     struct {
    100       const MCExpr *Val;
    101     } Imm;
    102 
    103     struct {
    104       unsigned Base;
    105       unsigned OffReg;
    106       const MCExpr *Off;
    107     } Mem;
    108 
    109     struct {
    110       const MCExpr *Val;
    111     } FslImm;
    112   };
    113 
    114   MBlazeOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
    115 public:
    116   MBlazeOperand(const MBlazeOperand &o) : MCParsedAsmOperand() {
    117     Kind = o.Kind;
    118     StartLoc = o.StartLoc;
    119     EndLoc = o.EndLoc;
    120     switch (Kind) {
    121     case Register:
    122       Reg = o.Reg;
    123       break;
    124     case Immediate:
    125       Imm = o.Imm;
    126       break;
    127     case Token:
    128       Tok = o.Tok;
    129       break;
    130     case Memory:
    131       Mem = o.Mem;
    132       break;
    133     case Fsl:
    134       FslImm = o.FslImm;
    135       break;
    136     }
    137   }
    138 
    139   /// getStartLoc - Get the location of the first token of this operand.
    140   SMLoc getStartLoc() const { return StartLoc; }
    141 
    142   /// getEndLoc - Get the location of the last token of this operand.
    143   SMLoc getEndLoc() const { return EndLoc; }
    144 
    145   unsigned getReg() const {
    146     assert(Kind == Register && "Invalid access!");
    147     return Reg.RegNum;
    148   }
    149 
    150   const MCExpr *getImm() const {
    151     assert(Kind == Immediate && "Invalid access!");
    152     return Imm.Val;
    153   }
    154 
    155   const MCExpr *getFslImm() const {
    156     assert(Kind == Fsl && "Invalid access!");
    157     return FslImm.Val;
    158   }
    159 
    160   unsigned getMemBase() const {
    161     assert(Kind == Memory && "Invalid access!");
    162     return Mem.Base;
    163   }
    164 
    165   const MCExpr* getMemOff() const {
    166     assert(Kind == Memory && "Invalid access!");
    167     return Mem.Off;
    168   }
    169 
    170   unsigned getMemOffReg() const {
    171     assert(Kind == Memory && "Invalid access!");
    172     return Mem.OffReg;
    173   }
    174 
    175   bool isToken() const { return Kind == Token; }
    176   bool isImm() const { return Kind == Immediate; }
    177   bool isMem() const { return Kind == Memory; }
    178   bool isFsl() const { return Kind == Fsl; }
    179   bool isReg() const { return Kind == Register; }
    180 
    181   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
    182     // Add as immediates when possible.  Null MCExpr = 0.
    183     if (Expr == 0)
    184       Inst.addOperand(MCOperand::CreateImm(0));
    185     else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
    186       Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
    187     else
    188       Inst.addOperand(MCOperand::CreateExpr(Expr));
    189   }
    190 
    191   void addRegOperands(MCInst &Inst, unsigned N) const {
    192     assert(N == 1 && "Invalid number of operands!");
    193     Inst.addOperand(MCOperand::CreateReg(getReg()));
    194   }
    195 
    196   void addImmOperands(MCInst &Inst, unsigned N) const {
    197     assert(N == 1 && "Invalid number of operands!");
    198     addExpr(Inst, getImm());
    199   }
    200 
    201   void addFslOperands(MCInst &Inst, unsigned N) const {
    202     assert(N == 1 && "Invalid number of operands!");
    203     addExpr(Inst, getFslImm());
    204   }
    205 
    206   void addMemOperands(MCInst &Inst, unsigned N) const {
    207     assert(N == 2 && "Invalid number of operands!");
    208 
    209     Inst.addOperand(MCOperand::CreateReg(getMemBase()));
    210 
    211     unsigned RegOff = getMemOffReg();
    212     if (RegOff)
    213       Inst.addOperand(MCOperand::CreateReg(RegOff));
    214     else
    215       addExpr(Inst, getMemOff());
    216   }
    217 
    218   StringRef getToken() const {
    219     assert(Kind == Token && "Invalid access!");
    220     return StringRef(Tok.Data, Tok.Length);
    221   }
    222 
    223   virtual void print(raw_ostream &OS) const;
    224 
    225   static MBlazeOperand *CreateToken(StringRef Str, SMLoc S) {
    226     MBlazeOperand *Op = new MBlazeOperand(Token);
    227     Op->Tok.Data = Str.data();
    228     Op->Tok.Length = Str.size();
    229     Op->StartLoc = S;
    230     Op->EndLoc = S;
    231     return Op;
    232   }
    233 
    234   static MBlazeOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
    235     MBlazeOperand *Op = new MBlazeOperand(Register);
    236     Op->Reg.RegNum = RegNum;
    237     Op->StartLoc = S;
    238     Op->EndLoc = E;
    239     return Op;
    240   }
    241 
    242   static MBlazeOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
    243     MBlazeOperand *Op = new MBlazeOperand(Immediate);
    244     Op->Imm.Val = Val;
    245     Op->StartLoc = S;
    246     Op->EndLoc = E;
    247     return Op;
    248   }
    249 
    250   static MBlazeOperand *CreateFslImm(const MCExpr *Val, SMLoc S, SMLoc E) {
    251     MBlazeOperand *Op = new MBlazeOperand(Fsl);
    252     Op->Imm.Val = Val;
    253     Op->StartLoc = S;
    254     Op->EndLoc = E;
    255     return Op;
    256   }
    257 
    258   static MBlazeOperand *CreateMem(unsigned Base, const MCExpr *Off, SMLoc S,
    259                                   SMLoc E) {
    260     MBlazeOperand *Op = new MBlazeOperand(Memory);
    261     Op->Mem.Base = Base;
    262     Op->Mem.Off = Off;
    263     Op->Mem.OffReg = 0;
    264     Op->StartLoc = S;
    265     Op->EndLoc = E;
    266     return Op;
    267   }
    268 
    269   static MBlazeOperand *CreateMem(unsigned Base, unsigned Off, SMLoc S,
    270                                   SMLoc E) {
    271     MBlazeOperand *Op = new MBlazeOperand(Memory);
    272     Op->Mem.Base = Base;
    273     Op->Mem.OffReg = Off;
    274     Op->Mem.Off = 0;
    275     Op->StartLoc = S;
    276     Op->EndLoc = E;
    277     return Op;
    278   }
    279 };
    280 
    281 } // end anonymous namespace.
    282 
    283 void MBlazeOperand::print(raw_ostream &OS) const {
    284   switch (Kind) {
    285   case Immediate:
    286     getImm()->print(OS);
    287     break;
    288   case Register:
    289     OS << "<register R";
    290     OS << getMBlazeRegisterNumbering(getReg()) << ">";
    291     break;
    292   case Token:
    293     OS << "'" << getToken() << "'";
    294     break;
    295   case Memory: {
    296     OS << "<memory R";
    297     OS << getMBlazeRegisterNumbering(getMemBase());
    298     OS << ", ";
    299 
    300     unsigned RegOff = getMemOffReg();
    301     if (RegOff)
    302       OS << "R" << getMBlazeRegisterNumbering(RegOff);
    303     else
    304       OS << getMemOff();
    305     OS << ">";
    306     }
    307     break;
    308   case Fsl:
    309     getFslImm()->print(OS);
    310     break;
    311   }
    312 }
    313 
    314 /// @name Auto-generated Match Functions
    315 /// {
    316 
    317 static unsigned MatchRegisterName(StringRef Name);
    318 
    319 /// }
    320 //
    321 bool MBlazeAsmParser::
    322 MatchAndEmitInstruction(SMLoc IDLoc,
    323                         SmallVectorImpl<MCParsedAsmOperand*> &Operands,
    324                         MCStreamer &Out) {
    325   MCInst Inst;
    326   unsigned Kind;
    327   unsigned ErrorInfo;
    328 
    329   switch (MatchInstructionImpl(Operands, Kind, Inst, ErrorInfo)) {
    330   default: break;
    331   case Match_Success:
    332     Out.EmitInstruction(Inst);
    333     return false;
    334   case Match_MissingFeature:
    335     return Error(IDLoc, "instruction use requires an option to be enabled");
    336   case Match_MnemonicFail:
    337       return Error(IDLoc, "unrecognized instruction mnemonic");
    338   case Match_InvalidOperand: {
    339     SMLoc ErrorLoc = IDLoc;
    340     if (ErrorInfo != ~0U) {
    341       if (ErrorInfo >= Operands.size())
    342         return Error(IDLoc, "too few operands for instruction");
    343 
    344       ErrorLoc = ((MBlazeOperand*)Operands[ErrorInfo])->getStartLoc();
    345       if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
    346     }
    347 
    348     return Error(ErrorLoc, "invalid operand for instruction");
    349   }
    350   }
    351 
    352   llvm_unreachable("Implement any new match types added!");
    353 }
    354 
    355 MBlazeOperand *MBlazeAsmParser::
    356 ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
    357   if (Operands.size() != 4)
    358     return 0;
    359 
    360   MBlazeOperand &Base = *(MBlazeOperand*)Operands[2];
    361   MBlazeOperand &Offset = *(MBlazeOperand*)Operands[3];
    362 
    363   SMLoc S = Base.getStartLoc();
    364   SMLoc O = Offset.getStartLoc();
    365   SMLoc E = Offset.getEndLoc();
    366 
    367   if (!Base.isReg()) {
    368     Error(S, "base address must be a register");
    369     return 0;
    370   }
    371 
    372   if (!Offset.isReg() && !Offset.isImm()) {
    373     Error(O, "offset must be a register or immediate");
    374     return 0;
    375   }
    376 
    377   MBlazeOperand *Op;
    378   if (Offset.isReg())
    379     Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getReg(), S, E);
    380   else
    381     Op = MBlazeOperand::CreateMem(Base.getReg(), Offset.getImm(), S, E);
    382 
    383   delete Operands.pop_back_val();
    384   delete Operands.pop_back_val();
    385   Operands.push_back(Op);
    386 
    387   return Op;
    388 }
    389 
    390 bool MBlazeAsmParser::ParseRegister(unsigned &RegNo,
    391                                     SMLoc &StartLoc, SMLoc &EndLoc) {
    392   return (ParseRegister(RegNo) == 0);
    393 }
    394 
    395 MBlazeOperand *MBlazeAsmParser::ParseRegister(unsigned &RegNo) {
    396   SMLoc S = Parser.getTok().getLoc();
    397   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
    398 
    399   switch (getLexer().getKind()) {
    400   default: return 0;
    401   case AsmToken::Identifier:
    402     RegNo = MatchRegisterName(getLexer().getTok().getIdentifier());
    403     if (RegNo == 0)
    404       return 0;
    405 
    406     getLexer().Lex();
    407     return MBlazeOperand::CreateReg(RegNo, S, E);
    408   }
    409 }
    410 
    411 static unsigned MatchFslRegister(StringRef String) {
    412   if (!String.startswith("rfsl"))
    413     return -1;
    414 
    415   unsigned regNum;
    416   if (String.substr(4).getAsInteger(10,regNum))
    417     return -1;
    418 
    419   return regNum;
    420 }
    421 
    422 MBlazeOperand *MBlazeAsmParser::ParseFsl() {
    423   SMLoc S = Parser.getTok().getLoc();
    424   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
    425 
    426   switch (getLexer().getKind()) {
    427   default: return 0;
    428   case AsmToken::Identifier:
    429     unsigned reg = MatchFslRegister(getLexer().getTok().getIdentifier());
    430     if (reg >= 16)
    431       return 0;
    432 
    433     getLexer().Lex();
    434     const MCExpr *EVal = MCConstantExpr::Create(reg,getContext());
    435     return MBlazeOperand::CreateFslImm(EVal,S,E);
    436   }
    437 }
    438 
    439 MBlazeOperand *MBlazeAsmParser::ParseImmediate() {
    440   SMLoc S = Parser.getTok().getLoc();
    441   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
    442 
    443   const MCExpr *EVal;
    444   switch (getLexer().getKind()) {
    445   default: return 0;
    446   case AsmToken::LParen:
    447   case AsmToken::Plus:
    448   case AsmToken::Minus:
    449   case AsmToken::Integer:
    450   case AsmToken::Identifier:
    451     if (getParser().ParseExpression(EVal))
    452       return 0;
    453 
    454     return MBlazeOperand::CreateImm(EVal, S, E);
    455   }
    456 }
    457 
    458 MBlazeOperand *MBlazeAsmParser::
    459 ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
    460   MBlazeOperand *Op;
    461 
    462   // Attempt to parse the next token as a register name
    463   unsigned RegNo;
    464   Op = ParseRegister(RegNo);
    465 
    466   // Attempt to parse the next token as an FSL immediate
    467   if (!Op)
    468     Op = ParseFsl();
    469 
    470   // Attempt to parse the next token as an immediate
    471   if (!Op)
    472     Op = ParseImmediate();
    473 
    474   // If the token could not be parsed then fail
    475   if (!Op) {
    476     Error(Parser.getTok().getLoc(), "unknown operand");
    477     return 0;
    478   }
    479 
    480   // Push the parsed operand into the list of operands
    481   Operands.push_back(Op);
    482   return Op;
    483 }
    484 
    485 /// Parse an mblaze instruction mnemonic followed by its operands.
    486 bool MBlazeAsmParser::
    487 ParseInstruction(StringRef Name, SMLoc NameLoc,
    488                  SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
    489   // The first operands is the token for the instruction name
    490   size_t dotLoc = Name.find('.');
    491   Operands.push_back(MBlazeOperand::CreateToken(Name.substr(0,dotLoc),NameLoc));
    492   if (dotLoc < Name.size())
    493     Operands.push_back(MBlazeOperand::CreateToken(Name.substr(dotLoc),NameLoc));
    494 
    495   // If there are no more operands then finish
    496   if (getLexer().is(AsmToken::EndOfStatement))
    497     return false;
    498 
    499   // Parse the first operand
    500   if (!ParseOperand(Operands))
    501     return true;
    502 
    503   while (getLexer().isNot(AsmToken::EndOfStatement) &&
    504          getLexer().is(AsmToken::Comma)) {
    505     // Consume the comma token
    506     getLexer().Lex();
    507 
    508     // Parse the next operand
    509     if (!ParseOperand(Operands))
    510       return true;
    511   }
    512 
    513   // If the instruction requires a memory operand then we need to
    514   // replace the last two operands (base+offset) with a single
    515   // memory operand.
    516   if (Name.startswith("lw") || Name.startswith("sw") ||
    517       Name.startswith("lh") || Name.startswith("sh") ||
    518       Name.startswith("lb") || Name.startswith("sb"))
    519     return (ParseMemory(Operands) == NULL);
    520 
    521   return false;
    522 }
    523 
    524 /// ParseDirective parses the MBlaze specific directives
    525 bool MBlazeAsmParser::ParseDirective(AsmToken DirectiveID) {
    526   StringRef IDVal = DirectiveID.getIdentifier();
    527   if (IDVal == ".word")
    528     return ParseDirectiveWord(2, DirectiveID.getLoc());
    529   return true;
    530 }
    531 
    532 /// ParseDirectiveWord
    533 ///  ::= .word [ expression (, expression)* ]
    534 bool MBlazeAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
    535   if (getLexer().isNot(AsmToken::EndOfStatement)) {
    536     for (;;) {
    537       const MCExpr *Value;
    538       if (getParser().ParseExpression(Value))
    539         return true;
    540 
    541       getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
    542 
    543       if (getLexer().is(AsmToken::EndOfStatement))
    544         break;
    545 
    546       // FIXME: Improve diagnostic.
    547       if (getLexer().isNot(AsmToken::Comma))
    548         return Error(L, "unexpected token in directive");
    549       Parser.Lex();
    550     }
    551   }
    552 
    553   Parser.Lex();
    554   return false;
    555 }
    556 
    557 extern "C" void LLVMInitializeMBlazeAsmLexer();
    558 
    559 /// Force static initialization.
    560 extern "C" void LLVMInitializeMBlazeAsmParser() {
    561   RegisterMCAsmParser<MBlazeAsmParser> X(TheMBlazeTarget);
    562   LLVMInitializeMBlazeAsmLexer();
    563 }
    564 
    565 #define GET_REGISTER_MATCHER
    566 #define GET_MATCHER_IMPLEMENTATION
    567 #include "MBlazeGenAsmMatcher.inc"
    568