109467b48Spatrick //===- MILexer.cpp - Machine instructions lexer implementation ------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file implements the lexing of machine instructions.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick 
1309467b48Spatrick #include "MILexer.h"
1409467b48Spatrick #include "llvm/ADT/StringExtras.h"
1509467b48Spatrick #include "llvm/ADT/StringSwitch.h"
1609467b48Spatrick #include "llvm/ADT/Twine.h"
1709467b48Spatrick #include <cassert>
1809467b48Spatrick #include <cctype>
1909467b48Spatrick #include <string>
2009467b48Spatrick 
2109467b48Spatrick using namespace llvm;
2209467b48Spatrick 
2309467b48Spatrick namespace {
2409467b48Spatrick 
2509467b48Spatrick using ErrorCallbackType =
2609467b48Spatrick     function_ref<void(StringRef::iterator Loc, const Twine &)>;
2709467b48Spatrick 
2809467b48Spatrick /// This class provides a way to iterate and get characters from the source
2909467b48Spatrick /// string.
3009467b48Spatrick class Cursor {
3109467b48Spatrick   const char *Ptr = nullptr;
3209467b48Spatrick   const char *End = nullptr;
3309467b48Spatrick 
3409467b48Spatrick public:
Cursor(std::nullopt_t)35*d415bd75Srobert   Cursor(std::nullopt_t) {}
3609467b48Spatrick 
Cursor(StringRef Str)3709467b48Spatrick   explicit Cursor(StringRef Str) {
3809467b48Spatrick     Ptr = Str.data();
3909467b48Spatrick     End = Ptr + Str.size();
4009467b48Spatrick   }
4109467b48Spatrick 
isEOF() const4209467b48Spatrick   bool isEOF() const { return Ptr == End; }
4309467b48Spatrick 
peek(int I=0) const4409467b48Spatrick   char peek(int I = 0) const { return End - Ptr <= I ? 0 : Ptr[I]; }
4509467b48Spatrick 
advance(unsigned I=1)4609467b48Spatrick   void advance(unsigned I = 1) { Ptr += I; }
4709467b48Spatrick 
remaining() const4809467b48Spatrick   StringRef remaining() const { return StringRef(Ptr, End - Ptr); }
4909467b48Spatrick 
upto(Cursor C) const5009467b48Spatrick   StringRef upto(Cursor C) const {
5109467b48Spatrick     assert(C.Ptr >= Ptr && C.Ptr <= End);
5209467b48Spatrick     return StringRef(Ptr, C.Ptr - Ptr);
5309467b48Spatrick   }
5409467b48Spatrick 
location() const5509467b48Spatrick   StringRef::iterator location() const { return Ptr; }
5609467b48Spatrick 
operator bool() const5709467b48Spatrick   operator bool() const { return Ptr != nullptr; }
5809467b48Spatrick };
5909467b48Spatrick 
6009467b48Spatrick } // end anonymous namespace
6109467b48Spatrick 
reset(TokenKind Kind,StringRef Range)6209467b48Spatrick MIToken &MIToken::reset(TokenKind Kind, StringRef Range) {
6309467b48Spatrick   this->Kind = Kind;
6409467b48Spatrick   this->Range = Range;
6509467b48Spatrick   return *this;
6609467b48Spatrick }
6709467b48Spatrick 
setStringValue(StringRef StrVal)6809467b48Spatrick MIToken &MIToken::setStringValue(StringRef StrVal) {
6909467b48Spatrick   StringValue = StrVal;
7009467b48Spatrick   return *this;
7109467b48Spatrick }
7209467b48Spatrick 
setOwnedStringValue(std::string StrVal)7309467b48Spatrick MIToken &MIToken::setOwnedStringValue(std::string StrVal) {
7409467b48Spatrick   StringValueStorage = std::move(StrVal);
7509467b48Spatrick   StringValue = StringValueStorage;
7609467b48Spatrick   return *this;
7709467b48Spatrick }
7809467b48Spatrick 
setIntegerValue(APSInt IntVal)7909467b48Spatrick MIToken &MIToken::setIntegerValue(APSInt IntVal) {
8009467b48Spatrick   this->IntVal = std::move(IntVal);
8109467b48Spatrick   return *this;
8209467b48Spatrick }
8309467b48Spatrick 
8409467b48Spatrick /// Skip the leading whitespace characters and return the updated cursor.
skipWhitespace(Cursor C)8509467b48Spatrick static Cursor skipWhitespace(Cursor C) {
8609467b48Spatrick   while (isblank(C.peek()))
8709467b48Spatrick     C.advance();
8809467b48Spatrick   return C;
8909467b48Spatrick }
9009467b48Spatrick 
isNewlineChar(char C)9109467b48Spatrick static bool isNewlineChar(char C) { return C == '\n' || C == '\r'; }
9209467b48Spatrick 
9309467b48Spatrick /// Skip a line comment and return the updated cursor.
skipComment(Cursor C)9409467b48Spatrick static Cursor skipComment(Cursor C) {
9509467b48Spatrick   if (C.peek() != ';')
9609467b48Spatrick     return C;
9709467b48Spatrick   while (!isNewlineChar(C.peek()) && !C.isEOF())
9809467b48Spatrick     C.advance();
9909467b48Spatrick   return C;
10009467b48Spatrick }
10109467b48Spatrick 
102097a140dSpatrick /// Machine operands can have comments, enclosed between /* and */.
103097a140dSpatrick /// This eats up all tokens, including /* and */.
skipMachineOperandComment(Cursor C)104097a140dSpatrick static Cursor skipMachineOperandComment(Cursor C) {
105097a140dSpatrick   if (C.peek() != '/' || C.peek(1) != '*')
106097a140dSpatrick     return C;
107097a140dSpatrick 
108097a140dSpatrick   while (C.peek() != '*' || C.peek(1) != '/')
109097a140dSpatrick     C.advance();
110097a140dSpatrick 
111097a140dSpatrick   C.advance();
112097a140dSpatrick   C.advance();
113097a140dSpatrick   return C;
114097a140dSpatrick }
115097a140dSpatrick 
11609467b48Spatrick /// Return true if the given character satisfies the following regular
11709467b48Spatrick /// expression: [-a-zA-Z$._0-9]
isIdentifierChar(char C)11809467b48Spatrick static bool isIdentifierChar(char C) {
11909467b48Spatrick   return isalpha(C) || isdigit(C) || C == '_' || C == '-' || C == '.' ||
12009467b48Spatrick          C == '$';
12109467b48Spatrick }
12209467b48Spatrick 
12309467b48Spatrick /// Unescapes the given string value.
12409467b48Spatrick ///
12509467b48Spatrick /// Expects the string value to be quoted.
unescapeQuotedString(StringRef Value)12609467b48Spatrick static std::string unescapeQuotedString(StringRef Value) {
12709467b48Spatrick   assert(Value.front() == '"' && Value.back() == '"');
12809467b48Spatrick   Cursor C = Cursor(Value.substr(1, Value.size() - 2));
12909467b48Spatrick 
13009467b48Spatrick   std::string Str;
13109467b48Spatrick   Str.reserve(C.remaining().size());
13209467b48Spatrick   while (!C.isEOF()) {
13309467b48Spatrick     char Char = C.peek();
13409467b48Spatrick     if (Char == '\\') {
13509467b48Spatrick       if (C.peek(1) == '\\') {
13609467b48Spatrick         // Two '\' become one
13709467b48Spatrick         Str += '\\';
13809467b48Spatrick         C.advance(2);
13909467b48Spatrick         continue;
14009467b48Spatrick       }
14109467b48Spatrick       if (isxdigit(C.peek(1)) && isxdigit(C.peek(2))) {
14209467b48Spatrick         Str += hexDigitValue(C.peek(1)) * 16 + hexDigitValue(C.peek(2));
14309467b48Spatrick         C.advance(3);
14409467b48Spatrick         continue;
14509467b48Spatrick       }
14609467b48Spatrick     }
14709467b48Spatrick     Str += Char;
14809467b48Spatrick     C.advance();
14909467b48Spatrick   }
15009467b48Spatrick   return Str;
15109467b48Spatrick }
15209467b48Spatrick 
15309467b48Spatrick /// Lex a string constant using the following regular expression: \"[^\"]*\"
lexStringConstant(Cursor C,ErrorCallbackType ErrorCallback)15409467b48Spatrick static Cursor lexStringConstant(Cursor C, ErrorCallbackType ErrorCallback) {
15509467b48Spatrick   assert(C.peek() == '"');
15609467b48Spatrick   for (C.advance(); C.peek() != '"'; C.advance()) {
15709467b48Spatrick     if (C.isEOF() || isNewlineChar(C.peek())) {
15809467b48Spatrick       ErrorCallback(
15909467b48Spatrick           C.location(),
16009467b48Spatrick           "end of machine instruction reached before the closing '\"'");
161*d415bd75Srobert       return std::nullopt;
16209467b48Spatrick     }
16309467b48Spatrick   }
16409467b48Spatrick   C.advance();
16509467b48Spatrick   return C;
16609467b48Spatrick }
16709467b48Spatrick 
lexName(Cursor C,MIToken & Token,MIToken::TokenKind Type,unsigned PrefixLength,ErrorCallbackType ErrorCallback)16809467b48Spatrick static Cursor lexName(Cursor C, MIToken &Token, MIToken::TokenKind Type,
16909467b48Spatrick                       unsigned PrefixLength, ErrorCallbackType ErrorCallback) {
17009467b48Spatrick   auto Range = C;
17109467b48Spatrick   C.advance(PrefixLength);
17209467b48Spatrick   if (C.peek() == '"') {
17309467b48Spatrick     if (Cursor R = lexStringConstant(C, ErrorCallback)) {
17409467b48Spatrick       StringRef String = Range.upto(R);
17509467b48Spatrick       Token.reset(Type, String)
17609467b48Spatrick           .setOwnedStringValue(
17709467b48Spatrick               unescapeQuotedString(String.drop_front(PrefixLength)));
17809467b48Spatrick       return R;
17909467b48Spatrick     }
18009467b48Spatrick     Token.reset(MIToken::Error, Range.remaining());
18109467b48Spatrick     return Range;
18209467b48Spatrick   }
18309467b48Spatrick   while (isIdentifierChar(C.peek()))
18409467b48Spatrick     C.advance();
18509467b48Spatrick   Token.reset(Type, Range.upto(C))
18609467b48Spatrick       .setStringValue(Range.upto(C).drop_front(PrefixLength));
18709467b48Spatrick   return C;
18809467b48Spatrick }
18909467b48Spatrick 
getIdentifierKind(StringRef Identifier)19009467b48Spatrick static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
19109467b48Spatrick   return StringSwitch<MIToken::TokenKind>(Identifier)
19209467b48Spatrick       .Case("_", MIToken::underscore)
19309467b48Spatrick       .Case("implicit", MIToken::kw_implicit)
19409467b48Spatrick       .Case("implicit-def", MIToken::kw_implicit_define)
19509467b48Spatrick       .Case("def", MIToken::kw_def)
19609467b48Spatrick       .Case("dead", MIToken::kw_dead)
19709467b48Spatrick       .Case("killed", MIToken::kw_killed)
19809467b48Spatrick       .Case("undef", MIToken::kw_undef)
19909467b48Spatrick       .Case("internal", MIToken::kw_internal)
20009467b48Spatrick       .Case("early-clobber", MIToken::kw_early_clobber)
20109467b48Spatrick       .Case("debug-use", MIToken::kw_debug_use)
20209467b48Spatrick       .Case("renamable", MIToken::kw_renamable)
20309467b48Spatrick       .Case("tied-def", MIToken::kw_tied_def)
20409467b48Spatrick       .Case("frame-setup", MIToken::kw_frame_setup)
20509467b48Spatrick       .Case("frame-destroy", MIToken::kw_frame_destroy)
20609467b48Spatrick       .Case("nnan", MIToken::kw_nnan)
20709467b48Spatrick       .Case("ninf", MIToken::kw_ninf)
20809467b48Spatrick       .Case("nsz", MIToken::kw_nsz)
20909467b48Spatrick       .Case("arcp", MIToken::kw_arcp)
21009467b48Spatrick       .Case("contract", MIToken::kw_contract)
21109467b48Spatrick       .Case("afn", MIToken::kw_afn)
21209467b48Spatrick       .Case("reassoc", MIToken::kw_reassoc)
21309467b48Spatrick       .Case("nuw", MIToken::kw_nuw)
21409467b48Spatrick       .Case("nsw", MIToken::kw_nsw)
21509467b48Spatrick       .Case("exact", MIToken::kw_exact)
21609467b48Spatrick       .Case("nofpexcept", MIToken::kw_nofpexcept)
21709467b48Spatrick       .Case("debug-location", MIToken::kw_debug_location)
21873471bf0Spatrick       .Case("debug-instr-number", MIToken::kw_debug_instr_number)
219*d415bd75Srobert       .Case("dbg-instr-ref", MIToken::kw_dbg_instr_ref)
22009467b48Spatrick       .Case("same_value", MIToken::kw_cfi_same_value)
22109467b48Spatrick       .Case("offset", MIToken::kw_cfi_offset)
22209467b48Spatrick       .Case("rel_offset", MIToken::kw_cfi_rel_offset)
22309467b48Spatrick       .Case("def_cfa_register", MIToken::kw_cfi_def_cfa_register)
22409467b48Spatrick       .Case("def_cfa_offset", MIToken::kw_cfi_def_cfa_offset)
22509467b48Spatrick       .Case("adjust_cfa_offset", MIToken::kw_cfi_adjust_cfa_offset)
22609467b48Spatrick       .Case("escape", MIToken::kw_cfi_escape)
22709467b48Spatrick       .Case("def_cfa", MIToken::kw_cfi_def_cfa)
22873471bf0Spatrick       .Case("llvm_def_aspace_cfa", MIToken::kw_cfi_llvm_def_aspace_cfa)
22909467b48Spatrick       .Case("remember_state", MIToken::kw_cfi_remember_state)
23009467b48Spatrick       .Case("restore", MIToken::kw_cfi_restore)
23109467b48Spatrick       .Case("restore_state", MIToken::kw_cfi_restore_state)
23209467b48Spatrick       .Case("undefined", MIToken::kw_cfi_undefined)
23309467b48Spatrick       .Case("register", MIToken::kw_cfi_register)
23409467b48Spatrick       .Case("window_save", MIToken::kw_cfi_window_save)
23573471bf0Spatrick       .Case("negate_ra_sign_state",
23673471bf0Spatrick             MIToken::kw_cfi_aarch64_negate_ra_sign_state)
23709467b48Spatrick       .Case("blockaddress", MIToken::kw_blockaddress)
23809467b48Spatrick       .Case("intrinsic", MIToken::kw_intrinsic)
23909467b48Spatrick       .Case("target-index", MIToken::kw_target_index)
24009467b48Spatrick       .Case("half", MIToken::kw_half)
24109467b48Spatrick       .Case("float", MIToken::kw_float)
24209467b48Spatrick       .Case("double", MIToken::kw_double)
24309467b48Spatrick       .Case("x86_fp80", MIToken::kw_x86_fp80)
24409467b48Spatrick       .Case("fp128", MIToken::kw_fp128)
24509467b48Spatrick       .Case("ppc_fp128", MIToken::kw_ppc_fp128)
24609467b48Spatrick       .Case("target-flags", MIToken::kw_target_flags)
24709467b48Spatrick       .Case("volatile", MIToken::kw_volatile)
24809467b48Spatrick       .Case("non-temporal", MIToken::kw_non_temporal)
24909467b48Spatrick       .Case("dereferenceable", MIToken::kw_dereferenceable)
25009467b48Spatrick       .Case("invariant", MIToken::kw_invariant)
25109467b48Spatrick       .Case("align", MIToken::kw_align)
252*d415bd75Srobert       .Case("basealign", MIToken::kw_basealign)
25309467b48Spatrick       .Case("addrspace", MIToken::kw_addrspace)
25409467b48Spatrick       .Case("stack", MIToken::kw_stack)
25509467b48Spatrick       .Case("got", MIToken::kw_got)
25609467b48Spatrick       .Case("jump-table", MIToken::kw_jump_table)
25709467b48Spatrick       .Case("constant-pool", MIToken::kw_constant_pool)
25809467b48Spatrick       .Case("call-entry", MIToken::kw_call_entry)
25909467b48Spatrick       .Case("custom", MIToken::kw_custom)
26009467b48Spatrick       .Case("liveout", MIToken::kw_liveout)
26109467b48Spatrick       .Case("landing-pad", MIToken::kw_landing_pad)
262*d415bd75Srobert       .Case("inlineasm-br-indirect-target",
263*d415bd75Srobert             MIToken::kw_inlineasm_br_indirect_target)
264097a140dSpatrick       .Case("ehfunclet-entry", MIToken::kw_ehfunclet_entry)
26509467b48Spatrick       .Case("liveins", MIToken::kw_liveins)
26609467b48Spatrick       .Case("successors", MIToken::kw_successors)
26709467b48Spatrick       .Case("floatpred", MIToken::kw_floatpred)
26809467b48Spatrick       .Case("intpred", MIToken::kw_intpred)
26909467b48Spatrick       .Case("shufflemask", MIToken::kw_shufflemask)
27009467b48Spatrick       .Case("pre-instr-symbol", MIToken::kw_pre_instr_symbol)
27109467b48Spatrick       .Case("post-instr-symbol", MIToken::kw_post_instr_symbol)
27209467b48Spatrick       .Case("heap-alloc-marker", MIToken::kw_heap_alloc_marker)
273*d415bd75Srobert       .Case("pcsections", MIToken::kw_pcsections)
274*d415bd75Srobert       .Case("cfi-type", MIToken::kw_cfi_type)
275097a140dSpatrick       .Case("bbsections", MIToken::kw_bbsections)
276*d415bd75Srobert       .Case("bb_id", MIToken::kw_bb_id)
27709467b48Spatrick       .Case("unknown-size", MIToken::kw_unknown_size)
27873471bf0Spatrick       .Case("unknown-address", MIToken::kw_unknown_address)
27973471bf0Spatrick       .Case("distinct", MIToken::kw_distinct)
280*d415bd75Srobert       .Case("ir-block-address-taken", MIToken::kw_ir_block_address_taken)
281*d415bd75Srobert       .Case("machine-block-address-taken",
282*d415bd75Srobert             MIToken::kw_machine_block_address_taken)
28309467b48Spatrick       .Default(MIToken::Identifier);
28409467b48Spatrick }
28509467b48Spatrick 
maybeLexIdentifier(Cursor C,MIToken & Token)28609467b48Spatrick static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) {
28709467b48Spatrick   if (!isalpha(C.peek()) && C.peek() != '_')
288*d415bd75Srobert     return std::nullopt;
28909467b48Spatrick   auto Range = C;
29009467b48Spatrick   while (isIdentifierChar(C.peek()))
29109467b48Spatrick     C.advance();
29209467b48Spatrick   auto Identifier = Range.upto(C);
29309467b48Spatrick   Token.reset(getIdentifierKind(Identifier), Identifier)
29409467b48Spatrick       .setStringValue(Identifier);
29509467b48Spatrick   return C;
29609467b48Spatrick }
29709467b48Spatrick 
maybeLexMachineBasicBlock(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)29809467b48Spatrick static Cursor maybeLexMachineBasicBlock(Cursor C, MIToken &Token,
29909467b48Spatrick                                         ErrorCallbackType ErrorCallback) {
30009467b48Spatrick   bool IsReference = C.remaining().startswith("%bb.");
30109467b48Spatrick   if (!IsReference && !C.remaining().startswith("bb."))
302*d415bd75Srobert     return std::nullopt;
30309467b48Spatrick   auto Range = C;
30409467b48Spatrick   unsigned PrefixLength = IsReference ? 4 : 3;
30509467b48Spatrick   C.advance(PrefixLength); // Skip '%bb.' or 'bb.'
30609467b48Spatrick   if (!isdigit(C.peek())) {
30709467b48Spatrick     Token.reset(MIToken::Error, C.remaining());
30809467b48Spatrick     ErrorCallback(C.location(), "expected a number after '%bb.'");
30909467b48Spatrick     return C;
31009467b48Spatrick   }
31109467b48Spatrick   auto NumberRange = C;
31209467b48Spatrick   while (isdigit(C.peek()))
31309467b48Spatrick     C.advance();
31409467b48Spatrick   StringRef Number = NumberRange.upto(C);
31509467b48Spatrick   unsigned StringOffset = PrefixLength + Number.size(); // Drop '%bb.<id>'
31609467b48Spatrick   // TODO: The format bb.<id>.<irname> is supported only when it's not a
31709467b48Spatrick   // reference. Once we deprecate the format where the irname shows up, we
31809467b48Spatrick   // should only lex forward if it is a reference.
31909467b48Spatrick   if (C.peek() == '.') {
32009467b48Spatrick     C.advance(); // Skip '.'
32109467b48Spatrick     ++StringOffset;
32209467b48Spatrick     while (isIdentifierChar(C.peek()))
32309467b48Spatrick       C.advance();
32409467b48Spatrick   }
32509467b48Spatrick   Token.reset(IsReference ? MIToken::MachineBasicBlock
32609467b48Spatrick                           : MIToken::MachineBasicBlockLabel,
32709467b48Spatrick               Range.upto(C))
32809467b48Spatrick       .setIntegerValue(APSInt(Number))
32909467b48Spatrick       .setStringValue(Range.upto(C).drop_front(StringOffset));
33009467b48Spatrick   return C;
33109467b48Spatrick }
33209467b48Spatrick 
maybeLexIndex(Cursor C,MIToken & Token,StringRef Rule,MIToken::TokenKind Kind)33309467b48Spatrick static Cursor maybeLexIndex(Cursor C, MIToken &Token, StringRef Rule,
33409467b48Spatrick                             MIToken::TokenKind Kind) {
33509467b48Spatrick   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
336*d415bd75Srobert     return std::nullopt;
33709467b48Spatrick   auto Range = C;
33809467b48Spatrick   C.advance(Rule.size());
33909467b48Spatrick   auto NumberRange = C;
34009467b48Spatrick   while (isdigit(C.peek()))
34109467b48Spatrick     C.advance();
34209467b48Spatrick   Token.reset(Kind, Range.upto(C)).setIntegerValue(APSInt(NumberRange.upto(C)));
34309467b48Spatrick   return C;
34409467b48Spatrick }
34509467b48Spatrick 
maybeLexIndexAndName(Cursor C,MIToken & Token,StringRef Rule,MIToken::TokenKind Kind)34609467b48Spatrick static Cursor maybeLexIndexAndName(Cursor C, MIToken &Token, StringRef Rule,
34709467b48Spatrick                                    MIToken::TokenKind Kind) {
34809467b48Spatrick   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
349*d415bd75Srobert     return std::nullopt;
35009467b48Spatrick   auto Range = C;
35109467b48Spatrick   C.advance(Rule.size());
35209467b48Spatrick   auto NumberRange = C;
35309467b48Spatrick   while (isdigit(C.peek()))
35409467b48Spatrick     C.advance();
35509467b48Spatrick   StringRef Number = NumberRange.upto(C);
35609467b48Spatrick   unsigned StringOffset = Rule.size() + Number.size();
35709467b48Spatrick   if (C.peek() == '.') {
35809467b48Spatrick     C.advance();
35909467b48Spatrick     ++StringOffset;
36009467b48Spatrick     while (isIdentifierChar(C.peek()))
36109467b48Spatrick       C.advance();
36209467b48Spatrick   }
36309467b48Spatrick   Token.reset(Kind, Range.upto(C))
36409467b48Spatrick       .setIntegerValue(APSInt(Number))
36509467b48Spatrick       .setStringValue(Range.upto(C).drop_front(StringOffset));
36609467b48Spatrick   return C;
36709467b48Spatrick }
36809467b48Spatrick 
maybeLexJumpTableIndex(Cursor C,MIToken & Token)36909467b48Spatrick static Cursor maybeLexJumpTableIndex(Cursor C, MIToken &Token) {
37009467b48Spatrick   return maybeLexIndex(C, Token, "%jump-table.", MIToken::JumpTableIndex);
37109467b48Spatrick }
37209467b48Spatrick 
maybeLexStackObject(Cursor C,MIToken & Token)37309467b48Spatrick static Cursor maybeLexStackObject(Cursor C, MIToken &Token) {
37409467b48Spatrick   return maybeLexIndexAndName(C, Token, "%stack.", MIToken::StackObject);
37509467b48Spatrick }
37609467b48Spatrick 
maybeLexFixedStackObject(Cursor C,MIToken & Token)37709467b48Spatrick static Cursor maybeLexFixedStackObject(Cursor C, MIToken &Token) {
37809467b48Spatrick   return maybeLexIndex(C, Token, "%fixed-stack.", MIToken::FixedStackObject);
37909467b48Spatrick }
38009467b48Spatrick 
maybeLexConstantPoolItem(Cursor C,MIToken & Token)38109467b48Spatrick static Cursor maybeLexConstantPoolItem(Cursor C, MIToken &Token) {
38209467b48Spatrick   return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem);
38309467b48Spatrick }
38409467b48Spatrick 
maybeLexSubRegisterIndex(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)38509467b48Spatrick static Cursor maybeLexSubRegisterIndex(Cursor C, MIToken &Token,
38609467b48Spatrick                                        ErrorCallbackType ErrorCallback) {
38709467b48Spatrick   const StringRef Rule = "%subreg.";
38809467b48Spatrick   if (!C.remaining().startswith(Rule))
389*d415bd75Srobert     return std::nullopt;
39009467b48Spatrick   return lexName(C, Token, MIToken::SubRegisterIndex, Rule.size(),
39109467b48Spatrick                  ErrorCallback);
39209467b48Spatrick }
39309467b48Spatrick 
maybeLexIRBlock(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)39409467b48Spatrick static Cursor maybeLexIRBlock(Cursor C, MIToken &Token,
39509467b48Spatrick                               ErrorCallbackType ErrorCallback) {
39609467b48Spatrick   const StringRef Rule = "%ir-block.";
39709467b48Spatrick   if (!C.remaining().startswith(Rule))
398*d415bd75Srobert     return std::nullopt;
39909467b48Spatrick   if (isdigit(C.peek(Rule.size())))
40009467b48Spatrick     return maybeLexIndex(C, Token, Rule, MIToken::IRBlock);
40109467b48Spatrick   return lexName(C, Token, MIToken::NamedIRBlock, Rule.size(), ErrorCallback);
40209467b48Spatrick }
40309467b48Spatrick 
maybeLexIRValue(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)40409467b48Spatrick static Cursor maybeLexIRValue(Cursor C, MIToken &Token,
40509467b48Spatrick                               ErrorCallbackType ErrorCallback) {
40609467b48Spatrick   const StringRef Rule = "%ir.";
40709467b48Spatrick   if (!C.remaining().startswith(Rule))
408*d415bd75Srobert     return std::nullopt;
40909467b48Spatrick   if (isdigit(C.peek(Rule.size())))
41009467b48Spatrick     return maybeLexIndex(C, Token, Rule, MIToken::IRValue);
41109467b48Spatrick   return lexName(C, Token, MIToken::NamedIRValue, Rule.size(), ErrorCallback);
41209467b48Spatrick }
41309467b48Spatrick 
maybeLexStringConstant(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)41409467b48Spatrick static Cursor maybeLexStringConstant(Cursor C, MIToken &Token,
41509467b48Spatrick                                      ErrorCallbackType ErrorCallback) {
41609467b48Spatrick   if (C.peek() != '"')
417*d415bd75Srobert     return std::nullopt;
41809467b48Spatrick   return lexName(C, Token, MIToken::StringConstant, /*PrefixLength=*/0,
41909467b48Spatrick                  ErrorCallback);
42009467b48Spatrick }
42109467b48Spatrick 
lexVirtualRegister(Cursor C,MIToken & Token)42209467b48Spatrick static Cursor lexVirtualRegister(Cursor C, MIToken &Token) {
42309467b48Spatrick   auto Range = C;
42409467b48Spatrick   C.advance(); // Skip '%'
42509467b48Spatrick   auto NumberRange = C;
42609467b48Spatrick   while (isdigit(C.peek()))
42709467b48Spatrick     C.advance();
42809467b48Spatrick   Token.reset(MIToken::VirtualRegister, Range.upto(C))
42909467b48Spatrick       .setIntegerValue(APSInt(NumberRange.upto(C)));
43009467b48Spatrick   return C;
43109467b48Spatrick }
43209467b48Spatrick 
43309467b48Spatrick /// Returns true for a character allowed in a register name.
isRegisterChar(char C)43409467b48Spatrick static bool isRegisterChar(char C) {
43509467b48Spatrick   return isIdentifierChar(C) && C != '.';
43609467b48Spatrick }
43709467b48Spatrick 
lexNamedVirtualRegister(Cursor C,MIToken & Token)43809467b48Spatrick static Cursor lexNamedVirtualRegister(Cursor C, MIToken &Token) {
43909467b48Spatrick   Cursor Range = C;
44009467b48Spatrick   C.advance(); // Skip '%'
44109467b48Spatrick   while (isRegisterChar(C.peek()))
44209467b48Spatrick     C.advance();
44309467b48Spatrick   Token.reset(MIToken::NamedVirtualRegister, Range.upto(C))
44409467b48Spatrick       .setStringValue(Range.upto(C).drop_front(1)); // Drop the '%'
44509467b48Spatrick   return C;
44609467b48Spatrick }
44709467b48Spatrick 
maybeLexRegister(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)44809467b48Spatrick static Cursor maybeLexRegister(Cursor C, MIToken &Token,
44909467b48Spatrick                                ErrorCallbackType ErrorCallback) {
45009467b48Spatrick   if (C.peek() != '%' && C.peek() != '$')
451*d415bd75Srobert     return std::nullopt;
45209467b48Spatrick 
45309467b48Spatrick   if (C.peek() == '%') {
45409467b48Spatrick     if (isdigit(C.peek(1)))
45509467b48Spatrick       return lexVirtualRegister(C, Token);
45609467b48Spatrick 
45709467b48Spatrick     if (isRegisterChar(C.peek(1)))
45809467b48Spatrick       return lexNamedVirtualRegister(C, Token);
45909467b48Spatrick 
460*d415bd75Srobert     return std::nullopt;
46109467b48Spatrick   }
46209467b48Spatrick 
46309467b48Spatrick   assert(C.peek() == '$');
46409467b48Spatrick   auto Range = C;
46509467b48Spatrick   C.advance(); // Skip '$'
46609467b48Spatrick   while (isRegisterChar(C.peek()))
46709467b48Spatrick     C.advance();
46809467b48Spatrick   Token.reset(MIToken::NamedRegister, Range.upto(C))
46909467b48Spatrick       .setStringValue(Range.upto(C).drop_front(1)); // Drop the '$'
47009467b48Spatrick   return C;
47109467b48Spatrick }
47209467b48Spatrick 
maybeLexGlobalValue(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)47309467b48Spatrick static Cursor maybeLexGlobalValue(Cursor C, MIToken &Token,
47409467b48Spatrick                                   ErrorCallbackType ErrorCallback) {
47509467b48Spatrick   if (C.peek() != '@')
476*d415bd75Srobert     return std::nullopt;
47709467b48Spatrick   if (!isdigit(C.peek(1)))
47809467b48Spatrick     return lexName(C, Token, MIToken::NamedGlobalValue, /*PrefixLength=*/1,
47909467b48Spatrick                    ErrorCallback);
48009467b48Spatrick   auto Range = C;
48109467b48Spatrick   C.advance(1); // Skip the '@'
48209467b48Spatrick   auto NumberRange = C;
48309467b48Spatrick   while (isdigit(C.peek()))
48409467b48Spatrick     C.advance();
48509467b48Spatrick   Token.reset(MIToken::GlobalValue, Range.upto(C))
48609467b48Spatrick       .setIntegerValue(APSInt(NumberRange.upto(C)));
48709467b48Spatrick   return C;
48809467b48Spatrick }
48909467b48Spatrick 
maybeLexExternalSymbol(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)49009467b48Spatrick static Cursor maybeLexExternalSymbol(Cursor C, MIToken &Token,
49109467b48Spatrick                                      ErrorCallbackType ErrorCallback) {
49209467b48Spatrick   if (C.peek() != '&')
493*d415bd75Srobert     return std::nullopt;
49409467b48Spatrick   return lexName(C, Token, MIToken::ExternalSymbol, /*PrefixLength=*/1,
49509467b48Spatrick                  ErrorCallback);
49609467b48Spatrick }
49709467b48Spatrick 
maybeLexMCSymbol(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)49809467b48Spatrick static Cursor maybeLexMCSymbol(Cursor C, MIToken &Token,
49909467b48Spatrick                                ErrorCallbackType ErrorCallback) {
50009467b48Spatrick   const StringRef Rule = "<mcsymbol ";
50109467b48Spatrick   if (!C.remaining().startswith(Rule))
502*d415bd75Srobert     return std::nullopt;
50309467b48Spatrick   auto Start = C;
50409467b48Spatrick   C.advance(Rule.size());
50509467b48Spatrick 
50609467b48Spatrick   // Try a simple unquoted name.
50709467b48Spatrick   if (C.peek() != '"') {
50809467b48Spatrick     while (isIdentifierChar(C.peek()))
50909467b48Spatrick       C.advance();
51009467b48Spatrick     StringRef String = Start.upto(C).drop_front(Rule.size());
51109467b48Spatrick     if (C.peek() != '>') {
51209467b48Spatrick       ErrorCallback(C.location(),
51309467b48Spatrick                     "expected the '<mcsymbol ...' to be closed by a '>'");
51409467b48Spatrick       Token.reset(MIToken::Error, Start.remaining());
51509467b48Spatrick       return Start;
51609467b48Spatrick     }
51709467b48Spatrick     C.advance();
51809467b48Spatrick 
51909467b48Spatrick     Token.reset(MIToken::MCSymbol, Start.upto(C)).setStringValue(String);
52009467b48Spatrick     return C;
52109467b48Spatrick   }
52209467b48Spatrick 
52309467b48Spatrick   // Otherwise lex out a quoted name.
52409467b48Spatrick   Cursor R = lexStringConstant(C, ErrorCallback);
52509467b48Spatrick   if (!R) {
52609467b48Spatrick     ErrorCallback(C.location(),
52709467b48Spatrick                   "unable to parse quoted string from opening quote");
52809467b48Spatrick     Token.reset(MIToken::Error, Start.remaining());
52909467b48Spatrick     return Start;
53009467b48Spatrick   }
53109467b48Spatrick   StringRef String = Start.upto(R).drop_front(Rule.size());
53209467b48Spatrick   if (R.peek() != '>') {
53309467b48Spatrick     ErrorCallback(R.location(),
53409467b48Spatrick                   "expected the '<mcsymbol ...' to be closed by a '>'");
53509467b48Spatrick     Token.reset(MIToken::Error, Start.remaining());
53609467b48Spatrick     return Start;
53709467b48Spatrick   }
53809467b48Spatrick   R.advance();
53909467b48Spatrick 
54009467b48Spatrick   Token.reset(MIToken::MCSymbol, Start.upto(R))
54109467b48Spatrick       .setOwnedStringValue(unescapeQuotedString(String));
54209467b48Spatrick   return R;
54309467b48Spatrick }
54409467b48Spatrick 
isValidHexFloatingPointPrefix(char C)54509467b48Spatrick static bool isValidHexFloatingPointPrefix(char C) {
546097a140dSpatrick   return C == 'H' || C == 'K' || C == 'L' || C == 'M' || C == 'R';
54709467b48Spatrick }
54809467b48Spatrick 
lexFloatingPointLiteral(Cursor Range,Cursor C,MIToken & Token)54909467b48Spatrick static Cursor lexFloatingPointLiteral(Cursor Range, Cursor C, MIToken &Token) {
55009467b48Spatrick   C.advance();
55109467b48Spatrick   // Skip over [0-9]*([eE][-+]?[0-9]+)?
55209467b48Spatrick   while (isdigit(C.peek()))
55309467b48Spatrick     C.advance();
55409467b48Spatrick   if ((C.peek() == 'e' || C.peek() == 'E') &&
55509467b48Spatrick       (isdigit(C.peek(1)) ||
55609467b48Spatrick        ((C.peek(1) == '-' || C.peek(1) == '+') && isdigit(C.peek(2))))) {
55709467b48Spatrick     C.advance(2);
55809467b48Spatrick     while (isdigit(C.peek()))
55909467b48Spatrick       C.advance();
56009467b48Spatrick   }
56109467b48Spatrick   Token.reset(MIToken::FloatingPointLiteral, Range.upto(C));
56209467b48Spatrick   return C;
56309467b48Spatrick }
56409467b48Spatrick 
maybeLexHexadecimalLiteral(Cursor C,MIToken & Token)56509467b48Spatrick static Cursor maybeLexHexadecimalLiteral(Cursor C, MIToken &Token) {
56609467b48Spatrick   if (C.peek() != '0' || (C.peek(1) != 'x' && C.peek(1) != 'X'))
567*d415bd75Srobert     return std::nullopt;
56809467b48Spatrick   Cursor Range = C;
56909467b48Spatrick   C.advance(2);
57009467b48Spatrick   unsigned PrefLen = 2;
57109467b48Spatrick   if (isValidHexFloatingPointPrefix(C.peek())) {
57209467b48Spatrick     C.advance();
57309467b48Spatrick     PrefLen++;
57409467b48Spatrick   }
57509467b48Spatrick   while (isxdigit(C.peek()))
57609467b48Spatrick     C.advance();
57709467b48Spatrick   StringRef StrVal = Range.upto(C);
57809467b48Spatrick   if (StrVal.size() <= PrefLen)
579*d415bd75Srobert     return std::nullopt;
58009467b48Spatrick   if (PrefLen == 2)
58109467b48Spatrick     Token.reset(MIToken::HexLiteral, Range.upto(C));
58209467b48Spatrick   else // It must be 3, which means that there was a floating-point prefix.
58309467b48Spatrick     Token.reset(MIToken::FloatingPointLiteral, Range.upto(C));
58409467b48Spatrick   return C;
58509467b48Spatrick }
58609467b48Spatrick 
maybeLexNumericalLiteral(Cursor C,MIToken & Token)58709467b48Spatrick static Cursor maybeLexNumericalLiteral(Cursor C, MIToken &Token) {
58809467b48Spatrick   if (!isdigit(C.peek()) && (C.peek() != '-' || !isdigit(C.peek(1))))
589*d415bd75Srobert     return std::nullopt;
59009467b48Spatrick   auto Range = C;
59109467b48Spatrick   C.advance();
59209467b48Spatrick   while (isdigit(C.peek()))
59309467b48Spatrick     C.advance();
59409467b48Spatrick   if (C.peek() == '.')
59509467b48Spatrick     return lexFloatingPointLiteral(Range, C, Token);
59609467b48Spatrick   StringRef StrVal = Range.upto(C);
59709467b48Spatrick   Token.reset(MIToken::IntegerLiteral, StrVal).setIntegerValue(APSInt(StrVal));
59809467b48Spatrick   return C;
59909467b48Spatrick }
60009467b48Spatrick 
getMetadataKeywordKind(StringRef Identifier)60109467b48Spatrick static MIToken::TokenKind getMetadataKeywordKind(StringRef Identifier) {
60209467b48Spatrick   return StringSwitch<MIToken::TokenKind>(Identifier)
60309467b48Spatrick       .Case("!tbaa", MIToken::md_tbaa)
60409467b48Spatrick       .Case("!alias.scope", MIToken::md_alias_scope)
60509467b48Spatrick       .Case("!noalias", MIToken::md_noalias)
60609467b48Spatrick       .Case("!range", MIToken::md_range)
60709467b48Spatrick       .Case("!DIExpression", MIToken::md_diexpr)
60809467b48Spatrick       .Case("!DILocation", MIToken::md_dilocation)
60909467b48Spatrick       .Default(MIToken::Error);
61009467b48Spatrick }
61109467b48Spatrick 
maybeLexExclaim(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)61209467b48Spatrick static Cursor maybeLexExclaim(Cursor C, MIToken &Token,
61309467b48Spatrick                               ErrorCallbackType ErrorCallback) {
61409467b48Spatrick   if (C.peek() != '!')
615*d415bd75Srobert     return std::nullopt;
61609467b48Spatrick   auto Range = C;
61709467b48Spatrick   C.advance(1);
61809467b48Spatrick   if (isdigit(C.peek()) || !isIdentifierChar(C.peek())) {
61909467b48Spatrick     Token.reset(MIToken::exclaim, Range.upto(C));
62009467b48Spatrick     return C;
62109467b48Spatrick   }
62209467b48Spatrick   while (isIdentifierChar(C.peek()))
62309467b48Spatrick     C.advance();
62409467b48Spatrick   StringRef StrVal = Range.upto(C);
62509467b48Spatrick   Token.reset(getMetadataKeywordKind(StrVal), StrVal);
62609467b48Spatrick   if (Token.isError())
62709467b48Spatrick     ErrorCallback(Token.location(),
62809467b48Spatrick                   "use of unknown metadata keyword '" + StrVal + "'");
62909467b48Spatrick   return C;
63009467b48Spatrick }
63109467b48Spatrick 
symbolToken(char C)63209467b48Spatrick static MIToken::TokenKind symbolToken(char C) {
63309467b48Spatrick   switch (C) {
63409467b48Spatrick   case ',':
63509467b48Spatrick     return MIToken::comma;
63609467b48Spatrick   case '.':
63709467b48Spatrick     return MIToken::dot;
63809467b48Spatrick   case '=':
63909467b48Spatrick     return MIToken::equal;
64009467b48Spatrick   case ':':
64109467b48Spatrick     return MIToken::colon;
64209467b48Spatrick   case '(':
64309467b48Spatrick     return MIToken::lparen;
64409467b48Spatrick   case ')':
64509467b48Spatrick     return MIToken::rparen;
64609467b48Spatrick   case '{':
64709467b48Spatrick     return MIToken::lbrace;
64809467b48Spatrick   case '}':
64909467b48Spatrick     return MIToken::rbrace;
65009467b48Spatrick   case '+':
65109467b48Spatrick     return MIToken::plus;
65209467b48Spatrick   case '-':
65309467b48Spatrick     return MIToken::minus;
65409467b48Spatrick   case '<':
65509467b48Spatrick     return MIToken::less;
65609467b48Spatrick   case '>':
65709467b48Spatrick     return MIToken::greater;
65809467b48Spatrick   default:
65909467b48Spatrick     return MIToken::Error;
66009467b48Spatrick   }
66109467b48Spatrick }
66209467b48Spatrick 
maybeLexSymbol(Cursor C,MIToken & Token)66309467b48Spatrick static Cursor maybeLexSymbol(Cursor C, MIToken &Token) {
66409467b48Spatrick   MIToken::TokenKind Kind;
66509467b48Spatrick   unsigned Length = 1;
66609467b48Spatrick   if (C.peek() == ':' && C.peek(1) == ':') {
66709467b48Spatrick     Kind = MIToken::coloncolon;
66809467b48Spatrick     Length = 2;
66909467b48Spatrick   } else
67009467b48Spatrick     Kind = symbolToken(C.peek());
67109467b48Spatrick   if (Kind == MIToken::Error)
672*d415bd75Srobert     return std::nullopt;
67309467b48Spatrick   auto Range = C;
67409467b48Spatrick   C.advance(Length);
67509467b48Spatrick   Token.reset(Kind, Range.upto(C));
67609467b48Spatrick   return C;
67709467b48Spatrick }
67809467b48Spatrick 
maybeLexNewline(Cursor C,MIToken & Token)67909467b48Spatrick static Cursor maybeLexNewline(Cursor C, MIToken &Token) {
68009467b48Spatrick   if (!isNewlineChar(C.peek()))
681*d415bd75Srobert     return std::nullopt;
68209467b48Spatrick   auto Range = C;
68309467b48Spatrick   C.advance();
68409467b48Spatrick   Token.reset(MIToken::Newline, Range.upto(C));
68509467b48Spatrick   return C;
68609467b48Spatrick }
68709467b48Spatrick 
maybeLexEscapedIRValue(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)68809467b48Spatrick static Cursor maybeLexEscapedIRValue(Cursor C, MIToken &Token,
68909467b48Spatrick                                      ErrorCallbackType ErrorCallback) {
69009467b48Spatrick   if (C.peek() != '`')
691*d415bd75Srobert     return std::nullopt;
69209467b48Spatrick   auto Range = C;
69309467b48Spatrick   C.advance();
69409467b48Spatrick   auto StrRange = C;
69509467b48Spatrick   while (C.peek() != '`') {
69609467b48Spatrick     if (C.isEOF() || isNewlineChar(C.peek())) {
69709467b48Spatrick       ErrorCallback(
69809467b48Spatrick           C.location(),
69909467b48Spatrick           "end of machine instruction reached before the closing '`'");
70009467b48Spatrick       Token.reset(MIToken::Error, Range.remaining());
70109467b48Spatrick       return C;
70209467b48Spatrick     }
70309467b48Spatrick     C.advance();
70409467b48Spatrick   }
70509467b48Spatrick   StringRef Value = StrRange.upto(C);
70609467b48Spatrick   C.advance();
70709467b48Spatrick   Token.reset(MIToken::QuotedIRValue, Range.upto(C)).setStringValue(Value);
70809467b48Spatrick   return C;
70909467b48Spatrick }
71009467b48Spatrick 
lexMIToken(StringRef Source,MIToken & Token,ErrorCallbackType ErrorCallback)71109467b48Spatrick StringRef llvm::lexMIToken(StringRef Source, MIToken &Token,
71209467b48Spatrick                            ErrorCallbackType ErrorCallback) {
71309467b48Spatrick   auto C = skipComment(skipWhitespace(Cursor(Source)));
71409467b48Spatrick   if (C.isEOF()) {
71509467b48Spatrick     Token.reset(MIToken::Eof, C.remaining());
71609467b48Spatrick     return C.remaining();
71709467b48Spatrick   }
71809467b48Spatrick 
719097a140dSpatrick   C = skipMachineOperandComment(C);
720097a140dSpatrick 
72109467b48Spatrick   if (Cursor R = maybeLexMachineBasicBlock(C, Token, ErrorCallback))
72209467b48Spatrick     return R.remaining();
72309467b48Spatrick   if (Cursor R = maybeLexIdentifier(C, Token))
72409467b48Spatrick     return R.remaining();
72509467b48Spatrick   if (Cursor R = maybeLexJumpTableIndex(C, Token))
72609467b48Spatrick     return R.remaining();
72709467b48Spatrick   if (Cursor R = maybeLexStackObject(C, Token))
72809467b48Spatrick     return R.remaining();
72909467b48Spatrick   if (Cursor R = maybeLexFixedStackObject(C, Token))
73009467b48Spatrick     return R.remaining();
73109467b48Spatrick   if (Cursor R = maybeLexConstantPoolItem(C, Token))
73209467b48Spatrick     return R.remaining();
73309467b48Spatrick   if (Cursor R = maybeLexSubRegisterIndex(C, Token, ErrorCallback))
73409467b48Spatrick     return R.remaining();
73509467b48Spatrick   if (Cursor R = maybeLexIRBlock(C, Token, ErrorCallback))
73609467b48Spatrick     return R.remaining();
73709467b48Spatrick   if (Cursor R = maybeLexIRValue(C, Token, ErrorCallback))
73809467b48Spatrick     return R.remaining();
73909467b48Spatrick   if (Cursor R = maybeLexRegister(C, Token, ErrorCallback))
74009467b48Spatrick     return R.remaining();
74109467b48Spatrick   if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback))
74209467b48Spatrick     return R.remaining();
74309467b48Spatrick   if (Cursor R = maybeLexExternalSymbol(C, Token, ErrorCallback))
74409467b48Spatrick     return R.remaining();
74509467b48Spatrick   if (Cursor R = maybeLexMCSymbol(C, Token, ErrorCallback))
74609467b48Spatrick     return R.remaining();
74709467b48Spatrick   if (Cursor R = maybeLexHexadecimalLiteral(C, Token))
74809467b48Spatrick     return R.remaining();
74909467b48Spatrick   if (Cursor R = maybeLexNumericalLiteral(C, Token))
75009467b48Spatrick     return R.remaining();
75109467b48Spatrick   if (Cursor R = maybeLexExclaim(C, Token, ErrorCallback))
75209467b48Spatrick     return R.remaining();
75309467b48Spatrick   if (Cursor R = maybeLexSymbol(C, Token))
75409467b48Spatrick     return R.remaining();
75509467b48Spatrick   if (Cursor R = maybeLexNewline(C, Token))
75609467b48Spatrick     return R.remaining();
75709467b48Spatrick   if (Cursor R = maybeLexEscapedIRValue(C, Token, ErrorCallback))
75809467b48Spatrick     return R.remaining();
75909467b48Spatrick   if (Cursor R = maybeLexStringConstant(C, Token, ErrorCallback))
76009467b48Spatrick     return R.remaining();
76109467b48Spatrick 
76209467b48Spatrick   Token.reset(MIToken::Error, C.remaining());
76309467b48Spatrick   ErrorCallback(C.location(),
76409467b48Spatrick                 Twine("unexpected character '") + Twine(C.peek()) + "'");
76509467b48Spatrick   return C.remaining();
76609467b48Spatrick }
767