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 
72970c12eaSAlex Lorenz /// Unescapes the given string value.
73970c12eaSAlex Lorenz ///
74970c12eaSAlex Lorenz /// Expects the string value to be quoted.
75970c12eaSAlex Lorenz static std::string unescapeQuotedString(StringRef Value) {
76b29554daSAlex Lorenz   assert(Value.front() == '"' && Value.back() == '"');
77b29554daSAlex Lorenz   Cursor C = Cursor(Value.substr(1, Value.size() - 2));
78b29554daSAlex Lorenz 
79970c12eaSAlex Lorenz   std::string Str;
80b29554daSAlex Lorenz   Str.reserve(C.remaining().size());
81b29554daSAlex Lorenz   while (!C.isEOF()) {
82b29554daSAlex Lorenz     char Char = C.peek();
83b29554daSAlex Lorenz     if (Char == '\\') {
84b29554daSAlex Lorenz       if (C.peek(1) == '\\') {
85b29554daSAlex Lorenz         // Two '\' become one
86b29554daSAlex Lorenz         Str += '\\';
87b29554daSAlex Lorenz         C.advance(2);
88b29554daSAlex Lorenz         continue;
89b29554daSAlex Lorenz       }
90b29554daSAlex Lorenz       if (isxdigit(C.peek(1)) && isxdigit(C.peek(2))) {
91b29554daSAlex Lorenz         Str += hexDigitValue(C.peek(1)) * 16 + hexDigitValue(C.peek(2));
92b29554daSAlex Lorenz         C.advance(3);
93b29554daSAlex Lorenz         continue;
94b29554daSAlex Lorenz       }
95b29554daSAlex Lorenz     }
96b29554daSAlex Lorenz     Str += Char;
97b29554daSAlex Lorenz     C.advance();
98b29554daSAlex Lorenz   }
99970c12eaSAlex Lorenz   return Str;
100b29554daSAlex Lorenz }
101b29554daSAlex Lorenz 
102b29554daSAlex Lorenz /// Lex a string constant using the following regular expression: \"[^\"]*\"
103b29554daSAlex Lorenz static Cursor lexStringConstant(
104b29554daSAlex Lorenz     Cursor C,
105b29554daSAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
106b29554daSAlex Lorenz   assert(C.peek() == '"');
107b29554daSAlex Lorenz   for (C.advance(); C.peek() != '"'; C.advance()) {
108b29554daSAlex Lorenz     if (C.isEOF()) {
109b29554daSAlex Lorenz       ErrorCallback(
110b29554daSAlex Lorenz           C.location(),
111b29554daSAlex Lorenz           "end of machine instruction reached before the closing '\"'");
112b29554daSAlex Lorenz       return None;
113b29554daSAlex Lorenz     }
114b29554daSAlex Lorenz   }
115b29554daSAlex Lorenz   C.advance();
116b29554daSAlex Lorenz   return C;
117b29554daSAlex Lorenz }
118b29554daSAlex Lorenz 
11982a1cfdcSAlex Lorenz static Cursor lexName(
120970c12eaSAlex Lorenz     Cursor C, MIToken &Token, MIToken::TokenKind Type, unsigned PrefixLength,
12182a1cfdcSAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
12282a1cfdcSAlex Lorenz   auto Range = C;
12382a1cfdcSAlex Lorenz   C.advance(PrefixLength);
12482a1cfdcSAlex Lorenz   if (C.peek() == '"') {
12582a1cfdcSAlex Lorenz     if (Cursor R = lexStringConstant(C, ErrorCallback)) {
126970c12eaSAlex Lorenz       StringRef String = Range.upto(R);
127970c12eaSAlex Lorenz       Token = MIToken(Type, String,
128970c12eaSAlex Lorenz                       unescapeQuotedString(String.drop_front(PrefixLength)),
129970c12eaSAlex Lorenz                       PrefixLength);
13082a1cfdcSAlex Lorenz       return R;
13182a1cfdcSAlex Lorenz     }
13282a1cfdcSAlex Lorenz     Token = MIToken(MIToken::Error, Range.remaining());
13382a1cfdcSAlex Lorenz     return Range;
13482a1cfdcSAlex Lorenz   }
13582a1cfdcSAlex Lorenz   while (isIdentifierChar(C.peek()))
13682a1cfdcSAlex Lorenz     C.advance();
13782a1cfdcSAlex Lorenz   Token = MIToken(Type, Range.upto(C), PrefixLength);
13882a1cfdcSAlex Lorenz   return C;
13982a1cfdcSAlex Lorenz }
14082a1cfdcSAlex Lorenz 
141*05e3882eSAlex Lorenz static Cursor maybeLexIntegerType(Cursor C, MIToken &Token) {
142*05e3882eSAlex Lorenz   if (C.peek() != 'i' || !isdigit(C.peek(1)))
143*05e3882eSAlex Lorenz     return None;
144*05e3882eSAlex Lorenz   auto Range = C;
145*05e3882eSAlex Lorenz   C.advance(); // Skip 'i'
146*05e3882eSAlex Lorenz   while (isdigit(C.peek()))
147*05e3882eSAlex Lorenz     C.advance();
148*05e3882eSAlex Lorenz   Token = MIToken(MIToken::IntegerType, Range.upto(C));
149*05e3882eSAlex Lorenz   return C;
150*05e3882eSAlex Lorenz }
151*05e3882eSAlex Lorenz 
152cb268d46SAlex Lorenz static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
153cb268d46SAlex Lorenz   return StringSwitch<MIToken::TokenKind>(Identifier)
154cb268d46SAlex Lorenz       .Case("_", MIToken::underscore)
155cb268d46SAlex Lorenz       .Case("implicit", MIToken::kw_implicit)
156cb268d46SAlex Lorenz       .Case("implicit-def", MIToken::kw_implicit_define)
157cbbfd0b1SAlex Lorenz       .Case("dead", MIToken::kw_dead)
158495ad879SAlex Lorenz       .Case("killed", MIToken::kw_killed)
1594d026b89SAlex Lorenz       .Case("undef", MIToken::kw_undef)
16001c1a5eeSAlex Lorenz       .Case("early-clobber", MIToken::kw_early_clobber)
1619075258bSAlex Lorenz       .Case("debug-use", MIToken::kw_debug_use)
162e5a44660SAlex Lorenz       .Case("frame-setup", MIToken::kw_frame_setup)
16346d760d1SAlex Lorenz       .Case("debug-location", MIToken::kw_debug_location)
1648cfc6867SAlex Lorenz       .Case(".cfi_offset", MIToken::kw_cfi_offset)
1655b0d5f6fSAlex Lorenz       .Case(".cfi_def_cfa_register", MIToken::kw_cfi_def_cfa_register)
166f4baeb51SAlex Lorenz       .Case(".cfi_def_cfa_offset", MIToken::kw_cfi_def_cfa_offset)
167b139323fSAlex Lorenz       .Case(".cfi_def_cfa", MIToken::kw_cfi_def_cfa)
168deb53490SAlex Lorenz       .Case("blockaddress", MIToken::kw_blockaddress)
169ef5c196fSAlex Lorenz       .Case("target-index", MIToken::kw_target_index)
170ad156fb6SAlex Lorenz       .Case("half", MIToken::kw_half)
171ad156fb6SAlex Lorenz       .Case("float", MIToken::kw_float)
172ad156fb6SAlex Lorenz       .Case("double", MIToken::kw_double)
173ad156fb6SAlex Lorenz       .Case("x86_fp80", MIToken::kw_x86_fp80)
174ad156fb6SAlex Lorenz       .Case("fp128", MIToken::kw_fp128)
175ad156fb6SAlex Lorenz       .Case("ppc_fp128", MIToken::kw_ppc_fp128)
176a518b796SAlex Lorenz       .Case("volatile", MIToken::kw_volatile)
177cb268d46SAlex Lorenz       .Default(MIToken::Identifier);
178cb268d46SAlex Lorenz }
179cb268d46SAlex Lorenz 
1806c6c46e4SAlex Lorenz static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) {
181f4baeb51SAlex Lorenz   if (!isalpha(C.peek()) && C.peek() != '_' && C.peek() != '.')
1826c6c46e4SAlex Lorenz     return None;
18391370c5dSAlex Lorenz   auto Range = C;
18491370c5dSAlex Lorenz   while (isIdentifierChar(C.peek()))
18591370c5dSAlex Lorenz     C.advance();
18612b554e6SAlex Lorenz   auto Identifier = Range.upto(C);
187cb268d46SAlex Lorenz   Token = MIToken(getIdentifierKind(Identifier), Identifier);
18891370c5dSAlex Lorenz   return C;
18991370c5dSAlex Lorenz }
19091370c5dSAlex Lorenz 
1916c6c46e4SAlex Lorenz static Cursor maybeLexMachineBasicBlock(
19233f0aef3SAlex Lorenz     Cursor C, MIToken &Token,
19333f0aef3SAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
1946c6c46e4SAlex Lorenz   if (!C.remaining().startswith("%bb."))
1956c6c46e4SAlex Lorenz     return None;
19633f0aef3SAlex Lorenz   auto Range = C;
19733f0aef3SAlex Lorenz   C.advance(4); // Skip '%bb.'
19833f0aef3SAlex Lorenz   if (!isdigit(C.peek())) {
19933f0aef3SAlex Lorenz     Token = MIToken(MIToken::Error, C.remaining());
20033f0aef3SAlex Lorenz     ErrorCallback(C.location(), "expected a number after '%bb.'");
20133f0aef3SAlex Lorenz     return C;
20233f0aef3SAlex Lorenz   }
20333f0aef3SAlex Lorenz   auto NumberRange = C;
20433f0aef3SAlex Lorenz   while (isdigit(C.peek()))
20533f0aef3SAlex Lorenz     C.advance();
20633f0aef3SAlex Lorenz   StringRef Number = NumberRange.upto(C);
20733f0aef3SAlex Lorenz   unsigned StringOffset = 4 + Number.size(); // Drop '%bb.<id>'
20833f0aef3SAlex Lorenz   if (C.peek() == '.') {
20933f0aef3SAlex Lorenz     C.advance(); // Skip '.'
21033f0aef3SAlex Lorenz     ++StringOffset;
21133f0aef3SAlex Lorenz     while (isIdentifierChar(C.peek()))
21233f0aef3SAlex Lorenz       C.advance();
21333f0aef3SAlex Lorenz   }
21433f0aef3SAlex Lorenz   Token = MIToken(MIToken::MachineBasicBlock, Range.upto(C), APSInt(Number),
21533f0aef3SAlex Lorenz                   StringOffset);
21633f0aef3SAlex Lorenz   return C;
21733f0aef3SAlex Lorenz }
21833f0aef3SAlex Lorenz 
21931d70683SAlex Lorenz static Cursor maybeLexIndex(Cursor C, MIToken &Token, StringRef Rule,
22031d70683SAlex Lorenz                             MIToken::TokenKind Kind) {
22131d70683SAlex Lorenz   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
22231d70683SAlex Lorenz     return None;
22331d70683SAlex Lorenz   auto Range = C;
22431d70683SAlex Lorenz   C.advance(Rule.size());
22531d70683SAlex Lorenz   auto NumberRange = C;
22631d70683SAlex Lorenz   while (isdigit(C.peek()))
22731d70683SAlex Lorenz     C.advance();
22831d70683SAlex Lorenz   Token = MIToken(Kind, Range.upto(C), APSInt(NumberRange.upto(C)));
22931d70683SAlex Lorenz   return C;
23031d70683SAlex Lorenz }
23131d70683SAlex Lorenz 
2327feaf7c6SAlex Lorenz static Cursor maybeLexIndexAndName(Cursor C, MIToken &Token, StringRef Rule,
2337feaf7c6SAlex Lorenz                                    MIToken::TokenKind Kind) {
2347feaf7c6SAlex Lorenz   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
2357feaf7c6SAlex Lorenz     return None;
2367feaf7c6SAlex Lorenz   auto Range = C;
2377feaf7c6SAlex Lorenz   C.advance(Rule.size());
2387feaf7c6SAlex Lorenz   auto NumberRange = C;
2397feaf7c6SAlex Lorenz   while (isdigit(C.peek()))
2407feaf7c6SAlex Lorenz     C.advance();
2417feaf7c6SAlex Lorenz   StringRef Number = NumberRange.upto(C);
2427feaf7c6SAlex Lorenz   unsigned StringOffset = Rule.size() + Number.size();
2437feaf7c6SAlex Lorenz   if (C.peek() == '.') {
2447feaf7c6SAlex Lorenz     C.advance();
2457feaf7c6SAlex Lorenz     ++StringOffset;
2467feaf7c6SAlex Lorenz     while (isIdentifierChar(C.peek()))
2477feaf7c6SAlex Lorenz       C.advance();
2487feaf7c6SAlex Lorenz   }
2497feaf7c6SAlex Lorenz   Token = MIToken(Kind, Range.upto(C), APSInt(Number), StringOffset);
2507feaf7c6SAlex Lorenz   return C;
2517feaf7c6SAlex Lorenz }
2527feaf7c6SAlex Lorenz 
25331d70683SAlex Lorenz static Cursor maybeLexJumpTableIndex(Cursor C, MIToken &Token) {
25431d70683SAlex Lorenz   return maybeLexIndex(C, Token, "%jump-table.", MIToken::JumpTableIndex);
25531d70683SAlex Lorenz }
25631d70683SAlex Lorenz 
2577feaf7c6SAlex Lorenz static Cursor maybeLexStackObject(Cursor C, MIToken &Token) {
2587feaf7c6SAlex Lorenz   return maybeLexIndexAndName(C, Token, "%stack.", MIToken::StackObject);
2597feaf7c6SAlex Lorenz }
2607feaf7c6SAlex Lorenz 
2617feaf7c6SAlex Lorenz static Cursor maybeLexFixedStackObject(Cursor C, MIToken &Token) {
2627feaf7c6SAlex Lorenz   return maybeLexIndex(C, Token, "%fixed-stack.", MIToken::FixedStackObject);
2637feaf7c6SAlex Lorenz }
2647feaf7c6SAlex Lorenz 
265ab980499SAlex Lorenz static Cursor maybeLexConstantPoolItem(Cursor C, MIToken &Token) {
266ab980499SAlex Lorenz   return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem);
267ab980499SAlex Lorenz }
268ab980499SAlex Lorenz 
269deb53490SAlex Lorenz static Cursor maybeLexIRBlock(
270deb53490SAlex Lorenz     Cursor C, MIToken &Token,
271deb53490SAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
272deb53490SAlex Lorenz   const StringRef Rule = "%ir-block.";
273deb53490SAlex Lorenz   if (!C.remaining().startswith(Rule))
274deb53490SAlex Lorenz     return None;
275deb53490SAlex Lorenz   if (isdigit(C.peek(Rule.size())))
276deb53490SAlex Lorenz     return maybeLexIndex(C, Token, Rule, MIToken::IRBlock);
277970c12eaSAlex Lorenz   return lexName(C, Token, MIToken::NamedIRBlock, Rule.size(), ErrorCallback);
2788a1915b0SAlex Lorenz }
2798a1915b0SAlex Lorenz 
2804af7e610SAlex Lorenz static Cursor maybeLexIRValue(
2814af7e610SAlex Lorenz     Cursor C, MIToken &Token,
2824af7e610SAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
2834af7e610SAlex Lorenz   const StringRef Rule = "%ir.";
2844af7e610SAlex Lorenz   if (!C.remaining().startswith(Rule))
2854af7e610SAlex Lorenz     return None;
286970c12eaSAlex Lorenz   return lexName(C, Token, MIToken::NamedIRValue, Rule.size(), ErrorCallback);
2874af7e610SAlex Lorenz }
2884af7e610SAlex Lorenz 
28953464510SAlex Lorenz static Cursor lexVirtualRegister(Cursor C, MIToken &Token) {
29053464510SAlex Lorenz   auto Range = C;
29153464510SAlex Lorenz   C.advance(); // Skip '%'
29253464510SAlex Lorenz   auto NumberRange = C;
29353464510SAlex Lorenz   while (isdigit(C.peek()))
29453464510SAlex Lorenz     C.advance();
29553464510SAlex Lorenz   Token = MIToken(MIToken::VirtualRegister, Range.upto(C),
29653464510SAlex Lorenz                   APSInt(NumberRange.upto(C)));
29753464510SAlex Lorenz   return C;
29853464510SAlex Lorenz }
29953464510SAlex Lorenz 
3006c6c46e4SAlex Lorenz static Cursor maybeLexRegister(Cursor C, MIToken &Token) {
3016c6c46e4SAlex Lorenz   if (C.peek() != '%')
3026c6c46e4SAlex Lorenz     return None;
30353464510SAlex Lorenz   if (isdigit(C.peek(1)))
30453464510SAlex Lorenz     return lexVirtualRegister(C, Token);
305f3db51deSAlex Lorenz   auto Range = C;
306f3db51deSAlex Lorenz   C.advance(); // Skip '%'
307f3db51deSAlex Lorenz   while (isIdentifierChar(C.peek()))
308f3db51deSAlex Lorenz     C.advance();
30933f0aef3SAlex Lorenz   Token = MIToken(MIToken::NamedRegister, Range.upto(C),
31033f0aef3SAlex Lorenz                   /*StringOffset=*/1); // Drop the '%'
311f3db51deSAlex Lorenz   return C;
312f3db51deSAlex Lorenz }
313f3db51deSAlex Lorenz 
314c1fbb354SAlex Lorenz static Cursor maybeLexGlobalValue(
315c1fbb354SAlex Lorenz     Cursor C, MIToken &Token,
316c1fbb354SAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
317c1fbb354SAlex Lorenz   if (C.peek() != '@')
318c1fbb354SAlex Lorenz     return None;
319c1fbb354SAlex Lorenz   if (!isdigit(C.peek(1)))
320970c12eaSAlex Lorenz     return lexName(C, Token, MIToken::NamedGlobalValue, /*PrefixLength=*/1,
321c1fbb354SAlex Lorenz                    ErrorCallback);
322c1fbb354SAlex Lorenz   auto Range = C;
323c1fbb354SAlex Lorenz   C.advance(1); // Skip the '@'
324c1fbb354SAlex Lorenz   auto NumberRange = C;
325c1fbb354SAlex Lorenz   while (isdigit(C.peek()))
326c1fbb354SAlex Lorenz     C.advance();
327c1fbb354SAlex Lorenz   Token =
328c1fbb354SAlex Lorenz       MIToken(MIToken::GlobalValue, Range.upto(C), APSInt(NumberRange.upto(C)));
329c1fbb354SAlex Lorenz   return C;
330c1fbb354SAlex Lorenz }
331c1fbb354SAlex Lorenz 
3326ede3744SAlex Lorenz static Cursor maybeLexExternalSymbol(
3336ede3744SAlex Lorenz     Cursor C, MIToken &Token,
3346ede3744SAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
3356ede3744SAlex Lorenz   if (C.peek() != '$')
3366ede3744SAlex Lorenz     return None;
337970c12eaSAlex Lorenz   return lexName(C, Token, MIToken::ExternalSymbol, /*PrefixLength=*/1,
338970c12eaSAlex Lorenz                  ErrorCallback);
3396ede3744SAlex Lorenz }
3406ede3744SAlex Lorenz 
341ad156fb6SAlex Lorenz static bool isValidHexFloatingPointPrefix(char C) {
342ad156fb6SAlex Lorenz   return C == 'H' || C == 'K' || C == 'L' || C == 'M';
343ad156fb6SAlex Lorenz }
344ad156fb6SAlex Lorenz 
345ad156fb6SAlex Lorenz static Cursor maybeLexHexFloatingPointLiteral(Cursor C, MIToken &Token) {
346ad156fb6SAlex Lorenz   if (C.peek() != '0' || C.peek(1) != 'x')
347ad156fb6SAlex Lorenz     return None;
348ad156fb6SAlex Lorenz   Cursor Range = C;
349ad156fb6SAlex Lorenz   C.advance(2); // Skip '0x'
350ad156fb6SAlex Lorenz   if (isValidHexFloatingPointPrefix(C.peek()))
351ad156fb6SAlex Lorenz     C.advance();
352ad156fb6SAlex Lorenz   while (isxdigit(C.peek()))
353ad156fb6SAlex Lorenz     C.advance();
354ad156fb6SAlex Lorenz   Token = MIToken(MIToken::FloatingPointLiteral, Range.upto(C));
355ad156fb6SAlex Lorenz   return C;
356ad156fb6SAlex Lorenz }
357ad156fb6SAlex Lorenz 
358ad156fb6SAlex Lorenz static Cursor lexFloatingPointLiteral(Cursor Range, Cursor C, MIToken &Token) {
359ad156fb6SAlex Lorenz   C.advance();
360ad156fb6SAlex Lorenz   // Skip over [0-9]*([eE][-+]?[0-9]+)?
361ad156fb6SAlex Lorenz   while (isdigit(C.peek()))
362ad156fb6SAlex Lorenz     C.advance();
363ad156fb6SAlex Lorenz   if ((C.peek() == 'e' || C.peek() == 'E') &&
364ad156fb6SAlex Lorenz       (isdigit(C.peek(1)) ||
365ad156fb6SAlex Lorenz        ((C.peek(1) == '-' || C.peek(1) == '+') && isdigit(C.peek(2))))) {
366ad156fb6SAlex Lorenz     C.advance(2);
367ad156fb6SAlex Lorenz     while (isdigit(C.peek()))
368ad156fb6SAlex Lorenz       C.advance();
369ad156fb6SAlex Lorenz   }
370ad156fb6SAlex Lorenz   Token = MIToken(MIToken::FloatingPointLiteral, Range.upto(C));
371ad156fb6SAlex Lorenz   return C;
372ad156fb6SAlex Lorenz }
373ad156fb6SAlex Lorenz 
374ad156fb6SAlex Lorenz static Cursor maybeLexNumericalLiteral(Cursor C, MIToken &Token) {
3756c6c46e4SAlex Lorenz   if (!isdigit(C.peek()) && (C.peek() != '-' || !isdigit(C.peek(1))))
3766c6c46e4SAlex Lorenz     return None;
377240fc1e0SAlex Lorenz   auto Range = C;
378240fc1e0SAlex Lorenz   C.advance();
379240fc1e0SAlex Lorenz   while (isdigit(C.peek()))
380240fc1e0SAlex Lorenz     C.advance();
381ad156fb6SAlex Lorenz   if (C.peek() == '.')
382ad156fb6SAlex Lorenz     return lexFloatingPointLiteral(Range, C, Token);
383240fc1e0SAlex Lorenz   StringRef StrVal = Range.upto(C);
384240fc1e0SAlex Lorenz   Token = MIToken(MIToken::IntegerLiteral, StrVal, APSInt(StrVal));
385240fc1e0SAlex Lorenz   return C;
386240fc1e0SAlex Lorenz }
387240fc1e0SAlex Lorenz 
388f3db51deSAlex Lorenz static MIToken::TokenKind symbolToken(char C) {
389f3db51deSAlex Lorenz   switch (C) {
390f3db51deSAlex Lorenz   case ',':
391f3db51deSAlex Lorenz     return MIToken::comma;
392f3db51deSAlex Lorenz   case '=':
393f3db51deSAlex Lorenz     return MIToken::equal;
3942eacca86SAlex Lorenz   case ':':
3952eacca86SAlex Lorenz     return MIToken::colon;
39635e44469SAlex Lorenz   case '!':
39735e44469SAlex Lorenz     return MIToken::exclaim;
398deb53490SAlex Lorenz   case '(':
399deb53490SAlex Lorenz     return MIToken::lparen;
400deb53490SAlex Lorenz   case ')':
401deb53490SAlex Lorenz     return MIToken::rparen;
402f3db51deSAlex Lorenz   default:
403f3db51deSAlex Lorenz     return MIToken::Error;
404f3db51deSAlex Lorenz   }
405f3db51deSAlex Lorenz }
406f3db51deSAlex Lorenz 
4076c6c46e4SAlex Lorenz static Cursor maybeLexSymbol(Cursor C, MIToken &Token) {
4084af7e610SAlex Lorenz   MIToken::TokenKind Kind;
4094af7e610SAlex Lorenz   unsigned Length = 1;
4104af7e610SAlex Lorenz   if (C.peek() == ':' && C.peek(1) == ':') {
4114af7e610SAlex Lorenz     Kind = MIToken::coloncolon;
4124af7e610SAlex Lorenz     Length = 2;
4134af7e610SAlex Lorenz   } else
4144af7e610SAlex Lorenz     Kind = symbolToken(C.peek());
4156c6c46e4SAlex Lorenz   if (Kind == MIToken::Error)
4166c6c46e4SAlex Lorenz     return None;
417f3db51deSAlex Lorenz   auto Range = C;
4184af7e610SAlex Lorenz   C.advance(Length);
419f3db51deSAlex Lorenz   Token = MIToken(Kind, Range.upto(C));
420f3db51deSAlex Lorenz   return C;
421f3db51deSAlex Lorenz }
422f3db51deSAlex Lorenz 
42391370c5dSAlex Lorenz StringRef llvm::lexMIToken(
42491370c5dSAlex Lorenz     StringRef Source, MIToken &Token,
42591370c5dSAlex Lorenz     function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) {
42691370c5dSAlex Lorenz   auto C = skipWhitespace(Cursor(Source));
42791370c5dSAlex Lorenz   if (C.isEOF()) {
42891370c5dSAlex Lorenz     Token = MIToken(MIToken::Eof, C.remaining());
42991370c5dSAlex Lorenz     return C.remaining();
43091370c5dSAlex Lorenz   }
43191370c5dSAlex Lorenz 
432*05e3882eSAlex Lorenz   if (Cursor R = maybeLexIntegerType(C, Token))
433*05e3882eSAlex Lorenz     return R.remaining();
4346c6c46e4SAlex Lorenz   if (Cursor R = maybeLexIdentifier(C, Token))
4356c6c46e4SAlex Lorenz     return R.remaining();
4366c6c46e4SAlex Lorenz   if (Cursor R = maybeLexMachineBasicBlock(C, Token, ErrorCallback))
4376c6c46e4SAlex Lorenz     return R.remaining();
43831d70683SAlex Lorenz   if (Cursor R = maybeLexJumpTableIndex(C, Token))
43931d70683SAlex Lorenz     return R.remaining();
4407feaf7c6SAlex Lorenz   if (Cursor R = maybeLexStackObject(C, Token))
4417feaf7c6SAlex Lorenz     return R.remaining();
4427feaf7c6SAlex Lorenz   if (Cursor R = maybeLexFixedStackObject(C, Token))
4437feaf7c6SAlex Lorenz     return R.remaining();
444ab980499SAlex Lorenz   if (Cursor R = maybeLexConstantPoolItem(C, Token))
445ab980499SAlex Lorenz     return R.remaining();
446deb53490SAlex Lorenz   if (Cursor R = maybeLexIRBlock(C, Token, ErrorCallback))
4478a1915b0SAlex Lorenz     return R.remaining();
4484af7e610SAlex Lorenz   if (Cursor R = maybeLexIRValue(C, Token, ErrorCallback))
4494af7e610SAlex Lorenz     return R.remaining();
4506c6c46e4SAlex Lorenz   if (Cursor R = maybeLexRegister(C, Token))
4516c6c46e4SAlex Lorenz     return R.remaining();
452b29554daSAlex Lorenz   if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback))
4536c6c46e4SAlex Lorenz     return R.remaining();
4546ede3744SAlex Lorenz   if (Cursor R = maybeLexExternalSymbol(C, Token, ErrorCallback))
4556ede3744SAlex Lorenz     return R.remaining();
456ad156fb6SAlex Lorenz   if (Cursor R = maybeLexHexFloatingPointLiteral(C, Token))
457ad156fb6SAlex Lorenz     return R.remaining();
458ad156fb6SAlex Lorenz   if (Cursor R = maybeLexNumericalLiteral(C, Token))
4596c6c46e4SAlex Lorenz     return R.remaining();
4606c6c46e4SAlex Lorenz   if (Cursor R = maybeLexSymbol(C, Token))
4616c6c46e4SAlex Lorenz     return R.remaining();
4626c6c46e4SAlex Lorenz 
46391370c5dSAlex Lorenz   Token = MIToken(MIToken::Error, C.remaining());
46491370c5dSAlex Lorenz   ErrorCallback(C.location(),
4656c6c46e4SAlex Lorenz                 Twine("unexpected character '") + Twine(C.peek()) + "'");
46691370c5dSAlex Lorenz   return C.remaining();
46791370c5dSAlex Lorenz }
468