LCOV - code coverage report
Current view: top level - lib/CodeGen/MIRParser - MILexer.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 272 277 98.2 %
Date: 2018-07-13 00:08:38 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/APSInt.h"
      16             : #include "llvm/ADT/None.h"
      17             : #include "llvm/ADT/STLExtras.h"
      18             : #include "llvm/ADT/StringExtras.h"
      19             : #include "llvm/ADT/StringSwitch.h"
      20             : #include "llvm/ADT/StringRef.h"
      21             : #include "llvm/ADT/Twine.h"
      22             : #include <algorithm>
      23             : #include <cassert>
      24             : #include <cctype>
      25             : #include <string>
      26             : 
      27             : using namespace llvm;
      28             : 
      29             : namespace {
      30             : 
      31             : using ErrorCallbackType =
      32             :     function_ref<void(StringRef::iterator Loc, const Twine &)>;
      33             : 
      34             : /// This class provides a way to iterate and get characters from the source
      35             : /// string.
      36             : class Cursor {
      37             :   const char *Ptr = nullptr;
      38             :   const char *End = nullptr;
      39             : 
      40             : public:
      41             :   Cursor(NoneType) {}
      42             : 
      43      786979 :   explicit Cursor(StringRef Str) {
      44      786979 :     Ptr = Str.data();
      45      787537 :     End = Ptr + Str.size();
      46             :   }
      47             : 
      48             :   bool isEOF() const { return Ptr == End; }
      49             : 
      50    13810382 :   char peek(int I = 0) const { return End - Ptr <= I ? 0 : Ptr[I]; }
      51             : 
      52     5829754 :   void advance(unsigned I = 1) { Ptr += I; }
      53             : 
      54     5737164 :   StringRef remaining() const { return StringRef(Ptr, End - Ptr); }
      55             : 
      56             :   StringRef upto(Cursor C) const {
      57             :     assert(C.Ptr >= Ptr && C.Ptr <= End);
      58      700501 :     return StringRef(Ptr, C.Ptr - Ptr);
      59             :   }
      60             : 
      61             :   StringRef::iterator location() const { return Ptr; }
      62             : 
      63             :   operator bool() const { return Ptr != nullptr; }
      64             : };
      65             : 
      66             : } // end anonymous namespace
      67             : 
      68      786979 : MIToken &MIToken::reset(TokenKind Kind, StringRef Range) {
      69      786979 :   this->Kind = Kind;
      70      786979 :   this->Range = Range;
      71      786979 :   return *this;
      72             : }
      73             : 
      74      276645 : MIToken &MIToken::setStringValue(StringRef StrVal) {
      75      276645 :   StringValue = StrVal;
      76      276645 :   return *this;
      77             : }
      78             : 
      79         558 : MIToken &MIToken::setOwnedStringValue(std::string StrVal) {
      80         558 :   StringValueStorage = std::move(StrVal);
      81         558 :   StringValue = StringValueStorage;
      82         558 :   return *this;
      83             : }
      84             : 
      85      121461 : MIToken &MIToken::setIntegerValue(APSInt IntVal) {
      86      121461 :   this->IntVal = std::move(IntVal);
      87      121461 :   return *this;
      88             : }
      89             : 
      90             : /// Skip the leading whitespace characters and return the updated cursor.
      91      786979 : static Cursor skipWhitespace(Cursor C) {
      92     1556288 :   while (isblank(C.peek()))
      93             :     C.advance();
      94      786979 :   return C;
      95             : }
      96             : 
      97     3065855 : static bool isNewlineChar(char C) { return C == '\n' || C == '\r'; }
      98             : 
      99             : /// Skip a line comment and return the updated cursor.
     100      786979 : static Cursor skipComment(Cursor C) {
     101      775513 :   if (C.peek() != ';')
     102      726219 :     return C;
     103     2881582 :   while (!isNewlineChar(C.peek()) && !C.isEOF())
     104             :     C.advance();
     105       60760 :   return C;
     106             : }
     107             : 
     108             : /// Return true if the given character satisfies the following regular
     109             : /// expression: [-a-zA-Z$._0-9]
     110     1720656 : static bool isIdentifierChar(char C) {
     111     1985138 :   return isalpha(C) || isdigit(C) || C == '_' || C == '-' || C == '.' ||
     112     1985138 :          C == '$';
     113             : }
     114             : 
     115             : /// Unescapes the given string value.
     116             : ///
     117             : /// Expects the string value to be quoted.
     118         558 : static std::string unescapeQuotedString(StringRef Value) {
     119             :   assert(Value.front() == '"' && Value.back() == '"');
     120         558 :   Cursor C = Cursor(Value.substr(1, Value.size() - 2));
     121             : 
     122             :   std::string Str;
     123         558 :   Str.reserve(C.remaining().size());
     124        7618 :   while (!C.isEOF()) {
     125             :     char Char = C.peek();
     126        7060 :     if (Char == '\\') {
     127          44 :       if (C.peek(1) == '\\') {
     128             :         // Two '\' become one
     129             :         Str += '\\';
     130             :         C.advance(2);
     131           2 :         continue;
     132             :       }
     133         120 :       if (isxdigit(C.peek(1)) && isxdigit(C.peek(2))) {
     134         160 :         Str += hexDigitValue(C.peek(1)) * 16 + hexDigitValue(C.peek(2));
     135             :         C.advance(3);
     136          40 :         continue;
     137             :       }
     138             :     }
     139        7018 :     Str += Char;
     140             :     C.advance();
     141             :   }
     142         558 :   return Str;
     143             : }
     144             : 
     145             : /// Lex a string constant using the following regular expression: \"[^\"]*\"
     146         559 : static Cursor lexStringConstant(Cursor C, ErrorCallbackType ErrorCallback) {
     147             :   assert(C.peek() == '"');
     148        7715 :   for (C.advance(); C.peek() != '"'; C.advance()) {
     149       14314 :     if (C.isEOF() || isNewlineChar(C.peek())) {
     150           1 :       ErrorCallback(
     151             :           C.location(),
     152             :           "end of machine instruction reached before the closing '\"'");
     153           1 :       return None;
     154             :     }
     155             :   }
     156             :   C.advance();
     157         558 :   return C;
     158             : }
     159             : 
     160        3877 : static Cursor lexName(Cursor C, MIToken &Token, MIToken::TokenKind Type,
     161             :                       unsigned PrefixLength, ErrorCallbackType ErrorCallback) {
     162             :   auto Range = C;
     163             :   C.advance(PrefixLength);
     164        3877 :   if (C.peek() == '"') {
     165         559 :     if (Cursor R = lexStringConstant(C, ErrorCallback)) {
     166         558 :       StringRef String = Range.upto(R);
     167         558 :       Token.reset(Type, String)
     168         558 :           .setOwnedStringValue(
     169        1116 :               unescapeQuotedString(String.drop_front(PrefixLength)));
     170         558 :       return R;
     171             :     }
     172           1 :     Token.reset(MIToken::Error, Range.remaining());
     173           1 :     return Range;
     174             :   }
     175       23381 :   while (isIdentifierChar(C.peek()))
     176             :     C.advance();
     177        3318 :   Token.reset(Type, Range.upto(C))
     178        6636 :       .setStringValue(Range.upto(C).drop_front(PrefixLength));
     179        3318 :   return C;
     180             : }
     181             : 
     182      161274 : static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
     183      161274 :   return StringSwitch<MIToken::TokenKind>(Identifier)
     184             :       .Case("_", MIToken::underscore)
     185             :       .Case("implicit", MIToken::kw_implicit)
     186             :       .Case("implicit-def", MIToken::kw_implicit_define)
     187             :       .Case("def", MIToken::kw_def)
     188             :       .Case("dead", MIToken::kw_dead)
     189             :       .Case("killed", MIToken::kw_killed)
     190             :       .Case("undef", MIToken::kw_undef)
     191             :       .Case("internal", MIToken::kw_internal)
     192             :       .Case("early-clobber", MIToken::kw_early_clobber)
     193             :       .Case("debug-use", MIToken::kw_debug_use)
     194             :       .Case("renamable", MIToken::kw_renamable)
     195             :       .Case("tied-def", MIToken::kw_tied_def)
     196             :       .Case("frame-setup", MIToken::kw_frame_setup)
     197             :       .Case("frame-destroy", MIToken::kw_frame_destroy)
     198             :       .Case("nnan", MIToken::kw_nnan)
     199             :       .Case("ninf", MIToken::kw_ninf)
     200             :       .Case("nsz", MIToken::kw_nsz)
     201             :       .Case("arcp", MIToken::kw_arcp)
     202             :       .Case("contract", MIToken::kw_contract)
     203             :       .Case("afn", MIToken::kw_afn)
     204             :       .Case("reassoc", MIToken::kw_reassoc)
     205             :       .Case("debug-location", MIToken::kw_debug_location)
     206             :       .Case("same_value", MIToken::kw_cfi_same_value)
     207             :       .Case("offset", MIToken::kw_cfi_offset)
     208             :       .Case("rel_offset", MIToken::kw_cfi_rel_offset)
     209             :       .Case("def_cfa_register", MIToken::kw_cfi_def_cfa_register)
     210             :       .Case("def_cfa_offset", MIToken::kw_cfi_def_cfa_offset)
     211             :       .Case("adjust_cfa_offset", MIToken::kw_cfi_adjust_cfa_offset)
     212             :       .Case("escape", MIToken::kw_cfi_escape)
     213             :       .Case("def_cfa", MIToken::kw_cfi_def_cfa)
     214             :       .Case("remember_state", MIToken::kw_cfi_remember_state)
     215             :       .Case("restore", MIToken::kw_cfi_restore)
     216             :       .Case("restore_state", MIToken::kw_cfi_restore_state)
     217             :       .Case("undefined", MIToken::kw_cfi_undefined)
     218             :       .Case("register", MIToken::kw_cfi_register)
     219             :       .Case("window_save", MIToken::kw_cfi_window_save)
     220             :       .Case("blockaddress", MIToken::kw_blockaddress)
     221             :       .Case("intrinsic", MIToken::kw_intrinsic)
     222             :       .Case("target-index", MIToken::kw_target_index)
     223             :       .Case("half", MIToken::kw_half)
     224             :       .Case("float", MIToken::kw_float)
     225             :       .Case("double", MIToken::kw_double)
     226             :       .Case("x86_fp80", MIToken::kw_x86_fp80)
     227             :       .Case("fp128", MIToken::kw_fp128)
     228             :       .Case("ppc_fp128", MIToken::kw_ppc_fp128)
     229             :       .Case("target-flags", MIToken::kw_target_flags)
     230             :       .Case("volatile", MIToken::kw_volatile)
     231             :       .Case("non-temporal", MIToken::kw_non_temporal)
     232             :       .Case("dereferenceable", MIToken::kw_dereferenceable)
     233             :       .Case("invariant", MIToken::kw_invariant)
     234             :       .Case("align", MIToken::kw_align)
     235             :       .Case("addrspace", MIToken::kw_addrspace)
     236             :       .Case("stack", MIToken::kw_stack)
     237             :       .Case("got", MIToken::kw_got)
     238             :       .Case("jump-table", MIToken::kw_jump_table)
     239             :       .Case("constant-pool", MIToken::kw_constant_pool)
     240             :       .Case("call-entry", MIToken::kw_call_entry)
     241             :       .Case("liveout", MIToken::kw_liveout)
     242             :       .Case("address-taken", MIToken::kw_address_taken)
     243             :       .Case("landing-pad", MIToken::kw_landing_pad)
     244             :       .Case("liveins", MIToken::kw_liveins)
     245             :       .Case("successors", MIToken::kw_successors)
     246             :       .Case("floatpred", MIToken::kw_floatpred)
     247             :       .Case("intpred", MIToken::kw_intpred)
     248      161274 :       .Default(MIToken::Identifier);
     249             : }
     250             : 
     251      758349 : static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) {
     252     1359856 :   if (!isalpha(C.peek()) && C.peek() != '_')
     253      597075 :     return None;
     254             :   auto Range = C;
     255     1206529 :   while (isIdentifierChar(C.peek()))
     256             :     C.advance();
     257      161274 :   auto Identifier = Range.upto(C);
     258      161274 :   Token.reset(getIdentifierKind(Identifier), Identifier)
     259      161274 :       .setStringValue(Identifier);
     260      161274 :   return C;
     261             : }
     262             : 
     263      775513 : static Cursor maybeLexMachineBasicBlock(Cursor C, MIToken &Token,
     264             :                                         ErrorCallbackType ErrorCallback) {
     265             :   bool IsReference = C.remaining().startswith("%bb.");
     266             :   if (!IsReference && !C.remaining().startswith("bb."))
     267      758349 :     return None;
     268             :   auto Range = C;
     269       17164 :   unsigned PrefixLength = IsReference ? 4 : 3;
     270             :   C.advance(PrefixLength); // Skip '%bb.' or 'bb.'
     271       17164 :   if (!isdigit(C.peek())) {
     272           1 :     Token.reset(MIToken::Error, C.remaining());
     273           1 :     ErrorCallback(C.location(), "expected a number after '%bb.'");
     274           1 :     return C;
     275             :   }
     276             :   auto NumberRange = C;
     277       35322 :   while (isdigit(C.peek()))
     278             :     C.advance();
     279       17163 :   StringRef Number = NumberRange.upto(C);
     280       17163 :   unsigned StringOffset = PrefixLength + Number.size(); // Drop '%bb.<id>'
     281             :   // TODO: The format bb.<id>.<irname> is supported only when it's not a
     282             :   // reference. Once we deprecate the format where the irname shows up, we
     283             :   // should only lex forward if it is a reference.
     284       17153 :   if (C.peek() == '.') {
     285             :     C.advance(); // Skip '.'
     286        4634 :     ++StringOffset;
     287       29618 :     while (isIdentifierChar(C.peek()))
     288             :       C.advance();
     289             :   }
     290             :   Token.reset(IsReference ? MIToken::MachineBasicBlock
     291             :                           : MIToken::MachineBasicBlockLabel,
     292       17163 :               Range.upto(C))
     293       34326 :       .setIntegerValue(APSInt(Number))
     294       34326 :       .setStringValue(Range.upto(C).drop_front(StringOffset));
     295       17163 :   return C;
     296             : }
     297             : 
     298     1791312 : static Cursor maybeLexIndex(Cursor C, MIToken &Token, StringRef Rule,
     299             :                             MIToken::TokenKind Kind) {
     300        4432 :   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
     301     1789096 :     return None;
     302             :   auto Range = C;
     303             :   C.advance(Rule.size());
     304             :   auto NumberRange = C;
     305        4453 :   while (isdigit(C.peek()))
     306             :     C.advance();
     307        6648 :   Token.reset(Kind, Range.upto(C)).setIntegerValue(APSInt(NumberRange.upto(C)));
     308        2216 :   return C;
     309             : }
     310             : 
     311      597050 : static Cursor maybeLexIndexAndName(Cursor C, MIToken &Token, StringRef Rule,
     312             :                                    MIToken::TokenKind Kind) {
     313        1666 :   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
     314      596217 :     return None;
     315             :   auto Range = C;
     316         833 :   C.advance(Rule.size());
     317             :   auto NumberRange = C;
     318        1666 :   while (isdigit(C.peek()))
     319             :     C.advance();
     320         833 :   StringRef Number = NumberRange.upto(C);
     321         833 :   unsigned StringOffset = Rule.size() + Number.size();
     322         833 :   if (C.peek() == '.') {
     323             :     C.advance();
     324         404 :     ++StringOffset;
     325        1775 :     while (isIdentifierChar(C.peek()))
     326             :       C.advance();
     327             :   }
     328         833 :   Token.reset(Kind, Range.upto(C))
     329        1666 :       .setIntegerValue(APSInt(Number))
     330        1666 :       .setStringValue(Range.upto(C).drop_front(StringOffset));
     331         833 :   return C;
     332             : }
     333             : 
     334             : static Cursor maybeLexJumpTableIndex(Cursor C, MIToken &Token) {
     335      597075 :   return maybeLexIndex(C, Token, "%jump-table.", MIToken::JumpTableIndex);
     336             : }
     337             : 
     338             : static Cursor maybeLexStackObject(Cursor C, MIToken &Token) {
     339      597050 :   return maybeLexIndexAndName(C, Token, "%stack.", MIToken::StackObject);
     340             : }
     341             : 
     342             : static Cursor maybeLexFixedStackObject(Cursor C, MIToken &Token) {
     343      596217 :   return maybeLexIndex(C, Token, "%fixed-stack.", MIToken::FixedStackObject);
     344             : }
     345             : 
     346             : static Cursor maybeLexConstantPoolItem(Cursor C, MIToken &Token) {
     347      596055 :   return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem);
     348             : }
     349             : 
     350      595991 : static Cursor maybeLexSubRegisterIndex(Cursor C, MIToken &Token,
     351             :                                        ErrorCallbackType ErrorCallback) {
     352             :   const StringRef Rule = "%subreg.";
     353             :   if (!C.remaining().startswith(Rule))
     354      595819 :     return None;
     355             :   return lexName(C, Token, MIToken::SubRegisterIndex, Rule.size(),
     356         172 :                  ErrorCallback);
     357             : }
     358             : 
     359      595819 : static Cursor maybeLexIRBlock(Cursor C, MIToken &Token,
     360             :                               ErrorCallbackType ErrorCallback) {
     361             :   const StringRef Rule = "%ir-block.";
     362             :   if (!C.remaining().startswith(Rule))
     363      593940 :     return None;
     364        1879 :   if (isdigit(C.peek(Rule.size())))
     365        1869 :     return maybeLexIndex(C, Token, Rule, MIToken::IRBlock);
     366          10 :   return lexName(C, Token, MIToken::NamedIRBlock, Rule.size(), ErrorCallback);
     367             : }
     368             : 
     369      593940 : static Cursor maybeLexIRValue(Cursor C, MIToken &Token,
     370             :                               ErrorCallbackType ErrorCallback) {
     371             :   const StringRef Rule = "%ir.";
     372             :   if (!C.remaining().startswith(Rule))
     373      592122 :     return None;
     374        1818 :   if (isdigit(C.peek(Rule.size())))
     375          96 :     return maybeLexIndex(C, Token, Rule, MIToken::IRValue);
     376        1722 :   return lexName(C, Token, MIToken::NamedIRValue, Rule.size(), ErrorCallback);
     377             : }
     378             : 
     379         219 : static Cursor maybeLexStringConstant(Cursor C, MIToken &Token,
     380             :                                      ErrorCallbackType ErrorCallback) {
     381         219 :   if (C.peek() != '"')
     382           1 :     return None;
     383             :   return lexName(C, Token, MIToken::StringConstant, /*PrefixLength=*/0,
     384         218 :                  ErrorCallback);
     385             : }
     386             : 
     387       58455 : static Cursor lexVirtualRegister(Cursor C, MIToken &Token) {
     388             :   auto Range = C;
     389             :   C.advance(); // Skip '%'
     390             :   auto NumberRange = C;
     391      127548 :   while (isdigit(C.peek()))
     392             :     C.advance();
     393       58455 :   Token.reset(MIToken::VirtualRegister, Range.upto(C))
     394      116910 :       .setIntegerValue(APSInt(NumberRange.upto(C)));
     395       58455 :   return C;
     396             : }
     397             : 
     398             : /// Returns true for a character allowed in a register name.
     399             : static bool isRegisterChar(char C) {
     400      455888 :   return isIdentifierChar(C) && C != '.';
     401             : }
     402             : 
     403          88 : static Cursor lexNamedVirtualRegister(Cursor C, MIToken &Token) {
     404             :   Cursor Range = C;
     405             :   C.advance(); // Skip '%'
     406         632 :   while (isRegisterChar(C.peek()))
     407             :     C.advance();
     408          88 :   Token.reset(MIToken::NamedVirtualRegister, Range.upto(C))
     409         176 :       .setStringValue(Range.upto(C).drop_front(1)); // Drop the '%'
     410          88 :   return C;
     411             : }
     412             : 
     413      592122 : static Cursor maybeLexRegister(Cursor C, MIToken &Token,
     414             :                                ErrorCallbackType ErrorCallback) {
     415     1125701 :   if (C.peek() != '%' && C.peek() != '$')
     416      440586 :     return None;
     417             : 
     418      151536 :   if (C.peek() == '%') {
     419       58543 :     if (isdigit(C.peek(1)))
     420       58455 :       return lexVirtualRegister(C, Token);
     421             : 
     422          88 :     if (isRegisterChar(C.peek(1)))
     423          88 :       return lexNamedVirtualRegister(C, Token);
     424             : 
     425           0 :     return None;
     426             :   }
     427             : 
     428             :   assert(C.peek() == '$');
     429             :   auto Range = C;
     430             :   C.advance(); // Skip '$'
     431      455168 :   while (isRegisterChar(C.peek()))
     432             :     C.advance();
     433       92993 :   Token.reset(MIToken::NamedRegister, Range.upto(C))
     434      185986 :       .setStringValue(Range.upto(C).drop_front(1)); // Drop the '$'
     435       92993 :   return C;
     436             : }
     437             : 
     438      440586 : static Cursor maybeLexGlobalValue(Cursor C, MIToken &Token,
     439             :                                   ErrorCallbackType ErrorCallback) {
     440      440586 :   if (C.peek() != '@')
     441      439261 :     return None;
     442        1325 :   if (!isdigit(C.peek(1)))
     443             :     return lexName(C, Token, MIToken::NamedGlobalValue, /*PrefixLength=*/1,
     444        1317 :                    ErrorCallback);
     445             :   auto Range = C;
     446             :   C.advance(1); // Skip the '@'
     447             :   auto NumberRange = C;
     448          16 :   while (isdigit(C.peek()))
     449             :     C.advance();
     450           8 :   Token.reset(MIToken::GlobalValue, Range.upto(C))
     451          16 :       .setIntegerValue(APSInt(NumberRange.upto(C)));
     452           8 :   return C;
     453             : }
     454             : 
     455      439261 : static Cursor maybeLexExternalSymbol(Cursor C, MIToken &Token,
     456             :                                      ErrorCallbackType ErrorCallback) {
     457      439261 :   if (C.peek() != '&')
     458      438823 :     return None;
     459             :   return lexName(C, Token, MIToken::ExternalSymbol, /*PrefixLength=*/1,
     460         438 :                  ErrorCallback);
     461             : }
     462             : 
     463             : static bool isValidHexFloatingPointPrefix(char C) {
     464        2030 :   return C == 'H' || C == 'K' || C == 'L' || C == 'M';
     465             : }
     466             : 
     467         100 : static Cursor lexFloatingPointLiteral(Cursor Range, Cursor C, MIToken &Token) {
     468             :   C.advance();
     469             :   // Skip over [0-9]*([eE][-+]?[0-9]+)?
     470         366 :   while (isdigit(C.peek()))
     471             :     C.advance();
     472         232 :   if ((C.peek() == 'e' || C.peek() == 'E') &&
     473          64 :       (isdigit(C.peek(1)) ||
     474          64 :        ((C.peek(1) == '-' || C.peek(1) == '+') && isdigit(C.peek(2))))) {
     475             :     C.advance(2);
     476          96 :     while (isdigit(C.peek()))
     477             :       C.advance();
     478             :   }
     479         200 :   Token.reset(MIToken::FloatingPointLiteral, Range.upto(C));
     480         100 :   return C;
     481             : }
     482             : 
     483      438823 : static Cursor maybeLexHexadecimalLiteral(Cursor C, MIToken &Token) {
     484      471875 :   if (C.peek() != '0' || (C.peek(1) != 'x' && C.peek(1) != 'X'))
     485      436793 :     return None;
     486             :   Cursor Range = C;
     487             :   C.advance(2);
     488             :   unsigned PrefLen = 2;
     489             :   if (isValidHexFloatingPointPrefix(C.peek())) {
     490             :     C.advance();
     491             :     PrefLen++;
     492             :   }
     493       18196 :   while (isxdigit(C.peek()))
     494             :     C.advance();
     495             :   StringRef StrVal = Range.upto(C);
     496        2030 :   if (StrVal.size() <= PrefLen)
     497           0 :     return None;
     498        2030 :   if (PrefLen == 2)
     499        2028 :     Token.reset(MIToken::HexLiteral, Range.upto(C));
     500             :   else // It must be 3, which means that there was a floating-point prefix.
     501           2 :     Token.reset(MIToken::FloatingPointLiteral, Range.upto(C));
     502        2030 :   return C;
     503             : }
     504             : 
     505      436793 : static Cursor maybeLexNumericalLiteral(Cursor C, MIToken &Token) {
     506      832990 :   if (!isdigit(C.peek()) && (C.peek() != '-' || !isdigit(C.peek(1))))
     507      393907 :     return None;
     508             :   auto Range = C;
     509             :   C.advance();
     510       59581 :   while (isdigit(C.peek()))
     511             :     C.advance();
     512       42877 :   if (C.peek() == '.')
     513         100 :     return lexFloatingPointLiteral(Range, C, Token);
     514       42786 :   StringRef StrVal = Range.upto(C);
     515       85572 :   Token.reset(MIToken::IntegerLiteral, StrVal).setIntegerValue(APSInt(StrVal));
     516       42786 :   return C;
     517             : }
     518             : 
     519         435 : static MIToken::TokenKind getMetadataKeywordKind(StringRef Identifier) {
     520         435 :   return StringSwitch<MIToken::TokenKind>(Identifier)
     521             :       .Case("!tbaa", MIToken::md_tbaa)
     522             :       .Case("!alias.scope", MIToken::md_alias_scope)
     523             :       .Case("!noalias", MIToken::md_noalias)
     524             :       .Case("!range", MIToken::md_range)
     525             :       .Case("!DIExpression", MIToken::md_diexpr)
     526         435 :       .Default(MIToken::Error);
     527             : }
     528             : 
     529      393907 : static Cursor maybeLexExlaim(Cursor C, MIToken &Token,
     530             :                              ErrorCallbackType ErrorCallback) {
     531      393907 :   if (C.peek() != '!')
     532      391335 :     return None;
     533             :   auto Range = C;
     534             :   C.advance(1);
     535        2572 :   if (isdigit(C.peek()) || !isIdentifierChar(C.peek())) {
     536        2137 :     Token.reset(MIToken::exclaim, Range.upto(C));
     537        2137 :     return C;
     538             :   }
     539        3028 :   while (isIdentifierChar(C.peek()))
     540             :     C.advance();
     541         435 :   StringRef StrVal = Range.upto(C);
     542         435 :   Token.reset(getMetadataKeywordKind(StrVal), StrVal);
     543         435 :   if (Token.isError())
     544             :     ErrorCallback(Token.location(),
     545           1 :                   "use of unknown metadata keyword '" + StrVal + "'");
     546         435 :   return C;
     547             : }
     548             : 
     549             : static MIToken::TokenKind symbolToken(char C) {
     550      387028 :   switch (C) {
     551             :   case ',':
     552             :     return MIToken::comma;
     553             :   case '.':
     554             :     return MIToken::dot;
     555             :   case '=':
     556             :     return MIToken::equal;
     557             :   case ':':
     558             :     return MIToken::colon;
     559             :   case '(':
     560             :     return MIToken::lparen;
     561             :   case ')':
     562             :     return MIToken::rparen;
     563             :   case '{':
     564             :     return MIToken::lbrace;
     565             :   case '}':
     566             :     return MIToken::rbrace;
     567             :   case '+':
     568             :     return MIToken::plus;
     569             :   case '-':
     570             :     return MIToken::minus;
     571             :   case '<':
     572             :     return MIToken::less;
     573             :   case '>':
     574             :     return MIToken::greater;
     575             :   default:
     576             :     return MIToken::Error;
     577             :   }
     578             : }
     579             : 
     580      391335 : static Cursor maybeLexSymbol(Cursor C, MIToken &Token) {
     581             :   MIToken::TokenKind Kind;
     582             :   unsigned Length = 1;
     583      424541 :   if (C.peek() == ':' && C.peek(1) == ':') {
     584             :     Kind = MIToken::coloncolon;
     585             :     Length = 2;
     586             :   } else
     587             :     Kind = symbolToken(C.peek());
     588      387028 :   if (Kind == MIToken::Error)
     589      153718 :     return None;
     590             :   auto Range = C;
     591             :   C.advance(Length);
     592      237617 :   Token.reset(Kind, Range.upto(C));
     593      237617 :   return C;
     594             : }
     595             : 
     596      153718 : static Cursor maybeLexNewline(Cursor C, MIToken &Token) {
     597      153718 :   if (!isNewlineChar(C.peek()))
     598        1195 :     return None;
     599             :   auto Range = C;
     600             :   C.advance();
     601      152523 :   Token.reset(MIToken::Newline, Range.upto(C));
     602      152523 :   return C;
     603             : }
     604             : 
     605        1195 : static Cursor maybeLexEscapedIRValue(Cursor C, MIToken &Token,
     606             :                                      ErrorCallbackType ErrorCallback) {
     607        1195 :   if (C.peek() != '`')
     608         219 :     return None;
     609             :   auto Range = C;
     610             :   C.advance();
     611             :   auto StrRange = C;
     612       24374 :   while (C.peek() != '`') {
     613       46796 :     if (C.isEOF() || isNewlineChar(C.peek())) {
     614           0 :       ErrorCallback(
     615             :           C.location(),
     616             :           "end of machine instruction reached before the closing '`'");
     617           0 :       Token.reset(MIToken::Error, Range.remaining());
     618           0 :       return C;
     619             :     }
     620             :     C.advance();
     621             :   }
     622         976 :   StringRef Value = StrRange.upto(C);
     623             :   C.advance();
     624         976 :   Token.reset(MIToken::QuotedIRValue, Range.upto(C)).setStringValue(Value);
     625         976 :   return C;
     626             : }
     627             : 
     628      786979 : StringRef llvm::lexMIToken(StringRef Source, MIToken &Token,
     629             :                            ErrorCallbackType ErrorCallback) {
     630      786979 :   auto C = skipComment(skipWhitespace(Cursor(Source)));
     631      786979 :   if (C.isEOF()) {
     632       11466 :     Token.reset(MIToken::Eof, C.remaining());
     633             :     return C.remaining();
     634             :   }
     635             : 
     636      775513 :   if (Cursor R = maybeLexMachineBasicBlock(C, Token, ErrorCallback))
     637       17164 :     return R.remaining();
     638      758349 :   if (Cursor R = maybeLexIdentifier(C, Token))
     639      161274 :     return R.remaining();
     640      597075 :   if (Cursor R = maybeLexJumpTableIndex(C, Token))
     641             :     return R.remaining();
     642      597050 :   if (Cursor R = maybeLexStackObject(C, Token))
     643             :     return R.remaining();
     644      596217 :   if (Cursor R = maybeLexFixedStackObject(C, Token))
     645             :     return R.remaining();
     646      596055 :   if (Cursor R = maybeLexConstantPoolItem(C, Token))
     647             :     return R.remaining();
     648      595991 :   if (Cursor R = maybeLexSubRegisterIndex(C, Token, ErrorCallback))
     649         172 :     return R.remaining();
     650      595819 :   if (Cursor R = maybeLexIRBlock(C, Token, ErrorCallback))
     651        1879 :     return R.remaining();
     652      593940 :   if (Cursor R = maybeLexIRValue(C, Token, ErrorCallback))
     653        1818 :     return R.remaining();
     654      592122 :   if (Cursor R = maybeLexRegister(C, Token, ErrorCallback))
     655      151536 :     return R.remaining();
     656      440586 :   if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback))
     657        1325 :     return R.remaining();
     658      439261 :   if (Cursor R = maybeLexExternalSymbol(C, Token, ErrorCallback))
     659         438 :     return R.remaining();
     660      438823 :   if (Cursor R = maybeLexHexadecimalLiteral(C, Token))
     661        2030 :     return R.remaining();
     662      436793 :   if (Cursor R = maybeLexNumericalLiteral(C, Token))
     663       42886 :     return R.remaining();
     664      393907 :   if (Cursor R = maybeLexExlaim(C, Token, ErrorCallback))
     665        2572 :     return R.remaining();
     666      391335 :   if (Cursor R = maybeLexSymbol(C, Token))
     667      237617 :     return R.remaining();
     668      153718 :   if (Cursor R = maybeLexNewline(C, Token))
     669      152523 :     return R.remaining();
     670        1195 :   if (Cursor R = maybeLexEscapedIRValue(C, Token, ErrorCallback))
     671         976 :     return R.remaining();
     672         219 :   if (Cursor R = maybeLexStringConstant(C, Token, ErrorCallback))
     673         218 :     return R.remaining();
     674             : 
     675           1 :   Token.reset(MIToken::Error, C.remaining());
     676             :   ErrorCallback(C.location(),
     677           1 :                 Twine("unexpected character '") + Twine(C.peek()) + "'");
     678             :   return C.remaining();
     679             : }

Generated by: LCOV version 1.13