Removed the DumpSymbolsandMacros and LoadSymbolsandMacros MCStreamer API as
[oota-llvm.git] / tools / llvm-mc / AsmLexer.cpp
1 //===- AsmLexer.cpp - Lexer for Assembly Files ----------------------------===//
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 // This class implements the lexer for assembly files.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "AsmLexer.h"
15 #include "llvm/ADT/StringSet.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "llvm/Support/MemoryBuffer.h"
18 #include "llvm/Config/config.h"  // for strtoull.
19 #include <cerrno>
20 #include <cstdio>
21 #include <cstdlib>
22 using namespace llvm;
23
24 static StringSet<> &getSS(void *TheSS) {
25   return *(StringSet<>*)TheSS;
26 }
27
28 AsmLexer::AsmLexer(SourceMgr &SM) : SrcMgr(SM) {
29   CurBuffer = 0;
30   CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
31   CurPtr = CurBuf->getBufferStart();
32   TokStart = 0;
33   
34   TheStringSet = new StringSet<>();
35 }
36
37 AsmLexer::~AsmLexer() {
38   delete &getSS(TheStringSet);
39 }
40
41 SMLoc AsmLexer::getLoc() const {
42   return SMLoc::getFromPointer(TokStart);
43 }
44
45 void AsmLexer::PrintMessage(SMLoc Loc, const std::string &Msg, 
46                             const char *Type) const {
47   SrcMgr.PrintMessage(Loc, Msg, Type);
48 }
49
50 /// ReturnError - Set the error to the specified string at the specified
51 /// location.  This is defined to always return asmtok::Error.
52 asmtok::TokKind AsmLexer::ReturnError(const char *Loc, const std::string &Msg) {
53   SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error");
54   return asmtok::Error;
55 }
56
57 /// EnterIncludeFile - Enter the specified file.  This prints an error and
58 /// returns true on failure.
59 bool AsmLexer::EnterIncludeFile(const std::string &Filename) {
60   int NewBuf = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr));
61   if (NewBuf == -1)
62     return true;
63   
64   // Save the line number and lex buffer of the includer.
65   CurBuffer = NewBuf;
66   CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
67   CurPtr = CurBuf->getBufferStart();
68   return false;
69 }
70
71
72 int AsmLexer::getNextChar() {
73   char CurChar = *CurPtr++;
74   switch (CurChar) {
75   default:
76     return (unsigned char)CurChar;
77   case 0: {
78     // A nul character in the stream is either the end of the current buffer or
79     // a random nul in the file.  Disambiguate that here.
80     if (CurPtr-1 != CurBuf->getBufferEnd())
81       return 0;  // Just whitespace.
82     
83     // If this is the end of an included file, pop the parent file off the
84     // include stack.
85     SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer);
86     if (ParentIncludeLoc != SMLoc()) {
87       CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc);
88       CurBuf = SrcMgr.getMemoryBuffer(CurBuffer);
89       CurPtr = ParentIncludeLoc.getPointer();
90       
91       // Reset the token start pointer to the start of the new file.
92       TokStart = CurPtr;
93       
94       return getNextChar();
95     }
96     
97     // Otherwise, return end of file.
98     --CurPtr;  // Another call to lex will return EOF again.  
99     return EOF;
100   }
101   }
102 }
103
104 /// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
105 asmtok::TokKind AsmLexer::LexIdentifier() {
106   while (isalnum(*CurPtr) || *CurPtr == '_' || *CurPtr == '$' ||
107          *CurPtr == '.' || *CurPtr == '@')
108     ++CurPtr;
109   // Unique string.
110   CurStrVal =
111     getSS(TheStringSet).GetOrCreateValue(TokStart, CurPtr, 0).getKeyData();
112   return asmtok::Identifier;
113 }
114
115 /// LexPercent: Register: %[a-zA-Z0-9]+
116 asmtok::TokKind AsmLexer::LexPercent() {
117   if (!isalnum(*CurPtr))
118     return asmtok::Percent;  // Single %.
119   
120   while (isalnum(*CurPtr))
121     ++CurPtr;
122   
123   // Unique string.
124   CurStrVal =
125     getSS(TheStringSet).GetOrCreateValue(TokStart, CurPtr, 0).getKeyData();
126   return asmtok::Register;
127 }
128
129 /// LexSlash: Slash: /
130 ///           C-Style Comment: /* ... */
131 asmtok::TokKind AsmLexer::LexSlash() {
132   switch (*CurPtr) {
133   case '*': break; // C style comment.
134   case '/': return ++CurPtr, LexLineComment();
135   default:  return asmtok::Slash;
136   }
137
138   // C Style comment.
139   ++CurPtr;  // skip the star.
140   while (1) {
141     int CurChar = getNextChar();
142     switch (CurChar) {
143     case EOF:
144       return ReturnError(TokStart, "unterminated comment");
145     case '*':
146       // End of the comment?
147       if (CurPtr[0] != '/') break;
148       
149       ++CurPtr;   // End the */.
150       return LexToken();
151     }
152   }
153 }
154
155 /// LexLineComment: Comment: #[^\n]*
156 ///                        : //[^\n]*
157 asmtok::TokKind AsmLexer::LexLineComment() {
158   int CurChar = getNextChar();
159   while (CurChar != '\n' && CurChar != '\n' && CurChar != EOF)
160     CurChar = getNextChar();
161   
162   if (CurChar == EOF)
163     return asmtok::Eof;
164   return asmtok::EndOfStatement;
165 }
166
167
168 /// LexDigit: First character is [0-9].
169 ///   Local Label: [0-9][:]
170 ///   Forward/Backward Label: [0-9][fb]
171 ///   Binary integer: 0b[01]+
172 ///   Octal integer: 0[0-7]+
173 ///   Hex integer: 0x[0-9a-fA-F]+
174 ///   Decimal integer: [1-9][0-9]*
175 /// TODO: FP literal.
176 asmtok::TokKind AsmLexer::LexDigit() {
177   if (*CurPtr == ':')
178     return ReturnError(TokStart, "FIXME: local label not implemented");
179   if (*CurPtr == 'f' || *CurPtr == 'b')
180     return ReturnError(TokStart, "FIXME: directional label not implemented");
181   
182   // Decimal integer: [1-9][0-9]*
183   if (CurPtr[-1] != '0') {
184     while (isdigit(*CurPtr))
185       ++CurPtr;
186     CurIntVal = strtoll(TokStart, 0, 10);
187     return asmtok::IntVal;
188   }
189   
190   if (*CurPtr == 'b') {
191     ++CurPtr;
192     const char *NumStart = CurPtr;
193     while (CurPtr[0] == '0' || CurPtr[0] == '1')
194       ++CurPtr;
195     
196     // Requires at least one binary digit.
197     if (CurPtr == NumStart)
198       return ReturnError(CurPtr-2, "Invalid binary number");
199     CurIntVal = strtoll(NumStart, 0, 2);
200     return asmtok::IntVal;
201   }
202  
203   if (*CurPtr == 'x') {
204     ++CurPtr;
205     const char *NumStart = CurPtr;
206     while (isxdigit(CurPtr[0]))
207       ++CurPtr;
208     
209     // Requires at least one hex digit.
210     if (CurPtr == NumStart)
211       return ReturnError(CurPtr-2, "Invalid hexadecimal number");
212     
213     errno = 0;
214     CurIntVal = strtoll(NumStart, 0, 16);
215     if (errno == EINVAL)
216       return ReturnError(CurPtr-2, "Invalid hexadecimal number");
217     if (errno == ERANGE) {
218       errno = 0;
219       CurIntVal = (int64_t)strtoull(NumStart, 0, 16);
220       if (errno == EINVAL)
221         return ReturnError(CurPtr-2, "Invalid hexadecimal number");
222       if (errno == ERANGE)
223         return ReturnError(CurPtr-2, "Hexadecimal number out of range");
224     }
225     return asmtok::IntVal;
226   }
227   
228   // Must be an octal number, it starts with 0.
229   while (*CurPtr >= '0' && *CurPtr <= '7')
230     ++CurPtr;
231   CurIntVal = strtoll(TokStart, 0, 8);
232   return asmtok::IntVal;
233 }
234
235 /// LexQuote: String: "..."
236 asmtok::TokKind AsmLexer::LexQuote() {
237   int CurChar = getNextChar();
238   // TODO: does gas allow multiline string constants?
239   while (CurChar != '"') {
240     if (CurChar == '\\') {
241       // Allow \", etc.
242       CurChar = getNextChar();
243     }
244     
245     if (CurChar == EOF)
246       return ReturnError(TokStart, "unterminated string constant");
247
248     CurChar = getNextChar();
249   }
250   
251   // Unique string, include quotes for now.
252   CurStrVal =
253     getSS(TheStringSet).GetOrCreateValue(TokStart, CurPtr, 0).getKeyData();
254   return asmtok::String;
255 }
256
257
258 asmtok::TokKind AsmLexer::LexToken() {
259   TokStart = CurPtr;
260   // This always consumes at least one character.
261   int CurChar = getNextChar();
262   
263   switch (CurChar) {
264   default:
265     // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
266     if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
267       return LexIdentifier();
268     
269     // Unknown character, emit an error.
270     return ReturnError(TokStart, "invalid character in input");
271   case EOF: return asmtok::Eof;
272   case 0:
273   case ' ':
274   case '\t':
275     // Ignore whitespace.
276     return LexToken();
277   case '\n': // FALL THROUGH.
278   case '\r': // FALL THROUGH.
279   case ';': return asmtok::EndOfStatement;
280   case ':': return asmtok::Colon;
281   case '+': return asmtok::Plus;
282   case '-': return asmtok::Minus;
283   case '~': return asmtok::Tilde;
284   case '(': return asmtok::LParen;
285   case ')': return asmtok::RParen;
286   case '*': return asmtok::Star;
287   case ',': return asmtok::Comma;
288   case '$': return asmtok::Dollar;
289   case '=': 
290     if (*CurPtr == '=')
291       return ++CurPtr, asmtok::EqualEqual;
292     return asmtok::Equal;
293   case '|': 
294     if (*CurPtr == '|')
295       return ++CurPtr, asmtok::PipePipe;
296     return asmtok::Pipe;
297   case '^': return asmtok::Caret;
298   case '&': 
299     if (*CurPtr == '&')
300       return ++CurPtr, asmtok::AmpAmp;
301     return asmtok::Amp;
302   case '!': 
303     if (*CurPtr == '=')
304       return ++CurPtr, asmtok::ExclaimEqual;
305     return asmtok::Exclaim;
306   case '%': return LexPercent();
307   case '/': return LexSlash();
308   case '#': return LexLineComment();
309   case '"': return LexQuote();
310   case '0': case '1': case '2': case '3': case '4':
311   case '5': case '6': case '7': case '8': case '9':
312     return LexDigit();
313   case '<':
314     switch (*CurPtr) {
315     case '<': return ++CurPtr, asmtok::LessLess;
316     case '=': return ++CurPtr, asmtok::LessEqual;
317     case '>': return ++CurPtr, asmtok::LessGreater;
318     default: return asmtok::Less;
319     }
320   case '>':
321     switch (*CurPtr) {
322     case '>': return ++CurPtr, asmtok::GreaterGreater;      
323     case '=': return ++CurPtr, asmtok::GreaterEqual;      
324     default: return asmtok::Greater;
325     }
326       
327   // TODO: Quoted identifiers (objc methods etc)
328   // local labels: [0-9][:]
329   // Forward/backward labels: [0-9][fb]
330   // Integers, fp constants, character constants.
331   }
332 }