| //===-- 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); |
| } |