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