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 
11782a1cfdcSAlex Lorenz static Cursor lexName(
11882a1cfdcSAlex Lorenz     Cursor C, MIToken &Token, MIToken::TokenKind Type,
11982a1cfdcSAlex Lorenz     MIToken::TokenKind QuotedType, unsigned PrefixLength,
12082a1cfdcSAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
12182a1cfdcSAlex Lorenz   auto Range = C;
12282a1cfdcSAlex Lorenz   C.advance(PrefixLength);
12382a1cfdcSAlex Lorenz   if (C.peek() == '"') {
12482a1cfdcSAlex Lorenz     if (Cursor R = lexStringConstant(C, ErrorCallback)) {
12582a1cfdcSAlex Lorenz       Token = MIToken(QuotedType, Range.upto(R), PrefixLength);
12682a1cfdcSAlex Lorenz       return R;
12782a1cfdcSAlex Lorenz     }
12882a1cfdcSAlex Lorenz     Token = MIToken(MIToken::Error, Range.remaining());
12982a1cfdcSAlex Lorenz     return Range;
13082a1cfdcSAlex Lorenz   }
13182a1cfdcSAlex Lorenz   while (isIdentifierChar(C.peek()))
13282a1cfdcSAlex Lorenz     C.advance();
13382a1cfdcSAlex Lorenz   Token = MIToken(Type, Range.upto(C), PrefixLength);
13482a1cfdcSAlex Lorenz   return C;
13582a1cfdcSAlex Lorenz }
13682a1cfdcSAlex Lorenz 
137cb268d46SAlex Lorenz static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
138cb268d46SAlex Lorenz   return StringSwitch<MIToken::TokenKind>(Identifier)
139cb268d46SAlex Lorenz       .Case("_", MIToken::underscore)
140cb268d46SAlex Lorenz       .Case("implicit", MIToken::kw_implicit)
141cb268d46SAlex Lorenz       .Case("implicit-def", MIToken::kw_implicit_define)
142cbbfd0b1SAlex Lorenz       .Case("dead", MIToken::kw_dead)
143495ad879SAlex Lorenz       .Case("killed", MIToken::kw_killed)
1444d026b89SAlex Lorenz       .Case("undef", MIToken::kw_undef)
145e5a44660SAlex Lorenz       .Case("frame-setup", MIToken::kw_frame_setup)
14646d760d1SAlex Lorenz       .Case("debug-location", MIToken::kw_debug_location)
1478cfc6867SAlex Lorenz       .Case(".cfi_offset", MIToken::kw_cfi_offset)
1485b0d5f6fSAlex Lorenz       .Case(".cfi_def_cfa_register", MIToken::kw_cfi_def_cfa_register)
149f4baeb51SAlex Lorenz       .Case(".cfi_def_cfa_offset", MIToken::kw_cfi_def_cfa_offset)
150*b139323fSAlex Lorenz       .Case(".cfi_def_cfa", MIToken::kw_cfi_def_cfa)
151deb53490SAlex Lorenz       .Case("blockaddress", MIToken::kw_blockaddress)
152ef5c196fSAlex Lorenz       .Case("target-index", MIToken::kw_target_index)
153cb268d46SAlex Lorenz       .Default(MIToken::Identifier);
154cb268d46SAlex Lorenz }
155cb268d46SAlex Lorenz 
1566c6c46e4SAlex Lorenz static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) {
157f4baeb51SAlex Lorenz   if (!isalpha(C.peek()) && C.peek() != '_' && C.peek() != '.')
1586c6c46e4SAlex Lorenz     return None;
15991370c5dSAlex Lorenz   auto Range = C;
16091370c5dSAlex Lorenz   while (isIdentifierChar(C.peek()))
16191370c5dSAlex Lorenz     C.advance();
16212b554e6SAlex Lorenz   auto Identifier = Range.upto(C);
163cb268d46SAlex Lorenz   Token = MIToken(getIdentifierKind(Identifier), Identifier);
16491370c5dSAlex Lorenz   return C;
16591370c5dSAlex Lorenz }
16691370c5dSAlex Lorenz 
1676c6c46e4SAlex Lorenz static Cursor maybeLexMachineBasicBlock(
16833f0aef3SAlex Lorenz     Cursor C, MIToken &Token,
16933f0aef3SAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
1706c6c46e4SAlex Lorenz   if (!C.remaining().startswith("%bb."))
1716c6c46e4SAlex Lorenz     return None;
17233f0aef3SAlex Lorenz   auto Range = C;
17333f0aef3SAlex Lorenz   C.advance(4); // Skip '%bb.'
17433f0aef3SAlex Lorenz   if (!isdigit(C.peek())) {
17533f0aef3SAlex Lorenz     Token = MIToken(MIToken::Error, C.remaining());
17633f0aef3SAlex Lorenz     ErrorCallback(C.location(), "expected a number after '%bb.'");
17733f0aef3SAlex Lorenz     return C;
17833f0aef3SAlex Lorenz   }
17933f0aef3SAlex Lorenz   auto NumberRange = C;
18033f0aef3SAlex Lorenz   while (isdigit(C.peek()))
18133f0aef3SAlex Lorenz     C.advance();
18233f0aef3SAlex Lorenz   StringRef Number = NumberRange.upto(C);
18333f0aef3SAlex Lorenz   unsigned StringOffset = 4 + Number.size(); // Drop '%bb.<id>'
18433f0aef3SAlex Lorenz   if (C.peek() == '.') {
18533f0aef3SAlex Lorenz     C.advance(); // Skip '.'
18633f0aef3SAlex Lorenz     ++StringOffset;
18733f0aef3SAlex Lorenz     while (isIdentifierChar(C.peek()))
18833f0aef3SAlex Lorenz       C.advance();
18933f0aef3SAlex Lorenz   }
19033f0aef3SAlex Lorenz   Token = MIToken(MIToken::MachineBasicBlock, Range.upto(C), APSInt(Number),
19133f0aef3SAlex Lorenz                   StringOffset);
19233f0aef3SAlex Lorenz   return C;
19333f0aef3SAlex Lorenz }
19433f0aef3SAlex Lorenz 
19531d70683SAlex Lorenz static Cursor maybeLexIndex(Cursor C, MIToken &Token, StringRef Rule,
19631d70683SAlex Lorenz                             MIToken::TokenKind Kind) {
19731d70683SAlex Lorenz   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
19831d70683SAlex Lorenz     return None;
19931d70683SAlex Lorenz   auto Range = C;
20031d70683SAlex Lorenz   C.advance(Rule.size());
20131d70683SAlex Lorenz   auto NumberRange = C;
20231d70683SAlex Lorenz   while (isdigit(C.peek()))
20331d70683SAlex Lorenz     C.advance();
20431d70683SAlex Lorenz   Token = MIToken(Kind, Range.upto(C), APSInt(NumberRange.upto(C)));
20531d70683SAlex Lorenz   return C;
20631d70683SAlex Lorenz }
20731d70683SAlex Lorenz 
2087feaf7c6SAlex Lorenz static Cursor maybeLexIndexAndName(Cursor C, MIToken &Token, StringRef Rule,
2097feaf7c6SAlex Lorenz                                    MIToken::TokenKind Kind) {
2107feaf7c6SAlex Lorenz   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
2117feaf7c6SAlex Lorenz     return None;
2127feaf7c6SAlex Lorenz   auto Range = C;
2137feaf7c6SAlex Lorenz   C.advance(Rule.size());
2147feaf7c6SAlex Lorenz   auto NumberRange = C;
2157feaf7c6SAlex Lorenz   while (isdigit(C.peek()))
2167feaf7c6SAlex Lorenz     C.advance();
2177feaf7c6SAlex Lorenz   StringRef Number = NumberRange.upto(C);
2187feaf7c6SAlex Lorenz   unsigned StringOffset = Rule.size() + Number.size();
2197feaf7c6SAlex Lorenz   if (C.peek() == '.') {
2207feaf7c6SAlex Lorenz     C.advance();
2217feaf7c6SAlex Lorenz     ++StringOffset;
2227feaf7c6SAlex Lorenz     while (isIdentifierChar(C.peek()))
2237feaf7c6SAlex Lorenz       C.advance();
2247feaf7c6SAlex Lorenz   }
2257feaf7c6SAlex Lorenz   Token = MIToken(Kind, Range.upto(C), APSInt(Number), StringOffset);
2267feaf7c6SAlex Lorenz   return C;
2277feaf7c6SAlex Lorenz }
2287feaf7c6SAlex Lorenz 
22931d70683SAlex Lorenz static Cursor maybeLexJumpTableIndex(Cursor C, MIToken &Token) {
23031d70683SAlex Lorenz   return maybeLexIndex(C, Token, "%jump-table.", MIToken::JumpTableIndex);
23131d70683SAlex Lorenz }
23231d70683SAlex Lorenz 
2337feaf7c6SAlex Lorenz static Cursor maybeLexStackObject(Cursor C, MIToken &Token) {
2347feaf7c6SAlex Lorenz   return maybeLexIndexAndName(C, Token, "%stack.", MIToken::StackObject);
2357feaf7c6SAlex Lorenz }
2367feaf7c6SAlex Lorenz 
2377feaf7c6SAlex Lorenz static Cursor maybeLexFixedStackObject(Cursor C, MIToken &Token) {
2387feaf7c6SAlex Lorenz   return maybeLexIndex(C, Token, "%fixed-stack.", MIToken::FixedStackObject);
2397feaf7c6SAlex Lorenz }
2407feaf7c6SAlex Lorenz 
241ab980499SAlex Lorenz static Cursor maybeLexConstantPoolItem(Cursor C, MIToken &Token) {
242ab980499SAlex Lorenz   return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem);
243ab980499SAlex Lorenz }
244ab980499SAlex Lorenz 
245deb53490SAlex Lorenz static Cursor maybeLexIRBlock(
246deb53490SAlex Lorenz     Cursor C, MIToken &Token,
247deb53490SAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
248deb53490SAlex Lorenz   const StringRef Rule = "%ir-block.";
249deb53490SAlex Lorenz   if (!C.remaining().startswith(Rule))
250deb53490SAlex Lorenz     return None;
251deb53490SAlex Lorenz   if (isdigit(C.peek(Rule.size())))
252deb53490SAlex Lorenz     return maybeLexIndex(C, Token, Rule, MIToken::IRBlock);
253deb53490SAlex Lorenz   return lexName(C, Token, MIToken::NamedIRBlock, MIToken::QuotedNamedIRBlock,
254deb53490SAlex Lorenz                  Rule.size(), ErrorCallback);
2558a1915b0SAlex Lorenz }
2568a1915b0SAlex Lorenz 
25753464510SAlex Lorenz static Cursor lexVirtualRegister(Cursor C, MIToken &Token) {
25853464510SAlex Lorenz   auto Range = C;
25953464510SAlex Lorenz   C.advance(); // Skip '%'
26053464510SAlex Lorenz   auto NumberRange = C;
26153464510SAlex Lorenz   while (isdigit(C.peek()))
26253464510SAlex Lorenz     C.advance();
26353464510SAlex Lorenz   Token = MIToken(MIToken::VirtualRegister, Range.upto(C),
26453464510SAlex Lorenz                   APSInt(NumberRange.upto(C)));
26553464510SAlex Lorenz   return C;
26653464510SAlex Lorenz }
26753464510SAlex Lorenz 
2686c6c46e4SAlex Lorenz static Cursor maybeLexRegister(Cursor C, MIToken &Token) {
2696c6c46e4SAlex Lorenz   if (C.peek() != '%')
2706c6c46e4SAlex Lorenz     return None;
27153464510SAlex Lorenz   if (isdigit(C.peek(1)))
27253464510SAlex Lorenz     return lexVirtualRegister(C, Token);
273f3db51deSAlex Lorenz   auto Range = C;
274f3db51deSAlex Lorenz   C.advance(); // Skip '%'
275f3db51deSAlex Lorenz   while (isIdentifierChar(C.peek()))
276f3db51deSAlex Lorenz     C.advance();
27733f0aef3SAlex Lorenz   Token = MIToken(MIToken::NamedRegister, Range.upto(C),
27833f0aef3SAlex Lorenz                   /*StringOffset=*/1); // Drop the '%'
279f3db51deSAlex Lorenz   return C;
280f3db51deSAlex Lorenz }
281f3db51deSAlex Lorenz 
282c1fbb354SAlex Lorenz static Cursor maybeLexGlobalValue(
283c1fbb354SAlex Lorenz     Cursor C, MIToken &Token,
284c1fbb354SAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
285c1fbb354SAlex Lorenz   if (C.peek() != '@')
286c1fbb354SAlex Lorenz     return None;
287c1fbb354SAlex Lorenz   if (!isdigit(C.peek(1)))
288c1fbb354SAlex Lorenz     return lexName(C, Token, MIToken::NamedGlobalValue,
289c1fbb354SAlex Lorenz                    MIToken::QuotedNamedGlobalValue, /*PrefixLength=*/1,
290c1fbb354SAlex Lorenz                    ErrorCallback);
291c1fbb354SAlex Lorenz   auto Range = C;
292c1fbb354SAlex Lorenz   C.advance(1); // Skip the '@'
293c1fbb354SAlex Lorenz   auto NumberRange = C;
294c1fbb354SAlex Lorenz   while (isdigit(C.peek()))
295c1fbb354SAlex Lorenz     C.advance();
296c1fbb354SAlex Lorenz   Token =
297c1fbb354SAlex Lorenz       MIToken(MIToken::GlobalValue, Range.upto(C), APSInt(NumberRange.upto(C)));
298c1fbb354SAlex Lorenz   return C;
299c1fbb354SAlex Lorenz }
300c1fbb354SAlex Lorenz 
3016ede3744SAlex Lorenz static Cursor maybeLexExternalSymbol(
3026ede3744SAlex Lorenz     Cursor C, MIToken &Token,
3036ede3744SAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
3046ede3744SAlex Lorenz   if (C.peek() != '$')
3056ede3744SAlex Lorenz     return None;
3066ede3744SAlex Lorenz   return lexName(C, Token, MIToken::ExternalSymbol,
3076ede3744SAlex Lorenz                  MIToken::QuotedExternalSymbol,
3086ede3744SAlex Lorenz                  /*PrefixLength=*/1, ErrorCallback);
3096ede3744SAlex Lorenz }
3106ede3744SAlex Lorenz 
3116c6c46e4SAlex Lorenz static Cursor maybeLexIntegerLiteral(Cursor C, MIToken &Token) {
3126c6c46e4SAlex Lorenz   if (!isdigit(C.peek()) && (C.peek() != '-' || !isdigit(C.peek(1))))
3136c6c46e4SAlex Lorenz     return None;
314240fc1e0SAlex Lorenz   auto Range = C;
315240fc1e0SAlex Lorenz   C.advance();
316240fc1e0SAlex Lorenz   while (isdigit(C.peek()))
317240fc1e0SAlex Lorenz     C.advance();
318240fc1e0SAlex Lorenz   StringRef StrVal = Range.upto(C);
319240fc1e0SAlex Lorenz   Token = MIToken(MIToken::IntegerLiteral, StrVal, APSInt(StrVal));
320240fc1e0SAlex Lorenz   return C;
321240fc1e0SAlex Lorenz }
322240fc1e0SAlex Lorenz 
323f3db51deSAlex Lorenz static MIToken::TokenKind symbolToken(char C) {
324f3db51deSAlex Lorenz   switch (C) {
325f3db51deSAlex Lorenz   case ',':
326f3db51deSAlex Lorenz     return MIToken::comma;
327f3db51deSAlex Lorenz   case '=':
328f3db51deSAlex Lorenz     return MIToken::equal;
3292eacca86SAlex Lorenz   case ':':
3302eacca86SAlex Lorenz     return MIToken::colon;
33135e44469SAlex Lorenz   case '!':
33235e44469SAlex Lorenz     return MIToken::exclaim;
333deb53490SAlex Lorenz   case '(':
334deb53490SAlex Lorenz     return MIToken::lparen;
335deb53490SAlex Lorenz   case ')':
336deb53490SAlex Lorenz     return MIToken::rparen;
337f3db51deSAlex Lorenz   default:
338f3db51deSAlex Lorenz     return MIToken::Error;
339f3db51deSAlex Lorenz   }
340f3db51deSAlex Lorenz }
341f3db51deSAlex Lorenz 
3426c6c46e4SAlex Lorenz static Cursor maybeLexSymbol(Cursor C, MIToken &Token) {
3436c6c46e4SAlex Lorenz   auto Kind = symbolToken(C.peek());
3446c6c46e4SAlex Lorenz   if (Kind == MIToken::Error)
3456c6c46e4SAlex Lorenz     return None;
346f3db51deSAlex Lorenz   auto Range = C;
347f3db51deSAlex Lorenz   C.advance();
348f3db51deSAlex Lorenz   Token = MIToken(Kind, Range.upto(C));
349f3db51deSAlex Lorenz   return C;
350f3db51deSAlex Lorenz }
351f3db51deSAlex Lorenz 
35291370c5dSAlex Lorenz StringRef llvm::lexMIToken(
35391370c5dSAlex Lorenz     StringRef Source, MIToken &Token,
35491370c5dSAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
35591370c5dSAlex Lorenz   auto C = skipWhitespace(Cursor(Source));
35691370c5dSAlex Lorenz   if (C.isEOF()) {
35791370c5dSAlex Lorenz     Token = MIToken(MIToken::Eof, C.remaining());
35891370c5dSAlex Lorenz     return C.remaining();
35991370c5dSAlex Lorenz   }
36091370c5dSAlex Lorenz 
3616c6c46e4SAlex Lorenz   if (Cursor R = maybeLexIdentifier(C, Token))
3626c6c46e4SAlex Lorenz     return R.remaining();
3636c6c46e4SAlex Lorenz   if (Cursor R = maybeLexMachineBasicBlock(C, Token, ErrorCallback))
3646c6c46e4SAlex Lorenz     return R.remaining();
36531d70683SAlex Lorenz   if (Cursor R = maybeLexJumpTableIndex(C, Token))
36631d70683SAlex Lorenz     return R.remaining();
3677feaf7c6SAlex Lorenz   if (Cursor R = maybeLexStackObject(C, Token))
3687feaf7c6SAlex Lorenz     return R.remaining();
3697feaf7c6SAlex Lorenz   if (Cursor R = maybeLexFixedStackObject(C, Token))
3707feaf7c6SAlex Lorenz     return R.remaining();
371ab980499SAlex Lorenz   if (Cursor R = maybeLexConstantPoolItem(C, Token))
372ab980499SAlex Lorenz     return R.remaining();
373deb53490SAlex Lorenz   if (Cursor R = maybeLexIRBlock(C, Token, ErrorCallback))
3748a1915b0SAlex Lorenz     return R.remaining();
3756c6c46e4SAlex Lorenz   if (Cursor R = maybeLexRegister(C, Token))
3766c6c46e4SAlex Lorenz     return R.remaining();
377b29554daSAlex Lorenz   if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback))
3786c6c46e4SAlex Lorenz     return R.remaining();
3796ede3744SAlex Lorenz   if (Cursor R = maybeLexExternalSymbol(C, Token, ErrorCallback))
3806ede3744SAlex Lorenz     return R.remaining();
3816c6c46e4SAlex Lorenz   if (Cursor R = maybeLexIntegerLiteral(C, Token))
3826c6c46e4SAlex Lorenz     return R.remaining();
3836c6c46e4SAlex Lorenz   if (Cursor R = maybeLexSymbol(C, Token))
3846c6c46e4SAlex Lorenz     return R.remaining();
3856c6c46e4SAlex Lorenz 
38691370c5dSAlex Lorenz   Token = MIToken(MIToken::Error, C.remaining());
38791370c5dSAlex Lorenz   ErrorCallback(C.location(),
3886c6c46e4SAlex Lorenz                 Twine("unexpected character '") + Twine(C.peek()) + "'");
38991370c5dSAlex Lorenz   return C.remaining();
39091370c5dSAlex Lorenz }
391