LCOV - code coverage report
Current view: top level - lib/CodeGen/MIRParser - MILexer.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 339 385 88.1 %
Date: 2018-10-20 13:21:21 Functions: 32 42 76.2 %
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           0 :   Cursor(NoneType) {}
      42             : 
      43      922786 :   explicit Cursor(StringRef Str) {
      44      922786 :     Ptr = Str.data();
      45      923364 :     End = Ptr + Str.size();
      46             :   }
      47             : 
      48           0 :   bool isEOF() const { return Ptr == End; }
      49             : 
      50    10323978 :   char peek(int I = 0) const { return End - Ptr <= I ? 0 : Ptr[I]; }
      51             : 
      52     5668296 :   void advance(unsigned I = 1) { Ptr += I; }
      53             : 
      54        1308 :   StringRef remaining() const { return StringRef(Ptr, End - Ptr); }
      55             : 
      56           0 :   StringRef upto(Cursor C) const {
      57             :     assert(C.Ptr >= Ptr && C.Ptr <= End);
      58      718336 :     return StringRef(Ptr, C.Ptr - Ptr);
      59             :   }
      60             : 
      61           0 :   StringRef::iterator location() const { return Ptr; }
      62             : 
      63           0 :   operator bool() const { return Ptr != nullptr; }
      64             : };
      65             : 
      66             : } // end anonymous namespace
      67             : 
      68      922786 : MIToken &MIToken::reset(TokenKind Kind, StringRef Range) {
      69      922786 :   this->Kind = Kind;
      70      922786 :   this->Range = Range;
      71      922786 :   return *this;
      72             : }
      73             : 
      74      327290 : MIToken &MIToken::setStringValue(StringRef StrVal) {
      75      327290 :   StringValue = StrVal;
      76      327290 :   return *this;
      77             : }
      78             : 
      79         578 : MIToken &MIToken::setOwnedStringValue(std::string StrVal) {
      80         578 :   StringValueStorage = std::move(StrVal);
      81         578 :   StringValue = StringValueStorage;
      82         578 :   return *this;
      83             : }
      84             : 
      85      140014 : MIToken &MIToken::setIntegerValue(APSInt IntVal) {
      86      140014 :   this->IntVal = std::move(IntVal);
      87      140014 :   return *this;
      88             : }
      89             : 
      90             : /// Skip the leading whitespace characters and return the updated cursor.
      91      922786 : static Cursor skipWhitespace(Cursor C) {
      92     1780308 :   while (isblank(C.peek()))
      93             :     C.advance();
      94      922786 :   return C;
      95             : }
      96             : 
      97     3525831 : static bool isNewlineChar(char C) { return C == '\n' || C == '\r'; }
      98             : 
      99             : /// Skip a line comment and return the updated cursor.
     100      922786 : static Cursor skipComment(Cursor C) {
     101      909909 :   if (C.peek() != ';')
     102      853028 :     return C;
     103     3317170 :   while (!isNewlineChar(C.peek()) && !C.isEOF())
     104             :     C.advance();
     105       69758 :   return C;
     106             : }
     107             : 
     108             : /// Return true if the given character satisfies the following regular
     109             : /// expression: [-a-zA-Z$._0-9]
     110     2028055 : static bool isIdentifierChar(char C) {
     111     2028055 :   return isalpha(C) || isdigit(C) || C == '_' || C == '-' || C == '.' ||
     112      314598 :          C == '$';
     113             : }
     114             : 
     115             : /// Unescapes the given string value.
     116             : ///
     117             : /// Expects the string value to be quoted.
     118         578 : static std::string unescapeQuotedString(StringRef Value) {
     119             :   assert(Value.front() == '"' && Value.back() == '"');
     120        1156 :   Cursor C = Cursor(Value.substr(1, Value.size() - 2));
     121             : 
     122             :   std::string Str;
     123         578 :   Str.reserve(C.remaining().size());
     124        7656 :   while (!C.isEOF()) {
     125             :     char Char = C.peek();
     126        7078 :     if (Char == '\\') {
     127          42 :       if (C.peek(1) == '\\') {
     128             :         // Two '\' become one
     129             :         Str += '\\';
     130             :         C.advance(2);
     131           2 :         continue;
     132             :       }
     133          80 :       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        7036 :     Str += Char;
     140             :     C.advance();
     141             :   }
     142         578 :   return Str;
     143             : }
     144             : 
     145             : /// Lex a string constant using the following regular expression: \"[^\"]*\"
     146         579 : static Cursor lexStringConstant(Cursor C, ErrorCallbackType ErrorCallback) {
     147             :   assert(C.peek() == '"');
     148        7753 :   for (C.advance(); C.peek() != '"'; C.advance()) {
     149       14350 :     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         578 :   return C;
     158             : }
     159             : 
     160        4950 : static Cursor lexName(Cursor C, MIToken &Token, MIToken::TokenKind Type,
     161             :                       unsigned PrefixLength, ErrorCallbackType ErrorCallback) {
     162             :   auto Range = C;
     163             :   C.advance(PrefixLength);
     164        4950 :   if (C.peek() == '"') {
     165         579 :     if (Cursor R = lexStringConstant(C, ErrorCallback)) {
     166         578 :       StringRef String = Range.upto(R);
     167         578 :       Token.reset(Type, String)
     168             :           .setOwnedStringValue(
     169         578 :               unescapeQuotedString(String.drop_front(PrefixLength)));
     170         578 :       return R;
     171             :     }
     172           1 :     Token.reset(MIToken::Error, Range.remaining());
     173           1 :     return Range;
     174             :   }
     175       32151 :   while (isIdentifierChar(C.peek()))
     176             :     C.advance();
     177        4371 :   Token.reset(Type, Range.upto(C))
     178        8742 :       .setStringValue(Range.upto(C).drop_front(PrefixLength));
     179        4371 :   return C;
     180             : }
     181             : 
     182      194916 : static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
     183      194916 :   return StringSwitch<MIToken::TokenKind>(Identifier)
     184      194916 :       .Case("_", MIToken::underscore)
     185      194916 :       .Case("implicit", MIToken::kw_implicit)
     186      194916 :       .Case("implicit-def", MIToken::kw_implicit_define)
     187      194916 :       .Case("def", MIToken::kw_def)
     188      194916 :       .Case("dead", MIToken::kw_dead)
     189      194916 :       .Case("killed", MIToken::kw_killed)
     190      194916 :       .Case("undef", MIToken::kw_undef)
     191      194916 :       .Case("internal", MIToken::kw_internal)
     192      194916 :       .Case("early-clobber", MIToken::kw_early_clobber)
     193      194916 :       .Case("debug-use", MIToken::kw_debug_use)
     194      194916 :       .Case("renamable", MIToken::kw_renamable)
     195      194916 :       .Case("tied-def", MIToken::kw_tied_def)
     196      194916 :       .Case("frame-setup", MIToken::kw_frame_setup)
     197      194916 :       .Case("frame-destroy", MIToken::kw_frame_destroy)
     198      194916 :       .Case("nnan", MIToken::kw_nnan)
     199      194916 :       .Case("ninf", MIToken::kw_ninf)
     200      194916 :       .Case("nsz", MIToken::kw_nsz)
     201      194916 :       .Case("arcp", MIToken::kw_arcp)
     202      194916 :       .Case("contract", MIToken::kw_contract)
     203      194916 :       .Case("afn", MIToken::kw_afn)
     204      194916 :       .Case("reassoc", MIToken::kw_reassoc)
     205      194916 :       .Case("nuw" , MIToken::kw_nuw)
     206      194916 :       .Case("nsw" , MIToken::kw_nsw)
     207      194916 :       .Case("exact" , MIToken::kw_exact)
     208      194916 :       .Case("debug-location", MIToken::kw_debug_location)
     209      194916 :       .Case("same_value", MIToken::kw_cfi_same_value)
     210      194916 :       .Case("offset", MIToken::kw_cfi_offset)
     211      194916 :       .Case("rel_offset", MIToken::kw_cfi_rel_offset)
     212      194916 :       .Case("def_cfa_register", MIToken::kw_cfi_def_cfa_register)
     213      194916 :       .Case("def_cfa_offset", MIToken::kw_cfi_def_cfa_offset)
     214      194916 :       .Case("adjust_cfa_offset", MIToken::kw_cfi_adjust_cfa_offset)
     215      194916 :       .Case("escape", MIToken::kw_cfi_escape)
     216      194916 :       .Case("def_cfa", MIToken::kw_cfi_def_cfa)
     217      194916 :       .Case("remember_state", MIToken::kw_cfi_remember_state)
     218      194916 :       .Case("restore", MIToken::kw_cfi_restore)
     219      194916 :       .Case("restore_state", MIToken::kw_cfi_restore_state)
     220      194916 :       .Case("undefined", MIToken::kw_cfi_undefined)
     221      194916 :       .Case("register", MIToken::kw_cfi_register)
     222      194916 :       .Case("window_save", MIToken::kw_cfi_window_save)
     223      194916 :       .Case("blockaddress", MIToken::kw_blockaddress)
     224      194916 :       .Case("intrinsic", MIToken::kw_intrinsic)
     225      194916 :       .Case("target-index", MIToken::kw_target_index)
     226      194916 :       .Case("half", MIToken::kw_half)
     227      194916 :       .Case("float", MIToken::kw_float)
     228      194916 :       .Case("double", MIToken::kw_double)
     229      194916 :       .Case("x86_fp80", MIToken::kw_x86_fp80)
     230      194916 :       .Case("fp128", MIToken::kw_fp128)
     231      194916 :       .Case("ppc_fp128", MIToken::kw_ppc_fp128)
     232      194916 :       .Case("target-flags", MIToken::kw_target_flags)
     233      194916 :       .Case("volatile", MIToken::kw_volatile)
     234      194916 :       .Case("non-temporal", MIToken::kw_non_temporal)
     235      194916 :       .Case("dereferenceable", MIToken::kw_dereferenceable)
     236      194916 :       .Case("invariant", MIToken::kw_invariant)
     237      194916 :       .Case("align", MIToken::kw_align)
     238      194916 :       .Case("addrspace", MIToken::kw_addrspace)
     239      194916 :       .Case("stack", MIToken::kw_stack)
     240      194916 :       .Case("got", MIToken::kw_got)
     241      194916 :       .Case("jump-table", MIToken::kw_jump_table)
     242      194916 :       .Case("constant-pool", MIToken::kw_constant_pool)
     243      194916 :       .Case("call-entry", MIToken::kw_call_entry)
     244      194916 :       .Case("liveout", MIToken::kw_liveout)
     245      194916 :       .Case("address-taken", MIToken::kw_address_taken)
     246      194916 :       .Case("landing-pad", MIToken::kw_landing_pad)
     247      194916 :       .Case("liveins", MIToken::kw_liveins)
     248      194916 :       .Case("successors", MIToken::kw_successors)
     249      194916 :       .Case("floatpred", MIToken::kw_floatpred)
     250      194916 :       .Case("intpred", MIToken::kw_intpred)
     251      194916 :       .Case("pre-instr-symbol", MIToken::kw_pre_instr_symbol)
     252      194916 :       .Case("post-instr-symbol", MIToken::kw_post_instr_symbol)
     253      194916 :       .Case("unknown-size", MIToken::kw_unknown_size)
     254      194916 :       .Default(MIToken::Identifier);
     255             : }
     256             : 
     257      890482 : static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) {
     258     1593096 :   if (!isalpha(C.peek()) && C.peek() != '_')
     259      695566 :     return None;
     260             :   auto Range = C;
     261     1439749 :   while (isIdentifierChar(C.peek()))
     262             :     C.advance();
     263      194916 :   auto Identifier = Range.upto(C);
     264      194916 :   Token.reset(getIdentifierKind(Identifier), Identifier)
     265      194916 :       .setStringValue(Identifier);
     266      194916 :   return C;
     267             : }
     268             : 
     269      909909 : static Cursor maybeLexMachineBasicBlock(Cursor C, MIToken &Token,
     270             :                                         ErrorCallbackType ErrorCallback) {
     271             :   bool IsReference = C.remaining().startswith("%bb.");
     272             :   if (!IsReference && !C.remaining().startswith("bb."))
     273      890482 :     return None;
     274             :   auto Range = C;
     275       19427 :   unsigned PrefixLength = IsReference ? 4 : 3;
     276             :   C.advance(PrefixLength); // Skip '%bb.' or 'bb.'
     277       19427 :   if (!isdigit(C.peek())) {
     278           1 :     Token.reset(MIToken::Error, C.remaining());
     279           1 :     ErrorCallback(C.location(), "expected a number after '%bb.'");
     280           1 :     return C;
     281             :   }
     282             :   auto NumberRange = C;
     283       39980 :   while (isdigit(C.peek()))
     284             :     C.advance();
     285       19426 :   StringRef Number = NumberRange.upto(C);
     286       19426 :   unsigned StringOffset = PrefixLength + Number.size(); // Drop '%bb.<id>'
     287             :   // TODO: The format bb.<id>.<irname> is supported only when it's not a
     288             :   // reference. Once we deprecate the format where the irname shows up, we
     289             :   // should only lex forward if it is a reference.
     290       19411 :   if (C.peek() == '.') {
     291             :     C.advance(); // Skip '.'
     292        5184 :     ++StringOffset;
     293       33062 :     while (isIdentifierChar(C.peek()))
     294             :       C.advance();
     295             :   }
     296             :   Token.reset(IsReference ? MIToken::MachineBasicBlock
     297             :                           : MIToken::MachineBasicBlockLabel,
     298       32267 :               Range.upto(C))
     299       19426 :       .setIntegerValue(APSInt(Number))
     300       38852 :       .setStringValue(Range.upto(C).drop_front(StringOffset));
     301       19426 :   return C;
     302             : }
     303             : 
     304     2086991 : static Cursor maybeLexIndex(Cursor C, MIToken &Token, StringRef Rule,
     305             :                             MIToken::TokenKind Kind) {
     306        5696 :   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
     307     2084143 :     return None;
     308             :   auto Range = C;
     309             :   C.advance(Rule.size());
     310             :   auto NumberRange = C;
     311        5799 :   while (isdigit(C.peek()))
     312             :     C.advance();
     313        2848 :   Token.reset(Kind, Range.upto(C)).setIntegerValue(APSInt(NumberRange.upto(C)));
     314        2848 :   return C;
     315             : }
     316             : 
     317      695537 : static Cursor maybeLexIndexAndName(Cursor C, MIToken &Token, StringRef Rule,
     318             :                                    MIToken::TokenKind Kind) {
     319        1750 :   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
     320      694662 :     return None;
     321             :   auto Range = C;
     322         875 :   C.advance(Rule.size());
     323             :   auto NumberRange = C;
     324        1750 :   while (isdigit(C.peek()))
     325             :     C.advance();
     326         875 :   StringRef Number = NumberRange.upto(C);
     327         875 :   unsigned StringOffset = Rule.size() + Number.size();
     328         875 :   if (C.peek() == '.') {
     329             :     C.advance();
     330         406 :     ++StringOffset;
     331        1789 :     while (isIdentifierChar(C.peek()))
     332             :       C.advance();
     333             :   }
     334         875 :   Token.reset(Kind, Range.upto(C))
     335         875 :       .setIntegerValue(APSInt(Number))
     336        1750 :       .setStringValue(Range.upto(C).drop_front(StringOffset));
     337         875 :   return C;
     338             : }
     339             : 
     340             : static Cursor maybeLexJumpTableIndex(Cursor C, MIToken &Token) {
     341      695566 :   return maybeLexIndex(C, Token, "%jump-table.", MIToken::JumpTableIndex);
     342             : }
     343             : 
     344             : static Cursor maybeLexStackObject(Cursor C, MIToken &Token) {
     345      695537 :   return maybeLexIndexAndName(C, Token, "%stack.", MIToken::StackObject);
     346             : }
     347             : 
     348             : static Cursor maybeLexFixedStackObject(Cursor C, MIToken &Token) {
     349      694662 :   return maybeLexIndex(C, Token, "%fixed-stack.", MIToken::FixedStackObject);
     350             : }
     351             : 
     352             : static Cursor maybeLexConstantPoolItem(Cursor C, MIToken &Token) {
     353      694348 :   return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem);
     354             : }
     355             : 
     356      694258 : static Cursor maybeLexSubRegisterIndex(Cursor C, MIToken &Token,
     357             :                                        ErrorCallbackType ErrorCallback) {
     358             :   const StringRef Rule = "%subreg.";
     359      694258 :   if (!C.remaining().startswith(Rule))
     360      693980 :     return None;
     361             :   return lexName(C, Token, MIToken::SubRegisterIndex, Rule.size(),
     362         278 :                  ErrorCallback);
     363             : }
     364             : 
     365      693980 : static Cursor maybeLexIRBlock(Cursor C, MIToken &Token,
     366             :                               ErrorCallbackType ErrorCallback) {
     367             :   const StringRef Rule = "%ir-block.";
     368             :   if (!C.remaining().startswith(Rule))
     369      691743 :     return None;
     370        2237 :   if (isdigit(C.peek(Rule.size())))
     371        2205 :     return maybeLexIndex(C, Token, Rule, MIToken::IRBlock);
     372          32 :   return lexName(C, Token, MIToken::NamedIRBlock, Rule.size(), ErrorCallback);
     373             : }
     374             : 
     375      691743 : static Cursor maybeLexIRValue(Cursor C, MIToken &Token,
     376             :                               ErrorCallbackType ErrorCallback) {
     377             :   const StringRef Rule = "%ir.";
     378             :   if (!C.remaining().startswith(Rule))
     379      689666 :     return None;
     380        2077 :   if (isdigit(C.peek(Rule.size())))
     381         210 :     return maybeLexIndex(C, Token, Rule, MIToken::IRValue);
     382        1867 :   return lexName(C, Token, MIToken::NamedIRValue, Rule.size(), ErrorCallback);
     383             : }
     384             : 
     385         219 : static Cursor maybeLexStringConstant(Cursor C, MIToken &Token,
     386             :                                      ErrorCallbackType ErrorCallback) {
     387         219 :   if (C.peek() != '"')
     388           1 :     return None;
     389             :   return lexName(C, Token, MIToken::StringConstant, /*PrefixLength=*/0,
     390         218 :                  ErrorCallback);
     391             : }
     392             : 
     393       68685 : static Cursor lexVirtualRegister(Cursor C, MIToken &Token) {
     394             :   auto Range = C;
     395             :   C.advance(); // Skip '%'
     396             :   auto NumberRange = C;
     397      148934 :   while (isdigit(C.peek()))
     398             :     C.advance();
     399       68685 :   Token.reset(MIToken::VirtualRegister, Range.upto(C))
     400       68685 :       .setIntegerValue(APSInt(NumberRange.upto(C)));
     401       68685 :   return C;
     402             : }
     403             : 
     404             : /// Returns true for a character allowed in a register name.
     405             : static bool isRegisterChar(char C) {
     406         544 :   return isIdentifierChar(C) && C != '.';
     407             : }
     408             : 
     409          88 : static Cursor lexNamedVirtualRegister(Cursor C, MIToken &Token) {
     410             :   Cursor Range = C;
     411             :   C.advance(); // Skip '%'
     412         632 :   while (isRegisterChar(C.peek()))
     413             :     C.advance();
     414          88 :   Token.reset(MIToken::NamedVirtualRegister, Range.upto(C))
     415         176 :       .setStringValue(Range.upto(C).drop_front(1)); // Drop the '%'
     416          88 :   return C;
     417             : }
     418             : 
     419           0 : static Cursor maybeLexRegister(Cursor C, MIToken &Token,
     420             :                                ErrorCallbackType ErrorCallback) {
     421           0 :   if (C.peek() != '%' && C.peek() != '$')
     422           0 :     return None;
     423             : 
     424           0 :   if (C.peek() == '%') {
     425           0 :     if (isdigit(C.peek(1)))
     426           0 :       return lexVirtualRegister(C, Token);
     427             : 
     428           0 :     if (isRegisterChar(C.peek(1)))
     429           0 :       return lexNamedVirtualRegister(C, Token);
     430             : 
     431           0 :     return None;
     432             :   }
     433             : 
     434             :   assert(C.peek() == '$');
     435             :   auto Range = C;
     436             :   C.advance(); // Skip '$'
     437           0 :   while (isRegisterChar(C.peek()))
     438             :     C.advance();
     439           0 :   Token.reset(MIToken::NamedRegister, Range.upto(C))
     440           0 :       .setStringValue(Range.upto(C).drop_front(1)); // Drop the '$'
     441           0 :   return C;
     442             : }
     443             : 
     444      514305 : static Cursor maybeLexGlobalValue(Cursor C, MIToken &Token,
     445             :                                   ErrorCallbackType ErrorCallback) {
     446      514305 :   if (C.peek() != '@')
     447      512204 :     return None;
     448        2101 :   if (!isdigit(C.peek(1)))
     449             :     return lexName(C, Token, MIToken::NamedGlobalValue, /*PrefixLength=*/1,
     450        2089 :                    ErrorCallback);
     451             :   auto Range = C;
     452             :   C.advance(1); // Skip the '@'
     453             :   auto NumberRange = C;
     454          24 :   while (isdigit(C.peek()))
     455             :     C.advance();
     456          12 :   Token.reset(MIToken::GlobalValue, Range.upto(C))
     457          12 :       .setIntegerValue(APSInt(NumberRange.upto(C)));
     458          12 :   return C;
     459             : }
     460             : 
     461      512204 : static Cursor maybeLexExternalSymbol(Cursor C, MIToken &Token,
     462             :                                      ErrorCallbackType ErrorCallback) {
     463      512204 :   if (C.peek() != '&')
     464      511738 :     return None;
     465             :   return lexName(C, Token, MIToken::ExternalSymbol, /*PrefixLength=*/1,
     466         466 :                  ErrorCallback);
     467             : }
     468             : 
     469      511738 : static Cursor maybeLexMCSymbol(Cursor C, MIToken &Token,
     470             :                                ErrorCallbackType ErrorCallback) {
     471             :   const StringRef Rule = "<mcsymbol ";
     472             :   if (!C.remaining().startswith(Rule))
     473      511706 :     return None;
     474             :   auto Start = C;
     475             :   C.advance(Rule.size());
     476             : 
     477             :   // Try a simple unquoted name.
     478          32 :   if (C.peek() != '"') {
     479         272 :     while (isIdentifierChar(C.peek()))
     480             :       C.advance();
     481          64 :     StringRef String = Start.upto(C).drop_front(Rule.size());
     482          32 :     if (C.peek() != '>') {
     483           0 :       ErrorCallback(C.location(),
     484             :                     "expected the '<mcsymbol ...' to be closed by a '>'");
     485           0 :       Token.reset(MIToken::Error, Start.remaining());
     486           0 :       return Start;
     487             :     }
     488             :     C.advance();
     489             : 
     490          32 :     Token.reset(MIToken::MCSymbol, Start.upto(C)).setStringValue(String);
     491          32 :     return C;
     492             :   }
     493             : 
     494             :   // Otherwise lex out a quoted name.
     495           0 :   Cursor R = lexStringConstant(C, ErrorCallback);
     496           0 :   if (!R) {
     497           0 :     ErrorCallback(C.location(),
     498             :                   "unable to parse quoted string from opening quote");
     499           0 :     Token.reset(MIToken::Error, Start.remaining());
     500           0 :     return Start;
     501             :   }
     502           0 :   StringRef String = Start.upto(R).drop_front(Rule.size());
     503           0 :   if (R.peek() != '>') {
     504           0 :     ErrorCallback(R.location(),
     505             :                   "expected the '<mcsymbol ...' to be closed by a '>'");
     506           0 :     Token.reset(MIToken::Error, Start.remaining());
     507           0 :     return Start;
     508             :   }
     509             :   R.advance();
     510             : 
     511           0 :   Token.reset(MIToken::MCSymbol, Start.upto(R))
     512           0 :       .setOwnedStringValue(unescapeQuotedString(String));
     513           0 :   return R;
     514             : }
     515             : 
     516             : static bool isValidHexFloatingPointPrefix(char C) {
     517        2192 :   return C == 'H' || C == 'K' || C == 'L' || C == 'M';
     518             : }
     519             : 
     520           0 : static Cursor lexFloatingPointLiteral(Cursor Range, Cursor C, MIToken &Token) {
     521             :   C.advance();
     522             :   // Skip over [0-9]*([eE][-+]?[0-9]+)?
     523           0 :   while (isdigit(C.peek()))
     524             :     C.advance();
     525           0 :   if ((C.peek() == 'e' || C.peek() == 'E') &&
     526           0 :       (isdigit(C.peek(1)) ||
     527           0 :        ((C.peek(1) == '-' || C.peek(1) == '+') && isdigit(C.peek(2))))) {
     528             :     C.advance(2);
     529           0 :     while (isdigit(C.peek()))
     530             :       C.advance();
     531             :   }
     532           0 :   Token.reset(MIToken::FloatingPointLiteral, Range.upto(C));
     533           0 :   return C;
     534             : }
     535             : 
     536      511706 : static Cursor maybeLexHexadecimalLiteral(Cursor C, MIToken &Token) {
     537      548708 :   if (C.peek() != '0' || (C.peek(1) != 'x' && C.peek(1) != 'X'))
     538      509514 :     return None;
     539             :   Cursor Range = C;
     540             :   C.advance(2);
     541             :   unsigned PrefLen = 2;
     542             :   if (isValidHexFloatingPointPrefix(C.peek())) {
     543             :     C.advance();
     544             :     PrefLen++;
     545             :   }
     546       19654 :   while (isxdigit(C.peek()))
     547             :     C.advance();
     548             :   StringRef StrVal = Range.upto(C);
     549        2192 :   if (StrVal.size() <= PrefLen)
     550           0 :     return None;
     551        2192 :   if (PrefLen == 2)
     552        2190 :     Token.reset(MIToken::HexLiteral, Range.upto(C));
     553             :   else // It must be 3, which means that there was a floating-point prefix.
     554           2 :     Token.reset(MIToken::FloatingPointLiteral, Range.upto(C));
     555        2192 :   return C;
     556             : }
     557             : 
     558      509514 : static Cursor maybeLexNumericalLiteral(Cursor C, MIToken &Token) {
     559      973334 :   if (!isdigit(C.peek()) && (C.peek() != '-' || !isdigit(C.peek(1))))
     560      461246 :     return None;
     561             :   auto Range = C;
     562             :   C.advance();
     563       68191 :   while (isdigit(C.peek()))
     564             :     C.advance();
     565       48259 :   if (C.peek() == '.')
     566         100 :     return lexFloatingPointLiteral(Range, C, Token);
     567       48168 :   StringRef StrVal = Range.upto(C);
     568       48168 :   Token.reset(MIToken::IntegerLiteral, StrVal).setIntegerValue(APSInt(StrVal));
     569       48168 :   return C;
     570             : }
     571             : 
     572         471 : static MIToken::TokenKind getMetadataKeywordKind(StringRef Identifier) {
     573         471 :   return StringSwitch<MIToken::TokenKind>(Identifier)
     574         471 :       .Case("!tbaa", MIToken::md_tbaa)
     575         471 :       .Case("!alias.scope", MIToken::md_alias_scope)
     576         471 :       .Case("!noalias", MIToken::md_noalias)
     577         471 :       .Case("!range", MIToken::md_range)
     578         471 :       .Case("!DIExpression", MIToken::md_diexpr)
     579         471 :       .Default(MIToken::Error);
     580             : }
     581             : 
     582      461246 : static Cursor maybeLexExlaim(Cursor C, MIToken &Token,
     583             :                              ErrorCallbackType ErrorCallback) {
     584      461246 :   if (C.peek() != '!')
     585      458420 :     return None;
     586             :   auto Range = C;
     587             :   C.advance(1);
     588        2826 :   if (isdigit(C.peek()) || !isIdentifierChar(C.peek())) {
     589        2355 :     Token.reset(MIToken::exclaim, Range.upto(C));
     590        2355 :     return C;
     591             :   }
     592        3464 :   while (isIdentifierChar(C.peek()))
     593             :     C.advance();
     594         471 :   StringRef StrVal = Range.upto(C);
     595         471 :   Token.reset(getMetadataKeywordKind(StrVal), StrVal);
     596         471 :   if (Token.isError())
     597           1 :     ErrorCallback(Token.location(),
     598           1 :                   "use of unknown metadata keyword '" + StrVal + "'");
     599         471 :   return C;
     600             : }
     601             : 
     602             : static MIToken::TokenKind symbolToken(char C) {
     603      453593 :   switch (C) {
     604             :   case ',':
     605             :     return MIToken::comma;
     606             :   case '.':
     607             :     return MIToken::dot;
     608             :   case '=':
     609             :     return MIToken::equal;
     610             :   case ':':
     611             :     return MIToken::colon;
     612             :   case '(':
     613             :     return MIToken::lparen;
     614             :   case ')':
     615             :     return MIToken::rparen;
     616             :   case '{':
     617             :     return MIToken::lbrace;
     618             :   case '}':
     619             :     return MIToken::rbrace;
     620             :   case '+':
     621             :     return MIToken::plus;
     622             :   case '-':
     623             :     return MIToken::minus;
     624             :   case '<':
     625             :     return MIToken::less;
     626             :   case '>':
     627             :     return MIToken::greater;
     628             :   default:
     629             :     return MIToken::Error;
     630             :   }
     631             : }
     632             : 
     633      458420 : static Cursor maybeLexSymbol(Cursor C, MIToken &Token) {
     634             :   MIToken::TokenKind Kind;
     635             :   unsigned Length = 1;
     636      500028 :   if (C.peek() == ':' && C.peek(1) == ':') {
     637             :     Kind = MIToken::coloncolon;
     638             :     Length = 2;
     639             :   } else
     640             :     Kind = symbolToken(C.peek());
     641      453593 :   if (Kind == MIToken::Error)
     642      176612 :     return None;
     643             :   auto Range = C;
     644             :   C.advance(Length);
     645      281808 :   Token.reset(Kind, Range.upto(C));
     646      281808 :   return C;
     647             : }
     648             : 
     649      176612 : static Cursor maybeLexNewline(Cursor C, MIToken &Token) {
     650      176612 :   if (!isNewlineChar(C.peek()))
     651        1213 :     return None;
     652             :   auto Range = C;
     653             :   C.advance();
     654      175399 :   Token.reset(MIToken::Newline, Range.upto(C));
     655      175399 :   return C;
     656             : }
     657             : 
     658        1213 : static Cursor maybeLexEscapedIRValue(Cursor C, MIToken &Token,
     659             :                                      ErrorCallbackType ErrorCallback) {
     660        1213 :   if (C.peek() != '`')
     661         219 :     return None;
     662             :   auto Range = C;
     663             :   C.advance();
     664             :   auto StrRange = C;
     665       25868 :   while (C.peek() != '`') {
     666       49748 :     if (C.isEOF() || isNewlineChar(C.peek())) {
     667           0 :       ErrorCallback(
     668             :           C.location(),
     669             :           "end of machine instruction reached before the closing '`'");
     670           0 :       Token.reset(MIToken::Error, Range.remaining());
     671           0 :       return C;
     672             :     }
     673             :     C.advance();
     674             :   }
     675         994 :   StringRef Value = StrRange.upto(C);
     676             :   C.advance();
     677         994 :   Token.reset(MIToken::QuotedIRValue, Range.upto(C)).setStringValue(Value);
     678         994 :   return C;
     679             : }
     680             : 
     681      922786 : StringRef llvm::lexMIToken(StringRef Source, MIToken &Token,
     682             :                            ErrorCallbackType ErrorCallback) {
     683      922786 :   auto C = skipComment(skipWhitespace(Cursor(Source)));
     684      922786 :   if (C.isEOF()) {
     685       12877 :     Token.reset(MIToken::Eof, C.remaining());
     686             :     return C.remaining();
     687             :   }
     688             : 
     689      909909 :   if (Cursor R = maybeLexMachineBasicBlock(C, Token, ErrorCallback))
     690       19427 :     return R.remaining();
     691      890482 :   if (Cursor R = maybeLexIdentifier(C, Token))
     692      194916 :     return R.remaining();
     693      695566 :   if (Cursor R = maybeLexJumpTableIndex(C, Token))
     694             :     return R.remaining();
     695      695537 :   if (Cursor R = maybeLexStackObject(C, Token))
     696             :     return R.remaining();
     697      694662 :   if (Cursor R = maybeLexFixedStackObject(C, Token))
     698             :     return R.remaining();
     699      694348 :   if (Cursor R = maybeLexConstantPoolItem(C, Token))
     700             :     return R.remaining();
     701      694258 :   if (Cursor R = maybeLexSubRegisterIndex(C, Token, ErrorCallback))
     702         278 :     return R.remaining();
     703      693980 :   if (Cursor R = maybeLexIRBlock(C, Token, ErrorCallback))
     704        2237 :     return R.remaining();
     705      691743 :   if (Cursor R = maybeLexIRValue(C, Token, ErrorCallback))
     706        2077 :     return R.remaining();
     707      689666 :   if (Cursor R = maybeLexRegister(C, Token, ErrorCallback))
     708      175361 :     return R.remaining();
     709      514305 :   if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback))
     710        2101 :     return R.remaining();
     711      512204 :   if (Cursor R = maybeLexExternalSymbol(C, Token, ErrorCallback))
     712         466 :     return R.remaining();
     713      511738 :   if (Cursor R = maybeLexMCSymbol(C, Token, ErrorCallback))
     714          32 :     return R.remaining();
     715      511706 :   if (Cursor R = maybeLexHexadecimalLiteral(C, Token))
     716        2192 :     return R.remaining();
     717      509514 :   if (Cursor R = maybeLexNumericalLiteral(C, Token))
     718       48268 :     return R.remaining();
     719      461246 :   if (Cursor R = maybeLexExlaim(C, Token, ErrorCallback))
     720        2826 :     return R.remaining();
     721      458420 :   if (Cursor R = maybeLexSymbol(C, Token))
     722      281808 :     return R.remaining();
     723      176612 :   if (Cursor R = maybeLexNewline(C, Token))
     724      175399 :     return R.remaining();
     725        1213 :   if (Cursor R = maybeLexEscapedIRValue(C, Token, ErrorCallback))
     726         994 :     return R.remaining();
     727         219 :   if (Cursor R = maybeLexStringConstant(C, Token, ErrorCallback))
     728         218 :     return R.remaining();
     729             : 
     730           1 :   Token.reset(MIToken::Error, C.remaining());
     731           1 :   ErrorCallback(C.location(),
     732           1 :                 Twine("unexpected character '") + Twine(C.peek()) + "'");
     733             :   return C.remaining();
     734             : }

Generated by: LCOV version 1.13