LCOV - code coverage report
Current view: top level - lib/CodeGen/MIRParser - MILexer.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 336 341 98.5 %
Date: 2018-02-19 17:12:42 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      591043 :   explicit Cursor(StringRef Str) {
      44      591043 :     Ptr = Str.data();
      45      591141 :     End = Ptr + Str.size();
      46             :   }
      47             : 
      48             :   bool isEOF() const { return Ptr == End; }
      49             : 
      50    12018173 :   char peek(int I = 0) const { return End - Ptr <= I ? 0 : Ptr[I]; }
      51             : 
      52     4310098 :   void advance(unsigned I = 1) { Ptr += I; }
      53             : 
      54     4324531 :   StringRef remaining() const { return StringRef(Ptr, End - Ptr); }
      55             : 
      56             :   StringRef upto(Cursor C) const {
      57             :     assert(C.Ptr >= Ptr && C.Ptr <= End);
      58      531147 :     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      591043 : MIToken &MIToken::reset(TokenKind Kind, StringRef Range) {
      69      591043 :   this->Kind = Kind;
      70      591043 :   this->Range = Range;
      71      591043 :   return *this;
      72             : }
      73             : 
      74      186771 : MIToken &MIToken::setStringValue(StringRef StrVal) {
      75      186771 :   StringValue = StrVal;
      76      186771 :   return *this;
      77             : }
      78             : 
      79          98 : MIToken &MIToken::setOwnedStringValue(std::string StrVal) {
      80          98 :   StringValueStorage = std::move(StrVal);
      81          98 :   StringValue = StringValueStorage;
      82          98 :   return *this;
      83             : }
      84             : 
      85       93706 : MIToken &MIToken::setIntegerValue(APSInt IntVal) {
      86       93706 :   this->IntVal = std::move(IntVal);
      87       93706 :   return *this;
      88             : }
      89             : 
      90             : /// Skip the leading whitespace characters and return the updated cursor.
      91      591043 : static Cursor skipWhitespace(Cursor C) {
      92     1243272 :   while (isblank(C.peek()))
      93             :     C.advance();
      94      591043 :   return C;
      95             : }
      96             : 
      97     2170121 : static bool isNewlineChar(char C) { return C == '\n' || C == '\r'; }
      98             : 
      99             : /// Skip a line comment and return the updated cursor.
     100      591043 : static Cursor skipComment(Cursor C) {
     101      582478 :   if (C.peek() != ';')
     102      550877 :     return C;
     103     2048218 :   while (!isNewlineChar(C.peek()) && !C.isEOF())
     104             :     C.advance();
     105       40166 :   return C;
     106             : }
     107             : 
     108             : /// Return true if the given character satisfies the following regular
     109             : /// expression: [-a-zA-Z$._0-9]
     110     1199141 : static bool isIdentifierChar(char C) {
     111     1378298 :   return isalpha(C) || isdigit(C) || C == '_' || C == '-' || C == '.' ||
     112     1378298 :          C == '$';
     113             : }
     114             : 
     115             : /// Unescapes the given string value.
     116             : ///
     117             : /// Expects the string value to be quoted.
     118          98 : static std::string unescapeQuotedString(StringRef Value) {
     119             :   assert(Value.front() == '"' && Value.back() == '"');
     120          98 :   Cursor C = Cursor(Value.substr(1, Value.size() - 2));
     121             : 
     122             :   std::string Str;
     123          98 :   Str.reserve(C.remaining().size());
     124        1788 :   while (!C.isEOF()) {
     125             :     char Char = C.peek();
     126        1690 :     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        1648 :     Str += Char;
     140             :     C.advance();
     141             :   }
     142          98 :   return Str;
     143             : }
     144             : 
     145             : /// Lex a string constant using the following regular expression: \"[^\"]*\"
     146          99 : static Cursor lexStringConstant(Cursor C, ErrorCallbackType ErrorCallback) {
     147             :   assert(C.peek() == '"');
     148        1885 :   for (C.advance(); C.peek() != '"'; C.advance()) {
     149        3574 :     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          98 :   return C;
     158             : }
     159             : 
     160        2931 : static Cursor lexName(Cursor C, MIToken &Token, MIToken::TokenKind Type,
     161             :                       unsigned PrefixLength, ErrorCallbackType ErrorCallback) {
     162             :   auto Range = C;
     163             :   C.advance(PrefixLength);
     164        2931 :   if (C.peek() == '"') {
     165          99 :     if (Cursor R = lexStringConstant(C, ErrorCallback)) {
     166          98 :       StringRef String = Range.upto(R);
     167          98 :       Token.reset(Type, String)
     168          98 :           .setOwnedStringValue(
     169         196 :               unescapeQuotedString(String.drop_front(PrefixLength)));
     170          98 :       return R;
     171             :     }
     172           1 :     Token.reset(MIToken::Error, Range.remaining());
     173           1 :     return Range;
     174             :   }
     175       19523 :   while (isIdentifierChar(C.peek()))
     176             :     C.advance();
     177        2832 :   Token.reset(Type, Range.upto(C))
     178        5664 :       .setStringValue(Range.upto(C).drop_front(PrefixLength));
     179        2832 :   return C;
     180             : }
     181             : 
     182      582478 : static Cursor maybeLexIntegerOrScalarType(Cursor C, MIToken &Token) {
     183     1732422 :   if ((C.peek() != 'i' && C.peek() != 's' && C.peek() != 'p') ||
     184       40309 :       !isdigit(C.peek(1)))
     185      562615 :     return None;
     186             :   char Kind = C.peek();
     187             :   auto Range = C;
     188             :   C.advance(); // Skip 'i', 's', or 'p'
     189       55955 :   while (isdigit(C.peek()))
     190             :     C.advance();
     191             : 
     192       19863 :   Token.reset(Kind == 'i'
     193             :                   ? MIToken::IntegerType
     194       19310 :                   : (Kind == 's' ? MIToken::ScalarType : MIToken::PointerType),
     195       19863 :               Range.upto(C));
     196       19863 :   return C;
     197             : }
     198             : 
     199       97287 : static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
     200             :   return StringSwitch<MIToken::TokenKind>(Identifier)
     201      194574 :       .Case("_", MIToken::underscore)
     202      194574 :       .Case("implicit", MIToken::kw_implicit)
     203      194574 :       .Case("implicit-def", MIToken::kw_implicit_define)
     204      194574 :       .Case("def", MIToken::kw_def)
     205      194574 :       .Case("dead", MIToken::kw_dead)
     206      194574 :       .Case("killed", MIToken::kw_killed)
     207      194574 :       .Case("undef", MIToken::kw_undef)
     208      194574 :       .Case("internal", MIToken::kw_internal)
     209      194574 :       .Case("early-clobber", MIToken::kw_early_clobber)
     210      194574 :       .Case("debug-use", MIToken::kw_debug_use)
     211      194574 :       .Case("renamable", MIToken::kw_renamable)
     212      194574 :       .Case("tied-def", MIToken::kw_tied_def)
     213      194574 :       .Case("frame-setup", MIToken::kw_frame_setup)
     214      194574 :       .Case("frame-destroy", MIToken::kw_frame_destroy)
     215      194574 :       .Case("debug-location", MIToken::kw_debug_location)
     216      194574 :       .Case("same_value", MIToken::kw_cfi_same_value)
     217      194574 :       .Case("offset", MIToken::kw_cfi_offset)
     218      194574 :       .Case("rel_offset", MIToken::kw_cfi_rel_offset)
     219      194574 :       .Case("def_cfa_register", MIToken::kw_cfi_def_cfa_register)
     220      194574 :       .Case("def_cfa_offset", MIToken::kw_cfi_def_cfa_offset)
     221      194574 :       .Case("adjust_cfa_offset", MIToken::kw_cfi_adjust_cfa_offset)
     222      194574 :       .Case("escape", MIToken::kw_cfi_escape)
     223      194574 :       .Case("def_cfa", MIToken::kw_cfi_def_cfa)
     224      194574 :       .Case("remember_state", MIToken::kw_cfi_remember_state)
     225      194574 :       .Case("restore", MIToken::kw_cfi_restore)
     226      194574 :       .Case("restore_state", MIToken::kw_cfi_restore_state)
     227      194574 :       .Case("undefined", MIToken::kw_cfi_undefined)
     228      194574 :       .Case("register", MIToken::kw_cfi_register)
     229      194574 :       .Case("window_save", MIToken::kw_cfi_window_save)
     230      194574 :       .Case("blockaddress", MIToken::kw_blockaddress)
     231      194574 :       .Case("intrinsic", MIToken::kw_intrinsic)
     232      194574 :       .Case("target-index", MIToken::kw_target_index)
     233      194574 :       .Case("half", MIToken::kw_half)
     234      194574 :       .Case("float", MIToken::kw_float)
     235      194574 :       .Case("double", MIToken::kw_double)
     236      194574 :       .Case("x86_fp80", MIToken::kw_x86_fp80)
     237      194574 :       .Case("fp128", MIToken::kw_fp128)
     238      194574 :       .Case("ppc_fp128", MIToken::kw_ppc_fp128)
     239      194574 :       .Case("target-flags", MIToken::kw_target_flags)
     240      194574 :       .Case("volatile", MIToken::kw_volatile)
     241      194574 :       .Case("non-temporal", MIToken::kw_non_temporal)
     242      194574 :       .Case("dereferenceable", MIToken::kw_dereferenceable)
     243      194574 :       .Case("invariant", MIToken::kw_invariant)
     244      194574 :       .Case("align", MIToken::kw_align)
     245      194574 :       .Case("addrspace", MIToken::kw_addrspace)
     246      194574 :       .Case("stack", MIToken::kw_stack)
     247      194574 :       .Case("got", MIToken::kw_got)
     248      194574 :       .Case("jump-table", MIToken::kw_jump_table)
     249      194574 :       .Case("constant-pool", MIToken::kw_constant_pool)
     250      194574 :       .Case("call-entry", MIToken::kw_call_entry)
     251      194574 :       .Case("liveout", MIToken::kw_liveout)
     252      194574 :       .Case("address-taken", MIToken::kw_address_taken)
     253      194574 :       .Case("landing-pad", MIToken::kw_landing_pad)
     254      194574 :       .Case("liveins", MIToken::kw_liveins)
     255      194574 :       .Case("successors", MIToken::kw_successors)
     256      194574 :       .Case("floatpred", MIToken::kw_floatpred)
     257      194574 :       .Case("intpred", MIToken::kw_intpred)
     258       97287 :       .Default(MIToken::Identifier);
     259             : }
     260             : 
     261      550757 : static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) {
     262     1006907 :   if (!isalpha(C.peek()) && C.peek() != '_')
     263      453470 :     return None;
     264             :   auto Range = C;
     265      798279 :   while (isIdentifierChar(C.peek()))
     266             :     C.advance();
     267       97287 :   auto Identifier = Range.upto(C);
     268       97287 :   Token.reset(getIdentifierKind(Identifier), Identifier)
     269       97287 :       .setStringValue(Identifier);
     270       97287 :   return C;
     271             : }
     272             : 
     273      562615 : static Cursor maybeLexMachineBasicBlock(Cursor C, MIToken &Token,
     274             :                                         ErrorCallbackType ErrorCallback) {
     275             :   bool IsReference = C.remaining().startswith("%bb.");
     276             :   if (!IsReference && !C.remaining().startswith("bb."))
     277      550757 :     return None;
     278             :   auto Range = C;
     279       11858 :   unsigned PrefixLength = IsReference ? 4 : 3;
     280             :   C.advance(PrefixLength); // Skip '%bb.' or 'bb.'
     281       11858 :   if (!isdigit(C.peek())) {
     282           1 :     Token.reset(MIToken::Error, C.remaining());
     283           1 :     ErrorCallback(C.location(), "expected a number after '%bb.'");
     284           1 :     return C;
     285             :   }
     286             :   auto NumberRange = C;
     287       24268 :   while (isdigit(C.peek()))
     288             :     C.advance();
     289       11857 :   StringRef Number = NumberRange.upto(C);
     290       11857 :   unsigned StringOffset = PrefixLength + Number.size(); // Drop '%bb.<id>'
     291             :   // TODO: The format bb.<id>.<irname> is supported only when it's not a
     292             :   // reference. Once we deprecate the format where the irname shows up, we
     293             :   // should only lex forward if it is a reference.
     294       11847 :   if (C.peek() == '.') {
     295             :     C.advance(); // Skip '.'
     296        3420 :     ++StringOffset;
     297       22010 :     while (isIdentifierChar(C.peek()))
     298             :       C.advance();
     299             :   }
     300             :   Token.reset(IsReference ? MIToken::MachineBasicBlock
     301             :                           : MIToken::MachineBasicBlockLabel,
     302       11857 :               Range.upto(C))
     303       23714 :       .setIntegerValue(APSInt(Number))
     304       23714 :       .setStringValue(Range.upto(C).drop_front(StringOffset));
     305       11857 :   return C;
     306             : }
     307             : 
     308     1360795 : static Cursor maybeLexIndex(Cursor C, MIToken &Token, StringRef Rule,
     309             :                             MIToken::TokenKind Kind) {
     310        3496 :   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
     311     1359047 :     return None;
     312             :   auto Range = C;
     313             :   C.advance(Rule.size());
     314             :   auto NumberRange = C;
     315        3517 :   while (isdigit(C.peek()))
     316             :     C.advance();
     317        5244 :   Token.reset(Kind, Range.upto(C)).setIntegerValue(APSInt(NumberRange.upto(C)));
     318        1748 :   return C;
     319             : }
     320             : 
     321      453445 : static Cursor maybeLexIndexAndName(Cursor C, MIToken &Token, StringRef Rule,
     322             :                                    MIToken::TokenKind Kind) {
     323        1010 :   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
     324      452940 :     return None;
     325             :   auto Range = C;
     326         505 :   C.advance(Rule.size());
     327             :   auto NumberRange = C;
     328        1010 :   while (isdigit(C.peek()))
     329             :     C.advance();
     330         505 :   StringRef Number = NumberRange.upto(C);
     331         505 :   unsigned StringOffset = Rule.size() + Number.size();
     332         505 :   if (C.peek() == '.') {
     333             :     C.advance();
     334         250 :     ++StringOffset;
     335        1001 :     while (isIdentifierChar(C.peek()))
     336             :       C.advance();
     337             :   }
     338         505 :   Token.reset(Kind, Range.upto(C))
     339        1010 :       .setIntegerValue(APSInt(Number))
     340        1010 :       .setStringValue(Range.upto(C).drop_front(StringOffset));
     341         505 :   return C;
     342             : }
     343             : 
     344             : static Cursor maybeLexJumpTableIndex(Cursor C, MIToken &Token) {
     345      453470 :   return maybeLexIndex(C, Token, "%jump-table.", MIToken::JumpTableIndex);
     346             : }
     347             : 
     348             : static Cursor maybeLexStackObject(Cursor C, MIToken &Token) {
     349      453445 :   return maybeLexIndexAndName(C, Token, "%stack.", MIToken::StackObject);
     350             : }
     351             : 
     352             : static Cursor maybeLexFixedStackObject(Cursor C, MIToken &Token) {
     353      452940 :   return maybeLexIndex(C, Token, "%fixed-stack.", MIToken::FixedStackObject);
     354             : }
     355             : 
     356             : static Cursor maybeLexConstantPoolItem(Cursor C, MIToken &Token) {
     357      452822 :   return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem);
     358             : }
     359             : 
     360      452780 : static Cursor maybeLexSubRegisterIndex(Cursor C, MIToken &Token,
     361             :                                        ErrorCallbackType ErrorCallback) {
     362             :   const StringRef Rule = "%subreg.";
     363             :   if (!C.remaining().startswith(Rule))
     364      452622 :     return None;
     365             :   return lexName(C, Token, MIToken::SubRegisterIndex, Rule.size(),
     366         158 :                  ErrorCallback);
     367             : }
     368             : 
     369      452622 : static Cursor maybeLexIRBlock(Cursor C, MIToken &Token,
     370             :                               ErrorCallbackType ErrorCallback) {
     371             :   const StringRef Rule = "%ir-block.";
     372             :   if (!C.remaining().startswith(Rule))
     373      451131 :     return None;
     374        1491 :   if (isdigit(C.peek(Rule.size())))
     375        1481 :     return maybeLexIndex(C, Token, Rule, MIToken::IRBlock);
     376          10 :   return lexName(C, Token, MIToken::NamedIRBlock, Rule.size(), ErrorCallback);
     377             : }
     378             : 
     379      451131 : static Cursor maybeLexIRValue(Cursor C, MIToken &Token,
     380             :                               ErrorCallbackType ErrorCallback) {
     381             :   const StringRef Rule = "%ir.";
     382             :   if (!C.remaining().startswith(Rule))
     383      449583 :     return None;
     384        1548 :   if (isdigit(C.peek(Rule.size())))
     385          82 :     return maybeLexIndex(C, Token, Rule, MIToken::IRValue);
     386        1466 :   return lexName(C, Token, MIToken::NamedIRValue, Rule.size(), ErrorCallback);
     387             : }
     388             : 
     389          59 : static Cursor maybeLexStringConstant(Cursor C, MIToken &Token,
     390             :                                      ErrorCallbackType ErrorCallback) {
     391          59 :   if (C.peek() != '"')
     392           1 :     return None;
     393             :   return lexName(C, Token, MIToken::StringConstant, /*PrefixLength=*/0,
     394          58 :                  ErrorCallback);
     395             : }
     396             : 
     397       46886 : static Cursor lexVirtualRegister(Cursor C, MIToken &Token) {
     398             :   auto Range = C;
     399             :   C.advance(); // Skip '%'
     400             :   auto NumberRange = C;
     401      101792 :   while (isdigit(C.peek()))
     402             :     C.advance();
     403       46886 :   Token.reset(MIToken::VirtualRegister, Range.upto(C))
     404       93772 :       .setIntegerValue(APSInt(NumberRange.upto(C)));
     405       46886 :   return C;
     406             : }
     407             : 
     408             : /// Returns true for a character allowed in a register name.
     409             : static bool isRegisterChar(char C) {
     410      355241 :   return isIdentifierChar(C) && C != '.';
     411             : }
     412             : 
     413      449583 : static Cursor maybeLexRegister(Cursor C, MIToken &Token,
     414             :                                ErrorCallbackType ErrorCallback) {
     415      852280 :   if (C.peek() != '%' && C.peek() != '$')
     416      328715 :     return None;
     417             : 
     418      120868 :   if (C.peek() == '%') {
     419       46886 :     if (isdigit(C.peek(1)))
     420       46886 :       return lexVirtualRegister(C, Token);
     421             : 
     422             :     // ErrorCallback(Token.location(), "Named vregs are not yet supported.");
     423           0 :     return None;
     424             :   }
     425             : 
     426             :   assert(C.peek() == '$');
     427             :   auto Range = C;
     428             :   C.advance(); // Skip '$'
     429      355241 :   while (isRegisterChar(C.peek()))
     430             :     C.advance();
     431       73982 :   Token.reset(MIToken::NamedRegister, Range.upto(C))
     432      147964 :       .setStringValue(Range.upto(C).drop_front(1)); // Drop the '$'
     433       73982 :   return C;
     434             : }
     435             : 
     436      328715 : static Cursor maybeLexGlobalValue(Cursor C, MIToken &Token,
     437             :                                   ErrorCallbackType ErrorCallback) {
     438      328715 :   if (C.peek() != '@')
     439      327604 :     return None;
     440        1111 :   if (!isdigit(C.peek(1)))
     441             :     return lexName(C, Token, MIToken::NamedGlobalValue, /*PrefixLength=*/1,
     442        1103 :                    ErrorCallback);
     443             :   auto Range = C;
     444             :   C.advance(1); // Skip the '@'
     445             :   auto NumberRange = C;
     446          16 :   while (isdigit(C.peek()))
     447             :     C.advance();
     448           8 :   Token.reset(MIToken::GlobalValue, Range.upto(C))
     449          16 :       .setIntegerValue(APSInt(NumberRange.upto(C)));
     450           8 :   return C;
     451             : }
     452             : 
     453      327604 : static Cursor maybeLexExternalSymbol(Cursor C, MIToken &Token,
     454             :                                      ErrorCallbackType ErrorCallback) {
     455      327604 :   if (C.peek() != '&')
     456      327468 :     return None;
     457             :   return lexName(C, Token, MIToken::ExternalSymbol, /*PrefixLength=*/1,
     458         136 :                  ErrorCallback);
     459             : }
     460             : 
     461             : static bool isValidHexFloatingPointPrefix(char C) {
     462         912 :   return C == 'H' || C == 'K' || C == 'L' || C == 'M';
     463             : }
     464             : 
     465          86 : static Cursor lexFloatingPointLiteral(Cursor Range, Cursor C, MIToken &Token) {
     466             :   C.advance();
     467             :   // Skip over [0-9]*([eE][-+]?[0-9]+)?
     468         338 :   while (isdigit(C.peek()))
     469             :     C.advance();
     470         204 :   if ((C.peek() == 'e' || C.peek() == 'E') &&
     471          64 :       (isdigit(C.peek(1)) ||
     472          64 :        ((C.peek(1) == '-' || C.peek(1) == '+') && isdigit(C.peek(2))))) {
     473             :     C.advance(2);
     474          96 :     while (isdigit(C.peek()))
     475             :       C.advance();
     476             :   }
     477         172 :   Token.reset(MIToken::FloatingPointLiteral, Range.upto(C));
     478          86 :   return C;
     479             : }
     480             : 
     481      327468 : static Cursor maybeLexHexadecimalLiteral(Cursor C, MIToken &Token) {
     482      352074 :   if (C.peek() != '0' || (C.peek(1) != 'x' && C.peek(1) != 'X'))
     483      326556 :     return None;
     484             :   Cursor Range = C;
     485             :   C.advance(2);
     486             :   unsigned PrefLen = 2;
     487             :   if (isValidHexFloatingPointPrefix(C.peek())) {
     488             :     C.advance();
     489             :     PrefLen++;
     490             :   }
     491        8134 :   while (isxdigit(C.peek()))
     492             :     C.advance();
     493             :   StringRef StrVal = Range.upto(C);
     494         912 :   if (StrVal.size() <= PrefLen)
     495           0 :     return None;
     496         912 :   if (PrefLen == 2)
     497         910 :     Token.reset(MIToken::HexLiteral, Range.upto(C));
     498             :   else // It must be 3, which means that there was a floating-point prefix.
     499           2 :     Token.reset(MIToken::FloatingPointLiteral, Range.upto(C));
     500         912 :   return C;
     501             : }
     502             : 
     503      326556 : static Cursor maybeLexNumericalLiteral(Cursor C, MIToken &Token) {
     504      621870 :   if (!isdigit(C.peek()) && (C.peek() != '-' || !isdigit(C.peek(1))))
     505      293768 :     return None;
     506             :   auto Range = C;
     507             :   C.advance();
     508       46685 :   while (isdigit(C.peek()))
     509             :     C.advance();
     510       32781 :   if (C.peek() == '.')
     511          86 :     return lexFloatingPointLiteral(Range, C, Token);
     512       32702 :   StringRef StrVal = Range.upto(C);
     513       65404 :   Token.reset(MIToken::IntegerLiteral, StrVal).setIntegerValue(APSInt(StrVal));
     514       32702 :   return C;
     515             : }
     516             : 
     517         408 : static MIToken::TokenKind getMetadataKeywordKind(StringRef Identifier) {
     518             :   return StringSwitch<MIToken::TokenKind>(Identifier)
     519         816 :       .Case("!tbaa", MIToken::md_tbaa)
     520         816 :       .Case("!alias.scope", MIToken::md_alias_scope)
     521         816 :       .Case("!noalias", MIToken::md_noalias)
     522         816 :       .Case("!range", MIToken::md_range)
     523         816 :       .Case("!DIExpression", MIToken::md_diexpr)
     524         408 :       .Default(MIToken::Error);
     525             : }
     526             : 
     527      293768 : static Cursor maybeLexExlaim(Cursor C, MIToken &Token,
     528             :                              ErrorCallbackType ErrorCallback) {
     529      293768 :   if (C.peek() != '!')
     530      291291 :     return None;
     531             :   auto Range = C;
     532             :   C.advance(1);
     533        2477 :   if (isdigit(C.peek()) || !isIdentifierChar(C.peek())) {
     534        2069 :     Token.reset(MIToken::exclaim, Range.upto(C));
     535        2069 :     return C;
     536             :   }
     537        2677 :   while (isIdentifierChar(C.peek()))
     538             :     C.advance();
     539         408 :   StringRef StrVal = Range.upto(C);
     540         408 :   Token.reset(getMetadataKeywordKind(StrVal), StrVal);
     541         408 :   if (Token.isError())
     542             :     ErrorCallback(Token.location(),
     543           1 :                   "use of unknown metadata keyword '" + StrVal + "'");
     544         408 :   return C;
     545             : }
     546             : 
     547             : static MIToken::TokenKind symbolToken(char C) {
     548      288274 :   switch (C) {
     549             :   case ',':
     550             :     return MIToken::comma;
     551             :   case '.':
     552             :     return MIToken::dot;
     553             :   case '=':
     554             :     return MIToken::equal;
     555             :   case ':':
     556             :     return MIToken::colon;
     557             :   case '(':
     558             :     return MIToken::lparen;
     559             :   case ')':
     560             :     return MIToken::rparen;
     561             :   case '{':
     562             :     return MIToken::lbrace;
     563             :   case '}':
     564             :     return MIToken::rbrace;
     565             :   case '+':
     566             :     return MIToken::plus;
     567             :   case '-':
     568             :     return MIToken::minus;
     569             :   case '<':
     570             :     return MIToken::less;
     571             :   case '>':
     572             :     return MIToken::greater;
     573             :   default:
     574             :     return MIToken::Error;
     575             :   }
     576             : }
     577             : 
     578      291291 : static Cursor maybeLexSymbol(Cursor C, MIToken &Token) {
     579             :   MIToken::TokenKind Kind;
     580             :   unsigned Length = 1;
     581      312107 :   if (C.peek() == ':' && C.peek(1) == ':') {
     582             :     Kind = MIToken::coloncolon;
     583             :     Length = 2;
     584             :   } else
     585             :     Kind = symbolToken(C.peek());
     586      288274 :   if (Kind == MIToken::Error)
     587      110938 :     return None;
     588             :   auto Range = C;
     589             :   C.advance(Length);
     590      180353 :   Token.reset(Kind, Range.upto(C));
     591      180353 :   return C;
     592             : }
     593             : 
     594      110938 : static Cursor maybeLexNewline(Cursor C, MIToken &Token) {
     595      110938 :   if (!isNewlineChar(C.peek()))
     596         367 :     return None;
     597             :   auto Range = C;
     598             :   C.advance();
     599      110571 :   Token.reset(MIToken::Newline, Range.upto(C));
     600      110571 :   return C;
     601             : }
     602             : 
     603         367 : static Cursor maybeLexEscapedIRValue(Cursor C, MIToken &Token,
     604             :                                      ErrorCallbackType ErrorCallback) {
     605         367 :   if (C.peek() != '`')
     606          59 :     return None;
     607             :   auto Range = C;
     608             :   C.advance();
     609             :   auto StrRange = C;
     610        9486 :   while (C.peek() != '`') {
     611       18356 :     if (C.isEOF() || isNewlineChar(C.peek())) {
     612           0 :       ErrorCallback(
     613             :           C.location(),
     614             :           "end of machine instruction reached before the closing '`'");
     615           0 :       Token.reset(MIToken::Error, Range.remaining());
     616           0 :       return C;
     617             :     }
     618             :     C.advance();
     619             :   }
     620         308 :   StringRef Value = StrRange.upto(C);
     621             :   C.advance();
     622         308 :   Token.reset(MIToken::QuotedIRValue, Range.upto(C)).setStringValue(Value);
     623         308 :   return C;
     624             : }
     625             : 
     626      591043 : StringRef llvm::lexMIToken(StringRef Source, MIToken &Token,
     627             :                            ErrorCallbackType ErrorCallback) {
     628      591043 :   auto C = skipComment(skipWhitespace(Cursor(Source)));
     629      591043 :   if (C.isEOF()) {
     630        8565 :     Token.reset(MIToken::Eof, C.remaining());
     631             :     return C.remaining();
     632             :   }
     633             : 
     634      582478 :   if (Cursor R = maybeLexIntegerOrScalarType(C, Token))
     635       19863 :     return R.remaining();
     636      562615 :   if (Cursor R = maybeLexMachineBasicBlock(C, Token, ErrorCallback))
     637       11858 :     return R.remaining();
     638      550757 :   if (Cursor R = maybeLexIdentifier(C, Token))
     639       97287 :     return R.remaining();
     640      453470 :   if (Cursor R = maybeLexJumpTableIndex(C, Token))
     641             :     return R.remaining();
     642      453445 :   if (Cursor R = maybeLexStackObject(C, Token))
     643             :     return R.remaining();
     644      452940 :   if (Cursor R = maybeLexFixedStackObject(C, Token))
     645             :     return R.remaining();
     646      452822 :   if (Cursor R = maybeLexConstantPoolItem(C, Token))
     647             :     return R.remaining();
     648      452780 :   if (Cursor R = maybeLexSubRegisterIndex(C, Token, ErrorCallback))
     649         158 :     return R.remaining();
     650      452622 :   if (Cursor R = maybeLexIRBlock(C, Token, ErrorCallback))
     651        1491 :     return R.remaining();
     652      451131 :   if (Cursor R = maybeLexIRValue(C, Token, ErrorCallback))
     653        1548 :     return R.remaining();
     654      449583 :   if (Cursor R = maybeLexRegister(C, Token, ErrorCallback))
     655      120868 :     return R.remaining();
     656      328715 :   if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback))
     657        1111 :     return R.remaining();
     658      327604 :   if (Cursor R = maybeLexExternalSymbol(C, Token, ErrorCallback))
     659         136 :     return R.remaining();
     660      327468 :   if (Cursor R = maybeLexHexadecimalLiteral(C, Token))
     661         912 :     return R.remaining();
     662      326556 :   if (Cursor R = maybeLexNumericalLiteral(C, Token))
     663       32788 :     return R.remaining();
     664      293768 :   if (Cursor R = maybeLexExlaim(C, Token, ErrorCallback))
     665        2477 :     return R.remaining();
     666      291291 :   if (Cursor R = maybeLexSymbol(C, Token))
     667      180353 :     return R.remaining();
     668      110938 :   if (Cursor R = maybeLexNewline(C, Token))
     669      110571 :     return R.remaining();
     670         367 :   if (Cursor R = maybeLexEscapedIRValue(C, Token, ErrorCallback))
     671         308 :     return R.remaining();
     672          59 :   if (Cursor R = maybeLexStringConstant(C, Token, ErrorCallback))
     673          58 :     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