summaryrefslogtreecommitdiff
path: root/lib/Target/X86/AsmParser/X86AsmLexer.cpp
blob: 2794e60df238ec8cb5b56ae90ce1b021d7085ec5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//===-- 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"

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: {
    unsigned regID = MatchRegisterName(lexedToken.getString().lower());
    
    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);
}