//===-- X86AsmLexer.cpp - Tokenize X86 assembly to AsmTokens --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/X86BaseInfo.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCTargetAsmLexer.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"

using namespace llvm;

namespace {
  
class X86AsmLexer : public MCTargetAsmLexer {
  const MCAsmInfo &AsmInfo;
  
  bool tentativeIsValid;
  AsmToken tentativeToken;
  
  const AsmToken &lexTentative() {
    tentativeToken = getLexer()->Lex();
    tentativeIsValid = true;
    return tentativeToken;
  }
  
  const AsmToken &lexDefinite() {
    if (tentativeIsValid) {
      tentativeIsValid = false;
      return tentativeToken;
    }
    return getLexer()->Lex();
  }
  
  AsmToken LexTokenATT();
  AsmToken LexTokenIntel();
protected:
  AsmToken LexToken() {
    if (!Lexer) {
      SetError(SMLoc(), "No MCAsmLexer installed");
      return AsmToken(AsmToken::Error, "", 0);
    }
    
    switch (AsmInfo.getAssemblerDialect()) {
    default:
      SetError(SMLoc(), "Unhandled dialect");
      return AsmToken(AsmToken::Error, "", 0);
    case 0:
      return LexTokenATT();
    case 1:
      return LexTokenIntel();
    }
  }
public:
  X86AsmLexer(const Target &T, const MCRegisterInfo &MRI, const MCAsmInfo &MAI)
    : MCTargetAsmLexer(T), AsmInfo(MAI), tentativeIsValid(false) {
  }
};

} // end anonymous namespace

#define GET_REGISTER_MATCHER
#include "X86GenAsmMatcher.inc"

AsmToken X86AsmLexer::LexTokenATT() {
  AsmToken lexedToken = lexDefinite();
  
  switch (lexedToken.getKind()) {
  default:
    return lexedToken;
  case AsmToken::Error:
    SetError(Lexer->getErrLoc(), Lexer->getErr());
    return lexedToken;
      
  case AsmToken::Percent: {
    const AsmToken &nextToken = lexTentative();
    if (nextToken.getKind() != AsmToken::Identifier)
      return lexedToken;

      
    if (unsigned regID = MatchRegisterName(nextToken.getString())) {
      lexDefinite();
        
      // FIXME: This is completely wrong when there is a space or other
      // punctuation between the % and the register name.
      StringRef regStr(lexedToken.getString().data(),
                       lexedToken.getString().size() + 
                       nextToken.getString().size());
      
      return AsmToken(AsmToken::Register, regStr, 
                      static_cast<int64_t>(regID));
    }
    
    // Match register name failed.  If this is "db[0-7]", match it as an alias
    // for dr[0-7].
    if (nextToken.getString().size() == 3 &&
        nextToken.getString().startswith("db")) {
      int RegNo = -1;
      switch (nextToken.getString()[2]) {
      case '0': RegNo = X86::DR0; break;
      case '1': RegNo = X86::DR1; break;
      case '2': RegNo = X86::DR2; break;
      case '3': RegNo = X86::DR3; break;
      case '4': RegNo = X86::DR4; break;
      case '5': RegNo = X86::DR5; break;
      case '6': RegNo = X86::DR6; break;
      case '7': RegNo = X86::DR7; break;
      }
      
      if (RegNo != -1) {
        lexDefinite();

        // FIXME: This is completely wrong when there is a space or other
        // punctuation between the % and the register name.
        StringRef regStr(lexedToken.getString().data(),
                         lexedToken.getString().size() + 
                         nextToken.getString().size());
        return AsmToken(AsmToken::Register, regStr, 
                        static_cast<int64_t>(RegNo));
      }
    }
      
   
    return lexedToken;
  }    
  }
}

AsmToken X86AsmLexer::LexTokenIntel() {
  const AsmToken &lexedToken = lexDefinite();
  
  switch(lexedToken.getKind()) {
  default:
    return lexedToken;
  case AsmToken::Error:
    SetError(Lexer->getErrLoc(), Lexer->getErr());
    return lexedToken;
  case AsmToken::Identifier: {
    std::string upperCase = lexedToken.getString().str();
    std::string lowerCase = LowercaseString(upperCase);
    StringRef lowerRef(lowerCase);
    
    unsigned regID = MatchRegisterName(lowerRef);
    
    if (regID)
      return AsmToken(AsmToken::Register,
                      lexedToken.getString(),
                      static_cast<int64_t>(regID));
    return lexedToken;
  }
  }
}

extern "C" void LLVMInitializeX86AsmLexer() {
  RegisterMCAsmLexer<X86AsmLexer> X(TheX86_32Target);
  RegisterMCAsmLexer<X86AsmLexer> Y(TheX86_64Target);
}
