LCOV - code coverage report
Current view: top level - lib/MC/MCParser - AsmLexer.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 346 358 96.6 %
Date: 2018-10-20 13:21:21 Functions: 21 21 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "llvm/MC/MCParser/AsmLexer.h"
      15             : #include "llvm/ADT/APInt.h"
      16             : #include "llvm/ADT/ArrayRef.h"
      17             : #include "llvm/ADT/StringExtras.h"
      18             : #include "llvm/ADT/StringRef.h"
      19             : #include "llvm/ADT/StringSwitch.h"
      20             : #include "llvm/MC/MCAsmInfo.h"
      21             : #include "llvm/MC/MCParser/MCAsmLexer.h"
      22             : #include "llvm/Support/SMLoc.h"
      23             : #include "llvm/Support/SaveAndRestore.h"
      24             : #include <cassert>
      25             : #include <cctype>
      26             : #include <cstdio>
      27             : #include <cstring>
      28             : #include <string>
      29             : #include <tuple>
      30             : #include <utility>
      31             : 
      32             : using namespace llvm;
      33             : 
      34       18554 : AsmLexer::AsmLexer(const MCAsmInfo &MAI) : MAI(MAI) {
      35       18554 :   AllowAtInIdentifier = !StringRef(MAI.getCommentString()).startswith("@");
      36       18554 : }
      37             : 
      38             : AsmLexer::~AsmLexer() = default;
      39             : 
      40      417199 : void AsmLexer::setBuffer(StringRef Buf, const char *ptr) {
      41      417199 :   CurBuf = Buf;
      42             : 
      43      417199 :   if (ptr)
      44      199325 :     CurPtr = ptr;
      45             :   else
      46      217874 :     CurPtr = CurBuf.begin();
      47             : 
      48      417199 :   TokStart = nullptr;
      49      417199 : }
      50             : 
      51             : /// ReturnError - Set the error to the specified string at the specified
      52             : /// location.  This is defined to always return AsmToken::Error.
      53         179 : AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) {
      54             :   SetError(SMLoc::getFromPointer(Loc), Msg);
      55             : 
      56         179 :   return AsmToken(AsmToken::Error, StringRef(Loc, CurPtr - Loc));
      57             : }
      58             : 
      59    58848696 : int AsmLexer::getNextChar() {
      60   117697392 :   if (CurPtr == CurBuf.end())
      61             :     return EOF;
      62    58829950 :   return (unsigned char)*CurPtr++;
      63             : }
      64             : 
      65             : /// LexFloatLiteral: [0-9]*[.][0-9]*([eE][+-]?[0-9]*)?
      66             : ///
      67             : /// The leading integral digit sequence and dot should have already been
      68             : /// consumed, some or all of the fractional digit sequence *can* have been
      69             : /// consumed.
      70       25265 : AsmToken AsmLexer::LexFloatLiteral() {
      71             :   // Skip the fractional digit sequence.
      72      153604 :   while (isDigit(*CurPtr))
      73       51537 :     ++CurPtr;
      74             : 
      75             :   // Check for exponent; we intentionally accept a slighlty wider set of
      76             :   // literals here and rely on the upstream client to reject invalid ones (e.g.,
      77             :   // "1e+").
      78       25265 :   if (*CurPtr == 'e' || *CurPtr == 'E') {
      79         120 :     ++CurPtr;
      80         120 :     if (*CurPtr == '-' || *CurPtr == '+')
      81         111 :       ++CurPtr;
      82         696 :     while (isDigit(*CurPtr))
      83         228 :       ++CurPtr;
      84             :   }
      85             : 
      86             :   return AsmToken(AsmToken::Real,
      87       25265 :                   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          33 : 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          33 :   if (*CurPtr == '.') {
     103          26 :     ++CurPtr;
     104             : 
     105             :     const char *FracStart = CurPtr;
     106         174 :     while (isHexDigit(*CurPtr))
     107          74 :       ++CurPtr;
     108             : 
     109          26 :     NoFracDigits = CurPtr == FracStart;
     110             :   }
     111             : 
     112          33 :   if (NoIntDigits && NoFracDigits)
     113             :     return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
     114          10 :                                  "expected at least one significand digit");
     115             : 
     116             :   // Make sure we do have some kind of proper exponent part
     117          28 :   if (*CurPtr != 'p' && *CurPtr != 'P')
     118             :     return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
     119           4 :                                  "expected exponent part 'p'");
     120          26 :   ++CurPtr;
     121             : 
     122          26 :   if (*CurPtr == '+' || *CurPtr == '-')
     123          16 :     ++CurPtr;
     124             : 
     125             :   // N.b. exponent digits are *not* hex
     126          26 :   const char *ExpStart = CurPtr;
     127         120 :   while (isDigit(*CurPtr))
     128          34 :     ++CurPtr;
     129             : 
     130          26 :   if (CurPtr == ExpStart)
     131             :     return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
     132          14 :                                  "expected at least one exponent digit");
     133             : 
     134          19 :   return AsmToken(AsmToken::Real, StringRef(TokStart, CurPtr - TokStart));
     135             : }
     136             : 
     137             : /// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@?]*
     138    36572170 : static bool IsIdentifierChar(char c, bool AllowAt) {
     139     4564230 :   return isAlnum(c) || c == '_' || c == '$' || c == '.' ||
     140     3535743 :          (c == '@' && AllowAt) || c == '?';
     141             : }
     142             : 
     143     3532662 : AsmToken AsmLexer::LexIdentifier() {
     144             :   // Check for floating point literals.
     145     3532662 :   if (CurPtr[-1] == '.' && isDigit(*CurPtr)) {
     146             :     // Disambiguate a .1243foo identifier from a floating literal.
     147         320 :     while (isDigit(*CurPtr))
     148          86 :       ++CurPtr;
     149          74 :     if (*CurPtr == 'e' || *CurPtr == 'E' ||
     150          73 :         !IsIdentifierChar(*CurPtr, AllowAtInIdentifier))
     151          12 :       return LexFloatLiteral();
     152             :   }
     153             : 
     154    36572097 :   while (IsIdentifierChar(*CurPtr, AllowAtInIdentifier))
     155    33039447 :     ++CurPtr;
     156             : 
     157             :   // Handle . as a special case.
     158     3532650 :   if (CurPtr == TokStart+1 && TokStart[0] == '.')
     159             :     return AsmToken(AsmToken::Dot, StringRef(TokStart, 1));
     160             : 
     161     3532161 :   return AsmToken(AsmToken::Identifier, StringRef(TokStart, CurPtr - TokStart));
     162             : }
     163             : 
     164             : /// LexSlash: Slash: /
     165             : ///           C-Style Comment: /* ... */
     166      398285 : AsmToken AsmLexer::LexSlash() {
     167      398285 :   switch (*CurPtr) {
     168         104 :   case '*':
     169         104 :     IsAtStartOfStatement = false;
     170             :     break; // C style comment.
     171      387585 :   case '/':
     172      387585 :     ++CurPtr;
     173      387585 :     return LexLineComment();
     174       10596 :   default:
     175       10596 :     IsAtStartOfStatement = false;
     176       10596 :     return AsmToken(AsmToken::Slash, StringRef(TokStart, 1));
     177             :   }
     178             : 
     179             :   // C Style comment.
     180         104 :   ++CurPtr;  // skip the star.
     181             :   const char *CommentTextStart = CurPtr;
     182        5266 :   while (CurPtr != CurBuf.end()) {
     183        2633 :     switch (*CurPtr++) {
     184         104 :     case '*':
     185             :       // End of the comment?
     186         104 :       if (*CurPtr != '/')
     187             :         break;
     188             :       // If we have a CommentConsumer, notify it about the comment.
     189         104 :       if (CommentConsumer) {
     190           0 :         CommentConsumer->HandleComment(
     191             :             SMLoc::getFromPointer(CommentTextStart),
     192           0 :             StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
     193             :       }
     194         104 :       ++CurPtr;   // End the */.
     195             :       return AsmToken(AsmToken::Comment,
     196         104 :                       StringRef(TokStart, CurPtr - TokStart));
     197             :     }
     198             :   }
     199           0 :   return ReturnError(TokStart, "unterminated comment");
     200             : }
     201             : 
     202             : /// LexLineComment: Comment: #[^\n]*
     203             : ///                        : //[^\n]*
     204      830932 : AsmToken AsmLexer::LexLineComment() {
     205             :   // Mark This as an end of statement with a body of the
     206             :   // comment. While it would be nicer to leave this two tokens,
     207             :   // backwards compatability with TargetParsers makes keeping this in this form
     208             :   // better.
     209      830932 :   const char *CommentTextStart = CurPtr;
     210      830932 :   int CurChar = getNextChar();
     211    45991759 :   while (CurChar != '\n' && CurChar != '\r' && CurChar != EOF)
     212    45160827 :     CurChar = getNextChar();
     213      830932 :   if (CurChar == '\r' && CurPtr != CurBuf.end() && *CurPtr == '\n')
     214           0 :     ++CurPtr;
     215             : 
     216             :   // If we have a CommentConsumer, notify it about the comment.
     217      830932 :   if (CommentConsumer) {
     218       75740 :     CommentConsumer->HandleComment(
     219             :         SMLoc::getFromPointer(CommentTextStart),
     220       75740 :         StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
     221             :   }
     222             : 
     223      830932 :   IsAtStartOfLine = true;
     224             :   // This is a whole line comment. leave newline
     225      830932 :   if (IsAtStartOfStatement)
     226             :     return AsmToken(AsmToken::EndOfStatement,
     227      802926 :                     StringRef(TokStart, CurPtr - TokStart));
     228       28006 :   IsAtStartOfStatement = true;
     229             : 
     230             :   return AsmToken(AsmToken::EndOfStatement,
     231       28006 :                   StringRef(TokStart, CurPtr - 1 - TokStart));
     232             : }
     233             : 
     234             : static void SkipIgnoredIntegerSuffix(const char *&CurPtr) {
     235             :   // Skip ULL, UL, U, L and LL suffices.
     236      641069 :   if (CurPtr[0] == 'U')
     237           7 :     ++CurPtr;
     238      641069 :   if (CurPtr[0] == 'L')
     239          16 :     ++CurPtr;
     240      641069 :   if (CurPtr[0] == 'L')
     241           4 :     ++CurPtr;
     242             : }
     243             : 
     244             : // Look ahead to search for first non-hex digit, if it's [hH], then we treat the
     245             : // integer as a hexadecimal, possibly with leading zeroes.
     246      618055 : static unsigned doLookAhead(const char *&CurPtr, unsigned DefaultRadix) {
     247             :   const char *FirstHex = nullptr;
     248      618055 :   const char *LookAhead = CurPtr;
     249             :   while (true) {
     250     2121278 :     if (isDigit(*LookAhead)) {
     251      442306 :       ++LookAhead;
     252             :     } else if (isHexDigit(*LookAhead)) {
     253         278 :       if (!FirstHex)
     254             :         FirstHex = LookAhead;
     255         278 :       ++LookAhead;
     256             :     } else {
     257             :       break;
     258             :     }
     259             :   }
     260      618055 :   bool isHex = *LookAhead == 'h' || *LookAhead == 'H';
     261      618055 :   CurPtr = isHex || !FirstHex ? LookAhead : FirstHex;
     262      618055 :   if (isHex)
     263           6 :     return 16;
     264             :   return DefaultRadix;
     265             : }
     266             : 
     267      641069 : static AsmToken intToken(StringRef Ref, APInt &Value)
     268             : {
     269      641069 :   if (Value.isIntN(64))
     270      641053 :     return AsmToken(AsmToken::Integer, Ref, Value);
     271          16 :   return AsmToken(AsmToken::BigNum, Ref, Value);
     272             : }
     273             : 
     274             : /// LexDigit: First character is [0-9].
     275             : ///   Local Label: [0-9][:]
     276             : ///   Forward/Backward Label: [0-9][fb]
     277             : ///   Binary integer: 0b[01]+
     278             : ///   Octal integer: 0[0-7]+
     279             : ///   Hex integer: 0x[0-9a-fA-F]+ or [0x]?[0-9][0-9a-fA-F]*[hH]
     280             : ///   Decimal integer: [1-9][0-9]*
     281      666393 : AsmToken AsmLexer::LexDigit() {
     282             :   // MASM-flavor binary integer: [01]+[bB]
     283             :   // MASM-flavor hexadecimal integer: [0-9][0-9a-fA-F]*[hH]
     284      666393 :   if (IsParsingMSInlineAsm && isdigit(CurPtr[-1])) {
     285         452 :     const char *FirstNonBinary = (CurPtr[-1] != '0' && CurPtr[-1] != '1') ?
     286             :                                    CurPtr - 1 : nullptr;
     287             :     const char *OldCurPtr = CurPtr;
     288         886 :     while (isHexDigit(*CurPtr)) {
     289         217 :       if (*CurPtr != '0' && *CurPtr != '1' && !FirstNonBinary)
     290             :         FirstNonBinary = CurPtr;
     291         217 :       ++CurPtr;
     292             :     }
     293             : 
     294             :     unsigned Radix = 0;
     295         452 :     if (*CurPtr == 'h' || *CurPtr == 'H') {
     296             :       // hexadecimal number
     297          25 :       ++CurPtr;
     298             :       Radix = 16;
     299         427 :     } else if (FirstNonBinary && FirstNonBinary + 1 == CurPtr &&
     300         222 :                (*FirstNonBinary == 'b' || *FirstNonBinary == 'B'))
     301             :       Radix = 2;
     302             : 
     303         452 :     if (Radix == 2 || Radix == 16) {
     304          28 :       StringRef Result(TokStart, CurPtr - TokStart);
     305             :       APInt Value(128, 0, true);
     306             : 
     307          28 :       if (Result.drop_back().getAsInteger(Radix, Value))
     308             :         return ReturnError(TokStart, Radix == 2 ? "invalid binary number" :
     309           0 :                              "invalid hexdecimal number");
     310             : 
     311             :       // MSVC accepts and ignores type suffices on integer literals.
     312             :       SkipIgnoredIntegerSuffix(CurPtr);
     313             : 
     314          28 :       return intToken(Result, Value);
     315             :    }
     316             : 
     317             :     // octal/decimal integers, or floating point numbers, fall through
     318         424 :     CurPtr = OldCurPtr;
     319             :   }
     320             : 
     321             :   // Decimal integer: [1-9][0-9]*
     322      666365 :   if (CurPtr[-1] != '0' || CurPtr[0] == '.') {
     323      561922 :     unsigned Radix = doLookAhead(CurPtr, 10);
     324             :     bool isHex = Radix == 16;
     325             :     // Check for floating point literals.
     326      561922 :     if (!isHex && (*CurPtr == '.' || *CurPtr == 'e')) {
     327       25253 :       ++CurPtr;
     328       25253 :       return LexFloatLiteral();
     329             :     }
     330             : 
     331      536669 :     StringRef Result(TokStart, CurPtr - TokStart);
     332             : 
     333             :     APInt Value(128, 0, true);
     334      536669 :     if (Result.getAsInteger(Radix, Value))
     335             :       return ReturnError(TokStart, !isHex ? "invalid decimal number" :
     336           0 :                            "invalid hexdecimal number");
     337             : 
     338             :     // Consume the [bB][hH].
     339      536669 :     if (Radix == 2 || Radix == 16)
     340           3 :       ++CurPtr;
     341             : 
     342             :     // The darwin/x86 (and x86-64) assembler accepts and ignores type
     343             :     // suffices on integer literals.
     344             :     SkipIgnoredIntegerSuffix(CurPtr);
     345             : 
     346      536669 :     return intToken(Result, Value);
     347             :   }
     348             : 
     349      104443 :   if (!IsParsingMSInlineAsm && ((*CurPtr == 'b') || (*CurPtr == 'B'))) {
     350          14 :     ++CurPtr;
     351             :     // See if we actually have "0b" as part of something like "jmp 0b\n"
     352          28 :     if (!isDigit(CurPtr[0])) {
     353          10 :       --CurPtr;
     354          10 :       StringRef Result(TokStart, CurPtr - TokStart);
     355             :       return AsmToken(AsmToken::Integer, Result, 0);
     356             :     }
     357             :     const char *NumStart = CurPtr;
     358         139 :     while (CurPtr[0] == '0' || CurPtr[0] == '1')
     359         135 :       ++CurPtr;
     360             : 
     361             :     // Requires at least one binary digit.
     362           4 :     if (CurPtr == NumStart)
     363           0 :       return ReturnError(TokStart, "invalid binary number");
     364             : 
     365           4 :     StringRef Result(TokStart, CurPtr - TokStart);
     366             : 
     367             :     APInt Value(128, 0, true);
     368           4 :     if (Result.substr(2).getAsInteger(2, Value))
     369           0 :       return ReturnError(TokStart, "invalid binary number");
     370             : 
     371             :     // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
     372             :     // suffixes on integer literals.
     373             :     SkipIgnoredIntegerSuffix(CurPtr);
     374             : 
     375           4 :     return intToken(Result, Value);
     376             :   }
     377             : 
     378      104429 :   if ((*CurPtr == 'x') || (*CurPtr == 'X')) {
     379       48296 :     ++CurPtr;
     380             :     const char *NumStart = CurPtr;
     381      353156 :     while (isHexDigit(CurPtr[0]))
     382      152430 :       ++CurPtr;
     383             : 
     384             :     // "0x.0p0" is valid, and "0x0p0" (but not "0xp0" for example, which will be
     385             :     // diagnosed by LexHexFloatLiteral).
     386       48296 :     if (CurPtr[0] == '.' || CurPtr[0] == 'p' || CurPtr[0] == 'P')
     387          33 :       return LexHexFloatLiteral(NumStart == CurPtr);
     388             : 
     389             :     // Otherwise requires at least one hex digit.
     390       48263 :     if (CurPtr == NumStart)
     391           6 :       return ReturnError(CurPtr-2, "invalid hexadecimal number");
     392             : 
     393             :     APInt Result(128, 0);
     394       96520 :     if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result))
     395           0 :       return ReturnError(TokStart, "invalid hexadecimal number");
     396             : 
     397             :     // Consume the optional [hH].
     398       48260 :     if (!IsParsingMSInlineAsm && (*CurPtr == 'h' || *CurPtr == 'H'))
     399           2 :       ++CurPtr;
     400             : 
     401             :     // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
     402             :     // suffixes on integer literals.
     403             :     SkipIgnoredIntegerSuffix(CurPtr);
     404             : 
     405       96520 :     return intToken(StringRef(TokStart, CurPtr - TokStart), Result);
     406             :   }
     407             : 
     408             :   // Either octal or hexadecimal.
     409             :   APInt Value(128, 0, true);
     410       56133 :   unsigned Radix = doLookAhead(CurPtr, 8);
     411             :   bool isHex = Radix == 16;
     412       56133 :   StringRef Result(TokStart, CurPtr - TokStart);
     413       56133 :   if (Result.getAsInteger(Radix, Value))
     414             :     return ReturnError(TokStart, !isHex ? "invalid octal number" :
     415          75 :                        "invalid hexdecimal number");
     416             : 
     417             :   // Consume the [hH].
     418       56108 :   if (Radix == 16)
     419           3 :     ++CurPtr;
     420             : 
     421             :   // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
     422             :   // suffixes on integer literals.
     423             :   SkipIgnoredIntegerSuffix(CurPtr);
     424             : 
     425       56108 :   return intToken(Result, Value);
     426             : }
     427             : 
     428             : /// LexSingleQuote: Integer: 'b'
     429         146 : AsmToken AsmLexer::LexSingleQuote() {
     430         146 :   int CurChar = getNextChar();
     431             : 
     432         146 :   if (CurChar == '\\')
     433           5 :     CurChar = getNextChar();
     434             : 
     435         146 :   if (CurChar == EOF)
     436           0 :     return ReturnError(TokStart, "unterminated single quote");
     437             : 
     438         146 :   CurChar = getNextChar();
     439             : 
     440         146 :   if (CurChar != '\'')
     441         252 :     return ReturnError(TokStart, "single quote way too long");
     442             : 
     443             :   // The idea here being that 'c' is basically just an integral
     444             :   // constant.
     445          20 :   StringRef Res = StringRef(TokStart,CurPtr - TokStart);
     446             :   long long Value;
     447             : 
     448             :   if (Res.startswith("\'\\")) {
     449             :     char theChar = Res[2];
     450           5 :     switch (theChar) {
     451           2 :       default: Value = theChar; break;
     452             :       case '\'': Value = '\''; break;
     453           1 :       case 't': Value = '\t'; break;
     454           1 :       case 'n': Value = '\n'; break;
     455           0 :       case 'b': Value = '\b'; break;
     456             :     }
     457             :   } else
     458          15 :     Value = TokStart[1];
     459             : 
     460          20 :   return AsmToken(AsmToken::Integer, Res, Value);
     461             : }
     462             : 
     463             : /// LexQuote: String: "..."
     464       72446 : AsmToken AsmLexer::LexQuote() {
     465       72446 :   int CurChar = getNextChar();
     466             :   // TODO: does gas allow multiline string constants?
     467      173539 :   while (CurChar != '"') {
     468      101093 :     if (CurChar == '\\') {
     469             :       // Allow \", etc.
     470         422 :       CurChar = getNextChar();
     471             :     }
     472             : 
     473      101093 :     if (CurChar == EOF)
     474           0 :       return ReturnError(TokStart, "unterminated string constant");
     475             : 
     476      101093 :     CurChar = getNextChar();
     477             :   }
     478             : 
     479       72446 :   return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart));
     480             : }
     481             : 
     482         734 : StringRef AsmLexer::LexUntilEndOfStatement() {
     483         734 :   TokStart = CurPtr;
     484             : 
     485       41438 :   while (!isAtStartOfComment(CurPtr) &&     // Start of line comment.
     486       20719 :          !isAtStatementSeparator(CurPtr) && // End of statement marker.
     487       41438 :          *CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) {
     488       19985 :     ++CurPtr;
     489             :   }
     490         734 :   return StringRef(TokStart, CurPtr-TokStart);
     491             : }
     492             : 
     493          30 : StringRef AsmLexer::LexUntilEndOfLine() {
     494          30 :   TokStart = CurPtr;
     495             : 
     496         649 :   while (*CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) {
     497         619 :     ++CurPtr;
     498             :   }
     499          30 :   return StringRef(TokStart, CurPtr-TokStart);
     500             : }
     501             : 
     502      510333 : size_t AsmLexer::peekTokens(MutableArrayRef<AsmToken> Buf,
     503             :                             bool ShouldSkipSpace) {
     504      510333 :   SaveAndRestore<const char *> SavedTokenStart(TokStart);
     505      510333 :   SaveAndRestore<const char *> SavedCurPtr(CurPtr);
     506      510333 :   SaveAndRestore<bool> SavedAtStartOfLine(IsAtStartOfLine);
     507      510333 :   SaveAndRestore<bool> SavedAtStartOfStatement(IsAtStartOfStatement);
     508      510333 :   SaveAndRestore<bool> SavedSkipSpace(SkipSpace, ShouldSkipSpace);
     509      510333 :   SaveAndRestore<bool> SavedIsPeeking(IsPeeking, true);
     510             :   std::string SavedErr = getErr();
     511             :   SMLoc SavedErrLoc = getErrLoc();
     512             : 
     513             :   size_t ReadCount;
     514     1243460 :   for (ReadCount = 0; ReadCount < Buf.size(); ++ReadCount) {
     515      733128 :     AsmToken Token = LexToken();
     516             : 
     517             :     Buf[ReadCount] = Token;
     518             : 
     519      733128 :     if (Token.is(AsmToken::Eof))
     520             :       break;
     521             :   }
     522             : 
     523             :   SetError(SavedErrLoc, SavedErr);
     524      510333 :   return ReadCount;
     525             : }
     526             : 
     527    12480988 : bool AsmLexer::isAtStartOfComment(const char *Ptr) {
     528    12480988 :   StringRef CommentString = MAI.getCommentString();
     529             : 
     530    12480988 :   if (CommentString.size() == 1)
     531    11595122 :     return CommentString[0] == Ptr[0];
     532             : 
     533             :   // Allow # preprocessor commments also be counted as comments for "##" cases
     534      885866 :   if (CommentString[1] == '#')
     535      120976 :     return CommentString[0] == Ptr[0];
     536             : 
     537      764890 :   return strncmp(Ptr, CommentString.data(), CommentString.size()) == 0;
     538             : }
     539             : 
     540    12260021 : bool AsmLexer::isAtStatementSeparator(const char *Ptr) {
     541    12260021 :   return strncmp(Ptr, MAI.getSeparatorString(),
     542    24520042 :                  strlen(MAI.getSeparatorString())) == 0;
     543             : }
     544             : 
     545    12682679 : AsmToken AsmLexer::LexToken() {
     546    12682679 :   TokStart = CurPtr;
     547             :   // This always consumes at least one character.
     548    12682679 :   int CurChar = getNextChar();
     549             : 
     550    12682679 :   if (!IsPeeking && CurChar == '#' && IsAtStartOfStatement) {
     551             :     // If this starts with a '#', this may be a cpp
     552             :     // hash directive and otherwise a line comment.
     553     1334460 :     AsmToken TokenBuf[2];
     554             :     MutableArrayRef<AsmToken> Buf(TokenBuf, 2);
     555      222410 :     size_t num = peekTokens(Buf, true);
     556             :     // There cannot be a space preceeding this
     557      222410 :     if (IsAtStartOfLine && num == 2 && TokenBuf[0].is(AsmToken::Integer) &&
     558         284 :         TokenBuf[1].is(AsmToken::String)) {
     559          30 :       CurPtr = TokStart; // reset curPtr;
     560          30 :       StringRef s = LexUntilEndOfLine();
     561             :       UnLex(TokenBuf[1]);
     562             :       UnLex(TokenBuf[0]);
     563             :       return AsmToken(AsmToken::HashDirective, s);
     564             :     }
     565      222380 :     return LexLineComment();
     566             :   }
     567             : 
     568    12460269 :   if (isAtStartOfComment(TokStart))
     569      220967 :     return LexLineComment();
     570             : 
     571    12239302 :   if (isAtStatementSeparator(TokStart)) {
     572      335773 :     CurPtr += strlen(MAI.getSeparatorString()) - 1;
     573      335773 :     IsAtStartOfLine = true;
     574      335773 :     IsAtStartOfStatement = true;
     575             :     return AsmToken(AsmToken::EndOfStatement,
     576      335773 :                     StringRef(TokStart, strlen(MAI.getSeparatorString())));
     577             :   }
     578             : 
     579             :   // If we're missing a newline at EOF, make sure we still get an
     580             :   // EndOfStatement token before the Eof token.
     581    11903529 :   if (CurChar == EOF && !IsAtStartOfStatement) {
     582         217 :     IsAtStartOfLine = true;
     583         217 :     IsAtStartOfStatement = true;
     584         217 :     return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
     585             :   }
     586    11903312 :   IsAtStartOfLine = false;
     587    11903312 :   bool OldIsAtStartOfStatement = IsAtStartOfStatement;
     588    11903312 :   IsAtStartOfStatement = false;
     589    11903312 :   switch (CurChar) {
     590     3532673 :   default:
     591             :     // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
     592     3532673 :     if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
     593     3532662 :       return LexIdentifier();
     594             : 
     595             :     // Unknown character, emit an error.
     596          22 :     return ReturnError(TokStart, "invalid character in input");
     597       18518 :   case EOF:
     598       18518 :     IsAtStartOfLine = true;
     599       18518 :     IsAtStartOfStatement = true;
     600       18518 :     return AsmToken(AsmToken::Eof, StringRef(TokStart, 0));
     601     2971224 :   case 0:
     602             :   case ' ':
     603             :   case '\t':
     604     2971224 :     IsAtStartOfStatement = OldIsAtStartOfStatement;
     605     7378157 :     while (*CurPtr == ' ' || *CurPtr == '\t')
     606     4406933 :       CurPtr++;
     607     2971224 :     if (SkipSpace)
     608     2969739 :       return LexToken(); // Ignore whitespace.
     609             :     else
     610        1485 :       return AsmToken(AsmToken::Space, StringRef(TokStart, CurPtr - TokStart));
     611           9 :   case '\r': {
     612           9 :     IsAtStartOfLine = true;
     613           9 :     IsAtStartOfStatement = true;
     614             :     // If this is a CR followed by LF, treat that as one token.
     615          18 :     if (CurPtr != CurBuf.end() && *CurPtr == '\n')
     616           9 :       ++CurPtr;
     617             :     return AsmToken(AsmToken::EndOfStatement,
     618           9 :                     StringRef(TokStart, CurPtr - TokStart));
     619             :   }
     620     1733441 :   case '\n':
     621     1733441 :     IsAtStartOfLine = true;
     622     1733441 :     IsAtStartOfStatement = true;
     623     1733441 :     return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
     624      343031 :   case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1));
     625        8399 :   case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1));
     626      177431 :   case '-': return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
     627         200 :   case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1));
     628      108426 :   case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1));
     629      107869 :   case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1));
     630      149654 :   case '[': return AsmToken(AsmToken::LBrac, StringRef(TokStart, 1));
     631      149747 :   case ']': return AsmToken(AsmToken::RBrac, StringRef(TokStart, 1));
     632       48826 :   case '{': return AsmToken(AsmToken::LCurly, StringRef(TokStart, 1));
     633       48938 :   case '}': return AsmToken(AsmToken::RCurly, StringRef(TokStart, 1));
     634        2018 :   case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1));
     635      879884 :   case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1));
     636       81292 :   case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1));
     637        2860 :   case '@': return AsmToken(AsmToken::At, StringRef(TokStart, 1));
     638        4285 :   case '\\': return AsmToken(AsmToken::BackSlash, StringRef(TokStart, 1));
     639        4610 :   case '=':
     640        4610 :     if (*CurPtr == '=') {
     641          55 :       ++CurPtr;
     642          55 :       return AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2));
     643             :     }
     644        4555 :     return AsmToken(AsmToken::Equal, StringRef(TokStart, 1));
     645        5316 :   case '|':
     646        5316 :     if (*CurPtr == '|') {
     647          10 :       ++CurPtr;
     648          10 :       return AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2));
     649             :     }
     650        5306 :     return AsmToken(AsmToken::Pipe, StringRef(TokStart, 1));
     651         203 :   case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1));
     652         102 :   case '&':
     653         102 :     if (*CurPtr == '&') {
     654           9 :       ++CurPtr;
     655           9 :       return AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2));
     656             :     }
     657          93 :     return AsmToken(AsmToken::Amp, StringRef(TokStart, 1));
     658        2411 :   case '!':
     659        2411 :     if (*CurPtr == '=') {
     660          87 :       ++CurPtr;
     661          87 :       return AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2));
     662             :     }
     663        2324 :     return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1));
     664      353602 :   case '%':
     665      353602 :     if (MAI.hasMipsExpressions()) {
     666             :       AsmToken::TokenKind Operator;
     667             :       unsigned OperatorLength;
     668             : 
     669             :       std::tie(Operator, OperatorLength) =
     670       12314 :           StringSwitch<std::pair<AsmToken::TokenKind, unsigned>>(
     671             :               StringRef(CurPtr))
     672             :               .StartsWith("call16", {AsmToken::PercentCall16, 7})
     673             :               .StartsWith("call_hi", {AsmToken::PercentCall_Hi, 8})
     674             :               .StartsWith("call_lo", {AsmToken::PercentCall_Lo, 8})
     675             :               .StartsWith("dtprel_hi", {AsmToken::PercentDtprel_Hi, 10})
     676             :               .StartsWith("dtprel_lo", {AsmToken::PercentDtprel_Lo, 10})
     677             :               .StartsWith("got_disp", {AsmToken::PercentGot_Disp, 9})
     678             :               .StartsWith("got_hi", {AsmToken::PercentGot_Hi, 7})
     679             :               .StartsWith("got_lo", {AsmToken::PercentGot_Lo, 7})
     680             :               .StartsWith("got_ofst", {AsmToken::PercentGot_Ofst, 9})
     681             :               .StartsWith("got_page", {AsmToken::PercentGot_Page, 9})
     682             :               .StartsWith("gottprel", {AsmToken::PercentGottprel, 9})
     683             :               .StartsWith("got", {AsmToken::PercentGot, 4})
     684             :               .StartsWith("gp_rel", {AsmToken::PercentGp_Rel, 7})
     685             :               .StartsWith("higher", {AsmToken::PercentHigher, 7})
     686             :               .StartsWith("highest", {AsmToken::PercentHighest, 8})
     687             :               .StartsWith("hi", {AsmToken::PercentHi, 3})
     688             :               .StartsWith("lo", {AsmToken::PercentLo, 3})
     689             :               .StartsWith("neg", {AsmToken::PercentNeg, 4})
     690             :               .StartsWith("pcrel_hi", {AsmToken::PercentPcrel_Hi, 9})
     691             :               .StartsWith("pcrel_lo", {AsmToken::PercentPcrel_Lo, 9})
     692             :               .StartsWith("tlsgd", {AsmToken::PercentTlsgd, 6})
     693             :               .StartsWith("tlsldm", {AsmToken::PercentTlsldm, 7})
     694             :               .StartsWith("tprel_hi", {AsmToken::PercentTprel_Hi, 9})
     695             :               .StartsWith("tprel_lo", {AsmToken::PercentTprel_Lo, 9})
     696             :               .Default({AsmToken::Percent, 1});
     697             : 
     698       12314 :       if (Operator != AsmToken::Percent) {
     699       12277 :         CurPtr += OperatorLength - 1;
     700       12277 :         return AsmToken(Operator, StringRef(TokStart, OperatorLength));
     701             :       }
     702             :     }
     703      341325 :     return AsmToken(AsmToken::Percent, StringRef(TokStart, 1));
     704      398285 :   case '/':
     705      398285 :     IsAtStartOfStatement = OldIsAtStartOfStatement;
     706      398285 :     return LexSlash();
     707       30429 :   case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1));
     708         146 :   case '\'': return LexSingleQuote();
     709       72446 :   case '"': return LexQuote();
     710      666393 :   case '0': case '1': case '2': case '3': case '4':
     711             :   case '5': case '6': case '7': case '8': case '9':
     712      666393 :     return LexDigit();
     713         568 :   case '<':
     714         568 :     switch (*CurPtr) {
     715         520 :     case '<':
     716         520 :       ++CurPtr;
     717         520 :       return AsmToken(AsmToken::LessLess, StringRef(TokStart, 2));
     718           9 :     case '=':
     719           9 :       ++CurPtr;
     720           9 :       return AsmToken(AsmToken::LessEqual, StringRef(TokStart, 2));
     721           7 :     case '>':
     722           7 :       ++CurPtr;
     723           7 :       return AsmToken(AsmToken::LessGreater, StringRef(TokStart, 2));
     724          32 :     default:
     725          32 :       return AsmToken(AsmToken::Less, StringRef(TokStart, 1));
     726             :     }
     727          76 :   case '>':
     728          76 :     switch (*CurPtr) {
     729          36 :     case '>':
     730          36 :       ++CurPtr;
     731          36 :       return AsmToken(AsmToken::GreaterGreater, StringRef(TokStart, 2));
     732           9 :     case '=':
     733           9 :       ++CurPtr;
     734           9 :       return AsmToken(AsmToken::GreaterEqual, StringRef(TokStart, 2));
     735          31 :     default:
     736          31 :       return AsmToken(AsmToken::Greater, StringRef(TokStart, 1));
     737             :     }
     738             : 
     739             :   // TODO: Quoted identifiers (objc methods etc)
     740             :   // local labels: [0-9][:]
     741             :   // Forward/backward labels: [0-9][fb]
     742             :   // Integers, fp constants, character constants.
     743             :   }
     744             : }

Generated by: LCOV version 1.13