LLVM  10.0.0svn
AsmLexer.cpp
Go to the documentation of this file.
1 //===- AsmLexer.cpp - Lexer for Assembly Files ----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This class implements the lexer for assembly files.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "llvm/ADT/APInt.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/ADT/StringSwitch.h"
19 #include "llvm/MC/MCAsmInfo.h"
21 #include "llvm/Support/SMLoc.h"
23 #include <cassert>
24 #include <cctype>
25 #include <cstdio>
26 #include <cstring>
27 #include <string>
28 #include <tuple>
29 #include <utility>
30 
31 using namespace llvm;
32 
33 AsmLexer::AsmLexer(const MCAsmInfo &MAI) : MAI(MAI) {
35 }
36 
37 AsmLexer::~AsmLexer() = default;
38 
39 void AsmLexer::setBuffer(StringRef Buf, const char *ptr) {
40  CurBuf = Buf;
41 
42  if (ptr)
43  CurPtr = ptr;
44  else
45  CurPtr = CurBuf.begin();
46 
47  TokStart = nullptr;
48 }
49 
50 /// ReturnError - Set the error to the specified string at the specified
51 /// location. This is defined to always return AsmToken::Error.
52 AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) {
54 
55  return AsmToken(AsmToken::Error, StringRef(Loc, CurPtr - Loc));
56 }
57 
58 int AsmLexer::getNextChar() {
59  if (CurPtr == CurBuf.end())
60  return EOF;
61  return (unsigned char)*CurPtr++;
62 }
63 
64 /// The leading integral digit sequence and dot should have already been
65 /// consumed, some or all of the fractional digit sequence *can* have been
66 /// consumed.
67 AsmToken AsmLexer::LexFloatLiteral() {
68  // Skip the fractional digit sequence.
69  while (isDigit(*CurPtr))
70  ++CurPtr;
71 
72  if (*CurPtr == '-' || *CurPtr == '+')
73  return ReturnError(CurPtr, "Invalid sign in float literal");
74 
75  // Check for exponent
76  if ((*CurPtr == 'e' || *CurPtr == 'E')) {
77  ++CurPtr;
78 
79  if (*CurPtr == '-' || *CurPtr == '+')
80  ++CurPtr;
81 
82  while (isDigit(*CurPtr))
83  ++CurPtr;
84  }
85 
86  return AsmToken(AsmToken::Real,
87  StringRef(TokStart, CurPtr - TokStart));
88 }
89 
90 /// LexHexFloatLiteral matches essentially (.[0-9a-fA-F]*)?[pP][+-]?[0-9a-fA-F]+
91 /// while making sure there are enough actual digits around for the constant to
92 /// be valid.
93 ///
94 /// The leading "0x[0-9a-fA-F]*" (i.e. integer part) has already been consumed
95 /// before we get here.
96 AsmToken AsmLexer::LexHexFloatLiteral(bool NoIntDigits) {
97  assert((*CurPtr == 'p' || *CurPtr == 'P' || *CurPtr == '.') &&
98  "unexpected parse state in floating hex");
99  bool NoFracDigits = true;
100 
101  // Skip the fractional part if there is one
102  if (*CurPtr == '.') {
103  ++CurPtr;
104 
105  const char *FracStart = CurPtr;
106  while (isHexDigit(*CurPtr))
107  ++CurPtr;
108 
109  NoFracDigits = CurPtr == FracStart;
110  }
111 
112  if (NoIntDigits && NoFracDigits)
113  return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
114  "expected at least one significand digit");
115 
116  // Make sure we do have some kind of proper exponent part
117  if (*CurPtr != 'p' && *CurPtr != 'P')
118  return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
119  "expected exponent part 'p'");
120  ++CurPtr;
121 
122  if (*CurPtr == '+' || *CurPtr == '-')
123  ++CurPtr;
124 
125  // N.b. exponent digits are *not* hex
126  const char *ExpStart = CurPtr;
127  while (isDigit(*CurPtr))
128  ++CurPtr;
129 
130  if (CurPtr == ExpStart)
131  return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
132  "expected at least one exponent digit");
133 
134  return AsmToken(AsmToken::Real, StringRef(TokStart, CurPtr - TokStart));
135 }
136 
137 /// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@?]*
138 static bool IsIdentifierChar(char c, bool AllowAt) {
139  return isAlnum(c) || c == '_' || c == '$' || c == '.' ||
140  (c == '@' && AllowAt) || c == '?';
141 }
142 
143 AsmToken AsmLexer::LexIdentifier() {
144  // Check for floating point literals.
145  if (CurPtr[-1] == '.' && isDigit(*CurPtr)) {
146  // Disambiguate a .1243foo identifier from a floating literal.
147  while (isDigit(*CurPtr))
148  ++CurPtr;
149 
150  if (!IsIdentifierChar(*CurPtr, AllowAtInIdentifier) ||
151  *CurPtr == 'e' || *CurPtr == 'E')
152  return LexFloatLiteral();
153  }
154 
155  while (IsIdentifierChar(*CurPtr, AllowAtInIdentifier))
156  ++CurPtr;
157 
158  // Handle . as a special case.
159  if (CurPtr == TokStart+1 && TokStart[0] == '.')
161 
163 }
164 
165 /// LexSlash: Slash: /
166 /// C-Style Comment: /* ... */
167 AsmToken AsmLexer::LexSlash() {
168  switch (*CurPtr) {
169  case '*':
170  IsAtStartOfStatement = false;
171  break; // C style comment.
172  case '/':
173  ++CurPtr;
174  return LexLineComment();
175  default:
176  IsAtStartOfStatement = false;
178  }
179 
180  // C Style comment.
181  ++CurPtr; // skip the star.
182  const char *CommentTextStart = CurPtr;
183  while (CurPtr != CurBuf.end()) {
184  switch (*CurPtr++) {
185  case '*':
186  // End of the comment?
187  if (*CurPtr != '/')
188  break;
189  // If we have a CommentConsumer, notify it about the comment.
190  if (CommentConsumer) {
192  SMLoc::getFromPointer(CommentTextStart),
193  StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
194  }
195  ++CurPtr; // End the */.
197  StringRef(TokStart, CurPtr - TokStart));
198  }
199  }
200  return ReturnError(TokStart, "unterminated comment");
201 }
202 
203 /// LexLineComment: Comment: #[^\n]*
204 /// : //[^\n]*
205 AsmToken AsmLexer::LexLineComment() {
206  // Mark This as an end of statement with a body of the
207  // comment. While it would be nicer to leave this two tokens,
208  // backwards compatability with TargetParsers makes keeping this in this form
209  // better.
210  const char *CommentTextStart = CurPtr;
211  int CurChar = getNextChar();
212  while (CurChar != '\n' && CurChar != '\r' && CurChar != EOF)
213  CurChar = getNextChar();
214  if (CurChar == '\r' && CurPtr != CurBuf.end() && *CurPtr == '\n')
215  ++CurPtr;
216 
217  // If we have a CommentConsumer, notify it about the comment.
218  if (CommentConsumer) {
220  SMLoc::getFromPointer(CommentTextStart),
221  StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
222  }
223 
224  IsAtStartOfLine = true;
225  // This is a whole line comment. leave newline
226  if (IsAtStartOfStatement)
228  StringRef(TokStart, CurPtr - TokStart));
229  IsAtStartOfStatement = true;
230 
232  StringRef(TokStart, CurPtr - 1 - TokStart));
233 }
234 
235 static void SkipIgnoredIntegerSuffix(const char *&CurPtr) {
236  // Skip ULL, UL, U, L and LL suffices.
237  if (CurPtr[0] == 'U')
238  ++CurPtr;
239  if (CurPtr[0] == 'L')
240  ++CurPtr;
241  if (CurPtr[0] == 'L')
242  ++CurPtr;
243 }
244 
245 // Look ahead to search for first non-hex digit, if it's [hH], then we treat the
246 // integer as a hexadecimal, possibly with leading zeroes.
247 static unsigned doHexLookAhead(const char *&CurPtr, unsigned DefaultRadix,
248  bool LexHex) {
249  const char *FirstNonDec = nullptr;
250  const char *LookAhead = CurPtr;
251  while (true) {
252  if (isDigit(*LookAhead)) {
253  ++LookAhead;
254  } else {
255  if (!FirstNonDec)
256  FirstNonDec = LookAhead;
257 
258  // Keep going if we are looking for a 'h' suffix.
259  if (LexHex && isHexDigit(*LookAhead))
260  ++LookAhead;
261  else
262  break;
263  }
264  }
265  bool isHex = LexHex && (*LookAhead == 'h' || *LookAhead == 'H');
266  CurPtr = isHex || !FirstNonDec ? LookAhead : FirstNonDec;
267  if (isHex)
268  return 16;
269  return DefaultRadix;
270 }
271 
273 {
274  if (Value.isIntN(64))
275  return AsmToken(AsmToken::Integer, Ref, Value);
276  return AsmToken(AsmToken::BigNum, Ref, Value);
277 }
278 
279 /// LexDigit: First character is [0-9].
280 /// Local Label: [0-9][:]
281 /// Forward/Backward Label: [0-9][fb]
282 /// Binary integer: 0b[01]+
283 /// Octal integer: 0[0-7]+
284 /// Hex integer: 0x[0-9a-fA-F]+ or [0x]?[0-9][0-9a-fA-F]*[hH]
285 /// Decimal integer: [1-9][0-9]*
286 AsmToken AsmLexer::LexDigit() {
287  // MASM-flavor binary integer: [01]+[bB]
288  // MASM-flavor hexadecimal integer: [0-9][0-9a-fA-F]*[hH]
289  if (LexMasmIntegers && isdigit(CurPtr[-1])) {
290  const char *FirstNonBinary = (CurPtr[-1] != '0' && CurPtr[-1] != '1') ?
291  CurPtr - 1 : nullptr;
292  const char *OldCurPtr = CurPtr;
293  while (isHexDigit(*CurPtr)) {
294  if (*CurPtr != '0' && *CurPtr != '1' && !FirstNonBinary)
295  FirstNonBinary = CurPtr;
296  ++CurPtr;
297  }
298 
299  unsigned Radix = 0;
300  if (*CurPtr == 'h' || *CurPtr == 'H') {
301  // hexadecimal number
302  ++CurPtr;
303  Radix = 16;
304  } else if (FirstNonBinary && FirstNonBinary + 1 == CurPtr &&
305  (*FirstNonBinary == 'b' || *FirstNonBinary == 'B'))
306  Radix = 2;
307 
308  if (Radix == 2 || Radix == 16) {
309  StringRef Result(TokStart, CurPtr - TokStart);
310  APInt Value(128, 0, true);
311 
312  if (Result.drop_back().getAsInteger(Radix, Value))
313  return ReturnError(TokStart, Radix == 2 ? "invalid binary number" :
314  "invalid hexdecimal number");
315 
316  // MSVC accepts and ignores type suffices on integer literals.
317  SkipIgnoredIntegerSuffix(CurPtr);
318 
319  return intToken(Result, Value);
320  }
321 
322  // octal/decimal integers, or floating point numbers, fall through
323  CurPtr = OldCurPtr;
324  }
325 
326  // Decimal integer: [1-9][0-9]*
327  if (CurPtr[-1] != '0' || CurPtr[0] == '.') {
328  unsigned Radix = doHexLookAhead(CurPtr, 10, LexMasmIntegers);
329  bool isHex = Radix == 16;
330  // Check for floating point literals.
331  if (!isHex && (*CurPtr == '.' || *CurPtr == 'e' || *CurPtr == 'E')) {
332  if (*CurPtr == '.')
333  ++CurPtr;
334  return LexFloatLiteral();
335  }
336 
337  StringRef Result(TokStart, CurPtr - TokStart);
338 
339  APInt Value(128, 0, true);
340  if (Result.getAsInteger(Radix, Value))
341  return ReturnError(TokStart, !isHex ? "invalid decimal number" :
342  "invalid hexdecimal number");
343 
344  // Consume the [hH].
345  if (LexMasmIntegers && Radix == 16)
346  ++CurPtr;
347 
348  // The darwin/x86 (and x86-64) assembler accepts and ignores type
349  // suffices on integer literals.
350  SkipIgnoredIntegerSuffix(CurPtr);
351 
352  return intToken(Result, Value);
353  }
354 
355  if (!LexMasmIntegers && ((*CurPtr == 'b') || (*CurPtr == 'B'))) {
356  ++CurPtr;
357  // See if we actually have "0b" as part of something like "jmp 0b\n"
358  if (!isDigit(CurPtr[0])) {
359  --CurPtr;
360  StringRef Result(TokStart, CurPtr - TokStart);
361  return AsmToken(AsmToken::Integer, Result, 0);
362  }
363  const char *NumStart = CurPtr;
364  while (CurPtr[0] == '0' || CurPtr[0] == '1')
365  ++CurPtr;
366 
367  // Requires at least one binary digit.
368  if (CurPtr == NumStart)
369  return ReturnError(TokStart, "invalid binary number");
370 
371  StringRef Result(TokStart, CurPtr - TokStart);
372 
373  APInt Value(128, 0, true);
374  if (Result.substr(2).getAsInteger(2, Value))
375  return ReturnError(TokStart, "invalid binary number");
376 
377  // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
378  // suffixes on integer literals.
379  SkipIgnoredIntegerSuffix(CurPtr);
380 
381  return intToken(Result, Value);
382  }
383 
384  if ((*CurPtr == 'x') || (*CurPtr == 'X')) {
385  ++CurPtr;
386  const char *NumStart = CurPtr;
387  while (isHexDigit(CurPtr[0]))
388  ++CurPtr;
389 
390  // "0x.0p0" is valid, and "0x0p0" (but not "0xp0" for example, which will be
391  // diagnosed by LexHexFloatLiteral).
392  if (CurPtr[0] == '.' || CurPtr[0] == 'p' || CurPtr[0] == 'P')
393  return LexHexFloatLiteral(NumStart == CurPtr);
394 
395  // Otherwise requires at least one hex digit.
396  if (CurPtr == NumStart)
397  return ReturnError(CurPtr-2, "invalid hexadecimal number");
398 
399  APInt Result(128, 0);
400  if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result))
401  return ReturnError(TokStart, "invalid hexadecimal number");
402 
403  // Consume the optional [hH].
404  if (LexMasmIntegers && (*CurPtr == 'h' || *CurPtr == 'H'))
405  ++CurPtr;
406 
407  // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
408  // suffixes on integer literals.
409  SkipIgnoredIntegerSuffix(CurPtr);
410 
411  return intToken(StringRef(TokStart, CurPtr - TokStart), Result);
412  }
413 
414  // Either octal or hexadecimal.
415  APInt Value(128, 0, true);
416  unsigned Radix = doHexLookAhead(CurPtr, 8, LexMasmIntegers);
417  bool isHex = Radix == 16;
418  StringRef Result(TokStart, CurPtr - TokStart);
419  if (Result.getAsInteger(Radix, Value))
420  return ReturnError(TokStart, !isHex ? "invalid octal number" :
421  "invalid hexdecimal number");
422 
423  // Consume the [hH].
424  if (Radix == 16)
425  ++CurPtr;
426 
427  // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
428  // suffixes on integer literals.
429  SkipIgnoredIntegerSuffix(CurPtr);
430 
431  return intToken(Result, Value);
432 }
433 
434 /// LexSingleQuote: Integer: 'b'
435 AsmToken AsmLexer::LexSingleQuote() {
436  int CurChar = getNextChar();
437 
438  if (CurChar == '\\')
439  CurChar = getNextChar();
440 
441  if (CurChar == EOF)
442  return ReturnError(TokStart, "unterminated single quote");
443 
444  CurChar = getNextChar();
445 
446  if (CurChar != '\'')
447  return ReturnError(TokStart, "single quote way too long");
448 
449  // The idea here being that 'c' is basically just an integral
450  // constant.
451  StringRef Res = StringRef(TokStart,CurPtr - TokStart);
452  long long Value;
453 
454  if (Res.startswith("\'\\")) {
455  char theChar = Res[2];
456  switch (theChar) {
457  default: Value = theChar; break;
458  case '\'': Value = '\''; break;
459  case 't': Value = '\t'; break;
460  case 'n': Value = '\n'; break;
461  case 'b': Value = '\b'; break;
462  }
463  } else
464  Value = TokStart[1];
465 
466  return AsmToken(AsmToken::Integer, Res, Value);
467 }
468 
469 /// LexQuote: String: "..."
470 AsmToken AsmLexer::LexQuote() {
471  int CurChar = getNextChar();
472  // TODO: does gas allow multiline string constants?
473  while (CurChar != '"') {
474  if (CurChar == '\\') {
475  // Allow \", etc.
476  CurChar = getNextChar();
477  }
478 
479  if (CurChar == EOF)
480  return ReturnError(TokStart, "unterminated string constant");
481 
482  CurChar = getNextChar();
483  }
484 
486 }
487 
489  TokStart = CurPtr;
490 
491  while (!isAtStartOfComment(CurPtr) && // Start of line comment.
492  !isAtStatementSeparator(CurPtr) && // End of statement marker.
493  *CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) {
494  ++CurPtr;
495  }
496  return StringRef(TokStart, CurPtr-TokStart);
497 }
498 
499 StringRef AsmLexer::LexUntilEndOfLine() {
500  TokStart = CurPtr;
501 
502  while (*CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) {
503  ++CurPtr;
504  }
505  return StringRef(TokStart, CurPtr-TokStart);
506 }
507 
509  bool ShouldSkipSpace) {
510  SaveAndRestore<const char *> SavedTokenStart(TokStart);
511  SaveAndRestore<const char *> SavedCurPtr(CurPtr);
512  SaveAndRestore<bool> SavedAtStartOfLine(IsAtStartOfLine);
513  SaveAndRestore<bool> SavedAtStartOfStatement(IsAtStartOfStatement);
514  SaveAndRestore<bool> SavedSkipSpace(SkipSpace, ShouldSkipSpace);
515  SaveAndRestore<bool> SavedIsPeeking(IsPeeking, true);
516  std::string SavedErr = getErr();
517  SMLoc SavedErrLoc = getErrLoc();
518 
519  size_t ReadCount;
520  for (ReadCount = 0; ReadCount < Buf.size(); ++ReadCount) {
521  AsmToken Token = LexToken();
522 
523  Buf[ReadCount] = Token;
524 
525  if (Token.is(AsmToken::Eof))
526  break;
527  }
528 
529  SetError(SavedErrLoc, SavedErr);
530  return ReadCount;
531 }
532 
533 bool AsmLexer::isAtStartOfComment(const char *Ptr) {
534  StringRef CommentString = MAI.getCommentString();
535 
536  if (CommentString.size() == 1)
537  return CommentString[0] == Ptr[0];
538 
539  // Allow # preprocessor commments also be counted as comments for "##" cases
540  if (CommentString[1] == '#')
541  return CommentString[0] == Ptr[0];
542 
543  return strncmp(Ptr, CommentString.data(), CommentString.size()) == 0;
544 }
545 
546 bool AsmLexer::isAtStatementSeparator(const char *Ptr) {
547  return strncmp(Ptr, MAI.getSeparatorString(),
548  strlen(MAI.getSeparatorString())) == 0;
549 }
550 
552  TokStart = CurPtr;
553  // This always consumes at least one character.
554  int CurChar = getNextChar();
555 
556  if (!IsPeeking && CurChar == '#' && IsAtStartOfStatement) {
557  // If this starts with a '#', this may be a cpp
558  // hash directive and otherwise a line comment.
559  AsmToken TokenBuf[2];
560  MutableArrayRef<AsmToken> Buf(TokenBuf, 2);
561  size_t num = peekTokens(Buf, true);
562  // There cannot be a space preceding this
563  if (IsAtStartOfLine && num == 2 && TokenBuf[0].is(AsmToken::Integer) &&
564  TokenBuf[1].is(AsmToken::String)) {
565  CurPtr = TokStart; // reset curPtr;
566  StringRef s = LexUntilEndOfLine();
567  UnLex(TokenBuf[1]);
568  UnLex(TokenBuf[0]);
570  }
571  return LexLineComment();
572  }
573 
574  if (isAtStartOfComment(TokStart))
575  return LexLineComment();
576 
577  if (isAtStatementSeparator(TokStart)) {
578  CurPtr += strlen(MAI.getSeparatorString()) - 1;
579  IsAtStartOfLine = true;
580  IsAtStartOfStatement = true;
582  StringRef(TokStart, strlen(MAI.getSeparatorString())));
583  }
584 
585  // If we're missing a newline at EOF, make sure we still get an
586  // EndOfStatement token before the Eof token.
587  if (CurChar == EOF && !IsAtStartOfStatement) {
588  IsAtStartOfLine = true;
589  IsAtStartOfStatement = true;
591  }
592  IsAtStartOfLine = false;
593  bool OldIsAtStartOfStatement = IsAtStartOfStatement;
594  IsAtStartOfStatement = false;
595  switch (CurChar) {
596  default:
597  // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
598  if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
599  return LexIdentifier();
600 
601  // Unknown character, emit an error.
602  return ReturnError(TokStart, "invalid character in input");
603  case EOF:
604  IsAtStartOfLine = true;
605  IsAtStartOfStatement = true;
607  case 0:
608  case ' ':
609  case '\t':
610  IsAtStartOfStatement = OldIsAtStartOfStatement;
611  while (*CurPtr == ' ' || *CurPtr == '\t')
612  CurPtr++;
613  if (SkipSpace)
614  return LexToken(); // Ignore whitespace.
615  else
616  return AsmToken(AsmToken::Space, StringRef(TokStart, CurPtr - TokStart));
617  case '\r': {
618  IsAtStartOfLine = true;
619  IsAtStartOfStatement = true;
620  // If this is a CR followed by LF, treat that as one token.
621  if (CurPtr != CurBuf.end() && *CurPtr == '\n')
622  ++CurPtr;
624  StringRef(TokStart, CurPtr - TokStart));
625  }
626  case '\n':
627  IsAtStartOfLine = true;
628  IsAtStartOfStatement = true;
630  case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1));
631  case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1));
632  case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1));
633  case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1));
634  case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1));
635  case '[': return AsmToken(AsmToken::LBrac, StringRef(TokStart, 1));
636  case ']': return AsmToken(AsmToken::RBrac, StringRef(TokStart, 1));
637  case '{': return AsmToken(AsmToken::LCurly, StringRef(TokStart, 1));
638  case '}': return AsmToken(AsmToken::RCurly, StringRef(TokStart, 1));
639  case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1));
640  case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1));
641  case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1));
642  case '@': return AsmToken(AsmToken::At, StringRef(TokStart, 1));
643  case '\\': return AsmToken(AsmToken::BackSlash, StringRef(TokStart, 1));
644  case '=':
645  if (*CurPtr == '=') {
646  ++CurPtr;
648  }
650  case '-':
651  if (*CurPtr == '>') {
652  ++CurPtr;
654  }
656  case '|':
657  if (*CurPtr == '|') {
658  ++CurPtr;
660  }
662  case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1));
663  case '&':
664  if (*CurPtr == '&') {
665  ++CurPtr;
667  }
669  case '!':
670  if (*CurPtr == '=') {
671  ++CurPtr;
673  }
675  case '%':
676  if (MAI.hasMipsExpressions()) {
678  unsigned OperatorLength;
679 
680  std::tie(Operator, OperatorLength) =
682  StringRef(CurPtr))
683  .StartsWith("call16", {AsmToken::PercentCall16, 7})
684  .StartsWith("call_hi", {AsmToken::PercentCall_Hi, 8})
685  .StartsWith("call_lo", {AsmToken::PercentCall_Lo, 8})
686  .StartsWith("dtprel_hi", {AsmToken::PercentDtprel_Hi, 10})
687  .StartsWith("dtprel_lo", {AsmToken::PercentDtprel_Lo, 10})
688  .StartsWith("got_disp", {AsmToken::PercentGot_Disp, 9})
689  .StartsWith("got_hi", {AsmToken::PercentGot_Hi, 7})
690  .StartsWith("got_lo", {AsmToken::PercentGot_Lo, 7})
691  .StartsWith("got_ofst", {AsmToken::PercentGot_Ofst, 9})
692  .StartsWith("got_page", {AsmToken::PercentGot_Page, 9})
693  .StartsWith("gottprel", {AsmToken::PercentGottprel, 9})
694  .StartsWith("got", {AsmToken::PercentGot, 4})
695  .StartsWith("gp_rel", {AsmToken::PercentGp_Rel, 7})
696  .StartsWith("higher", {AsmToken::PercentHigher, 7})
697  .StartsWith("highest", {AsmToken::PercentHighest, 8})
698  .StartsWith("hi", {AsmToken::PercentHi, 3})
699  .StartsWith("lo", {AsmToken::PercentLo, 3})
700  .StartsWith("neg", {AsmToken::PercentNeg, 4})
701  .StartsWith("pcrel_hi", {AsmToken::PercentPcrel_Hi, 9})
702  .StartsWith("pcrel_lo", {AsmToken::PercentPcrel_Lo, 9})
703  .StartsWith("tlsgd", {AsmToken::PercentTlsgd, 6})
704  .StartsWith("tlsldm", {AsmToken::PercentTlsldm, 7})
705  .StartsWith("tprel_hi", {AsmToken::PercentTprel_Hi, 9})
706  .StartsWith("tprel_lo", {AsmToken::PercentTprel_Lo, 9})
707  .Default({AsmToken::Percent, 1});
708 
709  if (Operator != AsmToken::Percent) {
710  CurPtr += OperatorLength - 1;
711  return AsmToken(Operator, StringRef(TokStart, OperatorLength));
712  }
713  }
715  case '/':
716  IsAtStartOfStatement = OldIsAtStartOfStatement;
717  return LexSlash();
718  case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1));
719  case '\'': return LexSingleQuote();
720  case '"': return LexQuote();
721  case '0': case '1': case '2': case '3': case '4':
722  case '5': case '6': case '7': case '8': case '9':
723  return LexDigit();
724  case '<':
725  switch (*CurPtr) {
726  case '<':
727  ++CurPtr;
729  case '=':
730  ++CurPtr;
732  case '>':
733  ++CurPtr;
735  default:
737  }
738  case '>':
739  switch (*CurPtr) {
740  case '>':
741  ++CurPtr;
743  case '=':
744  ++CurPtr;
746  default:
748  }
749 
750  // TODO: Quoted identifiers (objc methods etc)
751  // local labels: [0-9][:]
752  // Forward/backward labels: [0-9][fb]
753  // Integers, fp constants, character constants.
754  }
755 }
AsmCommentConsumer * CommentConsumer
Definition: MCAsmLexer.h:53
This class represents lattice values for constants.
Definition: AllocatorList.h:23
bool is(AsmToken::TokenKind K) const
Check if the current token has kind K.
Definition: MCAsmLexer.h:135
LLVM_NODISCARD bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:256
static unsigned doHexLookAhead(const char *&CurPtr, unsigned DefaultRadix, bool LexHex)
Definition: AsmLexer.cpp:247
bool isAlnum(char C)
Checks whether character C is either a decimal digit or an uppercase or lowercase letter as classifie...
Definition: StringExtras.h:88
void setBuffer(StringRef Buf, const char *ptr=nullptr)
Definition: AsmLexer.cpp:39
The access may reference the value stored in memory.
Target independent representation for an assembler token.
Definition: MCAsmMacro.h:21
LLVM_NODISCARD StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:578
This file implements a class to represent arbitrary precision integral constant values and operations...
static bool startswith(StringRef Magic, const char(&S)[N])
Definition: Magic.cpp:29
size_t peekTokens(MutableArrayRef< AsmToken > Buf, bool ShouldSkipSpace=true) override
Look ahead an arbitrary number of tokens.
Definition: AsmLexer.cpp:508
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:130
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:56
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:42
void SetError(SMLoc errLoc, const std::string &err)
Definition: MCAsmLexer.h:59
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:290
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:148
bool isHexDigit(char C)
Checks if character C is a hexadecimal numeric character.
Definition: StringExtras.h:79
const char * getSeparatorString() const
Definition: MCAsmInfo.h:486
static AsmToken intToken(StringRef Ref, APInt &Value)
Definition: AsmLexer.cpp:272
const char * TokStart
Definition: MCAsmLexer.h:48
StringRef getCommentString() const
Definition: MCAsmInfo.h:492
const std::string & getErr()
Get the current error string.
Definition: MCAsmLexer.h:127
bool isIntN(unsigned N) const
Check if this APInt has an N-bits unsigned integer value.
Definition: APInt.h:449
std::enable_if< std::numeric_limits< T >::is_signed, bool >::type getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition: StringRef.h:478
bool hasMipsExpressions() const
Definition: MCAsmInfo.h:641
void UnLex(AsmToken const &Token)
Definition: MCAsmLexer.h:87
This is a utility class that provides an abstraction for the common functionality between Instruction...
Definition: Operator.h:30
StringRef LexUntilEndOfStatement() override
Definition: AsmLexer.cpp:488
bool is(TokenKind K) const
Definition: MCAsmMacro.h:82
Class for arbitrary precision integers.
Definition: APInt.h:69
iterator begin() const
Definition: StringRef.h:101
A utility class that uses RAII to save and restore the value of a variable.
static SMLoc getFromPointer(const char *Ptr)
Definition: SMLoc.h:36
bool isDigit(char C)
Checks if character C is one of the 10 decimal digits.
Definition: StringExtras.h:76
~AsmLexer() override
AsmToken LexToken() override
LexToken - Read the next token and return its code.
Definition: AsmLexer.cpp:551
LLVM_NODISCARD const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:122
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:73
LLVM_NODISCARD StringRef drop_back(size_t N=1) const
Return a StringRef equal to &#39;this&#39; but with the last N elements dropped.
Definition: StringRef.h:628
SMLoc getErrLoc()
Get the current error location.
Definition: MCAsmLexer.h:122
This file provides utility classes that use RAII to save and restore values.
static void SkipIgnoredIntegerSuffix(const char *&CurPtr)
Definition: AsmLexer.cpp:235
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
Represents a location in source code.
Definition: SMLoc.h:23
static bool IsIdentifierChar(char c, bool AllowAt)
LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@?]*.
Definition: AsmLexer.cpp:138
bool LexMasmIntegers
Definition: MCAsmLexer.h:52
iterator end() const
Definition: StringRef.h:103
bool AllowAtInIdentifier
Definition: MCAsmLexer.h:50
virtual void HandleComment(SMLoc Loc, StringRef CommentText)=0
Callback function for when a comment is lexed.
AsmLexer(const MCAsmInfo &MAI)
Definition: AsmLexer.cpp:33