1fa57bd0cSEugene Zelenko //===- MILexer.cpp - Machine instructions lexer implementation ------------===//
291370c5dSAlex Lorenz //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
691370c5dSAlex Lorenz //
791370c5dSAlex Lorenz //===----------------------------------------------------------------------===//
891370c5dSAlex Lorenz //
991370c5dSAlex Lorenz // This file implements the lexing of machine instructions.
1091370c5dSAlex Lorenz //
1191370c5dSAlex Lorenz //===----------------------------------------------------------------------===//
1291370c5dSAlex Lorenz 
1391370c5dSAlex Lorenz #include "MILexer.h"
1447b292d3SMehdi Amini #include "llvm/ADT/None.h"
15b29554daSAlex Lorenz #include "llvm/ADT/StringExtras.h"
16cb268d46SAlex Lorenz #include "llvm/ADT/StringSwitch.h"
1791370c5dSAlex Lorenz #include "llvm/ADT/Twine.h"
18fa57bd0cSEugene Zelenko #include <cassert>
1991370c5dSAlex Lorenz #include <cctype>
20fa57bd0cSEugene Zelenko #include <string>
2191370c5dSAlex Lorenz 
2291370c5dSAlex Lorenz using namespace llvm;
2391370c5dSAlex Lorenz 
2491370c5dSAlex Lorenz namespace {
2591370c5dSAlex Lorenz 
26fa57bd0cSEugene Zelenko using ErrorCallbackType =
27fa57bd0cSEugene Zelenko     function_ref<void(StringRef::iterator Loc, const Twine &)>;
280d208fc9SMatthias Braun 
2991370c5dSAlex Lorenz /// This class provides a way to iterate and get characters from the source
3091370c5dSAlex Lorenz /// string.
3191370c5dSAlex Lorenz class Cursor {
32fa57bd0cSEugene Zelenko   const char *Ptr = nullptr;
33fa57bd0cSEugene Zelenko   const char *End = nullptr;
3491370c5dSAlex Lorenz 
3591370c5dSAlex Lorenz public:
Cursor(NoneType)36fa57bd0cSEugene Zelenko   Cursor(NoneType) {}
376c6c46e4SAlex Lorenz 
Cursor(StringRef Str)3891370c5dSAlex Lorenz   explicit Cursor(StringRef Str) {
3991370c5dSAlex Lorenz     Ptr = Str.data();
4091370c5dSAlex Lorenz     End = Ptr + Str.size();
4191370c5dSAlex Lorenz   }
4291370c5dSAlex Lorenz 
isEOF() const4391370c5dSAlex Lorenz   bool isEOF() const { return Ptr == End; }
4491370c5dSAlex Lorenz 
peek(int I=0) const45c267b5f5SNAKAMURA Takumi   char peek(int I = 0) const { return End - Ptr <= I ? 0 : Ptr[I]; }
4691370c5dSAlex Lorenz 
advance(unsigned I=1)4733f0aef3SAlex Lorenz   void advance(unsigned I = 1) { Ptr += I; }
4891370c5dSAlex Lorenz 
remaining() const4991370c5dSAlex Lorenz   StringRef remaining() const { return StringRef(Ptr, End - Ptr); }
5091370c5dSAlex Lorenz 
upto(Cursor C) const5191370c5dSAlex Lorenz   StringRef upto(Cursor C) const {
5291370c5dSAlex Lorenz     assert(C.Ptr >= Ptr && C.Ptr <= End);
5391370c5dSAlex Lorenz     return StringRef(Ptr, C.Ptr - Ptr);
5491370c5dSAlex Lorenz   }
5591370c5dSAlex Lorenz 
location() const5691370c5dSAlex Lorenz   StringRef::iterator location() const { return Ptr; }
576c6c46e4SAlex Lorenz 
operator bool() const586c6c46e4SAlex Lorenz   operator bool() const { return Ptr != nullptr; }
5991370c5dSAlex Lorenz };
6091370c5dSAlex Lorenz 
6191370c5dSAlex Lorenz } // end anonymous namespace
6291370c5dSAlex Lorenz 
reset(TokenKind Kind,StringRef Range)633fb77686SAlex Lorenz MIToken &MIToken::reset(TokenKind Kind, StringRef Range) {
643fb77686SAlex Lorenz   this->Kind = Kind;
653fb77686SAlex Lorenz   this->Range = Range;
663fb77686SAlex Lorenz   return *this;
673fb77686SAlex Lorenz }
683fb77686SAlex Lorenz 
setStringValue(StringRef StrVal)693fb77686SAlex Lorenz MIToken &MIToken::setStringValue(StringRef StrVal) {
703fb77686SAlex Lorenz   StringValue = StrVal;
713fb77686SAlex Lorenz   return *this;
723fb77686SAlex Lorenz }
733fb77686SAlex Lorenz 
setOwnedStringValue(std::string StrVal)743fb77686SAlex Lorenz MIToken &MIToken::setOwnedStringValue(std::string StrVal) {
753fb77686SAlex Lorenz   StringValueStorage = std::move(StrVal);
763fb77686SAlex Lorenz   StringValue = StringValueStorage;
773fb77686SAlex Lorenz   return *this;
783fb77686SAlex Lorenz }
793fb77686SAlex Lorenz 
setIntegerValue(APSInt IntVal)803fb77686SAlex Lorenz MIToken &MIToken::setIntegerValue(APSInt IntVal) {
813fb77686SAlex Lorenz   this->IntVal = std::move(IntVal);
823fb77686SAlex Lorenz   return *this;
833fb77686SAlex Lorenz }
843fb77686SAlex Lorenz 
8591370c5dSAlex Lorenz /// Skip the leading whitespace characters and return the updated cursor.
skipWhitespace(Cursor C)8691370c5dSAlex Lorenz static Cursor skipWhitespace(Cursor C) {
875022f6bbSAlex Lorenz   while (isblank(C.peek()))
885022f6bbSAlex Lorenz     C.advance();
895022f6bbSAlex Lorenz   return C;
905022f6bbSAlex Lorenz }
915022f6bbSAlex Lorenz 
isNewlineChar(char C)925022f6bbSAlex Lorenz static bool isNewlineChar(char C) { return C == '\n' || C == '\r'; }
935022f6bbSAlex Lorenz 
945022f6bbSAlex Lorenz /// Skip a line comment and return the updated cursor.
skipComment(Cursor C)955022f6bbSAlex Lorenz static Cursor skipComment(Cursor C) {
965022f6bbSAlex Lorenz   if (C.peek() != ';')
975022f6bbSAlex Lorenz     return C;
985022f6bbSAlex Lorenz   while (!isNewlineChar(C.peek()) && !C.isEOF())
9991370c5dSAlex Lorenz     C.advance();
10091370c5dSAlex Lorenz   return C;
10191370c5dSAlex Lorenz }
10291370c5dSAlex Lorenz 
1037efabe5cSSjoerd Meijer /// Machine operands can have comments, enclosed between /* and */.
1047efabe5cSSjoerd Meijer /// This eats up all tokens, including /* and */.
skipMachineOperandComment(Cursor C)1057efabe5cSSjoerd Meijer static Cursor skipMachineOperandComment(Cursor C) {
1067efabe5cSSjoerd Meijer   if (C.peek() != '/' || C.peek(1) != '*')
1077efabe5cSSjoerd Meijer     return C;
1087efabe5cSSjoerd Meijer 
1097efabe5cSSjoerd Meijer   while (C.peek() != '*' || C.peek(1) != '/')
1107efabe5cSSjoerd Meijer     C.advance();
1117efabe5cSSjoerd Meijer 
1127efabe5cSSjoerd Meijer   C.advance();
1137efabe5cSSjoerd Meijer   C.advance();
1147efabe5cSSjoerd Meijer   return C;
1157efabe5cSSjoerd Meijer }
1167efabe5cSSjoerd Meijer 
117484903ecSAlex Lorenz /// Return true if the given character satisfies the following regular
118484903ecSAlex Lorenz /// expression: [-a-zA-Z$._0-9]
isIdentifierChar(char C)11991370c5dSAlex Lorenz static bool isIdentifierChar(char C) {
120484903ecSAlex Lorenz   return isalpha(C) || isdigit(C) || C == '_' || C == '-' || C == '.' ||
121484903ecSAlex Lorenz          C == '$';
12291370c5dSAlex Lorenz }
12391370c5dSAlex Lorenz 
124970c12eaSAlex Lorenz /// Unescapes the given string value.
125970c12eaSAlex Lorenz ///
126970c12eaSAlex Lorenz /// Expects the string value to be quoted.
unescapeQuotedString(StringRef Value)127970c12eaSAlex Lorenz static std::string unescapeQuotedString(StringRef Value) {
128b29554daSAlex Lorenz   assert(Value.front() == '"' && Value.back() == '"');
129b29554daSAlex Lorenz   Cursor C = Cursor(Value.substr(1, Value.size() - 2));
130b29554daSAlex Lorenz 
131970c12eaSAlex Lorenz   std::string Str;
132b29554daSAlex Lorenz   Str.reserve(C.remaining().size());
133b29554daSAlex Lorenz   while (!C.isEOF()) {
134b29554daSAlex Lorenz     char Char = C.peek();
135b29554daSAlex Lorenz     if (Char == '\\') {
136b29554daSAlex Lorenz       if (C.peek(1) == '\\') {
137b29554daSAlex Lorenz         // Two '\' become one
138b29554daSAlex Lorenz         Str += '\\';
139b29554daSAlex Lorenz         C.advance(2);
140b29554daSAlex Lorenz         continue;
141b29554daSAlex Lorenz       }
142b29554daSAlex Lorenz       if (isxdigit(C.peek(1)) && isxdigit(C.peek(2))) {
143b29554daSAlex Lorenz         Str += hexDigitValue(C.peek(1)) * 16 + hexDigitValue(C.peek(2));
144b29554daSAlex Lorenz         C.advance(3);
145b29554daSAlex Lorenz         continue;
146b29554daSAlex Lorenz       }
147b29554daSAlex Lorenz     }
148b29554daSAlex Lorenz     Str += Char;
149b29554daSAlex Lorenz     C.advance();
150b29554daSAlex Lorenz   }
151970c12eaSAlex Lorenz   return Str;
152b29554daSAlex Lorenz }
153b29554daSAlex Lorenz 
154b29554daSAlex Lorenz /// Lex a string constant using the following regular expression: \"[^\"]*\"
lexStringConstant(Cursor C,ErrorCallbackType ErrorCallback)1550d208fc9SMatthias Braun static Cursor lexStringConstant(Cursor C, ErrorCallbackType ErrorCallback) {
156b29554daSAlex Lorenz   assert(C.peek() == '"');
157b29554daSAlex Lorenz   for (C.advance(); C.peek() != '"'; C.advance()) {
1585022f6bbSAlex Lorenz     if (C.isEOF() || isNewlineChar(C.peek())) {
159b29554daSAlex Lorenz       ErrorCallback(
160b29554daSAlex Lorenz           C.location(),
161b29554daSAlex Lorenz           "end of machine instruction reached before the closing '\"'");
162b29554daSAlex Lorenz       return None;
163b29554daSAlex Lorenz     }
164b29554daSAlex Lorenz   }
165b29554daSAlex Lorenz   C.advance();
166b29554daSAlex Lorenz   return C;
167b29554daSAlex Lorenz }
168b29554daSAlex Lorenz 
lexName(Cursor C,MIToken & Token,MIToken::TokenKind Type,unsigned PrefixLength,ErrorCallbackType ErrorCallback)1690d208fc9SMatthias Braun static Cursor lexName(Cursor C, MIToken &Token, MIToken::TokenKind Type,
1700d208fc9SMatthias Braun                       unsigned PrefixLength, ErrorCallbackType ErrorCallback) {
17182a1cfdcSAlex Lorenz   auto Range = C;
17282a1cfdcSAlex Lorenz   C.advance(PrefixLength);
17382a1cfdcSAlex Lorenz   if (C.peek() == '"') {
17482a1cfdcSAlex Lorenz     if (Cursor R = lexStringConstant(C, ErrorCallback)) {
175970c12eaSAlex Lorenz       StringRef String = Range.upto(R);
1763fb77686SAlex Lorenz       Token.reset(Type, String)
1773fb77686SAlex Lorenz           .setOwnedStringValue(
1783fb77686SAlex Lorenz               unescapeQuotedString(String.drop_front(PrefixLength)));
17982a1cfdcSAlex Lorenz       return R;
18082a1cfdcSAlex Lorenz     }
1813fb77686SAlex Lorenz     Token.reset(MIToken::Error, Range.remaining());
18282a1cfdcSAlex Lorenz     return Range;
18382a1cfdcSAlex Lorenz   }
18482a1cfdcSAlex Lorenz   while (isIdentifierChar(C.peek()))
18582a1cfdcSAlex Lorenz     C.advance();
1863fb77686SAlex Lorenz   Token.reset(Type, Range.upto(C))
1873fb77686SAlex Lorenz       .setStringValue(Range.upto(C).drop_front(PrefixLength));
18882a1cfdcSAlex Lorenz   return C;
18982a1cfdcSAlex Lorenz }
19082a1cfdcSAlex Lorenz 
getIdentifierKind(StringRef Identifier)191cb268d46SAlex Lorenz static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
192cb268d46SAlex Lorenz   return StringSwitch<MIToken::TokenKind>(Identifier)
193cb268d46SAlex Lorenz       .Case("_", MIToken::underscore)
194cb268d46SAlex Lorenz       .Case("implicit", MIToken::kw_implicit)
195cb268d46SAlex Lorenz       .Case("implicit-def", MIToken::kw_implicit_define)
196e66a7ccfSAlex Lorenz       .Case("def", MIToken::kw_def)
197cbbfd0b1SAlex Lorenz       .Case("dead", MIToken::kw_dead)
198495ad879SAlex Lorenz       .Case("killed", MIToken::kw_killed)
1994d026b89SAlex Lorenz       .Case("undef", MIToken::kw_undef)
2001039fd1aSAlex Lorenz       .Case("internal", MIToken::kw_internal)
20101c1a5eeSAlex Lorenz       .Case("early-clobber", MIToken::kw_early_clobber)
2029075258bSAlex Lorenz       .Case("debug-use", MIToken::kw_debug_use)
20360c43102SGeoff Berry       .Case("renamable", MIToken::kw_renamable)
2045ef93b0cSAlex Lorenz       .Case("tied-def", MIToken::kw_tied_def)
205e5a44660SAlex Lorenz       .Case("frame-setup", MIToken::kw_frame_setup)
206dbf2c48fSFrancis Visoiu Mistrih       .Case("frame-destroy", MIToken::kw_frame_destroy)
2077d1b25d0SMichael Berg       .Case("nnan", MIToken::kw_nnan)
2087d1b25d0SMichael Berg       .Case("ninf", MIToken::kw_ninf)
2097d1b25d0SMichael Berg       .Case("nsz", MIToken::kw_nsz)
2107d1b25d0SMichael Berg       .Case("arcp", MIToken::kw_arcp)
2117d1b25d0SMichael Berg       .Case("contract", MIToken::kw_contract)
2127d1b25d0SMichael Berg       .Case("afn", MIToken::kw_afn)
2137d1b25d0SMichael Berg       .Case("reassoc", MIToken::kw_reassoc)
214c72a7259SMichael Berg       .Case("nuw", MIToken::kw_nuw)
215c72a7259SMichael Berg       .Case("nsw", MIToken::kw_nsw)
216c72a7259SMichael Berg       .Case("exact", MIToken::kw_exact)
217f0fd11dfSUlrich Weigand       .Case("nofpexcept", MIToken::kw_nofpexcept)
21846d760d1SAlex Lorenz       .Case("debug-location", MIToken::kw_debug_location)
2192c5f3d54SJeremy Morse       .Case("debug-instr-number", MIToken::kw_debug_instr_number)
220ee067920SMatthias Braun       .Case("same_value", MIToken::kw_cfi_same_value)
221ee067920SMatthias Braun       .Case("offset", MIToken::kw_cfi_offset)
2225de20e03SFrancis Visoiu Mistrih       .Case("rel_offset", MIToken::kw_cfi_rel_offset)
223ee067920SMatthias Braun       .Case("def_cfa_register", MIToken::kw_cfi_def_cfa_register)
224ee067920SMatthias Braun       .Case("def_cfa_offset", MIToken::kw_cfi_def_cfa_offset)
2255de20e03SFrancis Visoiu Mistrih       .Case("adjust_cfa_offset", MIToken::kw_cfi_adjust_cfa_offset)
2265de20e03SFrancis Visoiu Mistrih       .Case("escape", MIToken::kw_cfi_escape)
227ee067920SMatthias Braun       .Case("def_cfa", MIToken::kw_cfi_def_cfa)
228167e7afcSRamNalamothu       .Case("llvm_def_aspace_cfa", MIToken::kw_cfi_llvm_def_aspace_cfa)
2295de20e03SFrancis Visoiu Mistrih       .Case("remember_state", MIToken::kw_cfi_remember_state)
23066d2c269SFrancis Visoiu Mistrih       .Case("restore", MIToken::kw_cfi_restore)
2315de20e03SFrancis Visoiu Mistrih       .Case("restore_state", MIToken::kw_cfi_restore_state)
2325de20e03SFrancis Visoiu Mistrih       .Case("undefined", MIToken::kw_cfi_undefined)
2335de20e03SFrancis Visoiu Mistrih       .Case("register", MIToken::kw_cfi_register)
2345de20e03SFrancis Visoiu Mistrih       .Case("window_save", MIToken::kw_cfi_window_save)
2354a98cf78SScott Linder       .Case("negate_ra_sign_state",
2364a98cf78SScott Linder             MIToken::kw_cfi_aarch64_negate_ra_sign_state)
237deb53490SAlex Lorenz       .Case("blockaddress", MIToken::kw_blockaddress)
2386b3bd612STim Northover       .Case("intrinsic", MIToken::kw_intrinsic)
239ef5c196fSAlex Lorenz       .Case("target-index", MIToken::kw_target_index)
240ad156fb6SAlex Lorenz       .Case("half", MIToken::kw_half)
241ad156fb6SAlex Lorenz       .Case("float", MIToken::kw_float)
242ad156fb6SAlex Lorenz       .Case("double", MIToken::kw_double)
243ad156fb6SAlex Lorenz       .Case("x86_fp80", MIToken::kw_x86_fp80)
244ad156fb6SAlex Lorenz       .Case("fp128", MIToken::kw_fp128)
245ad156fb6SAlex Lorenz       .Case("ppc_fp128", MIToken::kw_ppc_fp128)
24649873a83SAlex Lorenz       .Case("target-flags", MIToken::kw_target_flags)
247a518b796SAlex Lorenz       .Case("volatile", MIToken::kw_volatile)
24810fd0385SAlex Lorenz       .Case("non-temporal", MIToken::kw_non_temporal)
249adbf09e8SJustin Lebar       .Case("dereferenceable", MIToken::kw_dereferenceable)
250dc8de2a6SAlex Lorenz       .Case("invariant", MIToken::kw_invariant)
25161420f79SAlex Lorenz       .Case("align", MIToken::kw_align)
252*719bac55SJay Foad       .Case("basealign", MIToken::kw_basealign)
253e4718e84SFrancis Visoiu Mistrih       .Case("addrspace", MIToken::kw_addrspace)
25446e9558aSAlex Lorenz       .Case("stack", MIToken::kw_stack)
255d858f874SAlex Lorenz       .Case("got", MIToken::kw_got)
2564be56e93SAlex Lorenz       .Case("jump-table", MIToken::kw_jump_table)
25791097a3fSAlex Lorenz       .Case("constant-pool", MIToken::kw_constant_pool)
2580d009645SAlex Lorenz       .Case("call-entry", MIToken::kw_call_entry)
259de3d0ee0SDaniel Sanders       .Case("custom", MIToken::kw_custom)
260b97c9ef4SAlex Lorenz       .Case("liveout", MIToken::kw_liveout)
2615022f6bbSAlex Lorenz       .Case("address-taken", MIToken::kw_address_taken)
2625022f6bbSAlex Lorenz       .Case("landing-pad", MIToken::kw_landing_pad)
263548b01c7SJay Foad       .Case("inlineasm-br-indirect-target",
264548b01c7SJay Foad             MIToken::kw_inlineasm_br_indirect_target)
2655ff5ddd0SReid Kleckner       .Case("ehfunclet-entry", MIToken::kw_ehfunclet_entry)
2665022f6bbSAlex Lorenz       .Case("liveins", MIToken::kw_liveins)
2675022f6bbSAlex Lorenz       .Case("successors", MIToken::kw_successors)
268de3aea04STim Northover       .Case("floatpred", MIToken::kw_floatpred)
269de3aea04STim Northover       .Case("intpred", MIToken::kw_intpred)
2705af9cf04SMatt Arsenault       .Case("shufflemask", MIToken::kw_shufflemask)
27175ca6be1SChandler Carruth       .Case("pre-instr-symbol", MIToken::kw_pre_instr_symbol)
27275ca6be1SChandler Carruth       .Case("post-instr-symbol", MIToken::kw_post_instr_symbol)
273a078c77dSAmy Huang       .Case("heap-alloc-marker", MIToken::kw_heap_alloc_marker)
274df082ac4SSriraman Tallam       .Case("bbsections", MIToken::kw_bbsections)
275cc3f6302SKrzysztof Parzyszek       .Case("unknown-size", MIToken::kw_unknown_size)
276134a179dSDaniel Sanders       .Case("unknown-address", MIToken::kw_unknown_address)
277e818efacSMichael Liao       .Case("distinct", MIToken::kw_distinct)
278cb268d46SAlex Lorenz       .Default(MIToken::Identifier);
279cb268d46SAlex Lorenz }
280cb268d46SAlex Lorenz 
maybeLexIdentifier(Cursor C,MIToken & Token)2816c6c46e4SAlex Lorenz static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) {
282333e468dSMatthias Braun   if (!isalpha(C.peek()) && C.peek() != '_')
2836c6c46e4SAlex Lorenz     return None;
28491370c5dSAlex Lorenz   auto Range = C;
28591370c5dSAlex Lorenz   while (isIdentifierChar(C.peek()))
28691370c5dSAlex Lorenz     C.advance();
28712b554e6SAlex Lorenz   auto Identifier = Range.upto(C);
2883fb77686SAlex Lorenz   Token.reset(getIdentifierKind(Identifier), Identifier)
2893fb77686SAlex Lorenz       .setStringValue(Identifier);
29091370c5dSAlex Lorenz   return C;
29191370c5dSAlex Lorenz }
29291370c5dSAlex Lorenz 
maybeLexMachineBasicBlock(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)2930d208fc9SMatthias Braun static Cursor maybeLexMachineBasicBlock(Cursor C, MIToken &Token,
2940d208fc9SMatthias Braun                                         ErrorCallbackType ErrorCallback) {
2955022f6bbSAlex Lorenz   bool IsReference = C.remaining().startswith("%bb.");
2965022f6bbSAlex Lorenz   if (!IsReference && !C.remaining().startswith("bb."))
2976c6c46e4SAlex Lorenz     return None;
29833f0aef3SAlex Lorenz   auto Range = C;
2995022f6bbSAlex Lorenz   unsigned PrefixLength = IsReference ? 4 : 3;
3005022f6bbSAlex Lorenz   C.advance(PrefixLength); // Skip '%bb.' or 'bb.'
30133f0aef3SAlex Lorenz   if (!isdigit(C.peek())) {
3023fb77686SAlex Lorenz     Token.reset(MIToken::Error, C.remaining());
30333f0aef3SAlex Lorenz     ErrorCallback(C.location(), "expected a number after '%bb.'");
30433f0aef3SAlex Lorenz     return C;
30533f0aef3SAlex Lorenz   }
30633f0aef3SAlex Lorenz   auto NumberRange = C;
30733f0aef3SAlex Lorenz   while (isdigit(C.peek()))
30833f0aef3SAlex Lorenz     C.advance();
30933f0aef3SAlex Lorenz   StringRef Number = NumberRange.upto(C);
3105022f6bbSAlex Lorenz   unsigned StringOffset = PrefixLength + Number.size(); // Drop '%bb.<id>'
31125528d6dSFrancis Visoiu Mistrih   // TODO: The format bb.<id>.<irname> is supported only when it's not a
31225528d6dSFrancis Visoiu Mistrih   // reference. Once we deprecate the format where the irname shows up, we
31325528d6dSFrancis Visoiu Mistrih   // should only lex forward if it is a reference.
31433f0aef3SAlex Lorenz   if (C.peek() == '.') {
31533f0aef3SAlex Lorenz     C.advance(); // Skip '.'
31633f0aef3SAlex Lorenz     ++StringOffset;
31733f0aef3SAlex Lorenz     while (isIdentifierChar(C.peek()))
31833f0aef3SAlex Lorenz       C.advance();
31933f0aef3SAlex Lorenz   }
3205022f6bbSAlex Lorenz   Token.reset(IsReference ? MIToken::MachineBasicBlock
3215022f6bbSAlex Lorenz                           : MIToken::MachineBasicBlockLabel,
3225022f6bbSAlex Lorenz               Range.upto(C))
3233fb77686SAlex Lorenz       .setIntegerValue(APSInt(Number))
3243fb77686SAlex Lorenz       .setStringValue(Range.upto(C).drop_front(StringOffset));
32533f0aef3SAlex Lorenz   return C;
32633f0aef3SAlex Lorenz }
32733f0aef3SAlex Lorenz 
maybeLexIndex(Cursor C,MIToken & Token,StringRef Rule,MIToken::TokenKind Kind)32831d70683SAlex Lorenz static Cursor maybeLexIndex(Cursor C, MIToken &Token, StringRef Rule,
32931d70683SAlex Lorenz                             MIToken::TokenKind Kind) {
33031d70683SAlex Lorenz   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
33131d70683SAlex Lorenz     return None;
33231d70683SAlex Lorenz   auto Range = C;
33331d70683SAlex Lorenz   C.advance(Rule.size());
33431d70683SAlex Lorenz   auto NumberRange = C;
33531d70683SAlex Lorenz   while (isdigit(C.peek()))
33631d70683SAlex Lorenz     C.advance();
3373fb77686SAlex Lorenz   Token.reset(Kind, Range.upto(C)).setIntegerValue(APSInt(NumberRange.upto(C)));
33831d70683SAlex Lorenz   return C;
33931d70683SAlex Lorenz }
34031d70683SAlex Lorenz 
maybeLexIndexAndName(Cursor C,MIToken & Token,StringRef Rule,MIToken::TokenKind Kind)3417feaf7c6SAlex Lorenz static Cursor maybeLexIndexAndName(Cursor C, MIToken &Token, StringRef Rule,
3427feaf7c6SAlex Lorenz                                    MIToken::TokenKind Kind) {
3437feaf7c6SAlex Lorenz   if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size())))
3447feaf7c6SAlex Lorenz     return None;
3457feaf7c6SAlex Lorenz   auto Range = C;
3467feaf7c6SAlex Lorenz   C.advance(Rule.size());
3477feaf7c6SAlex Lorenz   auto NumberRange = C;
3487feaf7c6SAlex Lorenz   while (isdigit(C.peek()))
3497feaf7c6SAlex Lorenz     C.advance();
3507feaf7c6SAlex Lorenz   StringRef Number = NumberRange.upto(C);
3517feaf7c6SAlex Lorenz   unsigned StringOffset = Rule.size() + Number.size();
3527feaf7c6SAlex Lorenz   if (C.peek() == '.') {
3537feaf7c6SAlex Lorenz     C.advance();
3547feaf7c6SAlex Lorenz     ++StringOffset;
3557feaf7c6SAlex Lorenz     while (isIdentifierChar(C.peek()))
3567feaf7c6SAlex Lorenz       C.advance();
3577feaf7c6SAlex Lorenz   }
3583fb77686SAlex Lorenz   Token.reset(Kind, Range.upto(C))
3593fb77686SAlex Lorenz       .setIntegerValue(APSInt(Number))
3603fb77686SAlex Lorenz       .setStringValue(Range.upto(C).drop_front(StringOffset));
3617feaf7c6SAlex Lorenz   return C;
3627feaf7c6SAlex Lorenz }
3637feaf7c6SAlex Lorenz 
maybeLexJumpTableIndex(Cursor C,MIToken & Token)36431d70683SAlex Lorenz static Cursor maybeLexJumpTableIndex(Cursor C, MIToken &Token) {
36531d70683SAlex Lorenz   return maybeLexIndex(C, Token, "%jump-table.", MIToken::JumpTableIndex);
36631d70683SAlex Lorenz }
36731d70683SAlex Lorenz 
maybeLexStackObject(Cursor C,MIToken & Token)3687feaf7c6SAlex Lorenz static Cursor maybeLexStackObject(Cursor C, MIToken &Token) {
3697feaf7c6SAlex Lorenz   return maybeLexIndexAndName(C, Token, "%stack.", MIToken::StackObject);
3707feaf7c6SAlex Lorenz }
3717feaf7c6SAlex Lorenz 
maybeLexFixedStackObject(Cursor C,MIToken & Token)3727feaf7c6SAlex Lorenz static Cursor maybeLexFixedStackObject(Cursor C, MIToken &Token) {
3737feaf7c6SAlex Lorenz   return maybeLexIndex(C, Token, "%fixed-stack.", MIToken::FixedStackObject);
3747feaf7c6SAlex Lorenz }
3757feaf7c6SAlex Lorenz 
maybeLexConstantPoolItem(Cursor C,MIToken & Token)376ab980499SAlex Lorenz static Cursor maybeLexConstantPoolItem(Cursor C, MIToken &Token) {
377ab980499SAlex Lorenz   return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem);
378ab980499SAlex Lorenz }
379ab980499SAlex Lorenz 
maybeLexSubRegisterIndex(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)380b74eb41dSMatthias Braun static Cursor maybeLexSubRegisterIndex(Cursor C, MIToken &Token,
381b74eb41dSMatthias Braun                                        ErrorCallbackType ErrorCallback) {
382b74eb41dSMatthias Braun   const StringRef Rule = "%subreg.";
383b74eb41dSMatthias Braun   if (!C.remaining().startswith(Rule))
384b74eb41dSMatthias Braun     return None;
385b74eb41dSMatthias Braun   return lexName(C, Token, MIToken::SubRegisterIndex, Rule.size(),
386b74eb41dSMatthias Braun                  ErrorCallback);
387b74eb41dSMatthias Braun }
388b74eb41dSMatthias Braun 
maybeLexIRBlock(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)3890d208fc9SMatthias Braun static Cursor maybeLexIRBlock(Cursor C, MIToken &Token,
3900d208fc9SMatthias Braun                               ErrorCallbackType ErrorCallback) {
391deb53490SAlex Lorenz   const StringRef Rule = "%ir-block.";
392deb53490SAlex Lorenz   if (!C.remaining().startswith(Rule))
393deb53490SAlex Lorenz     return None;
394deb53490SAlex Lorenz   if (isdigit(C.peek(Rule.size())))
395deb53490SAlex Lorenz     return maybeLexIndex(C, Token, Rule, MIToken::IRBlock);
396970c12eaSAlex Lorenz   return lexName(C, Token, MIToken::NamedIRBlock, Rule.size(), ErrorCallback);
3978a1915b0SAlex Lorenz }
3988a1915b0SAlex Lorenz 
maybeLexIRValue(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)3990d208fc9SMatthias Braun static Cursor maybeLexIRValue(Cursor C, MIToken &Token,
4000d208fc9SMatthias Braun                               ErrorCallbackType ErrorCallback) {
4014af7e610SAlex Lorenz   const StringRef Rule = "%ir.";
4024af7e610SAlex Lorenz   if (!C.remaining().startswith(Rule))
4034af7e610SAlex Lorenz     return None;
404dd13be0bSAlex Lorenz   if (isdigit(C.peek(Rule.size())))
405dd13be0bSAlex Lorenz     return maybeLexIndex(C, Token, Rule, MIToken::IRValue);
406970c12eaSAlex Lorenz   return lexName(C, Token, MIToken::NamedIRValue, Rule.size(), ErrorCallback);
4074af7e610SAlex Lorenz }
4084af7e610SAlex Lorenz 
maybeLexStringConstant(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)409bb80d3e1SKonstantin Zhuravlyov static Cursor maybeLexStringConstant(Cursor C, MIToken &Token,
410bb80d3e1SKonstantin Zhuravlyov                                      ErrorCallbackType ErrorCallback) {
411bb80d3e1SKonstantin Zhuravlyov   if (C.peek() != '"')
412bb80d3e1SKonstantin Zhuravlyov     return None;
413bb80d3e1SKonstantin Zhuravlyov   return lexName(C, Token, MIToken::StringConstant, /*PrefixLength=*/0,
414bb80d3e1SKonstantin Zhuravlyov                  ErrorCallback);
415bb80d3e1SKonstantin Zhuravlyov }
416bb80d3e1SKonstantin Zhuravlyov 
lexVirtualRegister(Cursor C,MIToken & Token)41753464510SAlex Lorenz static Cursor lexVirtualRegister(Cursor C, MIToken &Token) {
41853464510SAlex Lorenz   auto Range = C;
41953464510SAlex Lorenz   C.advance(); // Skip '%'
42053464510SAlex Lorenz   auto NumberRange = C;
42153464510SAlex Lorenz   while (isdigit(C.peek()))
42253464510SAlex Lorenz     C.advance();
4233fb77686SAlex Lorenz   Token.reset(MIToken::VirtualRegister, Range.upto(C))
4243fb77686SAlex Lorenz       .setIntegerValue(APSInt(NumberRange.upto(C)));
42553464510SAlex Lorenz   return C;
42653464510SAlex Lorenz }
42753464510SAlex Lorenz 
428333e468dSMatthias Braun /// Returns true for a character allowed in a register name.
isRegisterChar(char C)429333e468dSMatthias Braun static bool isRegisterChar(char C) {
430333e468dSMatthias Braun   return isIdentifierChar(C) && C != '.';
431333e468dSMatthias Braun }
432333e468dSMatthias Braun 
lexNamedVirtualRegister(Cursor C,MIToken & Token)433399b46c9SPuyan Lotfi static Cursor lexNamedVirtualRegister(Cursor C, MIToken &Token) {
434399b46c9SPuyan Lotfi   Cursor Range = C;
435399b46c9SPuyan Lotfi   C.advance(); // Skip '%'
436399b46c9SPuyan Lotfi   while (isRegisterChar(C.peek()))
437399b46c9SPuyan Lotfi     C.advance();
438399b46c9SPuyan Lotfi   Token.reset(MIToken::NamedVirtualRegister, Range.upto(C))
439399b46c9SPuyan Lotfi       .setStringValue(Range.upto(C).drop_front(1)); // Drop the '%'
440399b46c9SPuyan Lotfi   return C;
441399b46c9SPuyan Lotfi }
442399b46c9SPuyan Lotfi 
maybeLexRegister(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)44343e94b15SPuyan Lotfi static Cursor maybeLexRegister(Cursor C, MIToken &Token,
44443e94b15SPuyan Lotfi                                ErrorCallbackType ErrorCallback) {
44543e94b15SPuyan Lotfi   if (C.peek() != '%' && C.peek() != '$')
4466c6c46e4SAlex Lorenz     return None;
44743e94b15SPuyan Lotfi 
44843e94b15SPuyan Lotfi   if (C.peek() == '%') {
44953464510SAlex Lorenz     if (isdigit(C.peek(1)))
45053464510SAlex Lorenz       return lexVirtualRegister(C, Token);
45143e94b15SPuyan Lotfi 
452399b46c9SPuyan Lotfi     if (isRegisterChar(C.peek(1)))
453399b46c9SPuyan Lotfi       return lexNamedVirtualRegister(C, Token);
454399b46c9SPuyan Lotfi 
45543e94b15SPuyan Lotfi     return None;
45643e94b15SPuyan Lotfi   }
45743e94b15SPuyan Lotfi 
45843e94b15SPuyan Lotfi   assert(C.peek() == '$');
459f3db51deSAlex Lorenz   auto Range = C;
46043e94b15SPuyan Lotfi   C.advance(); // Skip '$'
461333e468dSMatthias Braun   while (isRegisterChar(C.peek()))
462f3db51deSAlex Lorenz     C.advance();
4633fb77686SAlex Lorenz   Token.reset(MIToken::NamedRegister, Range.upto(C))
46443e94b15SPuyan Lotfi       .setStringValue(Range.upto(C).drop_front(1)); // Drop the '$'
465f3db51deSAlex Lorenz   return C;
466f3db51deSAlex Lorenz }
467f3db51deSAlex Lorenz 
maybeLexGlobalValue(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)4680d208fc9SMatthias Braun static Cursor maybeLexGlobalValue(Cursor C, MIToken &Token,
4690d208fc9SMatthias Braun                                   ErrorCallbackType ErrorCallback) {
470c1fbb354SAlex Lorenz   if (C.peek() != '@')
471c1fbb354SAlex Lorenz     return None;
472c1fbb354SAlex Lorenz   if (!isdigit(C.peek(1)))
473970c12eaSAlex Lorenz     return lexName(C, Token, MIToken::NamedGlobalValue, /*PrefixLength=*/1,
474c1fbb354SAlex Lorenz                    ErrorCallback);
475c1fbb354SAlex Lorenz   auto Range = C;
476c1fbb354SAlex Lorenz   C.advance(1); // Skip the '@'
477c1fbb354SAlex Lorenz   auto NumberRange = C;
478c1fbb354SAlex Lorenz   while (isdigit(C.peek()))
479c1fbb354SAlex Lorenz     C.advance();
4803fb77686SAlex Lorenz   Token.reset(MIToken::GlobalValue, Range.upto(C))
4813fb77686SAlex Lorenz       .setIntegerValue(APSInt(NumberRange.upto(C)));
482c1fbb354SAlex Lorenz   return C;
483c1fbb354SAlex Lorenz }
484c1fbb354SAlex Lorenz 
maybeLexExternalSymbol(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)4850d208fc9SMatthias Braun static Cursor maybeLexExternalSymbol(Cursor C, MIToken &Token,
4860d208fc9SMatthias Braun                                      ErrorCallbackType ErrorCallback) {
487fe6c9cbbSPuyan Lotfi   if (C.peek() != '&')
4886ede3744SAlex Lorenz     return None;
489970c12eaSAlex Lorenz   return lexName(C, Token, MIToken::ExternalSymbol, /*PrefixLength=*/1,
490970c12eaSAlex Lorenz                  ErrorCallback);
4916ede3744SAlex Lorenz }
4926ede3744SAlex Lorenz 
maybeLexMCSymbol(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)49375ca6be1SChandler Carruth static Cursor maybeLexMCSymbol(Cursor C, MIToken &Token,
49475ca6be1SChandler Carruth                                ErrorCallbackType ErrorCallback) {
49575ca6be1SChandler Carruth   const StringRef Rule = "<mcsymbol ";
49675ca6be1SChandler Carruth   if (!C.remaining().startswith(Rule))
49775ca6be1SChandler Carruth     return None;
49875ca6be1SChandler Carruth   auto Start = C;
49975ca6be1SChandler Carruth   C.advance(Rule.size());
50075ca6be1SChandler Carruth 
50175ca6be1SChandler Carruth   // Try a simple unquoted name.
50275ca6be1SChandler Carruth   if (C.peek() != '"') {
50375ca6be1SChandler Carruth     while (isIdentifierChar(C.peek()))
50475ca6be1SChandler Carruth       C.advance();
50575ca6be1SChandler Carruth     StringRef String = Start.upto(C).drop_front(Rule.size());
50675ca6be1SChandler Carruth     if (C.peek() != '>') {
50775ca6be1SChandler Carruth       ErrorCallback(C.location(),
50875ca6be1SChandler Carruth                     "expected the '<mcsymbol ...' to be closed by a '>'");
50975ca6be1SChandler Carruth       Token.reset(MIToken::Error, Start.remaining());
51075ca6be1SChandler Carruth       return Start;
51175ca6be1SChandler Carruth     }
51275ca6be1SChandler Carruth     C.advance();
51375ca6be1SChandler Carruth 
51475ca6be1SChandler Carruth     Token.reset(MIToken::MCSymbol, Start.upto(C)).setStringValue(String);
51575ca6be1SChandler Carruth     return C;
51675ca6be1SChandler Carruth   }
51775ca6be1SChandler Carruth 
51875ca6be1SChandler Carruth   // Otherwise lex out a quoted name.
51975ca6be1SChandler Carruth   Cursor R = lexStringConstant(C, ErrorCallback);
52075ca6be1SChandler Carruth   if (!R) {
52175ca6be1SChandler Carruth     ErrorCallback(C.location(),
52275ca6be1SChandler Carruth                   "unable to parse quoted string from opening quote");
52375ca6be1SChandler Carruth     Token.reset(MIToken::Error, Start.remaining());
52475ca6be1SChandler Carruth     return Start;
52575ca6be1SChandler Carruth   }
52675ca6be1SChandler Carruth   StringRef String = Start.upto(R).drop_front(Rule.size());
52775ca6be1SChandler Carruth   if (R.peek() != '>') {
52875ca6be1SChandler Carruth     ErrorCallback(R.location(),
52975ca6be1SChandler Carruth                   "expected the '<mcsymbol ...' to be closed by a '>'");
53075ca6be1SChandler Carruth     Token.reset(MIToken::Error, Start.remaining());
53175ca6be1SChandler Carruth     return Start;
53275ca6be1SChandler Carruth   }
53375ca6be1SChandler Carruth   R.advance();
53475ca6be1SChandler Carruth 
53575ca6be1SChandler Carruth   Token.reset(MIToken::MCSymbol, Start.upto(R))
53675ca6be1SChandler Carruth       .setOwnedStringValue(unescapeQuotedString(String));
53775ca6be1SChandler Carruth   return R;
53875ca6be1SChandler Carruth }
53975ca6be1SChandler Carruth 
isValidHexFloatingPointPrefix(char C)540ad156fb6SAlex Lorenz static bool isValidHexFloatingPointPrefix(char C) {
5418c24f331STies Stuij   return C == 'H' || C == 'K' || C == 'L' || C == 'M' || C == 'R';
542ad156fb6SAlex Lorenz }
543ad156fb6SAlex Lorenz 
lexFloatingPointLiteral(Cursor Range,Cursor C,MIToken & Token)544ad156fb6SAlex Lorenz static Cursor lexFloatingPointLiteral(Cursor Range, Cursor C, MIToken &Token) {
545ad156fb6SAlex Lorenz   C.advance();
546ad156fb6SAlex Lorenz   // Skip over [0-9]*([eE][-+]?[0-9]+)?
547ad156fb6SAlex Lorenz   while (isdigit(C.peek()))
548ad156fb6SAlex Lorenz     C.advance();
549ad156fb6SAlex Lorenz   if ((C.peek() == 'e' || C.peek() == 'E') &&
550ad156fb6SAlex Lorenz       (isdigit(C.peek(1)) ||
551ad156fb6SAlex Lorenz        ((C.peek(1) == '-' || C.peek(1) == '+') && isdigit(C.peek(2))))) {
552ad156fb6SAlex Lorenz     C.advance(2);
553ad156fb6SAlex Lorenz     while (isdigit(C.peek()))
554ad156fb6SAlex Lorenz       C.advance();
555ad156fb6SAlex Lorenz   }
5563fb77686SAlex Lorenz   Token.reset(MIToken::FloatingPointLiteral, Range.upto(C));
557ad156fb6SAlex Lorenz   return C;
558ad156fb6SAlex Lorenz }
559ad156fb6SAlex Lorenz 
maybeLexHexadecimalLiteral(Cursor C,MIToken & Token)560d62669d7SKrzysztof Parzyszek static Cursor maybeLexHexadecimalLiteral(Cursor C, MIToken &Token) {
561d62669d7SKrzysztof Parzyszek   if (C.peek() != '0' || (C.peek(1) != 'x' && C.peek(1) != 'X'))
562d62669d7SKrzysztof Parzyszek     return None;
563d62669d7SKrzysztof Parzyszek   Cursor Range = C;
564d62669d7SKrzysztof Parzyszek   C.advance(2);
565d62669d7SKrzysztof Parzyszek   unsigned PrefLen = 2;
566d62669d7SKrzysztof Parzyszek   if (isValidHexFloatingPointPrefix(C.peek())) {
567d62669d7SKrzysztof Parzyszek     C.advance();
568d62669d7SKrzysztof Parzyszek     PrefLen++;
569d62669d7SKrzysztof Parzyszek   }
570d62669d7SKrzysztof Parzyszek   while (isxdigit(C.peek()))
571d62669d7SKrzysztof Parzyszek     C.advance();
572d62669d7SKrzysztof Parzyszek   StringRef StrVal = Range.upto(C);
573d62669d7SKrzysztof Parzyszek   if (StrVal.size() <= PrefLen)
574d62669d7SKrzysztof Parzyszek     return None;
575d62669d7SKrzysztof Parzyszek   if (PrefLen == 2)
576d62669d7SKrzysztof Parzyszek     Token.reset(MIToken::HexLiteral, Range.upto(C));
577d62669d7SKrzysztof Parzyszek   else // It must be 3, which means that there was a floating-point prefix.
578d62669d7SKrzysztof Parzyszek     Token.reset(MIToken::FloatingPointLiteral, Range.upto(C));
579d62669d7SKrzysztof Parzyszek   return C;
580d62669d7SKrzysztof Parzyszek }
581d62669d7SKrzysztof Parzyszek 
maybeLexNumericalLiteral(Cursor C,MIToken & Token)582ad156fb6SAlex Lorenz static Cursor maybeLexNumericalLiteral(Cursor C, MIToken &Token) {
5836c6c46e4SAlex Lorenz   if (!isdigit(C.peek()) && (C.peek() != '-' || !isdigit(C.peek(1))))
5846c6c46e4SAlex Lorenz     return None;
585240fc1e0SAlex Lorenz   auto Range = C;
586240fc1e0SAlex Lorenz   C.advance();
587240fc1e0SAlex Lorenz   while (isdigit(C.peek()))
588240fc1e0SAlex Lorenz     C.advance();
589ad156fb6SAlex Lorenz   if (C.peek() == '.')
590ad156fb6SAlex Lorenz     return lexFloatingPointLiteral(Range, C, Token);
591240fc1e0SAlex Lorenz   StringRef StrVal = Range.upto(C);
5923fb77686SAlex Lorenz   Token.reset(MIToken::IntegerLiteral, StrVal).setIntegerValue(APSInt(StrVal));
593240fc1e0SAlex Lorenz   return C;
594240fc1e0SAlex Lorenz }
595240fc1e0SAlex Lorenz 
getMetadataKeywordKind(StringRef Identifier)596a617c916SAlex Lorenz static MIToken::TokenKind getMetadataKeywordKind(StringRef Identifier) {
597a617c916SAlex Lorenz   return StringSwitch<MIToken::TokenKind>(Identifier)
598a617c916SAlex Lorenz       .Case("!tbaa", MIToken::md_tbaa)
599a16f624dSAlex Lorenz       .Case("!alias.scope", MIToken::md_alias_scope)
60003e940d1SAlex Lorenz       .Case("!noalias", MIToken::md_noalias)
601eb625686SAlex Lorenz       .Case("!range", MIToken::md_range)
6026d353348SReid Kleckner       .Case("!DIExpression", MIToken::md_diexpr)
6039f3cf55eSDaniel Sanders       .Case("!DILocation", MIToken::md_dilocation)
604a617c916SAlex Lorenz       .Default(MIToken::Error);
605a617c916SAlex Lorenz }
606a617c916SAlex Lorenz 
maybeLexExclaim(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)607a078c77dSAmy Huang static Cursor maybeLexExclaim(Cursor C, MIToken &Token,
6080d208fc9SMatthias Braun                               ErrorCallbackType ErrorCallback) {
609a617c916SAlex Lorenz   if (C.peek() != '!')
610a617c916SAlex Lorenz     return None;
611a617c916SAlex Lorenz   auto Range = C;
612a617c916SAlex Lorenz   C.advance(1);
613a617c916SAlex Lorenz   if (isdigit(C.peek()) || !isIdentifierChar(C.peek())) {
614a617c916SAlex Lorenz     Token.reset(MIToken::exclaim, Range.upto(C));
615a617c916SAlex Lorenz     return C;
616a617c916SAlex Lorenz   }
617a617c916SAlex Lorenz   while (isIdentifierChar(C.peek()))
618a617c916SAlex Lorenz     C.advance();
619a617c916SAlex Lorenz   StringRef StrVal = Range.upto(C);
620a617c916SAlex Lorenz   Token.reset(getMetadataKeywordKind(StrVal), StrVal);
621a617c916SAlex Lorenz   if (Token.isError())
622a617c916SAlex Lorenz     ErrorCallback(Token.location(),
623a617c916SAlex Lorenz                   "use of unknown metadata keyword '" + StrVal + "'");
624a617c916SAlex Lorenz   return C;
625a617c916SAlex Lorenz }
626a617c916SAlex Lorenz 
symbolToken(char C)627f3db51deSAlex Lorenz static MIToken::TokenKind symbolToken(char C) {
628f3db51deSAlex Lorenz   switch (C) {
629f3db51deSAlex Lorenz   case ',':
630f3db51deSAlex Lorenz     return MIToken::comma;
631333e468dSMatthias Braun   case '.':
632333e468dSMatthias Braun     return MIToken::dot;
633f3db51deSAlex Lorenz   case '=':
634f3db51deSAlex Lorenz     return MIToken::equal;
6352eacca86SAlex Lorenz   case ':':
6362eacca86SAlex Lorenz     return MIToken::colon;
637deb53490SAlex Lorenz   case '(':
638deb53490SAlex Lorenz     return MIToken::lparen;
639deb53490SAlex Lorenz   case ')':
640deb53490SAlex Lorenz     return MIToken::rparen;
641f9a2b123SAlex Lorenz   case '{':
642f9a2b123SAlex Lorenz     return MIToken::lbrace;
643f9a2b123SAlex Lorenz   case '}':
644f9a2b123SAlex Lorenz     return MIToken::rbrace;
6455672a893SAlex Lorenz   case '+':
6465672a893SAlex Lorenz     return MIToken::plus;
6475672a893SAlex Lorenz   case '-':
6485672a893SAlex Lorenz     return MIToken::minus;
649287c6bb5SQuentin Colombet   case '<':
6505e63e78cSQuentin Colombet     return MIToken::less;
651287c6bb5SQuentin Colombet   case '>':
6525e63e78cSQuentin Colombet     return MIToken::greater;
653f3db51deSAlex Lorenz   default:
654f3db51deSAlex Lorenz     return MIToken::Error;
655f3db51deSAlex Lorenz   }
656f3db51deSAlex Lorenz }
657f3db51deSAlex Lorenz 
maybeLexSymbol(Cursor C,MIToken & Token)6586c6c46e4SAlex Lorenz static Cursor maybeLexSymbol(Cursor C, MIToken &Token) {
6594af7e610SAlex Lorenz   MIToken::TokenKind Kind;
6604af7e610SAlex Lorenz   unsigned Length = 1;
6614af7e610SAlex Lorenz   if (C.peek() == ':' && C.peek(1) == ':') {
6624af7e610SAlex Lorenz     Kind = MIToken::coloncolon;
6634af7e610SAlex Lorenz     Length = 2;
6644af7e610SAlex Lorenz   } else
6654af7e610SAlex Lorenz     Kind = symbolToken(C.peek());
6666c6c46e4SAlex Lorenz   if (Kind == MIToken::Error)
6676c6c46e4SAlex Lorenz     return None;
668f3db51deSAlex Lorenz   auto Range = C;
6694af7e610SAlex Lorenz   C.advance(Length);
6703fb77686SAlex Lorenz   Token.reset(Kind, Range.upto(C));
671f3db51deSAlex Lorenz   return C;
672f3db51deSAlex Lorenz }
673f3db51deSAlex Lorenz 
maybeLexNewline(Cursor C,MIToken & Token)6745022f6bbSAlex Lorenz static Cursor maybeLexNewline(Cursor C, MIToken &Token) {
6755022f6bbSAlex Lorenz   if (!isNewlineChar(C.peek()))
6765022f6bbSAlex Lorenz     return None;
6775022f6bbSAlex Lorenz   auto Range = C;
6785022f6bbSAlex Lorenz   C.advance();
6795022f6bbSAlex Lorenz   Token.reset(MIToken::Newline, Range.upto(C));
6805022f6bbSAlex Lorenz   return C;
6815022f6bbSAlex Lorenz }
6825022f6bbSAlex Lorenz 
maybeLexEscapedIRValue(Cursor C,MIToken & Token,ErrorCallbackType ErrorCallback)6830d208fc9SMatthias Braun static Cursor maybeLexEscapedIRValue(Cursor C, MIToken &Token,
6840d208fc9SMatthias Braun                                      ErrorCallbackType ErrorCallback) {
685c1136ef3SAlex Lorenz   if (C.peek() != '`')
686c1136ef3SAlex Lorenz     return None;
687c1136ef3SAlex Lorenz   auto Range = C;
688c1136ef3SAlex Lorenz   C.advance();
689c1136ef3SAlex Lorenz   auto StrRange = C;
690c1136ef3SAlex Lorenz   while (C.peek() != '`') {
691c1136ef3SAlex Lorenz     if (C.isEOF() || isNewlineChar(C.peek())) {
692c1136ef3SAlex Lorenz       ErrorCallback(
693c1136ef3SAlex Lorenz           C.location(),
694c1136ef3SAlex Lorenz           "end of machine instruction reached before the closing '`'");
695c1136ef3SAlex Lorenz       Token.reset(MIToken::Error, Range.remaining());
696c1136ef3SAlex Lorenz       return C;
697c1136ef3SAlex Lorenz     }
698c1136ef3SAlex Lorenz     C.advance();
699c1136ef3SAlex Lorenz   }
700c1136ef3SAlex Lorenz   StringRef Value = StrRange.upto(C);
701c1136ef3SAlex Lorenz   C.advance();
702c1136ef3SAlex Lorenz   Token.reset(MIToken::QuotedIRValue, Range.upto(C)).setStringValue(Value);
703c1136ef3SAlex Lorenz   return C;
704c1136ef3SAlex Lorenz }
705c1136ef3SAlex Lorenz 
lexMIToken(StringRef Source,MIToken & Token,ErrorCallbackType ErrorCallback)7060d208fc9SMatthias Braun StringRef llvm::lexMIToken(StringRef Source, MIToken &Token,
7070d208fc9SMatthias Braun                            ErrorCallbackType ErrorCallback) {
7085022f6bbSAlex Lorenz   auto C = skipComment(skipWhitespace(Cursor(Source)));
70991370c5dSAlex Lorenz   if (C.isEOF()) {
7103fb77686SAlex Lorenz     Token.reset(MIToken::Eof, C.remaining());
71191370c5dSAlex Lorenz     return C.remaining();
71291370c5dSAlex Lorenz   }
71391370c5dSAlex Lorenz 
7147efabe5cSSjoerd Meijer   C = skipMachineOperandComment(C);
7157efabe5cSSjoerd Meijer 
7166c6c46e4SAlex Lorenz   if (Cursor R = maybeLexMachineBasicBlock(C, Token, ErrorCallback))
7176c6c46e4SAlex Lorenz     return R.remaining();
7185022f6bbSAlex Lorenz   if (Cursor R = maybeLexIdentifier(C, Token))
7195022f6bbSAlex Lorenz     return R.remaining();
72031d70683SAlex Lorenz   if (Cursor R = maybeLexJumpTableIndex(C, Token))
72131d70683SAlex Lorenz     return R.remaining();
7227feaf7c6SAlex Lorenz   if (Cursor R = maybeLexStackObject(C, Token))
7237feaf7c6SAlex Lorenz     return R.remaining();
7247feaf7c6SAlex Lorenz   if (Cursor R = maybeLexFixedStackObject(C, Token))
7257feaf7c6SAlex Lorenz     return R.remaining();
726ab980499SAlex Lorenz   if (Cursor R = maybeLexConstantPoolItem(C, Token))
727ab980499SAlex Lorenz     return R.remaining();
728b74eb41dSMatthias Braun   if (Cursor R = maybeLexSubRegisterIndex(C, Token, ErrorCallback))
729b74eb41dSMatthias Braun     return R.remaining();
730deb53490SAlex Lorenz   if (Cursor R = maybeLexIRBlock(C, Token, ErrorCallback))
7318a1915b0SAlex Lorenz     return R.remaining();
7324af7e610SAlex Lorenz   if (Cursor R = maybeLexIRValue(C, Token, ErrorCallback))
7334af7e610SAlex Lorenz     return R.remaining();
73443e94b15SPuyan Lotfi   if (Cursor R = maybeLexRegister(C, Token, ErrorCallback))
7356c6c46e4SAlex Lorenz     return R.remaining();
736b29554daSAlex Lorenz   if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback))
7376c6c46e4SAlex Lorenz     return R.remaining();
7386ede3744SAlex Lorenz   if (Cursor R = maybeLexExternalSymbol(C, Token, ErrorCallback))
7396ede3744SAlex Lorenz     return R.remaining();
74075ca6be1SChandler Carruth   if (Cursor R = maybeLexMCSymbol(C, Token, ErrorCallback))
74175ca6be1SChandler Carruth     return R.remaining();
742d62669d7SKrzysztof Parzyszek   if (Cursor R = maybeLexHexadecimalLiteral(C, Token))
743ad156fb6SAlex Lorenz     return R.remaining();
744ad156fb6SAlex Lorenz   if (Cursor R = maybeLexNumericalLiteral(C, Token))
7456c6c46e4SAlex Lorenz     return R.remaining();
746a078c77dSAmy Huang   if (Cursor R = maybeLexExclaim(C, Token, ErrorCallback))
747a617c916SAlex Lorenz     return R.remaining();
7486c6c46e4SAlex Lorenz   if (Cursor R = maybeLexSymbol(C, Token))
7496c6c46e4SAlex Lorenz     return R.remaining();
7505022f6bbSAlex Lorenz   if (Cursor R = maybeLexNewline(C, Token))
7515022f6bbSAlex Lorenz     return R.remaining();
752c1136ef3SAlex Lorenz   if (Cursor R = maybeLexEscapedIRValue(C, Token, ErrorCallback))
753c1136ef3SAlex Lorenz     return R.remaining();
754bb80d3e1SKonstantin Zhuravlyov   if (Cursor R = maybeLexStringConstant(C, Token, ErrorCallback))
755bb80d3e1SKonstantin Zhuravlyov     return R.remaining();
7566c6c46e4SAlex Lorenz 
7573fb77686SAlex Lorenz   Token.reset(MIToken::Error, C.remaining());
75891370c5dSAlex Lorenz   ErrorCallback(C.location(),
7596c6c46e4SAlex Lorenz                 Twine("unexpected character '") + Twine(C.peek()) + "'");
76091370c5dSAlex Lorenz   return C.remaining();
76191370c5dSAlex Lorenz }
762