//===-- 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 "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Target/TargetAsmLexer.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "X86.h" using namespace llvm; namespace { class X86AsmLexer : public TargetAsmLexer { 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 MCAsmInfo &MAI) : TargetAsmLexer(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(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(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(regID)); return lexedToken; } } } extern "C" void LLVMInitializeX86AsmLexer() { RegisterAsmLexer X(TheX86_32Target); RegisterAsmLexer Y(TheX86_64Target); }