static Cursor maybeLexMachineBasicBlock(Cursor C, MIToken &Token, ErrorCallbackType ErrorCallback) { bool IsReference = C.remaining().startswith("%bb."); if (!IsReference && !C.remaining().startswith("bb.")) return None; auto Range = C; unsigned PrefixLength = IsReference ? 4 : 3; C.advance(PrefixLength); // Skip '%bb.' or 'bb.' if (!isdigit(C.peek())) { Token.reset(MIToken::Error, C.remaining()); ErrorCallback(C.location(), "expected a number after '%bb.'"); return C; } auto NumberRange = C; while (isdigit(C.peek())) C.advance(); StringRef Number = NumberRange.upto(C); unsigned StringOffset = PrefixLength + Number.size(); // Drop '%bb.<id>' // TODO: The format bb.<id>.<irname> is supported only when it's not a // reference. Once we deprecate the format where the irname shows up, we // should only lex forward if it is a reference. if (C.peek() == '.') { C.advance(); // Skip '.' ++StringOffset; while (isIdentifierChar(C.peek())) C.advance(); } Token.reset(IsReference ? MIToken::MachineBasicBlock : MIToken::MachineBasicBlockLabel, Range.upto(C)) .setIntegerValue(APSInt(Number)) .setStringValue(Range.upto(C).drop_front(StringOffset)); return C; }
StringRef llvm::lexMIToken(StringRef Source, MIToken &Token, ErrorCallbackType ErrorCallback) { auto C = skipComment(skipWhitespace(Cursor(Source))); if (C.isEOF()) { Token.reset(MIToken::Eof, C.remaining()); return C.remaining(); } if (Cursor R = maybeLexIntegerOrScalarType(C, Token)) return R.remaining(); if (Cursor R = maybeLexMachineBasicBlock(C, Token, ErrorCallback)) return R.remaining(); if (Cursor R = maybeLexIdentifier(C, Token)) return R.remaining(); if (Cursor R = maybeLexJumpTableIndex(C, Token)) return R.remaining(); if (Cursor R = maybeLexStackObject(C, Token)) return R.remaining(); if (Cursor R = maybeLexFixedStackObject(C, Token)) return R.remaining(); if (Cursor R = maybeLexConstantPoolItem(C, Token)) return R.remaining(); if (Cursor R = maybeLexSubRegisterIndex(C, Token, ErrorCallback)) return R.remaining(); if (Cursor R = maybeLexIRBlock(C, Token, ErrorCallback)) return R.remaining(); if (Cursor R = maybeLexIRValue(C, Token, ErrorCallback)) return R.remaining(); if (Cursor R = maybeLexRegister(C, Token)) return R.remaining(); if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback)) return R.remaining(); if (Cursor R = maybeLexExternalSymbol(C, Token, ErrorCallback)) return R.remaining(); if (Cursor R = maybeLexHexadecimalLiteral(C, Token)) return R.remaining(); if (Cursor R = maybeLexNumericalLiteral(C, Token)) return R.remaining(); if (Cursor R = maybeLexExlaim(C, Token, ErrorCallback)) return R.remaining(); if (Cursor R = maybeLexSymbol(C, Token)) return R.remaining(); if (Cursor R = maybeLexNewline(C, Token)) return R.remaining(); if (Cursor R = maybeLexEscapedIRValue(C, Token, ErrorCallback)) return R.remaining(); if (Cursor R = maybeLexStringConstant(C, Token, ErrorCallback)) return R.remaining(); Token.reset(MIToken::Error, C.remaining()); ErrorCallback(C.location(), Twine("unexpected character '") + Twine(C.peek()) + "'"); return C.remaining(); }
static Cursor maybeLexNewline(Cursor C, MIToken &Token) { if (!isNewlineChar(C.peek())) return None; auto Range = C; C.advance(); Token.reset(MIToken::Newline, Range.upto(C)); return C; }
static Cursor maybeLexIntegerType(Cursor C, MIToken &Token) { if (C.peek() != 'i' || !isdigit(C.peek(1))) return None; auto Range = C; C.advance(); // Skip 'i' while (isdigit(C.peek())) C.advance(); Token.reset(MIToken::IntegerType, Range.upto(C)); return C; }
static Cursor lexVirtualRegister(Cursor C, MIToken &Token) { auto Range = C; C.advance(); // Skip '%' auto NumberRange = C; while (isdigit(C.peek())) C.advance(); Token.reset(MIToken::VirtualRegister, Range.upto(C)) .setIntegerValue(APSInt(NumberRange.upto(C))); return C; }
static Cursor maybeLexExlaim(Cursor C, MIToken &Token, ErrorCallbackType ErrorCallback) { if (C.peek() != '!') return None; auto Range = C; C.advance(1); if (isdigit(C.peek()) || !isIdentifierChar(C.peek())) { Token.reset(MIToken::exclaim, Range.upto(C)); return C; } while (isIdentifierChar(C.peek())) C.advance(); StringRef StrVal = Range.upto(C); Token.reset(getMetadataKeywordKind(StrVal), StrVal); if (Token.isError()) ErrorCallback(Token.location(), "use of unknown metadata keyword '" + StrVal + "'"); return C; }
static Cursor maybeLexIdentifier(Cursor C, MIToken &Token) { if (!isalpha(C.peek()) && C.peek() != '_') return None; auto Range = C; while (isIdentifierChar(C.peek())) C.advance(); auto Identifier = Range.upto(C); Token.reset(getIdentifierKind(Identifier), Identifier) .setStringValue(Identifier); return C; }
static Cursor lexName(Cursor C, MIToken &Token, MIToken::TokenKind Type, unsigned PrefixLength, ErrorCallbackType ErrorCallback) { auto Range = C; C.advance(PrefixLength); if (C.peek() == '"') { if (Cursor R = lexStringConstant(C, ErrorCallback)) { StringRef String = Range.upto(R); Token.reset(Type, String) .setOwnedStringValue( unescapeQuotedString(String.drop_front(PrefixLength))); return R; } Token.reset(MIToken::Error, Range.remaining()); return Range; } while (isIdentifierChar(C.peek())) C.advance(); Token.reset(Type, Range.upto(C)) .setStringValue(Range.upto(C).drop_front(PrefixLength)); return C; }
static Cursor maybeLexHexadecimalLiteral(Cursor C, MIToken &Token) { if (C.peek() != '0' || (C.peek(1) != 'x' && C.peek(1) != 'X')) return None; Cursor Range = C; C.advance(2); unsigned PrefLen = 2; if (isValidHexFloatingPointPrefix(C.peek())) { C.advance(); PrefLen++; } while (isxdigit(C.peek())) C.advance(); StringRef StrVal = Range.upto(C); if (StrVal.size() <= PrefLen) return None; if (PrefLen == 2) Token.reset(MIToken::HexLiteral, Range.upto(C)); else // It must be 3, which means that there was a floating-point prefix. Token.reset(MIToken::FloatingPointLiteral, Range.upto(C)); return C; }
static Cursor maybeLexHexFloatingPointLiteral(Cursor C, MIToken &Token) { if (C.peek() != '0' || C.peek(1) != 'x') return None; Cursor Range = C; C.advance(2); // Skip '0x' if (isValidHexFloatingPointPrefix(C.peek())) C.advance(); while (isxdigit(C.peek())) C.advance(); Token.reset(MIToken::FloatingPointLiteral, Range.upto(C)); return C; }
static Cursor maybeLexIndex(Cursor C, MIToken &Token, StringRef Rule, MIToken::TokenKind Kind) { if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size()))) return None; auto Range = C; C.advance(Rule.size()); auto NumberRange = C; while (isdigit(C.peek())) C.advance(); Token.reset(Kind, Range.upto(C)).setIntegerValue(APSInt(NumberRange.upto(C))); return C; }
static Cursor maybeLexRegister(Cursor C, MIToken &Token) { if (C.peek() != '%') return None; if (isdigit(C.peek(1))) return lexVirtualRegister(C, Token); auto Range = C; C.advance(); // Skip '%' while (isRegisterChar(C.peek())) C.advance(); Token.reset(MIToken::NamedRegister, Range.upto(C)) .setStringValue(Range.upto(C).drop_front(1)); // Drop the '%' return C; }
static Cursor maybeLexEscapedIRValue(Cursor C, MIToken &Token, ErrorCallbackType ErrorCallback) { if (C.peek() != '`') return None; auto Range = C; C.advance(); auto StrRange = C; while (C.peek() != '`') { if (C.isEOF() || isNewlineChar(C.peek())) { ErrorCallback( C.location(), "end of machine instruction reached before the closing '`'"); Token.reset(MIToken::Error, Range.remaining()); return C; } C.advance(); } StringRef Value = StrRange.upto(C); C.advance(); Token.reset(MIToken::QuotedIRValue, Range.upto(C)).setStringValue(Value); return C; }
static Cursor maybeLexNumericalLiteral(Cursor C, MIToken &Token) { if (!isdigit(C.peek()) && (C.peek() != '-' || !isdigit(C.peek(1)))) return None; auto Range = C; C.advance(); while (isdigit(C.peek())) C.advance(); if (C.peek() == '.') return lexFloatingPointLiteral(Range, C, Token); StringRef StrVal = Range.upto(C); Token.reset(MIToken::IntegerLiteral, StrVal).setIntegerValue(APSInt(StrVal)); return C; }
static Cursor maybeLexSymbol(Cursor C, MIToken &Token) { MIToken::TokenKind Kind; unsigned Length = 1; if (C.peek() == ':' && C.peek(1) == ':') { Kind = MIToken::coloncolon; Length = 2; } else Kind = symbolToken(C.peek()); if (Kind == MIToken::Error) return None; auto Range = C; C.advance(Length); Token.reset(Kind, Range.upto(C)); return C; }
static Cursor lexFloatingPointLiteral(Cursor Range, Cursor C, MIToken &Token) { C.advance(); // Skip over [0-9]*([eE][-+]?[0-9]+)? while (isdigit(C.peek())) C.advance(); if ((C.peek() == 'e' || C.peek() == 'E') && (isdigit(C.peek(1)) || ((C.peek(1) == '-' || C.peek(1) == '+') && isdigit(C.peek(2))))) { C.advance(2); while (isdigit(C.peek())) C.advance(); } Token.reset(MIToken::FloatingPointLiteral, Range.upto(C)); return C; }
static Cursor maybeLexGlobalValue(Cursor C, MIToken &Token, ErrorCallbackType ErrorCallback) { if (C.peek() != '@') return None; if (!isdigit(C.peek(1))) return lexName(C, Token, MIToken::NamedGlobalValue, /*PrefixLength=*/1, ErrorCallback); auto Range = C; C.advance(1); // Skip the '@' auto NumberRange = C; while (isdigit(C.peek())) C.advance(); Token.reset(MIToken::GlobalValue, Range.upto(C)) .setIntegerValue(APSInt(NumberRange.upto(C))); return C; }
static Cursor maybeLexIntegerOrScalarType(Cursor C, MIToken &Token) { if ((C.peek() != 'i' && C.peek() != 's' && C.peek() != 'p') || !isdigit(C.peek(1))) return None; char Kind = C.peek(); auto Range = C; C.advance(); // Skip 'i', 's', or 'p' while (isdigit(C.peek())) C.advance(); Token.reset(Kind == 'i' ? MIToken::IntegerType : (Kind == 's' ? MIToken::ScalarType : MIToken::PointerType), Range.upto(C)); return C; }
static Cursor maybeLexIndexAndName(Cursor C, MIToken &Token, StringRef Rule, MIToken::TokenKind Kind) { if (!C.remaining().startswith(Rule) || !isdigit(C.peek(Rule.size()))) return None; auto Range = C; C.advance(Rule.size()); auto NumberRange = C; while (isdigit(C.peek())) C.advance(); StringRef Number = NumberRange.upto(C); unsigned StringOffset = Rule.size() + Number.size(); if (C.peek() == '.') { C.advance(); ++StringOffset; while (isIdentifierChar(C.peek())) C.advance(); } Token.reset(Kind, Range.upto(C)) .setIntegerValue(APSInt(Number)) .setStringValue(Range.upto(C).drop_front(StringOffset)); return C; }