1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-20 03:23:01 +02:00
llvm-mirror/lib/MC/MCParser/AsmLexer.cpp
Chandler Carruth eb66b33867 Sort the remaining #include lines in include/... and lib/....
I did this a long time ago with a janky python script, but now
clang-format has built-in support for this. I fed clang-format every
line with a #include and let it re-sort things according to the precise
LLVM rules for include ordering baked into clang-format these days.

I've reverted a number of files where the results of sorting includes
isn't healthy. Either places where we have legacy code relying on
particular include ordering (where possible, I'll fix these separately)
or where we have particular formatting around #include lines that
I didn't want to disturb in this patch.

This patch is *entirely* mechanical. If you get merge conflicts or
anything, just ignore the changes in this patch and run clang-format
over your #include lines in the files.

Sorry for any noise here, but it is important to keep these things
stable. I was seeing an increasing number of patches with irrelevant
re-ordering of #include lines because clang-format was used. This patch
at least isolates that churn, makes it easy to skip when resolving
conflicts, and gets us to a clean baseline (again).

llvm-svn: 304787
2017-06-06 11:49:48 +00:00

734 lines
24 KiB
C++

//===- AsmLexer.cpp - Lexer for Assembly Files ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class implements the lexer for assembly files.
//
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCParser/AsmLexer.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SaveAndRestore.h"
#include <cassert>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <string>
#include <tuple>
#include <utility>
using namespace llvm;
AsmLexer::AsmLexer(const MCAsmInfo &MAI) : MAI(MAI) {
AllowAtInIdentifier = !StringRef(MAI.getCommentString()).startswith("@");
}
AsmLexer::~AsmLexer() = default;
void AsmLexer::setBuffer(StringRef Buf, const char *ptr) {
CurBuf = Buf;
if (ptr)
CurPtr = ptr;
else
CurPtr = CurBuf.begin();
TokStart = nullptr;
}
/// ReturnError - Set the error to the specified string at the specified
/// location. This is defined to always return AsmToken::Error.
AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) {
SetError(SMLoc::getFromPointer(Loc), Msg);
return AsmToken(AsmToken::Error, StringRef(Loc, CurPtr - Loc));
}
int AsmLexer::getNextChar() {
if (CurPtr == CurBuf.end())
return EOF;
return (unsigned char)*CurPtr++;
}
/// LexFloatLiteral: [0-9]*[.][0-9]*([eE][+-]?[0-9]*)?
///
/// The leading integral digit sequence and dot should have already been
/// consumed, some or all of the fractional digit sequence *can* have been
/// consumed.
AsmToken AsmLexer::LexFloatLiteral() {
// Skip the fractional digit sequence.
while (isdigit(*CurPtr))
++CurPtr;
// Check for exponent; we intentionally accept a slighlty wider set of
// literals here and rely on the upstream client to reject invalid ones (e.g.,
// "1e+").
if (*CurPtr == 'e' || *CurPtr == 'E') {
++CurPtr;
if (*CurPtr == '-' || *CurPtr == '+')
++CurPtr;
while (isdigit(*CurPtr))
++CurPtr;
}
return AsmToken(AsmToken::Real,
StringRef(TokStart, CurPtr - TokStart));
}
/// LexHexFloatLiteral matches essentially (.[0-9a-fA-F]*)?[pP][+-]?[0-9a-fA-F]+
/// while making sure there are enough actual digits around for the constant to
/// be valid.
///
/// The leading "0x[0-9a-fA-F]*" (i.e. integer part) has already been consumed
/// before we get here.
AsmToken AsmLexer::LexHexFloatLiteral(bool NoIntDigits) {
assert((*CurPtr == 'p' || *CurPtr == 'P' || *CurPtr == '.') &&
"unexpected parse state in floating hex");
bool NoFracDigits = true;
// Skip the fractional part if there is one
if (*CurPtr == '.') {
++CurPtr;
const char *FracStart = CurPtr;
while (isxdigit(*CurPtr))
++CurPtr;
NoFracDigits = CurPtr == FracStart;
}
if (NoIntDigits && NoFracDigits)
return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
"expected at least one significand digit");
// Make sure we do have some kind of proper exponent part
if (*CurPtr != 'p' && *CurPtr != 'P')
return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
"expected exponent part 'p'");
++CurPtr;
if (*CurPtr == '+' || *CurPtr == '-')
++CurPtr;
// N.b. exponent digits are *not* hex
const char *ExpStart = CurPtr;
while (isdigit(*CurPtr))
++CurPtr;
if (CurPtr == ExpStart)
return ReturnError(TokStart, "invalid hexadecimal floating-point constant: "
"expected at least one exponent digit");
return AsmToken(AsmToken::Real, StringRef(TokStart, CurPtr - TokStart));
}
/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@?]*
static bool IsIdentifierChar(char c, bool AllowAt) {
return isalnum(c) || c == '_' || c == '$' || c == '.' ||
(c == '@' && AllowAt) || c == '?';
}
AsmToken AsmLexer::LexIdentifier() {
// Check for floating point literals.
if (CurPtr[-1] == '.' && isdigit(*CurPtr)) {
// Disambiguate a .1243foo identifier from a floating literal.
while (isdigit(*CurPtr))
++CurPtr;
if (*CurPtr == 'e' || *CurPtr == 'E' ||
!IsIdentifierChar(*CurPtr, AllowAtInIdentifier))
return LexFloatLiteral();
}
while (IsIdentifierChar(*CurPtr, AllowAtInIdentifier))
++CurPtr;
// Handle . as a special case.
if (CurPtr == TokStart+1 && TokStart[0] == '.')
return AsmToken(AsmToken::Dot, StringRef(TokStart, 1));
return AsmToken(AsmToken::Identifier, StringRef(TokStart, CurPtr - TokStart));
}
/// LexSlash: Slash: /
/// C-Style Comment: /* ... */
AsmToken AsmLexer::LexSlash() {
switch (*CurPtr) {
case '*':
IsAtStartOfStatement = false;
break; // C style comment.
case '/':
++CurPtr;
return LexLineComment();
default:
IsAtStartOfStatement = false;
return AsmToken(AsmToken::Slash, StringRef(TokStart, 1));
}
// C Style comment.
++CurPtr; // skip the star.
const char *CommentTextStart = CurPtr;
while (CurPtr != CurBuf.end()) {
switch (*CurPtr++) {
case '*':
// End of the comment?
if (*CurPtr != '/')
break;
// If we have a CommentConsumer, notify it about the comment.
if (CommentConsumer) {
CommentConsumer->HandleComment(
SMLoc::getFromPointer(CommentTextStart),
StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
}
++CurPtr; // End the */.
return AsmToken(AsmToken::Comment,
StringRef(TokStart, CurPtr - TokStart));
}
}
return ReturnError(TokStart, "unterminated comment");
}
/// LexLineComment: Comment: #[^\n]*
/// : //[^\n]*
AsmToken AsmLexer::LexLineComment() {
// Mark This as an end of statement with a body of the
// comment. While it would be nicer to leave this two tokens,
// backwards compatability with TargetParsers makes keeping this in this form
// better.
const char *CommentTextStart = CurPtr;
int CurChar = getNextChar();
while (CurChar != '\n' && CurChar != '\r' && CurChar != EOF)
CurChar = getNextChar();
// If we have a CommentConsumer, notify it about the comment.
if (CommentConsumer) {
CommentConsumer->HandleComment(
SMLoc::getFromPointer(CommentTextStart),
StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
}
IsAtStartOfLine = true;
// This is a whole line comment. leave newline
if (IsAtStartOfStatement)
return AsmToken(AsmToken::EndOfStatement,
StringRef(TokStart, CurPtr - TokStart));
IsAtStartOfStatement = true;
return AsmToken(AsmToken::EndOfStatement,
StringRef(TokStart, CurPtr - 1 - TokStart));
}
static void SkipIgnoredIntegerSuffix(const char *&CurPtr) {
// Skip ULL, UL, U, L and LL suffices.
if (CurPtr[0] == 'U')
++CurPtr;
if (CurPtr[0] == 'L')
++CurPtr;
if (CurPtr[0] == 'L')
++CurPtr;
}
// Look ahead to search for first non-hex digit, if it's [hH], then we treat the
// integer as a hexadecimal, possibly with leading zeroes.
static unsigned doLookAhead(const char *&CurPtr, unsigned DefaultRadix) {
const char *FirstHex = nullptr;
const char *LookAhead = CurPtr;
while (true) {
if (isdigit(*LookAhead)) {
++LookAhead;
} else if (isxdigit(*LookAhead)) {
if (!FirstHex)
FirstHex = LookAhead;
++LookAhead;
} else {
break;
}
}
bool isHex = *LookAhead == 'h' || *LookAhead == 'H';
CurPtr = isHex || !FirstHex ? LookAhead : FirstHex;
if (isHex)
return 16;
return DefaultRadix;
}
static AsmToken intToken(StringRef Ref, APInt &Value)
{
if (Value.isIntN(64))
return AsmToken(AsmToken::Integer, Ref, Value);
return AsmToken(AsmToken::BigNum, Ref, Value);
}
/// LexDigit: First character is [0-9].
/// Local Label: [0-9][:]
/// Forward/Backward Label: [0-9][fb]
/// Binary integer: 0b[01]+
/// Octal integer: 0[0-7]+
/// Hex integer: 0x[0-9a-fA-F]+ or [0x]?[0-9][0-9a-fA-F]*[hH]
/// Decimal integer: [1-9][0-9]*
AsmToken AsmLexer::LexDigit() {
// MASM-flavor binary integer: [01]+[bB]
// MASM-flavor hexadecimal integer: [0-9][0-9a-fA-F]*[hH]
if (IsParsingMSInlineAsm && isdigit(CurPtr[-1])) {
const char *FirstNonBinary = (CurPtr[-1] != '0' && CurPtr[-1] != '1') ?
CurPtr - 1 : nullptr;
const char *OldCurPtr = CurPtr;
while (isxdigit(*CurPtr)) {
if (*CurPtr != '0' && *CurPtr != '1' && !FirstNonBinary)
FirstNonBinary = CurPtr;
++CurPtr;
}
unsigned Radix = 0;
if (*CurPtr == 'h' || *CurPtr == 'H') {
// hexadecimal number
++CurPtr;
Radix = 16;
} else if (FirstNonBinary && FirstNonBinary + 1 == CurPtr &&
(*FirstNonBinary == 'b' || *FirstNonBinary == 'B'))
Radix = 2;
if (Radix == 2 || Radix == 16) {
StringRef Result(TokStart, CurPtr - TokStart);
APInt Value(128, 0, true);
if (Result.drop_back().getAsInteger(Radix, Value))
return ReturnError(TokStart, Radix == 2 ? "invalid binary number" :
"invalid hexdecimal number");
// MSVC accepts and ignores type suffices on integer literals.
SkipIgnoredIntegerSuffix(CurPtr);
return intToken(Result, Value);
}
// octal/decimal integers, or floating point numbers, fall through
CurPtr = OldCurPtr;
}
// Decimal integer: [1-9][0-9]*
if (CurPtr[-1] != '0' || CurPtr[0] == '.') {
unsigned Radix = doLookAhead(CurPtr, 10);
bool isHex = Radix == 16;
// Check for floating point literals.
if (!isHex && (*CurPtr == '.' || *CurPtr == 'e')) {
++CurPtr;
return LexFloatLiteral();
}
StringRef Result(TokStart, CurPtr - TokStart);
APInt Value(128, 0, true);
if (Result.getAsInteger(Radix, Value))
return ReturnError(TokStart, !isHex ? "invalid decimal number" :
"invalid hexdecimal number");
// Consume the [bB][hH].
if (Radix == 2 || Radix == 16)
++CurPtr;
// The darwin/x86 (and x86-64) assembler accepts and ignores type
// suffices on integer literals.
SkipIgnoredIntegerSuffix(CurPtr);
return intToken(Result, Value);
}
if (!IsParsingMSInlineAsm && ((*CurPtr == 'b') || (*CurPtr == 'B'))) {
++CurPtr;
// See if we actually have "0b" as part of something like "jmp 0b\n"
if (!isdigit(CurPtr[0])) {
--CurPtr;
StringRef Result(TokStart, CurPtr - TokStart);
return AsmToken(AsmToken::Integer, Result, 0);
}
const char *NumStart = CurPtr;
while (CurPtr[0] == '0' || CurPtr[0] == '1')
++CurPtr;
// Requires at least one binary digit.
if (CurPtr == NumStart)
return ReturnError(TokStart, "invalid binary number");
StringRef Result(TokStart, CurPtr - TokStart);
APInt Value(128, 0, true);
if (Result.substr(2).getAsInteger(2, Value))
return ReturnError(TokStart, "invalid binary number");
// The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
// suffixes on integer literals.
SkipIgnoredIntegerSuffix(CurPtr);
return intToken(Result, Value);
}
if ((*CurPtr == 'x') || (*CurPtr == 'X')) {
++CurPtr;
const char *NumStart = CurPtr;
while (isxdigit(CurPtr[0]))
++CurPtr;
// "0x.0p0" is valid, and "0x0p0" (but not "0xp0" for example, which will be
// diagnosed by LexHexFloatLiteral).
if (CurPtr[0] == '.' || CurPtr[0] == 'p' || CurPtr[0] == 'P')
return LexHexFloatLiteral(NumStart == CurPtr);
// Otherwise requires at least one hex digit.
if (CurPtr == NumStart)
return ReturnError(CurPtr-2, "invalid hexadecimal number");
APInt Result(128, 0);
if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result))
return ReturnError(TokStart, "invalid hexadecimal number");
// Consume the optional [hH].
if (!IsParsingMSInlineAsm && (*CurPtr == 'h' || *CurPtr == 'H'))
++CurPtr;
// The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
// suffixes on integer literals.
SkipIgnoredIntegerSuffix(CurPtr);
return intToken(StringRef(TokStart, CurPtr - TokStart), Result);
}
// Either octal or hexadecimal.
APInt Value(128, 0, true);
unsigned Radix = doLookAhead(CurPtr, 8);
bool isHex = Radix == 16;
StringRef Result(TokStart, CurPtr - TokStart);
if (Result.getAsInteger(Radix, Value))
return ReturnError(TokStart, !isHex ? "invalid octal number" :
"invalid hexdecimal number");
// Consume the [hH].
if (Radix == 16)
++CurPtr;
// The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL
// suffixes on integer literals.
SkipIgnoredIntegerSuffix(CurPtr);
return intToken(Result, Value);
}
/// LexSingleQuote: Integer: 'b'
AsmToken AsmLexer::LexSingleQuote() {
int CurChar = getNextChar();
if (CurChar == '\\')
CurChar = getNextChar();
if (CurChar == EOF)
return ReturnError(TokStart, "unterminated single quote");
CurChar = getNextChar();
if (CurChar != '\'')
return ReturnError(TokStart, "single quote way too long");
// The idea here being that 'c' is basically just an integral
// constant.
StringRef Res = StringRef(TokStart,CurPtr - TokStart);
long long Value;
if (Res.startswith("\'\\")) {
char theChar = Res[2];
switch (theChar) {
default: Value = theChar; break;
case '\'': Value = '\''; break;
case 't': Value = '\t'; break;
case 'n': Value = '\n'; break;
case 'b': Value = '\b'; break;
}
} else
Value = TokStart[1];
return AsmToken(AsmToken::Integer, Res, Value);
}
/// LexQuote: String: "..."
AsmToken AsmLexer::LexQuote() {
int CurChar = getNextChar();
// TODO: does gas allow multiline string constants?
while (CurChar != '"') {
if (CurChar == '\\') {
// Allow \", etc.
CurChar = getNextChar();
}
if (CurChar == EOF)
return ReturnError(TokStart, "unterminated string constant");
CurChar = getNextChar();
}
return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart));
}
StringRef AsmLexer::LexUntilEndOfStatement() {
TokStart = CurPtr;
while (!isAtStartOfComment(CurPtr) && // Start of line comment.
!isAtStatementSeparator(CurPtr) && // End of statement marker.
*CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) {
++CurPtr;
}
return StringRef(TokStart, CurPtr-TokStart);
}
StringRef AsmLexer::LexUntilEndOfLine() {
TokStart = CurPtr;
while (*CurPtr != '\n' && *CurPtr != '\r' && CurPtr != CurBuf.end()) {
++CurPtr;
}
return StringRef(TokStart, CurPtr-TokStart);
}
size_t AsmLexer::peekTokens(MutableArrayRef<AsmToken> Buf,
bool ShouldSkipSpace) {
SaveAndRestore<const char *> SavedTokenStart(TokStart);
SaveAndRestore<const char *> SavedCurPtr(CurPtr);
SaveAndRestore<bool> SavedAtStartOfLine(IsAtStartOfLine);
SaveAndRestore<bool> SavedAtStartOfStatement(IsAtStartOfStatement);
SaveAndRestore<bool> SavedSkipSpace(SkipSpace, ShouldSkipSpace);
SaveAndRestore<bool> SavedIsPeeking(IsPeeking, true);
std::string SavedErr = getErr();
SMLoc SavedErrLoc = getErrLoc();
size_t ReadCount;
for (ReadCount = 0; ReadCount < Buf.size(); ++ReadCount) {
AsmToken Token = LexToken();
Buf[ReadCount] = Token;
if (Token.is(AsmToken::Eof))
break;
}
SetError(SavedErrLoc, SavedErr);
return ReadCount;
}
bool AsmLexer::isAtStartOfComment(const char *Ptr) {
StringRef CommentString = MAI.getCommentString();
if (CommentString.size() == 1)
return CommentString[0] == Ptr[0];
// Allow # preprocessor commments also be counted as comments for "##" cases
if (CommentString[1] == '#')
return CommentString[0] == Ptr[0];
return strncmp(Ptr, CommentString.data(), CommentString.size()) == 0;
}
bool AsmLexer::isAtStatementSeparator(const char *Ptr) {
return strncmp(Ptr, MAI.getSeparatorString(),
strlen(MAI.getSeparatorString())) == 0;
}
AsmToken AsmLexer::LexToken() {
TokStart = CurPtr;
// This always consumes at least one character.
int CurChar = getNextChar();
if (!IsPeeking && CurChar == '#' && IsAtStartOfStatement) {
// If this starts with a '#', this may be a cpp
// hash directive and otherwise a line comment.
AsmToken TokenBuf[2];
MutableArrayRef<AsmToken> Buf(TokenBuf, 2);
size_t num = peekTokens(Buf, true);
// There cannot be a space preceeding this
if (IsAtStartOfLine && num == 2 && TokenBuf[0].is(AsmToken::Integer) &&
TokenBuf[1].is(AsmToken::String)) {
CurPtr = TokStart; // reset curPtr;
StringRef s = LexUntilEndOfLine();
UnLex(TokenBuf[1]);
UnLex(TokenBuf[0]);
return AsmToken(AsmToken::HashDirective, s);
}
return LexLineComment();
}
if (isAtStartOfComment(TokStart))
return LexLineComment();
if (isAtStatementSeparator(TokStart)) {
CurPtr += strlen(MAI.getSeparatorString()) - 1;
IsAtStartOfLine = true;
IsAtStartOfStatement = true;
return AsmToken(AsmToken::EndOfStatement,
StringRef(TokStart, strlen(MAI.getSeparatorString())));
}
// If we're missing a newline at EOF, make sure we still get an
// EndOfStatement token before the Eof token.
if (CurChar == EOF && !IsAtStartOfStatement) {
IsAtStartOfLine = true;
IsAtStartOfStatement = true;
return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
}
IsAtStartOfLine = false;
bool OldIsAtStartOfStatement = IsAtStartOfStatement;
IsAtStartOfStatement = false;
switch (CurChar) {
default:
// Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
return LexIdentifier();
// Unknown character, emit an error.
return ReturnError(TokStart, "invalid character in input");
case EOF:
IsAtStartOfLine = true;
IsAtStartOfStatement = true;
return AsmToken(AsmToken::Eof, StringRef(TokStart, 0));
case 0:
case ' ':
case '\t':
IsAtStartOfStatement = OldIsAtStartOfStatement;
while (*CurPtr == ' ' || *CurPtr == '\t')
CurPtr++;
if (SkipSpace)
return LexToken(); // Ignore whitespace.
else
return AsmToken(AsmToken::Space, StringRef(TokStart, CurPtr - TokStart));
case '\n':
case '\r':
IsAtStartOfLine = true;
IsAtStartOfStatement = true;
return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1));
case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1));
case '-': return AsmToken(AsmToken::Minus, StringRef(TokStart, 1));
case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1));
case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1));
case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1));
case '[': return AsmToken(AsmToken::LBrac, StringRef(TokStart, 1));
case ']': return AsmToken(AsmToken::RBrac, StringRef(TokStart, 1));
case '{': return AsmToken(AsmToken::LCurly, StringRef(TokStart, 1));
case '}': return AsmToken(AsmToken::RCurly, StringRef(TokStart, 1));
case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1));
case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1));
case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1));
case '@': return AsmToken(AsmToken::At, StringRef(TokStart, 1));
case '\\': return AsmToken(AsmToken::BackSlash, StringRef(TokStart, 1));
case '=':
if (*CurPtr == '=') {
++CurPtr;
return AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2));
}
return AsmToken(AsmToken::Equal, StringRef(TokStart, 1));
case '|':
if (*CurPtr == '|') {
++CurPtr;
return AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2));
}
return AsmToken(AsmToken::Pipe, StringRef(TokStart, 1));
case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1));
case '&':
if (*CurPtr == '&') {
++CurPtr;
return AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2));
}
return AsmToken(AsmToken::Amp, StringRef(TokStart, 1));
case '!':
if (*CurPtr == '=') {
++CurPtr;
return AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2));
}
return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1));
case '%':
if (MAI.hasMipsExpressions()) {
AsmToken::TokenKind Operator;
unsigned OperatorLength;
std::tie(Operator, OperatorLength) =
StringSwitch<std::pair<AsmToken::TokenKind, unsigned>>(
StringRef(CurPtr))
.StartsWith("call16", {AsmToken::PercentCall16, 7})
.StartsWith("call_hi", {AsmToken::PercentCall_Hi, 8})
.StartsWith("call_lo", {AsmToken::PercentCall_Lo, 8})
.StartsWith("dtprel_hi", {AsmToken::PercentDtprel_Hi, 10})
.StartsWith("dtprel_lo", {AsmToken::PercentDtprel_Lo, 10})
.StartsWith("got_disp", {AsmToken::PercentGot_Disp, 9})
.StartsWith("got_hi", {AsmToken::PercentGot_Hi, 7})
.StartsWith("got_lo", {AsmToken::PercentGot_Lo, 7})
.StartsWith("got_ofst", {AsmToken::PercentGot_Ofst, 9})
.StartsWith("got_page", {AsmToken::PercentGot_Page, 9})
.StartsWith("gottprel", {AsmToken::PercentGottprel, 9})
.StartsWith("got", {AsmToken::PercentGot, 4})
.StartsWith("gp_rel", {AsmToken::PercentGp_Rel, 7})
.StartsWith("higher", {AsmToken::PercentHigher, 7})
.StartsWith("highest", {AsmToken::PercentHighest, 8})
.StartsWith("hi", {AsmToken::PercentHi, 3})
.StartsWith("lo", {AsmToken::PercentLo, 3})
.StartsWith("neg", {AsmToken::PercentNeg, 4})
.StartsWith("pcrel_hi", {AsmToken::PercentPcrel_Hi, 9})
.StartsWith("pcrel_lo", {AsmToken::PercentPcrel_Lo, 9})
.StartsWith("tlsgd", {AsmToken::PercentTlsgd, 6})
.StartsWith("tlsldm", {AsmToken::PercentTlsldm, 7})
.StartsWith("tprel_hi", {AsmToken::PercentTprel_Hi, 9})
.StartsWith("tprel_lo", {AsmToken::PercentTprel_Lo, 9})
.Default({AsmToken::Percent, 1});
if (Operator != AsmToken::Percent) {
CurPtr += OperatorLength - 1;
return AsmToken(Operator, StringRef(TokStart, OperatorLength));
}
}
return AsmToken(AsmToken::Percent, StringRef(TokStart, 1));
case '/':
IsAtStartOfStatement = OldIsAtStartOfStatement;
return LexSlash();
case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1));
case '\'': return LexSingleQuote();
case '"': return LexQuote();
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return LexDigit();
case '<':
switch (*CurPtr) {
case '<':
++CurPtr;
return AsmToken(AsmToken::LessLess, StringRef(TokStart, 2));
case '=':
++CurPtr;
return AsmToken(AsmToken::LessEqual, StringRef(TokStart, 2));
case '>':
++CurPtr;
return AsmToken(AsmToken::LessGreater, StringRef(TokStart, 2));
default:
return AsmToken(AsmToken::Less, StringRef(TokStart, 1));
}
case '>':
switch (*CurPtr) {
case '>':
++CurPtr;
return AsmToken(AsmToken::GreaterGreater, StringRef(TokStart, 2));
case '=':
++CurPtr;
return AsmToken(AsmToken::GreaterEqual, StringRef(TokStart, 2));
default:
return AsmToken(AsmToken::Greater, StringRef(TokStart, 1));
}
// TODO: Quoted identifiers (objc methods etc)
// local labels: [0-9][:]
// Forward/backward labels: [0-9][fb]
// Integers, fp constants, character constants.
}
}