1e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan//===-- X86AsmLexer.cpp - Tokenize X86 assembly to AsmTokens --------------===//
2e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan//
3e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan//                     The LLVM Compiler Infrastructure
4e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan//
5e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan// This file is distributed under the University of Illinois Open Source
6e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan// License. See LICENSE.TXT for details.
7e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan//
8e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan//===----------------------------------------------------------------------===//
9e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan
1094b9550a32d189704a8eae55505edf62662c0534Evan Cheng#include "MCTargetDesc/X86BaseInfo.h"
11436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan#include "llvm/MC/MCAsmInfo.h"
12e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan#include "llvm/MC/MCParser/MCAsmLexer.h"
13e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
1494b9550a32d189704a8eae55505edf62662c0534Evan Cheng#include "llvm/MC/MCTargetAsmLexer.h"
153e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetRegistry.h"
16a7cfc08ebe737062917b442830eb5321b0f79e89Evan Cheng#include "llvm/ADT/SmallVector.h"
17e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan
18e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callananusing namespace llvm;
19e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan
20e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanannamespace {
21e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan
2294b9550a32d189704a8eae55505edf62662c0534Evan Chengclass X86AsmLexer : public MCTargetAsmLexer {
23e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan  const MCAsmInfo &AsmInfo;
24cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan
25cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan  bool tentativeIsValid;
26cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan  AsmToken tentativeToken;
27cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan
28cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan  const AsmToken &lexTentative() {
29894c1af05fb3f0d8e2ee6565816fa220b260ed9dSean Callanan    tentativeToken = getLexer()->Lex();
30cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan    tentativeIsValid = true;
31cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan    return tentativeToken;
32cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan  }
33cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan
34cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan  const AsmToken &lexDefinite() {
35adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner    if (tentativeIsValid) {
36cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan      tentativeIsValid = false;
37cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan      return tentativeToken;
38cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan    }
39adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner    return getLexer()->Lex();
40cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan  }
41436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan
42436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan  AsmToken LexTokenATT();
43436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan  AsmToken LexTokenIntel();
44e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callananprotected:
45436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan  AsmToken LexToken() {
46cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan    if (!Lexer) {
47cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan      SetError(SMLoc(), "No MCAsmLexer installed");
48cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan      return AsmToken(AsmToken::Error, "", 0);
49cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan    }
50cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan
51436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan    switch (AsmInfo.getAssemblerDialect()) {
52436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan    default:
53436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan      SetError(SMLoc(), "Unhandled dialect");
54436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan      return AsmToken(AsmToken::Error, "", 0);
55436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan    case 0:
56436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan      return LexTokenATT();
57436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan    case 1:
58436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan      return LexTokenIntel();
59436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan    }
60436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan  }
61e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callananpublic:
621b0fc9b4182d6bd0703cdfb3b0b91d1e093c946cEvan Cheng  X86AsmLexer(const Target &T, const MCRegisterInfo &MRI, const MCAsmInfo &MAI)
6394b9550a32d189704a8eae55505edf62662c0534Evan Cheng    : MCTargetAsmLexer(T), AsmInfo(MAI), tentativeIsValid(false) {
64e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan  }
65e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan};
66e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan
670692ee676f8cdad25ad09a868bf597af4115c9d9Chris Lattner} // end anonymous namespace
68e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan
690692ee676f8cdad25ad09a868bf597af4115c9d9Chris Lattner#define GET_REGISTER_MATCHER
700692ee676f8cdad25ad09a868bf597af4115c9d9Chris Lattner#include "X86GenAsmMatcher.inc"
71cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan
72436c48485c365b399a908944ebbf4f761a4f9f6aSean CallananAsmToken X86AsmLexer::LexTokenATT() {
73adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner  AsmToken lexedToken = lexDefinite();
74cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan
75cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan  switch (lexedToken.getKind()) {
76cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan  default:
77adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner    return lexedToken;
78cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan  case AsmToken::Error:
79cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan    SetError(Lexer->getErrLoc(), Lexer->getErr());
80adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner    return lexedToken;
81adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner
82adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner  case AsmToken::Percent: {
83cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan    const AsmToken &nextToken = lexTentative();
8402758a44e41564aafa0e50843aaedafe6b3ed7b3Chris Lattner    if (nextToken.getKind() != AsmToken::Identifier)
85adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner      return lexedToken;
8602758a44e41564aafa0e50843aaedafe6b3ed7b3Chris Lattner
87cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan
8802758a44e41564aafa0e50843aaedafe6b3ed7b3Chris Lattner    if (unsigned regID = MatchRegisterName(nextToken.getString())) {
8902758a44e41564aafa0e50843aaedafe6b3ed7b3Chris Lattner      lexDefinite();
90cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan
91645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      // FIXME: This is completely wrong when there is a space or other
92645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      // punctuation between the % and the register name.
9302758a44e41564aafa0e50843aaedafe6b3ed7b3Chris Lattner      StringRef regStr(lexedToken.getString().data(),
9402758a44e41564aafa0e50843aaedafe6b3ed7b3Chris Lattner                       lexedToken.getString().size() +
9502758a44e41564aafa0e50843aaedafe6b3ed7b3Chris Lattner                       nextToken.getString().size());
9602758a44e41564aafa0e50843aaedafe6b3ed7b3Chris Lattner
97adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner      return AsmToken(AsmToken::Register, regStr,
9802758a44e41564aafa0e50843aaedafe6b3ed7b3Chris Lattner                      static_cast<int64_t>(regID));
99cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan    }
10002758a44e41564aafa0e50843aaedafe6b3ed7b3Chris Lattner
101645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner    // Match register name failed.  If this is "db[0-7]", match it as an alias
102645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner    // for dr[0-7].
103645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner    if (nextToken.getString().size() == 3 &&
104645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner        nextToken.getString().startswith("db")) {
105645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      int RegNo = -1;
106645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      switch (nextToken.getString()[2]) {
107645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      case '0': RegNo = X86::DR0; break;
108645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      case '1': RegNo = X86::DR1; break;
109645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      case '2': RegNo = X86::DR2; break;
110645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      case '3': RegNo = X86::DR3; break;
111645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      case '4': RegNo = X86::DR4; break;
112645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      case '5': RegNo = X86::DR5; break;
113645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      case '6': RegNo = X86::DR6; break;
114645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      case '7': RegNo = X86::DR7; break;
115645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      }
116645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner
117645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      if (RegNo != -1) {
118645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner        lexDefinite();
119645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner
120645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner        // FIXME: This is completely wrong when there is a space or other
121645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner        // punctuation between the % and the register name.
122645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner        StringRef regStr(lexedToken.getString().data(),
123645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner                         lexedToken.getString().size() +
124645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner                         nextToken.getString().size());
125645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner        return AsmToken(AsmToken::Register, regStr,
126645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner                        static_cast<int64_t>(RegNo));
127645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner      }
128645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner    }
129645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner
130645b209c4af53c0d21292df3d506cf79d4e3ec11Chris Lattner
131adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner    return lexedToken;
132cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan  }
133cf2e3d108d6f8f692c01bd48767c7f8dd9e20dcfSean Callanan  }
134436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan}
135436c48485c365b399a908944ebbf4f761a4f9f6aSean Callanan
136436c48485c365b399a908944ebbf4f761a4f9f6aSean CallananAsmToken X86AsmLexer::LexTokenIntel() {
1377dcef4c47578befe40d488c953e3f5b328667300Sean Callanan  const AsmToken &lexedToken = lexDefinite();
1387dcef4c47578befe40d488c953e3f5b328667300Sean Callanan
1397dcef4c47578befe40d488c953e3f5b328667300Sean Callanan  switch(lexedToken.getKind()) {
1407dcef4c47578befe40d488c953e3f5b328667300Sean Callanan  default:
141adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner    return lexedToken;
1427dcef4c47578befe40d488c953e3f5b328667300Sean Callanan  case AsmToken::Error:
1437dcef4c47578befe40d488c953e3f5b328667300Sean Callanan    SetError(Lexer->getErrLoc(), Lexer->getErr());
144adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner    return lexedToken;
145adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner  case AsmToken::Identifier: {
1467b135ae6d5904bca27ae81ca3c4324f8c8b855fdBenjamin Kramer    unsigned regID = MatchRegisterName(lexedToken.getString().lower());
1477dcef4c47578befe40d488c953e3f5b328667300Sean Callanan
148adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner    if (regID)
1497dcef4c47578befe40d488c953e3f5b328667300Sean Callanan      return AsmToken(AsmToken::Register,
1507dcef4c47578befe40d488c953e3f5b328667300Sean Callanan                      lexedToken.getString(),
1517dcef4c47578befe40d488c953e3f5b328667300Sean Callanan                      static_cast<int64_t>(regID));
152adabe1a92cf594fc4015f83024bc06b8687f09e3Chris Lattner    return lexedToken;
1537dcef4c47578befe40d488c953e3f5b328667300Sean Callanan  }
1547dcef4c47578befe40d488c953e3f5b328667300Sean Callanan  }
155e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan}
156e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan
157e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callananextern "C" void LLVMInitializeX86AsmLexer() {
15894b9550a32d189704a8eae55505edf62662c0534Evan Cheng  RegisterMCAsmLexer<X86AsmLexer> X(TheX86_32Target);
15994b9550a32d189704a8eae55505edf62662c0534Evan Cheng  RegisterMCAsmLexer<X86AsmLexer> Y(TheX86_64Target);
160e88f55254cde9d9443f1299b61aa6a93ec50b791Sean Callanan}
161