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