2007-11-18 16:46:26 +08:00
|
|
|
//===- LLLexer.cpp - Lexer for .ll Files ----------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 04:36:04 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2007-11-18 16:46:26 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Implement the Lexer for .ll files.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "LLLexer.h"
|
2013-01-19 07:05:41 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/ADT/Twine.h"
|
2014-01-07 20:34:26 +08:00
|
|
|
#include "llvm/AsmParser/Parser.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
|
|
#include "llvm/IR/Instruction.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
2009-07-12 04:10:48 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2007-12-09 03:03:30 +08:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
2009-07-03 06:46:18 +08:00
|
|
|
#include "llvm/Support/SourceMgr.h"
|
2009-01-02 15:01:27 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2010-12-20 04:43:38 +08:00
|
|
|
#include <cctype>
|
2009-08-24 18:34:41 +08:00
|
|
|
#include <cstdio>
|
2009-01-02 15:18:46 +08:00
|
|
|
#include <cstdlib>
|
2009-01-03 06:49:28 +08:00
|
|
|
#include <cstring>
|
2007-11-18 16:46:26 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2010-09-28 01:42:11 +08:00
|
|
|
bool LLLexer::Error(LocTy ErrorLoc, const Twine &Msg) const {
|
2011-10-16 13:43:57 +08:00
|
|
|
ErrorInfo = SM.GetMessage(ErrorLoc, SourceMgr::DK_Error, Msg);
|
2009-01-02 15:01:27 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-04-06 06:42:53 +08:00
|
|
|
void LLLexer::Warning(LocTy WarningLoc, const Twine &Msg) const {
|
|
|
|
SM.PrintMessage(WarningLoc, SourceMgr::DK_Warning, Msg);
|
|
|
|
}
|
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Helper functions.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
// atoull - Convert an ascii string of decimal digits into the unsigned long
|
|
|
|
// long representation... this does not have to do input error checking,
|
|
|
|
// because we know that the input will be matched by a suitable regex...
|
|
|
|
//
|
2009-01-02 15:01:27 +08:00
|
|
|
uint64_t LLLexer::atoull(const char *Buffer, const char *End) {
|
2007-11-18 16:46:26 +08:00
|
|
|
uint64_t Result = 0;
|
|
|
|
for (; Buffer != End; Buffer++) {
|
|
|
|
uint64_t OldRes = Result;
|
|
|
|
Result *= 10;
|
|
|
|
Result += *Buffer-'0';
|
|
|
|
if (Result < OldRes) { // Uh, oh, overflow detected!!!
|
2009-01-02 15:01:27 +08:00
|
|
|
Error("constant bigger than 64 bits detected!");
|
2007-11-18 16:46:26 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2009-01-02 15:01:27 +08:00
|
|
|
uint64_t LLLexer::HexIntToVal(const char *Buffer, const char *End) {
|
2007-11-18 16:46:26 +08:00
|
|
|
uint64_t Result = 0;
|
|
|
|
for (; Buffer != End; ++Buffer) {
|
|
|
|
uint64_t OldRes = Result;
|
|
|
|
Result *= 16;
|
2013-01-19 07:05:41 +08:00
|
|
|
Result += hexDigitValue(*Buffer);
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
if (Result < OldRes) { // Uh, oh, overflow detected!!!
|
2009-01-02 15:01:27 +08:00
|
|
|
Error("constant bigger than 64 bits detected!");
|
2007-11-18 16:46:26 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2009-01-02 15:01:27 +08:00
|
|
|
void LLLexer::HexToIntPair(const char *Buffer, const char *End,
|
|
|
|
uint64_t Pair[2]) {
|
2007-11-18 16:46:26 +08:00
|
|
|
Pair[0] = 0;
|
2014-12-10 03:10:03 +08:00
|
|
|
if (End - Buffer >= 16) {
|
|
|
|
for (int i = 0; i < 16; i++, Buffer++) {
|
|
|
|
assert(Buffer != End);
|
|
|
|
Pair[0] *= 16;
|
|
|
|
Pair[0] += hexDigitValue(*Buffer);
|
|
|
|
}
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
Pair[1] = 0;
|
2014-12-10 03:10:03 +08:00
|
|
|
for (int i = 0; i < 16 && Buffer != End; i++, Buffer++) {
|
2007-11-18 16:46:26 +08:00
|
|
|
Pair[1] *= 16;
|
2013-01-19 07:05:41 +08:00
|
|
|
Pair[1] += hexDigitValue(*Buffer);
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2007-11-19 02:25:18 +08:00
|
|
|
if (Buffer != End)
|
2009-01-02 15:01:27 +08:00
|
|
|
Error("constant bigger than 128 bits detected!");
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
|
2009-03-24 05:16:53 +08:00
|
|
|
/// FP80HexToIntPair - translate an 80 bit FP80 number (20 hexits) into
|
|
|
|
/// { low64, high16 } as usual for an APInt.
|
|
|
|
void LLLexer::FP80HexToIntPair(const char *Buffer, const char *End,
|
|
|
|
uint64_t Pair[2]) {
|
|
|
|
Pair[1] = 0;
|
|
|
|
for (int i=0; i<4 && Buffer != End; i++, Buffer++) {
|
|
|
|
assert(Buffer != End);
|
|
|
|
Pair[1] *= 16;
|
2013-01-19 07:05:41 +08:00
|
|
|
Pair[1] += hexDigitValue(*Buffer);
|
2009-03-24 05:16:53 +08:00
|
|
|
}
|
|
|
|
Pair[0] = 0;
|
2015-09-01 05:36:14 +08:00
|
|
|
for (int i = 0; i < 16 && Buffer != End; i++, Buffer++) {
|
2009-03-24 05:16:53 +08:00
|
|
|
Pair[0] *= 16;
|
2013-01-19 07:05:41 +08:00
|
|
|
Pair[0] += hexDigitValue(*Buffer);
|
2009-03-24 05:16:53 +08:00
|
|
|
}
|
|
|
|
if (Buffer != End)
|
|
|
|
Error("constant bigger than 128 bits detected!");
|
|
|
|
}
|
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
// UnEscapeLexed - Run through the specified buffer and change \xx codes to the
|
|
|
|
// appropriate character.
|
|
|
|
static void UnEscapeLexed(std::string &Str) {
|
|
|
|
if (Str.empty()) return;
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
char *Buffer = &Str[0], *EndBuffer = Buffer+Str.size();
|
|
|
|
char *BOut = Buffer;
|
|
|
|
for (char *BIn = Buffer; BIn != EndBuffer; ) {
|
|
|
|
if (BIn[0] == '\\') {
|
|
|
|
if (BIn < EndBuffer-1 && BIn[1] == '\\') {
|
|
|
|
*BOut++ = '\\'; // Two \ becomes one
|
|
|
|
BIn += 2;
|
2013-02-13 05:21:59 +08:00
|
|
|
} else if (BIn < EndBuffer-2 &&
|
|
|
|
isxdigit(static_cast<unsigned char>(BIn[1])) &&
|
|
|
|
isxdigit(static_cast<unsigned char>(BIn[2]))) {
|
2013-01-19 07:05:41 +08:00
|
|
|
*BOut = hexDigitValue(BIn[1]) * 16 + hexDigitValue(BIn[2]);
|
2007-11-18 16:46:26 +08:00
|
|
|
BIn += 3; // Skip over handled chars
|
|
|
|
++BOut;
|
|
|
|
} else {
|
|
|
|
*BOut++ = *BIn++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*BOut++ = *BIn++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Str.resize(BOut-Buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// isLabelChar - Return true for [-a-zA-Z$._0-9].
|
|
|
|
static bool isLabelChar(char C) {
|
2013-02-13 05:21:59 +08:00
|
|
|
return isalnum(static_cast<unsigned char>(C)) || C == '-' || C == '$' ||
|
|
|
|
C == '.' || C == '_';
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// isLabelTail - Return true if this pointer points to a valid end of a label.
|
|
|
|
static const char *isLabelTail(const char *CurPtr) {
|
|
|
|
while (1) {
|
|
|
|
if (CurPtr[0] == ':') return CurPtr+1;
|
2014-04-15 14:32:26 +08:00
|
|
|
if (!isLabelChar(CurPtr[0])) return nullptr;
|
2007-11-18 16:46:26 +08:00
|
|
|
++CurPtr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Lexer definition.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2014-08-19 06:28:28 +08:00
|
|
|
LLLexer::LLLexer(StringRef StartBuf, SourceMgr &sm, SMDiagnostic &Err,
|
2009-07-08 02:44:11 +08:00
|
|
|
LLVMContext &C)
|
|
|
|
: CurBuf(StartBuf), ErrorInfo(Err), SM(sm), Context(C), APFloatVal(0.0) {
|
2014-08-19 06:28:28 +08:00
|
|
|
CurPtr = CurBuf.begin();
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int LLLexer::getNextChar() {
|
|
|
|
char CurChar = *CurPtr++;
|
|
|
|
switch (CurChar) {
|
|
|
|
default: return (unsigned char)CurChar;
|
|
|
|
case 0:
|
|
|
|
// A nul character in the stream is either the end of the current buffer or
|
|
|
|
// a random nul in the file. Disambiguate that here.
|
2014-08-19 06:28:28 +08:00
|
|
|
if (CurPtr-1 != CurBuf.end())
|
2007-11-18 16:46:26 +08:00
|
|
|
return 0; // Just whitespace.
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
// Otherwise, return end of file.
|
2007-12-16 17:16:12 +08:00
|
|
|
--CurPtr; // Another call to lex will return EOF again.
|
2007-11-18 16:46:26 +08:00
|
|
|
return EOF;
|
2007-12-16 17:16:12 +08:00
|
|
|
}
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-02 15:01:27 +08:00
|
|
|
lltok::Kind LLLexer::LexToken() {
|
2007-11-18 16:46:26 +08:00
|
|
|
TokStart = CurPtr;
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
int CurChar = getNextChar();
|
|
|
|
switch (CurChar) {
|
|
|
|
default:
|
|
|
|
// Handle letters: [a-zA-Z_]
|
2013-02-13 05:21:59 +08:00
|
|
|
if (isalpha(static_cast<unsigned char>(CurChar)) || CurChar == '_')
|
2007-11-18 16:46:26 +08:00
|
|
|
return LexIdentifier();
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::Error;
|
|
|
|
case EOF: return lltok::Eof;
|
2007-11-18 16:46:26 +08:00
|
|
|
case 0:
|
|
|
|
case ' ':
|
|
|
|
case '\t':
|
|
|
|
case '\n':
|
|
|
|
case '\r':
|
|
|
|
// Ignore whitespace.
|
|
|
|
return LexToken();
|
|
|
|
case '+': return LexPositive();
|
|
|
|
case '@': return LexAt();
|
2014-06-28 02:19:56 +08:00
|
|
|
case '$': return LexDollar();
|
2007-11-18 16:46:26 +08:00
|
|
|
case '%': return LexPercent();
|
|
|
|
case '"': return LexQuote();
|
|
|
|
case '.':
|
|
|
|
if (const char *Ptr = isLabelTail(CurPtr)) {
|
|
|
|
CurPtr = Ptr;
|
2009-01-02 15:01:27 +08:00
|
|
|
StrVal.assign(TokStart, CurPtr-1);
|
|
|
|
return lltok::LabelStr;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
if (CurPtr[0] == '.' && CurPtr[1] == '.') {
|
|
|
|
CurPtr += 2;
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::dotdotdot;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::Error;
|
2007-11-18 16:46:26 +08:00
|
|
|
case ';':
|
|
|
|
SkipLineComment();
|
|
|
|
return LexToken();
|
2009-12-30 12:56:59 +08:00
|
|
|
case '!': return LexExclaim();
|
2013-02-06 14:52:58 +08:00
|
|
|
case '#': return LexHash();
|
2007-11-18 16:46:26 +08:00
|
|
|
case '0': case '1': case '2': case '3': case '4':
|
|
|
|
case '5': case '6': case '7': case '8': case '9':
|
2007-12-16 17:16:12 +08:00
|
|
|
case '-':
|
2007-11-18 16:46:26 +08:00
|
|
|
return LexDigitOrNegative();
|
2009-01-02 15:01:27 +08:00
|
|
|
case '=': return lltok::equal;
|
|
|
|
case '[': return lltok::lsquare;
|
|
|
|
case ']': return lltok::rsquare;
|
|
|
|
case '{': return lltok::lbrace;
|
|
|
|
case '}': return lltok::rbrace;
|
|
|
|
case '<': return lltok::less;
|
|
|
|
case '>': return lltok::greater;
|
|
|
|
case '(': return lltok::lparen;
|
|
|
|
case ')': return lltok::rparen;
|
|
|
|
case ',': return lltok::comma;
|
|
|
|
case '*': return lltok::star;
|
2015-02-21 09:02:18 +08:00
|
|
|
case '|': return lltok::bar;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LLLexer::SkipLineComment() {
|
|
|
|
while (1) {
|
|
|
|
if (CurPtr[0] == '\n' || CurPtr[0] == '\r' || getNextChar() == EOF)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-07 14:40:24 +08:00
|
|
|
/// Lex all tokens that start with an @ character.
|
2009-01-02 15:01:27 +08:00
|
|
|
/// GlobalVar @\"[^\"]*\"
|
|
|
|
/// GlobalVar @[-a-zA-Z$._][-a-zA-Z$._0-9]*
|
|
|
|
/// GlobalVarID @[0-9]+
|
|
|
|
lltok::Kind LLLexer::LexAt() {
|
2014-12-10 08:43:17 +08:00
|
|
|
return LexVar(lltok::GlobalVar, lltok::GlobalID);
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
|
2014-06-28 02:19:56 +08:00
|
|
|
lltok::Kind LLLexer::LexDollar() {
|
|
|
|
if (const char *Ptr = isLabelTail(TokStart)) {
|
|
|
|
CurPtr = Ptr;
|
|
|
|
StrVal.assign(TokStart, CurPtr - 1);
|
|
|
|
return lltok::LabelStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle DollarStringConstant: $\"[^\"]*\"
|
|
|
|
if (CurPtr[0] == '"') {
|
|
|
|
++CurPtr;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
int CurChar = getNextChar();
|
|
|
|
|
|
|
|
if (CurChar == EOF) {
|
|
|
|
Error("end of file in COMDAT variable name");
|
|
|
|
return lltok::Error;
|
|
|
|
}
|
|
|
|
if (CurChar == '"') {
|
|
|
|
StrVal.assign(TokStart + 2, CurPtr - 1);
|
|
|
|
UnEscapeLexed(StrVal);
|
|
|
|
if (StringRef(StrVal).find_first_of(0) != StringRef::npos) {
|
|
|
|
Error("Null bytes are not allowed in names");
|
|
|
|
return lltok::Error;
|
|
|
|
}
|
|
|
|
return lltok::ComdatVar;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle ComdatVarName: $[-a-zA-Z$._][-a-zA-Z$._0-9]*
|
|
|
|
if (ReadVarName())
|
|
|
|
return lltok::ComdatVar;
|
|
|
|
|
|
|
|
return lltok::Error;
|
|
|
|
}
|
|
|
|
|
2011-06-05 02:16:26 +08:00
|
|
|
/// ReadString - Read a string until the closing quote.
|
|
|
|
lltok::Kind LLLexer::ReadString(lltok::Kind kind) {
|
|
|
|
const char *Start = CurPtr;
|
|
|
|
while (1) {
|
|
|
|
int CurChar = getNextChar();
|
|
|
|
|
|
|
|
if (CurChar == EOF) {
|
|
|
|
Error("end of file in string constant");
|
|
|
|
return lltok::Error;
|
|
|
|
}
|
|
|
|
if (CurChar == '"') {
|
|
|
|
StrVal.assign(Start, CurPtr-1);
|
|
|
|
UnEscapeLexed(StrVal);
|
|
|
|
return kind;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ReadVarName - Read the rest of a token containing a variable name.
|
|
|
|
bool LLLexer::ReadVarName() {
|
|
|
|
const char *NameStart = CurPtr;
|
2013-02-13 05:21:59 +08:00
|
|
|
if (isalpha(static_cast<unsigned char>(CurPtr[0])) ||
|
|
|
|
CurPtr[0] == '-' || CurPtr[0] == '$' ||
|
2011-06-05 02:16:26 +08:00
|
|
|
CurPtr[0] == '.' || CurPtr[0] == '_') {
|
|
|
|
++CurPtr;
|
2013-02-13 05:21:59 +08:00
|
|
|
while (isalnum(static_cast<unsigned char>(CurPtr[0])) ||
|
|
|
|
CurPtr[0] == '-' || CurPtr[0] == '$' ||
|
2011-06-05 02:16:26 +08:00
|
|
|
CurPtr[0] == '.' || CurPtr[0] == '_')
|
|
|
|
++CurPtr;
|
|
|
|
|
|
|
|
StrVal.assign(NameStart, CurPtr);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2007-11-18 16:46:26 +08:00
|
|
|
|
2014-12-10 08:43:17 +08:00
|
|
|
lltok::Kind LLLexer::LexVar(lltok::Kind Var, lltok::Kind VarID) {
|
|
|
|
// Handle StringConstant: \"[^\"]*\"
|
2007-11-18 16:46:26 +08:00
|
|
|
if (CurPtr[0] == '"') {
|
|
|
|
++CurPtr;
|
2014-12-10 08:43:17 +08:00
|
|
|
|
|
|
|
while (1) {
|
|
|
|
int CurChar = getNextChar();
|
|
|
|
|
|
|
|
if (CurChar == EOF) {
|
|
|
|
Error("end of file in global variable name");
|
|
|
|
return lltok::Error;
|
|
|
|
}
|
|
|
|
if (CurChar == '"') {
|
|
|
|
StrVal.assign(TokStart+2, CurPtr-1);
|
|
|
|
UnEscapeLexed(StrVal);
|
|
|
|
if (StringRef(StrVal).find_first_of(0) != StringRef::npos) {
|
|
|
|
Error("Null bytes are not allowed in names");
|
|
|
|
return lltok::Error;
|
|
|
|
}
|
|
|
|
return Var;
|
|
|
|
}
|
|
|
|
}
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2014-12-10 08:43:17 +08:00
|
|
|
// Handle VarName: [-a-zA-Z$._][-a-zA-Z$._0-9]*
|
2011-06-05 02:16:26 +08:00
|
|
|
if (ReadVarName())
|
2014-12-10 08:43:17 +08:00
|
|
|
return Var;
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2014-12-10 08:43:17 +08:00
|
|
|
// Handle VarID: [0-9]+
|
2013-02-13 05:21:59 +08:00
|
|
|
if (isdigit(static_cast<unsigned char>(CurPtr[0]))) {
|
|
|
|
for (++CurPtr; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr)
|
2007-12-16 17:16:12 +08:00
|
|
|
/*empty*/;
|
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
uint64_t Val = atoull(TokStart+1, CurPtr);
|
|
|
|
if ((unsigned)Val != Val)
|
2009-01-02 15:01:27 +08:00
|
|
|
Error("invalid value number (too large)!");
|
|
|
|
UIntVal = unsigned(Val);
|
2014-12-10 08:43:17 +08:00
|
|
|
return VarID;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::Error;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
|
2015-06-07 14:40:24 +08:00
|
|
|
/// Lex all tokens that start with a % character.
|
2014-12-10 08:43:17 +08:00
|
|
|
/// LocalVar ::= %\"[^\"]*\"
|
|
|
|
/// LocalVar ::= %[-a-zA-Z$._][-a-zA-Z$._0-9]*
|
|
|
|
/// LocalVarID ::= %[0-9]+
|
|
|
|
lltok::Kind LLLexer::LexPercent() {
|
|
|
|
return LexVar(lltok::LocalVar, lltok::LocalVarID);
|
|
|
|
}
|
|
|
|
|
2015-06-07 14:40:24 +08:00
|
|
|
/// Lex all tokens that start with a " character.
|
2007-11-18 16:46:26 +08:00
|
|
|
/// QuoteLabel "[^"]+":
|
|
|
|
/// StringConstant "[^"]*"
|
2009-01-02 15:01:27 +08:00
|
|
|
lltok::Kind LLLexer::LexQuote() {
|
2011-06-05 02:16:26 +08:00
|
|
|
lltok::Kind kind = ReadString(lltok::StringConstant);
|
|
|
|
if (kind == lltok::Error || kind == lltok::Eof)
|
|
|
|
return kind;
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2011-06-05 02:16:26 +08:00
|
|
|
if (CurPtr[0] == ':') {
|
2007-11-18 16:46:26 +08:00
|
|
|
++CurPtr;
|
2014-12-10 10:10:35 +08:00
|
|
|
if (StringRef(StrVal).find_first_of(0) != StringRef::npos) {
|
|
|
|
Error("Null bytes are not allowed in names");
|
|
|
|
kind = lltok::Error;
|
|
|
|
} else {
|
|
|
|
kind = lltok::LabelStr;
|
|
|
|
}
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2011-06-05 02:16:26 +08:00
|
|
|
|
|
|
|
return kind;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
|
2015-06-07 14:40:24 +08:00
|
|
|
/// Lex all tokens that start with a ! character.
|
2009-07-29 08:34:02 +08:00
|
|
|
/// !foo
|
2009-12-30 13:02:06 +08:00
|
|
|
/// !
|
2009-12-30 12:56:59 +08:00
|
|
|
lltok::Kind LLLexer::LexExclaim() {
|
2009-12-30 13:02:06 +08:00
|
|
|
// Lex a metadata name as a MetadataVar.
|
2013-02-13 05:21:59 +08:00
|
|
|
if (isalpha(static_cast<unsigned char>(CurPtr[0])) ||
|
|
|
|
CurPtr[0] == '-' || CurPtr[0] == '$' ||
|
2011-06-15 14:37:58 +08:00
|
|
|
CurPtr[0] == '.' || CurPtr[0] == '_' || CurPtr[0] == '\\') {
|
2009-07-29 08:34:02 +08:00
|
|
|
++CurPtr;
|
2013-02-13 05:21:59 +08:00
|
|
|
while (isalnum(static_cast<unsigned char>(CurPtr[0])) ||
|
|
|
|
CurPtr[0] == '-' || CurPtr[0] == '$' ||
|
2011-06-15 14:37:58 +08:00
|
|
|
CurPtr[0] == '.' || CurPtr[0] == '_' || CurPtr[0] == '\\')
|
2009-07-29 08:34:02 +08:00
|
|
|
++CurPtr;
|
2007-11-18 16:46:26 +08:00
|
|
|
|
2009-07-29 08:34:02 +08:00
|
|
|
StrVal.assign(TokStart+1, CurPtr); // Skip !
|
2011-06-15 14:37:58 +08:00
|
|
|
UnEscapeLexed(StrVal);
|
2009-12-30 13:02:06 +08:00
|
|
|
return lltok::MetadataVar;
|
2009-07-29 08:34:02 +08:00
|
|
|
}
|
2009-12-30 12:56:59 +08:00
|
|
|
return lltok::exclaim;
|
2009-07-29 08:34:02 +08:00
|
|
|
}
|
2012-11-27 08:42:44 +08:00
|
|
|
|
2015-06-07 14:40:24 +08:00
|
|
|
/// Lex all tokens that start with a # character.
|
2013-02-06 14:52:58 +08:00
|
|
|
/// AttrGrpID ::= #[0-9]+
|
|
|
|
lltok::Kind LLLexer::LexHash() {
|
|
|
|
// Handle AttrGrpID: #[0-9]+
|
2013-02-13 05:21:59 +08:00
|
|
|
if (isdigit(static_cast<unsigned char>(CurPtr[0]))) {
|
|
|
|
for (++CurPtr; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr)
|
2013-02-06 14:52:58 +08:00
|
|
|
/*empty*/;
|
|
|
|
|
|
|
|
uint64_t Val = atoull(TokStart+1, CurPtr);
|
|
|
|
if ((unsigned)Val != Val)
|
|
|
|
Error("invalid value number (too large)!");
|
|
|
|
UIntVal = unsigned(Val);
|
|
|
|
return lltok::AttrGrpID;
|
|
|
|
}
|
|
|
|
|
|
|
|
return lltok::Error;
|
|
|
|
}
|
|
|
|
|
2015-06-07 14:40:24 +08:00
|
|
|
/// Lex a label, integer type, keyword, or hexadecimal integer constant.
|
2007-11-18 16:46:26 +08:00
|
|
|
/// Label [-a-zA-Z$._0-9]+:
|
|
|
|
/// IntegerType i[0-9]+
|
|
|
|
/// Keyword sdiv, float, ...
|
|
|
|
/// HexIntConstant [us]0x[0-9A-Fa-f]+
|
2009-01-02 15:01:27 +08:00
|
|
|
lltok::Kind LLLexer::LexIdentifier() {
|
2007-11-18 16:46:26 +08:00
|
|
|
const char *StartChar = CurPtr;
|
2014-04-15 14:32:26 +08:00
|
|
|
const char *IntEnd = CurPtr[-1] == 'i' ? nullptr : StartChar;
|
|
|
|
const char *KeywordEnd = nullptr;
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
for (; isLabelChar(*CurPtr); ++CurPtr) {
|
|
|
|
// If we decide this is an integer, remember the end of the sequence.
|
2013-02-13 05:21:59 +08:00
|
|
|
if (!IntEnd && !isdigit(static_cast<unsigned char>(*CurPtr)))
|
|
|
|
IntEnd = CurPtr;
|
|
|
|
if (!KeywordEnd && !isalnum(static_cast<unsigned char>(*CurPtr)) &&
|
|
|
|
*CurPtr != '_')
|
|
|
|
KeywordEnd = CurPtr;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
// If we stopped due to a colon, this really is a label.
|
|
|
|
if (*CurPtr == ':') {
|
2009-01-02 15:01:27 +08:00
|
|
|
StrVal.assign(StartChar-1, CurPtr++);
|
|
|
|
return lltok::LabelStr;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
// Otherwise, this wasn't a label. If this was valid as an integer type,
|
|
|
|
// return it.
|
2014-04-15 14:32:26 +08:00
|
|
|
if (!IntEnd) IntEnd = CurPtr;
|
2007-11-18 16:46:26 +08:00
|
|
|
if (IntEnd != StartChar) {
|
|
|
|
CurPtr = IntEnd;
|
|
|
|
uint64_t NumBits = atoull(StartChar, CurPtr);
|
2007-12-16 17:16:12 +08:00
|
|
|
if (NumBits < IntegerType::MIN_INT_BITS ||
|
2007-11-18 16:46:26 +08:00
|
|
|
NumBits > IntegerType::MAX_INT_BITS) {
|
2009-01-02 15:01:27 +08:00
|
|
|
Error("bitwidth for integer type out of range!");
|
|
|
|
return lltok::Error;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2009-08-14 05:58:54 +08:00
|
|
|
TyVal = IntegerType::get(Context, NumBits);
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::Type;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
// Otherwise, this was a letter sequence. See which keyword this is.
|
2014-04-15 14:32:26 +08:00
|
|
|
if (!KeywordEnd) KeywordEnd = CurPtr;
|
2007-11-18 16:46:26 +08:00
|
|
|
CurPtr = KeywordEnd;
|
|
|
|
--StartChar;
|
2015-02-21 08:18:40 +08:00
|
|
|
StringRef Keyword(StartChar, CurPtr - StartChar);
|
|
|
|
#define KEYWORD(STR) \
|
|
|
|
do { \
|
|
|
|
if (Keyword == #STR) \
|
|
|
|
return lltok::kw_##STR; \
|
2013-02-05 15:19:31 +08:00
|
|
|
} while (0)
|
2009-01-02 15:01:27 +08:00
|
|
|
|
|
|
|
KEYWORD(true); KEYWORD(false);
|
|
|
|
KEYWORD(declare); KEYWORD(define);
|
|
|
|
KEYWORD(global); KEYWORD(constant);
|
|
|
|
|
2009-01-16 04:18:42 +08:00
|
|
|
KEYWORD(private);
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(internal);
|
2009-04-13 13:44:34 +08:00
|
|
|
KEYWORD(available_externally);
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(linkonce);
|
Introduce new linkage types linkonce_odr, weak_odr, common_odr
and extern_weak_odr. These are the same as the non-odr versions,
except that they indicate that the global will only be overridden
by an *equivalent* global. In C, a function with weak linkage can
be overridden by a function which behaves completely differently.
This means that IP passes have to skip weak functions, since any
deductions made from the function definition might be wrong, since
the definition could be replaced by something completely different
at link time. This is not allowed in C++, thanks to the ODR
(One-Definition-Rule): if a function is replaced by another at
link-time, then the new function must be the same as the original
function. If a language knows that a function or other global can
only be overridden by an equivalent global, it can give it the
weak_odr linkage type, and the optimizers will understand that it
is alright to make deductions based on the function body. The
code generators on the other hand map weak and weak_odr linkage
to the same thing.
llvm-svn: 66339
2009-03-07 23:45:40 +08:00
|
|
|
KEYWORD(linkonce_odr);
|
IR: add "cmpxchg weak" variant to support permitted failure.
This commit adds a weak variant of the cmpxchg operation, as described
in C++11. A cmpxchg instruction with this modifier is permitted to
fail to store, even if the comparison indicated it should.
As a result, cmpxchg instructions must return a flag indicating
success in addition to their original iN value loaded. Thus, for
uniformity *all* cmpxchg instructions now return "{ iN, i1 }". The
second flag is 1 when the store succeeded.
At the DAG level, a new ATOMIC_CMP_SWAP_WITH_SUCCESS node has been
added as the natural representation for the new cmpxchg instructions.
It is a strong cmpxchg.
By default this gets Expanded to the existing ATOMIC_CMP_SWAP during
Legalization, so existing backends should see no change in behaviour.
If they wish to deal with the enhanced node instead, they can call
setOperationAction on it. Beware: as a node with 2 results, it cannot
be selected from TableGen.
Currently, no use is made of the extra information provided in this
patch. Test updates are almost entirely adapting the input IR to the
new scheme.
Summary for out of tree users:
------------------------------
+ Legacy Bitcode files are upgraded during read.
+ Legacy assembly IR files will be invalid.
+ Front-ends must adapt to different type for "cmpxchg".
+ Backends should be unaffected by default.
llvm-svn: 210903
2014-06-13 22:24:07 +08:00
|
|
|
KEYWORD(weak); // Use as a linkage, and a modifier for "cmpxchg".
|
Introduce new linkage types linkonce_odr, weak_odr, common_odr
and extern_weak_odr. These are the same as the non-odr versions,
except that they indicate that the global will only be overridden
by an *equivalent* global. In C, a function with weak linkage can
be overridden by a function which behaves completely differently.
This means that IP passes have to skip weak functions, since any
deductions made from the function definition might be wrong, since
the definition could be replaced by something completely different
at link time. This is not allowed in C++, thanks to the ODR
(One-Definition-Rule): if a function is replaced by another at
link-time, then the new function must be the same as the original
function. If a language knows that a function or other global can
only be overridden by an equivalent global, it can give it the
weak_odr linkage type, and the optimizers will understand that it
is alright to make deductions based on the function body. The
code generators on the other hand map weak and weak_odr linkage
to the same thing.
llvm-svn: 66339
2009-03-07 23:45:40 +08:00
|
|
|
KEYWORD(weak_odr);
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(appending);
|
|
|
|
KEYWORD(dllimport);
|
|
|
|
KEYWORD(dllexport);
|
|
|
|
KEYWORD(common);
|
|
|
|
KEYWORD(default);
|
|
|
|
KEYWORD(hidden);
|
|
|
|
KEYWORD(protected);
|
2011-01-09 00:42:36 +08:00
|
|
|
KEYWORD(unnamed_addr);
|
2013-02-05 13:57:38 +08:00
|
|
|
KEYWORD(externally_initialized);
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(extern_weak);
|
|
|
|
KEYWORD(external);
|
|
|
|
KEYWORD(thread_local);
|
2012-06-23 19:37:03 +08:00
|
|
|
KEYWORD(localdynamic);
|
|
|
|
KEYWORD(initialexec);
|
|
|
|
KEYWORD(localexec);
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(zeroinitializer);
|
|
|
|
KEYWORD(undef);
|
|
|
|
KEYWORD(null);
|
|
|
|
KEYWORD(to);
|
2015-08-01 01:58:14 +08:00
|
|
|
KEYWORD(caller);
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(tail);
|
2014-04-25 04:14:34 +08:00
|
|
|
KEYWORD(musttail);
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(target);
|
|
|
|
KEYWORD(triple);
|
2012-02-07 05:02:43 +08:00
|
|
|
KEYWORD(unwind);
|
2012-11-28 16:41:48 +08:00
|
|
|
KEYWORD(deplibs); // FIXME: Remove in 4.0.
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(datalayout);
|
|
|
|
KEYWORD(volatile);
|
2011-07-26 07:16:38 +08:00
|
|
|
KEYWORD(atomic);
|
|
|
|
KEYWORD(unordered);
|
|
|
|
KEYWORD(monotonic);
|
|
|
|
KEYWORD(acquire);
|
|
|
|
KEYWORD(release);
|
|
|
|
KEYWORD(acq_rel);
|
|
|
|
KEYWORD(seq_cst);
|
|
|
|
KEYWORD(singlethread);
|
|
|
|
|
2013-02-05 15:19:31 +08:00
|
|
|
KEYWORD(nnan);
|
|
|
|
KEYWORD(ninf);
|
|
|
|
KEYWORD(nsz);
|
|
|
|
KEYWORD(arcp);
|
|
|
|
KEYWORD(fast);
|
2009-07-23 06:44:56 +08:00
|
|
|
KEYWORD(nuw);
|
|
|
|
KEYWORD(nsw);
|
2009-07-21 05:19:07 +08:00
|
|
|
KEYWORD(exact);
|
2009-07-28 05:53:46 +08:00
|
|
|
KEYWORD(inbounds);
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(align);
|
|
|
|
KEYWORD(addrspace);
|
|
|
|
KEYWORD(section);
|
|
|
|
KEYWORD(alias);
|
|
|
|
KEYWORD(module);
|
|
|
|
KEYWORD(asm);
|
|
|
|
KEYWORD(sideeffect);
|
2009-10-22 07:28:00 +08:00
|
|
|
KEYWORD(alignstack);
|
2012-09-06 03:00:49 +08:00
|
|
|
KEYWORD(inteldialect);
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(gc);
|
2013-09-16 09:08:15 +08:00
|
|
|
KEYWORD(prefix);
|
2014-12-03 10:08:38 +08:00
|
|
|
KEYWORD(prologue);
|
2009-01-02 15:01:27 +08:00
|
|
|
|
|
|
|
KEYWORD(ccc);
|
|
|
|
KEYWORD(fastcc);
|
|
|
|
KEYWORD(coldcc);
|
|
|
|
KEYWORD(x86_stdcallcc);
|
|
|
|
KEYWORD(x86_fastcallcc);
|
2010-05-16 17:08:45 +08:00
|
|
|
KEYWORD(x86_thiscallcc);
|
2014-10-28 09:29:26 +08:00
|
|
|
KEYWORD(x86_vectorcallcc);
|
2009-06-17 02:50:49 +08:00
|
|
|
KEYWORD(arm_apcscc);
|
|
|
|
KEYWORD(arm_aapcscc);
|
|
|
|
KEYWORD(arm_aapcs_vfpcc);
|
2009-12-07 10:27:35 +08:00
|
|
|
KEYWORD(msp430_intrcc);
|
2010-09-25 15:46:17 +08:00
|
|
|
KEYWORD(ptx_kernel);
|
|
|
|
KEYWORD(ptx_device);
|
2012-10-02 01:01:31 +08:00
|
|
|
KEYWORD(spir_kernel);
|
|
|
|
KEYWORD(spir_func);
|
2012-10-24 22:46:16 +08:00
|
|
|
KEYWORD(intel_ocl_bicc);
|
2013-07-12 14:02:35 +08:00
|
|
|
KEYWORD(x86_64_sysvcc);
|
|
|
|
KEYWORD(x86_64_win64cc);
|
2013-11-01 06:12:01 +08:00
|
|
|
KEYWORD(webkit_jscc);
|
2013-11-09 07:28:16 +08:00
|
|
|
KEYWORD(anyregcc);
|
2014-01-18 03:47:03 +08:00
|
|
|
KEYWORD(preserve_mostcc);
|
|
|
|
KEYWORD(preserve_allcc);
|
2014-12-02 05:04:44 +08:00
|
|
|
KEYWORD(ghccc);
|
2009-06-17 02:50:49 +08:00
|
|
|
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(cc);
|
|
|
|
KEYWORD(c);
|
|
|
|
|
2013-02-06 14:52:58 +08:00
|
|
|
KEYWORD(attributes);
|
|
|
|
|
|
|
|
KEYWORD(alwaysinline);
|
2015-07-11 18:30:36 +08:00
|
|
|
KEYWORD(argmemonly);
|
2013-06-27 08:25:01 +08:00
|
|
|
KEYWORD(builtin);
|
2013-02-06 14:52:58 +08:00
|
|
|
KEYWORD(byval);
|
2013-12-19 10:14:12 +08:00
|
|
|
KEYWORD(inalloca);
|
2013-05-24 20:26:52 +08:00
|
|
|
KEYWORD(cold);
|
2015-05-27 07:48:40 +08:00
|
|
|
KEYWORD(convergent);
|
2014-07-18 23:51:28 +08:00
|
|
|
KEYWORD(dereferenceable);
|
2015-04-17 04:29:50 +08:00
|
|
|
KEYWORD(dereferenceable_or_null);
|
2013-02-06 14:52:58 +08:00
|
|
|
KEYWORD(inlinehint);
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(inreg);
|
2014-06-06 03:29:43 +08:00
|
|
|
KEYWORD(jumptable);
|
2013-02-06 14:52:58 +08:00
|
|
|
KEYWORD(minsize);
|
|
|
|
KEYWORD(naked);
|
|
|
|
KEYWORD(nest);
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(noalias);
|
2013-02-22 08:12:35 +08:00
|
|
|
KEYWORD(nobuiltin);
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(nocapture);
|
2013-02-06 14:52:58 +08:00
|
|
|
KEYWORD(noduplicate);
|
|
|
|
KEYWORD(noimplicitfloat);
|
|
|
|
KEYWORD(noinline);
|
|
|
|
KEYWORD(nonlazybind);
|
2014-05-20 09:23:40 +08:00
|
|
|
KEYWORD(nonnull);
|
2013-02-06 14:52:58 +08:00
|
|
|
KEYWORD(noredzone);
|
|
|
|
KEYWORD(noreturn);
|
|
|
|
KEYWORD(nounwind);
|
2013-08-23 19:53:55 +08:00
|
|
|
KEYWORD(optnone);
|
2013-02-06 14:52:58 +08:00
|
|
|
KEYWORD(optsize);
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(readnone);
|
|
|
|
KEYWORD(readonly);
|
2013-04-20 13:14:40 +08:00
|
|
|
KEYWORD(returned);
|
2011-10-03 22:45:37 +08:00
|
|
|
KEYWORD(returns_twice);
|
2013-02-06 14:52:58 +08:00
|
|
|
KEYWORD(signext);
|
|
|
|
KEYWORD(sret);
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(ssp);
|
|
|
|
KEYWORD(sspreq);
|
2013-01-23 14:41:41 +08:00
|
|
|
KEYWORD(sspstrong);
|
Protection against stack-based memory corruption errors using SafeStack
This patch adds the safe stack instrumentation pass to LLVM, which separates
the program stack into a safe stack, which stores return addresses, register
spills, and local variables that are statically verified to be accessed
in a safe way, and the unsafe stack, which stores everything else. Such
separation makes it much harder for an attacker to corrupt objects on the
safe stack, including function pointers stored in spilled registers and
return addresses. You can find more information about the safe stack, as
well as other parts of or control-flow hijack protection technique in our
OSDI paper on code-pointer integrity (http://dslab.epfl.ch/pubs/cpi.pdf)
and our project website (http://levee.epfl.ch).
The overhead of our implementation of the safe stack is very close to zero
(0.01% on the Phoronix benchmarks). This is lower than the overhead of
stack cookies, which are supported by LLVM and are commonly used today,
yet the security guarantees of the safe stack are strictly stronger than
stack cookies. In some cases, the safe stack improves performance due to
better cache locality.
Our current implementation of the safe stack is stable and robust, we
used it to recompile multiple projects on Linux including Chromium, and
we also recompiled the entire FreeBSD user-space system and more than 100
packages. We ran unit tests on the FreeBSD system and many of the packages
and observed no errors caused by the safe stack. The safe stack is also fully
binary compatible with non-instrumented code and can be applied to parts of
a program selectively.
This patch is our implementation of the safe stack on top of LLVM. The
patches make the following changes:
- Add the safestack function attribute, similar to the ssp, sspstrong and
sspreq attributes.
- Add the SafeStack instrumentation pass that applies the safe stack to all
functions that have the safestack attribute. This pass moves all unsafe local
variables to the unsafe stack with a separate stack pointer, whereas all
safe variables remain on the regular stack that is managed by LLVM as usual.
- Invoke the pass as the last stage before code generation (at the same time
the existing cookie-based stack protector pass is invoked).
- Add unit tests for the safe stack.
Original patch by Volodymyr Kuznetsov and others at the Dependable Systems
Lab at EPFL; updates and upstreaming by myself.
Differential Revision: http://reviews.llvm.org/D6094
llvm-svn: 239761
2015-06-16 05:07:11 +08:00
|
|
|
KEYWORD(safestack);
|
2013-02-26 14:58:09 +08:00
|
|
|
KEYWORD(sanitize_address);
|
|
|
|
KEYWORD(sanitize_thread);
|
|
|
|
KEYWORD(sanitize_memory);
|
2013-02-06 14:52:58 +08:00
|
|
|
KEYWORD(uwtable);
|
|
|
|
KEYWORD(zeroext);
|
2009-01-02 15:01:27 +08:00
|
|
|
|
|
|
|
KEYWORD(type);
|
|
|
|
KEYWORD(opaque);
|
|
|
|
|
2014-06-28 02:19:56 +08:00
|
|
|
KEYWORD(comdat);
|
|
|
|
|
|
|
|
// Comdat types
|
|
|
|
KEYWORD(any);
|
|
|
|
KEYWORD(exactmatch);
|
|
|
|
KEYWORD(largest);
|
|
|
|
KEYWORD(noduplicates);
|
|
|
|
KEYWORD(samesize);
|
|
|
|
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(eq); KEYWORD(ne); KEYWORD(slt); KEYWORD(sgt); KEYWORD(sle);
|
|
|
|
KEYWORD(sge); KEYWORD(ult); KEYWORD(ugt); KEYWORD(ule); KEYWORD(uge);
|
|
|
|
KEYWORD(oeq); KEYWORD(one); KEYWORD(olt); KEYWORD(ogt); KEYWORD(ole);
|
|
|
|
KEYWORD(oge); KEYWORD(ord); KEYWORD(uno); KEYWORD(ueq); KEYWORD(une);
|
2009-01-03 06:46:48 +08:00
|
|
|
|
2011-07-29 05:48:00 +08:00
|
|
|
KEYWORD(xchg); KEYWORD(nand); KEYWORD(max); KEYWORD(min); KEYWORD(umax);
|
|
|
|
KEYWORD(umin);
|
|
|
|
|
2009-01-02 15:01:27 +08:00
|
|
|
KEYWORD(x);
|
2009-10-28 11:39:23 +08:00
|
|
|
KEYWORD(blockaddress);
|
2011-08-13 04:24:12 +08:00
|
|
|
|
2015-01-09 06:38:29 +08:00
|
|
|
// Metadata types.
|
|
|
|
KEYWORD(distinct);
|
|
|
|
|
2014-08-20 05:30:15 +08:00
|
|
|
// Use-list order directives.
|
|
|
|
KEYWORD(uselistorder);
|
|
|
|
KEYWORD(uselistorder_bb);
|
|
|
|
|
2011-08-13 04:24:12 +08:00
|
|
|
KEYWORD(personality);
|
|
|
|
KEYWORD(cleanup);
|
|
|
|
KEYWORD(catch);
|
|
|
|
KEYWORD(filter);
|
2007-11-18 16:46:26 +08:00
|
|
|
#undef KEYWORD
|
|
|
|
|
|
|
|
// Keywords for types.
|
2015-02-21 07:49:24 +08:00
|
|
|
#define TYPEKEYWORD(STR, LLVMTY) \
|
|
|
|
do { \
|
2015-02-21 08:18:40 +08:00
|
|
|
if (Keyword == STR) { \
|
2015-02-21 07:49:24 +08:00
|
|
|
TyVal = LLVMTY; \
|
|
|
|
return lltok::Type; \
|
|
|
|
} \
|
|
|
|
} while (false)
|
2009-08-14 05:58:54 +08:00
|
|
|
TYPEKEYWORD("void", Type::getVoidTy(Context));
|
2011-12-17 08:04:22 +08:00
|
|
|
TYPEKEYWORD("half", Type::getHalfTy(Context));
|
2009-08-14 05:58:54 +08:00
|
|
|
TYPEKEYWORD("float", Type::getFloatTy(Context));
|
|
|
|
TYPEKEYWORD("double", Type::getDoubleTy(Context));
|
|
|
|
TYPEKEYWORD("x86_fp80", Type::getX86_FP80Ty(Context));
|
|
|
|
TYPEKEYWORD("fp128", Type::getFP128Ty(Context));
|
|
|
|
TYPEKEYWORD("ppc_fp128", Type::getPPC_FP128Ty(Context));
|
|
|
|
TYPEKEYWORD("label", Type::getLabelTy(Context));
|
|
|
|
TYPEKEYWORD("metadata", Type::getMetadataTy(Context));
|
2010-09-11 04:55:01 +08:00
|
|
|
TYPEKEYWORD("x86_mmx", Type::getX86_MMXTy(Context));
|
2015-08-14 13:09:07 +08:00
|
|
|
TYPEKEYWORD("token", Type::getTokenTy(Context));
|
2007-11-18 16:46:26 +08:00
|
|
|
#undef TYPEKEYWORD
|
|
|
|
|
|
|
|
// Keywords for instructions.
|
2015-02-21 07:49:24 +08:00
|
|
|
#define INSTKEYWORD(STR, Enum) \
|
|
|
|
do { \
|
2015-02-21 08:18:40 +08:00
|
|
|
if (Keyword == #STR) { \
|
2015-02-21 07:49:24 +08:00
|
|
|
UIntVal = Instruction::Enum; \
|
|
|
|
return lltok::kw_##STR; \
|
|
|
|
} \
|
|
|
|
} while (false)
|
2009-01-02 15:01:27 +08:00
|
|
|
|
2009-06-05 06:49:04 +08:00
|
|
|
INSTKEYWORD(add, Add); INSTKEYWORD(fadd, FAdd);
|
|
|
|
INSTKEYWORD(sub, Sub); INSTKEYWORD(fsub, FSub);
|
|
|
|
INSTKEYWORD(mul, Mul); INSTKEYWORD(fmul, FMul);
|
2009-01-02 15:01:27 +08:00
|
|
|
INSTKEYWORD(udiv, UDiv); INSTKEYWORD(sdiv, SDiv); INSTKEYWORD(fdiv, FDiv);
|
|
|
|
INSTKEYWORD(urem, URem); INSTKEYWORD(srem, SRem); INSTKEYWORD(frem, FRem);
|
|
|
|
INSTKEYWORD(shl, Shl); INSTKEYWORD(lshr, LShr); INSTKEYWORD(ashr, AShr);
|
|
|
|
INSTKEYWORD(and, And); INSTKEYWORD(or, Or); INSTKEYWORD(xor, Xor);
|
|
|
|
INSTKEYWORD(icmp, ICmp); INSTKEYWORD(fcmp, FCmp);
|
|
|
|
|
|
|
|
INSTKEYWORD(phi, PHI);
|
|
|
|
INSTKEYWORD(call, Call);
|
|
|
|
INSTKEYWORD(trunc, Trunc);
|
|
|
|
INSTKEYWORD(zext, ZExt);
|
|
|
|
INSTKEYWORD(sext, SExt);
|
|
|
|
INSTKEYWORD(fptrunc, FPTrunc);
|
|
|
|
INSTKEYWORD(fpext, FPExt);
|
|
|
|
INSTKEYWORD(uitofp, UIToFP);
|
|
|
|
INSTKEYWORD(sitofp, SIToFP);
|
|
|
|
INSTKEYWORD(fptoui, FPToUI);
|
|
|
|
INSTKEYWORD(fptosi, FPToSI);
|
|
|
|
INSTKEYWORD(inttoptr, IntToPtr);
|
|
|
|
INSTKEYWORD(ptrtoint, PtrToInt);
|
|
|
|
INSTKEYWORD(bitcast, BitCast);
|
2013-11-15 09:34:59 +08:00
|
|
|
INSTKEYWORD(addrspacecast, AddrSpaceCast);
|
2009-01-02 15:01:27 +08:00
|
|
|
INSTKEYWORD(select, Select);
|
|
|
|
INSTKEYWORD(va_arg, VAArg);
|
|
|
|
INSTKEYWORD(ret, Ret);
|
|
|
|
INSTKEYWORD(br, Br);
|
|
|
|
INSTKEYWORD(switch, Switch);
|
2009-10-28 08:19:10 +08:00
|
|
|
INSTKEYWORD(indirectbr, IndirectBr);
|
2009-01-02 15:01:27 +08:00
|
|
|
INSTKEYWORD(invoke, Invoke);
|
2011-07-31 14:30:59 +08:00
|
|
|
INSTKEYWORD(resume, Resume);
|
2009-01-02 15:01:27 +08:00
|
|
|
INSTKEYWORD(unreachable, Unreachable);
|
|
|
|
|
|
|
|
INSTKEYWORD(alloca, Alloca);
|
|
|
|
INSTKEYWORD(load, Load);
|
|
|
|
INSTKEYWORD(store, Store);
|
2011-07-29 05:48:00 +08:00
|
|
|
INSTKEYWORD(cmpxchg, AtomicCmpXchg);
|
|
|
|
INSTKEYWORD(atomicrmw, AtomicRMW);
|
2011-07-26 07:16:38 +08:00
|
|
|
INSTKEYWORD(fence, Fence);
|
2009-01-02 15:01:27 +08:00
|
|
|
INSTKEYWORD(getelementptr, GetElementPtr);
|
|
|
|
|
|
|
|
INSTKEYWORD(extractelement, ExtractElement);
|
|
|
|
INSTKEYWORD(insertelement, InsertElement);
|
|
|
|
INSTKEYWORD(shufflevector, ShuffleVector);
|
|
|
|
INSTKEYWORD(extractvalue, ExtractValue);
|
|
|
|
INSTKEYWORD(insertvalue, InsertValue);
|
2011-08-13 04:24:12 +08:00
|
|
|
INSTKEYWORD(landingpad, LandingPad);
|
2015-08-01 01:58:14 +08:00
|
|
|
INSTKEYWORD(cleanupret, CleanupRet);
|
|
|
|
INSTKEYWORD(catchret, CatchRet);
|
|
|
|
INSTKEYWORD(catchpad, CatchPad);
|
|
|
|
INSTKEYWORD(terminatepad, TerminatePad);
|
|
|
|
INSTKEYWORD(cleanuppad, CleanupPad);
|
|
|
|
INSTKEYWORD(catchendpad, CatchEndPad);
|
2015-09-03 17:09:43 +08:00
|
|
|
INSTKEYWORD(cleanupendpad, CleanupEndPad);
|
2007-12-16 17:16:12 +08:00
|
|
|
#undef INSTKEYWORD
|
|
|
|
|
2015-02-13 09:17:35 +08:00
|
|
|
#define DWKEYWORD(TYPE, TOKEN) \
|
2015-02-21 07:49:24 +08:00
|
|
|
do { \
|
2015-02-21 08:18:40 +08:00
|
|
|
if (Keyword.startswith("DW_" #TYPE "_")) { \
|
|
|
|
StrVal.assign(Keyword.begin(), Keyword.end()); \
|
2015-02-21 07:49:24 +08:00
|
|
|
return lltok::TOKEN; \
|
|
|
|
} \
|
|
|
|
} while (false)
|
2015-02-13 09:17:35 +08:00
|
|
|
DWKEYWORD(TAG, DwarfTag);
|
|
|
|
DWKEYWORD(ATE, DwarfAttEncoding);
|
2015-02-13 09:28:16 +08:00
|
|
|
DWKEYWORD(VIRTUALITY, DwarfVirtuality);
|
2015-02-13 09:21:25 +08:00
|
|
|
DWKEYWORD(LANG, DwarfLang);
|
2015-02-13 09:42:09 +08:00
|
|
|
DWKEYWORD(OP, DwarfOp);
|
2015-02-13 09:17:35 +08:00
|
|
|
#undef DWKEYWORD
|
2015-02-04 05:56:01 +08:00
|
|
|
|
2015-02-21 09:02:18 +08:00
|
|
|
if (Keyword.startswith("DIFlag")) {
|
|
|
|
StrVal.assign(Keyword.begin(), Keyword.end());
|
|
|
|
return lltok::DIFlag;
|
|
|
|
}
|
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
// Check for [us]0x[0-9A-Fa-f]+ which are Hexadecimal constant generated by
|
|
|
|
// the CFE to avoid forcing it to deal with 64-bit numbers.
|
|
|
|
if ((TokStart[0] == 'u' || TokStart[0] == 's') &&
|
2013-02-13 05:21:59 +08:00
|
|
|
TokStart[1] == '0' && TokStart[2] == 'x' &&
|
|
|
|
isxdigit(static_cast<unsigned char>(TokStart[3]))) {
|
2007-11-18 16:46:26 +08:00
|
|
|
int len = CurPtr-TokStart-3;
|
|
|
|
uint32_t bits = len * 4;
|
2014-12-10 07:50:38 +08:00
|
|
|
StringRef HexStr(TokStart + 3, len);
|
|
|
|
if (!std::all_of(HexStr.begin(), HexStr.end(), isxdigit)) {
|
|
|
|
// Bad token, return it as an error.
|
|
|
|
CurPtr = TokStart+3;
|
|
|
|
return lltok::Error;
|
|
|
|
}
|
|
|
|
APInt Tmp(bits, HexStr, 16);
|
2007-11-18 16:46:26 +08:00
|
|
|
uint32_t activeBits = Tmp.getActiveBits();
|
|
|
|
if (activeBits > 0 && activeBits < bits)
|
2010-12-07 16:25:19 +08:00
|
|
|
Tmp = Tmp.trunc(activeBits);
|
2009-01-02 15:01:27 +08:00
|
|
|
APSIntVal = APSInt(Tmp, TokStart[0] == 'u');
|
|
|
|
return lltok::APSInt;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-19 02:43:24 +08:00
|
|
|
// If this is "cc1234", return this as just "cc".
|
2007-11-18 16:46:26 +08:00
|
|
|
if (TokStart[0] == 'c' && TokStart[1] == 'c') {
|
|
|
|
CurPtr = TokStart+2;
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::kw_cc;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2009-01-02 15:01:27 +08:00
|
|
|
// Finally, if this isn't known, return an error.
|
2007-11-18 16:46:26 +08:00
|
|
|
CurPtr = TokStart+1;
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::Error;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
|
2015-06-07 14:40:24 +08:00
|
|
|
/// Lex all tokens that start with a 0x prefix, knowing they match and are not
|
|
|
|
/// labels.
|
2007-11-18 16:46:26 +08:00
|
|
|
/// HexFPConstant 0x[0-9A-Fa-f]+
|
|
|
|
/// HexFP80Constant 0xK[0-9A-Fa-f]+
|
|
|
|
/// HexFP128Constant 0xL[0-9A-Fa-f]+
|
|
|
|
/// HexPPC128Constant 0xM[0-9A-Fa-f]+
|
2012-05-24 23:59:06 +08:00
|
|
|
/// HexHalfConstant 0xH[0-9A-Fa-f]+
|
2009-01-02 15:01:27 +08:00
|
|
|
lltok::Kind LLLexer::Lex0x() {
|
2007-11-18 16:46:26 +08:00
|
|
|
CurPtr = TokStart + 2;
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
char Kind;
|
2012-05-25 01:11:00 +08:00
|
|
|
if ((CurPtr[0] >= 'K' && CurPtr[0] <= 'M') || CurPtr[0] == 'H') {
|
2007-11-18 16:46:26 +08:00
|
|
|
Kind = *CurPtr++;
|
|
|
|
} else {
|
|
|
|
Kind = 'J';
|
|
|
|
}
|
|
|
|
|
2013-02-13 05:21:59 +08:00
|
|
|
if (!isxdigit(static_cast<unsigned char>(CurPtr[0]))) {
|
2009-01-02 15:01:27 +08:00
|
|
|
// Bad token, return it as an error.
|
2007-11-18 16:46:26 +08:00
|
|
|
CurPtr = TokStart+1;
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::Error;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2013-02-13 05:21:59 +08:00
|
|
|
while (isxdigit(static_cast<unsigned char>(CurPtr[0])))
|
2007-11-18 16:46:26 +08:00
|
|
|
++CurPtr;
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
if (Kind == 'J') {
|
|
|
|
// HexFPConstant - Floating point constant represented in IEEE format as a
|
|
|
|
// hexadecimal number for when exponential notation is not precise enough.
|
2011-12-17 08:04:22 +08:00
|
|
|
// Half, Float, and double only.
|
2009-01-02 15:01:27 +08:00
|
|
|
APFloatVal = APFloat(BitsToDouble(HexIntToVal(TokStart+2, CurPtr)));
|
|
|
|
return lltok::APFloat;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
uint64_t Pair[2];
|
|
|
|
switch (Kind) {
|
2009-07-15 00:55:14 +08:00
|
|
|
default: llvm_unreachable("Unknown kind!");
|
2007-11-18 16:46:26 +08:00
|
|
|
case 'K':
|
|
|
|
// F80HexFPConstant - x87 long double in hexadecimal format (10 bytes)
|
2009-03-24 05:16:53 +08:00
|
|
|
FP80HexToIntPair(TokStart+3, CurPtr, Pair);
|
2013-01-22 17:46:31 +08:00
|
|
|
APFloatVal = APFloat(APFloat::x87DoubleExtended, APInt(80, Pair));
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::APFloat;
|
2007-11-18 16:46:26 +08:00
|
|
|
case 'L':
|
|
|
|
// F128HexFPConstant - IEEE 128-bit in hexadecimal format (16 bytes)
|
2009-03-24 05:16:53 +08:00
|
|
|
HexToIntPair(TokStart+3, CurPtr, Pair);
|
2013-01-22 17:46:31 +08:00
|
|
|
APFloatVal = APFloat(APFloat::IEEEquad, APInt(128, Pair));
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::APFloat;
|
2007-11-18 16:46:26 +08:00
|
|
|
case 'M':
|
|
|
|
// PPC128HexFPConstant - PowerPC 128-bit in hexadecimal format (16 bytes)
|
2009-03-24 05:16:53 +08:00
|
|
|
HexToIntPair(TokStart+3, CurPtr, Pair);
|
2013-01-22 17:46:31 +08:00
|
|
|
APFloatVal = APFloat(APFloat::PPCDoubleDouble, APInt(128, Pair));
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::APFloat;
|
2012-05-24 23:59:06 +08:00
|
|
|
case 'H':
|
2013-01-22 17:46:31 +08:00
|
|
|
APFloatVal = APFloat(APFloat::IEEEhalf,
|
|
|
|
APInt(16,HexIntToVal(TokStart+3, CurPtr)));
|
2012-05-24 23:59:06 +08:00
|
|
|
return lltok::APFloat;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-07 14:40:24 +08:00
|
|
|
/// Lex tokens for a label or a numeric constant, possibly starting with -.
|
2007-11-18 16:46:26 +08:00
|
|
|
/// Label [-a-zA-Z$._0-9]+:
|
|
|
|
/// NInteger -[0-9]+
|
|
|
|
/// FPConstant [-+]?[0-9]+[.][0-9]*([eE][-+]?[0-9]+)?
|
|
|
|
/// PInteger [0-9]+
|
|
|
|
/// HexFPConstant 0x[0-9A-Fa-f]+
|
|
|
|
/// HexFP80Constant 0xK[0-9A-Fa-f]+
|
|
|
|
/// HexFP128Constant 0xL[0-9A-Fa-f]+
|
|
|
|
/// HexPPC128Constant 0xM[0-9A-Fa-f]+
|
2009-01-02 15:01:27 +08:00
|
|
|
lltok::Kind LLLexer::LexDigitOrNegative() {
|
2012-11-16 14:10:48 +08:00
|
|
|
// If the letter after the negative is not a number, this is probably a label.
|
2013-02-13 05:21:59 +08:00
|
|
|
if (!isdigit(static_cast<unsigned char>(TokStart[0])) &&
|
|
|
|
!isdigit(static_cast<unsigned char>(CurPtr[0]))) {
|
2007-11-18 16:46:26 +08:00
|
|
|
// Okay, this is not a number after the -, it's probably a label.
|
|
|
|
if (const char *End = isLabelTail(CurPtr)) {
|
2009-01-02 15:01:27 +08:00
|
|
|
StrVal.assign(TokStart, End-1);
|
2007-11-18 16:46:26 +08:00
|
|
|
CurPtr = End;
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::LabelStr;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::Error;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
// At this point, it is either a label, int or fp constant.
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
// Skip digits, we have at least one.
|
2013-02-13 05:21:59 +08:00
|
|
|
for (; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr)
|
2007-12-16 17:16:12 +08:00
|
|
|
/*empty*/;
|
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
// Check to see if this really is a label afterall, e.g. "-1:".
|
|
|
|
if (isLabelChar(CurPtr[0]) || CurPtr[0] == ':') {
|
|
|
|
if (const char *End = isLabelTail(CurPtr)) {
|
2009-01-02 15:01:27 +08:00
|
|
|
StrVal.assign(TokStart, End-1);
|
2007-11-18 16:46:26 +08:00
|
|
|
CurPtr = End;
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::LabelStr;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
}
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
// If the next character is a '.', then it is a fp value, otherwise its
|
|
|
|
// integer.
|
|
|
|
if (CurPtr[0] != '.') {
|
|
|
|
if (TokStart[0] == '0' && TokStart[1] == 'x')
|
|
|
|
return Lex0x();
|
2015-06-24 02:22:10 +08:00
|
|
|
APSIntVal = APSInt(StringRef(TokStart, CurPtr - TokStart));
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::APSInt;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
++CurPtr;
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
// Skip over [0-9]*([eE][-+]?[0-9]+)?
|
2013-02-13 05:21:59 +08:00
|
|
|
while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr;
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
if (CurPtr[0] == 'e' || CurPtr[0] == 'E') {
|
2013-02-13 05:21:59 +08:00
|
|
|
if (isdigit(static_cast<unsigned char>(CurPtr[1])) ||
|
|
|
|
((CurPtr[1] == '-' || CurPtr[1] == '+') &&
|
|
|
|
isdigit(static_cast<unsigned char>(CurPtr[2])))) {
|
2007-11-18 16:46:26 +08:00
|
|
|
CurPtr += 2;
|
2013-02-13 05:21:59 +08:00
|
|
|
while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
}
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2010-12-20 04:42:43 +08:00
|
|
|
APFloatVal = APFloat(std::atof(TokStart));
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::APFloat;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
|
2015-06-07 14:40:24 +08:00
|
|
|
/// Lex a floating point constant starting with +.
|
2007-11-18 16:46:26 +08:00
|
|
|
/// FPConstant [-+]?[0-9]+[.][0-9]*([eE][-+]?[0-9]+)?
|
2009-01-02 15:01:27 +08:00
|
|
|
lltok::Kind LLLexer::LexPositive() {
|
2007-11-18 16:46:26 +08:00
|
|
|
// If the letter after the negative is a number, this is probably not a
|
|
|
|
// label.
|
2013-02-13 05:21:59 +08:00
|
|
|
if (!isdigit(static_cast<unsigned char>(CurPtr[0])))
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::Error;
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
// Skip digits.
|
2013-02-13 05:21:59 +08:00
|
|
|
for (++CurPtr; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr)
|
2007-12-16 17:16:12 +08:00
|
|
|
/*empty*/;
|
2007-11-18 16:46:26 +08:00
|
|
|
|
|
|
|
// At this point, we need a '.'.
|
|
|
|
if (CurPtr[0] != '.') {
|
|
|
|
CurPtr = TokStart+1;
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::Error;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
++CurPtr;
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
// Skip over [0-9]*([eE][-+]?[0-9]+)?
|
2013-02-13 05:21:59 +08:00
|
|
|
while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr;
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2007-11-18 16:46:26 +08:00
|
|
|
if (CurPtr[0] == 'e' || CurPtr[0] == 'E') {
|
2013-02-13 05:21:59 +08:00
|
|
|
if (isdigit(static_cast<unsigned char>(CurPtr[1])) ||
|
|
|
|
((CurPtr[1] == '-' || CurPtr[1] == '+') &&
|
|
|
|
isdigit(static_cast<unsigned char>(CurPtr[2])))) {
|
2007-11-18 16:46:26 +08:00
|
|
|
CurPtr += 2;
|
2013-02-13 05:21:59 +08:00
|
|
|
while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|
|
|
|
}
|
2007-12-16 17:16:12 +08:00
|
|
|
|
2010-12-20 04:42:43 +08:00
|
|
|
APFloatVal = APFloat(std::atof(TokStart));
|
2009-01-02 15:01:27 +08:00
|
|
|
return lltok::APFloat;
|
2007-11-18 16:46:26 +08:00
|
|
|
}
|