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) 191e66a7ccfSAlex Lorenz .Case("def", MIToken::kw_def) 192cbbfd0b1SAlex Lorenz .Case("dead", MIToken::kw_dead) 193495ad879SAlex Lorenz .Case("killed", MIToken::kw_killed) 1944d026b89SAlex Lorenz .Case("undef", MIToken::kw_undef) 1951039fd1aSAlex Lorenz .Case("internal", MIToken::kw_internal) 19601c1a5eeSAlex Lorenz .Case("early-clobber", MIToken::kw_early_clobber) 1979075258bSAlex Lorenz .Case("debug-use", MIToken::kw_debug_use) 1985ef93b0cSAlex Lorenz .Case("tied-def", MIToken::kw_tied_def) 199e5a44660SAlex Lorenz .Case("frame-setup", MIToken::kw_frame_setup) 20046d760d1SAlex Lorenz .Case("debug-location", MIToken::kw_debug_location) 201577d271aSAlex Lorenz .Case(".cfi_same_value", MIToken::kw_cfi_same_value) 2028cfc6867SAlex Lorenz .Case(".cfi_offset", MIToken::kw_cfi_offset) 2035b0d5f6fSAlex Lorenz .Case(".cfi_def_cfa_register", MIToken::kw_cfi_def_cfa_register) 204f4baeb51SAlex Lorenz .Case(".cfi_def_cfa_offset", MIToken::kw_cfi_def_cfa_offset) 205b139323fSAlex Lorenz .Case(".cfi_def_cfa", MIToken::kw_cfi_def_cfa) 206deb53490SAlex Lorenz .Case("blockaddress", MIToken::kw_blockaddress) 207ef5c196fSAlex Lorenz .Case("target-index", MIToken::kw_target_index) 208ad156fb6SAlex Lorenz .Case("half", MIToken::kw_half) 209ad156fb6SAlex Lorenz .Case("float", MIToken::kw_float) 210ad156fb6SAlex Lorenz .Case("double", MIToken::kw_double) 211ad156fb6SAlex Lorenz .Case("x86_fp80", MIToken::kw_x86_fp80) 212ad156fb6SAlex Lorenz .Case("fp128", MIToken::kw_fp128) 213ad156fb6SAlex Lorenz .Case("ppc_fp128", MIToken::kw_ppc_fp128) 21449873a83SAlex Lorenz .Case("target-flags", MIToken::kw_target_flags) 215a518b796SAlex Lorenz .Case("volatile", MIToken::kw_volatile) 21610fd0385SAlex Lorenz .Case("non-temporal", MIToken::kw_non_temporal) 217dc8de2a6SAlex Lorenz .Case("invariant", MIToken::kw_invariant) 21861420f79SAlex Lorenz .Case("align", MIToken::kw_align) 21946e9558aSAlex Lorenz .Case("stack", MIToken::kw_stack) 220d858f874SAlex Lorenz .Case("got", MIToken::kw_got) 2214be56e93SAlex Lorenz .Case("jump-table", MIToken::kw_jump_table) 22291097a3fSAlex Lorenz .Case("constant-pool", MIToken::kw_constant_pool) 2230d009645SAlex Lorenz .Case("call-entry", MIToken::kw_call_entry) 224b97c9ef4SAlex Lorenz .Case("liveout", MIToken::kw_liveout) 2255022f6bbSAlex Lorenz .Case("address-taken", MIToken::kw_address_taken) 2265022f6bbSAlex Lorenz .Case("landing-pad", MIToken::kw_landing_pad) 2275022f6bbSAlex Lorenz .Case("liveins", MIToken::kw_liveins) 2285022f6bbSAlex Lorenz .Case("successors", MIToken::kw_successors) 229cb268d46SAlex Lorenz .Default(MIToken::Identifier); 230cb268d46SAlex Lorenz } 231cb268d46SAlex Lorenz 2326c6c46e4SAlex Lorenz static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) { 233f4baeb51SAlex Lorenz if (!isalpha(C.peek()) && C.peek() != '_' && C.peek() != '.') 2346c6c46e4SAlex Lorenz return None; 23591370c5dSAlex Lorenz auto Range = C; 23691370c5dSAlex Lorenz while (isIdentifierChar(C.peek())) 23791370c5dSAlex Lorenz C.advance(); 23812b554e6SAlex Lorenz auto Identifier = Range.upto(C); 2393fb77686SAlex Lorenz Token.reset(getIdentifierKind(Identifier), Identifier) 2403fb77686SAlex Lorenz .setStringValue(Identifier); 24191370c5dSAlex Lorenz return C; 24291370c5dSAlex Lorenz } 24391370c5dSAlex Lorenz 2446c6c46e4SAlex Lorenz static Cursor maybeLexMachineBasicBlock( 24533f0aef3SAlex Lorenz Cursor C, MIToken &Token, 24633f0aef3SAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 2475022f6bbSAlex Lorenz bool IsReference = C.remaining().startswith("%bb."); 2485022f6bbSAlex Lorenz if (!IsReference && !C.remaining().startswith("bb.")) 2496c6c46e4SAlex Lorenz return None; 25033f0aef3SAlex Lorenz auto Range = C; 2515022f6bbSAlex Lorenz unsigned PrefixLength = IsReference ? 4 : 3; 2525022f6bbSAlex Lorenz C.advance(PrefixLength); // Skip '%bb.' or 'bb.' 25333f0aef3SAlex Lorenz if (!isdigit(C.peek())) { 2543fb77686SAlex Lorenz Token.reset(MIToken::Error, C.remaining()); 25533f0aef3SAlex Lorenz ErrorCallback(C.location(), "expected a number after '%bb.'"); 25633f0aef3SAlex Lorenz return C; 25733f0aef3SAlex Lorenz } 25833f0aef3SAlex Lorenz auto NumberRange = C; 25933f0aef3SAlex Lorenz while (isdigit(C.peek())) 26033f0aef3SAlex Lorenz C.advance(); 26133f0aef3SAlex Lorenz StringRef Number = NumberRange.upto(C); 2625022f6bbSAlex Lorenz unsigned StringOffset = PrefixLength + Number.size(); // Drop '%bb.<id>' 26333f0aef3SAlex Lorenz if (C.peek() == '.') { 26433f0aef3SAlex Lorenz C.advance(); // Skip '.' 26533f0aef3SAlex Lorenz ++StringOffset; 26633f0aef3SAlex Lorenz while (isIdentifierChar(C.peek())) 26733f0aef3SAlex Lorenz C.advance(); 26833f0aef3SAlex Lorenz } 2695022f6bbSAlex Lorenz Token.reset(IsReference ? MIToken::MachineBasicBlock 2705022f6bbSAlex Lorenz : MIToken::MachineBasicBlockLabel, 2715022f6bbSAlex Lorenz Range.upto(C)) 2723fb77686SAlex Lorenz .setIntegerValue(APSInt(Number)) 2733fb77686SAlex Lorenz .setStringValue(Range.upto(C).drop_front(StringOffset)); 27433f0aef3SAlex Lorenz return C; 27533f0aef3SAlex Lorenz } 27633f0aef3SAlex Lorenz 27731d70683SAlex Lorenz static Cursor maybeLexIndex(Cursor C, MIToken &Token, StringRef Rule, 27831d70683SAlex Lorenz MIToken::TokenKind Kind) { 27931d70683SAlex Lorenz if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size()))) 28031d70683SAlex Lorenz return None; 28131d70683SAlex Lorenz auto Range = C; 28231d70683SAlex Lorenz C.advance(Rule.size()); 28331d70683SAlex Lorenz auto NumberRange = C; 28431d70683SAlex Lorenz while (isdigit(C.peek())) 28531d70683SAlex Lorenz C.advance(); 2863fb77686SAlex Lorenz Token.reset(Kind, Range.upto(C)).setIntegerValue(APSInt(NumberRange.upto(C))); 28731d70683SAlex Lorenz return C; 28831d70683SAlex Lorenz } 28931d70683SAlex Lorenz 2907feaf7c6SAlex Lorenz static Cursor maybeLexIndexAndName(Cursor C, MIToken &Token, StringRef Rule, 2917feaf7c6SAlex Lorenz MIToken::TokenKind Kind) { 2927feaf7c6SAlex Lorenz if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size()))) 2937feaf7c6SAlex Lorenz return None; 2947feaf7c6SAlex Lorenz auto Range = C; 2957feaf7c6SAlex Lorenz C.advance(Rule.size()); 2967feaf7c6SAlex Lorenz auto NumberRange = C; 2977feaf7c6SAlex Lorenz while (isdigit(C.peek())) 2987feaf7c6SAlex Lorenz C.advance(); 2997feaf7c6SAlex Lorenz StringRef Number = NumberRange.upto(C); 3007feaf7c6SAlex Lorenz unsigned StringOffset = Rule.size() + Number.size(); 3017feaf7c6SAlex Lorenz if (C.peek() == '.') { 3027feaf7c6SAlex Lorenz C.advance(); 3037feaf7c6SAlex Lorenz ++StringOffset; 3047feaf7c6SAlex Lorenz while (isIdentifierChar(C.peek())) 3057feaf7c6SAlex Lorenz C.advance(); 3067feaf7c6SAlex Lorenz } 3073fb77686SAlex Lorenz Token.reset(Kind, Range.upto(C)) 3083fb77686SAlex Lorenz .setIntegerValue(APSInt(Number)) 3093fb77686SAlex Lorenz .setStringValue(Range.upto(C).drop_front(StringOffset)); 3107feaf7c6SAlex Lorenz return C; 3117feaf7c6SAlex Lorenz } 3127feaf7c6SAlex Lorenz 31331d70683SAlex Lorenz static Cursor maybeLexJumpTableIndex(Cursor C, MIToken &Token) { 31431d70683SAlex Lorenz return maybeLexIndex(C, Token, "%jump-table.", MIToken::JumpTableIndex); 31531d70683SAlex Lorenz } 31631d70683SAlex Lorenz 3177feaf7c6SAlex Lorenz static Cursor maybeLexStackObject(Cursor C, MIToken &Token) { 3187feaf7c6SAlex Lorenz return maybeLexIndexAndName(C, Token, "%stack.", MIToken::StackObject); 3197feaf7c6SAlex Lorenz } 3207feaf7c6SAlex Lorenz 3217feaf7c6SAlex Lorenz static Cursor maybeLexFixedStackObject(Cursor C, MIToken &Token) { 3227feaf7c6SAlex Lorenz return maybeLexIndex(C, Token, "%fixed-stack.", MIToken::FixedStackObject); 3237feaf7c6SAlex Lorenz } 3247feaf7c6SAlex Lorenz 325ab980499SAlex Lorenz static Cursor maybeLexConstantPoolItem(Cursor C, MIToken &Token) { 326ab980499SAlex Lorenz return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem); 327ab980499SAlex Lorenz } 328ab980499SAlex Lorenz 329deb53490SAlex Lorenz static Cursor maybeLexIRBlock( 330deb53490SAlex Lorenz Cursor C, MIToken &Token, 331deb53490SAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 332deb53490SAlex Lorenz const StringRef Rule = "%ir-block."; 333deb53490SAlex Lorenz if (!C.remaining().startswith(Rule)) 334deb53490SAlex Lorenz return None; 335deb53490SAlex Lorenz if (isdigit(C.peek(Rule.size()))) 336deb53490SAlex Lorenz return maybeLexIndex(C, Token, Rule, MIToken::IRBlock); 337970c12eaSAlex Lorenz return lexName(C, Token, MIToken::NamedIRBlock, Rule.size(), ErrorCallback); 3388a1915b0SAlex Lorenz } 3398a1915b0SAlex Lorenz 3404af7e610SAlex Lorenz static Cursor maybeLexIRValue( 3414af7e610SAlex Lorenz Cursor C, MIToken &Token, 3424af7e610SAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 3434af7e610SAlex Lorenz const StringRef Rule = "%ir."; 3444af7e610SAlex Lorenz if (!C.remaining().startswith(Rule)) 3454af7e610SAlex Lorenz return None; 346dd13be0bSAlex Lorenz if (isdigit(C.peek(Rule.size()))) 347dd13be0bSAlex Lorenz return maybeLexIndex(C, Token, Rule, MIToken::IRValue); 348970c12eaSAlex Lorenz return lexName(C, Token, MIToken::NamedIRValue, Rule.size(), ErrorCallback); 3494af7e610SAlex Lorenz } 3504af7e610SAlex Lorenz 35153464510SAlex Lorenz static Cursor lexVirtualRegister(Cursor C, MIToken &Token) { 35253464510SAlex Lorenz auto Range = C; 35353464510SAlex Lorenz C.advance(); // Skip '%' 35453464510SAlex Lorenz auto NumberRange = C; 35553464510SAlex Lorenz while (isdigit(C.peek())) 35653464510SAlex Lorenz C.advance(); 3573fb77686SAlex Lorenz Token.reset(MIToken::VirtualRegister, Range.upto(C)) 3583fb77686SAlex Lorenz .setIntegerValue(APSInt(NumberRange.upto(C))); 35953464510SAlex Lorenz return C; 36053464510SAlex Lorenz } 36153464510SAlex Lorenz 3626c6c46e4SAlex Lorenz static Cursor maybeLexRegister(Cursor C, MIToken &Token) { 3636c6c46e4SAlex Lorenz if (C.peek() != '%') 3646c6c46e4SAlex Lorenz return None; 36553464510SAlex Lorenz if (isdigit(C.peek(1))) 36653464510SAlex Lorenz return lexVirtualRegister(C, Token); 367f3db51deSAlex Lorenz auto Range = C; 368f3db51deSAlex Lorenz C.advance(); // Skip '%' 369f3db51deSAlex Lorenz while (isIdentifierChar(C.peek())) 370f3db51deSAlex Lorenz C.advance(); 3713fb77686SAlex Lorenz Token.reset(MIToken::NamedRegister, Range.upto(C)) 3723fb77686SAlex Lorenz .setStringValue(Range.upto(C).drop_front(1)); // Drop the '%' 373f3db51deSAlex Lorenz return C; 374f3db51deSAlex Lorenz } 375f3db51deSAlex Lorenz 376c1fbb354SAlex Lorenz static Cursor maybeLexGlobalValue( 377c1fbb354SAlex Lorenz Cursor C, MIToken &Token, 378c1fbb354SAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 379c1fbb354SAlex Lorenz if (C.peek() != '@') 380c1fbb354SAlex Lorenz return None; 381c1fbb354SAlex Lorenz if (!isdigit(C.peek(1))) 382970c12eaSAlex Lorenz return lexName(C, Token, MIToken::NamedGlobalValue, /*PrefixLength=*/1, 383c1fbb354SAlex Lorenz ErrorCallback); 384c1fbb354SAlex Lorenz auto Range = C; 385c1fbb354SAlex Lorenz C.advance(1); // Skip the '@' 386c1fbb354SAlex Lorenz auto NumberRange = C; 387c1fbb354SAlex Lorenz while (isdigit(C.peek())) 388c1fbb354SAlex Lorenz C.advance(); 3893fb77686SAlex Lorenz Token.reset(MIToken::GlobalValue, Range.upto(C)) 3903fb77686SAlex Lorenz .setIntegerValue(APSInt(NumberRange.upto(C))); 391c1fbb354SAlex Lorenz return C; 392c1fbb354SAlex Lorenz } 393c1fbb354SAlex Lorenz 3946ede3744SAlex Lorenz static Cursor maybeLexExternalSymbol( 3956ede3744SAlex Lorenz Cursor C, MIToken &Token, 3966ede3744SAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 3976ede3744SAlex Lorenz if (C.peek() != '$') 3986ede3744SAlex Lorenz return None; 399970c12eaSAlex Lorenz return lexName(C, Token, MIToken::ExternalSymbol, /*PrefixLength=*/1, 400970c12eaSAlex Lorenz ErrorCallback); 4016ede3744SAlex Lorenz } 4026ede3744SAlex Lorenz 403ad156fb6SAlex Lorenz static bool isValidHexFloatingPointPrefix(char C) { 404ad156fb6SAlex Lorenz return C == 'H' || C == 'K' || C == 'L' || C == 'M'; 405ad156fb6SAlex Lorenz } 406ad156fb6SAlex Lorenz 407ad156fb6SAlex Lorenz static Cursor maybeLexHexFloatingPointLiteral(Cursor C, MIToken &Token) { 408ad156fb6SAlex Lorenz if (C.peek() != '0' || C.peek(1) != 'x') 409ad156fb6SAlex Lorenz return None; 410ad156fb6SAlex Lorenz Cursor Range = C; 411ad156fb6SAlex Lorenz C.advance(2); // Skip '0x' 412ad156fb6SAlex Lorenz if (isValidHexFloatingPointPrefix(C.peek())) 413ad156fb6SAlex Lorenz C.advance(); 414ad156fb6SAlex Lorenz while (isxdigit(C.peek())) 415ad156fb6SAlex Lorenz C.advance(); 4163fb77686SAlex Lorenz Token.reset(MIToken::FloatingPointLiteral, Range.upto(C)); 417ad156fb6SAlex Lorenz return C; 418ad156fb6SAlex Lorenz } 419ad156fb6SAlex Lorenz 420ad156fb6SAlex Lorenz static Cursor lexFloatingPointLiteral(Cursor Range, Cursor C, MIToken &Token) { 421ad156fb6SAlex Lorenz C.advance(); 422ad156fb6SAlex Lorenz // Skip over [0-9]*([eE][-+]?[0-9]+)? 423ad156fb6SAlex Lorenz while (isdigit(C.peek())) 424ad156fb6SAlex Lorenz C.advance(); 425ad156fb6SAlex Lorenz if ((C.peek() == 'e' || C.peek() == 'E') && 426ad156fb6SAlex Lorenz (isdigit(C.peek(1)) || 427ad156fb6SAlex Lorenz ((C.peek(1) == '-' || C.peek(1) == '+') && isdigit(C.peek(2))))) { 428ad156fb6SAlex Lorenz C.advance(2); 429ad156fb6SAlex Lorenz while (isdigit(C.peek())) 430ad156fb6SAlex Lorenz C.advance(); 431ad156fb6SAlex Lorenz } 4323fb77686SAlex Lorenz Token.reset(MIToken::FloatingPointLiteral, Range.upto(C)); 433ad156fb6SAlex Lorenz return C; 434ad156fb6SAlex Lorenz } 435ad156fb6SAlex Lorenz 436ad156fb6SAlex Lorenz static Cursor maybeLexNumericalLiteral(Cursor C, MIToken &Token) { 4376c6c46e4SAlex Lorenz if (!isdigit(C.peek()) && (C.peek() != '-' || !isdigit(C.peek(1)))) 4386c6c46e4SAlex Lorenz return None; 439240fc1e0SAlex Lorenz auto Range = C; 440240fc1e0SAlex Lorenz C.advance(); 441240fc1e0SAlex Lorenz while (isdigit(C.peek())) 442240fc1e0SAlex Lorenz C.advance(); 443ad156fb6SAlex Lorenz if (C.peek() == '.') 444ad156fb6SAlex Lorenz return lexFloatingPointLiteral(Range, C, Token); 445240fc1e0SAlex Lorenz StringRef StrVal = Range.upto(C); 4463fb77686SAlex Lorenz Token.reset(MIToken::IntegerLiteral, StrVal).setIntegerValue(APSInt(StrVal)); 447240fc1e0SAlex Lorenz return C; 448240fc1e0SAlex Lorenz } 449240fc1e0SAlex Lorenz 450a617c916SAlex Lorenz static MIToken::TokenKind getMetadataKeywordKind(StringRef Identifier) { 451a617c916SAlex Lorenz return StringSwitch<MIToken::TokenKind>(Identifier) 452a617c916SAlex Lorenz .Case("!tbaa", MIToken::md_tbaa) 453a16f624dSAlex Lorenz .Case("!alias.scope", MIToken::md_alias_scope) 45403e940d1SAlex Lorenz .Case("!noalias", MIToken::md_noalias) 455eb625686SAlex Lorenz .Case("!range", MIToken::md_range) 456a617c916SAlex Lorenz .Default(MIToken::Error); 457a617c916SAlex Lorenz } 458a617c916SAlex Lorenz 459a617c916SAlex Lorenz static Cursor maybeLexExlaim( 460a617c916SAlex Lorenz Cursor C, MIToken &Token, 461a617c916SAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 462a617c916SAlex Lorenz if (C.peek() != '!') 463a617c916SAlex Lorenz return None; 464a617c916SAlex Lorenz auto Range = C; 465a617c916SAlex Lorenz C.advance(1); 466a617c916SAlex Lorenz if (isdigit(C.peek()) || !isIdentifierChar(C.peek())) { 467a617c916SAlex Lorenz Token.reset(MIToken::exclaim, Range.upto(C)); 468a617c916SAlex Lorenz return C; 469a617c916SAlex Lorenz } 470a617c916SAlex Lorenz while (isIdentifierChar(C.peek())) 471a617c916SAlex Lorenz C.advance(); 472a617c916SAlex Lorenz StringRef StrVal = Range.upto(C); 473a617c916SAlex Lorenz Token.reset(getMetadataKeywordKind(StrVal), StrVal); 474a617c916SAlex Lorenz if (Token.isError()) 475a617c916SAlex Lorenz ErrorCallback(Token.location(), 476a617c916SAlex Lorenz "use of unknown metadata keyword '" + StrVal + "'"); 477a617c916SAlex Lorenz return C; 478a617c916SAlex Lorenz } 479a617c916SAlex Lorenz 480f3db51deSAlex Lorenz static MIToken::TokenKind symbolToken(char C) { 481f3db51deSAlex Lorenz switch (C) { 482f3db51deSAlex Lorenz case ',': 483f3db51deSAlex Lorenz return MIToken::comma; 484f3db51deSAlex Lorenz case '=': 485f3db51deSAlex Lorenz return MIToken::equal; 4862eacca86SAlex Lorenz case ':': 4872eacca86SAlex Lorenz return MIToken::colon; 488deb53490SAlex Lorenz case '(': 489deb53490SAlex Lorenz return MIToken::lparen; 490deb53490SAlex Lorenz case ')': 491deb53490SAlex Lorenz return MIToken::rparen; 492f9a2b123SAlex Lorenz case '{': 493f9a2b123SAlex Lorenz return MIToken::lbrace; 494f9a2b123SAlex Lorenz case '}': 495f9a2b123SAlex Lorenz return MIToken::rbrace; 4965672a893SAlex Lorenz case '+': 4975672a893SAlex Lorenz return MIToken::plus; 4985672a893SAlex Lorenz case '-': 4995672a893SAlex Lorenz return MIToken::minus; 500*287c6bb5SQuentin Colombet case '<': 501*287c6bb5SQuentin Colombet return MIToken::lt; 502*287c6bb5SQuentin Colombet case '>': 503*287c6bb5SQuentin Colombet return MIToken::gt; 504f3db51deSAlex Lorenz default: 505f3db51deSAlex Lorenz return MIToken::Error; 506f3db51deSAlex Lorenz } 507f3db51deSAlex Lorenz } 508f3db51deSAlex Lorenz 5096c6c46e4SAlex Lorenz static Cursor maybeLexSymbol(Cursor C, MIToken &Token) { 5104af7e610SAlex Lorenz MIToken::TokenKind Kind; 5114af7e610SAlex Lorenz unsigned Length = 1; 5124af7e610SAlex Lorenz if (C.peek() == ':' && C.peek(1) == ':') { 5134af7e610SAlex Lorenz Kind = MIToken::coloncolon; 5144af7e610SAlex Lorenz Length = 2; 5154af7e610SAlex Lorenz } else 5164af7e610SAlex Lorenz Kind = symbolToken(C.peek()); 5176c6c46e4SAlex Lorenz if (Kind == MIToken::Error) 5186c6c46e4SAlex Lorenz return None; 519f3db51deSAlex Lorenz auto Range = C; 5204af7e610SAlex Lorenz C.advance(Length); 5213fb77686SAlex Lorenz Token.reset(Kind, Range.upto(C)); 522f3db51deSAlex Lorenz return C; 523f3db51deSAlex Lorenz } 524f3db51deSAlex Lorenz 5255022f6bbSAlex Lorenz static Cursor maybeLexNewline(Cursor C, MIToken &Token) { 5265022f6bbSAlex Lorenz if (!isNewlineChar(C.peek())) 5275022f6bbSAlex Lorenz return None; 5285022f6bbSAlex Lorenz auto Range = C; 5295022f6bbSAlex Lorenz C.advance(); 5305022f6bbSAlex Lorenz Token.reset(MIToken::Newline, Range.upto(C)); 5315022f6bbSAlex Lorenz return C; 5325022f6bbSAlex Lorenz } 5335022f6bbSAlex Lorenz 534c1136ef3SAlex Lorenz static Cursor maybeLexEscapedIRValue( 535c1136ef3SAlex Lorenz Cursor C, MIToken &Token, 536c1136ef3SAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 537c1136ef3SAlex Lorenz if (C.peek() != '`') 538c1136ef3SAlex Lorenz return None; 539c1136ef3SAlex Lorenz auto Range = C; 540c1136ef3SAlex Lorenz C.advance(); 541c1136ef3SAlex Lorenz auto StrRange = C; 542c1136ef3SAlex Lorenz while (C.peek() != '`') { 543c1136ef3SAlex Lorenz if (C.isEOF() || isNewlineChar(C.peek())) { 544c1136ef3SAlex Lorenz ErrorCallback( 545c1136ef3SAlex Lorenz C.location(), 546c1136ef3SAlex Lorenz "end of machine instruction reached before the closing '`'"); 547c1136ef3SAlex Lorenz Token.reset(MIToken::Error, Range.remaining()); 548c1136ef3SAlex Lorenz return C; 549c1136ef3SAlex Lorenz } 550c1136ef3SAlex Lorenz C.advance(); 551c1136ef3SAlex Lorenz } 552c1136ef3SAlex Lorenz StringRef Value = StrRange.upto(C); 553c1136ef3SAlex Lorenz C.advance(); 554c1136ef3SAlex Lorenz Token.reset(MIToken::QuotedIRValue, Range.upto(C)).setStringValue(Value); 555c1136ef3SAlex Lorenz return C; 556c1136ef3SAlex Lorenz } 557c1136ef3SAlex Lorenz 55891370c5dSAlex Lorenz StringRef llvm::lexMIToken( 55991370c5dSAlex Lorenz StringRef Source, MIToken &Token, 56091370c5dSAlex Lorenz function_ref<void(StringRef::iterator Loc, const Twine &)> ErrorCallback) { 5615022f6bbSAlex Lorenz auto C = skipComment(skipWhitespace(Cursor(Source))); 56291370c5dSAlex Lorenz if (C.isEOF()) { 5633fb77686SAlex Lorenz Token.reset(MIToken::Eof, C.remaining()); 56491370c5dSAlex Lorenz return C.remaining(); 56591370c5dSAlex Lorenz } 56691370c5dSAlex Lorenz 56705e3882eSAlex Lorenz if (Cursor R = maybeLexIntegerType(C, Token)) 56805e3882eSAlex Lorenz return R.remaining(); 5696c6c46e4SAlex Lorenz if (Cursor R = maybeLexMachineBasicBlock(C, Token, ErrorCallback)) 5706c6c46e4SAlex Lorenz return R.remaining(); 5715022f6bbSAlex Lorenz if (Cursor R = maybeLexIdentifier(C, Token)) 5725022f6bbSAlex Lorenz return R.remaining(); 57331d70683SAlex Lorenz if (Cursor R = maybeLexJumpTableIndex(C, Token)) 57431d70683SAlex Lorenz return R.remaining(); 5757feaf7c6SAlex Lorenz if (Cursor R = maybeLexStackObject(C, Token)) 5767feaf7c6SAlex Lorenz return R.remaining(); 5777feaf7c6SAlex Lorenz if (Cursor R = maybeLexFixedStackObject(C, Token)) 5787feaf7c6SAlex Lorenz return R.remaining(); 579ab980499SAlex Lorenz if (Cursor R = maybeLexConstantPoolItem(C, Token)) 580ab980499SAlex Lorenz return R.remaining(); 581deb53490SAlex Lorenz if (Cursor R = maybeLexIRBlock(C, Token, ErrorCallback)) 5828a1915b0SAlex Lorenz return R.remaining(); 5834af7e610SAlex Lorenz if (Cursor R = maybeLexIRValue(C, Token, ErrorCallback)) 5844af7e610SAlex Lorenz return R.remaining(); 5856c6c46e4SAlex Lorenz if (Cursor R = maybeLexRegister(C, Token)) 5866c6c46e4SAlex Lorenz return R.remaining(); 587b29554daSAlex Lorenz if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback)) 5886c6c46e4SAlex Lorenz return R.remaining(); 5896ede3744SAlex Lorenz if (Cursor R = maybeLexExternalSymbol(C, Token, ErrorCallback)) 5906ede3744SAlex Lorenz return R.remaining(); 591ad156fb6SAlex Lorenz if (Cursor R = maybeLexHexFloatingPointLiteral(C, Token)) 592ad156fb6SAlex Lorenz return R.remaining(); 593ad156fb6SAlex Lorenz if (Cursor R = maybeLexNumericalLiteral(C, Token)) 5946c6c46e4SAlex Lorenz return R.remaining(); 595a617c916SAlex Lorenz if (Cursor R = maybeLexExlaim(C, Token, ErrorCallback)) 596a617c916SAlex Lorenz return R.remaining(); 5976c6c46e4SAlex Lorenz if (Cursor R = maybeLexSymbol(C, Token)) 5986c6c46e4SAlex Lorenz return R.remaining(); 5995022f6bbSAlex Lorenz if (Cursor R = maybeLexNewline(C, Token)) 6005022f6bbSAlex Lorenz return R.remaining(); 601c1136ef3SAlex Lorenz if (Cursor R = maybeLexEscapedIRValue(C, Token, ErrorCallback)) 602c1136ef3SAlex Lorenz return R.remaining(); 6036c6c46e4SAlex Lorenz 6043fb77686SAlex Lorenz Token.reset(MIToken::Error, C.remaining()); 60591370c5dSAlex Lorenz ErrorCallback(C.location(), 6066c6c46e4SAlex Lorenz Twine("unexpected character '") + Twine(C.peek()) + "'"); 60791370c5dSAlex Lorenz return C.remaining(); 60891370c5dSAlex Lorenz } 609