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 583fb77686SAlex Lorenz MIToken &MIToken::reset(TokenKind Kind, StringRef Range) { 593fb77686SAlex Lorenz this->Kind = Kind; 603fb77686SAlex Lorenz this->Range = Range; 613fb77686SAlex Lorenz return *this; 623fb77686SAlex Lorenz } 633fb77686SAlex Lorenz 643fb77686SAlex Lorenz MIToken &MIToken::setStringValue(StringRef StrVal) { 653fb77686SAlex Lorenz StringValue = StrVal; 663fb77686SAlex Lorenz return *this; 673fb77686SAlex Lorenz } 683fb77686SAlex Lorenz 693fb77686SAlex Lorenz MIToken &MIToken::setOwnedStringValue(std::string StrVal) { 703fb77686SAlex Lorenz StringValueStorage = std::move(StrVal); 713fb77686SAlex Lorenz StringValue = StringValueStorage; 723fb77686SAlex Lorenz return *this; 733fb77686SAlex Lorenz } 743fb77686SAlex Lorenz 753fb77686SAlex Lorenz MIToken &MIToken::setIntegerValue(APSInt IntVal) { 763fb77686SAlex Lorenz this->IntVal = std::move(IntVal); 773fb77686SAlex Lorenz return *this; 783fb77686SAlex Lorenz } 793fb77686SAlex Lorenz 8091370c5dSAlex Lorenz /// Skip the leading whitespace characters and return the updated cursor. 8191370c5dSAlex Lorenz static Cursor skipWhitespace(Cursor C) { 825022f6bbSAlex Lorenz while (isblank(C.peek())) 835022f6bbSAlex Lorenz C.advance(); 845022f6bbSAlex Lorenz return C; 855022f6bbSAlex Lorenz } 865022f6bbSAlex Lorenz 875022f6bbSAlex Lorenz static bool isNewlineChar(char C) { return C == '\n' || C == '\r'; } 885022f6bbSAlex Lorenz 895022f6bbSAlex Lorenz /// Skip a line comment and return the updated cursor. 905022f6bbSAlex Lorenz static Cursor skipComment(Cursor C) { 915022f6bbSAlex Lorenz if (C.peek() != ';') 925022f6bbSAlex Lorenz return C; 935022f6bbSAlex Lorenz while (!isNewlineChar(C.peek()) && !C.isEOF()) 9491370c5dSAlex Lorenz C.advance(); 9591370c5dSAlex Lorenz return C; 9691370c5dSAlex Lorenz } 9791370c5dSAlex Lorenz 98484903ecSAlex Lorenz /// Return true if the given character satisfies the following regular 99484903ecSAlex Lorenz /// expression: [-a-zA-Z$._0-9] 10091370c5dSAlex Lorenz static bool isIdentifierChar(char C) { 101484903ecSAlex Lorenz return isalpha(C) || isdigit(C) || C == '_' || C == '-' || C == '.' || 102484903ecSAlex Lorenz C == '$'; 10391370c5dSAlex Lorenz } 10491370c5dSAlex Lorenz 105970c12eaSAlex Lorenz /// Unescapes the given string value. 106970c12eaSAlex Lorenz /// 107970c12eaSAlex Lorenz /// Expects the string value to be quoted. 108970c12eaSAlex Lorenz static std::string unescapeQuotedString(StringRef Value) { 109b29554daSAlex Lorenz assert(Value.front() == '"' && Value.back() == '"'); 110b29554daSAlex Lorenz Cursor C = Cursor(Value.substr(1, Value.size() - 2)); 111b29554daSAlex Lorenz 112970c12eaSAlex Lorenz std::string Str; 113b29554daSAlex Lorenz Str.reserve(C.remaining().size()); 114b29554daSAlex Lorenz while (!C.isEOF()) { 115b29554daSAlex Lorenz char Char = C.peek(); 116b29554daSAlex Lorenz if (Char == '\\') { 117b29554daSAlex Lorenz if (C.peek(1) == '\\') { 118b29554daSAlex Lorenz // Two '\' become one 119b29554daSAlex Lorenz Str += '\\'; 120b29554daSAlex Lorenz C.advance(2); 121b29554daSAlex Lorenz continue; 122b29554daSAlex Lorenz } 123b29554daSAlex Lorenz if (isxdigit(C.peek(1)) && isxdigit(C.peek(2))) { 124b29554daSAlex Lorenz Str += hexDigitValue(C.peek(1)) * 16 + hexDigitValue(C.peek(2)); 125b29554daSAlex Lorenz C.advance(3); 126b29554daSAlex Lorenz continue; 127b29554daSAlex Lorenz } 128b29554daSAlex Lorenz } 129b29554daSAlex Lorenz Str += Char; 130b29554daSAlex Lorenz C.advance(); 131b29554daSAlex Lorenz } 132970c12eaSAlex Lorenz return Str; 133b29554daSAlex Lorenz } 134b29554daSAlex Lorenz 135b29554daSAlex Lorenz /// Lex a string constant using the following regular expression: \"[^\"]*\" 136b29554daSAlex Lorenz static Cursor lexStringConstant( 137b29554daSAlex Lorenz Cursor C, 138b29554daSAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 139b29554daSAlex Lorenz assert(C.peek() == '"'); 140b29554daSAlex Lorenz for (C.advance(); C.peek() != '"'; C.advance()) { 1415022f6bbSAlex Lorenz if (C.isEOF() || isNewlineChar(C.peek())) { 142b29554daSAlex Lorenz ErrorCallback( 143b29554daSAlex Lorenz C.location(), 144b29554daSAlex Lorenz "end of machine instruction reached before the closing '\"'"); 145b29554daSAlex Lorenz return None; 146b29554daSAlex Lorenz } 147b29554daSAlex Lorenz } 148b29554daSAlex Lorenz C.advance(); 149b29554daSAlex Lorenz return C; 150b29554daSAlex Lorenz } 151b29554daSAlex Lorenz 15282a1cfdcSAlex Lorenz static Cursor lexName( 153970c12eaSAlex Lorenz Cursor C, MIToken &Token, MIToken::TokenKind Type, unsigned PrefixLength, 15482a1cfdcSAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 15582a1cfdcSAlex Lorenz auto Range = C; 15682a1cfdcSAlex Lorenz C.advance(PrefixLength); 15782a1cfdcSAlex Lorenz if (C.peek() == '"') { 15882a1cfdcSAlex Lorenz if (Cursor R = lexStringConstant(C, ErrorCallback)) { 159970c12eaSAlex Lorenz StringRef String = Range.upto(R); 1603fb77686SAlex Lorenz Token.reset(Type, String) 1613fb77686SAlex Lorenz .setOwnedStringValue( 1623fb77686SAlex Lorenz unescapeQuotedString(String.drop_front(PrefixLength))); 16382a1cfdcSAlex Lorenz return R; 16482a1cfdcSAlex Lorenz } 1653fb77686SAlex Lorenz Token.reset(MIToken::Error, Range.remaining()); 16682a1cfdcSAlex Lorenz return Range; 16782a1cfdcSAlex Lorenz } 16882a1cfdcSAlex Lorenz while (isIdentifierChar(C.peek())) 16982a1cfdcSAlex Lorenz C.advance(); 1703fb77686SAlex Lorenz Token.reset(Type, Range.upto(C)) 1713fb77686SAlex Lorenz .setStringValue(Range.upto(C).drop_front(PrefixLength)); 17282a1cfdcSAlex Lorenz return C; 17382a1cfdcSAlex Lorenz } 17482a1cfdcSAlex Lorenz 17505e3882eSAlex Lorenz static Cursor maybeLexIntegerType(Cursor C, MIToken &Token) { 17605e3882eSAlex Lorenz if (C.peek() != 'i' || !isdigit(C.peek(1))) 17705e3882eSAlex Lorenz return None; 17805e3882eSAlex Lorenz auto Range = C; 17905e3882eSAlex Lorenz C.advance(); // Skip 'i' 18005e3882eSAlex Lorenz while (isdigit(C.peek())) 18105e3882eSAlex Lorenz C.advance(); 1823fb77686SAlex Lorenz Token.reset(MIToken::IntegerType, Range.upto(C)); 18305e3882eSAlex Lorenz return C; 18405e3882eSAlex Lorenz } 18505e3882eSAlex Lorenz 186cb268d46SAlex Lorenz static MIToken::TokenKind getIdentifierKind(StringRef Identifier) { 187cb268d46SAlex Lorenz return StringSwitch<MIToken::TokenKind>(Identifier) 188cb268d46SAlex Lorenz .Case("_", MIToken::underscore) 189cb268d46SAlex Lorenz .Case("implicit", MIToken::kw_implicit) 190cb268d46SAlex Lorenz .Case("implicit-def", MIToken::kw_implicit_define) 191cbbfd0b1SAlex Lorenz .Case("dead", MIToken::kw_dead) 192495ad879SAlex Lorenz .Case("killed", MIToken::kw_killed) 1934d026b89SAlex Lorenz .Case("undef", MIToken::kw_undef) 1941039fd1aSAlex Lorenz .Case("internal", MIToken::kw_internal) 19501c1a5eeSAlex Lorenz .Case("early-clobber", MIToken::kw_early_clobber) 1969075258bSAlex Lorenz .Case("debug-use", MIToken::kw_debug_use) 197e5a44660SAlex Lorenz .Case("frame-setup", MIToken::kw_frame_setup) 19846d760d1SAlex Lorenz .Case("debug-location", MIToken::kw_debug_location) 199*577d271aSAlex Lorenz .Case(".cfi_same_value", MIToken::kw_cfi_same_value) 2008cfc6867SAlex Lorenz .Case(".cfi_offset", MIToken::kw_cfi_offset) 2015b0d5f6fSAlex Lorenz .Case(".cfi_def_cfa_register", MIToken::kw_cfi_def_cfa_register) 202f4baeb51SAlex Lorenz .Case(".cfi_def_cfa_offset", MIToken::kw_cfi_def_cfa_offset) 203b139323fSAlex Lorenz .Case(".cfi_def_cfa", MIToken::kw_cfi_def_cfa) 204deb53490SAlex Lorenz .Case("blockaddress", MIToken::kw_blockaddress) 205ef5c196fSAlex Lorenz .Case("target-index", MIToken::kw_target_index) 206ad156fb6SAlex Lorenz .Case("half", MIToken::kw_half) 207ad156fb6SAlex Lorenz .Case("float", MIToken::kw_float) 208ad156fb6SAlex Lorenz .Case("double", MIToken::kw_double) 209ad156fb6SAlex Lorenz .Case("x86_fp80", MIToken::kw_x86_fp80) 210ad156fb6SAlex Lorenz .Case("fp128", MIToken::kw_fp128) 211ad156fb6SAlex Lorenz .Case("ppc_fp128", MIToken::kw_ppc_fp128) 21249873a83SAlex Lorenz .Case("target-flags", MIToken::kw_target_flags) 213a518b796SAlex Lorenz .Case("volatile", MIToken::kw_volatile) 21410fd0385SAlex Lorenz .Case("non-temporal", MIToken::kw_non_temporal) 215dc8de2a6SAlex Lorenz .Case("invariant", MIToken::kw_invariant) 21661420f79SAlex Lorenz .Case("align", MIToken::kw_align) 21746e9558aSAlex Lorenz .Case("stack", MIToken::kw_stack) 218d858f874SAlex Lorenz .Case("got", MIToken::kw_got) 2194be56e93SAlex Lorenz .Case("jump-table", MIToken::kw_jump_table) 22091097a3fSAlex Lorenz .Case("constant-pool", MIToken::kw_constant_pool) 221b97c9ef4SAlex Lorenz .Case("liveout", MIToken::kw_liveout) 2225022f6bbSAlex Lorenz .Case("address-taken", MIToken::kw_address_taken) 2235022f6bbSAlex Lorenz .Case("landing-pad", MIToken::kw_landing_pad) 2245022f6bbSAlex Lorenz .Case("liveins", MIToken::kw_liveins) 2255022f6bbSAlex Lorenz .Case("successors", MIToken::kw_successors) 226cb268d46SAlex Lorenz .Default(MIToken::Identifier); 227cb268d46SAlex Lorenz } 228cb268d46SAlex Lorenz 2296c6c46e4SAlex Lorenz static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) { 230f4baeb51SAlex Lorenz if (!isalpha(C.peek()) && C.peek() != '_' && C.peek() != '.') 2316c6c46e4SAlex Lorenz return None; 23291370c5dSAlex Lorenz auto Range = C; 23391370c5dSAlex Lorenz while (isIdentifierChar(C.peek())) 23491370c5dSAlex Lorenz C.advance(); 23512b554e6SAlex Lorenz auto Identifier = Range.upto(C); 2363fb77686SAlex Lorenz Token.reset(getIdentifierKind(Identifier), Identifier) 2373fb77686SAlex Lorenz .setStringValue(Identifier); 23891370c5dSAlex Lorenz return C; 23991370c5dSAlex Lorenz } 24091370c5dSAlex Lorenz 2416c6c46e4SAlex Lorenz static Cursor maybeLexMachineBasicBlock( 24233f0aef3SAlex Lorenz Cursor C, MIToken &Token, 24333f0aef3SAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 2445022f6bbSAlex Lorenz bool IsReference = C.remaining().startswith("%bb."); 2455022f6bbSAlex Lorenz if (!IsReference && !C.remaining().startswith("bb.")) 2466c6c46e4SAlex Lorenz return None; 24733f0aef3SAlex Lorenz auto Range = C; 2485022f6bbSAlex Lorenz unsigned PrefixLength = IsReference ? 4 : 3; 2495022f6bbSAlex Lorenz C.advance(PrefixLength); // Skip '%bb.' or 'bb.' 25033f0aef3SAlex Lorenz if (!isdigit(C.peek())) { 2513fb77686SAlex Lorenz Token.reset(MIToken::Error, C.remaining()); 25233f0aef3SAlex Lorenz ErrorCallback(C.location(), "expected a number after '%bb.'"); 25333f0aef3SAlex Lorenz return C; 25433f0aef3SAlex Lorenz } 25533f0aef3SAlex Lorenz auto NumberRange = C; 25633f0aef3SAlex Lorenz while (isdigit(C.peek())) 25733f0aef3SAlex Lorenz C.advance(); 25833f0aef3SAlex Lorenz StringRef Number = NumberRange.upto(C); 2595022f6bbSAlex Lorenz unsigned StringOffset = PrefixLength + Number.size(); // Drop '%bb.<id>' 26033f0aef3SAlex Lorenz if (C.peek() == '.') { 26133f0aef3SAlex Lorenz C.advance(); // Skip '.' 26233f0aef3SAlex Lorenz ++StringOffset; 26333f0aef3SAlex Lorenz while (isIdentifierChar(C.peek())) 26433f0aef3SAlex Lorenz C.advance(); 26533f0aef3SAlex Lorenz } 2665022f6bbSAlex Lorenz Token.reset(IsReference ? MIToken::MachineBasicBlock 2675022f6bbSAlex Lorenz : MIToken::MachineBasicBlockLabel, 2685022f6bbSAlex Lorenz Range.upto(C)) 2693fb77686SAlex Lorenz .setIntegerValue(APSInt(Number)) 2703fb77686SAlex Lorenz .setStringValue(Range.upto(C).drop_front(StringOffset)); 27133f0aef3SAlex Lorenz return C; 27233f0aef3SAlex Lorenz } 27333f0aef3SAlex Lorenz 27431d70683SAlex Lorenz static Cursor maybeLexIndex(Cursor C, MIToken &Token, StringRef Rule, 27531d70683SAlex Lorenz MIToken::TokenKind Kind) { 27631d70683SAlex Lorenz if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size()))) 27731d70683SAlex Lorenz return None; 27831d70683SAlex Lorenz auto Range = C; 27931d70683SAlex Lorenz C.advance(Rule.size()); 28031d70683SAlex Lorenz auto NumberRange = C; 28131d70683SAlex Lorenz while (isdigit(C.peek())) 28231d70683SAlex Lorenz C.advance(); 2833fb77686SAlex Lorenz Token.reset(Kind, Range.upto(C)).setIntegerValue(APSInt(NumberRange.upto(C))); 28431d70683SAlex Lorenz return C; 28531d70683SAlex Lorenz } 28631d70683SAlex Lorenz 2877feaf7c6SAlex Lorenz static Cursor maybeLexIndexAndName(Cursor C, MIToken &Token, StringRef Rule, 2887feaf7c6SAlex Lorenz MIToken::TokenKind Kind) { 2897feaf7c6SAlex Lorenz if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size()))) 2907feaf7c6SAlex Lorenz return None; 2917feaf7c6SAlex Lorenz auto Range = C; 2927feaf7c6SAlex Lorenz C.advance(Rule.size()); 2937feaf7c6SAlex Lorenz auto NumberRange = C; 2947feaf7c6SAlex Lorenz while (isdigit(C.peek())) 2957feaf7c6SAlex Lorenz C.advance(); 2967feaf7c6SAlex Lorenz StringRef Number = NumberRange.upto(C); 2977feaf7c6SAlex Lorenz unsigned StringOffset = Rule.size() + Number.size(); 2987feaf7c6SAlex Lorenz if (C.peek() == '.') { 2997feaf7c6SAlex Lorenz C.advance(); 3007feaf7c6SAlex Lorenz ++StringOffset; 3017feaf7c6SAlex Lorenz while (isIdentifierChar(C.peek())) 3027feaf7c6SAlex Lorenz C.advance(); 3037feaf7c6SAlex Lorenz } 3043fb77686SAlex Lorenz Token.reset(Kind, Range.upto(C)) 3053fb77686SAlex Lorenz .setIntegerValue(APSInt(Number)) 3063fb77686SAlex Lorenz .setStringValue(Range.upto(C).drop_front(StringOffset)); 3077feaf7c6SAlex Lorenz return C; 3087feaf7c6SAlex Lorenz } 3097feaf7c6SAlex Lorenz 31031d70683SAlex Lorenz static Cursor maybeLexJumpTableIndex(Cursor C, MIToken &Token) { 31131d70683SAlex Lorenz return maybeLexIndex(C, Token, "%jump-table.", MIToken::JumpTableIndex); 31231d70683SAlex Lorenz } 31331d70683SAlex Lorenz 3147feaf7c6SAlex Lorenz static Cursor maybeLexStackObject(Cursor C, MIToken &Token) { 3157feaf7c6SAlex Lorenz return maybeLexIndexAndName(C, Token, "%stack.", MIToken::StackObject); 3167feaf7c6SAlex Lorenz } 3177feaf7c6SAlex Lorenz 3187feaf7c6SAlex Lorenz static Cursor maybeLexFixedStackObject(Cursor C, MIToken &Token) { 3197feaf7c6SAlex Lorenz return maybeLexIndex(C, Token, "%fixed-stack.", MIToken::FixedStackObject); 3207feaf7c6SAlex Lorenz } 3217feaf7c6SAlex Lorenz 322ab980499SAlex Lorenz static Cursor maybeLexConstantPoolItem(Cursor C, MIToken &Token) { 323ab980499SAlex Lorenz return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem); 324ab980499SAlex Lorenz } 325ab980499SAlex Lorenz 326deb53490SAlex Lorenz static Cursor maybeLexIRBlock( 327deb53490SAlex Lorenz Cursor C, MIToken &Token, 328deb53490SAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 329deb53490SAlex Lorenz const StringRef Rule = "%ir-block."; 330deb53490SAlex Lorenz if (!C.remaining().startswith(Rule)) 331deb53490SAlex Lorenz return None; 332deb53490SAlex Lorenz if (isdigit(C.peek(Rule.size()))) 333deb53490SAlex Lorenz return maybeLexIndex(C, Token, Rule, MIToken::IRBlock); 334970c12eaSAlex Lorenz return lexName(C, Token, MIToken::NamedIRBlock, Rule.size(), ErrorCallback); 3358a1915b0SAlex Lorenz } 3368a1915b0SAlex Lorenz 3374af7e610SAlex Lorenz static Cursor maybeLexIRValue( 3384af7e610SAlex Lorenz Cursor C, MIToken &Token, 3394af7e610SAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 3404af7e610SAlex Lorenz const StringRef Rule = "%ir."; 3414af7e610SAlex Lorenz if (!C.remaining().startswith(Rule)) 3424af7e610SAlex Lorenz return None; 343970c12eaSAlex Lorenz return lexName(C, Token, MIToken::NamedIRValue, Rule.size(), ErrorCallback); 3444af7e610SAlex Lorenz } 3454af7e610SAlex Lorenz 34653464510SAlex Lorenz static Cursor lexVirtualRegister(Cursor C, MIToken &Token) { 34753464510SAlex Lorenz auto Range = C; 34853464510SAlex Lorenz C.advance(); // Skip '%' 34953464510SAlex Lorenz auto NumberRange = C; 35053464510SAlex Lorenz while (isdigit(C.peek())) 35153464510SAlex Lorenz C.advance(); 3523fb77686SAlex Lorenz Token.reset(MIToken::VirtualRegister, Range.upto(C)) 3533fb77686SAlex Lorenz .setIntegerValue(APSInt(NumberRange.upto(C))); 35453464510SAlex Lorenz return C; 35553464510SAlex Lorenz } 35653464510SAlex Lorenz 3576c6c46e4SAlex Lorenz static Cursor maybeLexRegister(Cursor C, MIToken &Token) { 3586c6c46e4SAlex Lorenz if (C.peek() != '%') 3596c6c46e4SAlex Lorenz return None; 36053464510SAlex Lorenz if (isdigit(C.peek(1))) 36153464510SAlex Lorenz return lexVirtualRegister(C, Token); 362f3db51deSAlex Lorenz auto Range = C; 363f3db51deSAlex Lorenz C.advance(); // Skip '%' 364f3db51deSAlex Lorenz while (isIdentifierChar(C.peek())) 365f3db51deSAlex Lorenz C.advance(); 3663fb77686SAlex Lorenz Token.reset(MIToken::NamedRegister, Range.upto(C)) 3673fb77686SAlex Lorenz .setStringValue(Range.upto(C).drop_front(1)); // Drop the '%' 368f3db51deSAlex Lorenz return C; 369f3db51deSAlex Lorenz } 370f3db51deSAlex Lorenz 371c1fbb354SAlex Lorenz static Cursor maybeLexGlobalValue( 372c1fbb354SAlex Lorenz Cursor C, MIToken &Token, 373c1fbb354SAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 374c1fbb354SAlex Lorenz if (C.peek() != '@') 375c1fbb354SAlex Lorenz return None; 376c1fbb354SAlex Lorenz if (!isdigit(C.peek(1))) 377970c12eaSAlex Lorenz return lexName(C, Token, MIToken::NamedGlobalValue, /*PrefixLength=*/1, 378c1fbb354SAlex Lorenz ErrorCallback); 379c1fbb354SAlex Lorenz auto Range = C; 380c1fbb354SAlex Lorenz C.advance(1); // Skip the '@' 381c1fbb354SAlex Lorenz auto NumberRange = C; 382c1fbb354SAlex Lorenz while (isdigit(C.peek())) 383c1fbb354SAlex Lorenz C.advance(); 3843fb77686SAlex Lorenz Token.reset(MIToken::GlobalValue, Range.upto(C)) 3853fb77686SAlex Lorenz .setIntegerValue(APSInt(NumberRange.upto(C))); 386c1fbb354SAlex Lorenz return C; 387c1fbb354SAlex Lorenz } 388c1fbb354SAlex Lorenz 3896ede3744SAlex Lorenz static Cursor maybeLexExternalSymbol( 3906ede3744SAlex Lorenz Cursor C, MIToken &Token, 3916ede3744SAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 3926ede3744SAlex Lorenz if (C.peek() != '$') 3936ede3744SAlex Lorenz return None; 394970c12eaSAlex Lorenz return lexName(C, Token, MIToken::ExternalSymbol, /*PrefixLength=*/1, 395970c12eaSAlex Lorenz ErrorCallback); 3966ede3744SAlex Lorenz } 3976ede3744SAlex Lorenz 398ad156fb6SAlex Lorenz static bool isValidHexFloatingPointPrefix(char C) { 399ad156fb6SAlex Lorenz return C == 'H' || C == 'K' || C == 'L' || C == 'M'; 400ad156fb6SAlex Lorenz } 401ad156fb6SAlex Lorenz 402ad156fb6SAlex Lorenz static Cursor maybeLexHexFloatingPointLiteral(Cursor C, MIToken &Token) { 403ad156fb6SAlex Lorenz if (C.peek() != '0' || C.peek(1) != 'x') 404ad156fb6SAlex Lorenz return None; 405ad156fb6SAlex Lorenz Cursor Range = C; 406ad156fb6SAlex Lorenz C.advance(2); // Skip '0x' 407ad156fb6SAlex Lorenz if (isValidHexFloatingPointPrefix(C.peek())) 408ad156fb6SAlex Lorenz C.advance(); 409ad156fb6SAlex Lorenz while (isxdigit(C.peek())) 410ad156fb6SAlex Lorenz C.advance(); 4113fb77686SAlex Lorenz Token.reset(MIToken::FloatingPointLiteral, Range.upto(C)); 412ad156fb6SAlex Lorenz return C; 413ad156fb6SAlex Lorenz } 414ad156fb6SAlex Lorenz 415ad156fb6SAlex Lorenz static Cursor lexFloatingPointLiteral(Cursor Range, Cursor C, MIToken &Token) { 416ad156fb6SAlex Lorenz C.advance(); 417ad156fb6SAlex Lorenz // Skip over [0-9]*([eE][-+]?[0-9]+)? 418ad156fb6SAlex Lorenz while (isdigit(C.peek())) 419ad156fb6SAlex Lorenz C.advance(); 420ad156fb6SAlex Lorenz if ((C.peek() == 'e' || C.peek() == 'E') && 421ad156fb6SAlex Lorenz (isdigit(C.peek(1)) || 422ad156fb6SAlex Lorenz ((C.peek(1) == '-' || C.peek(1) == '+') && isdigit(C.peek(2))))) { 423ad156fb6SAlex Lorenz C.advance(2); 424ad156fb6SAlex Lorenz while (isdigit(C.peek())) 425ad156fb6SAlex Lorenz C.advance(); 426ad156fb6SAlex Lorenz } 4273fb77686SAlex Lorenz Token.reset(MIToken::FloatingPointLiteral, Range.upto(C)); 428ad156fb6SAlex Lorenz return C; 429ad156fb6SAlex Lorenz } 430ad156fb6SAlex Lorenz 431ad156fb6SAlex Lorenz static Cursor maybeLexNumericalLiteral(Cursor C, MIToken &Token) { 4326c6c46e4SAlex Lorenz if (!isdigit(C.peek()) && (C.peek() != '-' || !isdigit(C.peek(1)))) 4336c6c46e4SAlex Lorenz return None; 434240fc1e0SAlex Lorenz auto Range = C; 435240fc1e0SAlex Lorenz C.advance(); 436240fc1e0SAlex Lorenz while (isdigit(C.peek())) 437240fc1e0SAlex Lorenz C.advance(); 438ad156fb6SAlex Lorenz if (C.peek() == '.') 439ad156fb6SAlex Lorenz return lexFloatingPointLiteral(Range, C, Token); 440240fc1e0SAlex Lorenz StringRef StrVal = Range.upto(C); 4413fb77686SAlex Lorenz Token.reset(MIToken::IntegerLiteral, StrVal).setIntegerValue(APSInt(StrVal)); 442240fc1e0SAlex Lorenz return C; 443240fc1e0SAlex Lorenz } 444240fc1e0SAlex Lorenz 445f3db51deSAlex Lorenz static MIToken::TokenKind symbolToken(char C) { 446f3db51deSAlex Lorenz switch (C) { 447f3db51deSAlex Lorenz case ',': 448f3db51deSAlex Lorenz return MIToken::comma; 449f3db51deSAlex Lorenz case '=': 450f3db51deSAlex Lorenz return MIToken::equal; 4512eacca86SAlex Lorenz case ':': 4522eacca86SAlex Lorenz return MIToken::colon; 45335e44469SAlex Lorenz case '!': 45435e44469SAlex Lorenz return MIToken::exclaim; 455deb53490SAlex Lorenz case '(': 456deb53490SAlex Lorenz return MIToken::lparen; 457deb53490SAlex Lorenz case ')': 458deb53490SAlex Lorenz return MIToken::rparen; 459f9a2b123SAlex Lorenz case '{': 460f9a2b123SAlex Lorenz return MIToken::lbrace; 461f9a2b123SAlex Lorenz case '}': 462f9a2b123SAlex Lorenz return MIToken::rbrace; 4635672a893SAlex Lorenz case '+': 4645672a893SAlex Lorenz return MIToken::plus; 4655672a893SAlex Lorenz case '-': 4665672a893SAlex Lorenz return MIToken::minus; 467f3db51deSAlex Lorenz default: 468f3db51deSAlex Lorenz return MIToken::Error; 469f3db51deSAlex Lorenz } 470f3db51deSAlex Lorenz } 471f3db51deSAlex Lorenz 4726c6c46e4SAlex Lorenz static Cursor maybeLexSymbol(Cursor C, MIToken &Token) { 4734af7e610SAlex Lorenz MIToken::TokenKind Kind; 4744af7e610SAlex Lorenz unsigned Length = 1; 4754af7e610SAlex Lorenz if (C.peek() == ':' && C.peek(1) == ':') { 4764af7e610SAlex Lorenz Kind = MIToken::coloncolon; 4774af7e610SAlex Lorenz Length = 2; 4784af7e610SAlex Lorenz } else 4794af7e610SAlex Lorenz Kind = symbolToken(C.peek()); 4806c6c46e4SAlex Lorenz if (Kind == MIToken::Error) 4816c6c46e4SAlex Lorenz return None; 482f3db51deSAlex Lorenz auto Range = C; 4834af7e610SAlex Lorenz C.advance(Length); 4843fb77686SAlex Lorenz Token.reset(Kind, Range.upto(C)); 485f3db51deSAlex Lorenz return C; 486f3db51deSAlex Lorenz } 487f3db51deSAlex Lorenz 4885022f6bbSAlex Lorenz static Cursor maybeLexNewline(Cursor C, MIToken &Token) { 4895022f6bbSAlex Lorenz if (!isNewlineChar(C.peek())) 4905022f6bbSAlex Lorenz return None; 4915022f6bbSAlex Lorenz auto Range = C; 4925022f6bbSAlex Lorenz C.advance(); 4935022f6bbSAlex Lorenz Token.reset(MIToken::Newline, Range.upto(C)); 4945022f6bbSAlex Lorenz return C; 4955022f6bbSAlex Lorenz } 4965022f6bbSAlex Lorenz 49791370c5dSAlex Lorenz StringRef llvm::lexMIToken( 49891370c5dSAlex Lorenz StringRef Source, MIToken &Token, 49991370c5dSAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 5005022f6bbSAlex Lorenz auto C = skipComment(skipWhitespace(Cursor(Source))); 50191370c5dSAlex Lorenz if (C.isEOF()) { 5023fb77686SAlex Lorenz Token.reset(MIToken::Eof, C.remaining()); 50391370c5dSAlex Lorenz return C.remaining(); 50491370c5dSAlex Lorenz } 50591370c5dSAlex Lorenz 50605e3882eSAlex Lorenz if (Cursor R = maybeLexIntegerType(C, Token)) 50705e3882eSAlex Lorenz return R.remaining(); 5086c6c46e4SAlex Lorenz if (Cursor R = maybeLexMachineBasicBlock(C, Token, ErrorCallback)) 5096c6c46e4SAlex Lorenz return R.remaining(); 5105022f6bbSAlex Lorenz if (Cursor R = maybeLexIdentifier(C, Token)) 5115022f6bbSAlex Lorenz return R.remaining(); 51231d70683SAlex Lorenz if (Cursor R = maybeLexJumpTableIndex(C, Token)) 51331d70683SAlex Lorenz return R.remaining(); 5147feaf7c6SAlex Lorenz if (Cursor R = maybeLexStackObject(C, Token)) 5157feaf7c6SAlex Lorenz return R.remaining(); 5167feaf7c6SAlex Lorenz if (Cursor R = maybeLexFixedStackObject(C, Token)) 5177feaf7c6SAlex Lorenz return R.remaining(); 518ab980499SAlex Lorenz if (Cursor R = maybeLexConstantPoolItem(C, Token)) 519ab980499SAlex Lorenz return R.remaining(); 520deb53490SAlex Lorenz if (Cursor R = maybeLexIRBlock(C, Token, ErrorCallback)) 5218a1915b0SAlex Lorenz return R.remaining(); 5224af7e610SAlex Lorenz if (Cursor R = maybeLexIRValue(C, Token, ErrorCallback)) 5234af7e610SAlex Lorenz return R.remaining(); 5246c6c46e4SAlex Lorenz if (Cursor R = maybeLexRegister(C, Token)) 5256c6c46e4SAlex Lorenz return R.remaining(); 526b29554daSAlex Lorenz if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback)) 5276c6c46e4SAlex Lorenz return R.remaining(); 5286ede3744SAlex Lorenz if (Cursor R = maybeLexExternalSymbol(C, Token, ErrorCallback)) 5296ede3744SAlex Lorenz return R.remaining(); 530ad156fb6SAlex Lorenz if (Cursor R = maybeLexHexFloatingPointLiteral(C, Token)) 531ad156fb6SAlex Lorenz return R.remaining(); 532ad156fb6SAlex Lorenz if (Cursor R = maybeLexNumericalLiteral(C, Token)) 5336c6c46e4SAlex Lorenz return R.remaining(); 5346c6c46e4SAlex Lorenz if (Cursor R = maybeLexSymbol(C, Token)) 5356c6c46e4SAlex Lorenz return R.remaining(); 5365022f6bbSAlex Lorenz if (Cursor R = maybeLexNewline(C, Token)) 5375022f6bbSAlex Lorenz return R.remaining(); 5386c6c46e4SAlex Lorenz 5393fb77686SAlex Lorenz Token.reset(MIToken::Error, C.remaining()); 54091370c5dSAlex Lorenz ErrorCallback(C.location(), 5416c6c46e4SAlex Lorenz Twine("unexpected character '") + Twine(C.peek()) + "'"); 54291370c5dSAlex Lorenz return C.remaining(); 54391370c5dSAlex Lorenz } 544