191370c5dSAlex Lorenz //===- MILexer.cpp - Machine instructions lexer implementation ----------===//
291370c5dSAlex Lorenz //
391370c5dSAlex Lorenz //                     The LLVM Compiler Infrastructure
491370c5dSAlex Lorenz //
591370c5dSAlex Lorenz // This file is distributed under the University of Illinois Open Source
691370c5dSAlex Lorenz // License. See LICENSE.TXT for details.
791370c5dSAlex Lorenz //
891370c5dSAlex Lorenz //===----------------------------------------------------------------------===//
991370c5dSAlex Lorenz //
1091370c5dSAlex Lorenz // This file implements the lexing of machine instructions.
1191370c5dSAlex Lorenz //
1291370c5dSAlex Lorenz //===----------------------------------------------------------------------===//
1391370c5dSAlex Lorenz 
1491370c5dSAlex Lorenz #include "MILexer.h"
15b29554daSAlex Lorenz #include "llvm/ADT/StringExtras.h"
16cb268d46SAlex Lorenz #include "llvm/ADT/StringSwitch.h"
1791370c5dSAlex Lorenz #include "llvm/ADT/Twine.h"
1891370c5dSAlex Lorenz #include <cctype>
1991370c5dSAlex Lorenz 
2091370c5dSAlex Lorenz using namespace llvm;
2191370c5dSAlex Lorenz 
2291370c5dSAlex Lorenz namespace {
2391370c5dSAlex Lorenz 
2491370c5dSAlex Lorenz /// This class provides a way to iterate and get characters from the source
2591370c5dSAlex Lorenz /// string.
2691370c5dSAlex Lorenz class Cursor {
2791370c5dSAlex Lorenz   const char *Ptr;
2891370c5dSAlex Lorenz   const char *End;
2991370c5dSAlex Lorenz 
3091370c5dSAlex Lorenz public:
316c6c46e4SAlex Lorenz   Cursor(NoneType) : Ptr(nullptr), End(nullptr) {}
326c6c46e4SAlex Lorenz 
3391370c5dSAlex Lorenz   explicit Cursor(StringRef Str) {
3491370c5dSAlex Lorenz     Ptr = Str.data();
3591370c5dSAlex Lorenz     End = Ptr + Str.size();
3691370c5dSAlex Lorenz   }
3791370c5dSAlex Lorenz 
3891370c5dSAlex Lorenz   bool isEOF() const { return Ptr == End; }
3991370c5dSAlex Lorenz 
40c267b5f5SNAKAMURA Takumi   char peek(int I = 0) const { return End - Ptr <= I ? 0 : Ptr[I]; }
4191370c5dSAlex Lorenz 
4233f0aef3SAlex Lorenz   void advance(unsigned I = 1) { Ptr += I; }
4391370c5dSAlex Lorenz 
4491370c5dSAlex Lorenz   StringRef remaining() const { return StringRef(Ptr, End - Ptr); }
4591370c5dSAlex Lorenz 
4691370c5dSAlex Lorenz   StringRef upto(Cursor C) const {
4791370c5dSAlex Lorenz     assert(C.Ptr >= Ptr && C.Ptr <= End);
4891370c5dSAlex Lorenz     return StringRef(Ptr, C.Ptr - Ptr);
4991370c5dSAlex Lorenz   }
5091370c5dSAlex Lorenz 
5191370c5dSAlex Lorenz   StringRef::iterator location() const { return Ptr; }
526c6c46e4SAlex Lorenz 
536c6c46e4SAlex Lorenz   operator bool() const { return Ptr != nullptr; }
5491370c5dSAlex Lorenz };
5591370c5dSAlex Lorenz 
5691370c5dSAlex Lorenz } // end anonymous namespace
5791370c5dSAlex Lorenz 
5891370c5dSAlex Lorenz /// Skip the leading whitespace characters and return the updated cursor.
5991370c5dSAlex Lorenz static Cursor skipWhitespace(Cursor C) {
6091370c5dSAlex Lorenz   while (isspace(C.peek()))
6191370c5dSAlex Lorenz     C.advance();
6291370c5dSAlex Lorenz   return C;
6391370c5dSAlex Lorenz }
6491370c5dSAlex Lorenz 
65484903ecSAlex Lorenz /// Return true if the given character satisfies the following regular
66484903ecSAlex Lorenz /// expression: [-a-zA-Z$._0-9]
6791370c5dSAlex Lorenz static bool isIdentifierChar(char C) {
68484903ecSAlex Lorenz   return isalpha(C) || isdigit(C) || C == '_' || C == '-' || C == '.' ||
69484903ecSAlex Lorenz          C == '$';
7091370c5dSAlex Lorenz }
7191370c5dSAlex Lorenz 
72b29554daSAlex Lorenz void MIToken::unescapeQuotedStringValue(std::string &Str) const {
73b29554daSAlex Lorenz   assert(isStringValueQuoted() && "String value isn't quoted");
74b29554daSAlex Lorenz   StringRef Value = Range.drop_front(StringOffset);
75b29554daSAlex Lorenz   assert(Value.front() == '"' && Value.back() == '"');
76b29554daSAlex Lorenz   Cursor C = Cursor(Value.substr(1, Value.size() - 2));
77b29554daSAlex Lorenz 
78b29554daSAlex Lorenz   Str.clear();
79b29554daSAlex Lorenz   Str.reserve(C.remaining().size());
80b29554daSAlex Lorenz   while (!C.isEOF()) {
81b29554daSAlex Lorenz     char Char = C.peek();
82b29554daSAlex Lorenz     if (Char == '\\') {
83b29554daSAlex Lorenz       if (C.peek(1) == '\\') {
84b29554daSAlex Lorenz         // Two '\' become one
85b29554daSAlex Lorenz         Str += '\\';
86b29554daSAlex Lorenz         C.advance(2);
87b29554daSAlex Lorenz         continue;
88b29554daSAlex Lorenz       }
89b29554daSAlex Lorenz       if (isxdigit(C.peek(1)) && isxdigit(C.peek(2))) {
90b29554daSAlex Lorenz         Str += hexDigitValue(C.peek(1)) * 16 + hexDigitValue(C.peek(2));
91b29554daSAlex Lorenz         C.advance(3);
92b29554daSAlex Lorenz         continue;
93b29554daSAlex Lorenz       }
94b29554daSAlex Lorenz     }
95b29554daSAlex Lorenz     Str += Char;
96b29554daSAlex Lorenz     C.advance();
97b29554daSAlex Lorenz   }
98b29554daSAlex Lorenz }
99b29554daSAlex Lorenz 
100b29554daSAlex Lorenz /// Lex a string constant using the following regular expression: \"[^\"]*\"
101b29554daSAlex Lorenz static Cursor lexStringConstant(
102b29554daSAlex Lorenz     Cursor C,
103b29554daSAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
104b29554daSAlex Lorenz   assert(C.peek() == '"');
105b29554daSAlex Lorenz   for (C.advance(); C.peek() != '"'; C.advance()) {
106b29554daSAlex Lorenz     if (C.isEOF()) {
107b29554daSAlex Lorenz       ErrorCallback(
108b29554daSAlex Lorenz           C.location(),
109b29554daSAlex Lorenz           "end of machine instruction reached before the closing '\"'");
110b29554daSAlex Lorenz       return None;
111b29554daSAlex Lorenz     }
112b29554daSAlex Lorenz   }
113b29554daSAlex Lorenz   C.advance();
114b29554daSAlex Lorenz   return C;
115b29554daSAlex Lorenz }
116b29554daSAlex Lorenz 
117cb268d46SAlex Lorenz static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
118cb268d46SAlex Lorenz   return StringSwitch<MIToken::TokenKind>(Identifier)
119cb268d46SAlex Lorenz       .Case("_", MIToken::underscore)
120cb268d46SAlex Lorenz       .Case("implicit", MIToken::kw_implicit)
121cb268d46SAlex Lorenz       .Case("implicit-def", MIToken::kw_implicit_define)
122cbbfd0b1SAlex Lorenz       .Case("dead", MIToken::kw_dead)
123495ad879SAlex Lorenz       .Case("killed", MIToken::kw_killed)
1244d026b89SAlex Lorenz       .Case("undef", MIToken::kw_undef)
125e5a44660SAlex Lorenz       .Case("frame-setup", MIToken::kw_frame_setup)
12646d760d1SAlex Lorenz       .Case("debug-location", MIToken::kw_debug_location)
127*8cfc6867SAlex Lorenz       .Case(".cfi_offset", MIToken::kw_cfi_offset)
128f4baeb51SAlex Lorenz       .Case(".cfi_def_cfa_offset", MIToken::kw_cfi_def_cfa_offset)
129cb268d46SAlex Lorenz       .Default(MIToken::Identifier);
130cb268d46SAlex Lorenz }
131cb268d46SAlex Lorenz 
1326c6c46e4SAlex Lorenz static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) {
133f4baeb51SAlex Lorenz   if (!isalpha(C.peek()) && C.peek() != '_' && C.peek() != '.')
1346c6c46e4SAlex Lorenz     return None;
13591370c5dSAlex Lorenz   auto Range = C;
13691370c5dSAlex Lorenz   while (isIdentifierChar(C.peek()))
13791370c5dSAlex Lorenz     C.advance();
13812b554e6SAlex Lorenz   auto Identifier = Range.upto(C);
139cb268d46SAlex Lorenz   Token = MIToken(getIdentifierKind(Identifier), Identifier);
14091370c5dSAlex Lorenz   return C;
14191370c5dSAlex Lorenz }
14291370c5dSAlex Lorenz 
1436c6c46e4SAlex Lorenz static Cursor maybeLexMachineBasicBlock(
14433f0aef3SAlex Lorenz     Cursor C, MIToken &Token,
14533f0aef3SAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
1466c6c46e4SAlex Lorenz   if (!C.remaining().startswith("%bb."))
1476c6c46e4SAlex Lorenz     return None;
14833f0aef3SAlex Lorenz   auto Range = C;
14933f0aef3SAlex Lorenz   C.advance(4); // Skip '%bb.'
15033f0aef3SAlex Lorenz   if (!isdigit(C.peek())) {
15133f0aef3SAlex Lorenz     Token = MIToken(MIToken::Error, C.remaining());
15233f0aef3SAlex Lorenz     ErrorCallback(C.location(), "expected a number after '%bb.'");
15333f0aef3SAlex Lorenz     return C;
15433f0aef3SAlex Lorenz   }
15533f0aef3SAlex Lorenz   auto NumberRange = C;
15633f0aef3SAlex Lorenz   while (isdigit(C.peek()))
15733f0aef3SAlex Lorenz     C.advance();
15833f0aef3SAlex Lorenz   StringRef Number = NumberRange.upto(C);
15933f0aef3SAlex Lorenz   unsigned StringOffset = 4 + Number.size(); // Drop '%bb.<id>'
16033f0aef3SAlex Lorenz   if (C.peek() == '.') {
16133f0aef3SAlex Lorenz     C.advance(); // Skip '.'
16233f0aef3SAlex Lorenz     ++StringOffset;
16333f0aef3SAlex Lorenz     while (isIdentifierChar(C.peek()))
16433f0aef3SAlex Lorenz       C.advance();
16533f0aef3SAlex Lorenz   }
16633f0aef3SAlex Lorenz   Token = MIToken(MIToken::MachineBasicBlock, Range.upto(C), APSInt(Number),
16733f0aef3SAlex Lorenz                   StringOffset);
16833f0aef3SAlex Lorenz   return C;
16933f0aef3SAlex Lorenz }
17033f0aef3SAlex Lorenz 
17131d70683SAlex Lorenz static Cursor maybeLexIndex(Cursor C, MIToken &Token, StringRef Rule,
17231d70683SAlex Lorenz                             MIToken::TokenKind Kind) {
17331d70683SAlex Lorenz   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
17431d70683SAlex Lorenz     return None;
17531d70683SAlex Lorenz   auto Range = C;
17631d70683SAlex Lorenz   C.advance(Rule.size());
17731d70683SAlex Lorenz   auto NumberRange = C;
17831d70683SAlex Lorenz   while (isdigit(C.peek()))
17931d70683SAlex Lorenz     C.advance();
18031d70683SAlex Lorenz   Token = MIToken(Kind, Range.upto(C), APSInt(NumberRange.upto(C)));
18131d70683SAlex Lorenz   return C;
18231d70683SAlex Lorenz }
18331d70683SAlex Lorenz 
1847feaf7c6SAlex Lorenz static Cursor maybeLexIndexAndName(Cursor C, MIToken &Token, StringRef Rule,
1857feaf7c6SAlex Lorenz                                    MIToken::TokenKind Kind) {
1867feaf7c6SAlex Lorenz   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
1877feaf7c6SAlex Lorenz     return None;
1887feaf7c6SAlex Lorenz   auto Range = C;
1897feaf7c6SAlex Lorenz   C.advance(Rule.size());
1907feaf7c6SAlex Lorenz   auto NumberRange = C;
1917feaf7c6SAlex Lorenz   while (isdigit(C.peek()))
1927feaf7c6SAlex Lorenz     C.advance();
1937feaf7c6SAlex Lorenz   StringRef Number = NumberRange.upto(C);
1947feaf7c6SAlex Lorenz   unsigned StringOffset = Rule.size() + Number.size();
1957feaf7c6SAlex Lorenz   if (C.peek() == '.') {
1967feaf7c6SAlex Lorenz     C.advance();
1977feaf7c6SAlex Lorenz     ++StringOffset;
1987feaf7c6SAlex Lorenz     while (isIdentifierChar(C.peek()))
1997feaf7c6SAlex Lorenz       C.advance();
2007feaf7c6SAlex Lorenz   }
2017feaf7c6SAlex Lorenz   Token = MIToken(Kind, Range.upto(C), APSInt(Number), StringOffset);
2027feaf7c6SAlex Lorenz   return C;
2037feaf7c6SAlex Lorenz }
2047feaf7c6SAlex Lorenz 
20531d70683SAlex Lorenz static Cursor maybeLexJumpTableIndex(Cursor C, MIToken &Token) {
20631d70683SAlex Lorenz   return maybeLexIndex(C, Token, "%jump-table.", MIToken::JumpTableIndex);
20731d70683SAlex Lorenz }
20831d70683SAlex Lorenz 
2097feaf7c6SAlex Lorenz static Cursor maybeLexStackObject(Cursor C, MIToken &Token) {
2107feaf7c6SAlex Lorenz   return maybeLexIndexAndName(C, Token, "%stack.", MIToken::StackObject);
2117feaf7c6SAlex Lorenz }
2127feaf7c6SAlex Lorenz 
2137feaf7c6SAlex Lorenz static Cursor maybeLexFixedStackObject(Cursor C, MIToken &Token) {
2147feaf7c6SAlex Lorenz   return maybeLexIndex(C, Token, "%fixed-stack.", MIToken::FixedStackObject);
2157feaf7c6SAlex Lorenz }
2167feaf7c6SAlex Lorenz 
217ab980499SAlex Lorenz static Cursor maybeLexConstantPoolItem(Cursor C, MIToken &Token) {
218ab980499SAlex Lorenz   return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem);
219ab980499SAlex Lorenz }
220ab980499SAlex Lorenz 
22153464510SAlex Lorenz static Cursor lexVirtualRegister(Cursor C, MIToken &Token) {
22253464510SAlex Lorenz   auto Range = C;
22353464510SAlex Lorenz   C.advance(); // Skip '%'
22453464510SAlex Lorenz   auto NumberRange = C;
22553464510SAlex Lorenz   while (isdigit(C.peek()))
22653464510SAlex Lorenz     C.advance();
22753464510SAlex Lorenz   Token = MIToken(MIToken::VirtualRegister, Range.upto(C),
22853464510SAlex Lorenz                   APSInt(NumberRange.upto(C)));
22953464510SAlex Lorenz   return C;
23053464510SAlex Lorenz }
23153464510SAlex Lorenz 
2326c6c46e4SAlex Lorenz static Cursor maybeLexRegister(Cursor C, MIToken &Token) {
2336c6c46e4SAlex Lorenz   if (C.peek() != '%')
2346c6c46e4SAlex Lorenz     return None;
23553464510SAlex Lorenz   if (isdigit(C.peek(1)))
23653464510SAlex Lorenz     return lexVirtualRegister(C, Token);
237f3db51deSAlex Lorenz   auto Range = C;
238f3db51deSAlex Lorenz   C.advance(); // Skip '%'
239f3db51deSAlex Lorenz   while (isIdentifierChar(C.peek()))
240f3db51deSAlex Lorenz     C.advance();
24133f0aef3SAlex Lorenz   Token = MIToken(MIToken::NamedRegister, Range.upto(C),
24233f0aef3SAlex Lorenz                   /*StringOffset=*/1); // Drop the '%'
243f3db51deSAlex Lorenz   return C;
244f3db51deSAlex Lorenz }
245f3db51deSAlex Lorenz 
2466ede3744SAlex Lorenz static Cursor lexName(
2476ede3744SAlex Lorenz     Cursor C, MIToken &Token, MIToken::TokenKind Type,
2486ede3744SAlex Lorenz     MIToken::TokenKind QuotedType, unsigned PrefixLength,
2496ede3744SAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
2506ede3744SAlex Lorenz   auto Range = C;
2516ede3744SAlex Lorenz   C.advance(PrefixLength);
2526ede3744SAlex Lorenz   if (C.peek() == '"') {
2536ede3744SAlex Lorenz     if (Cursor R = lexStringConstant(C, ErrorCallback)) {
2546ede3744SAlex Lorenz       Token = MIToken(QuotedType, Range.upto(R), PrefixLength);
2556ede3744SAlex Lorenz       return R;
2566ede3744SAlex Lorenz     }
2576ede3744SAlex Lorenz     Token = MIToken(MIToken::Error, Range.remaining());
2586ede3744SAlex Lorenz     return Range;
2596ede3744SAlex Lorenz   }
2606ede3744SAlex Lorenz   while (isIdentifierChar(C.peek()))
2616ede3744SAlex Lorenz     C.advance();
2626ede3744SAlex Lorenz   Token = MIToken(Type, Range.upto(C), PrefixLength);
2636ede3744SAlex Lorenz   return C;
2646ede3744SAlex Lorenz }
2656ede3744SAlex Lorenz 
266c1fbb354SAlex Lorenz static Cursor maybeLexGlobalValue(
267c1fbb354SAlex Lorenz     Cursor C, MIToken &Token,
268c1fbb354SAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
269c1fbb354SAlex Lorenz   if (C.peek() != '@')
270c1fbb354SAlex Lorenz     return None;
271c1fbb354SAlex Lorenz   if (!isdigit(C.peek(1)))
272c1fbb354SAlex Lorenz     return lexName(C, Token, MIToken::NamedGlobalValue,
273c1fbb354SAlex Lorenz                    MIToken::QuotedNamedGlobalValue, /*PrefixLength=*/1,
274c1fbb354SAlex Lorenz                    ErrorCallback);
275c1fbb354SAlex Lorenz   auto Range = C;
276c1fbb354SAlex Lorenz   C.advance(1); // Skip the '@'
277c1fbb354SAlex Lorenz   auto NumberRange = C;
278c1fbb354SAlex Lorenz   while (isdigit(C.peek()))
279c1fbb354SAlex Lorenz     C.advance();
280c1fbb354SAlex Lorenz   Token =
281c1fbb354SAlex Lorenz       MIToken(MIToken::GlobalValue, Range.upto(C), APSInt(NumberRange.upto(C)));
282c1fbb354SAlex Lorenz   return C;
283c1fbb354SAlex Lorenz }
284c1fbb354SAlex Lorenz 
2856ede3744SAlex Lorenz static Cursor maybeLexExternalSymbol(
2866ede3744SAlex Lorenz     Cursor C, MIToken &Token,
2876ede3744SAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
2886ede3744SAlex Lorenz   if (C.peek() != '$')
2896ede3744SAlex Lorenz     return None;
2906ede3744SAlex Lorenz   return lexName(C, Token, MIToken::ExternalSymbol,
2916ede3744SAlex Lorenz                  MIToken::QuotedExternalSymbol,
2926ede3744SAlex Lorenz                  /*PrefixLength=*/1, ErrorCallback);
2936ede3744SAlex Lorenz }
2946ede3744SAlex Lorenz 
2956c6c46e4SAlex Lorenz static Cursor maybeLexIntegerLiteral(Cursor C, MIToken &Token) {
2966c6c46e4SAlex Lorenz   if (!isdigit(C.peek()) && (C.peek() != '-' || !isdigit(C.peek(1))))
2976c6c46e4SAlex Lorenz     return None;
298240fc1e0SAlex Lorenz   auto Range = C;
299240fc1e0SAlex Lorenz   C.advance();
300240fc1e0SAlex Lorenz   while (isdigit(C.peek()))
301240fc1e0SAlex Lorenz     C.advance();
302240fc1e0SAlex Lorenz   StringRef StrVal = Range.upto(C);
303240fc1e0SAlex Lorenz   Token = MIToken(MIToken::IntegerLiteral, StrVal, APSInt(StrVal));
304240fc1e0SAlex Lorenz   return C;
305240fc1e0SAlex Lorenz }
306240fc1e0SAlex Lorenz 
307f3db51deSAlex Lorenz static MIToken::TokenKind symbolToken(char C) {
308f3db51deSAlex Lorenz   switch (C) {
309f3db51deSAlex Lorenz   case ',':
310f3db51deSAlex Lorenz     return MIToken::comma;
311f3db51deSAlex Lorenz   case '=':
312f3db51deSAlex Lorenz     return MIToken::equal;
3132eacca86SAlex Lorenz   case ':':
3142eacca86SAlex Lorenz     return MIToken::colon;
31535e44469SAlex Lorenz   case '!':
31635e44469SAlex Lorenz     return MIToken::exclaim;
317f3db51deSAlex Lorenz   default:
318f3db51deSAlex Lorenz     return MIToken::Error;
319f3db51deSAlex Lorenz   }
320f3db51deSAlex Lorenz }
321f3db51deSAlex Lorenz 
3226c6c46e4SAlex Lorenz static Cursor maybeLexSymbol(Cursor C, MIToken &Token) {
3236c6c46e4SAlex Lorenz   auto Kind = symbolToken(C.peek());
3246c6c46e4SAlex Lorenz   if (Kind == MIToken::Error)
3256c6c46e4SAlex Lorenz     return None;
326f3db51deSAlex Lorenz   auto Range = C;
327f3db51deSAlex Lorenz   C.advance();
328f3db51deSAlex Lorenz   Token = MIToken(Kind, Range.upto(C));
329f3db51deSAlex Lorenz   return C;
330f3db51deSAlex Lorenz }
331f3db51deSAlex Lorenz 
33291370c5dSAlex Lorenz StringRef llvm::lexMIToken(
33391370c5dSAlex Lorenz     StringRef Source, MIToken &Token,
33491370c5dSAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
33591370c5dSAlex Lorenz   auto C = skipWhitespace(Cursor(Source));
33691370c5dSAlex Lorenz   if (C.isEOF()) {
33791370c5dSAlex Lorenz     Token = MIToken(MIToken::Eof, C.remaining());
33891370c5dSAlex Lorenz     return C.remaining();
33991370c5dSAlex Lorenz   }
34091370c5dSAlex Lorenz 
3416c6c46e4SAlex Lorenz   if (Cursor R = maybeLexIdentifier(C, Token))
3426c6c46e4SAlex Lorenz     return R.remaining();
3436c6c46e4SAlex Lorenz   if (Cursor R = maybeLexMachineBasicBlock(C, Token, ErrorCallback))
3446c6c46e4SAlex Lorenz     return R.remaining();
34531d70683SAlex Lorenz   if (Cursor R = maybeLexJumpTableIndex(C, Token))
34631d70683SAlex Lorenz     return R.remaining();
3477feaf7c6SAlex Lorenz   if (Cursor R = maybeLexStackObject(C, Token))
3487feaf7c6SAlex Lorenz     return R.remaining();
3497feaf7c6SAlex Lorenz   if (Cursor R = maybeLexFixedStackObject(C, Token))
3507feaf7c6SAlex Lorenz     return R.remaining();
351ab980499SAlex Lorenz   if (Cursor R = maybeLexConstantPoolItem(C, Token))
352ab980499SAlex Lorenz     return R.remaining();
3536c6c46e4SAlex Lorenz   if (Cursor R = maybeLexRegister(C, Token))
3546c6c46e4SAlex Lorenz     return R.remaining();
355b29554daSAlex Lorenz   if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback))
3566c6c46e4SAlex Lorenz     return R.remaining();
3576ede3744SAlex Lorenz   if (Cursor R = maybeLexExternalSymbol(C, Token, ErrorCallback))
3586ede3744SAlex Lorenz     return R.remaining();
3596c6c46e4SAlex Lorenz   if (Cursor R = maybeLexIntegerLiteral(C, Token))
3606c6c46e4SAlex Lorenz     return R.remaining();
3616c6c46e4SAlex Lorenz   if (Cursor R = maybeLexSymbol(C, Token))
3626c6c46e4SAlex Lorenz     return R.remaining();
3636c6c46e4SAlex Lorenz 
36491370c5dSAlex Lorenz   Token = MIToken(MIToken::Error, C.remaining());
36591370c5dSAlex Lorenz   ErrorCallback(C.location(),
3666c6c46e4SAlex Lorenz                 Twine("unexpected character '") + Twine(C.peek()) + "'");
36791370c5dSAlex Lorenz   return C.remaining();
36891370c5dSAlex Lorenz }
369