Home | History | Annotate | Download | only in AsmParser
      1 //===-- X86AsmLexer.cpp - Tokenize X86 assembly to AsmTokens --------------===//
      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/X86BaseInfo.h"
     11 #include "llvm/MC/MCAsmInfo.h"
     12 #include "llvm/MC/MCParser/MCAsmLexer.h"
     13 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
     14 #include "llvm/MC/MCTargetAsmLexer.h"
     15 #include "llvm/Support/TargetRegistry.h"
     16 #include "llvm/ADT/SmallVector.h"
     17 #include "llvm/ADT/StringExtras.h"
     18 
     19 using namespace llvm;
     20 
     21 namespace {
     22 
     23 class X86AsmLexer : public MCTargetAsmLexer {
     24   const MCAsmInfo &AsmInfo;
     25 
     26   bool tentativeIsValid;
     27   AsmToken tentativeToken;
     28 
     29   const AsmToken &lexTentative() {
     30     tentativeToken = getLexer()->Lex();
     31     tentativeIsValid = true;
     32     return tentativeToken;
     33   }
     34 
     35   const AsmToken &lexDefinite() {
     36     if (tentativeIsValid) {
     37       tentativeIsValid = false;
     38       return tentativeToken;
     39     }
     40     return getLexer()->Lex();
     41   }
     42 
     43   AsmToken LexTokenATT();
     44   AsmToken LexTokenIntel();
     45 protected:
     46   AsmToken LexToken() {
     47     if (!Lexer) {
     48       SetError(SMLoc(), "No MCAsmLexer installed");
     49       return AsmToken(AsmToken::Error, "", 0);
     50     }
     51 
     52     switch (AsmInfo.getAssemblerDialect()) {
     53     default:
     54       SetError(SMLoc(), "Unhandled dialect");
     55       return AsmToken(AsmToken::Error, "", 0);
     56     case 0:
     57       return LexTokenATT();
     58     case 1:
     59       return LexTokenIntel();
     60     }
     61   }
     62 public:
     63   X86AsmLexer(const Target &T, const MCRegisterInfo &MRI, const MCAsmInfo &MAI)
     64     : MCTargetAsmLexer(T), AsmInfo(MAI), tentativeIsValid(false) {
     65   }
     66 };
     67 
     68 } // end anonymous namespace
     69 
     70 #define GET_REGISTER_MATCHER
     71 #include "X86GenAsmMatcher.inc"
     72 
     73 AsmToken X86AsmLexer::LexTokenATT() {
     74   AsmToken lexedToken = lexDefinite();
     75 
     76   switch (lexedToken.getKind()) {
     77   default:
     78     return lexedToken;
     79   case AsmToken::Error:
     80     SetError(Lexer->getErrLoc(), Lexer->getErr());
     81     return lexedToken;
     82 
     83   case AsmToken::Percent: {
     84     const AsmToken &nextToken = lexTentative();
     85     if (nextToken.getKind() != AsmToken::Identifier)
     86       return lexedToken;
     87 
     88 
     89     if (unsigned regID = MatchRegisterName(nextToken.getString())) {
     90       lexDefinite();
     91 
     92       // FIXME: This is completely wrong when there is a space or other
     93       // punctuation between the % and the register name.
     94       StringRef regStr(lexedToken.getString().data(),
     95                        lexedToken.getString().size() +
     96                        nextToken.getString().size());
     97 
     98       return AsmToken(AsmToken::Register, regStr,
     99                       static_cast<int64_t>(regID));
    100     }
    101 
    102     // Match register name failed.  If this is "db[0-7]", match it as an alias
    103     // for dr[0-7].
    104     if (nextToken.getString().size() == 3 &&
    105         nextToken.getString().startswith("db")) {
    106       int RegNo = -1;
    107       switch (nextToken.getString()[2]) {
    108       case '0': RegNo = X86::DR0; break;
    109       case '1': RegNo = X86::DR1; break;
    110       case '2': RegNo = X86::DR2; break;
    111       case '3': RegNo = X86::DR3; break;
    112       case '4': RegNo = X86::DR4; break;
    113       case '5': RegNo = X86::DR5; break;
    114       case '6': RegNo = X86::DR6; break;
    115       case '7': RegNo = X86::DR7; break;
    116       }
    117 
    118       if (RegNo != -1) {
    119         lexDefinite();
    120 
    121         // FIXME: This is completely wrong when there is a space or other
    122         // punctuation between the % and the register name.
    123         StringRef regStr(lexedToken.getString().data(),
    124                          lexedToken.getString().size() +
    125                          nextToken.getString().size());
    126         return AsmToken(AsmToken::Register, regStr,
    127                         static_cast<int64_t>(RegNo));
    128       }
    129     }
    130 
    131 
    132     return lexedToken;
    133   }
    134   }
    135 }
    136 
    137 AsmToken X86AsmLexer::LexTokenIntel() {
    138   const AsmToken &lexedToken = lexDefinite();
    139 
    140   switch(lexedToken.getKind()) {
    141   default:
    142     return lexedToken;
    143   case AsmToken::Error:
    144     SetError(Lexer->getErrLoc(), Lexer->getErr());
    145     return lexedToken;
    146   case AsmToken::Identifier: {
    147     std::string upperCase = lexedToken.getString().str();
    148     std::string lowerCase = LowercaseString(upperCase);
    149     StringRef lowerRef(lowerCase);
    150 
    151     unsigned regID = MatchRegisterName(lowerRef);
    152 
    153     if (regID)
    154       return AsmToken(AsmToken::Register,
    155                       lexedToken.getString(),
    156                       static_cast<int64_t>(regID));
    157     return lexedToken;
    158   }
    159   }
    160 }
    161 
    162 extern "C" void LLVMInitializeX86AsmLexer() {
    163   RegisterMCAsmLexer<X86AsmLexer> X(TheX86_32Target);
    164   RegisterMCAsmLexer<X86AsmLexer> Y(TheX86_64Target);
    165 }
    166