LCOV - code coverage report
Current view: top level - lib/CodeGen/MIRParser - MILexer.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 411 415 99.0 %
Date: 2017-09-14 15:23:50 Functions: 33 33 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- MILexer.cpp - Machine instructions lexer implementation ----------===//
       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 file implements the lexing of machine instructions.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #include "MILexer.h"
      15             : #include "llvm/ADT/None.h"
      16             : #include "llvm/ADT/StringExtras.h"
      17             : #include "llvm/ADT/StringSwitch.h"
      18             : #include "llvm/ADT/Twine.h"
      19             : #include <cctype>
      20             : 
      21             : using namespace llvm;
      22             : 
      23             : namespace {
      24             : 
      25             : typedef function_ref<void(StringRef::iterator Loc, const Twine &)>
      26             :     ErrorCallbackType;
      27             : 
      28             : /// This class provides a way to iterate and get characters from the source
      29             : /// string.
      30             : class Cursor {
      31             :   const char *Ptr;
      32             :   const char *End;
      33             : 
      34             : public:
      35             :   Cursor(NoneType) : Ptr(nullptr), End(nullptr) {}
      36             : 
      37      416483 :   explicit Cursor(StringRef Str) {
      38      416483 :     Ptr = Str.data();
      39      416483 :     End = Ptr + Str.size();
      40             :   }
      41             : 
      42             :   bool isEOF() const { return Ptr == End; }
      43             : 
      44     7489776 :   char peek(int I = 0) const { return End - Ptr <= I ? 0 : Ptr[I]; }
      45             : 
      46     2511163 :   void advance(unsigned I = 1) { Ptr += I; }
      47             : 
      48     3393919 :   StringRef remaining() const { return StringRef(Ptr, End - Ptr); }
      49             : 
      50             :   StringRef upto(Cursor C) const {
      51             :     assert(C.Ptr >= Ptr && C.Ptr <= End);
      52      514433 :     return StringRef(Ptr, C.Ptr - Ptr);
      53             :   }
      54             : 
      55             :   StringRef::iterator location() const { return Ptr; }
      56             : 
      57             :   operator bool() const { return Ptr != nullptr; }
      58             : };
      59             : 
      60             : } // end anonymous namespace
      61             : 
      62      416423 : MIToken &MIToken::reset(TokenKind Kind, StringRef Range) {
      63      416423 :   this->Kind = Kind;
      64      416423 :   this->Range = Range;
      65      416423 :   return *this;
      66             : }
      67             : 
      68      138379 : MIToken &MIToken::setStringValue(StringRef StrVal) {
      69      138379 :   StringValue = StrVal;
      70      138379 :   return *this;
      71             : }
      72             : 
      73          60 : MIToken &MIToken::setOwnedStringValue(std::string StrVal) {
      74          60 :   StringValueStorage = std::move(StrVal);
      75         120 :   StringValue = StringValueStorage;
      76          60 :   return *this;
      77             : }
      78             : 
      79       63856 : MIToken &MIToken::setIntegerValue(APSInt IntVal) {
      80       63856 :   this->IntVal = std::move(IntVal);
      81       63856 :   return *this;
      82             : }
      83             : 
      84             : /// Skip the leading whitespace characters and return the updated cursor.
      85      416423 : static Cursor skipWhitespace(Cursor C) {
      86      928486 :   while (isblank(C.peek()))
      87      512063 :     C.advance();
      88      416423 :   return C;
      89             : }
      90             : 
      91      919495 : static bool isNewlineChar(char C) { return C == '\n' || C == '\r'; }
      92             : 
      93             : /// Skip a line comment and return the updated cursor.
      94      416423 : static Cursor skipComment(Cursor C) {
      95      410530 :   if (C.peek() != ';')
      96      400233 :     return C;
      97     1689124 :   while (!isNewlineChar(C.peek()) && !C.isEOF())
      98      828372 :     C.advance();
      99       16190 :   return C;
     100             : }
     101             : 
     102             : /// Return true if the given character satisfies the following regular
     103             : /// expression: [-a-zA-Z$._0-9]
     104      869547 : static bool isIdentifierChar(char C) {
     105     1002928 :   return isalpha(C) || isdigit(C) || C == '_' || C == '-' || C == '.' ||
     106     1002928 :          C == '$';
     107             : }
     108             : 
     109             : /// Unescapes the given string value.
     110             : ///
     111             : /// Expects the string value to be quoted.
     112          60 : static std::string unescapeQuotedString(StringRef Value) {
     113             :   assert(Value.front() == '"' && Value.back() == '"');
     114         180 :   Cursor C = Cursor(Value.substr(1, Value.size() - 2));
     115             : 
     116          60 :   std::string Str;
     117          60 :   Str.reserve(C.remaining().size());
     118         932 :   while (!C.isEOF()) {
     119         872 :     char Char = C.peek();
     120         872 :     if (Char == '\\') {
     121          44 :       if (C.peek(1) == '\\') {
     122             :         // Two '\' become one
     123           2 :         Str += '\\';
     124           4 :         C.advance(2);
     125           2 :         continue;
     126             :       }
     127         120 :       if (isxdigit(C.peek(1)) && isxdigit(C.peek(2))) {
     128         200 :         Str += hexDigitValue(C.peek(1)) * 16 + hexDigitValue(C.peek(2));
     129          80 :         C.advance(3);
     130          40 :         continue;
     131             :       }
     132             :     }
     133        1660 :     Str += Char;
     134         830 :     C.advance();
     135             :   }
     136          60 :   return Str;
     137             : }
     138             : 
     139             : /// Lex a string constant using the following regular expression: \"[^\"]*\"
     140          61 : static Cursor lexStringConstant(Cursor C, ErrorCallbackType ErrorCallback) {
     141             :   assert(C.peek() == '"');
     142        2058 :   for (C.advance(); C.peek() != '"'; C.advance()) {
     143        2907 :     if (C.isEOF() || isNewlineChar(C.peek())) {
     144           2 :       ErrorCallback(
     145             :           C.location(),
     146             :           "end of machine instruction reached before the closing '\"'");
     147           1 :       return None;
     148             :     }
     149             :   }
     150         120 :   C.advance();
     151          60 :   return C;
     152             : }
     153             : 
     154        1853 : static Cursor lexName(Cursor C, MIToken &Token, MIToken::TokenKind Type,
     155             :                       unsigned PrefixLength, ErrorCallbackType ErrorCallback) {
     156        1853 :   auto Range = C;
     157        3706 :   C.advance(PrefixLength);
     158        1853 :   if (C.peek() == '"') {
     159          61 :     if (Cursor R = lexStringConstant(C, ErrorCallback)) {
     160         120 :       StringRef String = Range.upto(R);
     161          60 :       Token.reset(Type, String)
     162          60 :           .setOwnedStringValue(
     163         180 :               unescapeQuotedString(String.drop_front(PrefixLength)));
     164          60 :       return R;
     165             :     }
     166           1 :     Token.reset(MIToken::Error, Range.remaining());
     167           1 :     return Range;
     168             :   }
     169       12369 :   while (isIdentifierChar(C.peek()))
     170       10577 :     C.advance();
     171        3584 :   Token.reset(Type, Range.upto(C))
     172        5376 :       .setStringValue(Range.upto(C).drop_front(PrefixLength));
     173        1792 :   return C;
     174             : }
     175             : 
     176      410530 : static Cursor maybeLexIntegerOrScalarType(Cursor C, MIToken &Token) {
     177     1221478 :   if ((C.peek() != 'i' && C.peek() != 's' && C.peek() != 'p') ||
     178       28685 :       !isdigit(C.peek(1)))
     179      395805 :     return None;
     180       14725 :   char Kind = C.peek();
     181       14725 :   auto Range = C;
     182       14725 :   C.advance(); // Skip 'i', 's', or 'p'
     183       39973 :   while (isdigit(C.peek()))
     184       25248 :     C.advance();
     185             : 
     186       14725 :   Token.reset(Kind == 'i'
     187             :                   ? MIToken::IntegerType
     188       14358 :                   : (Kind == 's' ? MIToken::ScalarType : MIToken::PointerType),
     189       29450 :               Range.upto(C));
     190       14725 :   return C;
     191             : }
     192             : 
     193       74573 : static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
     194       74573 :   return StringSwitch<MIToken::TokenKind>(Identifier)
     195      223719 :       .Case("_", MIToken::underscore)
     196      223719 :       .Case("implicit", MIToken::kw_implicit)
     197      223719 :       .Case("implicit-def", MIToken::kw_implicit_define)
     198      223719 :       .Case("def", MIToken::kw_def)
     199      223719 :       .Case("dead", MIToken::kw_dead)
     200      223719 :       .Case("killed", MIToken::kw_killed)
     201      223719 :       .Case("undef", MIToken::kw_undef)
     202      223719 :       .Case("internal", MIToken::kw_internal)
     203      223719 :       .Case("early-clobber", MIToken::kw_early_clobber)
     204      223719 :       .Case("debug-use", MIToken::kw_debug_use)
     205      223719 :       .Case("tied-def", MIToken::kw_tied_def)
     206      223719 :       .Case("frame-setup", MIToken::kw_frame_setup)
     207      223719 :       .Case("debug-location", MIToken::kw_debug_location)
     208      223719 :       .Case("same_value", MIToken::kw_cfi_same_value)
     209      223719 :       .Case("offset", MIToken::kw_cfi_offset)
     210      223719 :       .Case("def_cfa_register", MIToken::kw_cfi_def_cfa_register)
     211      223719 :       .Case("def_cfa_offset", MIToken::kw_cfi_def_cfa_offset)
     212      223719 :       .Case("def_cfa", MIToken::kw_cfi_def_cfa)
     213      223719 :       .Case("blockaddress", MIToken::kw_blockaddress)
     214      223719 :       .Case("intrinsic", MIToken::kw_intrinsic)
     215      223719 :       .Case("target-index", MIToken::kw_target_index)
     216      223719 :       .Case("half", MIToken::kw_half)
     217      223719 :       .Case("float", MIToken::kw_float)
     218      223719 :       .Case("double", MIToken::kw_double)
     219      223719 :       .Case("x86_fp80", MIToken::kw_x86_fp80)
     220      223719 :       .Case("fp128", MIToken::kw_fp128)
     221      223719 :       .Case("ppc_fp128", MIToken::kw_ppc_fp128)
     222      223719 :       .Case("target-flags", MIToken::kw_target_flags)
     223      223719 :       .Case("volatile", MIToken::kw_volatile)
     224      223719 :       .Case("non-temporal", MIToken::kw_non_temporal)
     225      223719 :       .Case("dereferenceable", MIToken::kw_dereferenceable)
     226      223719 :       .Case("invariant", MIToken::kw_invariant)
     227      223719 :       .Case("align", MIToken::kw_align)
     228      223719 :       .Case("stack", MIToken::kw_stack)
     229      223719 :       .Case("got", MIToken::kw_got)
     230      223719 :       .Case("jump-table", MIToken::kw_jump_table)
     231      223719 :       .Case("constant-pool", MIToken::kw_constant_pool)
     232      223719 :       .Case("call-entry", MIToken::kw_call_entry)
     233      223719 :       .Case("liveout", MIToken::kw_liveout)
     234      223719 :       .Case("address-taken", MIToken::kw_address_taken)
     235      223719 :       .Case("landing-pad", MIToken::kw_landing_pad)
     236      223719 :       .Case("liveins", MIToken::kw_liveins)
     237      223719 :       .Case("successors", MIToken::kw_successors)
     238      223719 :       .Case("floatpred", MIToken::kw_floatpred)
     239      223719 :       .Case("intpred", MIToken::kw_intpred)
     240      223719 :       .Default(MIToken::Identifier);
     241             : }
     242             : 
     243      386663 : static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) {
     244      707331 :   if (!isalpha(C.peek()) && C.peek() != '_')
     245      312090 :     return None;
     246             :   auto Range = C;
     247      587353 :   while (isIdentifierChar(C.peek()))
     248      512780 :     C.advance();
     249      149146 :   auto Identifier = Range.upto(C);
     250       74573 :   Token.reset(getIdentifierKind(Identifier), Identifier)
     251       74573 :       .setStringValue(Identifier);
     252       74573 :   return C;
     253             : }
     254             : 
     255      395805 : static Cursor maybeLexMachineBasicBlock(Cursor C, MIToken &Token,
     256             :                                         ErrorCallbackType ErrorCallback) {
     257      395805 :   bool IsReference = C.remaining().startswith("%bb.");
     258      392832 :   if (!IsReference && !C.remaining().startswith("bb."))
     259      386663 :     return None;
     260        9142 :   auto Range = C;
     261       18284 :   unsigned PrefixLength = IsReference ? 4 : 3;
     262       18284 :   C.advance(PrefixLength); // Skip '%bb.' or 'bb.'
     263        9142 :   if (!isdigit(C.peek())) {
     264           1 :     Token.reset(MIToken::Error, C.remaining());
     265           2 :     ErrorCallback(C.location(), "expected a number after '%bb.'");
     266           1 :     return C;
     267             :   }
     268             :   auto NumberRange = C;
     269       18554 :   while (isdigit(C.peek()))
     270        9413 :     C.advance();
     271       18282 :   StringRef Number = NumberRange.upto(C);
     272        9141 :   unsigned StringOffset = PrefixLength + Number.size(); // Drop '%bb.<id>'
     273        9141 :   if (C.peek() == '.') {
     274        6732 :     C.advance(); // Skip '.'
     275        3366 :     ++StringOffset;
     276       21974 :     while (isIdentifierChar(C.peek()))
     277       18608 :       C.advance();
     278             :   }
     279             :   Token.reset(IsReference ? MIToken::MachineBasicBlock
     280             :                           : MIToken::MachineBasicBlockLabel,
     281       18282 :               Range.upto(C))
     282       18282 :       .setIntegerValue(APSInt(Number))
     283       27423 :       .setStringValue(Range.upto(C).drop_front(StringOffset));
     284        9141 :   return C;
     285             : }
     286             : 
     287      937251 : static Cursor maybeLexIndex(Cursor C, MIToken &Token, StringRef Rule,
     288             :                             MIToken::TokenKind Kind) {
     289      940551 :   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
     290      935601 :     return None;
     291        1650 :   auto Range = C;
     292        3300 :   C.advance(Rule.size());
     293        1650 :   auto NumberRange = C;
     294        3309 :   while (isdigit(C.peek()))
     295        1659 :     C.advance();
     296        6600 :   Token.reset(Kind, Range.upto(C)).setIntegerValue(APSInt(NumberRange.upto(C)));
     297        1650 :   return C;
     298             : }
     299             : 
     300      312065 : static Cursor maybeLexIndexAndName(Cursor C, MIToken &Token, StringRef Rule,
     301             :                                    MIToken::TokenKind Kind) {
     302      312425 :   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
     303      311886 :     return None;
     304         179 :   auto Range = C;
     305         358 :   C.advance(Rule.size());
     306         179 :   auto NumberRange = C;
     307         358 :   while (isdigit(C.peek()))
     308         179 :     C.advance();
     309         358 :   StringRef Number = NumberRange.upto(C);
     310         179 :   unsigned StringOffset = Rule.size() + Number.size();
     311         179 :   if (C.peek() == '.') {
     312         128 :     C.advance();
     313          64 :     ++StringOffset;
     314         385 :     while (isIdentifierChar(C.peek()))
     315         321 :       C.advance();
     316             :   }
     317         358 :   Token.reset(Kind, Range.upto(C))
     318         358 :       .setIntegerValue(APSInt(Number))
     319         537 :       .setStringValue(Range.upto(C).drop_front(StringOffset));
     320         179 :   return C;
     321             : }
     322             : 
     323             : static Cursor maybeLexJumpTableIndex(Cursor C, MIToken &Token) {
     324      312090 :   return maybeLexIndex(C, Token, "%jump-table.", MIToken::JumpTableIndex);
     325             : }
     326             : 
     327             : static Cursor maybeLexStackObject(Cursor C, MIToken &Token) {
     328      312065 :   return maybeLexIndexAndName(C, Token, "%stack.", MIToken::StackObject);
     329             : }
     330             : 
     331             : static Cursor maybeLexFixedStackObject(Cursor C, MIToken &Token) {
     332      311886 :   return maybeLexIndex(C, Token, "%fixed-stack.", MIToken::FixedStackObject);
     333             : }
     334             : 
     335             : static Cursor maybeLexConstantPoolItem(Cursor C, MIToken &Token) {
     336      311784 :   return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem);
     337             : }
     338             : 
     339      311752 : static Cursor maybeLexSubRegisterIndex(Cursor C, MIToken &Token,
     340             :                                        ErrorCallbackType ErrorCallback) {
     341      311752 :   const StringRef Rule = "%subreg.";
     342      311858 :   if (!C.remaining().startswith(Rule))
     343      311646 :     return None;
     344         106 :   return lexName(C, Token, MIToken::SubRegisterIndex, Rule.size(),
     345         106 :                  ErrorCallback);
     346             : }
     347             : 
     348      311646 : static Cursor maybeLexIRBlock(Cursor C, MIToken &Token,
     349             :                               ErrorCallbackType ErrorCallback) {
     350      311646 :   const StringRef Rule = "%ir-block.";
     351      313103 :   if (!C.remaining().startswith(Rule))
     352      310189 :     return None;
     353        2914 :   if (isdigit(C.peek(Rule.size())))
     354        1447 :     return maybeLexIndex(C, Token, Rule, MIToken::IRBlock);
     355          10 :   return lexName(C, Token, MIToken::NamedIRBlock, Rule.size(), ErrorCallback);
     356             : }
     357             : 
     358      310189 : static Cursor maybeLexIRValue(Cursor C, MIToken &Token,
     359             :                               ErrorCallbackType ErrorCallback) {
     360      310189 :   const StringRef Rule = "%ir.";
     361      311043 :   if (!C.remaining().startswith(Rule))
     362      309335 :     return None;
     363        1708 :   if (isdigit(C.peek(Rule.size())))
     364          44 :     return maybeLexIndex(C, Token, Rule, MIToken::IRValue);
     365         810 :   return lexName(C, Token, MIToken::NamedIRValue, Rule.size(), ErrorCallback);
     366             : }
     367             : 
     368          27 : static Cursor maybeLexStringConstant(Cursor C, MIToken &Token,
     369             :                                      ErrorCallbackType ErrorCallback) {
     370          27 :   if (C.peek() != '"')
     371           1 :     return None;
     372             :   return lexName(C, Token, MIToken::StringConstant, /*PrefixLength=*/0,
     373          26 :                  ErrorCallback);
     374             : }
     375             : 
     376       28434 : static Cursor lexVirtualRegister(Cursor C, MIToken &Token) {
     377       28434 :   auto Range = C;
     378       56868 :   C.advance(); // Skip '%'
     379       28434 :   auto NumberRange = C;
     380       61855 :   while (isdigit(C.peek()))
     381       33421 :     C.advance();
     382       56868 :   Token.reset(MIToken::VirtualRegister, Range.upto(C))
     383       85302 :       .setIntegerValue(APSInt(NumberRange.upto(C)));
     384       28434 :   return C;
     385             : }
     386             : 
     387             : /// Returns true for a character allowed in a register name.
     388             : static bool isRegisterChar(char C) {
     389      246711 :   return isIdentifierChar(C) && C != '.';
     390             : }
     391             : 
     392      309335 : static Cursor maybeLexRegister(Cursor C, MIToken &Token) {
     393      309335 :   if (C.peek() != '%')
     394      228465 :     return None;
     395       80870 :   if (isdigit(C.peek(1)))
     396       28434 :     return lexVirtualRegister(C, Token);
     397       52436 :   auto Range = C;
     398       52436 :   C.advance(); // Skip '%'
     399      493422 :   while (isRegisterChar(C.peek()))
     400      194275 :     C.advance();
     401      104872 :   Token.reset(MIToken::NamedRegister, Range.upto(C))
     402      157308 :       .setStringValue(Range.upto(C).drop_front(1)); // Drop the '%'
     403       52436 :   return C;
     404             : }
     405             : 
     406      228465 : static Cursor maybeLexGlobalValue(Cursor C, MIToken &Token,
     407             :                                   ErrorCallbackType ErrorCallback) {
     408      228465 :   if (C.peek() != '@')
     409      227658 :     return None;
     410         807 :   if (!isdigit(C.peek(1)))
     411             :     return lexName(C, Token, MIToken::NamedGlobalValue, /*PrefixLength=*/1,
     412         799 :                    ErrorCallback);
     413           8 :   auto Range = C;
     414          16 :   C.advance(1); // Skip the '@'
     415           8 :   auto NumberRange = C;
     416          16 :   while (isdigit(C.peek()))
     417           8 :     C.advance();
     418          16 :   Token.reset(MIToken::GlobalValue, Range.upto(C))
     419          24 :       .setIntegerValue(APSInt(NumberRange.upto(C)));
     420           8 :   return C;
     421             : }
     422             : 
     423      227658 : static Cursor maybeLexExternalSymbol(Cursor C, MIToken &Token,
     424             :                                      ErrorCallbackType ErrorCallback) {
     425      227658 :   if (C.peek() != '$')
     426      227556 :     return None;
     427             :   return lexName(C, Token, MIToken::ExternalSymbol, /*PrefixLength=*/1,
     428         102 :                  ErrorCallback);
     429             : }
     430             : 
     431             : static bool isValidHexFloatingPointPrefix(char C) {
     432         688 :   return C == 'H' || C == 'K' || C == 'L' || C == 'M';
     433             : }
     434             : 
     435          34 : static Cursor lexFloatingPointLiteral(Cursor Range, Cursor C, MIToken &Token) {
     436          34 :   C.advance();
     437             :   // Skip over [0-9]*([eE][-+]?[0-9]+)?
     438         128 :   while (isdigit(C.peek()))
     439          94 :     C.advance();
     440          80 :   if ((C.peek() == 'e' || C.peek() == 'E') &&
     441          24 :       (isdigit(C.peek(1)) ||
     442          36 :        ((C.peek(1) == '-' || C.peek(1) == '+') && isdigit(C.peek(2))))) {
     443          12 :     C.advance(2);
     444          36 :     while (isdigit(C.peek()))
     445          24 :       C.advance();
     446             :   }
     447          68 :   Token.reset(MIToken::FloatingPointLiteral, Range.upto(C));
     448          34 :   return C;
     449             : }
     450             : 
     451      227556 : static Cursor maybeLexHexadecimalLiteral(Cursor C, MIToken &Token) {
     452      245578 :   if (C.peek() != '0' || (C.peek(1) != 'x' && C.peek(1) != 'X'))
     453      226868 :     return None;
     454         688 :   Cursor Range = C;
     455        1376 :   C.advance(2);
     456         688 :   unsigned PrefLen = 2;
     457         688 :   if (isValidHexFloatingPointPrefix(C.peek())) {
     458           4 :     C.advance();
     459           2 :     PrefLen++;
     460             :   }
     461        6154 :   while (isxdigit(C.peek()))
     462        5466 :     C.advance();
     463        1376 :   StringRef StrVal = Range.upto(C);
     464         688 :   if (StrVal.size() <= PrefLen)
     465           0 :     return None;
     466         688 :   if (PrefLen == 2)
     467        1372 :     Token.reset(MIToken::HexLiteral, Range.upto(C));
     468             :   else // It must be 3, which means that there was a floating-point prefix.
     469           4 :     Token.reset(MIToken::FloatingPointLiteral, Range.upto(C));
     470         688 :   return C;
     471             : }
     472             : 
     473      226868 : static Cursor maybeLexNumericalLiteral(Cursor C, MIToken &Token) {
     474      430316 :   if (!isdigit(C.peek()) && (C.peek() != '-' || !isdigit(C.peek(1))))
     475      202390 :     return None;
     476       24478 :   auto Range = C;
     477       24478 :   C.advance();
     478       34929 :   while (isdigit(C.peek()))
     479       10451 :     C.advance();
     480       24471 :   if (C.peek() == '.')
     481          34 :     return lexFloatingPointLiteral(Range, C, Token);
     482       48888 :   StringRef StrVal = Range.upto(C);
     483       48888 :   Token.reset(MIToken::IntegerLiteral, StrVal).setIntegerValue(APSInt(StrVal));
     484       24444 :   return C;
     485             : }
     486             : 
     487          86 : static MIToken::TokenKind getMetadataKeywordKind(StringRef Identifier) {
     488          86 :   return StringSwitch<MIToken::TokenKind>(Identifier)
     489         258 :       .Case("!tbaa", MIToken::md_tbaa)
     490         258 :       .Case("!alias.scope", MIToken::md_alias_scope)
     491         258 :       .Case("!noalias", MIToken::md_noalias)
     492         258 :       .Case("!range", MIToken::md_range)
     493         258 :       .Case("!DIExpression", MIToken::md_diexpr)
     494         258 :       .Default(MIToken::Error);
     495             : }
     496             : 
     497      202390 : static Cursor maybeLexExlaim(Cursor C, MIToken &Token,
     498             :                              ErrorCallbackType ErrorCallback) {
     499      202390 :   if (C.peek() != '!')
     500      200697 :     return None;
     501        1693 :   auto Range = C;
     502        3386 :   C.advance(1);
     503        1693 :   if (isdigit(C.peek()) || !isIdentifierChar(C.peek())) {
     504        3214 :     Token.reset(MIToken::exclaim, Range.upto(C));
     505        1607 :     return C;
     506             :   }
     507         667 :   while (isIdentifierChar(C.peek()))
     508         581 :     C.advance();
     509         172 :   StringRef StrVal = Range.upto(C);
     510          86 :   Token.reset(getMetadataKeywordKind(StrVal), StrVal);
     511          86 :   if (Token.isError())
     512           2 :     ErrorCallback(Token.location(),
     513           4 :                   "use of unknown metadata keyword '" + StrVal + "'");
     514          86 :   return C;
     515             : }
     516             : 
     517             : static MIToken::TokenKind symbolToken(char C) {
     518      198858 :   switch (C) {
     519             :   case ',':
     520             :     return MIToken::comma;
     521             :   case '.':
     522             :     return MIToken::dot;
     523             :   case '=':
     524             :     return MIToken::equal;
     525             :   case ':':
     526             :     return MIToken::colon;
     527             :   case '(':
     528             :     return MIToken::lparen;
     529             :   case ')':
     530             :     return MIToken::rparen;
     531             :   case '{':
     532             :     return MIToken::lbrace;
     533             :   case '}':
     534             :     return MIToken::rbrace;
     535             :   case '+':
     536             :     return MIToken::plus;
     537             :   case '-':
     538             :     return MIToken::minus;
     539             :   case '<':
     540             :     return MIToken::less;
     541             :   case '>':
     542             :     return MIToken::greater;
     543             :   default:
     544             :     return MIToken::Error;
     545             :   }
     546             : }
     547             : 
     548      200697 : static Cursor maybeLexSymbol(Cursor C, MIToken &Token) {
     549             :   MIToken::TokenKind Kind;
     550      200697 :   unsigned Length = 1;
     551      214207 :   if (C.peek() == ':' && C.peek(1) == ':') {
     552             :     Kind = MIToken::coloncolon;
     553             :     Length = 2;
     554             :   } else
     555      397716 :     Kind = symbolToken(C.peek());
     556      198858 :   if (Kind == MIToken::Error)
     557       67994 :     return None;
     558      132703 :   auto Range = C;
     559      265406 :   C.advance(Length);
     560      265406 :   Token.reset(Kind, Range.upto(C));
     561      132703 :   return C;
     562             : }
     563             : 
     564       67994 : static Cursor maybeLexNewline(Cursor C, MIToken &Token) {
     565      135988 :   if (!isNewlineChar(C.peek()))
     566         285 :     return None;
     567       67709 :   auto Range = C;
     568      135418 :   C.advance();
     569      135418 :   Token.reset(MIToken::Newline, Range.upto(C));
     570       67709 :   return C;
     571             : }
     572             : 
     573         285 : static Cursor maybeLexEscapedIRValue(Cursor C, MIToken &Token,
     574             :                                      ErrorCallbackType ErrorCallback) {
     575         285 :   if (C.peek() != '`')
     576          27 :     return None;
     577         258 :   auto Range = C;
     578         516 :   C.advance();
     579         258 :   auto StrRange = C;
     580        6228 :   while (C.peek() != '`') {
     581       17910 :     if (C.isEOF() || isNewlineChar(C.peek())) {
     582           0 :       ErrorCallback(
     583             :           C.location(),
     584             :           "end of machine instruction reached before the closing '`'");
     585           0 :       Token.reset(MIToken::Error, Range.remaining());
     586           0 :       return C;
     587             :     }
     588        5970 :     C.advance();
     589             :   }
     590         516 :   StringRef Value = StrRange.upto(C);
     591         516 :   C.advance();
     592         516 :   Token.reset(MIToken::QuotedIRValue, Range.upto(C)).setStringValue(Value);
     593         258 :   return C;
     594             : }
     595             : 
     596      416423 : StringRef llvm::lexMIToken(StringRef Source, MIToken &Token,
     597             :                            ErrorCallbackType ErrorCallback) {
     598      416423 :   auto C = skipComment(skipWhitespace(Cursor(Source)));
     599      416423 :   if (C.isEOF()) {
     600        5893 :     Token.reset(MIToken::Eof, C.remaining());
     601             :     return C.remaining();
     602             :   }
     603             : 
     604      410530 :   if (Cursor R = maybeLexIntegerOrScalarType(C, Token))
     605       14725 :     return R.remaining();
     606      395805 :   if (Cursor R = maybeLexMachineBasicBlock(C, Token, ErrorCallback))
     607        9142 :     return R.remaining();
     608      386663 :   if (Cursor R = maybeLexIdentifier(C, Token))
     609       74573 :     return R.remaining();
     610      312090 :   if (Cursor R = maybeLexJumpTableIndex(C, Token))
     611          25 :     return R.remaining();
     612      312065 :   if (Cursor R = maybeLexStackObject(C, Token))
     613         179 :     return R.remaining();
     614      311886 :   if (Cursor R = maybeLexFixedStackObject(C, Token))
     615         102 :     return R.remaining();
     616      311784 :   if (Cursor R = maybeLexConstantPoolItem(C, Token))
     617          32 :     return R.remaining();
     618      311752 :   if (Cursor R = maybeLexSubRegisterIndex(C, Token, ErrorCallback))
     619         106 :     return R.remaining();
     620      311646 :   if (Cursor R = maybeLexIRBlock(C, Token, ErrorCallback))
     621        1457 :     return R.remaining();
     622      310189 :   if (Cursor R = maybeLexIRValue(C, Token, ErrorCallback))
     623         854 :     return R.remaining();
     624      309335 :   if (Cursor R = maybeLexRegister(C, Token))
     625       80870 :     return R.remaining();
     626      228465 :   if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback))
     627         807 :     return R.remaining();
     628      227658 :   if (Cursor R = maybeLexExternalSymbol(C, Token, ErrorCallback))
     629         102 :     return R.remaining();
     630      227556 :   if (Cursor R = maybeLexHexadecimalLiteral(C, Token))
     631         688 :     return R.remaining();
     632      226868 :   if (Cursor R = maybeLexNumericalLiteral(C, Token))
     633       24478 :     return R.remaining();
     634      202390 :   if (Cursor R = maybeLexExlaim(C, Token, ErrorCallback))
     635        1693 :     return R.remaining();
     636      200697 :   if (Cursor R = maybeLexSymbol(C, Token))
     637      132703 :     return R.remaining();
     638       67994 :   if (Cursor R = maybeLexNewline(C, Token))
     639       67709 :     return R.remaining();
     640         285 :   if (Cursor R = maybeLexEscapedIRValue(C, Token, ErrorCallback))
     641         258 :     return R.remaining();
     642          27 :   if (Cursor R = maybeLexStringConstant(C, Token, ErrorCallback))
     643          26 :     return R.remaining();
     644             : 
     645           1 :   Token.reset(MIToken::Error, C.remaining());
     646           2 :   ErrorCallback(C.location(),
     647           7 :                 Twine("unexpected character '") + Twine(C.peek()) + "'");
     648             :   return C.remaining();
     649             : }

Generated by: LCOV version 1.13