diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:45:01 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:01 +0300 |
commit | 2d37894b1b037cf24231090eda8589bbb44fb6fc (patch) | |
tree | be835aa92c6248212e705f25388ebafcf84bc7a1 /contrib/libs/llvm12/lib/AsmParser | |
parent | 718c552901d703c502ccbefdfc3c9028d608b947 (diff) | |
download | ydb-2d37894b1b037cf24231090eda8589bbb44fb6fc.tar.gz |
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/llvm12/lib/AsmParser')
-rw-r--r-- | contrib/libs/llvm12/lib/AsmParser/LLLexer.cpp | 2330 | ||||
-rw-r--r-- | contrib/libs/llvm12/lib/AsmParser/LLLexer.h | 208 | ||||
-rw-r--r-- | contrib/libs/llvm12/lib/AsmParser/LLParser.cpp | 14970 | ||||
-rw-r--r-- | contrib/libs/llvm12/lib/AsmParser/LLParser.h | 788 | ||||
-rw-r--r-- | contrib/libs/llvm12/lib/AsmParser/LLToken.h | 968 | ||||
-rw-r--r-- | contrib/libs/llvm12/lib/AsmParser/Parser.cpp | 442 | ||||
-rw-r--r-- | contrib/libs/llvm12/lib/AsmParser/ya.make | 40 |
7 files changed, 9873 insertions, 9873 deletions
diff --git a/contrib/libs/llvm12/lib/AsmParser/LLLexer.cpp b/contrib/libs/llvm12/lib/AsmParser/LLLexer.cpp index 7bafc4b200..427de74f91 100644 --- a/contrib/libs/llvm12/lib/AsmParser/LLLexer.cpp +++ b/contrib/libs/llvm12/lib/AsmParser/LLLexer.cpp @@ -1,1173 +1,1173 @@ -//===- LLLexer.cpp - Lexer for .ll Files ----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Implement the Lexer for .ll files. -// -//===----------------------------------------------------------------------===// - -#include "LLLexer.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Twine.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Instruction.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/SourceMgr.h" -#include <cassert> -#include <cctype> -#include <cstdio> - -using namespace llvm; - -bool LLLexer::Error(LocTy ErrorLoc, const Twine &Msg) const { - ErrorInfo = SM.GetMessage(ErrorLoc, SourceMgr::DK_Error, Msg); - return true; -} - -void LLLexer::Warning(LocTy WarningLoc, const Twine &Msg) const { - SM.PrintMessage(WarningLoc, SourceMgr::DK_Warning, Msg); -} - -//===----------------------------------------------------------------------===// -// 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... -// -uint64_t LLLexer::atoull(const char *Buffer, const char *End) { - uint64_t Result = 0; - for (; Buffer != End; Buffer++) { - uint64_t OldRes = Result; - Result *= 10; - Result += *Buffer-'0'; - if (Result < OldRes) { // Uh, oh, overflow detected!!! - Error("constant bigger than 64 bits detected!"); - return 0; - } - } - return Result; -} - -uint64_t LLLexer::HexIntToVal(const char *Buffer, const char *End) { - uint64_t Result = 0; - for (; Buffer != End; ++Buffer) { - uint64_t OldRes = Result; - Result *= 16; - Result += hexDigitValue(*Buffer); - - if (Result < OldRes) { // Uh, oh, overflow detected!!! - Error("constant bigger than 64 bits detected!"); - return 0; - } - } - return Result; -} - -void LLLexer::HexToIntPair(const char *Buffer, const char *End, - uint64_t Pair[2]) { - Pair[0] = 0; - if (End - Buffer >= 16) { - for (int i = 0; i < 16; i++, Buffer++) { - assert(Buffer != End); - Pair[0] *= 16; - Pair[0] += hexDigitValue(*Buffer); - } - } - Pair[1] = 0; - for (int i = 0; i < 16 && Buffer != End; i++, Buffer++) { - Pair[1] *= 16; - Pair[1] += hexDigitValue(*Buffer); - } - if (Buffer != End) - Error("constant bigger than 128 bits detected!"); -} - -/// 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; - Pair[1] += hexDigitValue(*Buffer); - } - Pair[0] = 0; - for (int i = 0; i < 16 && Buffer != End; i++, Buffer++) { - Pair[0] *= 16; - Pair[0] += hexDigitValue(*Buffer); - } - if (Buffer != End) - Error("constant bigger than 128 bits detected!"); -} - -// UnEscapeLexed - Run through the specified buffer and change \xx codes to the -// appropriate character. -static void UnEscapeLexed(std::string &Str) { - if (Str.empty()) return; - - 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; - } else if (BIn < EndBuffer-2 && - isxdigit(static_cast<unsigned char>(BIn[1])) && - isxdigit(static_cast<unsigned char>(BIn[2]))) { - *BOut = hexDigitValue(BIn[1]) * 16 + hexDigitValue(BIn[2]); - 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) { - return isalnum(static_cast<unsigned char>(C)) || C == '-' || C == '$' || - C == '.' || C == '_'; -} - -/// isLabelTail - Return true if this pointer points to a valid end of a label. -static const char *isLabelTail(const char *CurPtr) { - while (true) { - if (CurPtr[0] == ':') return CurPtr+1; - if (!isLabelChar(CurPtr[0])) return nullptr; - ++CurPtr; - } -} - -//===----------------------------------------------------------------------===// -// Lexer definition. -//===----------------------------------------------------------------------===// - -LLLexer::LLLexer(StringRef StartBuf, SourceMgr &SM, SMDiagnostic &Err, - LLVMContext &C) - : CurBuf(StartBuf), ErrorInfo(Err), SM(SM), Context(C), APFloatVal(0.0), - IgnoreColonInIdentifiers(false) { - CurPtr = CurBuf.begin(); -} - -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. - if (CurPtr-1 != CurBuf.end()) - return 0; // Just whitespace. - - // Otherwise, return end of file. - --CurPtr; // Another call to lex will return EOF again. - return EOF; - } -} - -lltok::Kind LLLexer::LexToken() { - while (true) { - TokStart = CurPtr; - - int CurChar = getNextChar(); - switch (CurChar) { - default: - // Handle letters: [a-zA-Z_] - if (isalpha(static_cast<unsigned char>(CurChar)) || CurChar == '_') - return LexIdentifier(); - - return lltok::Error; - case EOF: return lltok::Eof; - case 0: - case ' ': - case '\t': - case '\n': - case '\r': - // Ignore whitespace. - continue; - case '+': return LexPositive(); - case '@': return LexAt(); - case '$': return LexDollar(); - case '%': return LexPercent(); - case '"': return LexQuote(); - case '.': - if (const char *Ptr = isLabelTail(CurPtr)) { - CurPtr = Ptr; - StrVal.assign(TokStart, CurPtr-1); - return lltok::LabelStr; - } - if (CurPtr[0] == '.' && CurPtr[1] == '.') { - CurPtr += 2; - return lltok::dotdotdot; - } - return lltok::Error; - case ';': - SkipLineComment(); - continue; - case '!': return LexExclaim(); - case '^': - return LexCaret(); - case ':': - return lltok::colon; - case '#': return LexHash(); - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - case '-': - return LexDigitOrNegative(); - 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; - case '|': return lltok::bar; - } - } -} - -void LLLexer::SkipLineComment() { - while (true) { - if (CurPtr[0] == '\n' || CurPtr[0] == '\r' || getNextChar() == EOF) - return; - } -} - -/// Lex all tokens that start with an @ character. -/// GlobalVar @\"[^\"]*\" -/// GlobalVar @[-a-zA-Z$._][-a-zA-Z$._0-9]* -/// GlobalVarID @[0-9]+ -lltok::Kind LLLexer::LexAt() { - return LexVar(lltok::GlobalVar, lltok::GlobalID); -} - -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 (true) { - 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; -} - -/// ReadString - Read a string until the closing quote. -lltok::Kind LLLexer::ReadString(lltok::Kind kind) { - const char *Start = CurPtr; - while (true) { - 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; - if (isalpha(static_cast<unsigned char>(CurPtr[0])) || - CurPtr[0] == '-' || CurPtr[0] == '$' || - CurPtr[0] == '.' || CurPtr[0] == '_') { - ++CurPtr; - while (isalnum(static_cast<unsigned char>(CurPtr[0])) || - CurPtr[0] == '-' || CurPtr[0] == '$' || - CurPtr[0] == '.' || CurPtr[0] == '_') - ++CurPtr; - - StrVal.assign(NameStart, CurPtr); - return true; - } - return false; -} - -// Lex an ID: [0-9]+. On success, the ID is stored in UIntVal and Token is -// returned, otherwise the Error token is returned. -lltok::Kind LLLexer::LexUIntID(lltok::Kind Token) { - if (!isdigit(static_cast<unsigned char>(CurPtr[0]))) - return lltok::Error; - - for (++CurPtr; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr) - /*empty*/; - - uint64_t Val = atoull(TokStart + 1, CurPtr); - if ((unsigned)Val != Val) - Error("invalid value number (too large)!"); - UIntVal = unsigned(Val); - return Token; -} - -lltok::Kind LLLexer::LexVar(lltok::Kind Var, lltok::Kind VarID) { - // Handle StringConstant: \"[^\"]*\" - if (CurPtr[0] == '"') { - ++CurPtr; - - while (true) { - 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; - } - } - } - - // Handle VarName: [-a-zA-Z$._][-a-zA-Z$._0-9]* - if (ReadVarName()) - return Var; - - // Handle VarID: [0-9]+ - return LexUIntID(VarID); -} - -/// Lex all tokens that start with a % character. -/// LocalVar ::= %\"[^\"]*\" -/// LocalVar ::= %[-a-zA-Z$._][-a-zA-Z$._0-9]* -/// LocalVarID ::= %[0-9]+ -lltok::Kind LLLexer::LexPercent() { - return LexVar(lltok::LocalVar, lltok::LocalVarID); -} - -/// Lex all tokens that start with a " character. -/// QuoteLabel "[^"]+": -/// StringConstant "[^"]*" -lltok::Kind LLLexer::LexQuote() { - lltok::Kind kind = ReadString(lltok::StringConstant); - if (kind == lltok::Error || kind == lltok::Eof) - return kind; - - if (CurPtr[0] == ':') { - ++CurPtr; - if (StringRef(StrVal).find_first_of(0) != StringRef::npos) { - Error("Null bytes are not allowed in names"); - kind = lltok::Error; - } else { - kind = lltok::LabelStr; - } - } - - return kind; -} - -/// Lex all tokens that start with a ! character. -/// !foo -/// ! -lltok::Kind LLLexer::LexExclaim() { - // Lex a metadata name as a MetadataVar. - if (isalpha(static_cast<unsigned char>(CurPtr[0])) || - CurPtr[0] == '-' || CurPtr[0] == '$' || - CurPtr[0] == '.' || CurPtr[0] == '_' || CurPtr[0] == '\\') { - ++CurPtr; - while (isalnum(static_cast<unsigned char>(CurPtr[0])) || - CurPtr[0] == '-' || CurPtr[0] == '$' || - CurPtr[0] == '.' || CurPtr[0] == '_' || CurPtr[0] == '\\') - ++CurPtr; - - StrVal.assign(TokStart+1, CurPtr); // Skip ! - UnEscapeLexed(StrVal); - return lltok::MetadataVar; - } - return lltok::exclaim; -} - -/// Lex all tokens that start with a ^ character. -/// SummaryID ::= ^[0-9]+ -lltok::Kind LLLexer::LexCaret() { - // Handle SummaryID: ^[0-9]+ - return LexUIntID(lltok::SummaryID); -} - -/// Lex all tokens that start with a # character. -/// AttrGrpID ::= #[0-9]+ -lltok::Kind LLLexer::LexHash() { - // Handle AttrGrpID: #[0-9]+ - return LexUIntID(lltok::AttrGrpID); -} - -/// Lex a label, integer type, keyword, or hexadecimal integer constant. -/// Label [-a-zA-Z$._0-9]+: -/// IntegerType i[0-9]+ -/// Keyword sdiv, float, ... -/// HexIntConstant [us]0x[0-9A-Fa-f]+ -lltok::Kind LLLexer::LexIdentifier() { - const char *StartChar = CurPtr; - const char *IntEnd = CurPtr[-1] == 'i' ? nullptr : StartChar; - const char *KeywordEnd = nullptr; - - for (; isLabelChar(*CurPtr); ++CurPtr) { - // If we decide this is an integer, remember the end of the sequence. - if (!IntEnd && !isdigit(static_cast<unsigned char>(*CurPtr))) - IntEnd = CurPtr; - if (!KeywordEnd && !isalnum(static_cast<unsigned char>(*CurPtr)) && - *CurPtr != '_') - KeywordEnd = CurPtr; - } - - // If we stopped due to a colon, unless we were directed to ignore it, - // this really is a label. - if (!IgnoreColonInIdentifiers && *CurPtr == ':') { - StrVal.assign(StartChar-1, CurPtr++); - return lltok::LabelStr; - } - - // Otherwise, this wasn't a label. If this was valid as an integer type, - // return it. - if (!IntEnd) IntEnd = CurPtr; - if (IntEnd != StartChar) { - CurPtr = IntEnd; - uint64_t NumBits = atoull(StartChar, CurPtr); - if (NumBits < IntegerType::MIN_INT_BITS || - NumBits > IntegerType::MAX_INT_BITS) { - Error("bitwidth for integer type out of range!"); - return lltok::Error; - } - TyVal = IntegerType::get(Context, NumBits); - return lltok::Type; - } - - // Otherwise, this was a letter sequence. See which keyword this is. - if (!KeywordEnd) KeywordEnd = CurPtr; - CurPtr = KeywordEnd; - --StartChar; - StringRef Keyword(StartChar, CurPtr - StartChar); - -#define KEYWORD(STR) \ - do { \ - if (Keyword == #STR) \ - return lltok::kw_##STR; \ - } while (false) - - KEYWORD(true); KEYWORD(false); - KEYWORD(declare); KEYWORD(define); - KEYWORD(global); KEYWORD(constant); - - KEYWORD(dso_local); - KEYWORD(dso_preemptable); - - KEYWORD(private); - KEYWORD(internal); - KEYWORD(available_externally); - KEYWORD(linkonce); - KEYWORD(linkonce_odr); - KEYWORD(weak); // Use as a linkage, and a modifier for "cmpxchg". - KEYWORD(weak_odr); - KEYWORD(appending); - KEYWORD(dllimport); - KEYWORD(dllexport); - KEYWORD(common); - KEYWORD(default); - KEYWORD(hidden); - KEYWORD(protected); - KEYWORD(unnamed_addr); - KEYWORD(local_unnamed_addr); - KEYWORD(externally_initialized); - KEYWORD(extern_weak); - KEYWORD(external); - KEYWORD(thread_local); - KEYWORD(localdynamic); - KEYWORD(initialexec); - KEYWORD(localexec); - KEYWORD(zeroinitializer); - KEYWORD(undef); - KEYWORD(null); - KEYWORD(none); +//===- LLLexer.cpp - Lexer for .ll Files ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implement the Lexer for .ll files. +// +//===----------------------------------------------------------------------===// + +#include "LLLexer.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SourceMgr.h" +#include <cassert> +#include <cctype> +#include <cstdio> + +using namespace llvm; + +bool LLLexer::Error(LocTy ErrorLoc, const Twine &Msg) const { + ErrorInfo = SM.GetMessage(ErrorLoc, SourceMgr::DK_Error, Msg); + return true; +} + +void LLLexer::Warning(LocTy WarningLoc, const Twine &Msg) const { + SM.PrintMessage(WarningLoc, SourceMgr::DK_Warning, Msg); +} + +//===----------------------------------------------------------------------===// +// 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... +// +uint64_t LLLexer::atoull(const char *Buffer, const char *End) { + uint64_t Result = 0; + for (; Buffer != End; Buffer++) { + uint64_t OldRes = Result; + Result *= 10; + Result += *Buffer-'0'; + if (Result < OldRes) { // Uh, oh, overflow detected!!! + Error("constant bigger than 64 bits detected!"); + return 0; + } + } + return Result; +} + +uint64_t LLLexer::HexIntToVal(const char *Buffer, const char *End) { + uint64_t Result = 0; + for (; Buffer != End; ++Buffer) { + uint64_t OldRes = Result; + Result *= 16; + Result += hexDigitValue(*Buffer); + + if (Result < OldRes) { // Uh, oh, overflow detected!!! + Error("constant bigger than 64 bits detected!"); + return 0; + } + } + return Result; +} + +void LLLexer::HexToIntPair(const char *Buffer, const char *End, + uint64_t Pair[2]) { + Pair[0] = 0; + if (End - Buffer >= 16) { + for (int i = 0; i < 16; i++, Buffer++) { + assert(Buffer != End); + Pair[0] *= 16; + Pair[0] += hexDigitValue(*Buffer); + } + } + Pair[1] = 0; + for (int i = 0; i < 16 && Buffer != End; i++, Buffer++) { + Pair[1] *= 16; + Pair[1] += hexDigitValue(*Buffer); + } + if (Buffer != End) + Error("constant bigger than 128 bits detected!"); +} + +/// 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; + Pair[1] += hexDigitValue(*Buffer); + } + Pair[0] = 0; + for (int i = 0; i < 16 && Buffer != End; i++, Buffer++) { + Pair[0] *= 16; + Pair[0] += hexDigitValue(*Buffer); + } + if (Buffer != End) + Error("constant bigger than 128 bits detected!"); +} + +// UnEscapeLexed - Run through the specified buffer and change \xx codes to the +// appropriate character. +static void UnEscapeLexed(std::string &Str) { + if (Str.empty()) return; + + 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; + } else if (BIn < EndBuffer-2 && + isxdigit(static_cast<unsigned char>(BIn[1])) && + isxdigit(static_cast<unsigned char>(BIn[2]))) { + *BOut = hexDigitValue(BIn[1]) * 16 + hexDigitValue(BIn[2]); + 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) { + return isalnum(static_cast<unsigned char>(C)) || C == '-' || C == '$' || + C == '.' || C == '_'; +} + +/// isLabelTail - Return true if this pointer points to a valid end of a label. +static const char *isLabelTail(const char *CurPtr) { + while (true) { + if (CurPtr[0] == ':') return CurPtr+1; + if (!isLabelChar(CurPtr[0])) return nullptr; + ++CurPtr; + } +} + +//===----------------------------------------------------------------------===// +// Lexer definition. +//===----------------------------------------------------------------------===// + +LLLexer::LLLexer(StringRef StartBuf, SourceMgr &SM, SMDiagnostic &Err, + LLVMContext &C) + : CurBuf(StartBuf), ErrorInfo(Err), SM(SM), Context(C), APFloatVal(0.0), + IgnoreColonInIdentifiers(false) { + CurPtr = CurBuf.begin(); +} + +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. + if (CurPtr-1 != CurBuf.end()) + return 0; // Just whitespace. + + // Otherwise, return end of file. + --CurPtr; // Another call to lex will return EOF again. + return EOF; + } +} + +lltok::Kind LLLexer::LexToken() { + while (true) { + TokStart = CurPtr; + + int CurChar = getNextChar(); + switch (CurChar) { + default: + // Handle letters: [a-zA-Z_] + if (isalpha(static_cast<unsigned char>(CurChar)) || CurChar == '_') + return LexIdentifier(); + + return lltok::Error; + case EOF: return lltok::Eof; + case 0: + case ' ': + case '\t': + case '\n': + case '\r': + // Ignore whitespace. + continue; + case '+': return LexPositive(); + case '@': return LexAt(); + case '$': return LexDollar(); + case '%': return LexPercent(); + case '"': return LexQuote(); + case '.': + if (const char *Ptr = isLabelTail(CurPtr)) { + CurPtr = Ptr; + StrVal.assign(TokStart, CurPtr-1); + return lltok::LabelStr; + } + if (CurPtr[0] == '.' && CurPtr[1] == '.') { + CurPtr += 2; + return lltok::dotdotdot; + } + return lltok::Error; + case ';': + SkipLineComment(); + continue; + case '!': return LexExclaim(); + case '^': + return LexCaret(); + case ':': + return lltok::colon; + case '#': return LexHash(); + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '-': + return LexDigitOrNegative(); + 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; + case '|': return lltok::bar; + } + } +} + +void LLLexer::SkipLineComment() { + while (true) { + if (CurPtr[0] == '\n' || CurPtr[0] == '\r' || getNextChar() == EOF) + return; + } +} + +/// Lex all tokens that start with an @ character. +/// GlobalVar @\"[^\"]*\" +/// GlobalVar @[-a-zA-Z$._][-a-zA-Z$._0-9]* +/// GlobalVarID @[0-9]+ +lltok::Kind LLLexer::LexAt() { + return LexVar(lltok::GlobalVar, lltok::GlobalID); +} + +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 (true) { + 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; +} + +/// ReadString - Read a string until the closing quote. +lltok::Kind LLLexer::ReadString(lltok::Kind kind) { + const char *Start = CurPtr; + while (true) { + 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; + if (isalpha(static_cast<unsigned char>(CurPtr[0])) || + CurPtr[0] == '-' || CurPtr[0] == '$' || + CurPtr[0] == '.' || CurPtr[0] == '_') { + ++CurPtr; + while (isalnum(static_cast<unsigned char>(CurPtr[0])) || + CurPtr[0] == '-' || CurPtr[0] == '$' || + CurPtr[0] == '.' || CurPtr[0] == '_') + ++CurPtr; + + StrVal.assign(NameStart, CurPtr); + return true; + } + return false; +} + +// Lex an ID: [0-9]+. On success, the ID is stored in UIntVal and Token is +// returned, otherwise the Error token is returned. +lltok::Kind LLLexer::LexUIntID(lltok::Kind Token) { + if (!isdigit(static_cast<unsigned char>(CurPtr[0]))) + return lltok::Error; + + for (++CurPtr; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr) + /*empty*/; + + uint64_t Val = atoull(TokStart + 1, CurPtr); + if ((unsigned)Val != Val) + Error("invalid value number (too large)!"); + UIntVal = unsigned(Val); + return Token; +} + +lltok::Kind LLLexer::LexVar(lltok::Kind Var, lltok::Kind VarID) { + // Handle StringConstant: \"[^\"]*\" + if (CurPtr[0] == '"') { + ++CurPtr; + + while (true) { + 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; + } + } + } + + // Handle VarName: [-a-zA-Z$._][-a-zA-Z$._0-9]* + if (ReadVarName()) + return Var; + + // Handle VarID: [0-9]+ + return LexUIntID(VarID); +} + +/// Lex all tokens that start with a % character. +/// LocalVar ::= %\"[^\"]*\" +/// LocalVar ::= %[-a-zA-Z$._][-a-zA-Z$._0-9]* +/// LocalVarID ::= %[0-9]+ +lltok::Kind LLLexer::LexPercent() { + return LexVar(lltok::LocalVar, lltok::LocalVarID); +} + +/// Lex all tokens that start with a " character. +/// QuoteLabel "[^"]+": +/// StringConstant "[^"]*" +lltok::Kind LLLexer::LexQuote() { + lltok::Kind kind = ReadString(lltok::StringConstant); + if (kind == lltok::Error || kind == lltok::Eof) + return kind; + + if (CurPtr[0] == ':') { + ++CurPtr; + if (StringRef(StrVal).find_first_of(0) != StringRef::npos) { + Error("Null bytes are not allowed in names"); + kind = lltok::Error; + } else { + kind = lltok::LabelStr; + } + } + + return kind; +} + +/// Lex all tokens that start with a ! character. +/// !foo +/// ! +lltok::Kind LLLexer::LexExclaim() { + // Lex a metadata name as a MetadataVar. + if (isalpha(static_cast<unsigned char>(CurPtr[0])) || + CurPtr[0] == '-' || CurPtr[0] == '$' || + CurPtr[0] == '.' || CurPtr[0] == '_' || CurPtr[0] == '\\') { + ++CurPtr; + while (isalnum(static_cast<unsigned char>(CurPtr[0])) || + CurPtr[0] == '-' || CurPtr[0] == '$' || + CurPtr[0] == '.' || CurPtr[0] == '_' || CurPtr[0] == '\\') + ++CurPtr; + + StrVal.assign(TokStart+1, CurPtr); // Skip ! + UnEscapeLexed(StrVal); + return lltok::MetadataVar; + } + return lltok::exclaim; +} + +/// Lex all tokens that start with a ^ character. +/// SummaryID ::= ^[0-9]+ +lltok::Kind LLLexer::LexCaret() { + // Handle SummaryID: ^[0-9]+ + return LexUIntID(lltok::SummaryID); +} + +/// Lex all tokens that start with a # character. +/// AttrGrpID ::= #[0-9]+ +lltok::Kind LLLexer::LexHash() { + // Handle AttrGrpID: #[0-9]+ + return LexUIntID(lltok::AttrGrpID); +} + +/// Lex a label, integer type, keyword, or hexadecimal integer constant. +/// Label [-a-zA-Z$._0-9]+: +/// IntegerType i[0-9]+ +/// Keyword sdiv, float, ... +/// HexIntConstant [us]0x[0-9A-Fa-f]+ +lltok::Kind LLLexer::LexIdentifier() { + const char *StartChar = CurPtr; + const char *IntEnd = CurPtr[-1] == 'i' ? nullptr : StartChar; + const char *KeywordEnd = nullptr; + + for (; isLabelChar(*CurPtr); ++CurPtr) { + // If we decide this is an integer, remember the end of the sequence. + if (!IntEnd && !isdigit(static_cast<unsigned char>(*CurPtr))) + IntEnd = CurPtr; + if (!KeywordEnd && !isalnum(static_cast<unsigned char>(*CurPtr)) && + *CurPtr != '_') + KeywordEnd = CurPtr; + } + + // If we stopped due to a colon, unless we were directed to ignore it, + // this really is a label. + if (!IgnoreColonInIdentifiers && *CurPtr == ':') { + StrVal.assign(StartChar-1, CurPtr++); + return lltok::LabelStr; + } + + // Otherwise, this wasn't a label. If this was valid as an integer type, + // return it. + if (!IntEnd) IntEnd = CurPtr; + if (IntEnd != StartChar) { + CurPtr = IntEnd; + uint64_t NumBits = atoull(StartChar, CurPtr); + if (NumBits < IntegerType::MIN_INT_BITS || + NumBits > IntegerType::MAX_INT_BITS) { + Error("bitwidth for integer type out of range!"); + return lltok::Error; + } + TyVal = IntegerType::get(Context, NumBits); + return lltok::Type; + } + + // Otherwise, this was a letter sequence. See which keyword this is. + if (!KeywordEnd) KeywordEnd = CurPtr; + CurPtr = KeywordEnd; + --StartChar; + StringRef Keyword(StartChar, CurPtr - StartChar); + +#define KEYWORD(STR) \ + do { \ + if (Keyword == #STR) \ + return lltok::kw_##STR; \ + } while (false) + + KEYWORD(true); KEYWORD(false); + KEYWORD(declare); KEYWORD(define); + KEYWORD(global); KEYWORD(constant); + + KEYWORD(dso_local); + KEYWORD(dso_preemptable); + + KEYWORD(private); + KEYWORD(internal); + KEYWORD(available_externally); + KEYWORD(linkonce); + KEYWORD(linkonce_odr); + KEYWORD(weak); // Use as a linkage, and a modifier for "cmpxchg". + KEYWORD(weak_odr); + KEYWORD(appending); + KEYWORD(dllimport); + KEYWORD(dllexport); + KEYWORD(common); + KEYWORD(default); + KEYWORD(hidden); + KEYWORD(protected); + KEYWORD(unnamed_addr); + KEYWORD(local_unnamed_addr); + KEYWORD(externally_initialized); + KEYWORD(extern_weak); + KEYWORD(external); + KEYWORD(thread_local); + KEYWORD(localdynamic); + KEYWORD(initialexec); + KEYWORD(localexec); + KEYWORD(zeroinitializer); + KEYWORD(undef); + KEYWORD(null); + KEYWORD(none); KEYWORD(poison); - KEYWORD(to); - KEYWORD(caller); - KEYWORD(within); - KEYWORD(from); - KEYWORD(tail); - KEYWORD(musttail); - KEYWORD(notail); - KEYWORD(target); - KEYWORD(triple); - KEYWORD(source_filename); - KEYWORD(unwind); - KEYWORD(deplibs); // FIXME: Remove in 4.0. - KEYWORD(datalayout); - KEYWORD(volatile); - KEYWORD(atomic); - KEYWORD(unordered); - KEYWORD(monotonic); - KEYWORD(acquire); - KEYWORD(release); - KEYWORD(acq_rel); - KEYWORD(seq_cst); - KEYWORD(syncscope); - - KEYWORD(nnan); - KEYWORD(ninf); - KEYWORD(nsz); - KEYWORD(arcp); - KEYWORD(contract); - KEYWORD(reassoc); - KEYWORD(afn); - KEYWORD(fast); - KEYWORD(nuw); - KEYWORD(nsw); - KEYWORD(exact); - KEYWORD(inbounds); - KEYWORD(inrange); - KEYWORD(align); - KEYWORD(addrspace); - KEYWORD(section); - KEYWORD(partition); - KEYWORD(alias); - KEYWORD(ifunc); - KEYWORD(module); - KEYWORD(asm); - KEYWORD(sideeffect); - KEYWORD(alignstack); - KEYWORD(inteldialect); - KEYWORD(gc); - KEYWORD(prefix); - KEYWORD(prologue); - - KEYWORD(ccc); - KEYWORD(fastcc); - KEYWORD(coldcc); - KEYWORD(cfguard_checkcc); - KEYWORD(x86_stdcallcc); - KEYWORD(x86_fastcallcc); - KEYWORD(x86_thiscallcc); - KEYWORD(x86_vectorcallcc); - KEYWORD(arm_apcscc); - KEYWORD(arm_aapcscc); - KEYWORD(arm_aapcs_vfpcc); - KEYWORD(aarch64_vector_pcs); - KEYWORD(aarch64_sve_vector_pcs); - KEYWORD(msp430_intrcc); - KEYWORD(avr_intrcc); - KEYWORD(avr_signalcc); - KEYWORD(ptx_kernel); - KEYWORD(ptx_device); - KEYWORD(spir_kernel); - KEYWORD(spir_func); - KEYWORD(intel_ocl_bicc); - KEYWORD(x86_64_sysvcc); - KEYWORD(win64cc); - KEYWORD(x86_regcallcc); - KEYWORD(webkit_jscc); - KEYWORD(swiftcc); - KEYWORD(anyregcc); - KEYWORD(preserve_mostcc); - KEYWORD(preserve_allcc); - KEYWORD(ghccc); - KEYWORD(x86_intrcc); - KEYWORD(hhvmcc); - KEYWORD(hhvm_ccc); - KEYWORD(cxx_fast_tlscc); - KEYWORD(amdgpu_vs); - KEYWORD(amdgpu_ls); - KEYWORD(amdgpu_hs); - KEYWORD(amdgpu_es); - KEYWORD(amdgpu_gs); - KEYWORD(amdgpu_ps); - KEYWORD(amdgpu_cs); - KEYWORD(amdgpu_kernel); + KEYWORD(to); + KEYWORD(caller); + KEYWORD(within); + KEYWORD(from); + KEYWORD(tail); + KEYWORD(musttail); + KEYWORD(notail); + KEYWORD(target); + KEYWORD(triple); + KEYWORD(source_filename); + KEYWORD(unwind); + KEYWORD(deplibs); // FIXME: Remove in 4.0. + KEYWORD(datalayout); + KEYWORD(volatile); + KEYWORD(atomic); + KEYWORD(unordered); + KEYWORD(monotonic); + KEYWORD(acquire); + KEYWORD(release); + KEYWORD(acq_rel); + KEYWORD(seq_cst); + KEYWORD(syncscope); + + KEYWORD(nnan); + KEYWORD(ninf); + KEYWORD(nsz); + KEYWORD(arcp); + KEYWORD(contract); + KEYWORD(reassoc); + KEYWORD(afn); + KEYWORD(fast); + KEYWORD(nuw); + KEYWORD(nsw); + KEYWORD(exact); + KEYWORD(inbounds); + KEYWORD(inrange); + KEYWORD(align); + KEYWORD(addrspace); + KEYWORD(section); + KEYWORD(partition); + KEYWORD(alias); + KEYWORD(ifunc); + KEYWORD(module); + KEYWORD(asm); + KEYWORD(sideeffect); + KEYWORD(alignstack); + KEYWORD(inteldialect); + KEYWORD(gc); + KEYWORD(prefix); + KEYWORD(prologue); + + KEYWORD(ccc); + KEYWORD(fastcc); + KEYWORD(coldcc); + KEYWORD(cfguard_checkcc); + KEYWORD(x86_stdcallcc); + KEYWORD(x86_fastcallcc); + KEYWORD(x86_thiscallcc); + KEYWORD(x86_vectorcallcc); + KEYWORD(arm_apcscc); + KEYWORD(arm_aapcscc); + KEYWORD(arm_aapcs_vfpcc); + KEYWORD(aarch64_vector_pcs); + KEYWORD(aarch64_sve_vector_pcs); + KEYWORD(msp430_intrcc); + KEYWORD(avr_intrcc); + KEYWORD(avr_signalcc); + KEYWORD(ptx_kernel); + KEYWORD(ptx_device); + KEYWORD(spir_kernel); + KEYWORD(spir_func); + KEYWORD(intel_ocl_bicc); + KEYWORD(x86_64_sysvcc); + KEYWORD(win64cc); + KEYWORD(x86_regcallcc); + KEYWORD(webkit_jscc); + KEYWORD(swiftcc); + KEYWORD(anyregcc); + KEYWORD(preserve_mostcc); + KEYWORD(preserve_allcc); + KEYWORD(ghccc); + KEYWORD(x86_intrcc); + KEYWORD(hhvmcc); + KEYWORD(hhvm_ccc); + KEYWORD(cxx_fast_tlscc); + KEYWORD(amdgpu_vs); + KEYWORD(amdgpu_ls); + KEYWORD(amdgpu_hs); + KEYWORD(amdgpu_es); + KEYWORD(amdgpu_gs); + KEYWORD(amdgpu_ps); + KEYWORD(amdgpu_cs); + KEYWORD(amdgpu_kernel); KEYWORD(amdgpu_gfx); - KEYWORD(tailcc); - - KEYWORD(cc); - KEYWORD(c); - - KEYWORD(attributes); - - KEYWORD(alwaysinline); - KEYWORD(allocsize); - KEYWORD(argmemonly); - KEYWORD(builtin); - KEYWORD(byval); - KEYWORD(inalloca); - KEYWORD(cold); - KEYWORD(convergent); - KEYWORD(dereferenceable); - KEYWORD(dereferenceable_or_null); - KEYWORD(inaccessiblememonly); - KEYWORD(inaccessiblemem_or_argmemonly); - KEYWORD(inlinehint); - KEYWORD(inreg); - KEYWORD(jumptable); - KEYWORD(minsize); - KEYWORD(naked); - KEYWORD(nest); - KEYWORD(noalias); - KEYWORD(nobuiltin); + KEYWORD(tailcc); + + KEYWORD(cc); + KEYWORD(c); + + KEYWORD(attributes); + + KEYWORD(alwaysinline); + KEYWORD(allocsize); + KEYWORD(argmemonly); + KEYWORD(builtin); + KEYWORD(byval); + KEYWORD(inalloca); + KEYWORD(cold); + KEYWORD(convergent); + KEYWORD(dereferenceable); + KEYWORD(dereferenceable_or_null); + KEYWORD(inaccessiblememonly); + KEYWORD(inaccessiblemem_or_argmemonly); + KEYWORD(inlinehint); + KEYWORD(inreg); + KEYWORD(jumptable); + KEYWORD(minsize); + KEYWORD(naked); + KEYWORD(nest); + KEYWORD(noalias); + KEYWORD(nobuiltin); KEYWORD(nocallback); - KEYWORD(nocapture); - KEYWORD(noduplicate); - KEYWORD(nofree); - KEYWORD(noimplicitfloat); - KEYWORD(noinline); - KEYWORD(norecurse); - KEYWORD(nonlazybind); - KEYWORD(nomerge); - KEYWORD(nonnull); + KEYWORD(nocapture); + KEYWORD(noduplicate); + KEYWORD(nofree); + KEYWORD(noimplicitfloat); + KEYWORD(noinline); + KEYWORD(norecurse); + KEYWORD(nonlazybind); + KEYWORD(nomerge); + KEYWORD(nonnull); KEYWORD(noprofile); - KEYWORD(noredzone); - KEYWORD(noreturn); - KEYWORD(nosync); - KEYWORD(nocf_check); - KEYWORD(noundef); - KEYWORD(nounwind); - KEYWORD(null_pointer_is_valid); - KEYWORD(optforfuzzing); - KEYWORD(optnone); - KEYWORD(optsize); - KEYWORD(preallocated); - KEYWORD(readnone); - KEYWORD(readonly); - KEYWORD(returned); - KEYWORD(returns_twice); - KEYWORD(signext); - KEYWORD(speculatable); - KEYWORD(sret); - KEYWORD(ssp); - KEYWORD(sspreq); - KEYWORD(sspstrong); - KEYWORD(strictfp); - KEYWORD(safestack); - KEYWORD(shadowcallstack); - KEYWORD(sanitize_address); - KEYWORD(sanitize_hwaddress); - KEYWORD(sanitize_memtag); - KEYWORD(sanitize_thread); - KEYWORD(sanitize_memory); - KEYWORD(speculative_load_hardening); - KEYWORD(swifterror); - KEYWORD(swiftself); - KEYWORD(uwtable); - KEYWORD(willreturn); - KEYWORD(writeonly); - KEYWORD(zeroext); - KEYWORD(immarg); + KEYWORD(noredzone); + KEYWORD(noreturn); + KEYWORD(nosync); + KEYWORD(nocf_check); + KEYWORD(noundef); + KEYWORD(nounwind); + KEYWORD(null_pointer_is_valid); + KEYWORD(optforfuzzing); + KEYWORD(optnone); + KEYWORD(optsize); + KEYWORD(preallocated); + KEYWORD(readnone); + KEYWORD(readonly); + KEYWORD(returned); + KEYWORD(returns_twice); + KEYWORD(signext); + KEYWORD(speculatable); + KEYWORD(sret); + KEYWORD(ssp); + KEYWORD(sspreq); + KEYWORD(sspstrong); + KEYWORD(strictfp); + KEYWORD(safestack); + KEYWORD(shadowcallstack); + KEYWORD(sanitize_address); + KEYWORD(sanitize_hwaddress); + KEYWORD(sanitize_memtag); + KEYWORD(sanitize_thread); + KEYWORD(sanitize_memory); + KEYWORD(speculative_load_hardening); + KEYWORD(swifterror); + KEYWORD(swiftself); + KEYWORD(uwtable); + KEYWORD(willreturn); + KEYWORD(writeonly); + KEYWORD(zeroext); + KEYWORD(immarg); KEYWORD(byref); KEYWORD(mustprogress); - - KEYWORD(type); - KEYWORD(opaque); - - KEYWORD(comdat); - - // Comdat types - KEYWORD(any); - KEYWORD(exactmatch); - KEYWORD(largest); - KEYWORD(noduplicates); - KEYWORD(samesize); - - 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); - - KEYWORD(xchg); KEYWORD(nand); KEYWORD(max); KEYWORD(min); KEYWORD(umax); - KEYWORD(umin); - - KEYWORD(vscale); - KEYWORD(x); - KEYWORD(blockaddress); + + KEYWORD(type); + KEYWORD(opaque); + + KEYWORD(comdat); + + // Comdat types + KEYWORD(any); + KEYWORD(exactmatch); + KEYWORD(largest); + KEYWORD(noduplicates); + KEYWORD(samesize); + + 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); + + KEYWORD(xchg); KEYWORD(nand); KEYWORD(max); KEYWORD(min); KEYWORD(umax); + KEYWORD(umin); + + KEYWORD(vscale); + KEYWORD(x); + KEYWORD(blockaddress); KEYWORD(dso_local_equivalent); - - // Metadata types. - KEYWORD(distinct); - - // Use-list order directives. - KEYWORD(uselistorder); - KEYWORD(uselistorder_bb); - - KEYWORD(personality); - KEYWORD(cleanup); - KEYWORD(catch); - KEYWORD(filter); - - // Summary index keywords. - KEYWORD(path); - KEYWORD(hash); - KEYWORD(gv); - KEYWORD(guid); - KEYWORD(name); - KEYWORD(summaries); - KEYWORD(flags); - KEYWORD(blockcount); - KEYWORD(linkage); - KEYWORD(notEligibleToImport); - KEYWORD(live); - KEYWORD(dsoLocal); - KEYWORD(canAutoHide); - KEYWORD(function); - KEYWORD(insts); - KEYWORD(funcFlags); - KEYWORD(readNone); - KEYWORD(readOnly); - KEYWORD(noRecurse); - KEYWORD(returnDoesNotAlias); - KEYWORD(noInline); - KEYWORD(alwaysInline); - KEYWORD(calls); - KEYWORD(callee); - KEYWORD(params); - KEYWORD(param); - KEYWORD(hotness); - KEYWORD(unknown); - KEYWORD(hot); - KEYWORD(critical); - KEYWORD(relbf); - KEYWORD(variable); - KEYWORD(vTableFuncs); - KEYWORD(virtFunc); - KEYWORD(aliasee); - KEYWORD(refs); - KEYWORD(typeIdInfo); - KEYWORD(typeTests); - KEYWORD(typeTestAssumeVCalls); - KEYWORD(typeCheckedLoadVCalls); - KEYWORD(typeTestAssumeConstVCalls); - KEYWORD(typeCheckedLoadConstVCalls); - KEYWORD(vFuncId); - KEYWORD(offset); - KEYWORD(args); - KEYWORD(typeid); - KEYWORD(typeidCompatibleVTable); - KEYWORD(summary); - KEYWORD(typeTestRes); - KEYWORD(kind); - KEYWORD(unsat); - KEYWORD(byteArray); - KEYWORD(inline); - KEYWORD(single); - KEYWORD(allOnes); - KEYWORD(sizeM1BitWidth); - KEYWORD(alignLog2); - KEYWORD(sizeM1); - KEYWORD(bitMask); - KEYWORD(inlineBits); - KEYWORD(vcall_visibility); - KEYWORD(wpdResolutions); - KEYWORD(wpdRes); - KEYWORD(indir); - KEYWORD(singleImpl); - KEYWORD(branchFunnel); - KEYWORD(singleImplName); - KEYWORD(resByArg); - KEYWORD(byArg); - KEYWORD(uniformRetVal); - KEYWORD(uniqueRetVal); - KEYWORD(virtualConstProp); - KEYWORD(info); - KEYWORD(byte); - KEYWORD(bit); - KEYWORD(varFlags); - -#undef KEYWORD - - // Keywords for types. -#define TYPEKEYWORD(STR, LLVMTY) \ - do { \ - if (Keyword == STR) { \ - TyVal = LLVMTY; \ - return lltok::Type; \ - } \ - } while (false) - - TYPEKEYWORD("void", Type::getVoidTy(Context)); - TYPEKEYWORD("half", Type::getHalfTy(Context)); - TYPEKEYWORD("bfloat", Type::getBFloatTy(Context)); - 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)); - TYPEKEYWORD("x86_mmx", Type::getX86_MMXTy(Context)); + + // Metadata types. + KEYWORD(distinct); + + // Use-list order directives. + KEYWORD(uselistorder); + KEYWORD(uselistorder_bb); + + KEYWORD(personality); + KEYWORD(cleanup); + KEYWORD(catch); + KEYWORD(filter); + + // Summary index keywords. + KEYWORD(path); + KEYWORD(hash); + KEYWORD(gv); + KEYWORD(guid); + KEYWORD(name); + KEYWORD(summaries); + KEYWORD(flags); + KEYWORD(blockcount); + KEYWORD(linkage); + KEYWORD(notEligibleToImport); + KEYWORD(live); + KEYWORD(dsoLocal); + KEYWORD(canAutoHide); + KEYWORD(function); + KEYWORD(insts); + KEYWORD(funcFlags); + KEYWORD(readNone); + KEYWORD(readOnly); + KEYWORD(noRecurse); + KEYWORD(returnDoesNotAlias); + KEYWORD(noInline); + KEYWORD(alwaysInline); + KEYWORD(calls); + KEYWORD(callee); + KEYWORD(params); + KEYWORD(param); + KEYWORD(hotness); + KEYWORD(unknown); + KEYWORD(hot); + KEYWORD(critical); + KEYWORD(relbf); + KEYWORD(variable); + KEYWORD(vTableFuncs); + KEYWORD(virtFunc); + KEYWORD(aliasee); + KEYWORD(refs); + KEYWORD(typeIdInfo); + KEYWORD(typeTests); + KEYWORD(typeTestAssumeVCalls); + KEYWORD(typeCheckedLoadVCalls); + KEYWORD(typeTestAssumeConstVCalls); + KEYWORD(typeCheckedLoadConstVCalls); + KEYWORD(vFuncId); + KEYWORD(offset); + KEYWORD(args); + KEYWORD(typeid); + KEYWORD(typeidCompatibleVTable); + KEYWORD(summary); + KEYWORD(typeTestRes); + KEYWORD(kind); + KEYWORD(unsat); + KEYWORD(byteArray); + KEYWORD(inline); + KEYWORD(single); + KEYWORD(allOnes); + KEYWORD(sizeM1BitWidth); + KEYWORD(alignLog2); + KEYWORD(sizeM1); + KEYWORD(bitMask); + KEYWORD(inlineBits); + KEYWORD(vcall_visibility); + KEYWORD(wpdResolutions); + KEYWORD(wpdRes); + KEYWORD(indir); + KEYWORD(singleImpl); + KEYWORD(branchFunnel); + KEYWORD(singleImplName); + KEYWORD(resByArg); + KEYWORD(byArg); + KEYWORD(uniformRetVal); + KEYWORD(uniqueRetVal); + KEYWORD(virtualConstProp); + KEYWORD(info); + KEYWORD(byte); + KEYWORD(bit); + KEYWORD(varFlags); + +#undef KEYWORD + + // Keywords for types. +#define TYPEKEYWORD(STR, LLVMTY) \ + do { \ + if (Keyword == STR) { \ + TyVal = LLVMTY; \ + return lltok::Type; \ + } \ + } while (false) + + TYPEKEYWORD("void", Type::getVoidTy(Context)); + TYPEKEYWORD("half", Type::getHalfTy(Context)); + TYPEKEYWORD("bfloat", Type::getBFloatTy(Context)); + 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)); + TYPEKEYWORD("x86_mmx", Type::getX86_MMXTy(Context)); TYPEKEYWORD("x86_amx", Type::getX86_AMXTy(Context)); - TYPEKEYWORD("token", Type::getTokenTy(Context)); - -#undef TYPEKEYWORD - - // Keywords for instructions. -#define INSTKEYWORD(STR, Enum) \ - do { \ - if (Keyword == #STR) { \ - UIntVal = Instruction::Enum; \ - return lltok::kw_##STR; \ - } \ - } while (false) - - INSTKEYWORD(fneg, FNeg); - - INSTKEYWORD(add, Add); INSTKEYWORD(fadd, FAdd); - INSTKEYWORD(sub, Sub); INSTKEYWORD(fsub, FSub); - INSTKEYWORD(mul, Mul); INSTKEYWORD(fmul, FMul); - 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); - INSTKEYWORD(addrspacecast, AddrSpaceCast); - INSTKEYWORD(select, Select); - INSTKEYWORD(va_arg, VAArg); - INSTKEYWORD(ret, Ret); - INSTKEYWORD(br, Br); - INSTKEYWORD(switch, Switch); - INSTKEYWORD(indirectbr, IndirectBr); - INSTKEYWORD(invoke, Invoke); - INSTKEYWORD(resume, Resume); - INSTKEYWORD(unreachable, Unreachable); - INSTKEYWORD(callbr, CallBr); - - INSTKEYWORD(alloca, Alloca); - INSTKEYWORD(load, Load); - INSTKEYWORD(store, Store); - INSTKEYWORD(cmpxchg, AtomicCmpXchg); - INSTKEYWORD(atomicrmw, AtomicRMW); - INSTKEYWORD(fence, Fence); - INSTKEYWORD(getelementptr, GetElementPtr); - - INSTKEYWORD(extractelement, ExtractElement); - INSTKEYWORD(insertelement, InsertElement); - INSTKEYWORD(shufflevector, ShuffleVector); - INSTKEYWORD(extractvalue, ExtractValue); - INSTKEYWORD(insertvalue, InsertValue); - INSTKEYWORD(landingpad, LandingPad); - INSTKEYWORD(cleanupret, CleanupRet); - INSTKEYWORD(catchret, CatchRet); - INSTKEYWORD(catchswitch, CatchSwitch); - INSTKEYWORD(catchpad, CatchPad); - INSTKEYWORD(cleanuppad, CleanupPad); - - INSTKEYWORD(freeze, Freeze); - -#undef INSTKEYWORD - -#define DWKEYWORD(TYPE, TOKEN) \ - do { \ - if (Keyword.startswith("DW_" #TYPE "_")) { \ - StrVal.assign(Keyword.begin(), Keyword.end()); \ - return lltok::TOKEN; \ - } \ - } while (false) - - DWKEYWORD(TAG, DwarfTag); - DWKEYWORD(ATE, DwarfAttEncoding); - DWKEYWORD(VIRTUALITY, DwarfVirtuality); - DWKEYWORD(LANG, DwarfLang); - DWKEYWORD(CC, DwarfCC); - DWKEYWORD(OP, DwarfOp); - DWKEYWORD(MACINFO, DwarfMacinfo); - -#undef DWKEYWORD - - if (Keyword.startswith("DIFlag")) { - StrVal.assign(Keyword.begin(), Keyword.end()); - return lltok::DIFlag; - } - - if (Keyword.startswith("DISPFlag")) { - StrVal.assign(Keyword.begin(), Keyword.end()); - return lltok::DISPFlag; - } - - if (Keyword.startswith("CSK_")) { - StrVal.assign(Keyword.begin(), Keyword.end()); - return lltok::ChecksumKind; - } - - if (Keyword == "NoDebug" || Keyword == "FullDebug" || - Keyword == "LineTablesOnly" || Keyword == "DebugDirectivesOnly") { - StrVal.assign(Keyword.begin(), Keyword.end()); - return lltok::EmissionKind; - } - - if (Keyword == "GNU" || Keyword == "None" || Keyword == "Default") { - StrVal.assign(Keyword.begin(), Keyword.end()); - return lltok::NameTableKind; - } - - // 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') && - TokStart[1] == '0' && TokStart[2] == 'x' && - isxdigit(static_cast<unsigned char>(TokStart[3]))) { - int len = CurPtr-TokStart-3; - uint32_t bits = len * 4; - StringRef HexStr(TokStart + 3, len); - if (!all_of(HexStr, isxdigit)) { - // Bad token, return it as an error. - CurPtr = TokStart+3; - return lltok::Error; - } - APInt Tmp(bits, HexStr, 16); - uint32_t activeBits = Tmp.getActiveBits(); - if (activeBits > 0 && activeBits < bits) - Tmp = Tmp.trunc(activeBits); - APSIntVal = APSInt(Tmp, TokStart[0] == 'u'); - return lltok::APSInt; - } - - // If this is "cc1234", return this as just "cc". - if (TokStart[0] == 'c' && TokStart[1] == 'c') { - CurPtr = TokStart+2; - return lltok::kw_cc; - } - - // Finally, if this isn't known, return an error. - CurPtr = TokStart+1; - return lltok::Error; -} - -/// Lex all tokens that start with a 0x prefix, knowing they match and are not -/// labels. -/// HexFPConstant 0x[0-9A-Fa-f]+ -/// HexFP80Constant 0xK[0-9A-Fa-f]+ -/// HexFP128Constant 0xL[0-9A-Fa-f]+ -/// HexPPC128Constant 0xM[0-9A-Fa-f]+ -/// HexHalfConstant 0xH[0-9A-Fa-f]+ -/// HexBFloatConstant 0xR[0-9A-Fa-f]+ -lltok::Kind LLLexer::Lex0x() { - CurPtr = TokStart + 2; - - char Kind; - if ((CurPtr[0] >= 'K' && CurPtr[0] <= 'M') || CurPtr[0] == 'H' || - CurPtr[0] == 'R') { - Kind = *CurPtr++; - } else { - Kind = 'J'; - } - - if (!isxdigit(static_cast<unsigned char>(CurPtr[0]))) { - // Bad token, return it as an error. - CurPtr = TokStart+1; - return lltok::Error; - } - - while (isxdigit(static_cast<unsigned char>(CurPtr[0]))) - ++CurPtr; - - if (Kind == 'J') { - // HexFPConstant - Floating point constant represented in IEEE format as a - // hexadecimal number for when exponential notation is not precise enough. - // Half, BFloat, Float, and double only. - APFloatVal = APFloat(APFloat::IEEEdouble(), - APInt(64, HexIntToVal(TokStart + 2, CurPtr))); - return lltok::APFloat; - } - - uint64_t Pair[2]; - switch (Kind) { - default: llvm_unreachable("Unknown kind!"); - case 'K': - // F80HexFPConstant - x87 long double in hexadecimal format (10 bytes) - FP80HexToIntPair(TokStart+3, CurPtr, Pair); - APFloatVal = APFloat(APFloat::x87DoubleExtended(), APInt(80, Pair)); - return lltok::APFloat; - case 'L': - // F128HexFPConstant - IEEE 128-bit in hexadecimal format (16 bytes) - HexToIntPair(TokStart+3, CurPtr, Pair); - APFloatVal = APFloat(APFloat::IEEEquad(), APInt(128, Pair)); - return lltok::APFloat; - case 'M': - // PPC128HexFPConstant - PowerPC 128-bit in hexadecimal format (16 bytes) - HexToIntPair(TokStart+3, CurPtr, Pair); - APFloatVal = APFloat(APFloat::PPCDoubleDouble(), APInt(128, Pair)); - return lltok::APFloat; - case 'H': - APFloatVal = APFloat(APFloat::IEEEhalf(), - APInt(16,HexIntToVal(TokStart+3, CurPtr))); - return lltok::APFloat; - case 'R': - // Brain floating point - APFloatVal = APFloat(APFloat::BFloat(), - APInt(16, HexIntToVal(TokStart + 3, CurPtr))); - return lltok::APFloat; - } -} - -/// Lex tokens for a label or a numeric constant, possibly starting with -. -/// 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]+ -lltok::Kind LLLexer::LexDigitOrNegative() { - // If the letter after the negative is not a number, this is probably a label. - if (!isdigit(static_cast<unsigned char>(TokStart[0])) && - !isdigit(static_cast<unsigned char>(CurPtr[0]))) { - // Okay, this is not a number after the -, it's probably a label. - if (const char *End = isLabelTail(CurPtr)) { - StrVal.assign(TokStart, End-1); - CurPtr = End; - return lltok::LabelStr; - } - - return lltok::Error; - } - - // At this point, it is either a label, int or fp constant. - - // Skip digits, we have at least one. - for (; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr) - /*empty*/; - - // Check if this is a fully-numeric label: - if (isdigit(TokStart[0]) && CurPtr[0] == ':') { - uint64_t Val = atoull(TokStart, CurPtr); - ++CurPtr; // Skip the colon. - if ((unsigned)Val != Val) - Error("invalid value number (too large)!"); - UIntVal = unsigned(Val); - return lltok::LabelID; - } - - // Check to see if this really is a string label, e.g. "-1:". - if (isLabelChar(CurPtr[0]) || CurPtr[0] == ':') { - if (const char *End = isLabelTail(CurPtr)) { - StrVal.assign(TokStart, End-1); - CurPtr = End; - return lltok::LabelStr; - } - } - - // 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(); - APSIntVal = APSInt(StringRef(TokStart, CurPtr - TokStart)); - return lltok::APSInt; - } - - ++CurPtr; - - // Skip over [0-9]*([eE][-+]?[0-9]+)? - while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr; - - if (CurPtr[0] == 'e' || CurPtr[0] == 'E') { - if (isdigit(static_cast<unsigned char>(CurPtr[1])) || - ((CurPtr[1] == '-' || CurPtr[1] == '+') && - isdigit(static_cast<unsigned char>(CurPtr[2])))) { - CurPtr += 2; - while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr; - } - } - - APFloatVal = APFloat(APFloat::IEEEdouble(), - StringRef(TokStart, CurPtr - TokStart)); - return lltok::APFloat; -} - -/// Lex a floating point constant starting with +. -/// FPConstant [-+]?[0-9]+[.][0-9]*([eE][-+]?[0-9]+)? -lltok::Kind LLLexer::LexPositive() { - // If the letter after the negative is a number, this is probably not a - // label. - if (!isdigit(static_cast<unsigned char>(CurPtr[0]))) - return lltok::Error; - - // Skip digits. - for (++CurPtr; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr) - /*empty*/; - - // At this point, we need a '.'. - if (CurPtr[0] != '.') { - CurPtr = TokStart+1; - return lltok::Error; - } - - ++CurPtr; - - // Skip over [0-9]*([eE][-+]?[0-9]+)? - while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr; - - if (CurPtr[0] == 'e' || CurPtr[0] == 'E') { - if (isdigit(static_cast<unsigned char>(CurPtr[1])) || - ((CurPtr[1] == '-' || CurPtr[1] == '+') && - isdigit(static_cast<unsigned char>(CurPtr[2])))) { - CurPtr += 2; - while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr; - } - } - - APFloatVal = APFloat(APFloat::IEEEdouble(), - StringRef(TokStart, CurPtr - TokStart)); - return lltok::APFloat; -} + TYPEKEYWORD("token", Type::getTokenTy(Context)); + +#undef TYPEKEYWORD + + // Keywords for instructions. +#define INSTKEYWORD(STR, Enum) \ + do { \ + if (Keyword == #STR) { \ + UIntVal = Instruction::Enum; \ + return lltok::kw_##STR; \ + } \ + } while (false) + + INSTKEYWORD(fneg, FNeg); + + INSTKEYWORD(add, Add); INSTKEYWORD(fadd, FAdd); + INSTKEYWORD(sub, Sub); INSTKEYWORD(fsub, FSub); + INSTKEYWORD(mul, Mul); INSTKEYWORD(fmul, FMul); + 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); + INSTKEYWORD(addrspacecast, AddrSpaceCast); + INSTKEYWORD(select, Select); + INSTKEYWORD(va_arg, VAArg); + INSTKEYWORD(ret, Ret); + INSTKEYWORD(br, Br); + INSTKEYWORD(switch, Switch); + INSTKEYWORD(indirectbr, IndirectBr); + INSTKEYWORD(invoke, Invoke); + INSTKEYWORD(resume, Resume); + INSTKEYWORD(unreachable, Unreachable); + INSTKEYWORD(callbr, CallBr); + + INSTKEYWORD(alloca, Alloca); + INSTKEYWORD(load, Load); + INSTKEYWORD(store, Store); + INSTKEYWORD(cmpxchg, AtomicCmpXchg); + INSTKEYWORD(atomicrmw, AtomicRMW); + INSTKEYWORD(fence, Fence); + INSTKEYWORD(getelementptr, GetElementPtr); + + INSTKEYWORD(extractelement, ExtractElement); + INSTKEYWORD(insertelement, InsertElement); + INSTKEYWORD(shufflevector, ShuffleVector); + INSTKEYWORD(extractvalue, ExtractValue); + INSTKEYWORD(insertvalue, InsertValue); + INSTKEYWORD(landingpad, LandingPad); + INSTKEYWORD(cleanupret, CleanupRet); + INSTKEYWORD(catchret, CatchRet); + INSTKEYWORD(catchswitch, CatchSwitch); + INSTKEYWORD(catchpad, CatchPad); + INSTKEYWORD(cleanuppad, CleanupPad); + + INSTKEYWORD(freeze, Freeze); + +#undef INSTKEYWORD + +#define DWKEYWORD(TYPE, TOKEN) \ + do { \ + if (Keyword.startswith("DW_" #TYPE "_")) { \ + StrVal.assign(Keyword.begin(), Keyword.end()); \ + return lltok::TOKEN; \ + } \ + } while (false) + + DWKEYWORD(TAG, DwarfTag); + DWKEYWORD(ATE, DwarfAttEncoding); + DWKEYWORD(VIRTUALITY, DwarfVirtuality); + DWKEYWORD(LANG, DwarfLang); + DWKEYWORD(CC, DwarfCC); + DWKEYWORD(OP, DwarfOp); + DWKEYWORD(MACINFO, DwarfMacinfo); + +#undef DWKEYWORD + + if (Keyword.startswith("DIFlag")) { + StrVal.assign(Keyword.begin(), Keyword.end()); + return lltok::DIFlag; + } + + if (Keyword.startswith("DISPFlag")) { + StrVal.assign(Keyword.begin(), Keyword.end()); + return lltok::DISPFlag; + } + + if (Keyword.startswith("CSK_")) { + StrVal.assign(Keyword.begin(), Keyword.end()); + return lltok::ChecksumKind; + } + + if (Keyword == "NoDebug" || Keyword == "FullDebug" || + Keyword == "LineTablesOnly" || Keyword == "DebugDirectivesOnly") { + StrVal.assign(Keyword.begin(), Keyword.end()); + return lltok::EmissionKind; + } + + if (Keyword == "GNU" || Keyword == "None" || Keyword == "Default") { + StrVal.assign(Keyword.begin(), Keyword.end()); + return lltok::NameTableKind; + } + + // 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') && + TokStart[1] == '0' && TokStart[2] == 'x' && + isxdigit(static_cast<unsigned char>(TokStart[3]))) { + int len = CurPtr-TokStart-3; + uint32_t bits = len * 4; + StringRef HexStr(TokStart + 3, len); + if (!all_of(HexStr, isxdigit)) { + // Bad token, return it as an error. + CurPtr = TokStart+3; + return lltok::Error; + } + APInt Tmp(bits, HexStr, 16); + uint32_t activeBits = Tmp.getActiveBits(); + if (activeBits > 0 && activeBits < bits) + Tmp = Tmp.trunc(activeBits); + APSIntVal = APSInt(Tmp, TokStart[0] == 'u'); + return lltok::APSInt; + } + + // If this is "cc1234", return this as just "cc". + if (TokStart[0] == 'c' && TokStart[1] == 'c') { + CurPtr = TokStart+2; + return lltok::kw_cc; + } + + // Finally, if this isn't known, return an error. + CurPtr = TokStart+1; + return lltok::Error; +} + +/// Lex all tokens that start with a 0x prefix, knowing they match and are not +/// labels. +/// HexFPConstant 0x[0-9A-Fa-f]+ +/// HexFP80Constant 0xK[0-9A-Fa-f]+ +/// HexFP128Constant 0xL[0-9A-Fa-f]+ +/// HexPPC128Constant 0xM[0-9A-Fa-f]+ +/// HexHalfConstant 0xH[0-9A-Fa-f]+ +/// HexBFloatConstant 0xR[0-9A-Fa-f]+ +lltok::Kind LLLexer::Lex0x() { + CurPtr = TokStart + 2; + + char Kind; + if ((CurPtr[0] >= 'K' && CurPtr[0] <= 'M') || CurPtr[0] == 'H' || + CurPtr[0] == 'R') { + Kind = *CurPtr++; + } else { + Kind = 'J'; + } + + if (!isxdigit(static_cast<unsigned char>(CurPtr[0]))) { + // Bad token, return it as an error. + CurPtr = TokStart+1; + return lltok::Error; + } + + while (isxdigit(static_cast<unsigned char>(CurPtr[0]))) + ++CurPtr; + + if (Kind == 'J') { + // HexFPConstant - Floating point constant represented in IEEE format as a + // hexadecimal number for when exponential notation is not precise enough. + // Half, BFloat, Float, and double only. + APFloatVal = APFloat(APFloat::IEEEdouble(), + APInt(64, HexIntToVal(TokStart + 2, CurPtr))); + return lltok::APFloat; + } + + uint64_t Pair[2]; + switch (Kind) { + default: llvm_unreachable("Unknown kind!"); + case 'K': + // F80HexFPConstant - x87 long double in hexadecimal format (10 bytes) + FP80HexToIntPair(TokStart+3, CurPtr, Pair); + APFloatVal = APFloat(APFloat::x87DoubleExtended(), APInt(80, Pair)); + return lltok::APFloat; + case 'L': + // F128HexFPConstant - IEEE 128-bit in hexadecimal format (16 bytes) + HexToIntPair(TokStart+3, CurPtr, Pair); + APFloatVal = APFloat(APFloat::IEEEquad(), APInt(128, Pair)); + return lltok::APFloat; + case 'M': + // PPC128HexFPConstant - PowerPC 128-bit in hexadecimal format (16 bytes) + HexToIntPair(TokStart+3, CurPtr, Pair); + APFloatVal = APFloat(APFloat::PPCDoubleDouble(), APInt(128, Pair)); + return lltok::APFloat; + case 'H': + APFloatVal = APFloat(APFloat::IEEEhalf(), + APInt(16,HexIntToVal(TokStart+3, CurPtr))); + return lltok::APFloat; + case 'R': + // Brain floating point + APFloatVal = APFloat(APFloat::BFloat(), + APInt(16, HexIntToVal(TokStart + 3, CurPtr))); + return lltok::APFloat; + } +} + +/// Lex tokens for a label or a numeric constant, possibly starting with -. +/// 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]+ +lltok::Kind LLLexer::LexDigitOrNegative() { + // If the letter after the negative is not a number, this is probably a label. + if (!isdigit(static_cast<unsigned char>(TokStart[0])) && + !isdigit(static_cast<unsigned char>(CurPtr[0]))) { + // Okay, this is not a number after the -, it's probably a label. + if (const char *End = isLabelTail(CurPtr)) { + StrVal.assign(TokStart, End-1); + CurPtr = End; + return lltok::LabelStr; + } + + return lltok::Error; + } + + // At this point, it is either a label, int or fp constant. + + // Skip digits, we have at least one. + for (; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr) + /*empty*/; + + // Check if this is a fully-numeric label: + if (isdigit(TokStart[0]) && CurPtr[0] == ':') { + uint64_t Val = atoull(TokStart, CurPtr); + ++CurPtr; // Skip the colon. + if ((unsigned)Val != Val) + Error("invalid value number (too large)!"); + UIntVal = unsigned(Val); + return lltok::LabelID; + } + + // Check to see if this really is a string label, e.g. "-1:". + if (isLabelChar(CurPtr[0]) || CurPtr[0] == ':') { + if (const char *End = isLabelTail(CurPtr)) { + StrVal.assign(TokStart, End-1); + CurPtr = End; + return lltok::LabelStr; + } + } + + // 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(); + APSIntVal = APSInt(StringRef(TokStart, CurPtr - TokStart)); + return lltok::APSInt; + } + + ++CurPtr; + + // Skip over [0-9]*([eE][-+]?[0-9]+)? + while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr; + + if (CurPtr[0] == 'e' || CurPtr[0] == 'E') { + if (isdigit(static_cast<unsigned char>(CurPtr[1])) || + ((CurPtr[1] == '-' || CurPtr[1] == '+') && + isdigit(static_cast<unsigned char>(CurPtr[2])))) { + CurPtr += 2; + while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr; + } + } + + APFloatVal = APFloat(APFloat::IEEEdouble(), + StringRef(TokStart, CurPtr - TokStart)); + return lltok::APFloat; +} + +/// Lex a floating point constant starting with +. +/// FPConstant [-+]?[0-9]+[.][0-9]*([eE][-+]?[0-9]+)? +lltok::Kind LLLexer::LexPositive() { + // If the letter after the negative is a number, this is probably not a + // label. + if (!isdigit(static_cast<unsigned char>(CurPtr[0]))) + return lltok::Error; + + // Skip digits. + for (++CurPtr; isdigit(static_cast<unsigned char>(CurPtr[0])); ++CurPtr) + /*empty*/; + + // At this point, we need a '.'. + if (CurPtr[0] != '.') { + CurPtr = TokStart+1; + return lltok::Error; + } + + ++CurPtr; + + // Skip over [0-9]*([eE][-+]?[0-9]+)? + while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr; + + if (CurPtr[0] == 'e' || CurPtr[0] == 'E') { + if (isdigit(static_cast<unsigned char>(CurPtr[1])) || + ((CurPtr[1] == '-' || CurPtr[1] == '+') && + isdigit(static_cast<unsigned char>(CurPtr[2])))) { + CurPtr += 2; + while (isdigit(static_cast<unsigned char>(CurPtr[0]))) ++CurPtr; + } + } + + APFloatVal = APFloat(APFloat::IEEEdouble(), + StringRef(TokStart, CurPtr - TokStart)); + return lltok::APFloat; +} diff --git a/contrib/libs/llvm12/lib/AsmParser/LLLexer.h b/contrib/libs/llvm12/lib/AsmParser/LLLexer.h index d7feb99fbb..c97d9781c3 100644 --- a/contrib/libs/llvm12/lib/AsmParser/LLLexer.h +++ b/contrib/libs/llvm12/lib/AsmParser/LLLexer.h @@ -1,104 +1,104 @@ -//===- LLLexer.h - Lexer for LLVM Assembly Files ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This class represents the Lexer for .ll files. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_ASMPARSER_LLLEXER_H -#define LLVM_LIB_ASMPARSER_LLLEXER_H - -#include "LLToken.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/APSInt.h" -#include "llvm/Support/SMLoc.h" -#include <string> - -namespace llvm { - class Type; - class SMDiagnostic; - class SourceMgr; - class LLVMContext; - - class LLLexer { - const char *CurPtr; - StringRef CurBuf; - SMDiagnostic &ErrorInfo; - SourceMgr &SM; - LLVMContext &Context; - - // Information about the current token. - const char *TokStart; - lltok::Kind CurKind; - std::string StrVal; - unsigned UIntVal; - Type *TyVal; - APFloat APFloatVal; - APSInt APSIntVal; - - // When false (default), an identifier ending in ':' is a label token. - // When true, the ':' is treated as a separate token. - bool IgnoreColonInIdentifiers; - - public: - explicit LLLexer(StringRef StartBuf, SourceMgr &SM, SMDiagnostic &, - LLVMContext &C); - - lltok::Kind Lex() { - return CurKind = LexToken(); - } - - typedef SMLoc LocTy; - LocTy getLoc() const { return SMLoc::getFromPointer(TokStart); } - lltok::Kind getKind() const { return CurKind; } - const std::string &getStrVal() const { return StrVal; } - Type *getTyVal() const { return TyVal; } - unsigned getUIntVal() const { return UIntVal; } - const APSInt &getAPSIntVal() const { return APSIntVal; } - const APFloat &getAPFloatVal() const { return APFloatVal; } - - void setIgnoreColonInIdentifiers(bool val) { - IgnoreColonInIdentifiers = val; - } - - bool Error(LocTy ErrorLoc, const Twine &Msg) const; - bool Error(const Twine &Msg) const { return Error(getLoc(), Msg); } - - void Warning(LocTy WarningLoc, const Twine &Msg) const; - void Warning(const Twine &Msg) const { return Warning(getLoc(), Msg); } - - private: - lltok::Kind LexToken(); - - int getNextChar(); - void SkipLineComment(); - lltok::Kind ReadString(lltok::Kind kind); - bool ReadVarName(); - - lltok::Kind LexIdentifier(); - lltok::Kind LexDigitOrNegative(); - lltok::Kind LexPositive(); - lltok::Kind LexAt(); - lltok::Kind LexDollar(); - lltok::Kind LexExclaim(); - lltok::Kind LexPercent(); - lltok::Kind LexUIntID(lltok::Kind Token); - lltok::Kind LexVar(lltok::Kind Var, lltok::Kind VarID); - lltok::Kind LexQuote(); - lltok::Kind Lex0x(); - lltok::Kind LexHash(); - lltok::Kind LexCaret(); - - uint64_t atoull(const char *Buffer, const char *End); - uint64_t HexIntToVal(const char *Buffer, const char *End); - void HexToIntPair(const char *Buffer, const char *End, uint64_t Pair[2]); - void FP80HexToIntPair(const char *Buffer, const char *End, uint64_t Pair[2]); - }; -} // end namespace llvm - -#endif +//===- LLLexer.h - Lexer for LLVM Assembly Files ----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This class represents the Lexer for .ll files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_ASMPARSER_LLLEXER_H +#define LLVM_LIB_ASMPARSER_LLLEXER_H + +#include "LLToken.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/Support/SMLoc.h" +#include <string> + +namespace llvm { + class Type; + class SMDiagnostic; + class SourceMgr; + class LLVMContext; + + class LLLexer { + const char *CurPtr; + StringRef CurBuf; + SMDiagnostic &ErrorInfo; + SourceMgr &SM; + LLVMContext &Context; + + // Information about the current token. + const char *TokStart; + lltok::Kind CurKind; + std::string StrVal; + unsigned UIntVal; + Type *TyVal; + APFloat APFloatVal; + APSInt APSIntVal; + + // When false (default), an identifier ending in ':' is a label token. + // When true, the ':' is treated as a separate token. + bool IgnoreColonInIdentifiers; + + public: + explicit LLLexer(StringRef StartBuf, SourceMgr &SM, SMDiagnostic &, + LLVMContext &C); + + lltok::Kind Lex() { + return CurKind = LexToken(); + } + + typedef SMLoc LocTy; + LocTy getLoc() const { return SMLoc::getFromPointer(TokStart); } + lltok::Kind getKind() const { return CurKind; } + const std::string &getStrVal() const { return StrVal; } + Type *getTyVal() const { return TyVal; } + unsigned getUIntVal() const { return UIntVal; } + const APSInt &getAPSIntVal() const { return APSIntVal; } + const APFloat &getAPFloatVal() const { return APFloatVal; } + + void setIgnoreColonInIdentifiers(bool val) { + IgnoreColonInIdentifiers = val; + } + + bool Error(LocTy ErrorLoc, const Twine &Msg) const; + bool Error(const Twine &Msg) const { return Error(getLoc(), Msg); } + + void Warning(LocTy WarningLoc, const Twine &Msg) const; + void Warning(const Twine &Msg) const { return Warning(getLoc(), Msg); } + + private: + lltok::Kind LexToken(); + + int getNextChar(); + void SkipLineComment(); + lltok::Kind ReadString(lltok::Kind kind); + bool ReadVarName(); + + lltok::Kind LexIdentifier(); + lltok::Kind LexDigitOrNegative(); + lltok::Kind LexPositive(); + lltok::Kind LexAt(); + lltok::Kind LexDollar(); + lltok::Kind LexExclaim(); + lltok::Kind LexPercent(); + lltok::Kind LexUIntID(lltok::Kind Token); + lltok::Kind LexVar(lltok::Kind Var, lltok::Kind VarID); + lltok::Kind LexQuote(); + lltok::Kind Lex0x(); + lltok::Kind LexHash(); + lltok::Kind LexCaret(); + + uint64_t atoull(const char *Buffer, const char *End); + uint64_t HexIntToVal(const char *Buffer, const char *End); + void HexToIntPair(const char *Buffer, const char *End, uint64_t Pair[2]); + void FP80HexToIntPair(const char *Buffer, const char *End, uint64_t Pair[2]); + }; +} // end namespace llvm + +#endif diff --git a/contrib/libs/llvm12/lib/AsmParser/LLParser.cpp b/contrib/libs/llvm12/lib/AsmParser/LLParser.cpp index 695ce10530..2a3fb8fb66 100644 --- a/contrib/libs/llvm12/lib/AsmParser/LLParser.cpp +++ b/contrib/libs/llvm12/lib/AsmParser/LLParser.cpp @@ -1,349 +1,349 @@ -//===-- LLParser.cpp - Parser Class ---------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the parser class for .ll files. -// -//===----------------------------------------------------------------------===// - -#include "LLParser.h" -#include "LLToken.h" -#include "llvm/ADT/APSInt.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/None.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/AsmParser/SlotMapping.h" -#include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/IR/Argument.h" -#include "llvm/IR/AutoUpgrade.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/Comdat.h" -#include "llvm/IR/ConstantRange.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalIFunc.h" -#include "llvm/IR/GlobalObject.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/Intrinsics.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Metadata.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Value.h" -#include "llvm/IR/ValueSymbolTable.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/SaveAndRestore.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <cassert> -#include <cstring> -#include <iterator> -#include <vector> - -using namespace llvm; - -static std::string getTypeString(Type *T) { - std::string Result; - raw_string_ostream Tmp(Result); - Tmp << *T; - return Tmp.str(); -} - -/// Run: module ::= toplevelentity* -bool LLParser::Run(bool UpgradeDebugInfo, - DataLayoutCallbackTy DataLayoutCallback) { - // Prime the lexer. - Lex.Lex(); - - if (Context.shouldDiscardValueNames()) +//===-- LLParser.cpp - Parser Class ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the parser class for .ll files. +// +//===----------------------------------------------------------------------===// + +#include "LLParser.h" +#include "LLToken.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/AsmParser/SlotMapping.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/IR/Argument.h" +#include "llvm/IR/AutoUpgrade.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/Comdat.h" +#include "llvm/IR/ConstantRange.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalIFunc.h" +#include "llvm/IR/GlobalObject.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" +#include "llvm/IR/ValueSymbolTable.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/SaveAndRestore.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstring> +#include <iterator> +#include <vector> + +using namespace llvm; + +static std::string getTypeString(Type *T) { + std::string Result; + raw_string_ostream Tmp(Result); + Tmp << *T; + return Tmp.str(); +} + +/// Run: module ::= toplevelentity* +bool LLParser::Run(bool UpgradeDebugInfo, + DataLayoutCallbackTy DataLayoutCallback) { + // Prime the lexer. + Lex.Lex(); + + if (Context.shouldDiscardValueNames()) return error( - Lex.getLoc(), - "Can't read textual IR with a Context that discards named Values"); - - if (M) { + Lex.getLoc(), + "Can't read textual IR with a Context that discards named Values"); + + if (M) { if (parseTargetDefinitions()) - return true; - - if (auto LayoutOverride = DataLayoutCallback(M->getTargetTriple())) - M->setDataLayout(*LayoutOverride); - } - + return true; + + if (auto LayoutOverride = DataLayoutCallback(M->getTargetTriple())) + M->setDataLayout(*LayoutOverride); + } + return parseTopLevelEntities() || validateEndOfModule(UpgradeDebugInfo) || validateEndOfIndex(); -} - -bool LLParser::parseStandaloneConstantValue(Constant *&C, - const SlotMapping *Slots) { - restoreParsingState(Slots); - Lex.Lex(); - - Type *Ty = nullptr; +} + +bool LLParser::parseStandaloneConstantValue(Constant *&C, + const SlotMapping *Slots) { + restoreParsingState(Slots); + Lex.Lex(); + + Type *Ty = nullptr; if (parseType(Ty) || parseConstantValue(Ty, C)) - return true; - if (Lex.getKind() != lltok::Eof) + return true; + if (Lex.getKind() != lltok::Eof) return error(Lex.getLoc(), "expected end of string"); - return false; -} - -bool LLParser::parseTypeAtBeginning(Type *&Ty, unsigned &Read, - const SlotMapping *Slots) { - restoreParsingState(Slots); - Lex.Lex(); - - Read = 0; - SMLoc Start = Lex.getLoc(); - Ty = nullptr; + return false; +} + +bool LLParser::parseTypeAtBeginning(Type *&Ty, unsigned &Read, + const SlotMapping *Slots) { + restoreParsingState(Slots); + Lex.Lex(); + + Read = 0; + SMLoc Start = Lex.getLoc(); + Ty = nullptr; if (parseType(Ty)) - return true; - SMLoc End = Lex.getLoc(); - Read = End.getPointer() - Start.getPointer(); - - return false; -} - -void LLParser::restoreParsingState(const SlotMapping *Slots) { - if (!Slots) - return; - NumberedVals = Slots->GlobalValues; - NumberedMetadata = Slots->MetadataNodes; - for (const auto &I : Slots->NamedTypes) - NamedTypes.insert( - std::make_pair(I.getKey(), std::make_pair(I.second, LocTy()))); - for (const auto &I : Slots->Types) - NumberedTypes.insert( - std::make_pair(I.first, std::make_pair(I.second, LocTy()))); -} - + return true; + SMLoc End = Lex.getLoc(); + Read = End.getPointer() - Start.getPointer(); + + return false; +} + +void LLParser::restoreParsingState(const SlotMapping *Slots) { + if (!Slots) + return; + NumberedVals = Slots->GlobalValues; + NumberedMetadata = Slots->MetadataNodes; + for (const auto &I : Slots->NamedTypes) + NamedTypes.insert( + std::make_pair(I.getKey(), std::make_pair(I.second, LocTy()))); + for (const auto &I : Slots->Types) + NumberedTypes.insert( + std::make_pair(I.first, std::make_pair(I.second, LocTy()))); +} + /// validateEndOfModule - Do final validity and sanity checks at the end of the -/// module. +/// module. bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) { - if (!M) - return false; - // Handle any function attribute group forward references. - for (const auto &RAG : ForwardRefAttrGroups) { - Value *V = RAG.first; - const std::vector<unsigned> &Attrs = RAG.second; - AttrBuilder B; - - for (const auto &Attr : Attrs) - B.merge(NumberedAttrBuilders[Attr]); - - if (Function *Fn = dyn_cast<Function>(V)) { - AttributeList AS = Fn->getAttributes(); - AttrBuilder FnAttrs(AS.getFnAttributes()); - AS = AS.removeAttributes(Context, AttributeList::FunctionIndex); - - FnAttrs.merge(B); - - // If the alignment was parsed as an attribute, move to the alignment - // field. - if (FnAttrs.hasAlignmentAttr()) { - Fn->setAlignment(FnAttrs.getAlignment()); - FnAttrs.removeAttribute(Attribute::Alignment); - } - - AS = AS.addAttributes(Context, AttributeList::FunctionIndex, - AttributeSet::get(Context, FnAttrs)); - Fn->setAttributes(AS); - } else if (CallInst *CI = dyn_cast<CallInst>(V)) { - AttributeList AS = CI->getAttributes(); - AttrBuilder FnAttrs(AS.getFnAttributes()); - AS = AS.removeAttributes(Context, AttributeList::FunctionIndex); - FnAttrs.merge(B); - AS = AS.addAttributes(Context, AttributeList::FunctionIndex, - AttributeSet::get(Context, FnAttrs)); - CI->setAttributes(AS); - } else if (InvokeInst *II = dyn_cast<InvokeInst>(V)) { - AttributeList AS = II->getAttributes(); - AttrBuilder FnAttrs(AS.getFnAttributes()); - AS = AS.removeAttributes(Context, AttributeList::FunctionIndex); - FnAttrs.merge(B); - AS = AS.addAttributes(Context, AttributeList::FunctionIndex, - AttributeSet::get(Context, FnAttrs)); - II->setAttributes(AS); - } else if (CallBrInst *CBI = dyn_cast<CallBrInst>(V)) { - AttributeList AS = CBI->getAttributes(); - AttrBuilder FnAttrs(AS.getFnAttributes()); - AS = AS.removeAttributes(Context, AttributeList::FunctionIndex); - FnAttrs.merge(B); - AS = AS.addAttributes(Context, AttributeList::FunctionIndex, - AttributeSet::get(Context, FnAttrs)); - CBI->setAttributes(AS); - } else if (auto *GV = dyn_cast<GlobalVariable>(V)) { - AttrBuilder Attrs(GV->getAttributes()); - Attrs.merge(B); - GV->setAttributes(AttributeSet::get(Context,Attrs)); - } else { - llvm_unreachable("invalid object with forward attribute group reference"); - } - } - - // If there are entries in ForwardRefBlockAddresses at this point, the - // function was never defined. - if (!ForwardRefBlockAddresses.empty()) + if (!M) + return false; + // Handle any function attribute group forward references. + for (const auto &RAG : ForwardRefAttrGroups) { + Value *V = RAG.first; + const std::vector<unsigned> &Attrs = RAG.second; + AttrBuilder B; + + for (const auto &Attr : Attrs) + B.merge(NumberedAttrBuilders[Attr]); + + if (Function *Fn = dyn_cast<Function>(V)) { + AttributeList AS = Fn->getAttributes(); + AttrBuilder FnAttrs(AS.getFnAttributes()); + AS = AS.removeAttributes(Context, AttributeList::FunctionIndex); + + FnAttrs.merge(B); + + // If the alignment was parsed as an attribute, move to the alignment + // field. + if (FnAttrs.hasAlignmentAttr()) { + Fn->setAlignment(FnAttrs.getAlignment()); + FnAttrs.removeAttribute(Attribute::Alignment); + } + + AS = AS.addAttributes(Context, AttributeList::FunctionIndex, + AttributeSet::get(Context, FnAttrs)); + Fn->setAttributes(AS); + } else if (CallInst *CI = dyn_cast<CallInst>(V)) { + AttributeList AS = CI->getAttributes(); + AttrBuilder FnAttrs(AS.getFnAttributes()); + AS = AS.removeAttributes(Context, AttributeList::FunctionIndex); + FnAttrs.merge(B); + AS = AS.addAttributes(Context, AttributeList::FunctionIndex, + AttributeSet::get(Context, FnAttrs)); + CI->setAttributes(AS); + } else if (InvokeInst *II = dyn_cast<InvokeInst>(V)) { + AttributeList AS = II->getAttributes(); + AttrBuilder FnAttrs(AS.getFnAttributes()); + AS = AS.removeAttributes(Context, AttributeList::FunctionIndex); + FnAttrs.merge(B); + AS = AS.addAttributes(Context, AttributeList::FunctionIndex, + AttributeSet::get(Context, FnAttrs)); + II->setAttributes(AS); + } else if (CallBrInst *CBI = dyn_cast<CallBrInst>(V)) { + AttributeList AS = CBI->getAttributes(); + AttrBuilder FnAttrs(AS.getFnAttributes()); + AS = AS.removeAttributes(Context, AttributeList::FunctionIndex); + FnAttrs.merge(B); + AS = AS.addAttributes(Context, AttributeList::FunctionIndex, + AttributeSet::get(Context, FnAttrs)); + CBI->setAttributes(AS); + } else if (auto *GV = dyn_cast<GlobalVariable>(V)) { + AttrBuilder Attrs(GV->getAttributes()); + Attrs.merge(B); + GV->setAttributes(AttributeSet::get(Context,Attrs)); + } else { + llvm_unreachable("invalid object with forward attribute group reference"); + } + } + + // If there are entries in ForwardRefBlockAddresses at this point, the + // function was never defined. + if (!ForwardRefBlockAddresses.empty()) return error(ForwardRefBlockAddresses.begin()->first.Loc, - "expected function name in blockaddress"); - - for (const auto &NT : NumberedTypes) - if (NT.second.second.isValid()) + "expected function name in blockaddress"); + + for (const auto &NT : NumberedTypes) + if (NT.second.second.isValid()) return error(NT.second.second, - "use of undefined type '%" + Twine(NT.first) + "'"); - - for (StringMap<std::pair<Type*, LocTy> >::iterator I = - NamedTypes.begin(), E = NamedTypes.end(); I != E; ++I) - if (I->second.second.isValid()) + "use of undefined type '%" + Twine(NT.first) + "'"); + + for (StringMap<std::pair<Type*, LocTy> >::iterator I = + NamedTypes.begin(), E = NamedTypes.end(); I != E; ++I) + if (I->second.second.isValid()) return error(I->second.second, - "use of undefined type named '" + I->getKey() + "'"); - - if (!ForwardRefComdats.empty()) + "use of undefined type named '" + I->getKey() + "'"); + + if (!ForwardRefComdats.empty()) return error(ForwardRefComdats.begin()->second, - "use of undefined comdat '$" + - ForwardRefComdats.begin()->first + "'"); - - if (!ForwardRefVals.empty()) + "use of undefined comdat '$" + + ForwardRefComdats.begin()->first + "'"); + + if (!ForwardRefVals.empty()) return error(ForwardRefVals.begin()->second.second, - "use of undefined value '@" + ForwardRefVals.begin()->first + + "use of undefined value '@" + ForwardRefVals.begin()->first + "'"); - - if (!ForwardRefValIDs.empty()) + + if (!ForwardRefValIDs.empty()) return error(ForwardRefValIDs.begin()->second.second, - "use of undefined value '@" + + "use of undefined value '@" + Twine(ForwardRefValIDs.begin()->first) + "'"); - - if (!ForwardRefMDNodes.empty()) + + if (!ForwardRefMDNodes.empty()) return error(ForwardRefMDNodes.begin()->second.second, - "use of undefined metadata '!" + + "use of undefined metadata '!" + Twine(ForwardRefMDNodes.begin()->first) + "'"); - - // Resolve metadata cycles. - for (auto &N : NumberedMetadata) { - if (N.second && !N.second->isResolved()) - N.second->resolveCycles(); - } - - for (auto *Inst : InstsWithTBAATag) { - MDNode *MD = Inst->getMetadata(LLVMContext::MD_tbaa); - assert(MD && "UpgradeInstWithTBAATag should have a TBAA tag"); - auto *UpgradedMD = UpgradeTBAANode(*MD); - if (MD != UpgradedMD) - Inst->setMetadata(LLVMContext::MD_tbaa, UpgradedMD); - } - - // Look for intrinsic functions and CallInst that need to be upgraded - for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ) - UpgradeCallsToIntrinsic(&*FI++); // must be post-increment, as we remove - - // Some types could be renamed during loading if several modules are - // loaded in the same LLVMContext (LTO scenario). In this case we should - // remangle intrinsics names as well. - for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ) { - Function *F = &*FI++; - if (auto Remangled = Intrinsic::remangleIntrinsicFunction(F)) { - F->replaceAllUsesWith(Remangled.getValue()); - F->eraseFromParent(); - } - } - - if (UpgradeDebugInfo) - llvm::UpgradeDebugInfo(*M); - - UpgradeModuleFlags(*M); - UpgradeSectionAttributes(*M); - - if (!Slots) - return false; - // Initialize the slot mapping. - // Because by this point we've parsed and validated everything, we can "steal" - // the mapping from LLParser as it doesn't need it anymore. - Slots->GlobalValues = std::move(NumberedVals); - Slots->MetadataNodes = std::move(NumberedMetadata); - for (const auto &I : NamedTypes) - Slots->NamedTypes.insert(std::make_pair(I.getKey(), I.second.first)); - for (const auto &I : NumberedTypes) - Slots->Types.insert(std::make_pair(I.first, I.second.first)); - - return false; -} - -/// Do final validity and sanity checks at the end of the index. + + // Resolve metadata cycles. + for (auto &N : NumberedMetadata) { + if (N.second && !N.second->isResolved()) + N.second->resolveCycles(); + } + + for (auto *Inst : InstsWithTBAATag) { + MDNode *MD = Inst->getMetadata(LLVMContext::MD_tbaa); + assert(MD && "UpgradeInstWithTBAATag should have a TBAA tag"); + auto *UpgradedMD = UpgradeTBAANode(*MD); + if (MD != UpgradedMD) + Inst->setMetadata(LLVMContext::MD_tbaa, UpgradedMD); + } + + // Look for intrinsic functions and CallInst that need to be upgraded + for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ) + UpgradeCallsToIntrinsic(&*FI++); // must be post-increment, as we remove + + // Some types could be renamed during loading if several modules are + // loaded in the same LLVMContext (LTO scenario). In this case we should + // remangle intrinsics names as well. + for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ) { + Function *F = &*FI++; + if (auto Remangled = Intrinsic::remangleIntrinsicFunction(F)) { + F->replaceAllUsesWith(Remangled.getValue()); + F->eraseFromParent(); + } + } + + if (UpgradeDebugInfo) + llvm::UpgradeDebugInfo(*M); + + UpgradeModuleFlags(*M); + UpgradeSectionAttributes(*M); + + if (!Slots) + return false; + // Initialize the slot mapping. + // Because by this point we've parsed and validated everything, we can "steal" + // the mapping from LLParser as it doesn't need it anymore. + Slots->GlobalValues = std::move(NumberedVals); + Slots->MetadataNodes = std::move(NumberedMetadata); + for (const auto &I : NamedTypes) + Slots->NamedTypes.insert(std::make_pair(I.getKey(), I.second.first)); + for (const auto &I : NumberedTypes) + Slots->Types.insert(std::make_pair(I.first, I.second.first)); + + return false; +} + +/// Do final validity and sanity checks at the end of the index. bool LLParser::validateEndOfIndex() { - if (!Index) - return false; - - if (!ForwardRefValueInfos.empty()) + if (!Index) + return false; + + if (!ForwardRefValueInfos.empty()) return error(ForwardRefValueInfos.begin()->second.front().second, - "use of undefined summary '^" + - Twine(ForwardRefValueInfos.begin()->first) + "'"); - - if (!ForwardRefAliasees.empty()) + "use of undefined summary '^" + + Twine(ForwardRefValueInfos.begin()->first) + "'"); + + if (!ForwardRefAliasees.empty()) return error(ForwardRefAliasees.begin()->second.front().second, - "use of undefined summary '^" + - Twine(ForwardRefAliasees.begin()->first) + "'"); - - if (!ForwardRefTypeIds.empty()) + "use of undefined summary '^" + + Twine(ForwardRefAliasees.begin()->first) + "'"); + + if (!ForwardRefTypeIds.empty()) return error(ForwardRefTypeIds.begin()->second.front().second, - "use of undefined type id summary '^" + - Twine(ForwardRefTypeIds.begin()->first) + "'"); - - return false; -} - -//===----------------------------------------------------------------------===// -// Top-Level Entities -//===----------------------------------------------------------------------===// - + "use of undefined type id summary '^" + + Twine(ForwardRefTypeIds.begin()->first) + "'"); + + return false; +} + +//===----------------------------------------------------------------------===// +// Top-Level Entities +//===----------------------------------------------------------------------===// + bool LLParser::parseTargetDefinitions() { - while (true) { - switch (Lex.getKind()) { - case lltok::kw_target: + while (true) { + switch (Lex.getKind()) { + case lltok::kw_target: if (parseTargetDefinition()) - return true; - break; - case lltok::kw_source_filename: + return true; + break; + case lltok::kw_source_filename: if (parseSourceFileName()) - return true; - break; - default: - return false; - } - } -} - + return true; + break; + default: + return false; + } + } +} + bool LLParser::parseTopLevelEntities() { - // If there is no Module, then parse just the summary index entries. - if (!M) { - while (true) { - switch (Lex.getKind()) { - case lltok::Eof: - return false; - case lltok::SummaryID: + // If there is no Module, then parse just the summary index entries. + if (!M) { + while (true) { + switch (Lex.getKind()) { + case lltok::Eof: + return false; + case lltok::SummaryID: if (parseSummaryEntry()) - return true; - break; - case lltok::kw_source_filename: + return true; + break; + case lltok::kw_source_filename: if (parseSourceFileName()) - return true; - break; - default: - // Skip everything else - Lex.Lex(); - } - } - } - while (true) { - switch (Lex.getKind()) { + return true; + break; + default: + // Skip everything else + Lex.Lex(); + } + } + } + while (true) { + switch (Lex.getKind()) { default: return tokError("expected top-level entity"); - case lltok::Eof: return false; + case lltok::Eof: return false; case lltok::kw_declare: if (parseDeclare()) return true; @@ -376,15 +376,15 @@ bool LLParser::parseTopLevelEntities() { if (parseNamedGlobal()) return true; break; - case lltok::ComdatVar: if (parseComdat()) return true; break; + case lltok::ComdatVar: if (parseComdat()) return true; break; case lltok::exclaim: if (parseStandaloneMetadata()) return true; break; - case lltok::SummaryID: + case lltok::SummaryID: if (parseSummaryEntry()) - return true; - break; + return true; + break; case lltok::MetadataVar: if (parseNamedMetadata()) return true; @@ -397,442 +397,442 @@ bool LLParser::parseTopLevelEntities() { if (parseUseListOrder()) return true; break; - case lltok::kw_uselistorder_bb: + case lltok::kw_uselistorder_bb: if (parseUseListOrderBB()) - return true; - break; - } - } -} - -/// toplevelentity -/// ::= 'module' 'asm' STRINGCONSTANT + return true; + break; + } + } +} + +/// toplevelentity +/// ::= 'module' 'asm' STRINGCONSTANT bool LLParser::parseModuleAsm() { - assert(Lex.getKind() == lltok::kw_module); - Lex.Lex(); - - std::string AsmStr; + assert(Lex.getKind() == lltok::kw_module); + Lex.Lex(); + + std::string AsmStr; if (parseToken(lltok::kw_asm, "expected 'module asm'") || parseStringConstant(AsmStr)) return true; - - M->appendModuleInlineAsm(AsmStr); - return false; -} - -/// toplevelentity -/// ::= 'target' 'triple' '=' STRINGCONSTANT -/// ::= 'target' 'datalayout' '=' STRINGCONSTANT + + M->appendModuleInlineAsm(AsmStr); + return false; +} + +/// toplevelentity +/// ::= 'target' 'triple' '=' STRINGCONSTANT +/// ::= 'target' 'datalayout' '=' STRINGCONSTANT bool LLParser::parseTargetDefinition() { - assert(Lex.getKind() == lltok::kw_target); - std::string Str; - switch (Lex.Lex()) { + assert(Lex.getKind() == lltok::kw_target); + std::string Str; + switch (Lex.Lex()) { default: return tokError("unknown target property"); - case lltok::kw_triple: - Lex.Lex(); + case lltok::kw_triple: + Lex.Lex(); if (parseToken(lltok::equal, "expected '=' after target triple") || parseStringConstant(Str)) - return true; - M->setTargetTriple(Str); - return false; - case lltok::kw_datalayout: - Lex.Lex(); + return true; + M->setTargetTriple(Str); + return false; + case lltok::kw_datalayout: + Lex.Lex(); if (parseToken(lltok::equal, "expected '=' after target datalayout") || parseStringConstant(Str)) - return true; - M->setDataLayout(Str); - return false; - } -} - -/// toplevelentity -/// ::= 'source_filename' '=' STRINGCONSTANT + return true; + M->setDataLayout(Str); + return false; + } +} + +/// toplevelentity +/// ::= 'source_filename' '=' STRINGCONSTANT bool LLParser::parseSourceFileName() { - assert(Lex.getKind() == lltok::kw_source_filename); - Lex.Lex(); + assert(Lex.getKind() == lltok::kw_source_filename); + Lex.Lex(); if (parseToken(lltok::equal, "expected '=' after source_filename") || parseStringConstant(SourceFileName)) - return true; - if (M) - M->setSourceFileName(SourceFileName); - return false; -} - -/// toplevelentity -/// ::= 'deplibs' '=' '[' ']' -/// ::= 'deplibs' '=' '[' STRINGCONSTANT (',' STRINGCONSTANT)* ']' -/// FIXME: Remove in 4.0. Currently parse, but ignore. + return true; + if (M) + M->setSourceFileName(SourceFileName); + return false; +} + +/// toplevelentity +/// ::= 'deplibs' '=' '[' ']' +/// ::= 'deplibs' '=' '[' STRINGCONSTANT (',' STRINGCONSTANT)* ']' +/// FIXME: Remove in 4.0. Currently parse, but ignore. bool LLParser::parseDepLibs() { - assert(Lex.getKind() == lltok::kw_deplibs); - Lex.Lex(); + assert(Lex.getKind() == lltok::kw_deplibs); + Lex.Lex(); if (parseToken(lltok::equal, "expected '=' after deplibs") || parseToken(lltok::lsquare, "expected '=' after deplibs")) - return true; - - if (EatIfPresent(lltok::rsquare)) - return false; - - do { - std::string Str; + return true; + + if (EatIfPresent(lltok::rsquare)) + return false; + + do { + std::string Str; if (parseStringConstant(Str)) return true; - } while (EatIfPresent(lltok::comma)); - + } while (EatIfPresent(lltok::comma)); + return parseToken(lltok::rsquare, "expected ']' at end of list"); -} - +} + /// parseUnnamedType: -/// ::= LocalVarID '=' 'type' type +/// ::= LocalVarID '=' 'type' type bool LLParser::parseUnnamedType() { - LocTy TypeLoc = Lex.getLoc(); - unsigned TypeID = Lex.getUIntVal(); - Lex.Lex(); // eat LocalVarID; - + LocTy TypeLoc = Lex.getLoc(); + unsigned TypeID = Lex.getUIntVal(); + Lex.Lex(); // eat LocalVarID; + if (parseToken(lltok::equal, "expected '=' after name") || parseToken(lltok::kw_type, "expected 'type' after '='")) - return true; - - Type *Result = nullptr; + return true; + + Type *Result = nullptr; if (parseStructDefinition(TypeLoc, "", NumberedTypes[TypeID], Result)) return true; - - if (!isa<StructType>(Result)) { - std::pair<Type*, LocTy> &Entry = NumberedTypes[TypeID]; - if (Entry.first) + + if (!isa<StructType>(Result)) { + std::pair<Type*, LocTy> &Entry = NumberedTypes[TypeID]; + if (Entry.first) return error(TypeLoc, "non-struct types may not be recursive"); - Entry.first = Result; - Entry.second = SMLoc(); - } - - return false; -} - -/// toplevelentity -/// ::= LocalVar '=' 'type' type + Entry.first = Result; + Entry.second = SMLoc(); + } + + return false; +} + +/// toplevelentity +/// ::= LocalVar '=' 'type' type bool LLParser::parseNamedType() { - std::string Name = Lex.getStrVal(); - LocTy NameLoc = Lex.getLoc(); - Lex.Lex(); // eat LocalVar. - + std::string Name = Lex.getStrVal(); + LocTy NameLoc = Lex.getLoc(); + Lex.Lex(); // eat LocalVar. + if (parseToken(lltok::equal, "expected '=' after name") || parseToken(lltok::kw_type, "expected 'type' after name")) - return true; - - Type *Result = nullptr; + return true; + + Type *Result = nullptr; if (parseStructDefinition(NameLoc, Name, NamedTypes[Name], Result)) return true; - - if (!isa<StructType>(Result)) { - std::pair<Type*, LocTy> &Entry = NamedTypes[Name]; - if (Entry.first) + + if (!isa<StructType>(Result)) { + std::pair<Type*, LocTy> &Entry = NamedTypes[Name]; + if (Entry.first) return error(NameLoc, "non-struct types may not be recursive"); - Entry.first = Result; - Entry.second = SMLoc(); - } - - return false; -} - -/// toplevelentity -/// ::= 'declare' FunctionHeader + Entry.first = Result; + Entry.second = SMLoc(); + } + + return false; +} + +/// toplevelentity +/// ::= 'declare' FunctionHeader bool LLParser::parseDeclare() { - assert(Lex.getKind() == lltok::kw_declare); - Lex.Lex(); - - std::vector<std::pair<unsigned, MDNode *>> MDs; - while (Lex.getKind() == lltok::MetadataVar) { - unsigned MDK; - MDNode *N; + assert(Lex.getKind() == lltok::kw_declare); + Lex.Lex(); + + std::vector<std::pair<unsigned, MDNode *>> MDs; + while (Lex.getKind() == lltok::MetadataVar) { + unsigned MDK; + MDNode *N; if (parseMetadataAttachment(MDK, N)) - return true; - MDs.push_back({MDK, N}); - } - - Function *F; + return true; + MDs.push_back({MDK, N}); + } + + Function *F; if (parseFunctionHeader(F, false)) - return true; - for (auto &MD : MDs) - F->addMetadata(MD.first, *MD.second); - return false; -} - -/// toplevelentity -/// ::= 'define' FunctionHeader (!dbg !56)* '{' ... + return true; + for (auto &MD : MDs) + F->addMetadata(MD.first, *MD.second); + return false; +} + +/// toplevelentity +/// ::= 'define' FunctionHeader (!dbg !56)* '{' ... bool LLParser::parseDefine() { - assert(Lex.getKind() == lltok::kw_define); - Lex.Lex(); - - Function *F; + assert(Lex.getKind() == lltok::kw_define); + Lex.Lex(); + + Function *F; return parseFunctionHeader(F, true) || parseOptionalFunctionMetadata(*F) || parseFunctionBody(*F); -} - +} + /// parseGlobalType -/// ::= 'constant' -/// ::= 'global' +/// ::= 'constant' +/// ::= 'global' bool LLParser::parseGlobalType(bool &IsConstant) { - if (Lex.getKind() == lltok::kw_constant) - IsConstant = true; - else if (Lex.getKind() == lltok::kw_global) - IsConstant = false; - else { - IsConstant = false; + if (Lex.getKind() == lltok::kw_constant) + IsConstant = true; + else if (Lex.getKind() == lltok::kw_global) + IsConstant = false; + else { + IsConstant = false; return tokError("expected 'global' or 'constant'"); - } - Lex.Lex(); - return false; -} - + } + Lex.Lex(); + return false; +} + bool LLParser::parseOptionalUnnamedAddr( - GlobalVariable::UnnamedAddr &UnnamedAddr) { - if (EatIfPresent(lltok::kw_unnamed_addr)) - UnnamedAddr = GlobalValue::UnnamedAddr::Global; - else if (EatIfPresent(lltok::kw_local_unnamed_addr)) - UnnamedAddr = GlobalValue::UnnamedAddr::Local; - else - UnnamedAddr = GlobalValue::UnnamedAddr::None; - return false; -} - + GlobalVariable::UnnamedAddr &UnnamedAddr) { + if (EatIfPresent(lltok::kw_unnamed_addr)) + UnnamedAddr = GlobalValue::UnnamedAddr::Global; + else if (EatIfPresent(lltok::kw_local_unnamed_addr)) + UnnamedAddr = GlobalValue::UnnamedAddr::Local; + else + UnnamedAddr = GlobalValue::UnnamedAddr::None; + return false; +} + /// parseUnnamedGlobal: -/// OptionalVisibility (ALIAS | IFUNC) ... -/// OptionalLinkage OptionalPreemptionSpecifier OptionalVisibility -/// OptionalDLLStorageClass -/// ... -> global variable -/// GlobalID '=' OptionalVisibility (ALIAS | IFUNC) ... +/// OptionalVisibility (ALIAS | IFUNC) ... +/// OptionalLinkage OptionalPreemptionSpecifier OptionalVisibility +/// OptionalDLLStorageClass +/// ... -> global variable +/// GlobalID '=' OptionalVisibility (ALIAS | IFUNC) ... /// GlobalID '=' OptionalLinkage OptionalPreemptionSpecifier /// OptionalVisibility -/// OptionalDLLStorageClass -/// ... -> global variable +/// OptionalDLLStorageClass +/// ... -> global variable bool LLParser::parseUnnamedGlobal() { - unsigned VarID = NumberedVals.size(); - std::string Name; - LocTy NameLoc = Lex.getLoc(); - - // Handle the GlobalID form. - if (Lex.getKind() == lltok::GlobalID) { - if (Lex.getUIntVal() != VarID) + unsigned VarID = NumberedVals.size(); + std::string Name; + LocTy NameLoc = Lex.getLoc(); + + // Handle the GlobalID form. + if (Lex.getKind() == lltok::GlobalID) { + if (Lex.getUIntVal() != VarID) return error(Lex.getLoc(), "variable expected to be numbered '%" + Twine(VarID) + "'"); - Lex.Lex(); // eat GlobalID; - + Lex.Lex(); // eat GlobalID; + if (parseToken(lltok::equal, "expected '=' after name")) - return true; - } - - bool HasLinkage; - unsigned Linkage, Visibility, DLLStorageClass; - bool DSOLocal; - GlobalVariable::ThreadLocalMode TLM; - GlobalVariable::UnnamedAddr UnnamedAddr; + return true; + } + + bool HasLinkage; + unsigned Linkage, Visibility, DLLStorageClass; + bool DSOLocal; + GlobalVariable::ThreadLocalMode TLM; + GlobalVariable::UnnamedAddr UnnamedAddr; if (parseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass, - DSOLocal) || + DSOLocal) || parseOptionalThreadLocal(TLM) || parseOptionalUnnamedAddr(UnnamedAddr)) - return true; - - if (Lex.getKind() != lltok::kw_alias && Lex.getKind() != lltok::kw_ifunc) + return true; + + if (Lex.getKind() != lltok::kw_alias && Lex.getKind() != lltok::kw_ifunc) return parseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility, - DLLStorageClass, DSOLocal, TLM, UnnamedAddr); - - return parseIndirectSymbol(Name, NameLoc, Linkage, Visibility, - DLLStorageClass, DSOLocal, TLM, UnnamedAddr); -} - + DLLStorageClass, DSOLocal, TLM, UnnamedAddr); + + return parseIndirectSymbol(Name, NameLoc, Linkage, Visibility, + DLLStorageClass, DSOLocal, TLM, UnnamedAddr); +} + /// parseNamedGlobal: -/// GlobalVar '=' OptionalVisibility (ALIAS | IFUNC) ... -/// GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier -/// OptionalVisibility OptionalDLLStorageClass -/// ... -> global variable +/// GlobalVar '=' OptionalVisibility (ALIAS | IFUNC) ... +/// GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier +/// OptionalVisibility OptionalDLLStorageClass +/// ... -> global variable bool LLParser::parseNamedGlobal() { - assert(Lex.getKind() == lltok::GlobalVar); - LocTy NameLoc = Lex.getLoc(); - std::string Name = Lex.getStrVal(); - Lex.Lex(); - - bool HasLinkage; - unsigned Linkage, Visibility, DLLStorageClass; - bool DSOLocal; - GlobalVariable::ThreadLocalMode TLM; - GlobalVariable::UnnamedAddr UnnamedAddr; + assert(Lex.getKind() == lltok::GlobalVar); + LocTy NameLoc = Lex.getLoc(); + std::string Name = Lex.getStrVal(); + Lex.Lex(); + + bool HasLinkage; + unsigned Linkage, Visibility, DLLStorageClass; + bool DSOLocal; + GlobalVariable::ThreadLocalMode TLM; + GlobalVariable::UnnamedAddr UnnamedAddr; if (parseToken(lltok::equal, "expected '=' in global variable") || parseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass, - DSOLocal) || + DSOLocal) || parseOptionalThreadLocal(TLM) || parseOptionalUnnamedAddr(UnnamedAddr)) - return true; - - if (Lex.getKind() != lltok::kw_alias && Lex.getKind() != lltok::kw_ifunc) + return true; + + if (Lex.getKind() != lltok::kw_alias && Lex.getKind() != lltok::kw_ifunc) return parseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility, - DLLStorageClass, DSOLocal, TLM, UnnamedAddr); - - return parseIndirectSymbol(Name, NameLoc, Linkage, Visibility, - DLLStorageClass, DSOLocal, TLM, UnnamedAddr); -} - -bool LLParser::parseComdat() { - assert(Lex.getKind() == lltok::ComdatVar); - std::string Name = Lex.getStrVal(); - LocTy NameLoc = Lex.getLoc(); - Lex.Lex(); - + DLLStorageClass, DSOLocal, TLM, UnnamedAddr); + + return parseIndirectSymbol(Name, NameLoc, Linkage, Visibility, + DLLStorageClass, DSOLocal, TLM, UnnamedAddr); +} + +bool LLParser::parseComdat() { + assert(Lex.getKind() == lltok::ComdatVar); + std::string Name = Lex.getStrVal(); + LocTy NameLoc = Lex.getLoc(); + Lex.Lex(); + if (parseToken(lltok::equal, "expected '=' here")) - return true; - + return true; + if (parseToken(lltok::kw_comdat, "expected comdat keyword")) return tokError("expected comdat type"); - - Comdat::SelectionKind SK; - switch (Lex.getKind()) { - default: + + Comdat::SelectionKind SK; + switch (Lex.getKind()) { + default: return tokError("unknown selection kind"); - case lltok::kw_any: - SK = Comdat::Any; - break; - case lltok::kw_exactmatch: - SK = Comdat::ExactMatch; - break; - case lltok::kw_largest: - SK = Comdat::Largest; - break; - case lltok::kw_noduplicates: - SK = Comdat::NoDuplicates; - break; - case lltok::kw_samesize: - SK = Comdat::SameSize; - break; - } - Lex.Lex(); - - // See if the comdat was forward referenced, if so, use the comdat. - Module::ComdatSymTabType &ComdatSymTab = M->getComdatSymbolTable(); - Module::ComdatSymTabType::iterator I = ComdatSymTab.find(Name); - if (I != ComdatSymTab.end() && !ForwardRefComdats.erase(Name)) + case lltok::kw_any: + SK = Comdat::Any; + break; + case lltok::kw_exactmatch: + SK = Comdat::ExactMatch; + break; + case lltok::kw_largest: + SK = Comdat::Largest; + break; + case lltok::kw_noduplicates: + SK = Comdat::NoDuplicates; + break; + case lltok::kw_samesize: + SK = Comdat::SameSize; + break; + } + Lex.Lex(); + + // See if the comdat was forward referenced, if so, use the comdat. + Module::ComdatSymTabType &ComdatSymTab = M->getComdatSymbolTable(); + Module::ComdatSymTabType::iterator I = ComdatSymTab.find(Name); + if (I != ComdatSymTab.end() && !ForwardRefComdats.erase(Name)) return error(NameLoc, "redefinition of comdat '$" + Name + "'"); - - Comdat *C; - if (I != ComdatSymTab.end()) - C = &I->second; - else - C = M->getOrInsertComdat(Name); - C->setSelectionKind(SK); - - return false; -} - -// MDString: -// ::= '!' STRINGCONSTANT + + Comdat *C; + if (I != ComdatSymTab.end()) + C = &I->second; + else + C = M->getOrInsertComdat(Name); + C->setSelectionKind(SK); + + return false; +} + +// MDString: +// ::= '!' STRINGCONSTANT bool LLParser::parseMDString(MDString *&Result) { - std::string Str; + std::string Str; if (parseStringConstant(Str)) return true; - Result = MDString::get(Context, Str); - return false; -} - -// MDNode: -// ::= '!' MDNodeNumber + Result = MDString::get(Context, Str); + return false; +} + +// MDNode: +// ::= '!' MDNodeNumber bool LLParser::parseMDNodeID(MDNode *&Result) { - // !{ ..., !42, ... } - LocTy IDLoc = Lex.getLoc(); - unsigned MID = 0; + // !{ ..., !42, ... } + LocTy IDLoc = Lex.getLoc(); + unsigned MID = 0; if (parseUInt32(MID)) - return true; - - // If not a forward reference, just return it now. - if (NumberedMetadata.count(MID)) { - Result = NumberedMetadata[MID]; - return false; - } - - // Otherwise, create MDNode forward reference. - auto &FwdRef = ForwardRefMDNodes[MID]; - FwdRef = std::make_pair(MDTuple::getTemporary(Context, None), IDLoc); - - Result = FwdRef.first.get(); - NumberedMetadata[MID].reset(Result); - return false; -} - + return true; + + // If not a forward reference, just return it now. + if (NumberedMetadata.count(MID)) { + Result = NumberedMetadata[MID]; + return false; + } + + // Otherwise, create MDNode forward reference. + auto &FwdRef = ForwardRefMDNodes[MID]; + FwdRef = std::make_pair(MDTuple::getTemporary(Context, None), IDLoc); + + Result = FwdRef.first.get(); + NumberedMetadata[MID].reset(Result); + return false; +} + /// parseNamedMetadata: -/// !foo = !{ !1, !2 } +/// !foo = !{ !1, !2 } bool LLParser::parseNamedMetadata() { - assert(Lex.getKind() == lltok::MetadataVar); - std::string Name = Lex.getStrVal(); - Lex.Lex(); - + assert(Lex.getKind() == lltok::MetadataVar); + std::string Name = Lex.getStrVal(); + Lex.Lex(); + if (parseToken(lltok::equal, "expected '=' here") || parseToken(lltok::exclaim, "Expected '!' here") || parseToken(lltok::lbrace, "Expected '{' here")) - return true; - - NamedMDNode *NMD = M->getOrInsertNamedMetadata(Name); - if (Lex.getKind() != lltok::rbrace) - do { - MDNode *N = nullptr; + return true; + + NamedMDNode *NMD = M->getOrInsertNamedMetadata(Name); + if (Lex.getKind() != lltok::rbrace) + do { + MDNode *N = nullptr; // parse DIExpressions inline as a special case. They are still MDNodes, - // so they can still appear in named metadata. Remove this logic if they - // become plain Metadata. - if (Lex.getKind() == lltok::MetadataVar && - Lex.getStrVal() == "DIExpression") { + // so they can still appear in named metadata. Remove this logic if they + // become plain Metadata. + if (Lex.getKind() == lltok::MetadataVar && + Lex.getStrVal() == "DIExpression") { if (parseDIExpression(N, /*IsDistinct=*/false)) - return true; + return true; } else if (parseToken(lltok::exclaim, "Expected '!' here") || parseMDNodeID(N)) { - return true; - } - NMD->addOperand(N); - } while (EatIfPresent(lltok::comma)); - + return true; + } + NMD->addOperand(N); + } while (EatIfPresent(lltok::comma)); + return parseToken(lltok::rbrace, "expected end of metadata node"); -} - +} + /// parseStandaloneMetadata: -/// !42 = !{...} +/// !42 = !{...} bool LLParser::parseStandaloneMetadata() { - assert(Lex.getKind() == lltok::exclaim); - Lex.Lex(); - unsigned MetadataID = 0; - - MDNode *Init; + assert(Lex.getKind() == lltok::exclaim); + Lex.Lex(); + unsigned MetadataID = 0; + + MDNode *Init; if (parseUInt32(MetadataID) || parseToken(lltok::equal, "expected '=' here")) - return true; - - // Detect common error, from old metadata syntax. - if (Lex.getKind() == lltok::Type) + return true; + + // Detect common error, from old metadata syntax. + if (Lex.getKind() == lltok::Type) return tokError("unexpected type in metadata definition"); - - bool IsDistinct = EatIfPresent(lltok::kw_distinct); - if (Lex.getKind() == lltok::MetadataVar) { + + bool IsDistinct = EatIfPresent(lltok::kw_distinct); + if (Lex.getKind() == lltok::MetadataVar) { if (parseSpecializedMDNode(Init, IsDistinct)) - return true; + return true; } else if (parseToken(lltok::exclaim, "Expected '!' here") || parseMDTuple(Init, IsDistinct)) - return true; - - // See if this was forward referenced, if so, handle it. - auto FI = ForwardRefMDNodes.find(MetadataID); - if (FI != ForwardRefMDNodes.end()) { - FI->second.first->replaceAllUsesWith(Init); - ForwardRefMDNodes.erase(FI); - - assert(NumberedMetadata[MetadataID] == Init && "Tracking VH didn't work"); - } else { - if (NumberedMetadata.count(MetadataID)) + return true; + + // See if this was forward referenced, if so, handle it. + auto FI = ForwardRefMDNodes.find(MetadataID); + if (FI != ForwardRefMDNodes.end()) { + FI->second.first->replaceAllUsesWith(Init); + ForwardRefMDNodes.erase(FI); + + assert(NumberedMetadata[MetadataID] == Init && "Tracking VH didn't work"); + } else { + if (NumberedMetadata.count(MetadataID)) return tokError("Metadata id is already used"); - NumberedMetadata[MetadataID].reset(Init); - } - - return false; -} - -// Skips a single module summary entry. + NumberedMetadata[MetadataID].reset(Init); + } + + return false; +} + +// Skips a single module summary entry. bool LLParser::skipModuleSummaryEntry() { - // Each module summary entry consists of a tag for the entry + // Each module summary entry consists of a tag for the entry // type, followed by a colon, then the fields which may be surrounded by // nested sets of parentheses. The "tag:" looks like a Label. Once parsing // support is in place we will look for the tokens corresponding to the // expected tags. - if (Lex.getKind() != lltok::kw_gv && Lex.getKind() != lltok::kw_module && + if (Lex.getKind() != lltok::kw_gv && Lex.getKind() != lltok::kw_module && Lex.getKind() != lltok::kw_typeid && Lex.getKind() != lltok::kw_flags && Lex.getKind() != lltok::kw_blockcount) return tokError( @@ -842,873 +842,873 @@ bool LLParser::skipModuleSummaryEntry() { return parseSummaryIndexFlags(); if (Lex.getKind() == lltok::kw_blockcount) return parseBlockCount(); - Lex.Lex(); + Lex.Lex(); if (parseToken(lltok::colon, "expected ':' at start of summary entry") || parseToken(lltok::lparen, "expected '(' at start of summary entry")) - return true; - // Now walk through the parenthesized entry, until the number of open - // parentheses goes back down to 0 (the first '(' was parsed above). - unsigned NumOpenParen = 1; - do { - switch (Lex.getKind()) { - case lltok::lparen: - NumOpenParen++; - break; - case lltok::rparen: - NumOpenParen--; - break; - case lltok::Eof: + return true; + // Now walk through the parenthesized entry, until the number of open + // parentheses goes back down to 0 (the first '(' was parsed above). + unsigned NumOpenParen = 1; + do { + switch (Lex.getKind()) { + case lltok::lparen: + NumOpenParen++; + break; + case lltok::rparen: + NumOpenParen--; + break; + case lltok::Eof: return tokError("found end of file while parsing summary entry"); - default: - // Skip everything in between parentheses. - break; - } - Lex.Lex(); - } while (NumOpenParen > 0); - return false; -} - -/// SummaryEntry -/// ::= SummaryID '=' GVEntry | ModuleEntry | TypeIdEntry + default: + // Skip everything in between parentheses. + break; + } + Lex.Lex(); + } while (NumOpenParen > 0); + return false; +} + +/// SummaryEntry +/// ::= SummaryID '=' GVEntry | ModuleEntry | TypeIdEntry bool LLParser::parseSummaryEntry() { - assert(Lex.getKind() == lltok::SummaryID); - unsigned SummaryID = Lex.getUIntVal(); - - // For summary entries, colons should be treated as distinct tokens, - // not an indication of the end of a label token. - Lex.setIgnoreColonInIdentifiers(true); - - Lex.Lex(); + assert(Lex.getKind() == lltok::SummaryID); + unsigned SummaryID = Lex.getUIntVal(); + + // For summary entries, colons should be treated as distinct tokens, + // not an indication of the end of a label token. + Lex.setIgnoreColonInIdentifiers(true); + + Lex.Lex(); if (parseToken(lltok::equal, "expected '=' here")) - return true; - - // If we don't have an index object, skip the summary entry. - if (!Index) + return true; + + // If we don't have an index object, skip the summary entry. + if (!Index) return skipModuleSummaryEntry(); - - bool result = false; - switch (Lex.getKind()) { - case lltok::kw_gv: + + bool result = false; + switch (Lex.getKind()) { + case lltok::kw_gv: result = parseGVEntry(SummaryID); - break; - case lltok::kw_module: + break; + case lltok::kw_module: result = parseModuleEntry(SummaryID); - break; - case lltok::kw_typeid: + break; + case lltok::kw_typeid: result = parseTypeIdEntry(SummaryID); - break; - case lltok::kw_typeidCompatibleVTable: + break; + case lltok::kw_typeidCompatibleVTable: result = parseTypeIdCompatibleVtableEntry(SummaryID); - break; - case lltok::kw_flags: + break; + case lltok::kw_flags: result = parseSummaryIndexFlags(); - break; - case lltok::kw_blockcount: + break; + case lltok::kw_blockcount: result = parseBlockCount(); - break; - default: + break; + default: result = error(Lex.getLoc(), "unexpected summary kind"); - break; - } - Lex.setIgnoreColonInIdentifiers(false); - return result; -} - -static bool isValidVisibilityForLinkage(unsigned V, unsigned L) { - return !GlobalValue::isLocalLinkage((GlobalValue::LinkageTypes)L) || - (GlobalValue::VisibilityTypes)V == GlobalValue::DefaultVisibility; -} - -// If there was an explicit dso_local, update GV. In the absence of an explicit -// dso_local we keep the default value. -static void maybeSetDSOLocal(bool DSOLocal, GlobalValue &GV) { - if (DSOLocal) - GV.setDSOLocal(true); -} - -/// parseIndirectSymbol: -/// ::= GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier -/// OptionalVisibility OptionalDLLStorageClass -/// OptionalThreadLocal OptionalUnnamedAddr -/// 'alias|ifunc' IndirectSymbol IndirectSymbolAttr* -/// -/// IndirectSymbol -/// ::= TypeAndValue -/// -/// IndirectSymbolAttr -/// ::= ',' 'partition' StringConstant -/// -/// Everything through OptionalUnnamedAddr has already been parsed. -/// -bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc, - unsigned L, unsigned Visibility, - unsigned DLLStorageClass, bool DSOLocal, - GlobalVariable::ThreadLocalMode TLM, - GlobalVariable::UnnamedAddr UnnamedAddr) { - bool IsAlias; - if (Lex.getKind() == lltok::kw_alias) - IsAlias = true; - else if (Lex.getKind() == lltok::kw_ifunc) - IsAlias = false; - else - llvm_unreachable("Not an alias or ifunc!"); - Lex.Lex(); - - GlobalValue::LinkageTypes Linkage = (GlobalValue::LinkageTypes) L; - - if(IsAlias && !GlobalAlias::isValidLinkage(Linkage)) + break; + } + Lex.setIgnoreColonInIdentifiers(false); + return result; +} + +static bool isValidVisibilityForLinkage(unsigned V, unsigned L) { + return !GlobalValue::isLocalLinkage((GlobalValue::LinkageTypes)L) || + (GlobalValue::VisibilityTypes)V == GlobalValue::DefaultVisibility; +} + +// If there was an explicit dso_local, update GV. In the absence of an explicit +// dso_local we keep the default value. +static void maybeSetDSOLocal(bool DSOLocal, GlobalValue &GV) { + if (DSOLocal) + GV.setDSOLocal(true); +} + +/// parseIndirectSymbol: +/// ::= GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier +/// OptionalVisibility OptionalDLLStorageClass +/// OptionalThreadLocal OptionalUnnamedAddr +/// 'alias|ifunc' IndirectSymbol IndirectSymbolAttr* +/// +/// IndirectSymbol +/// ::= TypeAndValue +/// +/// IndirectSymbolAttr +/// ::= ',' 'partition' StringConstant +/// +/// Everything through OptionalUnnamedAddr has already been parsed. +/// +bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc, + unsigned L, unsigned Visibility, + unsigned DLLStorageClass, bool DSOLocal, + GlobalVariable::ThreadLocalMode TLM, + GlobalVariable::UnnamedAddr UnnamedAddr) { + bool IsAlias; + if (Lex.getKind() == lltok::kw_alias) + IsAlias = true; + else if (Lex.getKind() == lltok::kw_ifunc) + IsAlias = false; + else + llvm_unreachable("Not an alias or ifunc!"); + Lex.Lex(); + + GlobalValue::LinkageTypes Linkage = (GlobalValue::LinkageTypes) L; + + if(IsAlias && !GlobalAlias::isValidLinkage(Linkage)) return error(NameLoc, "invalid linkage type for alias"); - - if (!isValidVisibilityForLinkage(Visibility, L)) + + if (!isValidVisibilityForLinkage(Visibility, L)) return error(NameLoc, - "symbol with local linkage must have default visibility"); - - Type *Ty; - LocTy ExplicitTypeLoc = Lex.getLoc(); + "symbol with local linkage must have default visibility"); + + Type *Ty; + LocTy ExplicitTypeLoc = Lex.getLoc(); if (parseType(Ty) || parseToken(lltok::comma, "expected comma after alias or ifunc's type")) - return true; - - Constant *Aliasee; - LocTy AliaseeLoc = Lex.getLoc(); - if (Lex.getKind() != lltok::kw_bitcast && - Lex.getKind() != lltok::kw_getelementptr && - Lex.getKind() != lltok::kw_addrspacecast && - Lex.getKind() != lltok::kw_inttoptr) { + return true; + + Constant *Aliasee; + LocTy AliaseeLoc = Lex.getLoc(); + if (Lex.getKind() != lltok::kw_bitcast && + Lex.getKind() != lltok::kw_getelementptr && + Lex.getKind() != lltok::kw_addrspacecast && + Lex.getKind() != lltok::kw_inttoptr) { if (parseGlobalTypeAndValue(Aliasee)) - return true; - } else { - // The bitcast dest type is not present, it is implied by the dest type. - ValID ID; + return true; + } else { + // The bitcast dest type is not present, it is implied by the dest type. + ValID ID; if (parseValID(ID)) - return true; - if (ID.Kind != ValID::t_Constant) + return true; + if (ID.Kind != ValID::t_Constant) return error(AliaseeLoc, "invalid aliasee"); - Aliasee = ID.ConstantVal; - } - - Type *AliaseeType = Aliasee->getType(); - auto *PTy = dyn_cast<PointerType>(AliaseeType); - if (!PTy) + Aliasee = ID.ConstantVal; + } + + Type *AliaseeType = Aliasee->getType(); + auto *PTy = dyn_cast<PointerType>(AliaseeType); + if (!PTy) return error(AliaseeLoc, "An alias or ifunc must have pointer type"); - unsigned AddrSpace = PTy->getAddressSpace(); - - if (IsAlias && Ty != PTy->getElementType()) + unsigned AddrSpace = PTy->getAddressSpace(); + + if (IsAlias && Ty != PTy->getElementType()) return error(ExplicitTypeLoc, "explicit pointee type doesn't match operand's pointee type"); - - if (!IsAlias && !PTy->getElementType()->isFunctionTy()) + + if (!IsAlias && !PTy->getElementType()->isFunctionTy()) return error(ExplicitTypeLoc, "explicit pointee type should be a function type"); - - GlobalValue *GVal = nullptr; - - // See if the alias was forward referenced, if so, prepare to replace the - // forward reference. - if (!Name.empty()) { - GVal = M->getNamedValue(Name); - if (GVal) { - if (!ForwardRefVals.erase(Name)) + + GlobalValue *GVal = nullptr; + + // See if the alias was forward referenced, if so, prepare to replace the + // forward reference. + if (!Name.empty()) { + GVal = M->getNamedValue(Name); + if (GVal) { + if (!ForwardRefVals.erase(Name)) return error(NameLoc, "redefinition of global '@" + Name + "'"); - } - } else { - auto I = ForwardRefValIDs.find(NumberedVals.size()); - if (I != ForwardRefValIDs.end()) { - GVal = I->second.first; - ForwardRefValIDs.erase(I); - } - } - - // Okay, create the alias but do not insert it into the module yet. - std::unique_ptr<GlobalIndirectSymbol> GA; - if (IsAlias) - GA.reset(GlobalAlias::create(Ty, AddrSpace, - (GlobalValue::LinkageTypes)Linkage, Name, - Aliasee, /*Parent*/ nullptr)); - else - GA.reset(GlobalIFunc::create(Ty, AddrSpace, - (GlobalValue::LinkageTypes)Linkage, Name, - Aliasee, /*Parent*/ nullptr)); - GA->setThreadLocalMode(TLM); - GA->setVisibility((GlobalValue::VisibilityTypes)Visibility); - GA->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); - GA->setUnnamedAddr(UnnamedAddr); - maybeSetDSOLocal(DSOLocal, *GA); - - // At this point we've parsed everything except for the IndirectSymbolAttrs. - // Now parse them if there are any. - while (Lex.getKind() == lltok::comma) { - Lex.Lex(); - - if (Lex.getKind() == lltok::kw_partition) { - Lex.Lex(); - GA->setPartition(Lex.getStrVal()); + } + } else { + auto I = ForwardRefValIDs.find(NumberedVals.size()); + if (I != ForwardRefValIDs.end()) { + GVal = I->second.first; + ForwardRefValIDs.erase(I); + } + } + + // Okay, create the alias but do not insert it into the module yet. + std::unique_ptr<GlobalIndirectSymbol> GA; + if (IsAlias) + GA.reset(GlobalAlias::create(Ty, AddrSpace, + (GlobalValue::LinkageTypes)Linkage, Name, + Aliasee, /*Parent*/ nullptr)); + else + GA.reset(GlobalIFunc::create(Ty, AddrSpace, + (GlobalValue::LinkageTypes)Linkage, Name, + Aliasee, /*Parent*/ nullptr)); + GA->setThreadLocalMode(TLM); + GA->setVisibility((GlobalValue::VisibilityTypes)Visibility); + GA->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); + GA->setUnnamedAddr(UnnamedAddr); + maybeSetDSOLocal(DSOLocal, *GA); + + // At this point we've parsed everything except for the IndirectSymbolAttrs. + // Now parse them if there are any. + while (Lex.getKind() == lltok::comma) { + Lex.Lex(); + + if (Lex.getKind() == lltok::kw_partition) { + Lex.Lex(); + GA->setPartition(Lex.getStrVal()); if (parseToken(lltok::StringConstant, "expected partition string")) - return true; - } else { + return true; + } else { return tokError("unknown alias or ifunc property!"); - } - } - - if (Name.empty()) - NumberedVals.push_back(GA.get()); - - if (GVal) { - // Verify that types agree. - if (GVal->getType() != GA->getType()) + } + } + + if (Name.empty()) + NumberedVals.push_back(GA.get()); + + if (GVal) { + // Verify that types agree. + if (GVal->getType() != GA->getType()) return error( - ExplicitTypeLoc, - "forward reference and definition of alias have different types"); - - // If they agree, just RAUW the old value with the alias and remove the - // forward ref info. - GVal->replaceAllUsesWith(GA.get()); - GVal->eraseFromParent(); - } - - // Insert into the module, we know its name won't collide now. - if (IsAlias) - M->getAliasList().push_back(cast<GlobalAlias>(GA.get())); - else - M->getIFuncList().push_back(cast<GlobalIFunc>(GA.get())); - assert(GA->getName() == Name && "Should not be a name conflict!"); - - // The module owns this now - GA.release(); - - return false; -} - + ExplicitTypeLoc, + "forward reference and definition of alias have different types"); + + // If they agree, just RAUW the old value with the alias and remove the + // forward ref info. + GVal->replaceAllUsesWith(GA.get()); + GVal->eraseFromParent(); + } + + // Insert into the module, we know its name won't collide now. + if (IsAlias) + M->getAliasList().push_back(cast<GlobalAlias>(GA.get())); + else + M->getIFuncList().push_back(cast<GlobalIFunc>(GA.get())); + assert(GA->getName() == Name && "Should not be a name conflict!"); + + // The module owns this now + GA.release(); + + return false; +} + /// parseGlobal -/// ::= GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier -/// OptionalVisibility OptionalDLLStorageClass -/// OptionalThreadLocal OptionalUnnamedAddr OptionalAddrSpace -/// OptionalExternallyInitialized GlobalType Type Const OptionalAttrs -/// ::= OptionalLinkage OptionalPreemptionSpecifier OptionalVisibility -/// OptionalDLLStorageClass OptionalThreadLocal OptionalUnnamedAddr -/// OptionalAddrSpace OptionalExternallyInitialized GlobalType Type -/// Const OptionalAttrs -/// -/// Everything up to and including OptionalUnnamedAddr has been parsed -/// already. -/// +/// ::= GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier +/// OptionalVisibility OptionalDLLStorageClass +/// OptionalThreadLocal OptionalUnnamedAddr OptionalAddrSpace +/// OptionalExternallyInitialized GlobalType Type Const OptionalAttrs +/// ::= OptionalLinkage OptionalPreemptionSpecifier OptionalVisibility +/// OptionalDLLStorageClass OptionalThreadLocal OptionalUnnamedAddr +/// OptionalAddrSpace OptionalExternallyInitialized GlobalType Type +/// Const OptionalAttrs +/// +/// Everything up to and including OptionalUnnamedAddr has been parsed +/// already. +/// bool LLParser::parseGlobal(const std::string &Name, LocTy NameLoc, - unsigned Linkage, bool HasLinkage, - unsigned Visibility, unsigned DLLStorageClass, - bool DSOLocal, GlobalVariable::ThreadLocalMode TLM, - GlobalVariable::UnnamedAddr UnnamedAddr) { - if (!isValidVisibilityForLinkage(Visibility, Linkage)) + unsigned Linkage, bool HasLinkage, + unsigned Visibility, unsigned DLLStorageClass, + bool DSOLocal, GlobalVariable::ThreadLocalMode TLM, + GlobalVariable::UnnamedAddr UnnamedAddr) { + if (!isValidVisibilityForLinkage(Visibility, Linkage)) return error(NameLoc, - "symbol with local linkage must have default visibility"); - - unsigned AddrSpace; - bool IsConstant, IsExternallyInitialized; - LocTy IsExternallyInitializedLoc; - LocTy TyLoc; - - Type *Ty = nullptr; + "symbol with local linkage must have default visibility"); + + unsigned AddrSpace; + bool IsConstant, IsExternallyInitialized; + LocTy IsExternallyInitializedLoc; + LocTy TyLoc; + + Type *Ty = nullptr; if (parseOptionalAddrSpace(AddrSpace) || parseOptionalToken(lltok::kw_externally_initialized, - IsExternallyInitialized, - &IsExternallyInitializedLoc) || + IsExternallyInitialized, + &IsExternallyInitializedLoc) || parseGlobalType(IsConstant) || parseType(Ty, TyLoc)) - return true; - - // If the linkage is specified and is external, then no initializer is - // present. - Constant *Init = nullptr; - if (!HasLinkage || - !GlobalValue::isValidDeclarationLinkage( - (GlobalValue::LinkageTypes)Linkage)) { + return true; + + // If the linkage is specified and is external, then no initializer is + // present. + Constant *Init = nullptr; + if (!HasLinkage || + !GlobalValue::isValidDeclarationLinkage( + (GlobalValue::LinkageTypes)Linkage)) { if (parseGlobalValue(Ty, Init)) - return true; - } - - if (Ty->isFunctionTy() || !PointerType::isValidElementType(Ty)) + return true; + } + + if (Ty->isFunctionTy() || !PointerType::isValidElementType(Ty)) return error(TyLoc, "invalid type for global variable"); - - GlobalValue *GVal = nullptr; - - // See if the global was forward referenced, if so, use the global. - if (!Name.empty()) { - GVal = M->getNamedValue(Name); - if (GVal) { - if (!ForwardRefVals.erase(Name)) + + GlobalValue *GVal = nullptr; + + // See if the global was forward referenced, if so, use the global. + if (!Name.empty()) { + GVal = M->getNamedValue(Name); + if (GVal) { + if (!ForwardRefVals.erase(Name)) return error(NameLoc, "redefinition of global '@" + Name + "'"); - } - } else { - auto I = ForwardRefValIDs.find(NumberedVals.size()); - if (I != ForwardRefValIDs.end()) { - GVal = I->second.first; - ForwardRefValIDs.erase(I); - } - } - - GlobalVariable *GV; - if (!GVal) { - GV = new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage, nullptr, - Name, nullptr, GlobalVariable::NotThreadLocal, - AddrSpace); - } else { - if (GVal->getValueType() != Ty) + } + } else { + auto I = ForwardRefValIDs.find(NumberedVals.size()); + if (I != ForwardRefValIDs.end()) { + GVal = I->second.first; + ForwardRefValIDs.erase(I); + } + } + + GlobalVariable *GV; + if (!GVal) { + GV = new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage, nullptr, + Name, nullptr, GlobalVariable::NotThreadLocal, + AddrSpace); + } else { + if (GVal->getValueType() != Ty) return error( TyLoc, "forward reference and definition of global have different types"); - - GV = cast<GlobalVariable>(GVal); - - // Move the forward-reference to the correct spot in the module. - M->getGlobalList().splice(M->global_end(), M->getGlobalList(), GV); - } - - if (Name.empty()) - NumberedVals.push_back(GV); - - // Set the parsed properties on the global. - if (Init) - GV->setInitializer(Init); - GV->setConstant(IsConstant); - GV->setLinkage((GlobalValue::LinkageTypes)Linkage); - maybeSetDSOLocal(DSOLocal, *GV); - GV->setVisibility((GlobalValue::VisibilityTypes)Visibility); - GV->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); - GV->setExternallyInitialized(IsExternallyInitialized); - GV->setThreadLocalMode(TLM); - GV->setUnnamedAddr(UnnamedAddr); - + + GV = cast<GlobalVariable>(GVal); + + // Move the forward-reference to the correct spot in the module. + M->getGlobalList().splice(M->global_end(), M->getGlobalList(), GV); + } + + if (Name.empty()) + NumberedVals.push_back(GV); + + // Set the parsed properties on the global. + if (Init) + GV->setInitializer(Init); + GV->setConstant(IsConstant); + GV->setLinkage((GlobalValue::LinkageTypes)Linkage); + maybeSetDSOLocal(DSOLocal, *GV); + GV->setVisibility((GlobalValue::VisibilityTypes)Visibility); + GV->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); + GV->setExternallyInitialized(IsExternallyInitialized); + GV->setThreadLocalMode(TLM); + GV->setUnnamedAddr(UnnamedAddr); + // parse attributes on the global. - while (Lex.getKind() == lltok::comma) { - Lex.Lex(); - - if (Lex.getKind() == lltok::kw_section) { - Lex.Lex(); - GV->setSection(Lex.getStrVal()); + while (Lex.getKind() == lltok::comma) { + Lex.Lex(); + + if (Lex.getKind() == lltok::kw_section) { + Lex.Lex(); + GV->setSection(Lex.getStrVal()); if (parseToken(lltok::StringConstant, "expected global section string")) - return true; - } else if (Lex.getKind() == lltok::kw_partition) { - Lex.Lex(); - GV->setPartition(Lex.getStrVal()); + return true; + } else if (Lex.getKind() == lltok::kw_partition) { + Lex.Lex(); + GV->setPartition(Lex.getStrVal()); if (parseToken(lltok::StringConstant, "expected partition string")) - return true; - } else if (Lex.getKind() == lltok::kw_align) { - MaybeAlign Alignment; + return true; + } else if (Lex.getKind() == lltok::kw_align) { + MaybeAlign Alignment; if (parseOptionalAlignment(Alignment)) return true; - GV->setAlignment(Alignment); - } else if (Lex.getKind() == lltok::MetadataVar) { + GV->setAlignment(Alignment); + } else if (Lex.getKind() == lltok::MetadataVar) { if (parseGlobalObjectMetadataAttachment(*GV)) - return true; - } else { - Comdat *C; - if (parseOptionalComdat(Name, C)) - return true; - if (C) - GV->setComdat(C); - else + return true; + } else { + Comdat *C; + if (parseOptionalComdat(Name, C)) + return true; + if (C) + GV->setComdat(C); + else return tokError("unknown global variable property!"); - } - } - - AttrBuilder Attrs; - LocTy BuiltinLoc; - std::vector<unsigned> FwdRefAttrGrps; + } + } + + AttrBuilder Attrs; + LocTy BuiltinLoc; + std::vector<unsigned> FwdRefAttrGrps; if (parseFnAttributeValuePairs(Attrs, FwdRefAttrGrps, false, BuiltinLoc)) - return true; - if (Attrs.hasAttributes() || !FwdRefAttrGrps.empty()) { - GV->setAttributes(AttributeSet::get(Context, Attrs)); - ForwardRefAttrGroups[GV] = FwdRefAttrGrps; - } - - return false; -} - + return true; + if (Attrs.hasAttributes() || !FwdRefAttrGrps.empty()) { + GV->setAttributes(AttributeSet::get(Context, Attrs)); + ForwardRefAttrGroups[GV] = FwdRefAttrGrps; + } + + return false; +} + /// parseUnnamedAttrGrp -/// ::= 'attributes' AttrGrpID '=' '{' AttrValPair+ '}' +/// ::= 'attributes' AttrGrpID '=' '{' AttrValPair+ '}' bool LLParser::parseUnnamedAttrGrp() { - assert(Lex.getKind() == lltok::kw_attributes); - LocTy AttrGrpLoc = Lex.getLoc(); - Lex.Lex(); - - if (Lex.getKind() != lltok::AttrGrpID) + assert(Lex.getKind() == lltok::kw_attributes); + LocTy AttrGrpLoc = Lex.getLoc(); + Lex.Lex(); + + if (Lex.getKind() != lltok::AttrGrpID) return tokError("expected attribute group id"); - - unsigned VarID = Lex.getUIntVal(); - std::vector<unsigned> unused; - LocTy BuiltinLoc; - Lex.Lex(); - + + unsigned VarID = Lex.getUIntVal(); + std::vector<unsigned> unused; + LocTy BuiltinLoc; + Lex.Lex(); + if (parseToken(lltok::equal, "expected '=' here") || parseToken(lltok::lbrace, "expected '{' here") || parseFnAttributeValuePairs(NumberedAttrBuilders[VarID], unused, true, - BuiltinLoc) || + BuiltinLoc) || parseToken(lltok::rbrace, "expected end of attribute group")) - return true; - - if (!NumberedAttrBuilders[VarID].hasAttributes()) + return true; + + if (!NumberedAttrBuilders[VarID].hasAttributes()) return error(AttrGrpLoc, "attribute group has no attributes"); - - return false; -} - + + return false; +} + /// parseFnAttributeValuePairs -/// ::= <attr> | <attr> '=' <value> +/// ::= <attr> | <attr> '=' <value> bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B, - std::vector<unsigned> &FwdRefAttrGrps, - bool inAttrGrp, LocTy &BuiltinLoc) { - bool HaveError = false; - - B.clear(); - - while (true) { - lltok::Kind Token = Lex.getKind(); - if (Token == lltok::kw_builtin) - BuiltinLoc = Lex.getLoc(); - switch (Token) { - default: - if (!inAttrGrp) return HaveError; + std::vector<unsigned> &FwdRefAttrGrps, + bool inAttrGrp, LocTy &BuiltinLoc) { + bool HaveError = false; + + B.clear(); + + while (true) { + lltok::Kind Token = Lex.getKind(); + if (Token == lltok::kw_builtin) + BuiltinLoc = Lex.getLoc(); + switch (Token) { + default: + if (!inAttrGrp) return HaveError; return error(Lex.getLoc(), "unterminated attribute group"); - case lltok::rbrace: - // Finished. - return false; - - case lltok::AttrGrpID: { - // Allow a function to reference an attribute group: - // - // define void @foo() #1 { ... } - if (inAttrGrp) + case lltok::rbrace: + // Finished. + return false; + + case lltok::AttrGrpID: { + // Allow a function to reference an attribute group: + // + // define void @foo() #1 { ... } + if (inAttrGrp) HaveError |= error( Lex.getLoc(), "cannot have an attribute group reference in an attribute group"); - - unsigned AttrGrpNum = Lex.getUIntVal(); - if (inAttrGrp) break; - - // Save the reference to the attribute group. We'll fill it in later. - FwdRefAttrGrps.push_back(AttrGrpNum); - break; - } - // Target-dependent attributes: - case lltok::StringConstant: { + + unsigned AttrGrpNum = Lex.getUIntVal(); + if (inAttrGrp) break; + + // Save the reference to the attribute group. We'll fill it in later. + FwdRefAttrGrps.push_back(AttrGrpNum); + break; + } + // Target-dependent attributes: + case lltok::StringConstant: { if (parseStringAttribute(B)) - return true; - continue; - } - - // Target-independent attributes: - case lltok::kw_align: { - // As a hack, we allow function alignment to be initially parsed as an - // attribute on a function declaration/definition or added to an attribute - // group and later moved to the alignment field. - MaybeAlign Alignment; - if (inAttrGrp) { - Lex.Lex(); - uint32_t Value = 0; + return true; + continue; + } + + // Target-independent attributes: + case lltok::kw_align: { + // As a hack, we allow function alignment to be initially parsed as an + // attribute on a function declaration/definition or added to an attribute + // group and later moved to the alignment field. + MaybeAlign Alignment; + if (inAttrGrp) { + Lex.Lex(); + uint32_t Value = 0; if (parseToken(lltok::equal, "expected '=' here") || parseUInt32(Value)) - return true; - Alignment = Align(Value); - } else { + return true; + Alignment = Align(Value); + } else { if (parseOptionalAlignment(Alignment)) - return true; - } - B.addAlignmentAttr(Alignment); - continue; - } - case lltok::kw_alignstack: { - unsigned Alignment; - if (inAttrGrp) { - Lex.Lex(); + return true; + } + B.addAlignmentAttr(Alignment); + continue; + } + case lltok::kw_alignstack: { + unsigned Alignment; + if (inAttrGrp) { + Lex.Lex(); if (parseToken(lltok::equal, "expected '=' here") || parseUInt32(Alignment)) - return true; - } else { + return true; + } else { if (parseOptionalStackAlignment(Alignment)) - return true; - } - B.addStackAlignmentAttr(Alignment); - continue; - } - case lltok::kw_allocsize: { - unsigned ElemSizeArg; - Optional<unsigned> NumElemsArg; - // inAttrGrp doesn't matter; we only support allocsize(a[, b]) - if (parseAllocSizeArguments(ElemSizeArg, NumElemsArg)) - return true; - B.addAllocSizeAttr(ElemSizeArg, NumElemsArg); - continue; - } - case lltok::kw_alwaysinline: B.addAttribute(Attribute::AlwaysInline); break; - case lltok::kw_argmemonly: B.addAttribute(Attribute::ArgMemOnly); break; - case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break; - case lltok::kw_cold: B.addAttribute(Attribute::Cold); break; + return true; + } + B.addStackAlignmentAttr(Alignment); + continue; + } + case lltok::kw_allocsize: { + unsigned ElemSizeArg; + Optional<unsigned> NumElemsArg; + // inAttrGrp doesn't matter; we only support allocsize(a[, b]) + if (parseAllocSizeArguments(ElemSizeArg, NumElemsArg)) + return true; + B.addAllocSizeAttr(ElemSizeArg, NumElemsArg); + continue; + } + case lltok::kw_alwaysinline: B.addAttribute(Attribute::AlwaysInline); break; + case lltok::kw_argmemonly: B.addAttribute(Attribute::ArgMemOnly); break; + case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break; + case lltok::kw_cold: B.addAttribute(Attribute::Cold); break; case lltok::kw_hot: B.addAttribute(Attribute::Hot); break; - case lltok::kw_convergent: B.addAttribute(Attribute::Convergent); break; - case lltok::kw_inaccessiblememonly: - B.addAttribute(Attribute::InaccessibleMemOnly); break; - case lltok::kw_inaccessiblemem_or_argmemonly: - B.addAttribute(Attribute::InaccessibleMemOrArgMemOnly); break; - case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break; - case lltok::kw_jumptable: B.addAttribute(Attribute::JumpTable); break; - case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break; + case lltok::kw_convergent: B.addAttribute(Attribute::Convergent); break; + case lltok::kw_inaccessiblememonly: + B.addAttribute(Attribute::InaccessibleMemOnly); break; + case lltok::kw_inaccessiblemem_or_argmemonly: + B.addAttribute(Attribute::InaccessibleMemOrArgMemOnly); break; + case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break; + case lltok::kw_jumptable: B.addAttribute(Attribute::JumpTable); break; + case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break; case lltok::kw_mustprogress: B.addAttribute(Attribute::MustProgress); break; - case lltok::kw_naked: B.addAttribute(Attribute::Naked); break; - case lltok::kw_nobuiltin: B.addAttribute(Attribute::NoBuiltin); break; + case lltok::kw_naked: B.addAttribute(Attribute::Naked); break; + case lltok::kw_nobuiltin: B.addAttribute(Attribute::NoBuiltin); break; case lltok::kw_nocallback: B.addAttribute(Attribute::NoCallback); break; - case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); break; - case lltok::kw_nofree: B.addAttribute(Attribute::NoFree); break; - case lltok::kw_noimplicitfloat: - B.addAttribute(Attribute::NoImplicitFloat); break; - case lltok::kw_noinline: B.addAttribute(Attribute::NoInline); break; - case lltok::kw_nonlazybind: B.addAttribute(Attribute::NonLazyBind); break; - case lltok::kw_nomerge: B.addAttribute(Attribute::NoMerge); break; - case lltok::kw_noredzone: B.addAttribute(Attribute::NoRedZone); break; - case lltok::kw_noreturn: B.addAttribute(Attribute::NoReturn); break; - case lltok::kw_nosync: B.addAttribute(Attribute::NoSync); break; - case lltok::kw_nocf_check: B.addAttribute(Attribute::NoCfCheck); break; + case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); break; + case lltok::kw_nofree: B.addAttribute(Attribute::NoFree); break; + case lltok::kw_noimplicitfloat: + B.addAttribute(Attribute::NoImplicitFloat); break; + case lltok::kw_noinline: B.addAttribute(Attribute::NoInline); break; + case lltok::kw_nonlazybind: B.addAttribute(Attribute::NonLazyBind); break; + case lltok::kw_nomerge: B.addAttribute(Attribute::NoMerge); break; + case lltok::kw_noredzone: B.addAttribute(Attribute::NoRedZone); break; + case lltok::kw_noreturn: B.addAttribute(Attribute::NoReturn); break; + case lltok::kw_nosync: B.addAttribute(Attribute::NoSync); break; + case lltok::kw_nocf_check: B.addAttribute(Attribute::NoCfCheck); break; case lltok::kw_noprofile: B.addAttribute(Attribute::NoProfile); break; - case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break; - case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break; - case lltok::kw_null_pointer_is_valid: - B.addAttribute(Attribute::NullPointerIsValid); break; - case lltok::kw_optforfuzzing: - B.addAttribute(Attribute::OptForFuzzing); break; - case lltok::kw_optnone: B.addAttribute(Attribute::OptimizeNone); break; - case lltok::kw_optsize: B.addAttribute(Attribute::OptimizeForSize); break; - case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break; - case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break; - case lltok::kw_returns_twice: - B.addAttribute(Attribute::ReturnsTwice); break; - case lltok::kw_speculatable: B.addAttribute(Attribute::Speculatable); break; - case lltok::kw_ssp: B.addAttribute(Attribute::StackProtect); break; - case lltok::kw_sspreq: B.addAttribute(Attribute::StackProtectReq); break; - case lltok::kw_sspstrong: - B.addAttribute(Attribute::StackProtectStrong); break; - case lltok::kw_safestack: B.addAttribute(Attribute::SafeStack); break; - case lltok::kw_shadowcallstack: - B.addAttribute(Attribute::ShadowCallStack); break; - case lltok::kw_sanitize_address: - B.addAttribute(Attribute::SanitizeAddress); break; - case lltok::kw_sanitize_hwaddress: - B.addAttribute(Attribute::SanitizeHWAddress); break; - case lltok::kw_sanitize_memtag: - B.addAttribute(Attribute::SanitizeMemTag); break; - case lltok::kw_sanitize_thread: - B.addAttribute(Attribute::SanitizeThread); break; - case lltok::kw_sanitize_memory: - B.addAttribute(Attribute::SanitizeMemory); break; - case lltok::kw_speculative_load_hardening: - B.addAttribute(Attribute::SpeculativeLoadHardening); - break; - case lltok::kw_strictfp: B.addAttribute(Attribute::StrictFP); break; - case lltok::kw_uwtable: B.addAttribute(Attribute::UWTable); break; - case lltok::kw_willreturn: B.addAttribute(Attribute::WillReturn); break; - case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break; - case lltok::kw_preallocated: { - Type *Ty; + case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break; + case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break; + case lltok::kw_null_pointer_is_valid: + B.addAttribute(Attribute::NullPointerIsValid); break; + case lltok::kw_optforfuzzing: + B.addAttribute(Attribute::OptForFuzzing); break; + case lltok::kw_optnone: B.addAttribute(Attribute::OptimizeNone); break; + case lltok::kw_optsize: B.addAttribute(Attribute::OptimizeForSize); break; + case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break; + case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break; + case lltok::kw_returns_twice: + B.addAttribute(Attribute::ReturnsTwice); break; + case lltok::kw_speculatable: B.addAttribute(Attribute::Speculatable); break; + case lltok::kw_ssp: B.addAttribute(Attribute::StackProtect); break; + case lltok::kw_sspreq: B.addAttribute(Attribute::StackProtectReq); break; + case lltok::kw_sspstrong: + B.addAttribute(Attribute::StackProtectStrong); break; + case lltok::kw_safestack: B.addAttribute(Attribute::SafeStack); break; + case lltok::kw_shadowcallstack: + B.addAttribute(Attribute::ShadowCallStack); break; + case lltok::kw_sanitize_address: + B.addAttribute(Attribute::SanitizeAddress); break; + case lltok::kw_sanitize_hwaddress: + B.addAttribute(Attribute::SanitizeHWAddress); break; + case lltok::kw_sanitize_memtag: + B.addAttribute(Attribute::SanitizeMemTag); break; + case lltok::kw_sanitize_thread: + B.addAttribute(Attribute::SanitizeThread); break; + case lltok::kw_sanitize_memory: + B.addAttribute(Attribute::SanitizeMemory); break; + case lltok::kw_speculative_load_hardening: + B.addAttribute(Attribute::SpeculativeLoadHardening); + break; + case lltok::kw_strictfp: B.addAttribute(Attribute::StrictFP); break; + case lltok::kw_uwtable: B.addAttribute(Attribute::UWTable); break; + case lltok::kw_willreturn: B.addAttribute(Attribute::WillReturn); break; + case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break; + case lltok::kw_preallocated: { + Type *Ty; if (parsePreallocated(Ty)) - return true; - B.addPreallocatedAttr(Ty); - break; - } - + return true; + B.addPreallocatedAttr(Ty); + break; + } + // error handling. - case lltok::kw_inreg: - case lltok::kw_signext: - case lltok::kw_zeroext: - HaveError |= + case lltok::kw_inreg: + case lltok::kw_signext: + case lltok::kw_zeroext: + HaveError |= error(Lex.getLoc(), "invalid use of attribute on a function"); - break; - case lltok::kw_byval: - case lltok::kw_dereferenceable: - case lltok::kw_dereferenceable_or_null: - case lltok::kw_inalloca: - case lltok::kw_nest: - case lltok::kw_noalias: - case lltok::kw_noundef: - case lltok::kw_nocapture: - case lltok::kw_nonnull: - case lltok::kw_returned: - case lltok::kw_sret: - case lltok::kw_swifterror: - case lltok::kw_swiftself: - case lltok::kw_immarg: + break; + case lltok::kw_byval: + case lltok::kw_dereferenceable: + case lltok::kw_dereferenceable_or_null: + case lltok::kw_inalloca: + case lltok::kw_nest: + case lltok::kw_noalias: + case lltok::kw_noundef: + case lltok::kw_nocapture: + case lltok::kw_nonnull: + case lltok::kw_returned: + case lltok::kw_sret: + case lltok::kw_swifterror: + case lltok::kw_swiftself: + case lltok::kw_immarg: case lltok::kw_byref: - HaveError |= + HaveError |= error(Lex.getLoc(), "invalid use of parameter-only attribute on a function"); - break; - } - + break; + } + // parsePreallocated() consumes token - if (Token != lltok::kw_preallocated) - Lex.Lex(); - } -} - -//===----------------------------------------------------------------------===// -// GlobalValue Reference/Resolution Routines. -//===----------------------------------------------------------------------===// - -static inline GlobalValue *createGlobalFwdRef(Module *M, PointerType *PTy, - const std::string &Name) { - if (auto *FT = dyn_cast<FunctionType>(PTy->getElementType())) - return Function::Create(FT, GlobalValue::ExternalWeakLinkage, - PTy->getAddressSpace(), Name, M); - else - return new GlobalVariable(*M, PTy->getElementType(), false, - GlobalValue::ExternalWeakLinkage, nullptr, Name, - nullptr, GlobalVariable::NotThreadLocal, - PTy->getAddressSpace()); -} - -Value *LLParser::checkValidVariableType(LocTy Loc, const Twine &Name, Type *Ty, - Value *Val, bool IsCall) { - if (Val->getType() == Ty) - return Val; - // For calls we also accept variables in the program address space. - Type *SuggestedTy = Ty; - if (IsCall && isa<PointerType>(Ty)) { - Type *TyInProgAS = cast<PointerType>(Ty)->getElementType()->getPointerTo( - M->getDataLayout().getProgramAddressSpace()); - SuggestedTy = TyInProgAS; - if (Val->getType() == TyInProgAS) - return Val; - } - if (Ty->isLabelTy()) + if (Token != lltok::kw_preallocated) + Lex.Lex(); + } +} + +//===----------------------------------------------------------------------===// +// GlobalValue Reference/Resolution Routines. +//===----------------------------------------------------------------------===// + +static inline GlobalValue *createGlobalFwdRef(Module *M, PointerType *PTy, + const std::string &Name) { + if (auto *FT = dyn_cast<FunctionType>(PTy->getElementType())) + return Function::Create(FT, GlobalValue::ExternalWeakLinkage, + PTy->getAddressSpace(), Name, M); + else + return new GlobalVariable(*M, PTy->getElementType(), false, + GlobalValue::ExternalWeakLinkage, nullptr, Name, + nullptr, GlobalVariable::NotThreadLocal, + PTy->getAddressSpace()); +} + +Value *LLParser::checkValidVariableType(LocTy Loc, const Twine &Name, Type *Ty, + Value *Val, bool IsCall) { + if (Val->getType() == Ty) + return Val; + // For calls we also accept variables in the program address space. + Type *SuggestedTy = Ty; + if (IsCall && isa<PointerType>(Ty)) { + Type *TyInProgAS = cast<PointerType>(Ty)->getElementType()->getPointerTo( + M->getDataLayout().getProgramAddressSpace()); + SuggestedTy = TyInProgAS; + if (Val->getType() == TyInProgAS) + return Val; + } + if (Ty->isLabelTy()) error(Loc, "'" + Name + "' is not a basic block"); - else + else error(Loc, "'" + Name + "' defined with type '" + - getTypeString(Val->getType()) + "' but expected '" + - getTypeString(SuggestedTy) + "'"); - return nullptr; -} - + getTypeString(Val->getType()) + "' but expected '" + + getTypeString(SuggestedTy) + "'"); + return nullptr; +} + /// getGlobalVal - Get a value with the specified name or ID, creating a -/// forward reference record if needed. This can return null if the value -/// exists but does not have the right type. +/// forward reference record if needed. This can return null if the value +/// exists but does not have the right type. GlobalValue *LLParser::getGlobalVal(const std::string &Name, Type *Ty, - LocTy Loc, bool IsCall) { - PointerType *PTy = dyn_cast<PointerType>(Ty); - if (!PTy) { + LocTy Loc, bool IsCall) { + PointerType *PTy = dyn_cast<PointerType>(Ty); + if (!PTy) { error(Loc, "global variable reference must have pointer type"); - return nullptr; - } - - // Look this name up in the normal function symbol table. - GlobalValue *Val = - cast_or_null<GlobalValue>(M->getValueSymbolTable().lookup(Name)); - - // If this is a forward reference for the value, see if we already created a - // forward ref record. - if (!Val) { - auto I = ForwardRefVals.find(Name); - if (I != ForwardRefVals.end()) - Val = I->second.first; - } - - // If we have the value in the symbol table or fwd-ref table, return it. - if (Val) - return cast_or_null<GlobalValue>( - checkValidVariableType(Loc, "@" + Name, Ty, Val, IsCall)); - - // Otherwise, create a new forward reference for this value and remember it. - GlobalValue *FwdVal = createGlobalFwdRef(M, PTy, Name); - ForwardRefVals[Name] = std::make_pair(FwdVal, Loc); - return FwdVal; -} - + return nullptr; + } + + // Look this name up in the normal function symbol table. + GlobalValue *Val = + cast_or_null<GlobalValue>(M->getValueSymbolTable().lookup(Name)); + + // If this is a forward reference for the value, see if we already created a + // forward ref record. + if (!Val) { + auto I = ForwardRefVals.find(Name); + if (I != ForwardRefVals.end()) + Val = I->second.first; + } + + // If we have the value in the symbol table or fwd-ref table, return it. + if (Val) + return cast_or_null<GlobalValue>( + checkValidVariableType(Loc, "@" + Name, Ty, Val, IsCall)); + + // Otherwise, create a new forward reference for this value and remember it. + GlobalValue *FwdVal = createGlobalFwdRef(M, PTy, Name); + ForwardRefVals[Name] = std::make_pair(FwdVal, Loc); + return FwdVal; +} + GlobalValue *LLParser::getGlobalVal(unsigned ID, Type *Ty, LocTy Loc, - bool IsCall) { - PointerType *PTy = dyn_cast<PointerType>(Ty); - if (!PTy) { + bool IsCall) { + PointerType *PTy = dyn_cast<PointerType>(Ty); + if (!PTy) { error(Loc, "global variable reference must have pointer type"); - return nullptr; - } - - GlobalValue *Val = ID < NumberedVals.size() ? NumberedVals[ID] : nullptr; - - // If this is a forward reference for the value, see if we already created a - // forward ref record. - if (!Val) { - auto I = ForwardRefValIDs.find(ID); - if (I != ForwardRefValIDs.end()) - Val = I->second.first; - } - - // If we have the value in the symbol table or fwd-ref table, return it. - if (Val) - return cast_or_null<GlobalValue>( - checkValidVariableType(Loc, "@" + Twine(ID), Ty, Val, IsCall)); - - // Otherwise, create a new forward reference for this value and remember it. - GlobalValue *FwdVal = createGlobalFwdRef(M, PTy, ""); - ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc); - return FwdVal; -} - -//===----------------------------------------------------------------------===// -// Comdat Reference/Resolution Routines. -//===----------------------------------------------------------------------===// - -Comdat *LLParser::getComdat(const std::string &Name, LocTy Loc) { - // Look this name up in the comdat symbol table. - Module::ComdatSymTabType &ComdatSymTab = M->getComdatSymbolTable(); - Module::ComdatSymTabType::iterator I = ComdatSymTab.find(Name); - if (I != ComdatSymTab.end()) - return &I->second; - - // Otherwise, create a new forward reference for this value and remember it. - Comdat *C = M->getOrInsertComdat(Name); - ForwardRefComdats[Name] = Loc; - return C; -} - -//===----------------------------------------------------------------------===// -// Helper Routines. -//===----------------------------------------------------------------------===// - + return nullptr; + } + + GlobalValue *Val = ID < NumberedVals.size() ? NumberedVals[ID] : nullptr; + + // If this is a forward reference for the value, see if we already created a + // forward ref record. + if (!Val) { + auto I = ForwardRefValIDs.find(ID); + if (I != ForwardRefValIDs.end()) + Val = I->second.first; + } + + // If we have the value in the symbol table or fwd-ref table, return it. + if (Val) + return cast_or_null<GlobalValue>( + checkValidVariableType(Loc, "@" + Twine(ID), Ty, Val, IsCall)); + + // Otherwise, create a new forward reference for this value and remember it. + GlobalValue *FwdVal = createGlobalFwdRef(M, PTy, ""); + ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc); + return FwdVal; +} + +//===----------------------------------------------------------------------===// +// Comdat Reference/Resolution Routines. +//===----------------------------------------------------------------------===// + +Comdat *LLParser::getComdat(const std::string &Name, LocTy Loc) { + // Look this name up in the comdat symbol table. + Module::ComdatSymTabType &ComdatSymTab = M->getComdatSymbolTable(); + Module::ComdatSymTabType::iterator I = ComdatSymTab.find(Name); + if (I != ComdatSymTab.end()) + return &I->second; + + // Otherwise, create a new forward reference for this value and remember it. + Comdat *C = M->getOrInsertComdat(Name); + ForwardRefComdats[Name] = Loc; + return C; +} + +//===----------------------------------------------------------------------===// +// Helper Routines. +//===----------------------------------------------------------------------===// + /// parseToken - If the current token has the specified kind, eat it and return -/// success. Otherwise, emit the specified error and return failure. +/// success. Otherwise, emit the specified error and return failure. bool LLParser::parseToken(lltok::Kind T, const char *ErrMsg) { - if (Lex.getKind() != T) + if (Lex.getKind() != T) return tokError(ErrMsg); - Lex.Lex(); - return false; -} - + Lex.Lex(); + return false; +} + /// parseStringConstant -/// ::= StringConstant +/// ::= StringConstant bool LLParser::parseStringConstant(std::string &Result) { - if (Lex.getKind() != lltok::StringConstant) + if (Lex.getKind() != lltok::StringConstant) return tokError("expected string constant"); - Result = Lex.getStrVal(); - Lex.Lex(); - return false; -} - + Result = Lex.getStrVal(); + Lex.Lex(); + return false; +} + /// parseUInt32 -/// ::= uint32 +/// ::= uint32 bool LLParser::parseUInt32(uint32_t &Val) { - if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) return tokError("expected integer"); - uint64_t Val64 = Lex.getAPSIntVal().getLimitedValue(0xFFFFFFFFULL+1); - if (Val64 != unsigned(Val64)) + uint64_t Val64 = Lex.getAPSIntVal().getLimitedValue(0xFFFFFFFFULL+1); + if (Val64 != unsigned(Val64)) return tokError("expected 32-bit integer (too large)"); - Val = Val64; - Lex.Lex(); - return false; -} - + Val = Val64; + Lex.Lex(); + return false; +} + /// parseUInt64 -/// ::= uint64 +/// ::= uint64 bool LLParser::parseUInt64(uint64_t &Val) { - if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) return tokError("expected integer"); - Val = Lex.getAPSIntVal().getLimitedValue(); - Lex.Lex(); - return false; -} - + Val = Lex.getAPSIntVal().getLimitedValue(); + Lex.Lex(); + return false; +} + /// parseTLSModel -/// := 'localdynamic' -/// := 'initialexec' -/// := 'localexec' +/// := 'localdynamic' +/// := 'initialexec' +/// := 'localexec' bool LLParser::parseTLSModel(GlobalVariable::ThreadLocalMode &TLM) { - switch (Lex.getKind()) { - default: + switch (Lex.getKind()) { + default: return tokError("expected localdynamic, initialexec or localexec"); - case lltok::kw_localdynamic: - TLM = GlobalVariable::LocalDynamicTLSModel; - break; - case lltok::kw_initialexec: - TLM = GlobalVariable::InitialExecTLSModel; - break; - case lltok::kw_localexec: - TLM = GlobalVariable::LocalExecTLSModel; - break; - } - - Lex.Lex(); - return false; -} - + case lltok::kw_localdynamic: + TLM = GlobalVariable::LocalDynamicTLSModel; + break; + case lltok::kw_initialexec: + TLM = GlobalVariable::InitialExecTLSModel; + break; + case lltok::kw_localexec: + TLM = GlobalVariable::LocalExecTLSModel; + break; + } + + Lex.Lex(); + return false; +} + /// parseOptionalThreadLocal -/// := /*empty*/ -/// := 'thread_local' -/// := 'thread_local' '(' tlsmodel ')' +/// := /*empty*/ +/// := 'thread_local' +/// := 'thread_local' '(' tlsmodel ')' bool LLParser::parseOptionalThreadLocal(GlobalVariable::ThreadLocalMode &TLM) { - TLM = GlobalVariable::NotThreadLocal; - if (!EatIfPresent(lltok::kw_thread_local)) - return false; - - TLM = GlobalVariable::GeneralDynamicTLSModel; - if (Lex.getKind() == lltok::lparen) { - Lex.Lex(); + TLM = GlobalVariable::NotThreadLocal; + if (!EatIfPresent(lltok::kw_thread_local)) + return false; + + TLM = GlobalVariable::GeneralDynamicTLSModel; + if (Lex.getKind() == lltok::lparen) { + Lex.Lex(); return parseTLSModel(TLM) || parseToken(lltok::rparen, "expected ')' after thread local model"); - } - return false; -} - + } + return false; +} + /// parseOptionalAddrSpace -/// := /*empty*/ -/// := 'addrspace' '(' uint32 ')' +/// := /*empty*/ +/// := 'addrspace' '(' uint32 ')' bool LLParser::parseOptionalAddrSpace(unsigned &AddrSpace, unsigned DefaultAS) { - AddrSpace = DefaultAS; - if (!EatIfPresent(lltok::kw_addrspace)) - return false; + AddrSpace = DefaultAS; + if (!EatIfPresent(lltok::kw_addrspace)) + return false; return parseToken(lltok::lparen, "expected '(' in address space") || parseUInt32(AddrSpace) || parseToken(lltok::rparen, "expected ')' in address space"); -} - +} + /// parseStringAttribute -/// := StringConstant -/// := StringConstant '=' StringConstant +/// := StringConstant +/// := StringConstant '=' StringConstant bool LLParser::parseStringAttribute(AttrBuilder &B) { - std::string Attr = Lex.getStrVal(); - Lex.Lex(); - std::string Val; + std::string Attr = Lex.getStrVal(); + Lex.Lex(); + std::string Val; if (EatIfPresent(lltok::equal) && parseStringConstant(Val)) - return true; - B.addAttribute(Attr, Val); - return false; -} - + return true; + B.addAttribute(Attr, Val); + return false; +} + /// parseOptionalParamAttrs - parse a potentially empty list of parameter /// attributes. bool LLParser::parseOptionalParamAttrs(AttrBuilder &B) { - bool HaveError = false; - - B.clear(); - - while (true) { - lltok::Kind Token = Lex.getKind(); - switch (Token) { - default: // End of attributes. - return HaveError; - case lltok::StringConstant: { + bool HaveError = false; + + B.clear(); + + while (true) { + lltok::Kind Token = Lex.getKind(); + switch (Token) { + default: // End of attributes. + return HaveError; + case lltok::StringConstant: { if (parseStringAttribute(B)) - return true; - continue; - } - case lltok::kw_align: { - MaybeAlign Alignment; + return true; + continue; + } + case lltok::kw_align: { + MaybeAlign Alignment; if (parseOptionalAlignment(Alignment, true)) - return true; - B.addAlignmentAttr(Alignment); - continue; - } - case lltok::kw_byval: { - Type *Ty; + return true; + B.addAlignmentAttr(Alignment); + continue; + } + case lltok::kw_byval: { + Type *Ty; if (parseRequiredTypeAttr(Ty, lltok::kw_byval)) - return true; - B.addByValAttr(Ty); - continue; - } + return true; + B.addByValAttr(Ty); + continue; + } case lltok::kw_sret: { Type *Ty; if (parseRequiredTypeAttr(Ty, lltok::kw_sret)) @@ -1716,27 +1716,27 @@ bool LLParser::parseOptionalParamAttrs(AttrBuilder &B) { B.addStructRetAttr(Ty); continue; } - case lltok::kw_preallocated: { - Type *Ty; + case lltok::kw_preallocated: { + Type *Ty; if (parsePreallocated(Ty)) - return true; - B.addPreallocatedAttr(Ty); - continue; - } - case lltok::kw_dereferenceable: { - uint64_t Bytes; + return true; + B.addPreallocatedAttr(Ty); + continue; + } + case lltok::kw_dereferenceable: { + uint64_t Bytes; if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes)) - return true; - B.addDereferenceableAttr(Bytes); - continue; - } - case lltok::kw_dereferenceable_or_null: { - uint64_t Bytes; + return true; + B.addDereferenceableAttr(Bytes); + continue; + } + case lltok::kw_dereferenceable_or_null: { + uint64_t Bytes; if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes)) - return true; - B.addDereferenceableOrNullAttr(Bytes); - continue; - } + return true; + B.addDereferenceableOrNullAttr(Bytes); + continue; + } case lltok::kw_byref: { Type *Ty; if (parseByRef(Ty)) @@ -1744,918 +1744,918 @@ bool LLParser::parseOptionalParamAttrs(AttrBuilder &B) { B.addByRefAttr(Ty); continue; } - case lltok::kw_inalloca: B.addAttribute(Attribute::InAlloca); break; - case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; - case lltok::kw_nest: B.addAttribute(Attribute::Nest); break; - case lltok::kw_noundef: - B.addAttribute(Attribute::NoUndef); - break; - case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; - case lltok::kw_nocapture: B.addAttribute(Attribute::NoCapture); break; - case lltok::kw_nofree: B.addAttribute(Attribute::NoFree); break; - case lltok::kw_nonnull: B.addAttribute(Attribute::NonNull); break; - case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break; - case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break; - case lltok::kw_returned: B.addAttribute(Attribute::Returned); break; - case lltok::kw_signext: B.addAttribute(Attribute::SExt); break; - case lltok::kw_swifterror: B.addAttribute(Attribute::SwiftError); break; - case lltok::kw_swiftself: B.addAttribute(Attribute::SwiftSelf); break; - case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break; - case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break; - case lltok::kw_immarg: B.addAttribute(Attribute::ImmArg); break; - - case lltok::kw_alignstack: - case lltok::kw_alwaysinline: - case lltok::kw_argmemonly: - case lltok::kw_builtin: - case lltok::kw_inlinehint: - case lltok::kw_jumptable: - case lltok::kw_minsize: + case lltok::kw_inalloca: B.addAttribute(Attribute::InAlloca); break; + case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; + case lltok::kw_nest: B.addAttribute(Attribute::Nest); break; + case lltok::kw_noundef: + B.addAttribute(Attribute::NoUndef); + break; + case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; + case lltok::kw_nocapture: B.addAttribute(Attribute::NoCapture); break; + case lltok::kw_nofree: B.addAttribute(Attribute::NoFree); break; + case lltok::kw_nonnull: B.addAttribute(Attribute::NonNull); break; + case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break; + case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break; + case lltok::kw_returned: B.addAttribute(Attribute::Returned); break; + case lltok::kw_signext: B.addAttribute(Attribute::SExt); break; + case lltok::kw_swifterror: B.addAttribute(Attribute::SwiftError); break; + case lltok::kw_swiftself: B.addAttribute(Attribute::SwiftSelf); break; + case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break; + case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break; + case lltok::kw_immarg: B.addAttribute(Attribute::ImmArg); break; + + case lltok::kw_alignstack: + case lltok::kw_alwaysinline: + case lltok::kw_argmemonly: + case lltok::kw_builtin: + case lltok::kw_inlinehint: + case lltok::kw_jumptable: + case lltok::kw_minsize: case lltok::kw_mustprogress: - case lltok::kw_naked: - case lltok::kw_nobuiltin: - case lltok::kw_noduplicate: - case lltok::kw_noimplicitfloat: - case lltok::kw_noinline: - case lltok::kw_nonlazybind: - case lltok::kw_nomerge: + case lltok::kw_naked: + case lltok::kw_nobuiltin: + case lltok::kw_noduplicate: + case lltok::kw_noimplicitfloat: + case lltok::kw_noinline: + case lltok::kw_nonlazybind: + case lltok::kw_nomerge: case lltok::kw_noprofile: - case lltok::kw_noredzone: - case lltok::kw_noreturn: - case lltok::kw_nocf_check: - case lltok::kw_nounwind: - case lltok::kw_optforfuzzing: - case lltok::kw_optnone: - case lltok::kw_optsize: - case lltok::kw_returns_twice: - case lltok::kw_sanitize_address: - case lltok::kw_sanitize_hwaddress: - case lltok::kw_sanitize_memtag: - case lltok::kw_sanitize_memory: - case lltok::kw_sanitize_thread: - case lltok::kw_speculative_load_hardening: - case lltok::kw_ssp: - case lltok::kw_sspreq: - case lltok::kw_sspstrong: - case lltok::kw_safestack: - case lltok::kw_shadowcallstack: - case lltok::kw_strictfp: - case lltok::kw_uwtable: + case lltok::kw_noredzone: + case lltok::kw_noreturn: + case lltok::kw_nocf_check: + case lltok::kw_nounwind: + case lltok::kw_optforfuzzing: + case lltok::kw_optnone: + case lltok::kw_optsize: + case lltok::kw_returns_twice: + case lltok::kw_sanitize_address: + case lltok::kw_sanitize_hwaddress: + case lltok::kw_sanitize_memtag: + case lltok::kw_sanitize_memory: + case lltok::kw_sanitize_thread: + case lltok::kw_speculative_load_hardening: + case lltok::kw_ssp: + case lltok::kw_sspreq: + case lltok::kw_sspstrong: + case lltok::kw_safestack: + case lltok::kw_shadowcallstack: + case lltok::kw_strictfp: + case lltok::kw_uwtable: HaveError |= error(Lex.getLoc(), "invalid use of function-only attribute"); - break; - } - - Lex.Lex(); - } -} - + break; + } + + Lex.Lex(); + } +} + /// parseOptionalReturnAttrs - parse a potentially empty list of return /// attributes. bool LLParser::parseOptionalReturnAttrs(AttrBuilder &B) { - bool HaveError = false; - - B.clear(); - - while (true) { - lltok::Kind Token = Lex.getKind(); - switch (Token) { - default: // End of attributes. - return HaveError; - case lltok::StringConstant: { + bool HaveError = false; + + B.clear(); + + while (true) { + lltok::Kind Token = Lex.getKind(); + switch (Token) { + default: // End of attributes. + return HaveError; + case lltok::StringConstant: { if (parseStringAttribute(B)) - return true; - continue; - } - case lltok::kw_dereferenceable: { - uint64_t Bytes; + return true; + continue; + } + case lltok::kw_dereferenceable: { + uint64_t Bytes; if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes)) - return true; - B.addDereferenceableAttr(Bytes); - continue; - } - case lltok::kw_dereferenceable_or_null: { - uint64_t Bytes; + return true; + B.addDereferenceableAttr(Bytes); + continue; + } + case lltok::kw_dereferenceable_or_null: { + uint64_t Bytes; if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes)) - return true; - B.addDereferenceableOrNullAttr(Bytes); - continue; - } - case lltok::kw_align: { - MaybeAlign Alignment; + return true; + B.addDereferenceableOrNullAttr(Bytes); + continue; + } + case lltok::kw_align: { + MaybeAlign Alignment; if (parseOptionalAlignment(Alignment)) - return true; - B.addAlignmentAttr(Alignment); - continue; - } - case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; - case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; - case lltok::kw_noundef: - B.addAttribute(Attribute::NoUndef); - break; - case lltok::kw_nonnull: B.addAttribute(Attribute::NonNull); break; - case lltok::kw_signext: B.addAttribute(Attribute::SExt); break; - case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break; - + return true; + B.addAlignmentAttr(Alignment); + continue; + } + case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; + case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; + case lltok::kw_noundef: + B.addAttribute(Attribute::NoUndef); + break; + case lltok::kw_nonnull: B.addAttribute(Attribute::NonNull); break; + case lltok::kw_signext: B.addAttribute(Attribute::SExt); break; + case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break; + // error handling. - case lltok::kw_byval: - case lltok::kw_inalloca: - case lltok::kw_nest: - case lltok::kw_nocapture: - case lltok::kw_returned: - case lltok::kw_sret: - case lltok::kw_swifterror: - case lltok::kw_swiftself: - case lltok::kw_immarg: + case lltok::kw_byval: + case lltok::kw_inalloca: + case lltok::kw_nest: + case lltok::kw_nocapture: + case lltok::kw_returned: + case lltok::kw_sret: + case lltok::kw_swifterror: + case lltok::kw_swiftself: + case lltok::kw_immarg: case lltok::kw_byref: HaveError |= error(Lex.getLoc(), "invalid use of parameter-only attribute"); - break; - - case lltok::kw_alignstack: - case lltok::kw_alwaysinline: - case lltok::kw_argmemonly: - case lltok::kw_builtin: - case lltok::kw_cold: - case lltok::kw_inlinehint: - case lltok::kw_jumptable: - case lltok::kw_minsize: + break; + + case lltok::kw_alignstack: + case lltok::kw_alwaysinline: + case lltok::kw_argmemonly: + case lltok::kw_builtin: + case lltok::kw_cold: + case lltok::kw_inlinehint: + case lltok::kw_jumptable: + case lltok::kw_minsize: case lltok::kw_mustprogress: - case lltok::kw_naked: - case lltok::kw_nobuiltin: - case lltok::kw_noduplicate: - case lltok::kw_noimplicitfloat: - case lltok::kw_noinline: - case lltok::kw_nonlazybind: - case lltok::kw_nomerge: + case lltok::kw_naked: + case lltok::kw_nobuiltin: + case lltok::kw_noduplicate: + case lltok::kw_noimplicitfloat: + case lltok::kw_noinline: + case lltok::kw_nonlazybind: + case lltok::kw_nomerge: case lltok::kw_noprofile: - case lltok::kw_noredzone: - case lltok::kw_noreturn: - case lltok::kw_nocf_check: - case lltok::kw_nounwind: - case lltok::kw_optforfuzzing: - case lltok::kw_optnone: - case lltok::kw_optsize: - case lltok::kw_returns_twice: - case lltok::kw_sanitize_address: - case lltok::kw_sanitize_hwaddress: - case lltok::kw_sanitize_memtag: - case lltok::kw_sanitize_memory: - case lltok::kw_sanitize_thread: - case lltok::kw_speculative_load_hardening: - case lltok::kw_ssp: - case lltok::kw_sspreq: - case lltok::kw_sspstrong: - case lltok::kw_safestack: - case lltok::kw_shadowcallstack: - case lltok::kw_strictfp: - case lltok::kw_uwtable: + case lltok::kw_noredzone: + case lltok::kw_noreturn: + case lltok::kw_nocf_check: + case lltok::kw_nounwind: + case lltok::kw_optforfuzzing: + case lltok::kw_optnone: + case lltok::kw_optsize: + case lltok::kw_returns_twice: + case lltok::kw_sanitize_address: + case lltok::kw_sanitize_hwaddress: + case lltok::kw_sanitize_memtag: + case lltok::kw_sanitize_memory: + case lltok::kw_sanitize_thread: + case lltok::kw_speculative_load_hardening: + case lltok::kw_ssp: + case lltok::kw_sspreq: + case lltok::kw_sspstrong: + case lltok::kw_safestack: + case lltok::kw_shadowcallstack: + case lltok::kw_strictfp: + case lltok::kw_uwtable: HaveError |= error(Lex.getLoc(), "invalid use of function-only attribute"); - break; - case lltok::kw_readnone: - case lltok::kw_readonly: + break; + case lltok::kw_readnone: + case lltok::kw_readonly: HaveError |= error(Lex.getLoc(), "invalid use of attribute on return type"); - break; - case lltok::kw_preallocated: - HaveError |= + break; + case lltok::kw_preallocated: + HaveError |= error(Lex.getLoc(), - "invalid use of parameter-only/call site-only attribute"); - break; - } - - Lex.Lex(); - } -} - -static unsigned parseOptionalLinkageAux(lltok::Kind Kind, bool &HasLinkage) { - HasLinkage = true; - switch (Kind) { - default: - HasLinkage = false; - return GlobalValue::ExternalLinkage; - case lltok::kw_private: - return GlobalValue::PrivateLinkage; - case lltok::kw_internal: - return GlobalValue::InternalLinkage; - case lltok::kw_weak: - return GlobalValue::WeakAnyLinkage; - case lltok::kw_weak_odr: - return GlobalValue::WeakODRLinkage; - case lltok::kw_linkonce: - return GlobalValue::LinkOnceAnyLinkage; - case lltok::kw_linkonce_odr: - return GlobalValue::LinkOnceODRLinkage; - case lltok::kw_available_externally: - return GlobalValue::AvailableExternallyLinkage; - case lltok::kw_appending: - return GlobalValue::AppendingLinkage; - case lltok::kw_common: - return GlobalValue::CommonLinkage; - case lltok::kw_extern_weak: - return GlobalValue::ExternalWeakLinkage; - case lltok::kw_external: - return GlobalValue::ExternalLinkage; - } -} - + "invalid use of parameter-only/call site-only attribute"); + break; + } + + Lex.Lex(); + } +} + +static unsigned parseOptionalLinkageAux(lltok::Kind Kind, bool &HasLinkage) { + HasLinkage = true; + switch (Kind) { + default: + HasLinkage = false; + return GlobalValue::ExternalLinkage; + case lltok::kw_private: + return GlobalValue::PrivateLinkage; + case lltok::kw_internal: + return GlobalValue::InternalLinkage; + case lltok::kw_weak: + return GlobalValue::WeakAnyLinkage; + case lltok::kw_weak_odr: + return GlobalValue::WeakODRLinkage; + case lltok::kw_linkonce: + return GlobalValue::LinkOnceAnyLinkage; + case lltok::kw_linkonce_odr: + return GlobalValue::LinkOnceODRLinkage; + case lltok::kw_available_externally: + return GlobalValue::AvailableExternallyLinkage; + case lltok::kw_appending: + return GlobalValue::AppendingLinkage; + case lltok::kw_common: + return GlobalValue::CommonLinkage; + case lltok::kw_extern_weak: + return GlobalValue::ExternalWeakLinkage; + case lltok::kw_external: + return GlobalValue::ExternalLinkage; + } +} + /// parseOptionalLinkage -/// ::= /*empty*/ -/// ::= 'private' -/// ::= 'internal' -/// ::= 'weak' -/// ::= 'weak_odr' -/// ::= 'linkonce' -/// ::= 'linkonce_odr' -/// ::= 'available_externally' -/// ::= 'appending' -/// ::= 'common' -/// ::= 'extern_weak' -/// ::= 'external' +/// ::= /*empty*/ +/// ::= 'private' +/// ::= 'internal' +/// ::= 'weak' +/// ::= 'weak_odr' +/// ::= 'linkonce' +/// ::= 'linkonce_odr' +/// ::= 'available_externally' +/// ::= 'appending' +/// ::= 'common' +/// ::= 'extern_weak' +/// ::= 'external' bool LLParser::parseOptionalLinkage(unsigned &Res, bool &HasLinkage, - unsigned &Visibility, + unsigned &Visibility, unsigned &DLLStorageClass, bool &DSOLocal) { - Res = parseOptionalLinkageAux(Lex.getKind(), HasLinkage); - if (HasLinkage) - Lex.Lex(); + Res = parseOptionalLinkageAux(Lex.getKind(), HasLinkage); + if (HasLinkage) + Lex.Lex(); parseOptionalDSOLocal(DSOLocal); parseOptionalVisibility(Visibility); parseOptionalDLLStorageClass(DLLStorageClass); - - if (DSOLocal && DLLStorageClass == GlobalValue::DLLImportStorageClass) { + + if (DSOLocal && DLLStorageClass == GlobalValue::DLLImportStorageClass) { return error(Lex.getLoc(), "dso_location and DLL-StorageClass mismatch"); - } - - return false; -} - + } + + return false; +} + void LLParser::parseOptionalDSOLocal(bool &DSOLocal) { - switch (Lex.getKind()) { - default: - DSOLocal = false; - break; - case lltok::kw_dso_local: - DSOLocal = true; - Lex.Lex(); - break; - case lltok::kw_dso_preemptable: - DSOLocal = false; - Lex.Lex(); - break; - } -} - + switch (Lex.getKind()) { + default: + DSOLocal = false; + break; + case lltok::kw_dso_local: + DSOLocal = true; + Lex.Lex(); + break; + case lltok::kw_dso_preemptable: + DSOLocal = false; + Lex.Lex(); + break; + } +} + /// parseOptionalVisibility -/// ::= /*empty*/ -/// ::= 'default' -/// ::= 'hidden' -/// ::= 'protected' -/// +/// ::= /*empty*/ +/// ::= 'default' +/// ::= 'hidden' +/// ::= 'protected' +/// void LLParser::parseOptionalVisibility(unsigned &Res) { - switch (Lex.getKind()) { - default: - Res = GlobalValue::DefaultVisibility; - return; - case lltok::kw_default: - Res = GlobalValue::DefaultVisibility; - break; - case lltok::kw_hidden: - Res = GlobalValue::HiddenVisibility; - break; - case lltok::kw_protected: - Res = GlobalValue::ProtectedVisibility; - break; - } - Lex.Lex(); -} - + switch (Lex.getKind()) { + default: + Res = GlobalValue::DefaultVisibility; + return; + case lltok::kw_default: + Res = GlobalValue::DefaultVisibility; + break; + case lltok::kw_hidden: + Res = GlobalValue::HiddenVisibility; + break; + case lltok::kw_protected: + Res = GlobalValue::ProtectedVisibility; + break; + } + Lex.Lex(); +} + /// parseOptionalDLLStorageClass -/// ::= /*empty*/ -/// ::= 'dllimport' -/// ::= 'dllexport' -/// +/// ::= /*empty*/ +/// ::= 'dllimport' +/// ::= 'dllexport' +/// void LLParser::parseOptionalDLLStorageClass(unsigned &Res) { - switch (Lex.getKind()) { - default: - Res = GlobalValue::DefaultStorageClass; - return; - case lltok::kw_dllimport: - Res = GlobalValue::DLLImportStorageClass; - break; - case lltok::kw_dllexport: - Res = GlobalValue::DLLExportStorageClass; - break; - } - Lex.Lex(); -} - + switch (Lex.getKind()) { + default: + Res = GlobalValue::DefaultStorageClass; + return; + case lltok::kw_dllimport: + Res = GlobalValue::DLLImportStorageClass; + break; + case lltok::kw_dllexport: + Res = GlobalValue::DLLExportStorageClass; + break; + } + Lex.Lex(); +} + /// parseOptionalCallingConv -/// ::= /*empty*/ -/// ::= 'ccc' -/// ::= 'fastcc' -/// ::= 'intel_ocl_bicc' -/// ::= 'coldcc' -/// ::= 'cfguard_checkcc' -/// ::= 'x86_stdcallcc' -/// ::= 'x86_fastcallcc' -/// ::= 'x86_thiscallcc' -/// ::= 'x86_vectorcallcc' -/// ::= 'arm_apcscc' -/// ::= 'arm_aapcscc' -/// ::= 'arm_aapcs_vfpcc' -/// ::= 'aarch64_vector_pcs' -/// ::= 'aarch64_sve_vector_pcs' -/// ::= 'msp430_intrcc' -/// ::= 'avr_intrcc' -/// ::= 'avr_signalcc' -/// ::= 'ptx_kernel' -/// ::= 'ptx_device' -/// ::= 'spir_func' -/// ::= 'spir_kernel' -/// ::= 'x86_64_sysvcc' -/// ::= 'win64cc' -/// ::= 'webkit_jscc' -/// ::= 'anyregcc' -/// ::= 'preserve_mostcc' -/// ::= 'preserve_allcc' -/// ::= 'ghccc' -/// ::= 'swiftcc' -/// ::= 'x86_intrcc' -/// ::= 'hhvmcc' -/// ::= 'hhvm_ccc' -/// ::= 'cxx_fast_tlscc' -/// ::= 'amdgpu_vs' -/// ::= 'amdgpu_ls' -/// ::= 'amdgpu_hs' -/// ::= 'amdgpu_es' -/// ::= 'amdgpu_gs' -/// ::= 'amdgpu_ps' -/// ::= 'amdgpu_cs' -/// ::= 'amdgpu_kernel' -/// ::= 'tailcc' -/// ::= 'cc' UINT -/// +/// ::= /*empty*/ +/// ::= 'ccc' +/// ::= 'fastcc' +/// ::= 'intel_ocl_bicc' +/// ::= 'coldcc' +/// ::= 'cfguard_checkcc' +/// ::= 'x86_stdcallcc' +/// ::= 'x86_fastcallcc' +/// ::= 'x86_thiscallcc' +/// ::= 'x86_vectorcallcc' +/// ::= 'arm_apcscc' +/// ::= 'arm_aapcscc' +/// ::= 'arm_aapcs_vfpcc' +/// ::= 'aarch64_vector_pcs' +/// ::= 'aarch64_sve_vector_pcs' +/// ::= 'msp430_intrcc' +/// ::= 'avr_intrcc' +/// ::= 'avr_signalcc' +/// ::= 'ptx_kernel' +/// ::= 'ptx_device' +/// ::= 'spir_func' +/// ::= 'spir_kernel' +/// ::= 'x86_64_sysvcc' +/// ::= 'win64cc' +/// ::= 'webkit_jscc' +/// ::= 'anyregcc' +/// ::= 'preserve_mostcc' +/// ::= 'preserve_allcc' +/// ::= 'ghccc' +/// ::= 'swiftcc' +/// ::= 'x86_intrcc' +/// ::= 'hhvmcc' +/// ::= 'hhvm_ccc' +/// ::= 'cxx_fast_tlscc' +/// ::= 'amdgpu_vs' +/// ::= 'amdgpu_ls' +/// ::= 'amdgpu_hs' +/// ::= 'amdgpu_es' +/// ::= 'amdgpu_gs' +/// ::= 'amdgpu_ps' +/// ::= 'amdgpu_cs' +/// ::= 'amdgpu_kernel' +/// ::= 'tailcc' +/// ::= 'cc' UINT +/// bool LLParser::parseOptionalCallingConv(unsigned &CC) { - switch (Lex.getKind()) { - default: CC = CallingConv::C; return false; - case lltok::kw_ccc: CC = CallingConv::C; break; - case lltok::kw_fastcc: CC = CallingConv::Fast; break; - case lltok::kw_coldcc: CC = CallingConv::Cold; break; - case lltok::kw_cfguard_checkcc: CC = CallingConv::CFGuard_Check; break; - case lltok::kw_x86_stdcallcc: CC = CallingConv::X86_StdCall; break; - case lltok::kw_x86_fastcallcc: CC = CallingConv::X86_FastCall; break; - case lltok::kw_x86_regcallcc: CC = CallingConv::X86_RegCall; break; - case lltok::kw_x86_thiscallcc: CC = CallingConv::X86_ThisCall; break; - case lltok::kw_x86_vectorcallcc:CC = CallingConv::X86_VectorCall; break; - case lltok::kw_arm_apcscc: CC = CallingConv::ARM_APCS; break; - case lltok::kw_arm_aapcscc: CC = CallingConv::ARM_AAPCS; break; - case lltok::kw_arm_aapcs_vfpcc:CC = CallingConv::ARM_AAPCS_VFP; break; - case lltok::kw_aarch64_vector_pcs:CC = CallingConv::AArch64_VectorCall; break; - case lltok::kw_aarch64_sve_vector_pcs: - CC = CallingConv::AArch64_SVE_VectorCall; - break; - case lltok::kw_msp430_intrcc: CC = CallingConv::MSP430_INTR; break; - case lltok::kw_avr_intrcc: CC = CallingConv::AVR_INTR; break; - case lltok::kw_avr_signalcc: CC = CallingConv::AVR_SIGNAL; break; - case lltok::kw_ptx_kernel: CC = CallingConv::PTX_Kernel; break; - case lltok::kw_ptx_device: CC = CallingConv::PTX_Device; break; - case lltok::kw_spir_kernel: CC = CallingConv::SPIR_KERNEL; break; - case lltok::kw_spir_func: CC = CallingConv::SPIR_FUNC; break; - case lltok::kw_intel_ocl_bicc: CC = CallingConv::Intel_OCL_BI; break; - case lltok::kw_x86_64_sysvcc: CC = CallingConv::X86_64_SysV; break; - case lltok::kw_win64cc: CC = CallingConv::Win64; break; - case lltok::kw_webkit_jscc: CC = CallingConv::WebKit_JS; break; - case lltok::kw_anyregcc: CC = CallingConv::AnyReg; break; - case lltok::kw_preserve_mostcc:CC = CallingConv::PreserveMost; break; - case lltok::kw_preserve_allcc: CC = CallingConv::PreserveAll; break; - case lltok::kw_ghccc: CC = CallingConv::GHC; break; - case lltok::kw_swiftcc: CC = CallingConv::Swift; break; - case lltok::kw_x86_intrcc: CC = CallingConv::X86_INTR; break; - case lltok::kw_hhvmcc: CC = CallingConv::HHVM; break; - case lltok::kw_hhvm_ccc: CC = CallingConv::HHVM_C; break; - case lltok::kw_cxx_fast_tlscc: CC = CallingConv::CXX_FAST_TLS; break; - case lltok::kw_amdgpu_vs: CC = CallingConv::AMDGPU_VS; break; + switch (Lex.getKind()) { + default: CC = CallingConv::C; return false; + case lltok::kw_ccc: CC = CallingConv::C; break; + case lltok::kw_fastcc: CC = CallingConv::Fast; break; + case lltok::kw_coldcc: CC = CallingConv::Cold; break; + case lltok::kw_cfguard_checkcc: CC = CallingConv::CFGuard_Check; break; + case lltok::kw_x86_stdcallcc: CC = CallingConv::X86_StdCall; break; + case lltok::kw_x86_fastcallcc: CC = CallingConv::X86_FastCall; break; + case lltok::kw_x86_regcallcc: CC = CallingConv::X86_RegCall; break; + case lltok::kw_x86_thiscallcc: CC = CallingConv::X86_ThisCall; break; + case lltok::kw_x86_vectorcallcc:CC = CallingConv::X86_VectorCall; break; + case lltok::kw_arm_apcscc: CC = CallingConv::ARM_APCS; break; + case lltok::kw_arm_aapcscc: CC = CallingConv::ARM_AAPCS; break; + case lltok::kw_arm_aapcs_vfpcc:CC = CallingConv::ARM_AAPCS_VFP; break; + case lltok::kw_aarch64_vector_pcs:CC = CallingConv::AArch64_VectorCall; break; + case lltok::kw_aarch64_sve_vector_pcs: + CC = CallingConv::AArch64_SVE_VectorCall; + break; + case lltok::kw_msp430_intrcc: CC = CallingConv::MSP430_INTR; break; + case lltok::kw_avr_intrcc: CC = CallingConv::AVR_INTR; break; + case lltok::kw_avr_signalcc: CC = CallingConv::AVR_SIGNAL; break; + case lltok::kw_ptx_kernel: CC = CallingConv::PTX_Kernel; break; + case lltok::kw_ptx_device: CC = CallingConv::PTX_Device; break; + case lltok::kw_spir_kernel: CC = CallingConv::SPIR_KERNEL; break; + case lltok::kw_spir_func: CC = CallingConv::SPIR_FUNC; break; + case lltok::kw_intel_ocl_bicc: CC = CallingConv::Intel_OCL_BI; break; + case lltok::kw_x86_64_sysvcc: CC = CallingConv::X86_64_SysV; break; + case lltok::kw_win64cc: CC = CallingConv::Win64; break; + case lltok::kw_webkit_jscc: CC = CallingConv::WebKit_JS; break; + case lltok::kw_anyregcc: CC = CallingConv::AnyReg; break; + case lltok::kw_preserve_mostcc:CC = CallingConv::PreserveMost; break; + case lltok::kw_preserve_allcc: CC = CallingConv::PreserveAll; break; + case lltok::kw_ghccc: CC = CallingConv::GHC; break; + case lltok::kw_swiftcc: CC = CallingConv::Swift; break; + case lltok::kw_x86_intrcc: CC = CallingConv::X86_INTR; break; + case lltok::kw_hhvmcc: CC = CallingConv::HHVM; break; + case lltok::kw_hhvm_ccc: CC = CallingConv::HHVM_C; break; + case lltok::kw_cxx_fast_tlscc: CC = CallingConv::CXX_FAST_TLS; break; + case lltok::kw_amdgpu_vs: CC = CallingConv::AMDGPU_VS; break; case lltok::kw_amdgpu_gfx: CC = CallingConv::AMDGPU_Gfx; break; - case lltok::kw_amdgpu_ls: CC = CallingConv::AMDGPU_LS; break; - case lltok::kw_amdgpu_hs: CC = CallingConv::AMDGPU_HS; break; - case lltok::kw_amdgpu_es: CC = CallingConv::AMDGPU_ES; break; - case lltok::kw_amdgpu_gs: CC = CallingConv::AMDGPU_GS; break; - case lltok::kw_amdgpu_ps: CC = CallingConv::AMDGPU_PS; break; - case lltok::kw_amdgpu_cs: CC = CallingConv::AMDGPU_CS; break; - case lltok::kw_amdgpu_kernel: CC = CallingConv::AMDGPU_KERNEL; break; - case lltok::kw_tailcc: CC = CallingConv::Tail; break; - case lltok::kw_cc: { - Lex.Lex(); + case lltok::kw_amdgpu_ls: CC = CallingConv::AMDGPU_LS; break; + case lltok::kw_amdgpu_hs: CC = CallingConv::AMDGPU_HS; break; + case lltok::kw_amdgpu_es: CC = CallingConv::AMDGPU_ES; break; + case lltok::kw_amdgpu_gs: CC = CallingConv::AMDGPU_GS; break; + case lltok::kw_amdgpu_ps: CC = CallingConv::AMDGPU_PS; break; + case lltok::kw_amdgpu_cs: CC = CallingConv::AMDGPU_CS; break; + case lltok::kw_amdgpu_kernel: CC = CallingConv::AMDGPU_KERNEL; break; + case lltok::kw_tailcc: CC = CallingConv::Tail; break; + case lltok::kw_cc: { + Lex.Lex(); return parseUInt32(CC); - } - } - - Lex.Lex(); - return false; -} - + } + } + + Lex.Lex(); + return false; +} + /// parseMetadataAttachment -/// ::= !dbg !42 +/// ::= !dbg !42 bool LLParser::parseMetadataAttachment(unsigned &Kind, MDNode *&MD) { - assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata attachment"); - - std::string Name = Lex.getStrVal(); - Kind = M->getMDKindID(Name); - Lex.Lex(); - + assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata attachment"); + + std::string Name = Lex.getStrVal(); + Kind = M->getMDKindID(Name); + Lex.Lex(); + return parseMDNode(MD); -} - +} + /// parseInstructionMetadata -/// ::= !dbg !42 (',' !dbg !57)* +/// ::= !dbg !42 (',' !dbg !57)* bool LLParser::parseInstructionMetadata(Instruction &Inst) { - do { - if (Lex.getKind() != lltok::MetadataVar) + do { + if (Lex.getKind() != lltok::MetadataVar) return tokError("expected metadata after comma"); - - unsigned MDK; - MDNode *N; + + unsigned MDK; + MDNode *N; if (parseMetadataAttachment(MDK, N)) - return true; - - Inst.setMetadata(MDK, N); - if (MDK == LLVMContext::MD_tbaa) - InstsWithTBAATag.push_back(&Inst); - - // If this is the end of the list, we're done. - } while (EatIfPresent(lltok::comma)); - return false; -} - + return true; + + Inst.setMetadata(MDK, N); + if (MDK == LLVMContext::MD_tbaa) + InstsWithTBAATag.push_back(&Inst); + + // If this is the end of the list, we're done. + } while (EatIfPresent(lltok::comma)); + return false; +} + /// parseGlobalObjectMetadataAttachment -/// ::= !dbg !57 +/// ::= !dbg !57 bool LLParser::parseGlobalObjectMetadataAttachment(GlobalObject &GO) { - unsigned MDK; - MDNode *N; + unsigned MDK; + MDNode *N; if (parseMetadataAttachment(MDK, N)) - return true; - - GO.addMetadata(MDK, *N); - return false; -} - + return true; + + GO.addMetadata(MDK, *N); + return false; +} + /// parseOptionalFunctionMetadata -/// ::= (!dbg !57)* +/// ::= (!dbg !57)* bool LLParser::parseOptionalFunctionMetadata(Function &F) { - while (Lex.getKind() == lltok::MetadataVar) + while (Lex.getKind() == lltok::MetadataVar) if (parseGlobalObjectMetadataAttachment(F)) - return true; - return false; -} - + return true; + return false; +} + /// parseOptionalAlignment -/// ::= /* empty */ -/// ::= 'align' 4 +/// ::= /* empty */ +/// ::= 'align' 4 bool LLParser::parseOptionalAlignment(MaybeAlign &Alignment, bool AllowParens) { - Alignment = None; - if (!EatIfPresent(lltok::kw_align)) - return false; - LocTy AlignLoc = Lex.getLoc(); - uint32_t Value = 0; - - LocTy ParenLoc = Lex.getLoc(); - bool HaveParens = false; - if (AllowParens) { - if (EatIfPresent(lltok::lparen)) - HaveParens = true; - } - + Alignment = None; + if (!EatIfPresent(lltok::kw_align)) + return false; + LocTy AlignLoc = Lex.getLoc(); + uint32_t Value = 0; + + LocTy ParenLoc = Lex.getLoc(); + bool HaveParens = false; + if (AllowParens) { + if (EatIfPresent(lltok::lparen)) + HaveParens = true; + } + if (parseUInt32(Value)) - return true; - - if (HaveParens && !EatIfPresent(lltok::rparen)) + return true; + + if (HaveParens && !EatIfPresent(lltok::rparen)) return error(ParenLoc, "expected ')'"); - - if (!isPowerOf2_32(Value)) + + if (!isPowerOf2_32(Value)) return error(AlignLoc, "alignment is not a power of two"); - if (Value > Value::MaximumAlignment) + if (Value > Value::MaximumAlignment) return error(AlignLoc, "huge alignments are not supported yet"); - Alignment = Align(Value); - return false; -} - + Alignment = Align(Value); + return false; +} + /// parseOptionalDerefAttrBytes -/// ::= /* empty */ -/// ::= AttrKind '(' 4 ')' -/// -/// where AttrKind is either 'dereferenceable' or 'dereferenceable_or_null'. +/// ::= /* empty */ +/// ::= AttrKind '(' 4 ')' +/// +/// where AttrKind is either 'dereferenceable' or 'dereferenceable_or_null'. bool LLParser::parseOptionalDerefAttrBytes(lltok::Kind AttrKind, - uint64_t &Bytes) { - assert((AttrKind == lltok::kw_dereferenceable || - AttrKind == lltok::kw_dereferenceable_or_null) && - "contract!"); - - Bytes = 0; - if (!EatIfPresent(AttrKind)) - return false; - LocTy ParenLoc = Lex.getLoc(); - if (!EatIfPresent(lltok::lparen)) + uint64_t &Bytes) { + assert((AttrKind == lltok::kw_dereferenceable || + AttrKind == lltok::kw_dereferenceable_or_null) && + "contract!"); + + Bytes = 0; + if (!EatIfPresent(AttrKind)) + return false; + LocTy ParenLoc = Lex.getLoc(); + if (!EatIfPresent(lltok::lparen)) return error(ParenLoc, "expected '('"); - LocTy DerefLoc = Lex.getLoc(); + LocTy DerefLoc = Lex.getLoc(); if (parseUInt64(Bytes)) return true; - ParenLoc = Lex.getLoc(); - if (!EatIfPresent(lltok::rparen)) + ParenLoc = Lex.getLoc(); + if (!EatIfPresent(lltok::rparen)) return error(ParenLoc, "expected ')'"); - if (!Bytes) + if (!Bytes) return error(DerefLoc, "dereferenceable bytes must be non-zero"); - return false; -} - + return false; +} + /// parseOptionalCommaAlign -/// ::= -/// ::= ',' align 4 -/// -/// This returns with AteExtraComma set to true if it ate an excess comma at the -/// end. +/// ::= +/// ::= ',' align 4 +/// +/// This returns with AteExtraComma set to true if it ate an excess comma at the +/// end. bool LLParser::parseOptionalCommaAlign(MaybeAlign &Alignment, - bool &AteExtraComma) { - AteExtraComma = false; - while (EatIfPresent(lltok::comma)) { - // Metadata at the end is an early exit. - if (Lex.getKind() == lltok::MetadataVar) { - AteExtraComma = true; - return false; - } - - if (Lex.getKind() != lltok::kw_align) + bool &AteExtraComma) { + AteExtraComma = false; + while (EatIfPresent(lltok::comma)) { + // Metadata at the end is an early exit. + if (Lex.getKind() == lltok::MetadataVar) { + AteExtraComma = true; + return false; + } + + if (Lex.getKind() != lltok::kw_align) return error(Lex.getLoc(), "expected metadata or 'align'"); - + if (parseOptionalAlignment(Alignment)) return true; - } - - return false; -} - + } + + return false; +} + /// parseOptionalCommaAddrSpace -/// ::= -/// ::= ',' addrspace(1) -/// -/// This returns with AteExtraComma set to true if it ate an excess comma at the -/// end. +/// ::= +/// ::= ',' addrspace(1) +/// +/// This returns with AteExtraComma set to true if it ate an excess comma at the +/// end. bool LLParser::parseOptionalCommaAddrSpace(unsigned &AddrSpace, LocTy &Loc, - bool &AteExtraComma) { - AteExtraComma = false; - while (EatIfPresent(lltok::comma)) { - // Metadata at the end is an early exit. - if (Lex.getKind() == lltok::MetadataVar) { - AteExtraComma = true; - return false; - } - - Loc = Lex.getLoc(); - if (Lex.getKind() != lltok::kw_addrspace) + bool &AteExtraComma) { + AteExtraComma = false; + while (EatIfPresent(lltok::comma)) { + // Metadata at the end is an early exit. + if (Lex.getKind() == lltok::MetadataVar) { + AteExtraComma = true; + return false; + } + + Loc = Lex.getLoc(); + if (Lex.getKind() != lltok::kw_addrspace) return error(Lex.getLoc(), "expected metadata or 'addrspace'"); - + if (parseOptionalAddrSpace(AddrSpace)) - return true; - } - - return false; -} - -bool LLParser::parseAllocSizeArguments(unsigned &BaseSizeArg, - Optional<unsigned> &HowManyArg) { - Lex.Lex(); - - auto StartParen = Lex.getLoc(); - if (!EatIfPresent(lltok::lparen)) + return true; + } + + return false; +} + +bool LLParser::parseAllocSizeArguments(unsigned &BaseSizeArg, + Optional<unsigned> &HowManyArg) { + Lex.Lex(); + + auto StartParen = Lex.getLoc(); + if (!EatIfPresent(lltok::lparen)) return error(StartParen, "expected '('"); - + if (parseUInt32(BaseSizeArg)) - return true; - - if (EatIfPresent(lltok::comma)) { - auto HowManyAt = Lex.getLoc(); - unsigned HowMany; + return true; + + if (EatIfPresent(lltok::comma)) { + auto HowManyAt = Lex.getLoc(); + unsigned HowMany; if (parseUInt32(HowMany)) - return true; - if (HowMany == BaseSizeArg) + return true; + if (HowMany == BaseSizeArg) return error(HowManyAt, - "'allocsize' indices can't refer to the same parameter"); - HowManyArg = HowMany; - } else - HowManyArg = None; - - auto EndParen = Lex.getLoc(); - if (!EatIfPresent(lltok::rparen)) + "'allocsize' indices can't refer to the same parameter"); + HowManyArg = HowMany; + } else + HowManyArg = None; + + auto EndParen = Lex.getLoc(); + if (!EatIfPresent(lltok::rparen)) return error(EndParen, "expected ')'"); - return false; -} - + return false; +} + /// parseScopeAndOrdering -/// if isAtomic: ::= SyncScope? AtomicOrdering -/// else: ::= -/// -/// This sets Scope and Ordering to the parsed values. +/// if isAtomic: ::= SyncScope? AtomicOrdering +/// else: ::= +/// +/// This sets Scope and Ordering to the parsed values. bool LLParser::parseScopeAndOrdering(bool IsAtomic, SyncScope::ID &SSID, - AtomicOrdering &Ordering) { + AtomicOrdering &Ordering) { if (!IsAtomic) - return false; - + return false; + return parseScope(SSID) || parseOrdering(Ordering); -} - +} + /// parseScope -/// ::= syncscope("singlethread" | "<target scope>")? -/// -/// This sets synchronization scope ID to the ID of the parsed value. +/// ::= syncscope("singlethread" | "<target scope>")? +/// +/// This sets synchronization scope ID to the ID of the parsed value. bool LLParser::parseScope(SyncScope::ID &SSID) { - SSID = SyncScope::System; - if (EatIfPresent(lltok::kw_syncscope)) { - auto StartParenAt = Lex.getLoc(); - if (!EatIfPresent(lltok::lparen)) + SSID = SyncScope::System; + if (EatIfPresent(lltok::kw_syncscope)) { + auto StartParenAt = Lex.getLoc(); + if (!EatIfPresent(lltok::lparen)) return error(StartParenAt, "Expected '(' in syncscope"); - - std::string SSN; - auto SSNAt = Lex.getLoc(); + + std::string SSN; + auto SSNAt = Lex.getLoc(); if (parseStringConstant(SSN)) return error(SSNAt, "Expected synchronization scope name"); - - auto EndParenAt = Lex.getLoc(); - if (!EatIfPresent(lltok::rparen)) + + auto EndParenAt = Lex.getLoc(); + if (!EatIfPresent(lltok::rparen)) return error(EndParenAt, "Expected ')' in syncscope"); - - SSID = Context.getOrInsertSyncScopeID(SSN); - } - - return false; -} - + + SSID = Context.getOrInsertSyncScopeID(SSN); + } + + return false; +} + /// parseOrdering -/// ::= AtomicOrdering -/// -/// This sets Ordering to the parsed value. +/// ::= AtomicOrdering +/// +/// This sets Ordering to the parsed value. bool LLParser::parseOrdering(AtomicOrdering &Ordering) { - switch (Lex.getKind()) { + switch (Lex.getKind()) { default: return tokError("Expected ordering on atomic instruction"); - case lltok::kw_unordered: Ordering = AtomicOrdering::Unordered; break; - case lltok::kw_monotonic: Ordering = AtomicOrdering::Monotonic; break; - // Not specified yet: - // case lltok::kw_consume: Ordering = AtomicOrdering::Consume; break; - case lltok::kw_acquire: Ordering = AtomicOrdering::Acquire; break; - case lltok::kw_release: Ordering = AtomicOrdering::Release; break; - case lltok::kw_acq_rel: Ordering = AtomicOrdering::AcquireRelease; break; - case lltok::kw_seq_cst: - Ordering = AtomicOrdering::SequentiallyConsistent; - break; - } - Lex.Lex(); - return false; -} - + case lltok::kw_unordered: Ordering = AtomicOrdering::Unordered; break; + case lltok::kw_monotonic: Ordering = AtomicOrdering::Monotonic; break; + // Not specified yet: + // case lltok::kw_consume: Ordering = AtomicOrdering::Consume; break; + case lltok::kw_acquire: Ordering = AtomicOrdering::Acquire; break; + case lltok::kw_release: Ordering = AtomicOrdering::Release; break; + case lltok::kw_acq_rel: Ordering = AtomicOrdering::AcquireRelease; break; + case lltok::kw_seq_cst: + Ordering = AtomicOrdering::SequentiallyConsistent; + break; + } + Lex.Lex(); + return false; +} + /// parseOptionalStackAlignment -/// ::= /* empty */ -/// ::= 'alignstack' '(' 4 ')' +/// ::= /* empty */ +/// ::= 'alignstack' '(' 4 ')' bool LLParser::parseOptionalStackAlignment(unsigned &Alignment) { - Alignment = 0; - if (!EatIfPresent(lltok::kw_alignstack)) - return false; - LocTy ParenLoc = Lex.getLoc(); - if (!EatIfPresent(lltok::lparen)) + Alignment = 0; + if (!EatIfPresent(lltok::kw_alignstack)) + return false; + LocTy ParenLoc = Lex.getLoc(); + if (!EatIfPresent(lltok::lparen)) return error(ParenLoc, "expected '('"); - LocTy AlignLoc = Lex.getLoc(); + LocTy AlignLoc = Lex.getLoc(); if (parseUInt32(Alignment)) return true; - ParenLoc = Lex.getLoc(); - if (!EatIfPresent(lltok::rparen)) + ParenLoc = Lex.getLoc(); + if (!EatIfPresent(lltok::rparen)) return error(ParenLoc, "expected ')'"); - if (!isPowerOf2_32(Alignment)) + if (!isPowerOf2_32(Alignment)) return error(AlignLoc, "stack alignment is not a power of two"); - return false; -} - + return false; +} + /// parseIndexList - This parses the index list for an insert/extractvalue -/// instruction. This sets AteExtraComma in the case where we eat an extra -/// comma at the end of the line and find that it is followed by metadata. -/// Clients that don't allow metadata can call the version of this function that -/// only takes one argument. -/// +/// instruction. This sets AteExtraComma in the case where we eat an extra +/// comma at the end of the line and find that it is followed by metadata. +/// Clients that don't allow metadata can call the version of this function that +/// only takes one argument. +/// /// parseIndexList -/// ::= (',' uint32)+ -/// +/// ::= (',' uint32)+ +/// bool LLParser::parseIndexList(SmallVectorImpl<unsigned> &Indices, - bool &AteExtraComma) { - AteExtraComma = false; - - if (Lex.getKind() != lltok::comma) + bool &AteExtraComma) { + AteExtraComma = false; + + if (Lex.getKind() != lltok::comma) return tokError("expected ',' as start of index list"); - - while (EatIfPresent(lltok::comma)) { - if (Lex.getKind() == lltok::MetadataVar) { + + while (EatIfPresent(lltok::comma)) { + if (Lex.getKind() == lltok::MetadataVar) { if (Indices.empty()) return tokError("expected index"); - AteExtraComma = true; - return false; - } - unsigned Idx = 0; + AteExtraComma = true; + return false; + } + unsigned Idx = 0; if (parseUInt32(Idx)) return true; - Indices.push_back(Idx); - } - - return false; -} - -//===----------------------------------------------------------------------===// -// Type Parsing. -//===----------------------------------------------------------------------===// - + Indices.push_back(Idx); + } + + return false; +} + +//===----------------------------------------------------------------------===// +// Type Parsing. +//===----------------------------------------------------------------------===// + /// parseType - parse a type. bool LLParser::parseType(Type *&Result, const Twine &Msg, bool AllowVoid) { - SMLoc TypeLoc = Lex.getLoc(); - switch (Lex.getKind()) { - default: + SMLoc TypeLoc = Lex.getLoc(); + switch (Lex.getKind()) { + default: return tokError(Msg); - case lltok::Type: - // Type ::= 'float' | 'void' (etc) - Result = Lex.getTyVal(); - Lex.Lex(); - break; - case lltok::lbrace: - // Type ::= StructType + case lltok::Type: + // Type ::= 'float' | 'void' (etc) + Result = Lex.getTyVal(); + Lex.Lex(); + break; + case lltok::lbrace: + // Type ::= StructType if (parseAnonStructType(Result, false)) - return true; - break; - case lltok::lsquare: - // Type ::= '[' ... ']' - Lex.Lex(); // eat the lsquare. + return true; + break; + case lltok::lsquare: + // Type ::= '[' ... ']' + Lex.Lex(); // eat the lsquare. if (parseArrayVectorType(Result, false)) - return true; - break; - case lltok::less: // Either vector or packed struct. - // Type ::= '<' ... '>' - Lex.Lex(); - if (Lex.getKind() == lltok::lbrace) { + return true; + break; + case lltok::less: // Either vector or packed struct. + // Type ::= '<' ... '>' + Lex.Lex(); + if (Lex.getKind() == lltok::lbrace) { if (parseAnonStructType(Result, true) || parseToken(lltok::greater, "expected '>' at end of packed struct")) - return true; + return true; } else if (parseArrayVectorType(Result, true)) - return true; - break; - case lltok::LocalVar: { - // Type ::= %foo - std::pair<Type*, LocTy> &Entry = NamedTypes[Lex.getStrVal()]; - - // If the type hasn't been defined yet, create a forward definition and - // remember where that forward def'n was seen (in case it never is defined). - if (!Entry.first) { - Entry.first = StructType::create(Context, Lex.getStrVal()); - Entry.second = Lex.getLoc(); - } - Result = Entry.first; - Lex.Lex(); - break; - } - - case lltok::LocalVarID: { - // Type ::= %4 - std::pair<Type*, LocTy> &Entry = NumberedTypes[Lex.getUIntVal()]; - - // If the type hasn't been defined yet, create a forward definition and - // remember where that forward def'n was seen (in case it never is defined). - if (!Entry.first) { - Entry.first = StructType::create(Context); - Entry.second = Lex.getLoc(); - } - Result = Entry.first; - Lex.Lex(); - break; - } - } - + return true; + break; + case lltok::LocalVar: { + // Type ::= %foo + std::pair<Type*, LocTy> &Entry = NamedTypes[Lex.getStrVal()]; + + // If the type hasn't been defined yet, create a forward definition and + // remember where that forward def'n was seen (in case it never is defined). + if (!Entry.first) { + Entry.first = StructType::create(Context, Lex.getStrVal()); + Entry.second = Lex.getLoc(); + } + Result = Entry.first; + Lex.Lex(); + break; + } + + case lltok::LocalVarID: { + // Type ::= %4 + std::pair<Type*, LocTy> &Entry = NumberedTypes[Lex.getUIntVal()]; + + // If the type hasn't been defined yet, create a forward definition and + // remember where that forward def'n was seen (in case it never is defined). + if (!Entry.first) { + Entry.first = StructType::create(Context); + Entry.second = Lex.getLoc(); + } + Result = Entry.first; + Lex.Lex(); + break; + } + } + // parse the type suffixes. - while (true) { - switch (Lex.getKind()) { - // End of type. - default: - if (!AllowVoid && Result->isVoidTy()) + while (true) { + switch (Lex.getKind()) { + // End of type. + default: + if (!AllowVoid && Result->isVoidTy()) return error(TypeLoc, "void type only allowed for function results"); - return false; - - // Type ::= Type '*' - case lltok::star: - if (Result->isLabelTy()) + return false; + + // Type ::= Type '*' + case lltok::star: + if (Result->isLabelTy()) return tokError("basic block pointers are invalid"); - if (Result->isVoidTy()) + if (Result->isVoidTy()) return tokError("pointers to void are invalid - use i8* instead"); - if (!PointerType::isValidElementType(Result)) + if (!PointerType::isValidElementType(Result)) return tokError("pointer to this type is invalid"); - Result = PointerType::getUnqual(Result); - Lex.Lex(); - break; - - // Type ::= Type 'addrspace' '(' uint32 ')' '*' - case lltok::kw_addrspace: { - if (Result->isLabelTy()) + Result = PointerType::getUnqual(Result); + Lex.Lex(); + break; + + // Type ::= Type 'addrspace' '(' uint32 ')' '*' + case lltok::kw_addrspace: { + if (Result->isLabelTy()) return tokError("basic block pointers are invalid"); - if (Result->isVoidTy()) + if (Result->isVoidTy()) return tokError("pointers to void are invalid; use i8* instead"); - if (!PointerType::isValidElementType(Result)) + if (!PointerType::isValidElementType(Result)) return tokError("pointer to this type is invalid"); - unsigned AddrSpace; + unsigned AddrSpace; if (parseOptionalAddrSpace(AddrSpace) || parseToken(lltok::star, "expected '*' in address space")) - return true; - - Result = PointerType::get(Result, AddrSpace); - break; - } - - /// Types '(' ArgTypeListI ')' OptFuncAttrs - case lltok::lparen: + return true; + + Result = PointerType::get(Result, AddrSpace); + break; + } + + /// Types '(' ArgTypeListI ')' OptFuncAttrs + case lltok::lparen: if (parseFunctionType(Result)) - return true; - break; - } - } -} - + return true; + break; + } + } +} + /// parseParameterList -/// ::= '(' ')' -/// ::= '(' Arg (',' Arg)* ')' -/// Arg -/// ::= Type OptionalAttributes Value OptionalAttributes +/// ::= '(' ')' +/// ::= '(' Arg (',' Arg)* ')' +/// Arg +/// ::= Type OptionalAttributes Value OptionalAttributes bool LLParser::parseParameterList(SmallVectorImpl<ParamInfo> &ArgList, - PerFunctionState &PFS, bool IsMustTailCall, - bool InVarArgsFunc) { + PerFunctionState &PFS, bool IsMustTailCall, + bool InVarArgsFunc) { if (parseToken(lltok::lparen, "expected '(' in call")) - return true; - - while (Lex.getKind() != lltok::rparen) { - // If this isn't the first argument, we need a comma. - if (!ArgList.empty() && + return true; + + while (Lex.getKind() != lltok::rparen) { + // If this isn't the first argument, we need a comma. + if (!ArgList.empty() && parseToken(lltok::comma, "expected ',' in argument list")) - return true; - + return true; + // parse an ellipsis if this is a musttail call in a variadic function. - if (Lex.getKind() == lltok::dotdotdot) { - const char *Msg = "unexpected ellipsis in argument list for "; - if (!IsMustTailCall) + if (Lex.getKind() == lltok::dotdotdot) { + const char *Msg = "unexpected ellipsis in argument list for "; + if (!IsMustTailCall) return tokError(Twine(Msg) + "non-musttail call"); - if (!InVarArgsFunc) + if (!InVarArgsFunc) return tokError(Twine(Msg) + "musttail call in non-varargs function"); - Lex.Lex(); // Lex the '...', it is purely for readability. + Lex.Lex(); // Lex the '...', it is purely for readability. return parseToken(lltok::rparen, "expected ')' at end of argument list"); - } - + } + // parse the argument. - LocTy ArgLoc; - Type *ArgTy = nullptr; - AttrBuilder ArgAttrs; - Value *V; + LocTy ArgLoc; + Type *ArgTy = nullptr; + AttrBuilder ArgAttrs; + Value *V; if (parseType(ArgTy, ArgLoc)) - return true; - - if (ArgTy->isMetadataTy()) { + return true; + + if (ArgTy->isMetadataTy()) { if (parseMetadataAsValue(V, PFS)) - return true; - } else { - // Otherwise, handle normal operands. + return true; + } else { + // Otherwise, handle normal operands. if (parseOptionalParamAttrs(ArgAttrs) || parseValue(ArgTy, V, PFS)) - return true; - } - ArgList.push_back(ParamInfo( - ArgLoc, V, AttributeSet::get(V->getContext(), ArgAttrs))); - } - - if (IsMustTailCall && InVarArgsFunc) + return true; + } + ArgList.push_back(ParamInfo( + ArgLoc, V, AttributeSet::get(V->getContext(), ArgAttrs))); + } + + if (IsMustTailCall && InVarArgsFunc) return tokError("expected '...' at end of argument list for musttail call " - "in varargs function"); - - Lex.Lex(); // Lex the ')'. - return false; -} - + "in varargs function"); + + Lex.Lex(); // Lex the ')'. + return false; +} + /// parseRequiredTypeAttr /// ::= attrname(<ty>) bool LLParser::parseRequiredTypeAttr(Type *&Result, lltok::Kind AttrName) { - Result = nullptr; + Result = nullptr; if (!EatIfPresent(AttrName)) - return true; - if (!EatIfPresent(lltok::lparen)) + return true; + if (!EatIfPresent(lltok::lparen)) return error(Lex.getLoc(), "expected '('"); if (parseType(Result)) - return true; - if (!EatIfPresent(lltok::rparen)) + return true; + if (!EatIfPresent(lltok::rparen)) return error(Lex.getLoc(), "expected ')'"); - return false; -} - + return false; +} + /// parsePreallocated -/// ::= preallocated(<ty>) +/// ::= preallocated(<ty>) bool LLParser::parsePreallocated(Type *&Result) { return parseRequiredTypeAttr(Result, lltok::kw_preallocated); -} - +} + /// parseByRef /// ::= byref(<type>) bool LLParser::parseByRef(Type *&Result) { @@ -2663,826 +2663,826 @@ bool LLParser::parseByRef(Type *&Result) { } /// parseOptionalOperandBundles -/// ::= /*empty*/ -/// ::= '[' OperandBundle [, OperandBundle ]* ']' -/// -/// OperandBundle -/// ::= bundle-tag '(' ')' -/// ::= bundle-tag '(' Type Value [, Type Value ]* ')' -/// -/// bundle-tag ::= String Constant +/// ::= /*empty*/ +/// ::= '[' OperandBundle [, OperandBundle ]* ']' +/// +/// OperandBundle +/// ::= bundle-tag '(' ')' +/// ::= bundle-tag '(' Type Value [, Type Value ]* ')' +/// +/// bundle-tag ::= String Constant bool LLParser::parseOptionalOperandBundles( - SmallVectorImpl<OperandBundleDef> &BundleList, PerFunctionState &PFS) { - LocTy BeginLoc = Lex.getLoc(); - if (!EatIfPresent(lltok::lsquare)) - return false; - - while (Lex.getKind() != lltok::rsquare) { - // If this isn't the first operand bundle, we need a comma. - if (!BundleList.empty() && + SmallVectorImpl<OperandBundleDef> &BundleList, PerFunctionState &PFS) { + LocTy BeginLoc = Lex.getLoc(); + if (!EatIfPresent(lltok::lsquare)) + return false; + + while (Lex.getKind() != lltok::rsquare) { + // If this isn't the first operand bundle, we need a comma. + if (!BundleList.empty() && parseToken(lltok::comma, "expected ',' in input list")) - return true; - - std::string Tag; + return true; + + std::string Tag; if (parseStringConstant(Tag)) - return true; - + return true; + if (parseToken(lltok::lparen, "expected '(' in operand bundle")) - return true; - - std::vector<Value *> Inputs; - while (Lex.getKind() != lltok::rparen) { - // If this isn't the first input, we need a comma. - if (!Inputs.empty() && + return true; + + std::vector<Value *> Inputs; + while (Lex.getKind() != lltok::rparen) { + // If this isn't the first input, we need a comma. + if (!Inputs.empty() && parseToken(lltok::comma, "expected ',' in input list")) - return true; - - Type *Ty = nullptr; - Value *Input = nullptr; + return true; + + Type *Ty = nullptr; + Value *Input = nullptr; if (parseType(Ty) || parseValue(Ty, Input, PFS)) - return true; - Inputs.push_back(Input); - } - - BundleList.emplace_back(std::move(Tag), std::move(Inputs)); - - Lex.Lex(); // Lex the ')'. - } - - if (BundleList.empty()) + return true; + Inputs.push_back(Input); + } + + BundleList.emplace_back(std::move(Tag), std::move(Inputs)); + + Lex.Lex(); // Lex the ')'. + } + + if (BundleList.empty()) return error(BeginLoc, "operand bundle set must not be empty"); - - Lex.Lex(); // Lex the ']'. - return false; -} - + + Lex.Lex(); // Lex the ']'. + return false; +} + /// parseArgumentList - parse the argument list for a function type or function -/// prototype. -/// ::= '(' ArgTypeListI ')' -/// ArgTypeListI -/// ::= /*empty*/ -/// ::= '...' -/// ::= ArgTypeList ',' '...' -/// ::= ArgType (',' ArgType)* -/// +/// prototype. +/// ::= '(' ArgTypeListI ')' +/// ArgTypeListI +/// ::= /*empty*/ +/// ::= '...' +/// ::= ArgTypeList ',' '...' +/// ::= ArgType (',' ArgType)* +/// bool LLParser::parseArgumentList(SmallVectorImpl<ArgInfo> &ArgList, bool &IsVarArg) { - unsigned CurValID = 0; + unsigned CurValID = 0; IsVarArg = false; - assert(Lex.getKind() == lltok::lparen); - Lex.Lex(); // eat the (. - - if (Lex.getKind() == lltok::rparen) { - // empty - } else if (Lex.getKind() == lltok::dotdotdot) { + assert(Lex.getKind() == lltok::lparen); + Lex.Lex(); // eat the (. + + if (Lex.getKind() == lltok::rparen) { + // empty + } else if (Lex.getKind() == lltok::dotdotdot) { IsVarArg = true; - Lex.Lex(); - } else { - LocTy TypeLoc = Lex.getLoc(); - Type *ArgTy = nullptr; - AttrBuilder Attrs; - std::string Name; - + Lex.Lex(); + } else { + LocTy TypeLoc = Lex.getLoc(); + Type *ArgTy = nullptr; + AttrBuilder Attrs; + std::string Name; + if (parseType(ArgTy) || parseOptionalParamAttrs(Attrs)) return true; - - if (ArgTy->isVoidTy()) + + if (ArgTy->isVoidTy()) return error(TypeLoc, "argument can not have void type"); - - if (Lex.getKind() == lltok::LocalVar) { - Name = Lex.getStrVal(); - Lex.Lex(); - } else if (Lex.getKind() == lltok::LocalVarID) { - if (Lex.getUIntVal() != CurValID) + + if (Lex.getKind() == lltok::LocalVar) { + Name = Lex.getStrVal(); + Lex.Lex(); + } else if (Lex.getKind() == lltok::LocalVarID) { + if (Lex.getUIntVal() != CurValID) return error(TypeLoc, "argument expected to be numbered '%" + - Twine(CurValID) + "'"); - ++CurValID; - Lex.Lex(); - } - - if (!FunctionType::isValidArgumentType(ArgTy)) + Twine(CurValID) + "'"); + ++CurValID; + Lex.Lex(); + } + + if (!FunctionType::isValidArgumentType(ArgTy)) return error(TypeLoc, "invalid type for function argument"); - - ArgList.emplace_back(TypeLoc, ArgTy, - AttributeSet::get(ArgTy->getContext(), Attrs), - std::move(Name)); - - while (EatIfPresent(lltok::comma)) { - // Handle ... at end of arg list. - if (EatIfPresent(lltok::dotdotdot)) { + + ArgList.emplace_back(TypeLoc, ArgTy, + AttributeSet::get(ArgTy->getContext(), Attrs), + std::move(Name)); + + while (EatIfPresent(lltok::comma)) { + // Handle ... at end of arg list. + if (EatIfPresent(lltok::dotdotdot)) { IsVarArg = true; - break; - } - - // Otherwise must be an argument type. - TypeLoc = Lex.getLoc(); + break; + } + + // Otherwise must be an argument type. + TypeLoc = Lex.getLoc(); if (parseType(ArgTy) || parseOptionalParamAttrs(Attrs)) return true; - - if (ArgTy->isVoidTy()) + + if (ArgTy->isVoidTy()) return error(TypeLoc, "argument can not have void type"); - - if (Lex.getKind() == lltok::LocalVar) { - Name = Lex.getStrVal(); - Lex.Lex(); - } else { - if (Lex.getKind() == lltok::LocalVarID) { - if (Lex.getUIntVal() != CurValID) + + if (Lex.getKind() == lltok::LocalVar) { + Name = Lex.getStrVal(); + Lex.Lex(); + } else { + if (Lex.getKind() == lltok::LocalVarID) { + if (Lex.getUIntVal() != CurValID) return error(TypeLoc, "argument expected to be numbered '%" + - Twine(CurValID) + "'"); - Lex.Lex(); - } - ++CurValID; - Name = ""; - } - - if (!ArgTy->isFirstClassType()) + Twine(CurValID) + "'"); + Lex.Lex(); + } + ++CurValID; + Name = ""; + } + + if (!ArgTy->isFirstClassType()) return error(TypeLoc, "invalid type for function argument"); - - ArgList.emplace_back(TypeLoc, ArgTy, - AttributeSet::get(ArgTy->getContext(), Attrs), - std::move(Name)); - } - } - + + ArgList.emplace_back(TypeLoc, ArgTy, + AttributeSet::get(ArgTy->getContext(), Attrs), + std::move(Name)); + } + } + return parseToken(lltok::rparen, "expected ')' at end of argument list"); -} - +} + /// parseFunctionType -/// ::= Type ArgumentList OptionalAttrs +/// ::= Type ArgumentList OptionalAttrs bool LLParser::parseFunctionType(Type *&Result) { - assert(Lex.getKind() == lltok::lparen); - - if (!FunctionType::isValidReturnType(Result)) + assert(Lex.getKind() == lltok::lparen); + + if (!FunctionType::isValidReturnType(Result)) return tokError("invalid function return type"); - - SmallVector<ArgInfo, 8> ArgList; + + SmallVector<ArgInfo, 8> ArgList; bool IsVarArg; if (parseArgumentList(ArgList, IsVarArg)) - return true; - - // Reject names on the arguments lists. - for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { - if (!ArgList[i].Name.empty()) + return true; + + // Reject names on the arguments lists. + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { + if (!ArgList[i].Name.empty()) return error(ArgList[i].Loc, "argument name invalid in function type"); - if (ArgList[i].Attrs.hasAttributes()) + if (ArgList[i].Attrs.hasAttributes()) return error(ArgList[i].Loc, - "argument attributes invalid in function type"); - } - - SmallVector<Type*, 16> ArgListTy; - for (unsigned i = 0, e = ArgList.size(); i != e; ++i) - ArgListTy.push_back(ArgList[i].Ty); - + "argument attributes invalid in function type"); + } + + SmallVector<Type*, 16> ArgListTy; + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) + ArgListTy.push_back(ArgList[i].Ty); + Result = FunctionType::get(Result, ArgListTy, IsVarArg); - return false; -} - + return false; +} + /// parseAnonStructType - parse an anonymous struct type, which is inlined into -/// other structs. +/// other structs. bool LLParser::parseAnonStructType(Type *&Result, bool Packed) { - SmallVector<Type*, 8> Elts; + SmallVector<Type*, 8> Elts; if (parseStructBody(Elts)) return true; - - Result = StructType::get(Context, Elts, Packed); - return false; -} - + + Result = StructType::get(Context, Elts, Packed); + return false; +} + /// parseStructDefinition - parse a struct in a 'type' definition. bool LLParser::parseStructDefinition(SMLoc TypeLoc, StringRef Name, std::pair<Type *, LocTy> &Entry, - Type *&ResultTy) { - // If the type was already defined, diagnose the redefinition. - if (Entry.first && !Entry.second.isValid()) + Type *&ResultTy) { + // If the type was already defined, diagnose the redefinition. + if (Entry.first && !Entry.second.isValid()) return error(TypeLoc, "redefinition of type"); - - // If we have opaque, just return without filling in the definition for the - // struct. This counts as a definition as far as the .ll file goes. - if (EatIfPresent(lltok::kw_opaque)) { - // This type is being defined, so clear the location to indicate this. - Entry.second = SMLoc(); - - // If this type number has never been uttered, create it. - if (!Entry.first) - Entry.first = StructType::create(Context, Name); - ResultTy = Entry.first; - return false; - } - - // If the type starts with '<', then it is either a packed struct or a vector. - bool isPacked = EatIfPresent(lltok::less); - - // If we don't have a struct, then we have a random type alias, which we - // accept for compatibility with old files. These types are not allowed to be - // forward referenced and not allowed to be recursive. - if (Lex.getKind() != lltok::lbrace) { - if (Entry.first) + + // If we have opaque, just return without filling in the definition for the + // struct. This counts as a definition as far as the .ll file goes. + if (EatIfPresent(lltok::kw_opaque)) { + // This type is being defined, so clear the location to indicate this. + Entry.second = SMLoc(); + + // If this type number has never been uttered, create it. + if (!Entry.first) + Entry.first = StructType::create(Context, Name); + ResultTy = Entry.first; + return false; + } + + // If the type starts with '<', then it is either a packed struct or a vector. + bool isPacked = EatIfPresent(lltok::less); + + // If we don't have a struct, then we have a random type alias, which we + // accept for compatibility with old files. These types are not allowed to be + // forward referenced and not allowed to be recursive. + if (Lex.getKind() != lltok::lbrace) { + if (Entry.first) return error(TypeLoc, "forward references to non-struct type"); - - ResultTy = nullptr; - if (isPacked) + + ResultTy = nullptr; + if (isPacked) return parseArrayVectorType(ResultTy, true); return parseType(ResultTy); - } - - // This type is being defined, so clear the location to indicate this. - Entry.second = SMLoc(); - - // If this type number has never been uttered, create it. - if (!Entry.first) - Entry.first = StructType::create(Context, Name); - - StructType *STy = cast<StructType>(Entry.first); - - SmallVector<Type*, 8> Body; + } + + // This type is being defined, so clear the location to indicate this. + Entry.second = SMLoc(); + + // If this type number has never been uttered, create it. + if (!Entry.first) + Entry.first = StructType::create(Context, Name); + + StructType *STy = cast<StructType>(Entry.first); + + SmallVector<Type*, 8> Body; if (parseStructBody(Body) || (isPacked && parseToken(lltok::greater, "expected '>' in packed struct"))) - return true; - - STy->setBody(Body, isPacked); - ResultTy = STy; - return false; -} - + return true; + + STy->setBody(Body, isPacked); + ResultTy = STy; + return false; +} + /// parseStructType: Handles packed and unpacked types. </> parsed elsewhere. -/// StructType -/// ::= '{' '}' -/// ::= '{' Type (',' Type)* '}' -/// ::= '<' '{' '}' '>' -/// ::= '<' '{' Type (',' Type)* '}' '>' +/// StructType +/// ::= '{' '}' +/// ::= '{' Type (',' Type)* '}' +/// ::= '<' '{' '}' '>' +/// ::= '<' '{' Type (',' Type)* '}' '>' bool LLParser::parseStructBody(SmallVectorImpl<Type *> &Body) { - assert(Lex.getKind() == lltok::lbrace); - Lex.Lex(); // Consume the '{' - - // Handle the empty struct. - if (EatIfPresent(lltok::rbrace)) - return false; - - LocTy EltTyLoc = Lex.getLoc(); - Type *Ty = nullptr; + assert(Lex.getKind() == lltok::lbrace); + Lex.Lex(); // Consume the '{' + + // Handle the empty struct. + if (EatIfPresent(lltok::rbrace)) + return false; + + LocTy EltTyLoc = Lex.getLoc(); + Type *Ty = nullptr; if (parseType(Ty)) return true; - Body.push_back(Ty); - - if (!StructType::isValidElementType(Ty)) + Body.push_back(Ty); + + if (!StructType::isValidElementType(Ty)) return error(EltTyLoc, "invalid element type for struct"); - - while (EatIfPresent(lltok::comma)) { - EltTyLoc = Lex.getLoc(); + + while (EatIfPresent(lltok::comma)) { + EltTyLoc = Lex.getLoc(); if (parseType(Ty)) return true; - - if (!StructType::isValidElementType(Ty)) + + if (!StructType::isValidElementType(Ty)) return error(EltTyLoc, "invalid element type for struct"); - - Body.push_back(Ty); - } - + + Body.push_back(Ty); + } + return parseToken(lltok::rbrace, "expected '}' at end of struct"); -} - +} + /// parseArrayVectorType - parse an array or vector type, assuming the first -/// token has already been consumed. -/// Type -/// ::= '[' APSINTVAL 'x' Types ']' -/// ::= '<' APSINTVAL 'x' Types '>' -/// ::= '<' 'vscale' 'x' APSINTVAL 'x' Types '>' +/// token has already been consumed. +/// Type +/// ::= '[' APSINTVAL 'x' Types ']' +/// ::= '<' APSINTVAL 'x' Types '>' +/// ::= '<' 'vscale' 'x' APSINTVAL 'x' Types '>' bool LLParser::parseArrayVectorType(Type *&Result, bool IsVector) { - bool Scalable = false; - + bool Scalable = false; + if (IsVector && Lex.getKind() == lltok::kw_vscale) { - Lex.Lex(); // consume the 'vscale' + Lex.Lex(); // consume the 'vscale' if (parseToken(lltok::kw_x, "expected 'x' after vscale")) - return true; - - Scalable = true; - } - - if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned() || - Lex.getAPSIntVal().getBitWidth() > 64) + return true; + + Scalable = true; + } + + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned() || + Lex.getAPSIntVal().getBitWidth() > 64) return tokError("expected number in address space"); - - LocTy SizeLoc = Lex.getLoc(); - uint64_t Size = Lex.getAPSIntVal().getZExtValue(); - Lex.Lex(); - + + LocTy SizeLoc = Lex.getLoc(); + uint64_t Size = Lex.getAPSIntVal().getZExtValue(); + Lex.Lex(); + if (parseToken(lltok::kw_x, "expected 'x' after element count")) return true; - - LocTy TypeLoc = Lex.getLoc(); - Type *EltTy = nullptr; + + LocTy TypeLoc = Lex.getLoc(); + Type *EltTy = nullptr; if (parseType(EltTy)) return true; - + if (parseToken(IsVector ? lltok::greater : lltok::rsquare, - "expected end of sequential type")) - return true; - + "expected end of sequential type")) + return true; + if (IsVector) { - if (Size == 0) + if (Size == 0) return error(SizeLoc, "zero element vector is illegal"); - if ((unsigned)Size != Size) + if ((unsigned)Size != Size) return error(SizeLoc, "size too large for vector"); - if (!VectorType::isValidElementType(EltTy)) + if (!VectorType::isValidElementType(EltTy)) return error(TypeLoc, "invalid vector element type"); - Result = VectorType::get(EltTy, unsigned(Size), Scalable); - } else { - if (!ArrayType::isValidElementType(EltTy)) + Result = VectorType::get(EltTy, unsigned(Size), Scalable); + } else { + if (!ArrayType::isValidElementType(EltTy)) return error(TypeLoc, "invalid array element type"); - Result = ArrayType::get(EltTy, Size); - } - return false; -} - -//===----------------------------------------------------------------------===// -// Function Semantic Analysis. -//===----------------------------------------------------------------------===// - -LLParser::PerFunctionState::PerFunctionState(LLParser &p, Function &f, - int functionNumber) - : P(p), F(f), FunctionNumber(functionNumber) { - - // Insert unnamed arguments into the NumberedVals list. - for (Argument &A : F.args()) - if (!A.hasName()) - NumberedVals.push_back(&A); -} - -LLParser::PerFunctionState::~PerFunctionState() { - // If there were any forward referenced non-basicblock values, delete them. - - for (const auto &P : ForwardRefVals) { - if (isa<BasicBlock>(P.second.first)) - continue; - P.second.first->replaceAllUsesWith( - UndefValue::get(P.second.first->getType())); - P.second.first->deleteValue(); - } - - for (const auto &P : ForwardRefValIDs) { - if (isa<BasicBlock>(P.second.first)) - continue; - P.second.first->replaceAllUsesWith( - UndefValue::get(P.second.first->getType())); - P.second.first->deleteValue(); - } -} - + Result = ArrayType::get(EltTy, Size); + } + return false; +} + +//===----------------------------------------------------------------------===// +// Function Semantic Analysis. +//===----------------------------------------------------------------------===// + +LLParser::PerFunctionState::PerFunctionState(LLParser &p, Function &f, + int functionNumber) + : P(p), F(f), FunctionNumber(functionNumber) { + + // Insert unnamed arguments into the NumberedVals list. + for (Argument &A : F.args()) + if (!A.hasName()) + NumberedVals.push_back(&A); +} + +LLParser::PerFunctionState::~PerFunctionState() { + // If there were any forward referenced non-basicblock values, delete them. + + for (const auto &P : ForwardRefVals) { + if (isa<BasicBlock>(P.second.first)) + continue; + P.second.first->replaceAllUsesWith( + UndefValue::get(P.second.first->getType())); + P.second.first->deleteValue(); + } + + for (const auto &P : ForwardRefValIDs) { + if (isa<BasicBlock>(P.second.first)) + continue; + P.second.first->replaceAllUsesWith( + UndefValue::get(P.second.first->getType())); + P.second.first->deleteValue(); + } +} + bool LLParser::PerFunctionState::finishFunction() { - if (!ForwardRefVals.empty()) + if (!ForwardRefVals.empty()) return P.error(ForwardRefVals.begin()->second.second, - "use of undefined value '%" + ForwardRefVals.begin()->first + + "use of undefined value '%" + ForwardRefVals.begin()->first + "'"); - if (!ForwardRefValIDs.empty()) + if (!ForwardRefValIDs.empty()) return P.error(ForwardRefValIDs.begin()->second.second, - "use of undefined value '%" + + "use of undefined value '%" + Twine(ForwardRefValIDs.begin()->first) + "'"); - return false; -} - + return false; +} + /// getVal - Get a value with the specified name or ID, creating a -/// forward reference record if needed. This can return null if the value -/// exists but does not have the right type. +/// forward reference record if needed. This can return null if the value +/// exists but does not have the right type. Value *LLParser::PerFunctionState::getVal(const std::string &Name, Type *Ty, - LocTy Loc, bool IsCall) { - // Look this name up in the normal function symbol table. - Value *Val = F.getValueSymbolTable()->lookup(Name); - - // If this is a forward reference for the value, see if we already created a - // forward ref record. - if (!Val) { - auto I = ForwardRefVals.find(Name); - if (I != ForwardRefVals.end()) - Val = I->second.first; - } - - // If we have the value in the symbol table or fwd-ref table, return it. - if (Val) - return P.checkValidVariableType(Loc, "%" + Name, Ty, Val, IsCall); - - // Don't make placeholders with invalid type. - if (!Ty->isFirstClassType()) { + LocTy Loc, bool IsCall) { + // Look this name up in the normal function symbol table. + Value *Val = F.getValueSymbolTable()->lookup(Name); + + // If this is a forward reference for the value, see if we already created a + // forward ref record. + if (!Val) { + auto I = ForwardRefVals.find(Name); + if (I != ForwardRefVals.end()) + Val = I->second.first; + } + + // If we have the value in the symbol table or fwd-ref table, return it. + if (Val) + return P.checkValidVariableType(Loc, "%" + Name, Ty, Val, IsCall); + + // Don't make placeholders with invalid type. + if (!Ty->isFirstClassType()) { P.error(Loc, "invalid use of a non-first-class type"); - return nullptr; - } - - // Otherwise, create a new forward reference for this value and remember it. - Value *FwdVal; - if (Ty->isLabelTy()) { - FwdVal = BasicBlock::Create(F.getContext(), Name, &F); - } else { - FwdVal = new Argument(Ty, Name); - } - - ForwardRefVals[Name] = std::make_pair(FwdVal, Loc); - return FwdVal; -} - + return nullptr; + } + + // Otherwise, create a new forward reference for this value and remember it. + Value *FwdVal; + if (Ty->isLabelTy()) { + FwdVal = BasicBlock::Create(F.getContext(), Name, &F); + } else { + FwdVal = new Argument(Ty, Name); + } + + ForwardRefVals[Name] = std::make_pair(FwdVal, Loc); + return FwdVal; +} + Value *LLParser::PerFunctionState::getVal(unsigned ID, Type *Ty, LocTy Loc, - bool IsCall) { - // Look this name up in the normal function symbol table. - Value *Val = ID < NumberedVals.size() ? NumberedVals[ID] : nullptr; - - // If this is a forward reference for the value, see if we already created a - // forward ref record. - if (!Val) { - auto I = ForwardRefValIDs.find(ID); - if (I != ForwardRefValIDs.end()) - Val = I->second.first; - } - - // If we have the value in the symbol table or fwd-ref table, return it. - if (Val) - return P.checkValidVariableType(Loc, "%" + Twine(ID), Ty, Val, IsCall); - - if (!Ty->isFirstClassType()) { + bool IsCall) { + // Look this name up in the normal function symbol table. + Value *Val = ID < NumberedVals.size() ? NumberedVals[ID] : nullptr; + + // If this is a forward reference for the value, see if we already created a + // forward ref record. + if (!Val) { + auto I = ForwardRefValIDs.find(ID); + if (I != ForwardRefValIDs.end()) + Val = I->second.first; + } + + // If we have the value in the symbol table or fwd-ref table, return it. + if (Val) + return P.checkValidVariableType(Loc, "%" + Twine(ID), Ty, Val, IsCall); + + if (!Ty->isFirstClassType()) { P.error(Loc, "invalid use of a non-first-class type"); - return nullptr; - } - - // Otherwise, create a new forward reference for this value and remember it. - Value *FwdVal; - if (Ty->isLabelTy()) { - FwdVal = BasicBlock::Create(F.getContext(), "", &F); - } else { - FwdVal = new Argument(Ty); - } - - ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc); - return FwdVal; -} - + return nullptr; + } + + // Otherwise, create a new forward reference for this value and remember it. + Value *FwdVal; + if (Ty->isLabelTy()) { + FwdVal = BasicBlock::Create(F.getContext(), "", &F); + } else { + FwdVal = new Argument(Ty); + } + + ForwardRefValIDs[ID] = std::make_pair(FwdVal, Loc); + return FwdVal; +} + /// setInstName - After an instruction is parsed and inserted into its -/// basic block, this installs its name. +/// basic block, this installs its name. bool LLParser::PerFunctionState::setInstName(int NameID, - const std::string &NameStr, - LocTy NameLoc, Instruction *Inst) { - // If this instruction has void type, it cannot have a name or ID specified. - if (Inst->getType()->isVoidTy()) { - if (NameID != -1 || !NameStr.empty()) + const std::string &NameStr, + LocTy NameLoc, Instruction *Inst) { + // If this instruction has void type, it cannot have a name or ID specified. + if (Inst->getType()->isVoidTy()) { + if (NameID != -1 || !NameStr.empty()) return P.error(NameLoc, "instructions returning void cannot have a name"); - return false; - } - - // If this was a numbered instruction, verify that the instruction is the - // expected value and resolve any forward references. - if (NameStr.empty()) { - // If neither a name nor an ID was specified, just use the next ID. - if (NameID == -1) - NameID = NumberedVals.size(); - - if (unsigned(NameID) != NumberedVals.size()) + return false; + } + + // If this was a numbered instruction, verify that the instruction is the + // expected value and resolve any forward references. + if (NameStr.empty()) { + // If neither a name nor an ID was specified, just use the next ID. + if (NameID == -1) + NameID = NumberedVals.size(); + + if (unsigned(NameID) != NumberedVals.size()) return P.error(NameLoc, "instruction expected to be numbered '%" + Twine(NumberedVals.size()) + "'"); - - auto FI = ForwardRefValIDs.find(NameID); - if (FI != ForwardRefValIDs.end()) { - Value *Sentinel = FI->second.first; - if (Sentinel->getType() != Inst->getType()) + + auto FI = ForwardRefValIDs.find(NameID); + if (FI != ForwardRefValIDs.end()) { + Value *Sentinel = FI->second.first; + if (Sentinel->getType() != Inst->getType()) return P.error(NameLoc, "instruction forward referenced with type '" + getTypeString(FI->second.first->getType()) + "'"); - - Sentinel->replaceAllUsesWith(Inst); - Sentinel->deleteValue(); - ForwardRefValIDs.erase(FI); - } - - NumberedVals.push_back(Inst); - return false; - } - - // Otherwise, the instruction had a name. Resolve forward refs and set it. - auto FI = ForwardRefVals.find(NameStr); - if (FI != ForwardRefVals.end()) { - Value *Sentinel = FI->second.first; - if (Sentinel->getType() != Inst->getType()) + + Sentinel->replaceAllUsesWith(Inst); + Sentinel->deleteValue(); + ForwardRefValIDs.erase(FI); + } + + NumberedVals.push_back(Inst); + return false; + } + + // Otherwise, the instruction had a name. Resolve forward refs and set it. + auto FI = ForwardRefVals.find(NameStr); + if (FI != ForwardRefVals.end()) { + Value *Sentinel = FI->second.first; + if (Sentinel->getType() != Inst->getType()) return P.error(NameLoc, "instruction forward referenced with type '" + getTypeString(FI->second.first->getType()) + "'"); - - Sentinel->replaceAllUsesWith(Inst); - Sentinel->deleteValue(); - ForwardRefVals.erase(FI); - } - - // Set the name on the instruction. - Inst->setName(NameStr); - - if (Inst->getName() != NameStr) + + Sentinel->replaceAllUsesWith(Inst); + Sentinel->deleteValue(); + ForwardRefVals.erase(FI); + } + + // Set the name on the instruction. + Inst->setName(NameStr); + + if (Inst->getName() != NameStr) return P.error(NameLoc, "multiple definition of local value named '" + NameStr + "'"); - return false; -} - + return false; +} + /// getBB - Get a basic block with the specified name or ID, creating a -/// forward reference record if needed. +/// forward reference record if needed. BasicBlock *LLParser::PerFunctionState::getBB(const std::string &Name, - LocTy Loc) { - return dyn_cast_or_null<BasicBlock>( + LocTy Loc) { + return dyn_cast_or_null<BasicBlock>( getVal(Name, Type::getLabelTy(F.getContext()), Loc, /*IsCall=*/false)); -} - +} + BasicBlock *LLParser::PerFunctionState::getBB(unsigned ID, LocTy Loc) { - return dyn_cast_or_null<BasicBlock>( + return dyn_cast_or_null<BasicBlock>( getVal(ID, Type::getLabelTy(F.getContext()), Loc, /*IsCall=*/false)); -} - +} + /// defineBB - Define the specified basic block, which is either named or -/// unnamed. If there is an error, this returns null otherwise it returns -/// the block being defined. +/// unnamed. If there is an error, this returns null otherwise it returns +/// the block being defined. BasicBlock *LLParser::PerFunctionState::defineBB(const std::string &Name, - int NameID, LocTy Loc) { - BasicBlock *BB; - if (Name.empty()) { - if (NameID != -1 && unsigned(NameID) != NumberedVals.size()) { + int NameID, LocTy Loc) { + BasicBlock *BB; + if (Name.empty()) { + if (NameID != -1 && unsigned(NameID) != NumberedVals.size()) { P.error(Loc, "label expected to be numbered '" + - Twine(NumberedVals.size()) + "'"); - return nullptr; - } + Twine(NumberedVals.size()) + "'"); + return nullptr; + } BB = getBB(NumberedVals.size(), Loc); - if (!BB) { + if (!BB) { P.error(Loc, "unable to create block numbered '" + - Twine(NumberedVals.size()) + "'"); - return nullptr; - } - } else { + Twine(NumberedVals.size()) + "'"); + return nullptr; + } + } else { BB = getBB(Name, Loc); - if (!BB) { + if (!BB) { P.error(Loc, "unable to create block named '" + Name + "'"); - return nullptr; - } - } - - // Move the block to the end of the function. Forward ref'd blocks are - // inserted wherever they happen to be referenced. - F.getBasicBlockList().splice(F.end(), F.getBasicBlockList(), BB); - - // Remove the block from forward ref sets. - if (Name.empty()) { - ForwardRefValIDs.erase(NumberedVals.size()); - NumberedVals.push_back(BB); - } else { - // BB forward references are already in the function symbol table. - ForwardRefVals.erase(Name); - } - - return BB; -} - -//===----------------------------------------------------------------------===// -// Constants. -//===----------------------------------------------------------------------===// - + return nullptr; + } + } + + // Move the block to the end of the function. Forward ref'd blocks are + // inserted wherever they happen to be referenced. + F.getBasicBlockList().splice(F.end(), F.getBasicBlockList(), BB); + + // Remove the block from forward ref sets. + if (Name.empty()) { + ForwardRefValIDs.erase(NumberedVals.size()); + NumberedVals.push_back(BB); + } else { + // BB forward references are already in the function symbol table. + ForwardRefVals.erase(Name); + } + + return BB; +} + +//===----------------------------------------------------------------------===// +// Constants. +//===----------------------------------------------------------------------===// + /// parseValID - parse an abstract value that doesn't necessarily have a -/// type implied. For example, if we parse "4" we don't know what integer type -/// it has. The value will later be combined with its type and checked for -/// sanity. PFS is used to convert function-local operands of metadata (since -/// metadata operands are not just parsed here but also converted to values). -/// PFS can be null when we are not parsing metadata values inside a function. +/// type implied. For example, if we parse "4" we don't know what integer type +/// it has. The value will later be combined with its type and checked for +/// sanity. PFS is used to convert function-local operands of metadata (since +/// metadata operands are not just parsed here but also converted to values). +/// PFS can be null when we are not parsing metadata values inside a function. bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS) { - ID.Loc = Lex.getLoc(); - switch (Lex.getKind()) { + ID.Loc = Lex.getLoc(); + switch (Lex.getKind()) { default: return tokError("expected value token"); - case lltok::GlobalID: // @42 - ID.UIntVal = Lex.getUIntVal(); - ID.Kind = ValID::t_GlobalID; - break; - case lltok::GlobalVar: // @foo - ID.StrVal = Lex.getStrVal(); - ID.Kind = ValID::t_GlobalName; - break; - case lltok::LocalVarID: // %42 - ID.UIntVal = Lex.getUIntVal(); - ID.Kind = ValID::t_LocalID; - break; - case lltok::LocalVar: // %foo - ID.StrVal = Lex.getStrVal(); - ID.Kind = ValID::t_LocalName; - break; - case lltok::APSInt: - ID.APSIntVal = Lex.getAPSIntVal(); - ID.Kind = ValID::t_APSInt; - break; - case lltok::APFloat: - ID.APFloatVal = Lex.getAPFloatVal(); - ID.Kind = ValID::t_APFloat; - break; - case lltok::kw_true: - ID.ConstantVal = ConstantInt::getTrue(Context); - ID.Kind = ValID::t_Constant; - break; - case lltok::kw_false: - ID.ConstantVal = ConstantInt::getFalse(Context); - ID.Kind = ValID::t_Constant; - break; - case lltok::kw_null: ID.Kind = ValID::t_Null; break; - case lltok::kw_undef: ID.Kind = ValID::t_Undef; break; + case lltok::GlobalID: // @42 + ID.UIntVal = Lex.getUIntVal(); + ID.Kind = ValID::t_GlobalID; + break; + case lltok::GlobalVar: // @foo + ID.StrVal = Lex.getStrVal(); + ID.Kind = ValID::t_GlobalName; + break; + case lltok::LocalVarID: // %42 + ID.UIntVal = Lex.getUIntVal(); + ID.Kind = ValID::t_LocalID; + break; + case lltok::LocalVar: // %foo + ID.StrVal = Lex.getStrVal(); + ID.Kind = ValID::t_LocalName; + break; + case lltok::APSInt: + ID.APSIntVal = Lex.getAPSIntVal(); + ID.Kind = ValID::t_APSInt; + break; + case lltok::APFloat: + ID.APFloatVal = Lex.getAPFloatVal(); + ID.Kind = ValID::t_APFloat; + break; + case lltok::kw_true: + ID.ConstantVal = ConstantInt::getTrue(Context); + ID.Kind = ValID::t_Constant; + break; + case lltok::kw_false: + ID.ConstantVal = ConstantInt::getFalse(Context); + ID.Kind = ValID::t_Constant; + break; + case lltok::kw_null: ID.Kind = ValID::t_Null; break; + case lltok::kw_undef: ID.Kind = ValID::t_Undef; break; case lltok::kw_poison: ID.Kind = ValID::t_Poison; break; - case lltok::kw_zeroinitializer: ID.Kind = ValID::t_Zero; break; - case lltok::kw_none: ID.Kind = ValID::t_None; break; - - case lltok::lbrace: { - // ValID ::= '{' ConstVector '}' - Lex.Lex(); - SmallVector<Constant*, 16> Elts; + case lltok::kw_zeroinitializer: ID.Kind = ValID::t_Zero; break; + case lltok::kw_none: ID.Kind = ValID::t_None; break; + + case lltok::lbrace: { + // ValID ::= '{' ConstVector '}' + Lex.Lex(); + SmallVector<Constant*, 16> Elts; if (parseGlobalValueVector(Elts) || parseToken(lltok::rbrace, "expected end of struct constant")) - return true; - - ID.ConstantStructElts = std::make_unique<Constant *[]>(Elts.size()); - ID.UIntVal = Elts.size(); - memcpy(ID.ConstantStructElts.get(), Elts.data(), - Elts.size() * sizeof(Elts[0])); - ID.Kind = ValID::t_ConstantStruct; - return false; - } - case lltok::less: { - // ValID ::= '<' ConstVector '>' --> Vector. - // ValID ::= '<' '{' ConstVector '}' '>' --> Packed Struct. - Lex.Lex(); - bool isPackedStruct = EatIfPresent(lltok::lbrace); - - SmallVector<Constant*, 16> Elts; - LocTy FirstEltLoc = Lex.getLoc(); + return true; + + ID.ConstantStructElts = std::make_unique<Constant *[]>(Elts.size()); + ID.UIntVal = Elts.size(); + memcpy(ID.ConstantStructElts.get(), Elts.data(), + Elts.size() * sizeof(Elts[0])); + ID.Kind = ValID::t_ConstantStruct; + return false; + } + case lltok::less: { + // ValID ::= '<' ConstVector '>' --> Vector. + // ValID ::= '<' '{' ConstVector '}' '>' --> Packed Struct. + Lex.Lex(); + bool isPackedStruct = EatIfPresent(lltok::lbrace); + + SmallVector<Constant*, 16> Elts; + LocTy FirstEltLoc = Lex.getLoc(); if (parseGlobalValueVector(Elts) || - (isPackedStruct && + (isPackedStruct && parseToken(lltok::rbrace, "expected end of packed struct")) || parseToken(lltok::greater, "expected end of constant")) - return true; - - if (isPackedStruct) { - ID.ConstantStructElts = std::make_unique<Constant *[]>(Elts.size()); - memcpy(ID.ConstantStructElts.get(), Elts.data(), - Elts.size() * sizeof(Elts[0])); - ID.UIntVal = Elts.size(); - ID.Kind = ValID::t_PackedConstantStruct; - return false; - } - - if (Elts.empty()) + return true; + + if (isPackedStruct) { + ID.ConstantStructElts = std::make_unique<Constant *[]>(Elts.size()); + memcpy(ID.ConstantStructElts.get(), Elts.data(), + Elts.size() * sizeof(Elts[0])); + ID.UIntVal = Elts.size(); + ID.Kind = ValID::t_PackedConstantStruct; + return false; + } + + if (Elts.empty()) return error(ID.Loc, "constant vector must not be empty"); - - if (!Elts[0]->getType()->isIntegerTy() && - !Elts[0]->getType()->isFloatingPointTy() && - !Elts[0]->getType()->isPointerTy()) + + if (!Elts[0]->getType()->isIntegerTy() && + !Elts[0]->getType()->isFloatingPointTy() && + !Elts[0]->getType()->isPointerTy()) return error( FirstEltLoc, "vector elements must have integer, pointer or floating point type"); - - // Verify that all the vector elements have the same type. - for (unsigned i = 1, e = Elts.size(); i != e; ++i) - if (Elts[i]->getType() != Elts[0]->getType()) + + // Verify that all the vector elements have the same type. + for (unsigned i = 1, e = Elts.size(); i != e; ++i) + if (Elts[i]->getType() != Elts[0]->getType()) return error(FirstEltLoc, "vector element #" + Twine(i) + " is not of type '" + getTypeString(Elts[0]->getType())); - - ID.ConstantVal = ConstantVector::get(Elts); - ID.Kind = ValID::t_Constant; - return false; - } - case lltok::lsquare: { // Array Constant - Lex.Lex(); - SmallVector<Constant*, 16> Elts; - LocTy FirstEltLoc = Lex.getLoc(); + + ID.ConstantVal = ConstantVector::get(Elts); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::lsquare: { // Array Constant + Lex.Lex(); + SmallVector<Constant*, 16> Elts; + LocTy FirstEltLoc = Lex.getLoc(); if (parseGlobalValueVector(Elts) || parseToken(lltok::rsquare, "expected end of array constant")) - return true; - - // Handle empty element. - if (Elts.empty()) { - // Use undef instead of an array because it's inconvenient to determine - // the element type at this point, there being no elements to examine. - ID.Kind = ValID::t_EmptyArray; - return false; - } - - if (!Elts[0]->getType()->isFirstClassType()) + return true; + + // Handle empty element. + if (Elts.empty()) { + // Use undef instead of an array because it's inconvenient to determine + // the element type at this point, there being no elements to examine. + ID.Kind = ValID::t_EmptyArray; + return false; + } + + if (!Elts[0]->getType()->isFirstClassType()) return error(FirstEltLoc, "invalid array element type: " + getTypeString(Elts[0]->getType())); - - ArrayType *ATy = ArrayType::get(Elts[0]->getType(), Elts.size()); - - // Verify all elements are correct type! - for (unsigned i = 0, e = Elts.size(); i != e; ++i) { - if (Elts[i]->getType() != Elts[0]->getType()) + + ArrayType *ATy = ArrayType::get(Elts[0]->getType(), Elts.size()); + + // Verify all elements are correct type! + for (unsigned i = 0, e = Elts.size(); i != e; ++i) { + if (Elts[i]->getType() != Elts[0]->getType()) return error(FirstEltLoc, "array element #" + Twine(i) + " is not of type '" + getTypeString(Elts[0]->getType())); - } - - ID.ConstantVal = ConstantArray::get(ATy, Elts); - ID.Kind = ValID::t_Constant; - return false; - } - case lltok::kw_c: // c "foo" - Lex.Lex(); - ID.ConstantVal = ConstantDataArray::getString(Context, Lex.getStrVal(), - false); + } + + ID.ConstantVal = ConstantArray::get(ATy, Elts); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::kw_c: // c "foo" + Lex.Lex(); + ID.ConstantVal = ConstantDataArray::getString(Context, Lex.getStrVal(), + false); if (parseToken(lltok::StringConstant, "expected string")) return true; - ID.Kind = ValID::t_Constant; - return false; - - case lltok::kw_asm: { - // ValID ::= 'asm' SideEffect? AlignStack? IntelDialect? STRINGCONSTANT ',' - // STRINGCONSTANT - bool HasSideEffect, AlignStack, AsmDialect; - Lex.Lex(); + ID.Kind = ValID::t_Constant; + return false; + + case lltok::kw_asm: { + // ValID ::= 'asm' SideEffect? AlignStack? IntelDialect? STRINGCONSTANT ',' + // STRINGCONSTANT + bool HasSideEffect, AlignStack, AsmDialect; + Lex.Lex(); if (parseOptionalToken(lltok::kw_sideeffect, HasSideEffect) || parseOptionalToken(lltok::kw_alignstack, AlignStack) || parseOptionalToken(lltok::kw_inteldialect, AsmDialect) || parseStringConstant(ID.StrVal) || parseToken(lltok::comma, "expected comma in inline asm expression") || parseToken(lltok::StringConstant, "expected constraint string")) - return true; - ID.StrVal2 = Lex.getStrVal(); - ID.UIntVal = unsigned(HasSideEffect) | (unsigned(AlignStack)<<1) | - (unsigned(AsmDialect)<<2); - ID.Kind = ValID::t_InlineAsm; - return false; - } - - case lltok::kw_blockaddress: { - // ValID ::= 'blockaddress' '(' @foo ',' %bar ')' - Lex.Lex(); - - ValID Fn, Label; - + return true; + ID.StrVal2 = Lex.getStrVal(); + ID.UIntVal = unsigned(HasSideEffect) | (unsigned(AlignStack)<<1) | + (unsigned(AsmDialect)<<2); + ID.Kind = ValID::t_InlineAsm; + return false; + } + + case lltok::kw_blockaddress: { + // ValID ::= 'blockaddress' '(' @foo ',' %bar ')' + Lex.Lex(); + + ValID Fn, Label; + if (parseToken(lltok::lparen, "expected '(' in block address expression") || parseValID(Fn) || parseToken(lltok::comma, "expected comma in block address expression") || parseValID(Label) || parseToken(lltok::rparen, "expected ')' in block address expression")) - return true; - - if (Fn.Kind != ValID::t_GlobalID && Fn.Kind != ValID::t_GlobalName) + return true; + + if (Fn.Kind != ValID::t_GlobalID && Fn.Kind != ValID::t_GlobalName) return error(Fn.Loc, "expected function name in blockaddress"); - if (Label.Kind != ValID::t_LocalID && Label.Kind != ValID::t_LocalName) + if (Label.Kind != ValID::t_LocalID && Label.Kind != ValID::t_LocalName) return error(Label.Loc, "expected basic block name in blockaddress"); - - // Try to find the function (but skip it if it's forward-referenced). - GlobalValue *GV = nullptr; - if (Fn.Kind == ValID::t_GlobalID) { - if (Fn.UIntVal < NumberedVals.size()) - GV = NumberedVals[Fn.UIntVal]; - } else if (!ForwardRefVals.count(Fn.StrVal)) { - GV = M->getNamedValue(Fn.StrVal); - } - Function *F = nullptr; - if (GV) { - // Confirm that it's actually a function with a definition. - if (!isa<Function>(GV)) + + // Try to find the function (but skip it if it's forward-referenced). + GlobalValue *GV = nullptr; + if (Fn.Kind == ValID::t_GlobalID) { + if (Fn.UIntVal < NumberedVals.size()) + GV = NumberedVals[Fn.UIntVal]; + } else if (!ForwardRefVals.count(Fn.StrVal)) { + GV = M->getNamedValue(Fn.StrVal); + } + Function *F = nullptr; + if (GV) { + // Confirm that it's actually a function with a definition. + if (!isa<Function>(GV)) return error(Fn.Loc, "expected function name in blockaddress"); - F = cast<Function>(GV); - if (F->isDeclaration()) + F = cast<Function>(GV); + if (F->isDeclaration()) return error(Fn.Loc, "cannot take blockaddress inside a declaration"); - } - - if (!F) { - // Make a global variable as a placeholder for this reference. - GlobalValue *&FwdRef = - ForwardRefBlockAddresses.insert(std::make_pair( - std::move(Fn), - std::map<ValID, GlobalValue *>())) - .first->second.insert(std::make_pair(std::move(Label), nullptr)) - .first->second; - if (!FwdRef) - FwdRef = new GlobalVariable(*M, Type::getInt8Ty(Context), false, - GlobalValue::InternalLinkage, nullptr, ""); - ID.ConstantVal = FwdRef; - ID.Kind = ValID::t_Constant; - return false; - } - - // We found the function; now find the basic block. Don't use PFS, since we - // might be inside a constant expression. - BasicBlock *BB; - if (BlockAddressPFS && F == &BlockAddressPFS->getFunction()) { - if (Label.Kind == ValID::t_LocalID) + } + + if (!F) { + // Make a global variable as a placeholder for this reference. + GlobalValue *&FwdRef = + ForwardRefBlockAddresses.insert(std::make_pair( + std::move(Fn), + std::map<ValID, GlobalValue *>())) + .first->second.insert(std::make_pair(std::move(Label), nullptr)) + .first->second; + if (!FwdRef) + FwdRef = new GlobalVariable(*M, Type::getInt8Ty(Context), false, + GlobalValue::InternalLinkage, nullptr, ""); + ID.ConstantVal = FwdRef; + ID.Kind = ValID::t_Constant; + return false; + } + + // We found the function; now find the basic block. Don't use PFS, since we + // might be inside a constant expression. + BasicBlock *BB; + if (BlockAddressPFS && F == &BlockAddressPFS->getFunction()) { + if (Label.Kind == ValID::t_LocalID) BB = BlockAddressPFS->getBB(Label.UIntVal, Label.Loc); - else + else BB = BlockAddressPFS->getBB(Label.StrVal, Label.Loc); - if (!BB) + if (!BB) return error(Label.Loc, "referenced value is not a basic block"); - } else { - if (Label.Kind == ValID::t_LocalID) + } else { + if (Label.Kind == ValID::t_LocalID) return error(Label.Loc, "cannot take address of numeric label after " - "the function is defined"); - BB = dyn_cast_or_null<BasicBlock>( - F->getValueSymbolTable()->lookup(Label.StrVal)); - if (!BB) + "the function is defined"); + BB = dyn_cast_or_null<BasicBlock>( + F->getValueSymbolTable()->lookup(Label.StrVal)); + if (!BB) return error(Label.Loc, "referenced value is not a basic block"); - } - - ID.ConstantVal = BlockAddress::get(F, BB); - ID.Kind = ValID::t_Constant; - return false; - } - + } + + ID.ConstantVal = BlockAddress::get(F, BB); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::kw_dso_local_equivalent: { // ValID ::= 'dso_local_equivalent' @foo Lex.Lex(); @@ -3516,1092 +3516,1092 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS) { return false; } - case lltok::kw_trunc: - case lltok::kw_zext: - case lltok::kw_sext: - case lltok::kw_fptrunc: - case lltok::kw_fpext: - case lltok::kw_bitcast: - case lltok::kw_addrspacecast: - case lltok::kw_uitofp: - case lltok::kw_sitofp: - case lltok::kw_fptoui: - case lltok::kw_fptosi: - case lltok::kw_inttoptr: - case lltok::kw_ptrtoint: { - unsigned Opc = Lex.getUIntVal(); - Type *DestTy = nullptr; - Constant *SrcVal; - Lex.Lex(); + case lltok::kw_trunc: + case lltok::kw_zext: + case lltok::kw_sext: + case lltok::kw_fptrunc: + case lltok::kw_fpext: + case lltok::kw_bitcast: + case lltok::kw_addrspacecast: + case lltok::kw_uitofp: + case lltok::kw_sitofp: + case lltok::kw_fptoui: + case lltok::kw_fptosi: + case lltok::kw_inttoptr: + case lltok::kw_ptrtoint: { + unsigned Opc = Lex.getUIntVal(); + Type *DestTy = nullptr; + Constant *SrcVal; + Lex.Lex(); if (parseToken(lltok::lparen, "expected '(' after constantexpr cast") || parseGlobalTypeAndValue(SrcVal) || parseToken(lltok::kw_to, "expected 'to' in constantexpr cast") || parseType(DestTy) || parseToken(lltok::rparen, "expected ')' at end of constantexpr cast")) - return true; - if (!CastInst::castIsValid((Instruction::CastOps)Opc, SrcVal, DestTy)) + return true; + if (!CastInst::castIsValid((Instruction::CastOps)Opc, SrcVal, DestTy)) return error(ID.Loc, "invalid cast opcode for cast from '" + getTypeString(SrcVal->getType()) + "' to '" + getTypeString(DestTy) + "'"); - ID.ConstantVal = ConstantExpr::getCast((Instruction::CastOps)Opc, - SrcVal, DestTy); - ID.Kind = ValID::t_Constant; - return false; - } - case lltok::kw_extractvalue: { - Lex.Lex(); - Constant *Val; - SmallVector<unsigned, 4> Indices; + ID.ConstantVal = ConstantExpr::getCast((Instruction::CastOps)Opc, + SrcVal, DestTy); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::kw_extractvalue: { + Lex.Lex(); + Constant *Val; + SmallVector<unsigned, 4> Indices; if (parseToken(lltok::lparen, "expected '(' in extractvalue constantexpr") || parseGlobalTypeAndValue(Val) || parseIndexList(Indices) || parseToken(lltok::rparen, "expected ')' in extractvalue constantexpr")) - return true; - - if (!Val->getType()->isAggregateType()) + return true; + + if (!Val->getType()->isAggregateType()) return error(ID.Loc, "extractvalue operand must be aggregate type"); - if (!ExtractValueInst::getIndexedType(Val->getType(), Indices)) + if (!ExtractValueInst::getIndexedType(Val->getType(), Indices)) return error(ID.Loc, "invalid indices for extractvalue"); - ID.ConstantVal = ConstantExpr::getExtractValue(Val, Indices); - ID.Kind = ValID::t_Constant; - return false; - } - case lltok::kw_insertvalue: { - Lex.Lex(); - Constant *Val0, *Val1; - SmallVector<unsigned, 4> Indices; + ID.ConstantVal = ConstantExpr::getExtractValue(Val, Indices); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::kw_insertvalue: { + Lex.Lex(); + Constant *Val0, *Val1; + SmallVector<unsigned, 4> Indices; if (parseToken(lltok::lparen, "expected '(' in insertvalue constantexpr") || parseGlobalTypeAndValue(Val0) || parseToken(lltok::comma, "expected comma in insertvalue constantexpr") || parseGlobalTypeAndValue(Val1) || parseIndexList(Indices) || parseToken(lltok::rparen, "expected ')' in insertvalue constantexpr")) - return true; - if (!Val0->getType()->isAggregateType()) + return true; + if (!Val0->getType()->isAggregateType()) return error(ID.Loc, "insertvalue operand must be aggregate type"); - Type *IndexedType = - ExtractValueInst::getIndexedType(Val0->getType(), Indices); - if (!IndexedType) + Type *IndexedType = + ExtractValueInst::getIndexedType(Val0->getType(), Indices); + if (!IndexedType) return error(ID.Loc, "invalid indices for insertvalue"); - if (IndexedType != Val1->getType()) + if (IndexedType != Val1->getType()) return error(ID.Loc, "insertvalue operand and field disagree in type: '" + - getTypeString(Val1->getType()) + - "' instead of '" + getTypeString(IndexedType) + - "'"); - ID.ConstantVal = ConstantExpr::getInsertValue(Val0, Val1, Indices); - ID.Kind = ValID::t_Constant; - return false; - } - case lltok::kw_icmp: - case lltok::kw_fcmp: { - unsigned PredVal, Opc = Lex.getUIntVal(); - Constant *Val0, *Val1; - Lex.Lex(); + getTypeString(Val1->getType()) + + "' instead of '" + getTypeString(IndexedType) + + "'"); + ID.ConstantVal = ConstantExpr::getInsertValue(Val0, Val1, Indices); + ID.Kind = ValID::t_Constant; + return false; + } + case lltok::kw_icmp: + case lltok::kw_fcmp: { + unsigned PredVal, Opc = Lex.getUIntVal(); + Constant *Val0, *Val1; + Lex.Lex(); if (parseCmpPredicate(PredVal, Opc) || parseToken(lltok::lparen, "expected '(' in compare constantexpr") || parseGlobalTypeAndValue(Val0) || parseToken(lltok::comma, "expected comma in compare constantexpr") || parseGlobalTypeAndValue(Val1) || parseToken(lltok::rparen, "expected ')' in compare constantexpr")) - return true; - - if (Val0->getType() != Val1->getType()) + return true; + + if (Val0->getType() != Val1->getType()) return error(ID.Loc, "compare operands must have the same type"); - - CmpInst::Predicate Pred = (CmpInst::Predicate)PredVal; - - if (Opc == Instruction::FCmp) { - if (!Val0->getType()->isFPOrFPVectorTy()) + + CmpInst::Predicate Pred = (CmpInst::Predicate)PredVal; + + if (Opc == Instruction::FCmp) { + if (!Val0->getType()->isFPOrFPVectorTy()) return error(ID.Loc, "fcmp requires floating point operands"); - ID.ConstantVal = ConstantExpr::getFCmp(Pred, Val0, Val1); - } else { - assert(Opc == Instruction::ICmp && "Unexpected opcode for CmpInst!"); - if (!Val0->getType()->isIntOrIntVectorTy() && - !Val0->getType()->isPtrOrPtrVectorTy()) + ID.ConstantVal = ConstantExpr::getFCmp(Pred, Val0, Val1); + } else { + assert(Opc == Instruction::ICmp && "Unexpected opcode for CmpInst!"); + if (!Val0->getType()->isIntOrIntVectorTy() && + !Val0->getType()->isPtrOrPtrVectorTy()) return error(ID.Loc, "icmp requires pointer or integer operands"); - ID.ConstantVal = ConstantExpr::getICmp(Pred, Val0, Val1); - } - ID.Kind = ValID::t_Constant; - return false; - } - - // Unary Operators. - case lltok::kw_fneg: { - unsigned Opc = Lex.getUIntVal(); - Constant *Val; - Lex.Lex(); + ID.ConstantVal = ConstantExpr::getICmp(Pred, Val0, Val1); + } + ID.Kind = ValID::t_Constant; + return false; + } + + // Unary Operators. + case lltok::kw_fneg: { + unsigned Opc = Lex.getUIntVal(); + Constant *Val; + Lex.Lex(); if (parseToken(lltok::lparen, "expected '(' in unary constantexpr") || parseGlobalTypeAndValue(Val) || parseToken(lltok::rparen, "expected ')' in unary constantexpr")) - return true; - - // Check that the type is valid for the operator. - switch (Opc) { - case Instruction::FNeg: - if (!Val->getType()->isFPOrFPVectorTy()) + return true; + + // Check that the type is valid for the operator. + switch (Opc) { + case Instruction::FNeg: + if (!Val->getType()->isFPOrFPVectorTy()) return error(ID.Loc, "constexpr requires fp operands"); - break; - default: llvm_unreachable("Unknown unary operator!"); - } - unsigned Flags = 0; - Constant *C = ConstantExpr::get(Opc, Val, Flags); - ID.ConstantVal = C; - ID.Kind = ValID::t_Constant; - return false; - } - // Binary Operators. - case lltok::kw_add: - case lltok::kw_fadd: - case lltok::kw_sub: - case lltok::kw_fsub: - case lltok::kw_mul: - case lltok::kw_fmul: - case lltok::kw_udiv: - case lltok::kw_sdiv: - case lltok::kw_fdiv: - case lltok::kw_urem: - case lltok::kw_srem: - case lltok::kw_frem: - case lltok::kw_shl: - case lltok::kw_lshr: - case lltok::kw_ashr: { - bool NUW = false; - bool NSW = false; - bool Exact = false; - unsigned Opc = Lex.getUIntVal(); - Constant *Val0, *Val1; - Lex.Lex(); - if (Opc == Instruction::Add || Opc == Instruction::Sub || - Opc == Instruction::Mul || Opc == Instruction::Shl) { - if (EatIfPresent(lltok::kw_nuw)) - NUW = true; - if (EatIfPresent(lltok::kw_nsw)) { - NSW = true; - if (EatIfPresent(lltok::kw_nuw)) - NUW = true; - } - } else if (Opc == Instruction::SDiv || Opc == Instruction::UDiv || - Opc == Instruction::LShr || Opc == Instruction::AShr) { - if (EatIfPresent(lltok::kw_exact)) - Exact = true; - } + break; + default: llvm_unreachable("Unknown unary operator!"); + } + unsigned Flags = 0; + Constant *C = ConstantExpr::get(Opc, Val, Flags); + ID.ConstantVal = C; + ID.Kind = ValID::t_Constant; + return false; + } + // Binary Operators. + case lltok::kw_add: + case lltok::kw_fadd: + case lltok::kw_sub: + case lltok::kw_fsub: + case lltok::kw_mul: + case lltok::kw_fmul: + case lltok::kw_udiv: + case lltok::kw_sdiv: + case lltok::kw_fdiv: + case lltok::kw_urem: + case lltok::kw_srem: + case lltok::kw_frem: + case lltok::kw_shl: + case lltok::kw_lshr: + case lltok::kw_ashr: { + bool NUW = false; + bool NSW = false; + bool Exact = false; + unsigned Opc = Lex.getUIntVal(); + Constant *Val0, *Val1; + Lex.Lex(); + if (Opc == Instruction::Add || Opc == Instruction::Sub || + Opc == Instruction::Mul || Opc == Instruction::Shl) { + if (EatIfPresent(lltok::kw_nuw)) + NUW = true; + if (EatIfPresent(lltok::kw_nsw)) { + NSW = true; + if (EatIfPresent(lltok::kw_nuw)) + NUW = true; + } + } else if (Opc == Instruction::SDiv || Opc == Instruction::UDiv || + Opc == Instruction::LShr || Opc == Instruction::AShr) { + if (EatIfPresent(lltok::kw_exact)) + Exact = true; + } if (parseToken(lltok::lparen, "expected '(' in binary constantexpr") || parseGlobalTypeAndValue(Val0) || parseToken(lltok::comma, "expected comma in binary constantexpr") || parseGlobalTypeAndValue(Val1) || parseToken(lltok::rparen, "expected ')' in binary constantexpr")) - return true; - if (Val0->getType() != Val1->getType()) + return true; + if (Val0->getType() != Val1->getType()) return error(ID.Loc, "operands of constexpr must have same type"); - // Check that the type is valid for the operator. - switch (Opc) { - case Instruction::Add: - case Instruction::Sub: - case Instruction::Mul: - case Instruction::UDiv: - case Instruction::SDiv: - case Instruction::URem: - case Instruction::SRem: - case Instruction::Shl: - case Instruction::AShr: - case Instruction::LShr: - if (!Val0->getType()->isIntOrIntVectorTy()) + // Check that the type is valid for the operator. + switch (Opc) { + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::URem: + case Instruction::SRem: + case Instruction::Shl: + case Instruction::AShr: + case Instruction::LShr: + if (!Val0->getType()->isIntOrIntVectorTy()) return error(ID.Loc, "constexpr requires integer operands"); - break; - case Instruction::FAdd: - case Instruction::FSub: - case Instruction::FMul: - case Instruction::FDiv: - case Instruction::FRem: - if (!Val0->getType()->isFPOrFPVectorTy()) + break; + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: + case Instruction::FRem: + if (!Val0->getType()->isFPOrFPVectorTy()) return error(ID.Loc, "constexpr requires fp operands"); - break; - default: llvm_unreachable("Unknown binary operator!"); - } - unsigned Flags = 0; - if (NUW) Flags |= OverflowingBinaryOperator::NoUnsignedWrap; - if (NSW) Flags |= OverflowingBinaryOperator::NoSignedWrap; - if (Exact) Flags |= PossiblyExactOperator::IsExact; - Constant *C = ConstantExpr::get(Opc, Val0, Val1, Flags); - ID.ConstantVal = C; - ID.Kind = ValID::t_Constant; - return false; - } - - // Logical Operations - case lltok::kw_and: - case lltok::kw_or: - case lltok::kw_xor: { - unsigned Opc = Lex.getUIntVal(); - Constant *Val0, *Val1; - Lex.Lex(); + break; + default: llvm_unreachable("Unknown binary operator!"); + } + unsigned Flags = 0; + if (NUW) Flags |= OverflowingBinaryOperator::NoUnsignedWrap; + if (NSW) Flags |= OverflowingBinaryOperator::NoSignedWrap; + if (Exact) Flags |= PossiblyExactOperator::IsExact; + Constant *C = ConstantExpr::get(Opc, Val0, Val1, Flags); + ID.ConstantVal = C; + ID.Kind = ValID::t_Constant; + return false; + } + + // Logical Operations + case lltok::kw_and: + case lltok::kw_or: + case lltok::kw_xor: { + unsigned Opc = Lex.getUIntVal(); + Constant *Val0, *Val1; + Lex.Lex(); if (parseToken(lltok::lparen, "expected '(' in logical constantexpr") || parseGlobalTypeAndValue(Val0) || parseToken(lltok::comma, "expected comma in logical constantexpr") || parseGlobalTypeAndValue(Val1) || parseToken(lltok::rparen, "expected ')' in logical constantexpr")) - return true; - if (Val0->getType() != Val1->getType()) + return true; + if (Val0->getType() != Val1->getType()) return error(ID.Loc, "operands of constexpr must have same type"); - if (!Val0->getType()->isIntOrIntVectorTy()) + if (!Val0->getType()->isIntOrIntVectorTy()) return error(ID.Loc, - "constexpr requires integer or integer vector operands"); - ID.ConstantVal = ConstantExpr::get(Opc, Val0, Val1); - ID.Kind = ValID::t_Constant; - return false; - } - - case lltok::kw_getelementptr: - case lltok::kw_shufflevector: - case lltok::kw_insertelement: - case lltok::kw_extractelement: - case lltok::kw_select: { - unsigned Opc = Lex.getUIntVal(); - SmallVector<Constant*, 16> Elts; - bool InBounds = false; - Type *Ty; - Lex.Lex(); - - if (Opc == Instruction::GetElementPtr) - InBounds = EatIfPresent(lltok::kw_inbounds); - + "constexpr requires integer or integer vector operands"); + ID.ConstantVal = ConstantExpr::get(Opc, Val0, Val1); + ID.Kind = ValID::t_Constant; + return false; + } + + case lltok::kw_getelementptr: + case lltok::kw_shufflevector: + case lltok::kw_insertelement: + case lltok::kw_extractelement: + case lltok::kw_select: { + unsigned Opc = Lex.getUIntVal(); + SmallVector<Constant*, 16> Elts; + bool InBounds = false; + Type *Ty; + Lex.Lex(); + + if (Opc == Instruction::GetElementPtr) + InBounds = EatIfPresent(lltok::kw_inbounds); + if (parseToken(lltok::lparen, "expected '(' in constantexpr")) - return true; - - LocTy ExplicitTypeLoc = Lex.getLoc(); - if (Opc == Instruction::GetElementPtr) { + return true; + + LocTy ExplicitTypeLoc = Lex.getLoc(); + if (Opc == Instruction::GetElementPtr) { if (parseType(Ty) || parseToken(lltok::comma, "expected comma after getelementptr's type")) - return true; - } - - Optional<unsigned> InRangeOp; + return true; + } + + Optional<unsigned> InRangeOp; if (parseGlobalValueVector( - Elts, Opc == Instruction::GetElementPtr ? &InRangeOp : nullptr) || + Elts, Opc == Instruction::GetElementPtr ? &InRangeOp : nullptr) || parseToken(lltok::rparen, "expected ')' in constantexpr")) - return true; - - if (Opc == Instruction::GetElementPtr) { - if (Elts.size() == 0 || - !Elts[0]->getType()->isPtrOrPtrVectorTy()) + return true; + + if (Opc == Instruction::GetElementPtr) { + if (Elts.size() == 0 || + !Elts[0]->getType()->isPtrOrPtrVectorTy()) return error(ID.Loc, "base of getelementptr must be a pointer"); - - Type *BaseType = Elts[0]->getType(); - auto *BasePointerType = cast<PointerType>(BaseType->getScalarType()); - if (Ty != BasePointerType->getElementType()) + + Type *BaseType = Elts[0]->getType(); + auto *BasePointerType = cast<PointerType>(BaseType->getScalarType()); + if (Ty != BasePointerType->getElementType()) return error( - ExplicitTypeLoc, - "explicit pointee type doesn't match operand's pointee type"); - - unsigned GEPWidth = - BaseType->isVectorTy() - ? cast<FixedVectorType>(BaseType)->getNumElements() - : 0; - - ArrayRef<Constant *> Indices(Elts.begin() + 1, Elts.end()); - for (Constant *Val : Indices) { - Type *ValTy = Val->getType(); - if (!ValTy->isIntOrIntVectorTy()) + ExplicitTypeLoc, + "explicit pointee type doesn't match operand's pointee type"); + + unsigned GEPWidth = + BaseType->isVectorTy() + ? cast<FixedVectorType>(BaseType)->getNumElements() + : 0; + + ArrayRef<Constant *> Indices(Elts.begin() + 1, Elts.end()); + for (Constant *Val : Indices) { + Type *ValTy = Val->getType(); + if (!ValTy->isIntOrIntVectorTy()) return error(ID.Loc, "getelementptr index must be an integer"); - if (auto *ValVTy = dyn_cast<VectorType>(ValTy)) { - unsigned ValNumEl = cast<FixedVectorType>(ValVTy)->getNumElements(); - if (GEPWidth && (ValNumEl != GEPWidth)) + if (auto *ValVTy = dyn_cast<VectorType>(ValTy)) { + unsigned ValNumEl = cast<FixedVectorType>(ValVTy)->getNumElements(); + if (GEPWidth && (ValNumEl != GEPWidth)) return error( - ID.Loc, - "getelementptr vector index has a wrong number of elements"); - // GEPWidth may have been unknown because the base is a scalar, - // but it is known now. - GEPWidth = ValNumEl; - } - } - - SmallPtrSet<Type*, 4> Visited; - if (!Indices.empty() && !Ty->isSized(&Visited)) + ID.Loc, + "getelementptr vector index has a wrong number of elements"); + // GEPWidth may have been unknown because the base is a scalar, + // but it is known now. + GEPWidth = ValNumEl; + } + } + + SmallPtrSet<Type*, 4> Visited; + if (!Indices.empty() && !Ty->isSized(&Visited)) return error(ID.Loc, "base element of getelementptr must be sized"); - - if (!GetElementPtrInst::getIndexedType(Ty, Indices)) + + if (!GetElementPtrInst::getIndexedType(Ty, Indices)) return error(ID.Loc, "invalid getelementptr indices"); - - if (InRangeOp) { - if (*InRangeOp == 0) + + if (InRangeOp) { + if (*InRangeOp == 0) return error(ID.Loc, - "inrange keyword may not appear on pointer operand"); - --*InRangeOp; - } - - ID.ConstantVal = ConstantExpr::getGetElementPtr(Ty, Elts[0], Indices, - InBounds, InRangeOp); - } else if (Opc == Instruction::Select) { - if (Elts.size() != 3) + "inrange keyword may not appear on pointer operand"); + --*InRangeOp; + } + + ID.ConstantVal = ConstantExpr::getGetElementPtr(Ty, Elts[0], Indices, + InBounds, InRangeOp); + } else if (Opc == Instruction::Select) { + if (Elts.size() != 3) return error(ID.Loc, "expected three operands to select"); - if (const char *Reason = SelectInst::areInvalidOperands(Elts[0], Elts[1], - Elts[2])) + if (const char *Reason = SelectInst::areInvalidOperands(Elts[0], Elts[1], + Elts[2])) return error(ID.Loc, Reason); - ID.ConstantVal = ConstantExpr::getSelect(Elts[0], Elts[1], Elts[2]); - } else if (Opc == Instruction::ShuffleVector) { - if (Elts.size() != 3) + ID.ConstantVal = ConstantExpr::getSelect(Elts[0], Elts[1], Elts[2]); + } else if (Opc == Instruction::ShuffleVector) { + if (Elts.size() != 3) return error(ID.Loc, "expected three operands to shufflevector"); - if (!ShuffleVectorInst::isValidOperands(Elts[0], Elts[1], Elts[2])) + if (!ShuffleVectorInst::isValidOperands(Elts[0], Elts[1], Elts[2])) return error(ID.Loc, "invalid operands to shufflevector"); - SmallVector<int, 16> Mask; - ShuffleVectorInst::getShuffleMask(cast<Constant>(Elts[2]), Mask); - ID.ConstantVal = ConstantExpr::getShuffleVector(Elts[0], Elts[1], Mask); - } else if (Opc == Instruction::ExtractElement) { - if (Elts.size() != 2) + SmallVector<int, 16> Mask; + ShuffleVectorInst::getShuffleMask(cast<Constant>(Elts[2]), Mask); + ID.ConstantVal = ConstantExpr::getShuffleVector(Elts[0], Elts[1], Mask); + } else if (Opc == Instruction::ExtractElement) { + if (Elts.size() != 2) return error(ID.Loc, "expected two operands to extractelement"); - if (!ExtractElementInst::isValidOperands(Elts[0], Elts[1])) + if (!ExtractElementInst::isValidOperands(Elts[0], Elts[1])) return error(ID.Loc, "invalid extractelement operands"); - ID.ConstantVal = ConstantExpr::getExtractElement(Elts[0], Elts[1]); - } else { - assert(Opc == Instruction::InsertElement && "Unknown opcode"); - if (Elts.size() != 3) + ID.ConstantVal = ConstantExpr::getExtractElement(Elts[0], Elts[1]); + } else { + assert(Opc == Instruction::InsertElement && "Unknown opcode"); + if (Elts.size() != 3) return error(ID.Loc, "expected three operands to insertelement"); - if (!InsertElementInst::isValidOperands(Elts[0], Elts[1], Elts[2])) + if (!InsertElementInst::isValidOperands(Elts[0], Elts[1], Elts[2])) return error(ID.Loc, "invalid insertelement operands"); - ID.ConstantVal = - ConstantExpr::getInsertElement(Elts[0], Elts[1],Elts[2]); - } - - ID.Kind = ValID::t_Constant; - return false; - } - } - - Lex.Lex(); - return false; -} - + ID.ConstantVal = + ConstantExpr::getInsertElement(Elts[0], Elts[1],Elts[2]); + } + + ID.Kind = ValID::t_Constant; + return false; + } + } + + Lex.Lex(); + return false; +} + /// parseGlobalValue - parse a global value with the specified type. bool LLParser::parseGlobalValue(Type *Ty, Constant *&C) { - C = nullptr; - ValID ID; - Value *V = nullptr; + C = nullptr; + ValID ID; + Value *V = nullptr; bool Parsed = parseValID(ID) || convertValIDToValue(Ty, ID, V, nullptr, /*IsCall=*/false); - if (V && !(C = dyn_cast<Constant>(V))) + if (V && !(C = dyn_cast<Constant>(V))) return error(ID.Loc, "global values must be constants"); - return Parsed; -} - + return Parsed; +} + bool LLParser::parseGlobalTypeAndValue(Constant *&V) { - Type *Ty = nullptr; + Type *Ty = nullptr; return parseType(Ty) || parseGlobalValue(Ty, V); -} - -bool LLParser::parseOptionalComdat(StringRef GlobalName, Comdat *&C) { - C = nullptr; - - LocTy KwLoc = Lex.getLoc(); - if (!EatIfPresent(lltok::kw_comdat)) - return false; - - if (EatIfPresent(lltok::lparen)) { - if (Lex.getKind() != lltok::ComdatVar) +} + +bool LLParser::parseOptionalComdat(StringRef GlobalName, Comdat *&C) { + C = nullptr; + + LocTy KwLoc = Lex.getLoc(); + if (!EatIfPresent(lltok::kw_comdat)) + return false; + + if (EatIfPresent(lltok::lparen)) { + if (Lex.getKind() != lltok::ComdatVar) return tokError("expected comdat variable"); - C = getComdat(Lex.getStrVal(), Lex.getLoc()); - Lex.Lex(); + C = getComdat(Lex.getStrVal(), Lex.getLoc()); + Lex.Lex(); if (parseToken(lltok::rparen, "expected ')' after comdat var")) - return true; - } else { - if (GlobalName.empty()) + return true; + } else { + if (GlobalName.empty()) return tokError("comdat cannot be unnamed"); - C = getComdat(std::string(GlobalName), KwLoc); - } - - return false; -} - + C = getComdat(std::string(GlobalName), KwLoc); + } + + return false; +} + /// parseGlobalValueVector -/// ::= /*empty*/ -/// ::= [inrange] TypeAndValue (',' [inrange] TypeAndValue)* +/// ::= /*empty*/ +/// ::= [inrange] TypeAndValue (',' [inrange] TypeAndValue)* bool LLParser::parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts, - Optional<unsigned> *InRangeOp) { - // Empty list. - if (Lex.getKind() == lltok::rbrace || - Lex.getKind() == lltok::rsquare || - Lex.getKind() == lltok::greater || - Lex.getKind() == lltok::rparen) - return false; - - do { - if (InRangeOp && !*InRangeOp && EatIfPresent(lltok::kw_inrange)) - *InRangeOp = Elts.size(); - - Constant *C; + Optional<unsigned> *InRangeOp) { + // Empty list. + if (Lex.getKind() == lltok::rbrace || + Lex.getKind() == lltok::rsquare || + Lex.getKind() == lltok::greater || + Lex.getKind() == lltok::rparen) + return false; + + do { + if (InRangeOp && !*InRangeOp && EatIfPresent(lltok::kw_inrange)) + *InRangeOp = Elts.size(); + + Constant *C; if (parseGlobalTypeAndValue(C)) return true; - Elts.push_back(C); - } while (EatIfPresent(lltok::comma)); - - return false; -} - + Elts.push_back(C); + } while (EatIfPresent(lltok::comma)); + + return false; +} + bool LLParser::parseMDTuple(MDNode *&MD, bool IsDistinct) { - SmallVector<Metadata *, 16> Elts; + SmallVector<Metadata *, 16> Elts; if (parseMDNodeVector(Elts)) - return true; - - MD = (IsDistinct ? MDTuple::getDistinct : MDTuple::get)(Context, Elts); - return false; -} - -/// MDNode: -/// ::= !{ ... } -/// ::= !7 -/// ::= !DILocation(...) + return true; + + MD = (IsDistinct ? MDTuple::getDistinct : MDTuple::get)(Context, Elts); + return false; +} + +/// MDNode: +/// ::= !{ ... } +/// ::= !7 +/// ::= !DILocation(...) bool LLParser::parseMDNode(MDNode *&N) { - if (Lex.getKind() == lltok::MetadataVar) + if (Lex.getKind() == lltok::MetadataVar) return parseSpecializedMDNode(N); - + return parseToken(lltok::exclaim, "expected '!' here") || parseMDNodeTail(N); -} - +} + bool LLParser::parseMDNodeTail(MDNode *&N) { - // !{ ... } - if (Lex.getKind() == lltok::lbrace) + // !{ ... } + if (Lex.getKind() == lltok::lbrace) return parseMDTuple(N); - - // !42 + + // !42 return parseMDNodeID(N); -} - -namespace { - -/// Structure to represent an optional metadata field. -template <class FieldTy> struct MDFieldImpl { - typedef MDFieldImpl ImplTy; - FieldTy Val; - bool Seen; - - void assign(FieldTy Val) { - Seen = true; - this->Val = std::move(Val); - } - - explicit MDFieldImpl(FieldTy Default) - : Val(std::move(Default)), Seen(false) {} -}; - -/// Structure to represent an optional metadata field that -/// can be of either type (A or B) and encapsulates the -/// MD<typeofA>Field and MD<typeofB>Field structs, so not -/// to reimplement the specifics for representing each Field. -template <class FieldTypeA, class FieldTypeB> struct MDEitherFieldImpl { - typedef MDEitherFieldImpl<FieldTypeA, FieldTypeB> ImplTy; - FieldTypeA A; - FieldTypeB B; - bool Seen; - - enum { - IsInvalid = 0, - IsTypeA = 1, - IsTypeB = 2 - } WhatIs; - - void assign(FieldTypeA A) { - Seen = true; - this->A = std::move(A); - WhatIs = IsTypeA; - } - - void assign(FieldTypeB B) { - Seen = true; - this->B = std::move(B); - WhatIs = IsTypeB; - } - - explicit MDEitherFieldImpl(FieldTypeA DefaultA, FieldTypeB DefaultB) - : A(std::move(DefaultA)), B(std::move(DefaultB)), Seen(false), - WhatIs(IsInvalid) {} -}; - -struct MDUnsignedField : public MDFieldImpl<uint64_t> { - uint64_t Max; - - MDUnsignedField(uint64_t Default = 0, uint64_t Max = UINT64_MAX) - : ImplTy(Default), Max(Max) {} -}; - -struct LineField : public MDUnsignedField { - LineField() : MDUnsignedField(0, UINT32_MAX) {} -}; - -struct ColumnField : public MDUnsignedField { - ColumnField() : MDUnsignedField(0, UINT16_MAX) {} -}; - -struct DwarfTagField : public MDUnsignedField { - DwarfTagField() : MDUnsignedField(0, dwarf::DW_TAG_hi_user) {} - DwarfTagField(dwarf::Tag DefaultTag) - : MDUnsignedField(DefaultTag, dwarf::DW_TAG_hi_user) {} -}; - -struct DwarfMacinfoTypeField : public MDUnsignedField { - DwarfMacinfoTypeField() : MDUnsignedField(0, dwarf::DW_MACINFO_vendor_ext) {} - DwarfMacinfoTypeField(dwarf::MacinfoRecordType DefaultType) - : MDUnsignedField(DefaultType, dwarf::DW_MACINFO_vendor_ext) {} -}; - -struct DwarfAttEncodingField : public MDUnsignedField { - DwarfAttEncodingField() : MDUnsignedField(0, dwarf::DW_ATE_hi_user) {} -}; - -struct DwarfVirtualityField : public MDUnsignedField { - DwarfVirtualityField() : MDUnsignedField(0, dwarf::DW_VIRTUALITY_max) {} -}; - -struct DwarfLangField : public MDUnsignedField { - DwarfLangField() : MDUnsignedField(0, dwarf::DW_LANG_hi_user) {} -}; - -struct DwarfCCField : public MDUnsignedField { - DwarfCCField() : MDUnsignedField(0, dwarf::DW_CC_hi_user) {} -}; - -struct EmissionKindField : public MDUnsignedField { - EmissionKindField() : MDUnsignedField(0, DICompileUnit::LastEmissionKind) {} -}; - -struct NameTableKindField : public MDUnsignedField { - NameTableKindField() - : MDUnsignedField( - 0, (unsigned) - DICompileUnit::DebugNameTableKind::LastDebugNameTableKind) {} -}; - -struct DIFlagField : public MDFieldImpl<DINode::DIFlags> { - DIFlagField() : MDFieldImpl(DINode::FlagZero) {} -}; - -struct DISPFlagField : public MDFieldImpl<DISubprogram::DISPFlags> { - DISPFlagField() : MDFieldImpl(DISubprogram::SPFlagZero) {} -}; - -struct MDAPSIntField : public MDFieldImpl<APSInt> { - MDAPSIntField() : ImplTy(APSInt()) {} -}; - -struct MDSignedField : public MDFieldImpl<int64_t> { - int64_t Min; - int64_t Max; - - MDSignedField(int64_t Default = 0) - : ImplTy(Default), Min(INT64_MIN), Max(INT64_MAX) {} - MDSignedField(int64_t Default, int64_t Min, int64_t Max) - : ImplTy(Default), Min(Min), Max(Max) {} -}; - -struct MDBoolField : public MDFieldImpl<bool> { - MDBoolField(bool Default = false) : ImplTy(Default) {} -}; - -struct MDField : public MDFieldImpl<Metadata *> { - bool AllowNull; - - MDField(bool AllowNull = true) : ImplTy(nullptr), AllowNull(AllowNull) {} -}; - -struct MDConstant : public MDFieldImpl<ConstantAsMetadata *> { - MDConstant() : ImplTy(nullptr) {} -}; - -struct MDStringField : public MDFieldImpl<MDString *> { - bool AllowEmpty; - MDStringField(bool AllowEmpty = true) - : ImplTy(nullptr), AllowEmpty(AllowEmpty) {} -}; - -struct MDFieldList : public MDFieldImpl<SmallVector<Metadata *, 4>> { - MDFieldList() : ImplTy(SmallVector<Metadata *, 4>()) {} -}; - -struct ChecksumKindField : public MDFieldImpl<DIFile::ChecksumKind> { - ChecksumKindField(DIFile::ChecksumKind CSKind) : ImplTy(CSKind) {} -}; - -struct MDSignedOrMDField : MDEitherFieldImpl<MDSignedField, MDField> { - MDSignedOrMDField(int64_t Default = 0, bool AllowNull = true) - : ImplTy(MDSignedField(Default), MDField(AllowNull)) {} - - MDSignedOrMDField(int64_t Default, int64_t Min, int64_t Max, - bool AllowNull = true) - : ImplTy(MDSignedField(Default, Min, Max), MDField(AllowNull)) {} - - bool isMDSignedField() const { return WhatIs == IsTypeA; } - bool isMDField() const { return WhatIs == IsTypeB; } - int64_t getMDSignedValue() const { - assert(isMDSignedField() && "Wrong field type"); - return A.Val; - } - Metadata *getMDFieldValue() const { - assert(isMDField() && "Wrong field type"); - return B.Val; - } -}; - -struct MDSignedOrUnsignedField - : MDEitherFieldImpl<MDSignedField, MDUnsignedField> { - MDSignedOrUnsignedField() : ImplTy(MDSignedField(0), MDUnsignedField(0)) {} - - bool isMDSignedField() const { return WhatIs == IsTypeA; } - bool isMDUnsignedField() const { return WhatIs == IsTypeB; } - int64_t getMDSignedValue() const { - assert(isMDSignedField() && "Wrong field type"); - return A.Val; - } - uint64_t getMDUnsignedValue() const { - assert(isMDUnsignedField() && "Wrong field type"); - return B.Val; - } -}; - -} // end anonymous namespace - -namespace llvm { - -template <> +} + +namespace { + +/// Structure to represent an optional metadata field. +template <class FieldTy> struct MDFieldImpl { + typedef MDFieldImpl ImplTy; + FieldTy Val; + bool Seen; + + void assign(FieldTy Val) { + Seen = true; + this->Val = std::move(Val); + } + + explicit MDFieldImpl(FieldTy Default) + : Val(std::move(Default)), Seen(false) {} +}; + +/// Structure to represent an optional metadata field that +/// can be of either type (A or B) and encapsulates the +/// MD<typeofA>Field and MD<typeofB>Field structs, so not +/// to reimplement the specifics for representing each Field. +template <class FieldTypeA, class FieldTypeB> struct MDEitherFieldImpl { + typedef MDEitherFieldImpl<FieldTypeA, FieldTypeB> ImplTy; + FieldTypeA A; + FieldTypeB B; + bool Seen; + + enum { + IsInvalid = 0, + IsTypeA = 1, + IsTypeB = 2 + } WhatIs; + + void assign(FieldTypeA A) { + Seen = true; + this->A = std::move(A); + WhatIs = IsTypeA; + } + + void assign(FieldTypeB B) { + Seen = true; + this->B = std::move(B); + WhatIs = IsTypeB; + } + + explicit MDEitherFieldImpl(FieldTypeA DefaultA, FieldTypeB DefaultB) + : A(std::move(DefaultA)), B(std::move(DefaultB)), Seen(false), + WhatIs(IsInvalid) {} +}; + +struct MDUnsignedField : public MDFieldImpl<uint64_t> { + uint64_t Max; + + MDUnsignedField(uint64_t Default = 0, uint64_t Max = UINT64_MAX) + : ImplTy(Default), Max(Max) {} +}; + +struct LineField : public MDUnsignedField { + LineField() : MDUnsignedField(0, UINT32_MAX) {} +}; + +struct ColumnField : public MDUnsignedField { + ColumnField() : MDUnsignedField(0, UINT16_MAX) {} +}; + +struct DwarfTagField : public MDUnsignedField { + DwarfTagField() : MDUnsignedField(0, dwarf::DW_TAG_hi_user) {} + DwarfTagField(dwarf::Tag DefaultTag) + : MDUnsignedField(DefaultTag, dwarf::DW_TAG_hi_user) {} +}; + +struct DwarfMacinfoTypeField : public MDUnsignedField { + DwarfMacinfoTypeField() : MDUnsignedField(0, dwarf::DW_MACINFO_vendor_ext) {} + DwarfMacinfoTypeField(dwarf::MacinfoRecordType DefaultType) + : MDUnsignedField(DefaultType, dwarf::DW_MACINFO_vendor_ext) {} +}; + +struct DwarfAttEncodingField : public MDUnsignedField { + DwarfAttEncodingField() : MDUnsignedField(0, dwarf::DW_ATE_hi_user) {} +}; + +struct DwarfVirtualityField : public MDUnsignedField { + DwarfVirtualityField() : MDUnsignedField(0, dwarf::DW_VIRTUALITY_max) {} +}; + +struct DwarfLangField : public MDUnsignedField { + DwarfLangField() : MDUnsignedField(0, dwarf::DW_LANG_hi_user) {} +}; + +struct DwarfCCField : public MDUnsignedField { + DwarfCCField() : MDUnsignedField(0, dwarf::DW_CC_hi_user) {} +}; + +struct EmissionKindField : public MDUnsignedField { + EmissionKindField() : MDUnsignedField(0, DICompileUnit::LastEmissionKind) {} +}; + +struct NameTableKindField : public MDUnsignedField { + NameTableKindField() + : MDUnsignedField( + 0, (unsigned) + DICompileUnit::DebugNameTableKind::LastDebugNameTableKind) {} +}; + +struct DIFlagField : public MDFieldImpl<DINode::DIFlags> { + DIFlagField() : MDFieldImpl(DINode::FlagZero) {} +}; + +struct DISPFlagField : public MDFieldImpl<DISubprogram::DISPFlags> { + DISPFlagField() : MDFieldImpl(DISubprogram::SPFlagZero) {} +}; + +struct MDAPSIntField : public MDFieldImpl<APSInt> { + MDAPSIntField() : ImplTy(APSInt()) {} +}; + +struct MDSignedField : public MDFieldImpl<int64_t> { + int64_t Min; + int64_t Max; + + MDSignedField(int64_t Default = 0) + : ImplTy(Default), Min(INT64_MIN), Max(INT64_MAX) {} + MDSignedField(int64_t Default, int64_t Min, int64_t Max) + : ImplTy(Default), Min(Min), Max(Max) {} +}; + +struct MDBoolField : public MDFieldImpl<bool> { + MDBoolField(bool Default = false) : ImplTy(Default) {} +}; + +struct MDField : public MDFieldImpl<Metadata *> { + bool AllowNull; + + MDField(bool AllowNull = true) : ImplTy(nullptr), AllowNull(AllowNull) {} +}; + +struct MDConstant : public MDFieldImpl<ConstantAsMetadata *> { + MDConstant() : ImplTy(nullptr) {} +}; + +struct MDStringField : public MDFieldImpl<MDString *> { + bool AllowEmpty; + MDStringField(bool AllowEmpty = true) + : ImplTy(nullptr), AllowEmpty(AllowEmpty) {} +}; + +struct MDFieldList : public MDFieldImpl<SmallVector<Metadata *, 4>> { + MDFieldList() : ImplTy(SmallVector<Metadata *, 4>()) {} +}; + +struct ChecksumKindField : public MDFieldImpl<DIFile::ChecksumKind> { + ChecksumKindField(DIFile::ChecksumKind CSKind) : ImplTy(CSKind) {} +}; + +struct MDSignedOrMDField : MDEitherFieldImpl<MDSignedField, MDField> { + MDSignedOrMDField(int64_t Default = 0, bool AllowNull = true) + : ImplTy(MDSignedField(Default), MDField(AllowNull)) {} + + MDSignedOrMDField(int64_t Default, int64_t Min, int64_t Max, + bool AllowNull = true) + : ImplTy(MDSignedField(Default, Min, Max), MDField(AllowNull)) {} + + bool isMDSignedField() const { return WhatIs == IsTypeA; } + bool isMDField() const { return WhatIs == IsTypeB; } + int64_t getMDSignedValue() const { + assert(isMDSignedField() && "Wrong field type"); + return A.Val; + } + Metadata *getMDFieldValue() const { + assert(isMDField() && "Wrong field type"); + return B.Val; + } +}; + +struct MDSignedOrUnsignedField + : MDEitherFieldImpl<MDSignedField, MDUnsignedField> { + MDSignedOrUnsignedField() : ImplTy(MDSignedField(0), MDUnsignedField(0)) {} + + bool isMDSignedField() const { return WhatIs == IsTypeA; } + bool isMDUnsignedField() const { return WhatIs == IsTypeB; } + int64_t getMDSignedValue() const { + assert(isMDSignedField() && "Wrong field type"); + return A.Val; + } + uint64_t getMDUnsignedValue() const { + assert(isMDUnsignedField() && "Wrong field type"); + return B.Val; + } +}; + +} // end anonymous namespace + +namespace llvm { + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, MDAPSIntField &Result) { - if (Lex.getKind() != lltok::APSInt) + if (Lex.getKind() != lltok::APSInt) return tokError("expected integer"); - - Result.assign(Lex.getAPSIntVal()); - Lex.Lex(); - return false; -} - -template <> + + Result.assign(Lex.getAPSIntVal()); + Lex.Lex(); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, - MDUnsignedField &Result) { - if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) + MDUnsignedField &Result) { + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) return tokError("expected unsigned integer"); - - auto &U = Lex.getAPSIntVal(); - if (U.ugt(Result.Max)) + + auto &U = Lex.getAPSIntVal(); + if (U.ugt(Result.Max)) return tokError("value for '" + Name + "' too large, limit is " + - Twine(Result.Max)); - Result.assign(U.getZExtValue()); - assert(Result.Val <= Result.Max && "Expected value in range"); - Lex.Lex(); - return false; -} - -template <> + Twine(Result.Max)); + Result.assign(U.getZExtValue()); + assert(Result.Val <= Result.Max && "Expected value in range"); + Lex.Lex(); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, LineField &Result) { return parseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); -} -template <> +} +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, ColumnField &Result) { return parseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); -} - -template <> +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, DwarfTagField &Result) { - if (Lex.getKind() == lltok::APSInt) + if (Lex.getKind() == lltok::APSInt) return parseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); - - if (Lex.getKind() != lltok::DwarfTag) + + if (Lex.getKind() != lltok::DwarfTag) return tokError("expected DWARF tag"); - - unsigned Tag = dwarf::getTag(Lex.getStrVal()); - if (Tag == dwarf::DW_TAG_invalid) + + unsigned Tag = dwarf::getTag(Lex.getStrVal()); + if (Tag == dwarf::DW_TAG_invalid) return tokError("invalid DWARF tag" + Twine(" '") + Lex.getStrVal() + "'"); - assert(Tag <= Result.Max && "Expected valid DWARF tag"); - - Result.assign(Tag); - Lex.Lex(); - return false; -} - -template <> + assert(Tag <= Result.Max && "Expected valid DWARF tag"); + + Result.assign(Tag); + Lex.Lex(); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, - DwarfMacinfoTypeField &Result) { - if (Lex.getKind() == lltok::APSInt) + DwarfMacinfoTypeField &Result) { + if (Lex.getKind() == lltok::APSInt) return parseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); - - if (Lex.getKind() != lltok::DwarfMacinfo) + + if (Lex.getKind() != lltok::DwarfMacinfo) return tokError("expected DWARF macinfo type"); - - unsigned Macinfo = dwarf::getMacinfo(Lex.getStrVal()); - if (Macinfo == dwarf::DW_MACINFO_invalid) + + unsigned Macinfo = dwarf::getMacinfo(Lex.getStrVal()); + if (Macinfo == dwarf::DW_MACINFO_invalid) return tokError("invalid DWARF macinfo type" + Twine(" '") + Lex.getStrVal() + "'"); - assert(Macinfo <= Result.Max && "Expected valid DWARF macinfo type"); - - Result.assign(Macinfo); - Lex.Lex(); - return false; -} - -template <> + assert(Macinfo <= Result.Max && "Expected valid DWARF macinfo type"); + + Result.assign(Macinfo); + Lex.Lex(); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, - DwarfVirtualityField &Result) { - if (Lex.getKind() == lltok::APSInt) + DwarfVirtualityField &Result) { + if (Lex.getKind() == lltok::APSInt) return parseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); - - if (Lex.getKind() != lltok::DwarfVirtuality) + + if (Lex.getKind() != lltok::DwarfVirtuality) return tokError("expected DWARF virtuality code"); - - unsigned Virtuality = dwarf::getVirtuality(Lex.getStrVal()); - if (Virtuality == dwarf::DW_VIRTUALITY_invalid) + + unsigned Virtuality = dwarf::getVirtuality(Lex.getStrVal()); + if (Virtuality == dwarf::DW_VIRTUALITY_invalid) return tokError("invalid DWARF virtuality code" + Twine(" '") + - Lex.getStrVal() + "'"); - assert(Virtuality <= Result.Max && "Expected valid DWARF virtuality code"); - Result.assign(Virtuality); - Lex.Lex(); - return false; -} - -template <> + Lex.getStrVal() + "'"); + assert(Virtuality <= Result.Max && "Expected valid DWARF virtuality code"); + Result.assign(Virtuality); + Lex.Lex(); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, DwarfLangField &Result) { - if (Lex.getKind() == lltok::APSInt) + if (Lex.getKind() == lltok::APSInt) return parseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); - - if (Lex.getKind() != lltok::DwarfLang) + + if (Lex.getKind() != lltok::DwarfLang) return tokError("expected DWARF language"); - - unsigned Lang = dwarf::getLanguage(Lex.getStrVal()); - if (!Lang) + + unsigned Lang = dwarf::getLanguage(Lex.getStrVal()); + if (!Lang) return tokError("invalid DWARF language" + Twine(" '") + Lex.getStrVal() + - "'"); - assert(Lang <= Result.Max && "Expected valid DWARF language"); - Result.assign(Lang); - Lex.Lex(); - return false; -} - -template <> + "'"); + assert(Lang <= Result.Max && "Expected valid DWARF language"); + Result.assign(Lang); + Lex.Lex(); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, DwarfCCField &Result) { - if (Lex.getKind() == lltok::APSInt) + if (Lex.getKind() == lltok::APSInt) return parseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); - - if (Lex.getKind() != lltok::DwarfCC) + + if (Lex.getKind() != lltok::DwarfCC) return tokError("expected DWARF calling convention"); - - unsigned CC = dwarf::getCallingConvention(Lex.getStrVal()); - if (!CC) + + unsigned CC = dwarf::getCallingConvention(Lex.getStrVal()); + if (!CC) return tokError("invalid DWARF calling convention" + Twine(" '") + Lex.getStrVal() + "'"); - assert(CC <= Result.Max && "Expected valid DWARF calling convention"); - Result.assign(CC); - Lex.Lex(); - return false; -} - -template <> + assert(CC <= Result.Max && "Expected valid DWARF calling convention"); + Result.assign(CC); + Lex.Lex(); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, EmissionKindField &Result) { - if (Lex.getKind() == lltok::APSInt) + if (Lex.getKind() == lltok::APSInt) return parseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); - - if (Lex.getKind() != lltok::EmissionKind) + + if (Lex.getKind() != lltok::EmissionKind) return tokError("expected emission kind"); - - auto Kind = DICompileUnit::getEmissionKind(Lex.getStrVal()); - if (!Kind) + + auto Kind = DICompileUnit::getEmissionKind(Lex.getStrVal()); + if (!Kind) return tokError("invalid emission kind" + Twine(" '") + Lex.getStrVal() + - "'"); - assert(*Kind <= Result.Max && "Expected valid emission kind"); - Result.assign(*Kind); - Lex.Lex(); - return false; -} - -template <> + "'"); + assert(*Kind <= Result.Max && "Expected valid emission kind"); + Result.assign(*Kind); + Lex.Lex(); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, - NameTableKindField &Result) { - if (Lex.getKind() == lltok::APSInt) + NameTableKindField &Result) { + if (Lex.getKind() == lltok::APSInt) return parseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); - - if (Lex.getKind() != lltok::NameTableKind) + + if (Lex.getKind() != lltok::NameTableKind) return tokError("expected nameTable kind"); - - auto Kind = DICompileUnit::getNameTableKind(Lex.getStrVal()); - if (!Kind) + + auto Kind = DICompileUnit::getNameTableKind(Lex.getStrVal()); + if (!Kind) return tokError("invalid nameTable kind" + Twine(" '") + Lex.getStrVal() + - "'"); - assert(((unsigned)*Kind) <= Result.Max && "Expected valid nameTable kind"); - Result.assign((unsigned)*Kind); - Lex.Lex(); - return false; -} - -template <> + "'"); + assert(((unsigned)*Kind) <= Result.Max && "Expected valid nameTable kind"); + Result.assign((unsigned)*Kind); + Lex.Lex(); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, - DwarfAttEncodingField &Result) { - if (Lex.getKind() == lltok::APSInt) + DwarfAttEncodingField &Result) { + if (Lex.getKind() == lltok::APSInt) return parseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result)); - - if (Lex.getKind() != lltok::DwarfAttEncoding) + + if (Lex.getKind() != lltok::DwarfAttEncoding) return tokError("expected DWARF type attribute encoding"); - - unsigned Encoding = dwarf::getAttributeEncoding(Lex.getStrVal()); - if (!Encoding) + + unsigned Encoding = dwarf::getAttributeEncoding(Lex.getStrVal()); + if (!Encoding) return tokError("invalid DWARF type attribute encoding" + Twine(" '") + - Lex.getStrVal() + "'"); - assert(Encoding <= Result.Max && "Expected valid DWARF language"); - Result.assign(Encoding); - Lex.Lex(); - return false; -} - -/// DIFlagField -/// ::= uint32 -/// ::= DIFlagVector -/// ::= DIFlagVector '|' DIFlagFwdDecl '|' uint32 '|' DIFlagPublic -template <> + Lex.getStrVal() + "'"); + assert(Encoding <= Result.Max && "Expected valid DWARF language"); + Result.assign(Encoding); + Lex.Lex(); + return false; +} + +/// DIFlagField +/// ::= uint32 +/// ::= DIFlagVector +/// ::= DIFlagVector '|' DIFlagFwdDecl '|' uint32 '|' DIFlagPublic +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, DIFlagField &Result) { - + // parser for a single flag. - auto parseFlag = [&](DINode::DIFlags &Val) { - if (Lex.getKind() == lltok::APSInt && !Lex.getAPSIntVal().isSigned()) { - uint32_t TempVal = static_cast<uint32_t>(Val); + auto parseFlag = [&](DINode::DIFlags &Val) { + if (Lex.getKind() == lltok::APSInt && !Lex.getAPSIntVal().isSigned()) { + uint32_t TempVal = static_cast<uint32_t>(Val); bool Res = parseUInt32(TempVal); - Val = static_cast<DINode::DIFlags>(TempVal); - return Res; - } - - if (Lex.getKind() != lltok::DIFlag) + Val = static_cast<DINode::DIFlags>(TempVal); + return Res; + } + + if (Lex.getKind() != lltok::DIFlag) return tokError("expected debug info flag"); - - Val = DINode::getFlag(Lex.getStrVal()); - if (!Val) + + Val = DINode::getFlag(Lex.getStrVal()); + if (!Val) return tokError(Twine("invalid debug info flag flag '") + - Lex.getStrVal() + "'"); - Lex.Lex(); - return false; - }; - + Lex.getStrVal() + "'"); + Lex.Lex(); + return false; + }; + // parse the flags and combine them together. - DINode::DIFlags Combined = DINode::FlagZero; - do { - DINode::DIFlags Val; - if (parseFlag(Val)) - return true; - Combined |= Val; - } while (EatIfPresent(lltok::bar)); - - Result.assign(Combined); - return false; -} - -/// DISPFlagField -/// ::= uint32 -/// ::= DISPFlagVector -/// ::= DISPFlagVector '|' DISPFlag* '|' uint32 -template <> + DINode::DIFlags Combined = DINode::FlagZero; + do { + DINode::DIFlags Val; + if (parseFlag(Val)) + return true; + Combined |= Val; + } while (EatIfPresent(lltok::bar)); + + Result.assign(Combined); + return false; +} + +/// DISPFlagField +/// ::= uint32 +/// ::= DISPFlagVector +/// ::= DISPFlagVector '|' DISPFlag* '|' uint32 +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, DISPFlagField &Result) { - + // parser for a single flag. - auto parseFlag = [&](DISubprogram::DISPFlags &Val) { - if (Lex.getKind() == lltok::APSInt && !Lex.getAPSIntVal().isSigned()) { - uint32_t TempVal = static_cast<uint32_t>(Val); + auto parseFlag = [&](DISubprogram::DISPFlags &Val) { + if (Lex.getKind() == lltok::APSInt && !Lex.getAPSIntVal().isSigned()) { + uint32_t TempVal = static_cast<uint32_t>(Val); bool Res = parseUInt32(TempVal); - Val = static_cast<DISubprogram::DISPFlags>(TempVal); - return Res; - } - - if (Lex.getKind() != lltok::DISPFlag) + Val = static_cast<DISubprogram::DISPFlags>(TempVal); + return Res; + } + + if (Lex.getKind() != lltok::DISPFlag) return tokError("expected debug info flag"); - - Val = DISubprogram::getFlag(Lex.getStrVal()); - if (!Val) + + Val = DISubprogram::getFlag(Lex.getStrVal()); + if (!Val) return tokError(Twine("invalid subprogram debug info flag '") + - Lex.getStrVal() + "'"); - Lex.Lex(); - return false; - }; - + Lex.getStrVal() + "'"); + Lex.Lex(); + return false; + }; + // parse the flags and combine them together. - DISubprogram::DISPFlags Combined = DISubprogram::SPFlagZero; - do { - DISubprogram::DISPFlags Val; - if (parseFlag(Val)) - return true; - Combined |= Val; - } while (EatIfPresent(lltok::bar)); - - Result.assign(Combined); - return false; -} - -template <> + DISubprogram::DISPFlags Combined = DISubprogram::SPFlagZero; + do { + DISubprogram::DISPFlags Val; + if (parseFlag(Val)) + return true; + Combined |= Val; + } while (EatIfPresent(lltok::bar)); + + Result.assign(Combined); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, MDSignedField &Result) { - if (Lex.getKind() != lltok::APSInt) + if (Lex.getKind() != lltok::APSInt) return tokError("expected signed integer"); - - auto &S = Lex.getAPSIntVal(); - if (S < Result.Min) + + auto &S = Lex.getAPSIntVal(); + if (S < Result.Min) return tokError("value for '" + Name + "' too small, limit is " + - Twine(Result.Min)); - if (S > Result.Max) + Twine(Result.Min)); + if (S > Result.Max) return tokError("value for '" + Name + "' too large, limit is " + - Twine(Result.Max)); - Result.assign(S.getExtValue()); - assert(Result.Val >= Result.Min && "Expected value in range"); - assert(Result.Val <= Result.Max && "Expected value in range"); - Lex.Lex(); - return false; -} - -template <> + Twine(Result.Max)); + Result.assign(S.getExtValue()); + assert(Result.Val >= Result.Min && "Expected value in range"); + assert(Result.Val <= Result.Max && "Expected value in range"); + Lex.Lex(); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, MDBoolField &Result) { - switch (Lex.getKind()) { - default: + switch (Lex.getKind()) { + default: return tokError("expected 'true' or 'false'"); - case lltok::kw_true: - Result.assign(true); - break; - case lltok::kw_false: - Result.assign(false); - break; - } - Lex.Lex(); - return false; -} - -template <> + case lltok::kw_true: + Result.assign(true); + break; + case lltok::kw_false: + Result.assign(false); + break; + } + Lex.Lex(); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, MDField &Result) { - if (Lex.getKind() == lltok::kw_null) { - if (!Result.AllowNull) + if (Lex.getKind() == lltok::kw_null) { + if (!Result.AllowNull) return tokError("'" + Name + "' cannot be null"); - Lex.Lex(); - Result.assign(nullptr); - return false; - } - - Metadata *MD; + Lex.Lex(); + Result.assign(nullptr); + return false; + } + + Metadata *MD; if (parseMetadata(MD, nullptr)) - return true; - - Result.assign(MD); - return false; -} - -template <> + return true; + + Result.assign(MD); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, - MDSignedOrMDField &Result) { - // Try to parse a signed int. - if (Lex.getKind() == lltok::APSInt) { - MDSignedField Res = Result.A; + MDSignedOrMDField &Result) { + // Try to parse a signed int. + if (Lex.getKind() == lltok::APSInt) { + MDSignedField Res = Result.A; if (!parseMDField(Loc, Name, Res)) { - Result.assign(Res); - return false; - } - return true; - } - - // Otherwise, try to parse as an MDField. - MDField Res = Result.B; + Result.assign(Res); + return false; + } + return true; + } + + // Otherwise, try to parse as an MDField. + MDField Res = Result.B; if (!parseMDField(Loc, Name, Res)) { - Result.assign(Res); - return false; - } - - return true; -} - -template <> + Result.assign(Res); + return false; + } + + return true; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, MDStringField &Result) { - LocTy ValueLoc = Lex.getLoc(); - std::string S; + LocTy ValueLoc = Lex.getLoc(); + std::string S; if (parseStringConstant(S)) - return true; - - if (!Result.AllowEmpty && S.empty()) + return true; + + if (!Result.AllowEmpty && S.empty()) return error(ValueLoc, "'" + Name + "' cannot be empty"); - - Result.assign(S.empty() ? nullptr : MDString::get(Context, S)); - return false; -} - -template <> + + Result.assign(S.empty() ? nullptr : MDString::get(Context, S)); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, MDFieldList &Result) { - SmallVector<Metadata *, 4> MDs; + SmallVector<Metadata *, 4> MDs; if (parseMDNodeVector(MDs)) - return true; - - Result.assign(std::move(MDs)); - return false; -} - -template <> + return true; + + Result.assign(std::move(MDs)); + return false; +} + +template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, - ChecksumKindField &Result) { - Optional<DIFile::ChecksumKind> CSKind = - DIFile::getChecksumKind(Lex.getStrVal()); - - if (Lex.getKind() != lltok::ChecksumKind || !CSKind) + ChecksumKindField &Result) { + Optional<DIFile::ChecksumKind> CSKind = + DIFile::getChecksumKind(Lex.getStrVal()); + + if (Lex.getKind() != lltok::ChecksumKind || !CSKind) return tokError("invalid checksum kind" + Twine(" '") + Lex.getStrVal() + "'"); - - Result.assign(*CSKind); - Lex.Lex(); - return false; -} - -} // end namespace llvm - -template <class ParserTy> + + Result.assign(*CSKind); + Lex.Lex(); + return false; +} + +} // end namespace llvm + +template <class ParserTy> bool LLParser::parseMDFieldsImplBody(ParserTy ParseField) { - do { - if (Lex.getKind() != lltok::LabelStr) + do { + if (Lex.getKind() != lltok::LabelStr) return tokError("expected field label here"); - + if (ParseField()) - return true; - } while (EatIfPresent(lltok::comma)); - - return false; -} - -template <class ParserTy> + return true; + } while (EatIfPresent(lltok::comma)); + + return false; +} + +template <class ParserTy> bool LLParser::parseMDFieldsImpl(ParserTy ParseField, LocTy &ClosingLoc) { - assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); - Lex.Lex(); - + assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); + Lex.Lex(); + if (parseToken(lltok::lparen, "expected '(' here")) - return true; - if (Lex.getKind() != lltok::rparen) + return true; + if (Lex.getKind() != lltok::rparen) if (parseMDFieldsImplBody(ParseField)) - return true; - - ClosingLoc = Lex.getLoc(); + return true; + + ClosingLoc = Lex.getLoc(); return parseToken(lltok::rparen, "expected ')' here"); -} - -template <class FieldTy> +} + +template <class FieldTy> bool LLParser::parseMDField(StringRef Name, FieldTy &Result) { - if (Result.Seen) + if (Result.Seen) return tokError("field '" + Name + "' cannot be specified more than once"); - - LocTy Loc = Lex.getLoc(); - Lex.Lex(); + + LocTy Loc = Lex.getLoc(); + Lex.Lex(); return parseMDField(Loc, Name, Result); -} - +} + bool LLParser::parseSpecializedMDNode(MDNode *&N, bool IsDistinct) { - assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); - -#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ - if (Lex.getStrVal() == #CLASS) \ + assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); + +#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ + if (Lex.getStrVal() == #CLASS) \ return parse##CLASS(N, IsDistinct); -#include "llvm/IR/Metadata.def" - +#include "llvm/IR/Metadata.def" + return tokError("expected metadata type"); -} - -#define DECLARE_FIELD(NAME, TYPE, INIT) TYPE NAME INIT -#define NOP_FIELD(NAME, TYPE, INIT) -#define REQUIRE_FIELD(NAME, TYPE, INIT) \ - if (!NAME.Seen) \ +} + +#define DECLARE_FIELD(NAME, TYPE, INIT) TYPE NAME INIT +#define NOP_FIELD(NAME, TYPE, INIT) +#define REQUIRE_FIELD(NAME, TYPE, INIT) \ + if (!NAME.Seen) \ return error(ClosingLoc, "missing required field '" #NAME "'"); -#define PARSE_MD_FIELD(NAME, TYPE, DEFAULT) \ - if (Lex.getStrVal() == #NAME) \ +#define PARSE_MD_FIELD(NAME, TYPE, DEFAULT) \ + if (Lex.getStrVal() == #NAME) \ return parseMDField(#NAME, NAME); -#define PARSE_MD_FIELDS() \ - VISIT_MD_FIELDS(DECLARE_FIELD, DECLARE_FIELD) \ - do { \ - LocTy ClosingLoc; \ +#define PARSE_MD_FIELDS() \ + VISIT_MD_FIELDS(DECLARE_FIELD, DECLARE_FIELD) \ + do { \ + LocTy ClosingLoc; \ if (parseMDFieldsImpl( \ [&]() -> bool { \ VISIT_MD_FIELDS(PARSE_MD_FIELD, PARSE_MD_FIELD) \ @@ -4609,88 +4609,88 @@ bool LLParser::parseSpecializedMDNode(MDNode *&N, bool IsDistinct) { "'"); \ }, \ ClosingLoc)) \ - return true; \ - VISIT_MD_FIELDS(NOP_FIELD, REQUIRE_FIELD) \ - } while (false) -#define GET_OR_DISTINCT(CLASS, ARGS) \ - (IsDistinct ? CLASS::getDistinct ARGS : CLASS::get ARGS) - + return true; \ + VISIT_MD_FIELDS(NOP_FIELD, REQUIRE_FIELD) \ + } while (false) +#define GET_OR_DISTINCT(CLASS, ARGS) \ + (IsDistinct ? CLASS::getDistinct ARGS : CLASS::get ARGS) + /// parseDILocationFields: -/// ::= !DILocation(line: 43, column: 8, scope: !5, inlinedAt: !6, -/// isImplicitCode: true) +/// ::= !DILocation(line: 43, column: 8, scope: !5, inlinedAt: !6, +/// isImplicitCode: true) bool LLParser::parseDILocation(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - OPTIONAL(line, LineField, ); \ - OPTIONAL(column, ColumnField, ); \ - REQUIRED(scope, MDField, (/* AllowNull */ false)); \ - OPTIONAL(inlinedAt, MDField, ); \ - OPTIONAL(isImplicitCode, MDBoolField, (false)); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = - GET_OR_DISTINCT(DILocation, (Context, line.Val, column.Val, scope.Val, - inlinedAt.Val, isImplicitCode.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(column, ColumnField, ); \ + REQUIRED(scope, MDField, (/* AllowNull */ false)); \ + OPTIONAL(inlinedAt, MDField, ); \ + OPTIONAL(isImplicitCode, MDBoolField, (false)); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = + GET_OR_DISTINCT(DILocation, (Context, line.Val, column.Val, scope.Val, + inlinedAt.Val, isImplicitCode.Val)); + return false; +} + /// parseGenericDINode: -/// ::= !GenericDINode(tag: 15, header: "...", operands: {...}) +/// ::= !GenericDINode(tag: 15, header: "...", operands: {...}) bool LLParser::parseGenericDINode(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(tag, DwarfTagField, ); \ - OPTIONAL(header, MDStringField, ); \ - OPTIONAL(operands, MDFieldList, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT(GenericDINode, - (Context, tag.Val, header.Val, operands.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + OPTIONAL(header, MDStringField, ); \ + OPTIONAL(operands, MDFieldList, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(GenericDINode, + (Context, tag.Val, header.Val, operands.Val)); + return false; +} + /// parseDISubrange: -/// ::= !DISubrange(count: 30, lowerBound: 2) -/// ::= !DISubrange(count: !node, lowerBound: 2) -/// ::= !DISubrange(lowerBound: !node1, upperBound: !node2, stride: !node3) +/// ::= !DISubrange(count: 30, lowerBound: 2) +/// ::= !DISubrange(count: !node, lowerBound: 2) +/// ::= !DISubrange(lowerBound: !node1, upperBound: !node2, stride: !node3) bool LLParser::parseDISubrange(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - OPTIONAL(count, MDSignedOrMDField, (-1, -1, INT64_MAX, false)); \ - OPTIONAL(lowerBound, MDSignedOrMDField, ); \ - OPTIONAL(upperBound, MDSignedOrMDField, ); \ - OPTIONAL(stride, MDSignedOrMDField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Metadata *Count = nullptr; - Metadata *LowerBound = nullptr; - Metadata *UpperBound = nullptr; - Metadata *Stride = nullptr; - if (count.isMDSignedField()) - Count = ConstantAsMetadata::get(ConstantInt::getSigned( - Type::getInt64Ty(Context), count.getMDSignedValue())); - else if (count.isMDField()) - Count = count.getMDFieldValue(); - - auto convToMetadata = [&](MDSignedOrMDField Bound) -> Metadata * { - if (Bound.isMDSignedField()) - return ConstantAsMetadata::get(ConstantInt::getSigned( - Type::getInt64Ty(Context), Bound.getMDSignedValue())); - if (Bound.isMDField()) - return Bound.getMDFieldValue(); - return nullptr; - }; - - LowerBound = convToMetadata(lowerBound); - UpperBound = convToMetadata(upperBound); - Stride = convToMetadata(stride); - - Result = GET_OR_DISTINCT(DISubrange, - (Context, Count, LowerBound, UpperBound, Stride)); - - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(count, MDSignedOrMDField, (-1, -1, INT64_MAX, false)); \ + OPTIONAL(lowerBound, MDSignedOrMDField, ); \ + OPTIONAL(upperBound, MDSignedOrMDField, ); \ + OPTIONAL(stride, MDSignedOrMDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Metadata *Count = nullptr; + Metadata *LowerBound = nullptr; + Metadata *UpperBound = nullptr; + Metadata *Stride = nullptr; + if (count.isMDSignedField()) + Count = ConstantAsMetadata::get(ConstantInt::getSigned( + Type::getInt64Ty(Context), count.getMDSignedValue())); + else if (count.isMDField()) + Count = count.getMDFieldValue(); + + auto convToMetadata = [&](MDSignedOrMDField Bound) -> Metadata * { + if (Bound.isMDSignedField()) + return ConstantAsMetadata::get(ConstantInt::getSigned( + Type::getInt64Ty(Context), Bound.getMDSignedValue())); + if (Bound.isMDField()) + return Bound.getMDFieldValue(); + return nullptr; + }; + + LowerBound = convToMetadata(lowerBound); + UpperBound = convToMetadata(upperBound); + Stride = convToMetadata(stride); + + Result = GET_OR_DISTINCT(DISubrange, + (Context, Count, LowerBound, UpperBound, Stride)); + + return false; +} + /// parseDIGenericSubrange: /// ::= !DIGenericSubrange(lowerBound: !node1, upperBound: !node2, stride: /// !node3) @@ -4725,49 +4725,49 @@ bool LLParser::parseDIGenericSubrange(MDNode *&Result, bool IsDistinct) { } /// parseDIEnumerator: -/// ::= !DIEnumerator(value: 30, isUnsigned: true, name: "SomeKind") +/// ::= !DIEnumerator(value: 30, isUnsigned: true, name: "SomeKind") bool LLParser::parseDIEnumerator(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(name, MDStringField, ); \ - REQUIRED(value, MDAPSIntField, ); \ - OPTIONAL(isUnsigned, MDBoolField, (false)); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - if (isUnsigned.Val && value.Val.isNegative()) +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(name, MDStringField, ); \ + REQUIRED(value, MDAPSIntField, ); \ + OPTIONAL(isUnsigned, MDBoolField, (false)); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + if (isUnsigned.Val && value.Val.isNegative()) return tokError("unsigned enumerator with negative value"); - - APSInt Value(value.Val); - // Add a leading zero so that unsigned values with the msb set are not - // mistaken for negative values when used for signed enumerators. - if (!isUnsigned.Val && value.Val.isUnsigned() && value.Val.isSignBitSet()) - Value = Value.zext(Value.getBitWidth() + 1); - - Result = - GET_OR_DISTINCT(DIEnumerator, (Context, Value, isUnsigned.Val, name.Val)); - - return false; -} - + + APSInt Value(value.Val); + // Add a leading zero so that unsigned values with the msb set are not + // mistaken for negative values when used for signed enumerators. + if (!isUnsigned.Val && value.Val.isUnsigned() && value.Val.isSignBitSet()) + Value = Value.zext(Value.getBitWidth() + 1); + + Result = + GET_OR_DISTINCT(DIEnumerator, (Context, Value, isUnsigned.Val, name.Val)); + + return false; +} + /// parseDIBasicType: -/// ::= !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, -/// encoding: DW_ATE_encoding, flags: 0) +/// ::= !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, +/// encoding: DW_ATE_encoding, flags: 0) bool LLParser::parseDIBasicType(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_base_type)); \ - OPTIONAL(name, MDStringField, ); \ - OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ - OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ - OPTIONAL(encoding, DwarfAttEncodingField, ); \ - OPTIONAL(flags, DIFlagField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT(DIBasicType, (Context, tag.Val, name.Val, size.Val, - align.Val, encoding.Val, flags.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_base_type)); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(encoding, DwarfAttEncodingField, ); \ + OPTIONAL(flags, DIFlagField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DIBasicType, (Context, tag.Val, name.Val, size.Val, + align.Val, encoding.Val, flags.Val)); + return false; +} + /// parseDIStringType: /// ::= !DIStringType(name: "character(4)", size: 32, align: 32) bool LLParser::parseDIStringType(MDNode *&Result, bool IsDistinct) { @@ -4790,64 +4790,64 @@ bool LLParser::parseDIStringType(MDNode *&Result, bool IsDistinct) { } /// parseDIDerivedType: -/// ::= !DIDerivedType(tag: DW_TAG_pointer_type, name: "int", file: !0, -/// line: 7, scope: !1, baseType: !2, size: 32, -/// align: 32, offset: 0, flags: 0, extraData: !3, -/// dwarfAddressSpace: 3) +/// ::= !DIDerivedType(tag: DW_TAG_pointer_type, name: "int", file: !0, +/// line: 7, scope: !1, baseType: !2, size: 32, +/// align: 32, offset: 0, flags: 0, extraData: !3, +/// dwarfAddressSpace: 3) bool LLParser::parseDIDerivedType(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(tag, DwarfTagField, ); \ - OPTIONAL(name, MDStringField, ); \ - OPTIONAL(file, MDField, ); \ - OPTIONAL(line, LineField, ); \ - OPTIONAL(scope, MDField, ); \ - REQUIRED(baseType, MDField, ); \ - OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ - OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ - OPTIONAL(offset, MDUnsignedField, (0, UINT64_MAX)); \ - OPTIONAL(flags, DIFlagField, ); \ - OPTIONAL(extraData, MDField, ); \ - OPTIONAL(dwarfAddressSpace, MDUnsignedField, (UINT32_MAX, UINT32_MAX)); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Optional<unsigned> DWARFAddressSpace; - if (dwarfAddressSpace.Val != UINT32_MAX) - DWARFAddressSpace = dwarfAddressSpace.Val; - - Result = GET_OR_DISTINCT(DIDerivedType, - (Context, tag.Val, name.Val, file.Val, line.Val, - scope.Val, baseType.Val, size.Val, align.Val, - offset.Val, DWARFAddressSpace, flags.Val, - extraData.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(scope, MDField, ); \ + REQUIRED(baseType, MDField, ); \ + OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(offset, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(extraData, MDField, ); \ + OPTIONAL(dwarfAddressSpace, MDUnsignedField, (UINT32_MAX, UINT32_MAX)); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Optional<unsigned> DWARFAddressSpace; + if (dwarfAddressSpace.Val != UINT32_MAX) + DWARFAddressSpace = dwarfAddressSpace.Val; + + Result = GET_OR_DISTINCT(DIDerivedType, + (Context, tag.Val, name.Val, file.Val, line.Val, + scope.Val, baseType.Val, size.Val, align.Val, + offset.Val, DWARFAddressSpace, flags.Val, + extraData.Val)); + return false; +} + bool LLParser::parseDICompositeType(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(tag, DwarfTagField, ); \ - OPTIONAL(name, MDStringField, ); \ - OPTIONAL(file, MDField, ); \ - OPTIONAL(line, LineField, ); \ - OPTIONAL(scope, MDField, ); \ - OPTIONAL(baseType, MDField, ); \ - OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ - OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ - OPTIONAL(offset, MDUnsignedField, (0, UINT64_MAX)); \ - OPTIONAL(flags, DIFlagField, ); \ - OPTIONAL(elements, MDField, ); \ - OPTIONAL(runtimeLang, DwarfLangField, ); \ - OPTIONAL(vtableHolder, MDField, ); \ - OPTIONAL(templateParams, MDField, ); \ - OPTIONAL(identifier, MDStringField, ); \ - OPTIONAL(discriminator, MDField, ); \ +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(scope, MDField, ); \ + OPTIONAL(baseType, MDField, ); \ + OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(offset, MDUnsignedField, (0, UINT64_MAX)); \ + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(elements, MDField, ); \ + OPTIONAL(runtimeLang, DwarfLangField, ); \ + OPTIONAL(vtableHolder, MDField, ); \ + OPTIONAL(templateParams, MDField, ); \ + OPTIONAL(identifier, MDStringField, ); \ + OPTIONAL(discriminator, MDField, ); \ OPTIONAL(dataLocation, MDField, ); \ OPTIONAL(associated, MDField, ); \ OPTIONAL(allocated, MDField, ); \ OPTIONAL(rank, MDSignedOrMDField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + Metadata *Rank = nullptr; if (rank.isMDSignedField()) Rank = ConstantAsMetadata::get(ConstantInt::getSigned( @@ -4855,653 +4855,653 @@ bool LLParser::parseDICompositeType(MDNode *&Result, bool IsDistinct) { else if (rank.isMDField()) Rank = rank.getMDFieldValue(); - // If this has an identifier try to build an ODR type. - if (identifier.Val) - if (auto *CT = DICompositeType::buildODRType( - Context, *identifier.Val, tag.Val, name.Val, file.Val, line.Val, - scope.Val, baseType.Val, size.Val, align.Val, offset.Val, flags.Val, - elements.Val, runtimeLang.Val, vtableHolder.Val, templateParams.Val, + // If this has an identifier try to build an ODR type. + if (identifier.Val) + if (auto *CT = DICompositeType::buildODRType( + Context, *identifier.Val, tag.Val, name.Val, file.Val, line.Val, + scope.Val, baseType.Val, size.Val, align.Val, offset.Val, flags.Val, + elements.Val, runtimeLang.Val, vtableHolder.Val, templateParams.Val, discriminator.Val, dataLocation.Val, associated.Val, allocated.Val, Rank)) { - Result = CT; - return false; - } - - // Create a new node, and save it in the context if it belongs in the type - // map. - Result = GET_OR_DISTINCT( - DICompositeType, - (Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val, - size.Val, align.Val, offset.Val, flags.Val, elements.Val, - runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val, + Result = CT; + return false; + } + + // Create a new node, and save it in the context if it belongs in the type + // map. + Result = GET_OR_DISTINCT( + DICompositeType, + (Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val, + size.Val, align.Val, offset.Val, flags.Val, elements.Val, + runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val, discriminator.Val, dataLocation.Val, associated.Val, allocated.Val, Rank)); - return false; -} - + return false; +} + bool LLParser::parseDISubroutineType(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - OPTIONAL(flags, DIFlagField, ); \ - OPTIONAL(cc, DwarfCCField, ); \ - REQUIRED(types, MDField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT(DISubroutineType, - (Context, flags.Val, cc.Val, types.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(cc, DwarfCCField, ); \ + REQUIRED(types, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DISubroutineType, + (Context, flags.Val, cc.Val, types.Val)); + return false; +} + /// parseDIFileType: -/// ::= !DIFileType(filename: "path/to/file", directory: "/path/to/dir", -/// checksumkind: CSK_MD5, -/// checksum: "000102030405060708090a0b0c0d0e0f", -/// source: "source file contents") +/// ::= !DIFileType(filename: "path/to/file", directory: "/path/to/dir", +/// checksumkind: CSK_MD5, +/// checksum: "000102030405060708090a0b0c0d0e0f", +/// source: "source file contents") bool LLParser::parseDIFile(MDNode *&Result, bool IsDistinct) { - // The default constructed value for checksumkind is required, but will never - // be used, as the parser checks if the field was actually Seen before using - // the Val. -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(filename, MDStringField, ); \ - REQUIRED(directory, MDStringField, ); \ - OPTIONAL(checksumkind, ChecksumKindField, (DIFile::CSK_MD5)); \ - OPTIONAL(checksum, MDStringField, ); \ - OPTIONAL(source, MDStringField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Optional<DIFile::ChecksumInfo<MDString *>> OptChecksum; - if (checksumkind.Seen && checksum.Seen) - OptChecksum.emplace(checksumkind.Val, checksum.Val); - else if (checksumkind.Seen || checksum.Seen) - return Lex.Error("'checksumkind' and 'checksum' must be provided together"); - - Optional<MDString *> OptSource; - if (source.Seen) - OptSource = source.Val; - Result = GET_OR_DISTINCT(DIFile, (Context, filename.Val, directory.Val, - OptChecksum, OptSource)); - return false; -} - + // The default constructed value for checksumkind is required, but will never + // be used, as the parser checks if the field was actually Seen before using + // the Val. +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(filename, MDStringField, ); \ + REQUIRED(directory, MDStringField, ); \ + OPTIONAL(checksumkind, ChecksumKindField, (DIFile::CSK_MD5)); \ + OPTIONAL(checksum, MDStringField, ); \ + OPTIONAL(source, MDStringField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Optional<DIFile::ChecksumInfo<MDString *>> OptChecksum; + if (checksumkind.Seen && checksum.Seen) + OptChecksum.emplace(checksumkind.Val, checksum.Val); + else if (checksumkind.Seen || checksum.Seen) + return Lex.Error("'checksumkind' and 'checksum' must be provided together"); + + Optional<MDString *> OptSource; + if (source.Seen) + OptSource = source.Val; + Result = GET_OR_DISTINCT(DIFile, (Context, filename.Val, directory.Val, + OptChecksum, OptSource)); + return false; +} + /// parseDICompileUnit: -/// ::= !DICompileUnit(language: DW_LANG_C99, file: !0, producer: "clang", -/// isOptimized: true, flags: "-O2", runtimeVersion: 1, -/// splitDebugFilename: "abc.debug", -/// emissionKind: FullDebug, enums: !1, retainedTypes: !2, -/// globals: !4, imports: !5, macros: !6, dwoId: 0x0abcd, -/// sysroot: "/", sdk: "MacOSX.sdk") +/// ::= !DICompileUnit(language: DW_LANG_C99, file: !0, producer: "clang", +/// isOptimized: true, flags: "-O2", runtimeVersion: 1, +/// splitDebugFilename: "abc.debug", +/// emissionKind: FullDebug, enums: !1, retainedTypes: !2, +/// globals: !4, imports: !5, macros: !6, dwoId: 0x0abcd, +/// sysroot: "/", sdk: "MacOSX.sdk") bool LLParser::parseDICompileUnit(MDNode *&Result, bool IsDistinct) { - if (!IsDistinct) - return Lex.Error("missing 'distinct', required for !DICompileUnit"); - -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(language, DwarfLangField, ); \ - REQUIRED(file, MDField, (/* AllowNull */ false)); \ - OPTIONAL(producer, MDStringField, ); \ - OPTIONAL(isOptimized, MDBoolField, ); \ - OPTIONAL(flags, MDStringField, ); \ - OPTIONAL(runtimeVersion, MDUnsignedField, (0, UINT32_MAX)); \ - OPTIONAL(splitDebugFilename, MDStringField, ); \ - OPTIONAL(emissionKind, EmissionKindField, ); \ - OPTIONAL(enums, MDField, ); \ - OPTIONAL(retainedTypes, MDField, ); \ - OPTIONAL(globals, MDField, ); \ - OPTIONAL(imports, MDField, ); \ - OPTIONAL(macros, MDField, ); \ - OPTIONAL(dwoId, MDUnsignedField, ); \ - OPTIONAL(splitDebugInlining, MDBoolField, = true); \ - OPTIONAL(debugInfoForProfiling, MDBoolField, = false); \ - OPTIONAL(nameTableKind, NameTableKindField, ); \ - OPTIONAL(rangesBaseAddress, MDBoolField, = false); \ - OPTIONAL(sysroot, MDStringField, ); \ - OPTIONAL(sdk, MDStringField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = DICompileUnit::getDistinct( - Context, language.Val, file.Val, producer.Val, isOptimized.Val, flags.Val, - runtimeVersion.Val, splitDebugFilename.Val, emissionKind.Val, enums.Val, - retainedTypes.Val, globals.Val, imports.Val, macros.Val, dwoId.Val, - splitDebugInlining.Val, debugInfoForProfiling.Val, nameTableKind.Val, - rangesBaseAddress.Val, sysroot.Val, sdk.Val); - return false; -} - + if (!IsDistinct) + return Lex.Error("missing 'distinct', required for !DICompileUnit"); + +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(language, DwarfLangField, ); \ + REQUIRED(file, MDField, (/* AllowNull */ false)); \ + OPTIONAL(producer, MDStringField, ); \ + OPTIONAL(isOptimized, MDBoolField, ); \ + OPTIONAL(flags, MDStringField, ); \ + OPTIONAL(runtimeVersion, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(splitDebugFilename, MDStringField, ); \ + OPTIONAL(emissionKind, EmissionKindField, ); \ + OPTIONAL(enums, MDField, ); \ + OPTIONAL(retainedTypes, MDField, ); \ + OPTIONAL(globals, MDField, ); \ + OPTIONAL(imports, MDField, ); \ + OPTIONAL(macros, MDField, ); \ + OPTIONAL(dwoId, MDUnsignedField, ); \ + OPTIONAL(splitDebugInlining, MDBoolField, = true); \ + OPTIONAL(debugInfoForProfiling, MDBoolField, = false); \ + OPTIONAL(nameTableKind, NameTableKindField, ); \ + OPTIONAL(rangesBaseAddress, MDBoolField, = false); \ + OPTIONAL(sysroot, MDStringField, ); \ + OPTIONAL(sdk, MDStringField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = DICompileUnit::getDistinct( + Context, language.Val, file.Val, producer.Val, isOptimized.Val, flags.Val, + runtimeVersion.Val, splitDebugFilename.Val, emissionKind.Val, enums.Val, + retainedTypes.Val, globals.Val, imports.Val, macros.Val, dwoId.Val, + splitDebugInlining.Val, debugInfoForProfiling.Val, nameTableKind.Val, + rangesBaseAddress.Val, sysroot.Val, sdk.Val); + return false; +} + /// parseDISubprogram: -/// ::= !DISubprogram(scope: !0, name: "foo", linkageName: "_Zfoo", -/// file: !1, line: 7, type: !2, isLocal: false, -/// isDefinition: true, scopeLine: 8, containingType: !3, -/// virtuality: DW_VIRTUALTIY_pure_virtual, -/// virtualIndex: 10, thisAdjustment: 4, flags: 11, -/// spFlags: 10, isOptimized: false, templateParams: !4, -/// declaration: !5, retainedNodes: !6, thrownTypes: !7) +/// ::= !DISubprogram(scope: !0, name: "foo", linkageName: "_Zfoo", +/// file: !1, line: 7, type: !2, isLocal: false, +/// isDefinition: true, scopeLine: 8, containingType: !3, +/// virtuality: DW_VIRTUALTIY_pure_virtual, +/// virtualIndex: 10, thisAdjustment: 4, flags: 11, +/// spFlags: 10, isOptimized: false, templateParams: !4, +/// declaration: !5, retainedNodes: !6, thrownTypes: !7) bool LLParser::parseDISubprogram(MDNode *&Result, bool IsDistinct) { - auto Loc = Lex.getLoc(); -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - OPTIONAL(scope, MDField, ); \ - OPTIONAL(name, MDStringField, ); \ - OPTIONAL(linkageName, MDStringField, ); \ - OPTIONAL(file, MDField, ); \ - OPTIONAL(line, LineField, ); \ - OPTIONAL(type, MDField, ); \ - OPTIONAL(isLocal, MDBoolField, ); \ - OPTIONAL(isDefinition, MDBoolField, (true)); \ - OPTIONAL(scopeLine, LineField, ); \ - OPTIONAL(containingType, MDField, ); \ - OPTIONAL(virtuality, DwarfVirtualityField, ); \ - OPTIONAL(virtualIndex, MDUnsignedField, (0, UINT32_MAX)); \ - OPTIONAL(thisAdjustment, MDSignedField, (0, INT32_MIN, INT32_MAX)); \ - OPTIONAL(flags, DIFlagField, ); \ - OPTIONAL(spFlags, DISPFlagField, ); \ - OPTIONAL(isOptimized, MDBoolField, ); \ - OPTIONAL(unit, MDField, ); \ - OPTIONAL(templateParams, MDField, ); \ - OPTIONAL(declaration, MDField, ); \ - OPTIONAL(retainedNodes, MDField, ); \ - OPTIONAL(thrownTypes, MDField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - // An explicit spFlags field takes precedence over individual fields in - // older IR versions. - DISubprogram::DISPFlags SPFlags = - spFlags.Seen ? spFlags.Val - : DISubprogram::toSPFlags(isLocal.Val, isDefinition.Val, - isOptimized.Val, virtuality.Val); - if ((SPFlags & DISubprogram::SPFlagDefinition) && !IsDistinct) - return Lex.Error( - Loc, - "missing 'distinct', required for !DISubprogram that is a Definition"); - Result = GET_OR_DISTINCT( - DISubprogram, - (Context, scope.Val, name.Val, linkageName.Val, file.Val, line.Val, - type.Val, scopeLine.Val, containingType.Val, virtualIndex.Val, - thisAdjustment.Val, flags.Val, SPFlags, unit.Val, templateParams.Val, - declaration.Val, retainedNodes.Val, thrownTypes.Val)); - return false; -} - + auto Loc = Lex.getLoc(); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(scope, MDField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(linkageName, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(type, MDField, ); \ + OPTIONAL(isLocal, MDBoolField, ); \ + OPTIONAL(isDefinition, MDBoolField, (true)); \ + OPTIONAL(scopeLine, LineField, ); \ + OPTIONAL(containingType, MDField, ); \ + OPTIONAL(virtuality, DwarfVirtualityField, ); \ + OPTIONAL(virtualIndex, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(thisAdjustment, MDSignedField, (0, INT32_MIN, INT32_MAX)); \ + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(spFlags, DISPFlagField, ); \ + OPTIONAL(isOptimized, MDBoolField, ); \ + OPTIONAL(unit, MDField, ); \ + OPTIONAL(templateParams, MDField, ); \ + OPTIONAL(declaration, MDField, ); \ + OPTIONAL(retainedNodes, MDField, ); \ + OPTIONAL(thrownTypes, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + // An explicit spFlags field takes precedence over individual fields in + // older IR versions. + DISubprogram::DISPFlags SPFlags = + spFlags.Seen ? spFlags.Val + : DISubprogram::toSPFlags(isLocal.Val, isDefinition.Val, + isOptimized.Val, virtuality.Val); + if ((SPFlags & DISubprogram::SPFlagDefinition) && !IsDistinct) + return Lex.Error( + Loc, + "missing 'distinct', required for !DISubprogram that is a Definition"); + Result = GET_OR_DISTINCT( + DISubprogram, + (Context, scope.Val, name.Val, linkageName.Val, file.Val, line.Val, + type.Val, scopeLine.Val, containingType.Val, virtualIndex.Val, + thisAdjustment.Val, flags.Val, SPFlags, unit.Val, templateParams.Val, + declaration.Val, retainedNodes.Val, thrownTypes.Val)); + return false; +} + /// parseDILexicalBlock: -/// ::= !DILexicalBlock(scope: !0, file: !2, line: 7, column: 9) +/// ::= !DILexicalBlock(scope: !0, file: !2, line: 7, column: 9) bool LLParser::parseDILexicalBlock(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(scope, MDField, (/* AllowNull */ false)); \ - OPTIONAL(file, MDField, ); \ - OPTIONAL(line, LineField, ); \ - OPTIONAL(column, ColumnField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT( - DILexicalBlock, (Context, scope.Val, file.Val, line.Val, column.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, (/* AllowNull */ false)); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(column, ColumnField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT( + DILexicalBlock, (Context, scope.Val, file.Val, line.Val, column.Val)); + return false; +} + /// parseDILexicalBlockFile: -/// ::= !DILexicalBlockFile(scope: !0, file: !2, discriminator: 9) +/// ::= !DILexicalBlockFile(scope: !0, file: !2, discriminator: 9) bool LLParser::parseDILexicalBlockFile(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(scope, MDField, (/* AllowNull */ false)); \ - OPTIONAL(file, MDField, ); \ - REQUIRED(discriminator, MDUnsignedField, (0, UINT32_MAX)); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT(DILexicalBlockFile, - (Context, scope.Val, file.Val, discriminator.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, (/* AllowNull */ false)); \ + OPTIONAL(file, MDField, ); \ + REQUIRED(discriminator, MDUnsignedField, (0, UINT32_MAX)); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DILexicalBlockFile, + (Context, scope.Val, file.Val, discriminator.Val)); + return false; +} + /// parseDICommonBlock: -/// ::= !DICommonBlock(scope: !0, file: !2, name: "COMMON name", line: 9) +/// ::= !DICommonBlock(scope: !0, file: !2, name: "COMMON name", line: 9) bool LLParser::parseDICommonBlock(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(scope, MDField, ); \ - OPTIONAL(declaration, MDField, ); \ - OPTIONAL(name, MDStringField, ); \ - OPTIONAL(file, MDField, ); \ - OPTIONAL(line, LineField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT(DICommonBlock, - (Context, scope.Val, declaration.Val, name.Val, - file.Val, line.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, ); \ + OPTIONAL(declaration, MDField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DICommonBlock, + (Context, scope.Val, declaration.Val, name.Val, + file.Val, line.Val)); + return false; +} + /// parseDINamespace: -/// ::= !DINamespace(scope: !0, file: !2, name: "SomeNamespace", line: 9) +/// ::= !DINamespace(scope: !0, file: !2, name: "SomeNamespace", line: 9) bool LLParser::parseDINamespace(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(scope, MDField, ); \ - OPTIONAL(name, MDStringField, ); \ - OPTIONAL(exportSymbols, MDBoolField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT(DINamespace, - (Context, scope.Val, name.Val, exportSymbols.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(exportSymbols, MDBoolField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DINamespace, + (Context, scope.Val, name.Val, exportSymbols.Val)); + return false; +} + /// parseDIMacro: /// ::= !DIMacro(macinfo: type, line: 9, name: "SomeMacro", value: /// "SomeValue") bool LLParser::parseDIMacro(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(type, DwarfMacinfoTypeField, ); \ - OPTIONAL(line, LineField, ); \ - REQUIRED(name, MDStringField, ); \ - OPTIONAL(value, MDStringField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT(DIMacro, - (Context, type.Val, line.Val, name.Val, value.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(type, DwarfMacinfoTypeField, ); \ + OPTIONAL(line, LineField, ); \ + REQUIRED(name, MDStringField, ); \ + OPTIONAL(value, MDStringField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DIMacro, + (Context, type.Val, line.Val, name.Val, value.Val)); + return false; +} + /// parseDIMacroFile: -/// ::= !DIMacroFile(line: 9, file: !2, nodes: !3) +/// ::= !DIMacroFile(line: 9, file: !2, nodes: !3) bool LLParser::parseDIMacroFile(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - OPTIONAL(type, DwarfMacinfoTypeField, (dwarf::DW_MACINFO_start_file)); \ - OPTIONAL(line, LineField, ); \ - REQUIRED(file, MDField, ); \ - OPTIONAL(nodes, MDField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT(DIMacroFile, - (Context, type.Val, line.Val, file.Val, nodes.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(type, DwarfMacinfoTypeField, (dwarf::DW_MACINFO_start_file)); \ + OPTIONAL(line, LineField, ); \ + REQUIRED(file, MDField, ); \ + OPTIONAL(nodes, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DIMacroFile, + (Context, type.Val, line.Val, file.Val, nodes.Val)); + return false; +} + /// parseDIModule: -/// ::= !DIModule(scope: !0, name: "SomeModule", configMacros: -/// "-DNDEBUG", includePath: "/usr/include", apinotes: "module.apinotes", +/// ::= !DIModule(scope: !0, name: "SomeModule", configMacros: +/// "-DNDEBUG", includePath: "/usr/include", apinotes: "module.apinotes", /// file: !1, line: 4, isDecl: false) bool LLParser::parseDIModule(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(scope, MDField, ); \ - REQUIRED(name, MDStringField, ); \ - OPTIONAL(configMacros, MDStringField, ); \ - OPTIONAL(includePath, MDStringField, ); \ - OPTIONAL(apinotes, MDStringField, ); \ - OPTIONAL(file, MDField, ); \ +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, ); \ + REQUIRED(name, MDStringField, ); \ + OPTIONAL(configMacros, MDStringField, ); \ + OPTIONAL(includePath, MDStringField, ); \ + OPTIONAL(apinotes, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ OPTIONAL(line, LineField, ); \ OPTIONAL(isDecl, MDBoolField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT(DIModule, (Context, file.Val, scope.Val, name.Val, - configMacros.Val, includePath.Val, + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DIModule, (Context, file.Val, scope.Val, name.Val, + configMacros.Val, includePath.Val, apinotes.Val, line.Val, isDecl.Val)); - return false; -} - + return false; +} + /// parseDITemplateTypeParameter: -/// ::= !DITemplateTypeParameter(name: "Ty", type: !1, defaulted: false) +/// ::= !DITemplateTypeParameter(name: "Ty", type: !1, defaulted: false) bool LLParser::parseDITemplateTypeParameter(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - OPTIONAL(name, MDStringField, ); \ - REQUIRED(type, MDField, ); \ - OPTIONAL(defaulted, MDBoolField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT(DITemplateTypeParameter, - (Context, name.Val, type.Val, defaulted.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(name, MDStringField, ); \ + REQUIRED(type, MDField, ); \ + OPTIONAL(defaulted, MDBoolField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DITemplateTypeParameter, + (Context, name.Val, type.Val, defaulted.Val)); + return false; +} + /// parseDITemplateValueParameter: -/// ::= !DITemplateValueParameter(tag: DW_TAG_template_value_parameter, -/// name: "V", type: !1, defaulted: false, -/// value: i32 7) +/// ::= !DITemplateValueParameter(tag: DW_TAG_template_value_parameter, +/// name: "V", type: !1, defaulted: false, +/// value: i32 7) bool LLParser::parseDITemplateValueParameter(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_template_value_parameter)); \ - OPTIONAL(name, MDStringField, ); \ - OPTIONAL(type, MDField, ); \ - OPTIONAL(defaulted, MDBoolField, ); \ - REQUIRED(value, MDField, ); - - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT( - DITemplateValueParameter, - (Context, tag.Val, name.Val, type.Val, defaulted.Val, value.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_template_value_parameter)); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(type, MDField, ); \ + OPTIONAL(defaulted, MDBoolField, ); \ + REQUIRED(value, MDField, ); + + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT( + DITemplateValueParameter, + (Context, tag.Val, name.Val, type.Val, defaulted.Val, value.Val)); + return false; +} + /// parseDIGlobalVariable: -/// ::= !DIGlobalVariable(scope: !0, name: "foo", linkageName: "foo", -/// file: !1, line: 7, type: !2, isLocal: false, -/// isDefinition: true, templateParams: !3, -/// declaration: !4, align: 8) +/// ::= !DIGlobalVariable(scope: !0, name: "foo", linkageName: "foo", +/// file: !1, line: 7, type: !2, isLocal: false, +/// isDefinition: true, templateParams: !3, +/// declaration: !4, align: 8) bool LLParser::parseDIGlobalVariable(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(name, MDStringField, (/* AllowEmpty */ false)); \ - OPTIONAL(scope, MDField, ); \ - OPTIONAL(linkageName, MDStringField, ); \ - OPTIONAL(file, MDField, ); \ - OPTIONAL(line, LineField, ); \ - OPTIONAL(type, MDField, ); \ - OPTIONAL(isLocal, MDBoolField, ); \ - OPTIONAL(isDefinition, MDBoolField, (true)); \ - OPTIONAL(templateParams, MDField, ); \ - OPTIONAL(declaration, MDField, ); \ - OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = - GET_OR_DISTINCT(DIGlobalVariable, - (Context, scope.Val, name.Val, linkageName.Val, file.Val, - line.Val, type.Val, isLocal.Val, isDefinition.Val, - declaration.Val, templateParams.Val, align.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(name, MDStringField, (/* AllowEmpty */ false)); \ + OPTIONAL(scope, MDField, ); \ + OPTIONAL(linkageName, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(type, MDField, ); \ + OPTIONAL(isLocal, MDBoolField, ); \ + OPTIONAL(isDefinition, MDBoolField, (true)); \ + OPTIONAL(templateParams, MDField, ); \ + OPTIONAL(declaration, MDField, ); \ + OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = + GET_OR_DISTINCT(DIGlobalVariable, + (Context, scope.Val, name.Val, linkageName.Val, file.Val, + line.Val, type.Val, isLocal.Val, isDefinition.Val, + declaration.Val, templateParams.Val, align.Val)); + return false; +} + /// parseDILocalVariable: -/// ::= !DILocalVariable(arg: 7, scope: !0, name: "foo", -/// file: !1, line: 7, type: !2, arg: 2, flags: 7, -/// align: 8) -/// ::= !DILocalVariable(scope: !0, name: "foo", -/// file: !1, line: 7, type: !2, arg: 2, flags: 7, -/// align: 8) +/// ::= !DILocalVariable(arg: 7, scope: !0, name: "foo", +/// file: !1, line: 7, type: !2, arg: 2, flags: 7, +/// align: 8) +/// ::= !DILocalVariable(scope: !0, name: "foo", +/// file: !1, line: 7, type: !2, arg: 2, flags: 7, +/// align: 8) bool LLParser::parseDILocalVariable(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(scope, MDField, (/* AllowNull */ false)); \ - OPTIONAL(name, MDStringField, ); \ - OPTIONAL(arg, MDUnsignedField, (0, UINT16_MAX)); \ - OPTIONAL(file, MDField, ); \ - OPTIONAL(line, LineField, ); \ - OPTIONAL(type, MDField, ); \ - OPTIONAL(flags, DIFlagField, ); \ - OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT(DILocalVariable, - (Context, scope.Val, name.Val, file.Val, line.Val, - type.Val, arg.Val, flags.Val, align.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, (/* AllowNull */ false)); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(arg, MDUnsignedField, (0, UINT16_MAX)); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(type, MDField, ); \ + OPTIONAL(flags, DIFlagField, ); \ + OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DILocalVariable, + (Context, scope.Val, name.Val, file.Val, line.Val, + type.Val, arg.Val, flags.Val, align.Val)); + return false; +} + /// parseDILabel: -/// ::= !DILabel(scope: !0, name: "foo", file: !1, line: 7) +/// ::= !DILabel(scope: !0, name: "foo", file: !1, line: 7) bool LLParser::parseDILabel(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(scope, MDField, (/* AllowNull */ false)); \ - REQUIRED(name, MDStringField, ); \ - REQUIRED(file, MDField, ); \ - REQUIRED(line, LineField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT(DILabel, - (Context, scope.Val, name.Val, file.Val, line.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, (/* AllowNull */ false)); \ + REQUIRED(name, MDStringField, ); \ + REQUIRED(file, MDField, ); \ + REQUIRED(line, LineField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DILabel, + (Context, scope.Val, name.Val, file.Val, line.Val)); + return false; +} + /// parseDIExpression: -/// ::= !DIExpression(0, 7, -1) +/// ::= !DIExpression(0, 7, -1) bool LLParser::parseDIExpression(MDNode *&Result, bool IsDistinct) { - assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); - Lex.Lex(); - + assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); + Lex.Lex(); + if (parseToken(lltok::lparen, "expected '(' here")) - return true; - - SmallVector<uint64_t, 8> Elements; - if (Lex.getKind() != lltok::rparen) - do { - if (Lex.getKind() == lltok::DwarfOp) { - if (unsigned Op = dwarf::getOperationEncoding(Lex.getStrVal())) { - Lex.Lex(); - Elements.push_back(Op); - continue; - } + return true; + + SmallVector<uint64_t, 8> Elements; + if (Lex.getKind() != lltok::rparen) + do { + if (Lex.getKind() == lltok::DwarfOp) { + if (unsigned Op = dwarf::getOperationEncoding(Lex.getStrVal())) { + Lex.Lex(); + Elements.push_back(Op); + continue; + } return tokError(Twine("invalid DWARF op '") + Lex.getStrVal() + "'"); - } - - if (Lex.getKind() == lltok::DwarfAttEncoding) { - if (unsigned Op = dwarf::getAttributeEncoding(Lex.getStrVal())) { - Lex.Lex(); - Elements.push_back(Op); - continue; - } + } + + if (Lex.getKind() == lltok::DwarfAttEncoding) { + if (unsigned Op = dwarf::getAttributeEncoding(Lex.getStrVal())) { + Lex.Lex(); + Elements.push_back(Op); + continue; + } return tokError(Twine("invalid DWARF attribute encoding '") + Lex.getStrVal() + "'"); - } - - if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) + } + + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) return tokError("expected unsigned integer"); - - auto &U = Lex.getAPSIntVal(); - if (U.ugt(UINT64_MAX)) + + auto &U = Lex.getAPSIntVal(); + if (U.ugt(UINT64_MAX)) return tokError("element too large, limit is " + Twine(UINT64_MAX)); - Elements.push_back(U.getZExtValue()); - Lex.Lex(); - } while (EatIfPresent(lltok::comma)); - + Elements.push_back(U.getZExtValue()); + Lex.Lex(); + } while (EatIfPresent(lltok::comma)); + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - Result = GET_OR_DISTINCT(DIExpression, (Context, Elements)); - return false; -} - + return true; + + Result = GET_OR_DISTINCT(DIExpression, (Context, Elements)); + return false; +} + /// parseDIGlobalVariableExpression: -/// ::= !DIGlobalVariableExpression(var: !0, expr: !1) +/// ::= !DIGlobalVariableExpression(var: !0, expr: !1) bool LLParser::parseDIGlobalVariableExpression(MDNode *&Result, - bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(var, MDField, ); \ - REQUIRED(expr, MDField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = - GET_OR_DISTINCT(DIGlobalVariableExpression, (Context, var.Val, expr.Val)); - return false; -} - + bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(var, MDField, ); \ + REQUIRED(expr, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = + GET_OR_DISTINCT(DIGlobalVariableExpression, (Context, var.Val, expr.Val)); + return false; +} + /// parseDIObjCProperty: -/// ::= !DIObjCProperty(name: "foo", file: !1, line: 7, setter: "setFoo", -/// getter: "getFoo", attributes: 7, type: !2) +/// ::= !DIObjCProperty(name: "foo", file: !1, line: 7, setter: "setFoo", +/// getter: "getFoo", attributes: 7, type: !2) bool LLParser::parseDIObjCProperty(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - OPTIONAL(name, MDStringField, ); \ - OPTIONAL(file, MDField, ); \ - OPTIONAL(line, LineField, ); \ - OPTIONAL(setter, MDStringField, ); \ - OPTIONAL(getter, MDStringField, ); \ - OPTIONAL(attributes, MDUnsignedField, (0, UINT32_MAX)); \ - OPTIONAL(type, MDField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT(DIObjCProperty, - (Context, name.Val, file.Val, line.Val, setter.Val, - getter.Val, attributes.Val, type.Val)); - return false; -} - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(setter, MDStringField, ); \ + OPTIONAL(getter, MDStringField, ); \ + OPTIONAL(attributes, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(type, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DIObjCProperty, + (Context, name.Val, file.Val, line.Val, setter.Val, + getter.Val, attributes.Val, type.Val)); + return false; +} + /// parseDIImportedEntity: -/// ::= !DIImportedEntity(tag: DW_TAG_imported_module, scope: !0, entity: !1, -/// line: 7, name: "foo") +/// ::= !DIImportedEntity(tag: DW_TAG_imported_module, scope: !0, entity: !1, +/// line: 7, name: "foo") bool LLParser::parseDIImportedEntity(MDNode *&Result, bool IsDistinct) { -#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ - REQUIRED(tag, DwarfTagField, ); \ - REQUIRED(scope, MDField, ); \ - OPTIONAL(entity, MDField, ); \ - OPTIONAL(file, MDField, ); \ - OPTIONAL(line, LineField, ); \ - OPTIONAL(name, MDStringField, ); - PARSE_MD_FIELDS(); -#undef VISIT_MD_FIELDS - - Result = GET_OR_DISTINCT( - DIImportedEntity, - (Context, tag.Val, scope.Val, entity.Val, file.Val, line.Val, name.Val)); - return false; -} - -#undef PARSE_MD_FIELD -#undef NOP_FIELD -#undef REQUIRE_FIELD -#undef DECLARE_FIELD - +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + REQUIRED(scope, MDField, ); \ + OPTIONAL(entity, MDField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(name, MDStringField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT( + DIImportedEntity, + (Context, tag.Val, scope.Val, entity.Val, file.Val, line.Val, name.Val)); + return false; +} + +#undef PARSE_MD_FIELD +#undef NOP_FIELD +#undef REQUIRE_FIELD +#undef DECLARE_FIELD + /// parseMetadataAsValue -/// ::= metadata i32 %local -/// ::= metadata i32 @global -/// ::= metadata i32 7 -/// ::= metadata !0 -/// ::= metadata !{...} -/// ::= metadata !"string" +/// ::= metadata i32 %local +/// ::= metadata i32 @global +/// ::= metadata i32 7 +/// ::= metadata !0 +/// ::= metadata !{...} +/// ::= metadata !"string" bool LLParser::parseMetadataAsValue(Value *&V, PerFunctionState &PFS) { - // Note: the type 'metadata' has already been parsed. - Metadata *MD; + // Note: the type 'metadata' has already been parsed. + Metadata *MD; if (parseMetadata(MD, &PFS)) - return true; - - V = MetadataAsValue::get(Context, MD); - return false; -} - + return true; + + V = MetadataAsValue::get(Context, MD); + return false; +} + /// parseValueAsMetadata -/// ::= i32 %local -/// ::= i32 @global -/// ::= i32 7 +/// ::= i32 %local +/// ::= i32 @global +/// ::= i32 7 bool LLParser::parseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg, - PerFunctionState *PFS) { - Type *Ty; - LocTy Loc; + PerFunctionState *PFS) { + Type *Ty; + LocTy Loc; if (parseType(Ty, TypeMsg, Loc)) - return true; - if (Ty->isMetadataTy()) + return true; + if (Ty->isMetadataTy()) return error(Loc, "invalid metadata-value-metadata roundtrip"); - - Value *V; + + Value *V; if (parseValue(Ty, V, PFS)) - return true; - - MD = ValueAsMetadata::get(V); - return false; -} - + return true; + + MD = ValueAsMetadata::get(V); + return false; +} + /// parseMetadata -/// ::= i32 %local -/// ::= i32 @global -/// ::= i32 7 -/// ::= !42 -/// ::= !{...} -/// ::= !"string" -/// ::= !DILocation(...) +/// ::= i32 %local +/// ::= i32 @global +/// ::= i32 7 +/// ::= !42 +/// ::= !{...} +/// ::= !"string" +/// ::= !DILocation(...) bool LLParser::parseMetadata(Metadata *&MD, PerFunctionState *PFS) { - if (Lex.getKind() == lltok::MetadataVar) { - MDNode *N; + if (Lex.getKind() == lltok::MetadataVar) { + MDNode *N; if (parseSpecializedMDNode(N)) - return true; - MD = N; - return false; - } - - // ValueAsMetadata: - // <type> <value> - if (Lex.getKind() != lltok::exclaim) + return true; + MD = N; + return false; + } + + // ValueAsMetadata: + // <type> <value> + if (Lex.getKind() != lltok::exclaim) return parseValueAsMetadata(MD, "expected metadata operand", PFS); - - // '!'. - assert(Lex.getKind() == lltok::exclaim && "Expected '!' here"); - Lex.Lex(); - - // MDString: - // ::= '!' STRINGCONSTANT - if (Lex.getKind() == lltok::StringConstant) { - MDString *S; + + // '!'. + assert(Lex.getKind() == lltok::exclaim && "Expected '!' here"); + Lex.Lex(); + + // MDString: + // ::= '!' STRINGCONSTANT + if (Lex.getKind() == lltok::StringConstant) { + MDString *S; if (parseMDString(S)) - return true; - MD = S; - return false; - } - - // MDNode: - // !{ ... } - // !7 - MDNode *N; + return true; + MD = S; + return false; + } + + // MDNode: + // !{ ... } + // !7 + MDNode *N; if (parseMDNodeTail(N)) - return true; - MD = N; - return false; -} - -//===----------------------------------------------------------------------===// -// Function Parsing. -//===----------------------------------------------------------------------===// - + return true; + MD = N; + return false; +} + +//===----------------------------------------------------------------------===// +// Function Parsing. +//===----------------------------------------------------------------------===// + bool LLParser::convertValIDToValue(Type *Ty, ValID &ID, Value *&V, - PerFunctionState *PFS, bool IsCall) { - if (Ty->isFunctionTy()) + PerFunctionState *PFS, bool IsCall) { + if (Ty->isFunctionTy()) return error(ID.Loc, "functions are not values, refer to them as pointers"); - - switch (ID.Kind) { - case ValID::t_LocalID: + + switch (ID.Kind) { + case ValID::t_LocalID: if (!PFS) return error(ID.Loc, "invalid use of function-local name"); V = PFS->getVal(ID.UIntVal, Ty, ID.Loc, IsCall); - return V == nullptr; - case ValID::t_LocalName: + return V == nullptr; + case ValID::t_LocalName: if (!PFS) return error(ID.Loc, "invalid use of function-local name"); V = PFS->getVal(ID.StrVal, Ty, ID.Loc, IsCall); - return V == nullptr; - case ValID::t_InlineAsm: { - if (!ID.FTy || !InlineAsm::Verify(ID.FTy, ID.StrVal2)) + return V == nullptr; + case ValID::t_InlineAsm: { + if (!ID.FTy || !InlineAsm::Verify(ID.FTy, ID.StrVal2)) return error(ID.Loc, "invalid type for inline asm constraint string"); - V = InlineAsm::get(ID.FTy, ID.StrVal, ID.StrVal2, ID.UIntVal & 1, - (ID.UIntVal >> 1) & 1, - (InlineAsm::AsmDialect(ID.UIntVal >> 2))); - return false; - } - case ValID::t_GlobalName: + V = InlineAsm::get(ID.FTy, ID.StrVal, ID.StrVal2, ID.UIntVal & 1, + (ID.UIntVal >> 1) & 1, + (InlineAsm::AsmDialect(ID.UIntVal >> 2))); + return false; + } + case ValID::t_GlobalName: V = getGlobalVal(ID.StrVal, Ty, ID.Loc, IsCall); - return V == nullptr; - case ValID::t_GlobalID: + return V == nullptr; + case ValID::t_GlobalID: V = getGlobalVal(ID.UIntVal, Ty, ID.Loc, IsCall); - return V == nullptr; - case ValID::t_APSInt: - if (!Ty->isIntegerTy()) + return V == nullptr; + case ValID::t_APSInt: + if (!Ty->isIntegerTy()) return error(ID.Loc, "integer constant must have integer type"); - ID.APSIntVal = ID.APSIntVal.extOrTrunc(Ty->getPrimitiveSizeInBits()); - V = ConstantInt::get(Context, ID.APSIntVal); - return false; - case ValID::t_APFloat: - if (!Ty->isFloatingPointTy() || - !ConstantFP::isValueValidForType(Ty, ID.APFloatVal)) + ID.APSIntVal = ID.APSIntVal.extOrTrunc(Ty->getPrimitiveSizeInBits()); + V = ConstantInt::get(Context, ID.APSIntVal); + return false; + case ValID::t_APFloat: + if (!Ty->isFloatingPointTy() || + !ConstantFP::isValueValidForType(Ty, ID.APFloatVal)) return error(ID.Loc, "floating point constant invalid for type"); - - // The lexer has no type info, so builds all half, bfloat, float, and double - // FP constants as double. Fix this here. Long double does not need this. - if (&ID.APFloatVal.getSemantics() == &APFloat::IEEEdouble()) { + + // The lexer has no type info, so builds all half, bfloat, float, and double + // FP constants as double. Fix this here. Long double does not need this. + if (&ID.APFloatVal.getSemantics() == &APFloat::IEEEdouble()) { // Check for signaling before potentially converting and losing that info. bool IsSNAN = ID.APFloatVal.isSignaling(); - bool Ignored; - if (Ty->isHalfTy()) - ID.APFloatVal.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, - &Ignored); - else if (Ty->isBFloatTy()) - ID.APFloatVal.convert(APFloat::BFloat(), APFloat::rmNearestTiesToEven, - &Ignored); - else if (Ty->isFloatTy()) - ID.APFloatVal.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, - &Ignored); + bool Ignored; + if (Ty->isHalfTy()) + ID.APFloatVal.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, + &Ignored); + else if (Ty->isBFloatTy()) + ID.APFloatVal.convert(APFloat::BFloat(), APFloat::rmNearestTiesToEven, + &Ignored); + else if (Ty->isFloatTy()) + ID.APFloatVal.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, + &Ignored); if (IsSNAN) { // The convert call above may quiet an SNaN, so manufacture another // SNaN. The bitcast works because the payload (significand) parameter @@ -5510,275 +5510,275 @@ bool LLParser::convertValIDToValue(Type *Ty, ValID &ID, Value *&V, ID.APFloatVal = APFloat::getSNaN(ID.APFloatVal.getSemantics(), ID.APFloatVal.isNegative(), &Payload); } - } - V = ConstantFP::get(Context, ID.APFloatVal); - - if (V->getType() != Ty) + } + V = ConstantFP::get(Context, ID.APFloatVal); + + if (V->getType() != Ty) return error(ID.Loc, "floating point constant does not have type '" + getTypeString(Ty) + "'"); - - return false; - case ValID::t_Null: - if (!Ty->isPointerTy()) + + return false; + case ValID::t_Null: + if (!Ty->isPointerTy()) return error(ID.Loc, "null must be a pointer type"); - V = ConstantPointerNull::get(cast<PointerType>(Ty)); - return false; - case ValID::t_Undef: - // FIXME: LabelTy should not be a first-class type. - if (!Ty->isFirstClassType() || Ty->isLabelTy()) + V = ConstantPointerNull::get(cast<PointerType>(Ty)); + return false; + case ValID::t_Undef: + // FIXME: LabelTy should not be a first-class type. + if (!Ty->isFirstClassType() || Ty->isLabelTy()) return error(ID.Loc, "invalid type for undef constant"); - V = UndefValue::get(Ty); - return false; - case ValID::t_EmptyArray: - if (!Ty->isArrayTy() || cast<ArrayType>(Ty)->getNumElements() != 0) + V = UndefValue::get(Ty); + return false; + case ValID::t_EmptyArray: + if (!Ty->isArrayTy() || cast<ArrayType>(Ty)->getNumElements() != 0) return error(ID.Loc, "invalid empty array initializer"); - V = UndefValue::get(Ty); - return false; - case ValID::t_Zero: - // FIXME: LabelTy should not be a first-class type. - if (!Ty->isFirstClassType() || Ty->isLabelTy()) + V = UndefValue::get(Ty); + return false; + case ValID::t_Zero: + // FIXME: LabelTy should not be a first-class type. + if (!Ty->isFirstClassType() || Ty->isLabelTy()) return error(ID.Loc, "invalid type for null constant"); - V = Constant::getNullValue(Ty); - return false; - case ValID::t_None: - if (!Ty->isTokenTy()) + V = Constant::getNullValue(Ty); + return false; + case ValID::t_None: + if (!Ty->isTokenTy()) return error(ID.Loc, "invalid type for none constant"); - V = Constant::getNullValue(Ty); - return false; + V = Constant::getNullValue(Ty); + return false; case ValID::t_Poison: // FIXME: LabelTy should not be a first-class type. if (!Ty->isFirstClassType() || Ty->isLabelTy()) return error(ID.Loc, "invalid type for poison constant"); V = PoisonValue::get(Ty); return false; - case ValID::t_Constant: - if (ID.ConstantVal->getType() != Ty) + case ValID::t_Constant: + if (ID.ConstantVal->getType() != Ty) return error(ID.Loc, "constant expression type mismatch"); - V = ID.ConstantVal; - return false; - case ValID::t_ConstantStruct: - case ValID::t_PackedConstantStruct: - if (StructType *ST = dyn_cast<StructType>(Ty)) { - if (ST->getNumElements() != ID.UIntVal) + V = ID.ConstantVal; + return false; + case ValID::t_ConstantStruct: + case ValID::t_PackedConstantStruct: + if (StructType *ST = dyn_cast<StructType>(Ty)) { + if (ST->getNumElements() != ID.UIntVal) return error(ID.Loc, - "initializer with struct type has wrong # elements"); - if (ST->isPacked() != (ID.Kind == ValID::t_PackedConstantStruct)) + "initializer with struct type has wrong # elements"); + if (ST->isPacked() != (ID.Kind == ValID::t_PackedConstantStruct)) return error(ID.Loc, "packed'ness of initializer and type don't match"); - - // Verify that the elements are compatible with the structtype. - for (unsigned i = 0, e = ID.UIntVal; i != e; ++i) - if (ID.ConstantStructElts[i]->getType() != ST->getElementType(i)) + + // Verify that the elements are compatible with the structtype. + for (unsigned i = 0, e = ID.UIntVal; i != e; ++i) + if (ID.ConstantStructElts[i]->getType() != ST->getElementType(i)) return error( ID.Loc, "element " + Twine(i) + " of struct initializer doesn't match struct element type"); - - V = ConstantStruct::get( - ST, makeArrayRef(ID.ConstantStructElts.get(), ID.UIntVal)); - } else + + V = ConstantStruct::get( + ST, makeArrayRef(ID.ConstantStructElts.get(), ID.UIntVal)); + } else return error(ID.Loc, "constant expression type mismatch"); - return false; - } - llvm_unreachable("Invalid ValID"); -} - -bool LLParser::parseConstantValue(Type *Ty, Constant *&C) { - C = nullptr; - ValID ID; - auto Loc = Lex.getLoc(); + return false; + } + llvm_unreachable("Invalid ValID"); +} + +bool LLParser::parseConstantValue(Type *Ty, Constant *&C) { + C = nullptr; + ValID ID; + auto Loc = Lex.getLoc(); if (parseValID(ID, /*PFS=*/nullptr)) - return true; - switch (ID.Kind) { - case ValID::t_APSInt: - case ValID::t_APFloat: - case ValID::t_Undef: - case ValID::t_Constant: - case ValID::t_ConstantStruct: - case ValID::t_PackedConstantStruct: { - Value *V; + return true; + switch (ID.Kind) { + case ValID::t_APSInt: + case ValID::t_APFloat: + case ValID::t_Undef: + case ValID::t_Constant: + case ValID::t_ConstantStruct: + case ValID::t_PackedConstantStruct: { + Value *V; if (convertValIDToValue(Ty, ID, V, /*PFS=*/nullptr, /*IsCall=*/false)) - return true; - assert(isa<Constant>(V) && "Expected a constant value"); - C = cast<Constant>(V); - return false; - } - case ValID::t_Null: - C = Constant::getNullValue(Ty); - return false; - default: + return true; + assert(isa<Constant>(V) && "Expected a constant value"); + C = cast<Constant>(V); + return false; + } + case ValID::t_Null: + C = Constant::getNullValue(Ty); + return false; + default: return error(Loc, "expected a constant value"); - } -} - + } +} + bool LLParser::parseValue(Type *Ty, Value *&V, PerFunctionState *PFS) { - V = nullptr; - ValID ID; + V = nullptr; + ValID ID; return parseValID(ID, PFS) || convertValIDToValue(Ty, ID, V, PFS, /*IsCall=*/false); -} - +} + bool LLParser::parseTypeAndValue(Value *&V, PerFunctionState *PFS) { - Type *Ty = nullptr; + Type *Ty = nullptr; return parseType(Ty) || parseValue(Ty, V, PFS); -} - +} + bool LLParser::parseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc, - PerFunctionState &PFS) { - Value *V; - Loc = Lex.getLoc(); + PerFunctionState &PFS) { + Value *V; + Loc = Lex.getLoc(); if (parseTypeAndValue(V, PFS)) return true; - if (!isa<BasicBlock>(V)) + if (!isa<BasicBlock>(V)) return error(Loc, "expected a basic block"); - BB = cast<BasicBlock>(V); - return false; -} - -/// FunctionHeader -/// ::= OptionalLinkage OptionalPreemptionSpecifier OptionalVisibility -/// OptionalCallingConv OptRetAttrs OptUnnamedAddr Type GlobalName -/// '(' ArgList ')' OptAddrSpace OptFuncAttrs OptSection OptionalAlign -/// OptGC OptionalPrefix OptionalPrologue OptPersonalityFn + BB = cast<BasicBlock>(V); + return false; +} + +/// FunctionHeader +/// ::= OptionalLinkage OptionalPreemptionSpecifier OptionalVisibility +/// OptionalCallingConv OptRetAttrs OptUnnamedAddr Type GlobalName +/// '(' ArgList ')' OptAddrSpace OptFuncAttrs OptSection OptionalAlign +/// OptGC OptionalPrefix OptionalPrologue OptPersonalityFn bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine) { // parse the linkage. - LocTy LinkageLoc = Lex.getLoc(); - unsigned Linkage; - unsigned Visibility; - unsigned DLLStorageClass; - bool DSOLocal; - AttrBuilder RetAttrs; - unsigned CC; - bool HasLinkage; - Type *RetType = nullptr; - LocTy RetTypeLoc = Lex.getLoc(); + LocTy LinkageLoc = Lex.getLoc(); + unsigned Linkage; + unsigned Visibility; + unsigned DLLStorageClass; + bool DSOLocal; + AttrBuilder RetAttrs; + unsigned CC; + bool HasLinkage; + Type *RetType = nullptr; + LocTy RetTypeLoc = Lex.getLoc(); if (parseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass, - DSOLocal) || + DSOLocal) || parseOptionalCallingConv(CC) || parseOptionalReturnAttrs(RetAttrs) || parseType(RetType, RetTypeLoc, true /*void allowed*/)) - return true; - - // Verify that the linkage is ok. - switch ((GlobalValue::LinkageTypes)Linkage) { - case GlobalValue::ExternalLinkage: - break; // always ok. - case GlobalValue::ExternalWeakLinkage: + return true; + + // Verify that the linkage is ok. + switch ((GlobalValue::LinkageTypes)Linkage) { + case GlobalValue::ExternalLinkage: + break; // always ok. + case GlobalValue::ExternalWeakLinkage: if (IsDefine) return error(LinkageLoc, "invalid linkage for function definition"); - break; - case GlobalValue::PrivateLinkage: - case GlobalValue::InternalLinkage: - case GlobalValue::AvailableExternallyLinkage: - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: + break; + case GlobalValue::PrivateLinkage: + case GlobalValue::InternalLinkage: + case GlobalValue::AvailableExternallyLinkage: + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: if (!IsDefine) return error(LinkageLoc, "invalid linkage for function declaration"); - break; - case GlobalValue::AppendingLinkage: - case GlobalValue::CommonLinkage: + break; + case GlobalValue::AppendingLinkage: + case GlobalValue::CommonLinkage: return error(LinkageLoc, "invalid function linkage type"); - } - - if (!isValidVisibilityForLinkage(Visibility, Linkage)) + } + + if (!isValidVisibilityForLinkage(Visibility, Linkage)) return error(LinkageLoc, - "symbol with local linkage must have default visibility"); - - if (!FunctionType::isValidReturnType(RetType)) + "symbol with local linkage must have default visibility"); + + if (!FunctionType::isValidReturnType(RetType)) return error(RetTypeLoc, "invalid function return type"); - - LocTy NameLoc = Lex.getLoc(); - - std::string FunctionName; - if (Lex.getKind() == lltok::GlobalVar) { - FunctionName = Lex.getStrVal(); - } else if (Lex.getKind() == lltok::GlobalID) { // @42 is ok. - unsigned NameID = Lex.getUIntVal(); - - if (NameID != NumberedVals.size()) + + LocTy NameLoc = Lex.getLoc(); + + std::string FunctionName; + if (Lex.getKind() == lltok::GlobalVar) { + FunctionName = Lex.getStrVal(); + } else if (Lex.getKind() == lltok::GlobalID) { // @42 is ok. + unsigned NameID = Lex.getUIntVal(); + + if (NameID != NumberedVals.size()) return tokError("function expected to be numbered '%" + - Twine(NumberedVals.size()) + "'"); - } else { + Twine(NumberedVals.size()) + "'"); + } else { return tokError("expected function name"); - } - - Lex.Lex(); - - if (Lex.getKind() != lltok::lparen) + } + + Lex.Lex(); + + if (Lex.getKind() != lltok::lparen) return tokError("expected '(' in function argument list"); - - SmallVector<ArgInfo, 8> ArgList; + + SmallVector<ArgInfo, 8> ArgList; bool IsVarArg; - AttrBuilder FuncAttrs; - std::vector<unsigned> FwdRefAttrGrps; - LocTy BuiltinLoc; - std::string Section; - std::string Partition; - MaybeAlign Alignment; - std::string GC; - GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None; - unsigned AddrSpace = 0; - Constant *Prefix = nullptr; - Constant *Prologue = nullptr; - Constant *PersonalityFn = nullptr; - Comdat *C; - + AttrBuilder FuncAttrs; + std::vector<unsigned> FwdRefAttrGrps; + LocTy BuiltinLoc; + std::string Section; + std::string Partition; + MaybeAlign Alignment; + std::string GC; + GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None; + unsigned AddrSpace = 0; + Constant *Prefix = nullptr; + Constant *Prologue = nullptr; + Constant *PersonalityFn = nullptr; + Comdat *C; + if (parseArgumentList(ArgList, IsVarArg) || parseOptionalUnnamedAddr(UnnamedAddr) || parseOptionalProgramAddrSpace(AddrSpace) || parseFnAttributeValuePairs(FuncAttrs, FwdRefAttrGrps, false, - BuiltinLoc) || + BuiltinLoc) || (EatIfPresent(lltok::kw_section) && parseStringConstant(Section)) || (EatIfPresent(lltok::kw_partition) && parseStringConstant(Partition)) || - parseOptionalComdat(FunctionName, C) || + parseOptionalComdat(FunctionName, C) || parseOptionalAlignment(Alignment) || (EatIfPresent(lltok::kw_gc) && parseStringConstant(GC)) || (EatIfPresent(lltok::kw_prefix) && parseGlobalTypeAndValue(Prefix)) || (EatIfPresent(lltok::kw_prologue) && parseGlobalTypeAndValue(Prologue)) || - (EatIfPresent(lltok::kw_personality) && + (EatIfPresent(lltok::kw_personality) && parseGlobalTypeAndValue(PersonalityFn))) - return true; - - if (FuncAttrs.contains(Attribute::Builtin)) + return true; + + if (FuncAttrs.contains(Attribute::Builtin)) return error(BuiltinLoc, "'builtin' attribute not valid on function"); - - // If the alignment was parsed as an attribute, move to the alignment field. - if (FuncAttrs.hasAlignmentAttr()) { - Alignment = FuncAttrs.getAlignment(); - FuncAttrs.removeAttribute(Attribute::Alignment); - } - - // Okay, if we got here, the function is syntactically valid. Convert types - // and do semantic checks. - std::vector<Type*> ParamTypeList; - SmallVector<AttributeSet, 8> Attrs; - - for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { - ParamTypeList.push_back(ArgList[i].Ty); - Attrs.push_back(ArgList[i].Attrs); - } - - AttributeList PAL = - AttributeList::get(Context, AttributeSet::get(Context, FuncAttrs), - AttributeSet::get(Context, RetAttrs), Attrs); - - if (PAL.hasAttribute(1, Attribute::StructRet) && !RetType->isVoidTy()) + + // If the alignment was parsed as an attribute, move to the alignment field. + if (FuncAttrs.hasAlignmentAttr()) { + Alignment = FuncAttrs.getAlignment(); + FuncAttrs.removeAttribute(Attribute::Alignment); + } + + // Okay, if we got here, the function is syntactically valid. Convert types + // and do semantic checks. + std::vector<Type*> ParamTypeList; + SmallVector<AttributeSet, 8> Attrs; + + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { + ParamTypeList.push_back(ArgList[i].Ty); + Attrs.push_back(ArgList[i].Attrs); + } + + AttributeList PAL = + AttributeList::get(Context, AttributeSet::get(Context, FuncAttrs), + AttributeSet::get(Context, RetAttrs), Attrs); + + if (PAL.hasAttribute(1, Attribute::StructRet) && !RetType->isVoidTy()) return error(RetTypeLoc, "functions with 'sret' argument must return void"); - + FunctionType *FT = FunctionType::get(RetType, ParamTypeList, IsVarArg); - PointerType *PFT = PointerType::get(FT, AddrSpace); - - Fn = nullptr; - if (!FunctionName.empty()) { - // If this was a definition of a forward reference, remove the definition - // from the forward reference table and fill in the forward ref. - auto FRVI = ForwardRefVals.find(FunctionName); - if (FRVI != ForwardRefVals.end()) { - Fn = M->getFunction(FunctionName); - if (!Fn) + PointerType *PFT = PointerType::get(FT, AddrSpace); + + Fn = nullptr; + if (!FunctionName.empty()) { + // If this was a definition of a forward reference, remove the definition + // from the forward reference table and fill in the forward ref. + auto FRVI = ForwardRefVals.find(FunctionName); + if (FRVI != ForwardRefVals.end()) { + Fn = M->getFunction(FunctionName); + if (!Fn) return error(FRVI->second.second, "invalid forward reference to " "function as global value!"); - if (Fn->getType() != PFT) + if (Fn->getType() != PFT) return error(FRVI->second.second, "invalid forward reference to " "function '" + @@ -5787,260 +5787,260 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine) { "expected '" + getTypeString(PFT) + "' but was '" + getTypeString(Fn->getType()) + "'"); - ForwardRefVals.erase(FRVI); - } else if ((Fn = M->getFunction(FunctionName))) { - // Reject redefinitions. + ForwardRefVals.erase(FRVI); + } else if ((Fn = M->getFunction(FunctionName))) { + // Reject redefinitions. return error(NameLoc, "invalid redefinition of function '" + FunctionName + "'"); - } else if (M->getNamedValue(FunctionName)) { + } else if (M->getNamedValue(FunctionName)) { return error(NameLoc, "redefinition of function '@" + FunctionName + "'"); - } - - } else { - // If this is a definition of a forward referenced function, make sure the - // types agree. - auto I = ForwardRefValIDs.find(NumberedVals.size()); - if (I != ForwardRefValIDs.end()) { - Fn = cast<Function>(I->second.first); - if (Fn->getType() != PFT) + } + + } else { + // If this is a definition of a forward referenced function, make sure the + // types agree. + auto I = ForwardRefValIDs.find(NumberedVals.size()); + if (I != ForwardRefValIDs.end()) { + Fn = cast<Function>(I->second.first); + if (Fn->getType() != PFT) return error(NameLoc, "type of definition and forward reference of '@" + Twine(NumberedVals.size()) + "' disagree: " "expected '" + getTypeString(PFT) + "' but was '" + getTypeString(Fn->getType()) + "'"); - ForwardRefValIDs.erase(I); - } - } - - if (!Fn) - Fn = Function::Create(FT, GlobalValue::ExternalLinkage, AddrSpace, - FunctionName, M); - else // Move the forward-reference to the correct spot in the module. - M->getFunctionList().splice(M->end(), M->getFunctionList(), Fn); - - assert(Fn->getAddressSpace() == AddrSpace && "Created function in wrong AS"); - - if (FunctionName.empty()) - NumberedVals.push_back(Fn); - - Fn->setLinkage((GlobalValue::LinkageTypes)Linkage); - maybeSetDSOLocal(DSOLocal, *Fn); - Fn->setVisibility((GlobalValue::VisibilityTypes)Visibility); - Fn->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); - Fn->setCallingConv(CC); - Fn->setAttributes(PAL); - Fn->setUnnamedAddr(UnnamedAddr); - Fn->setAlignment(MaybeAlign(Alignment)); - Fn->setSection(Section); - Fn->setPartition(Partition); - Fn->setComdat(C); - Fn->setPersonalityFn(PersonalityFn); - if (!GC.empty()) Fn->setGC(GC); - Fn->setPrefixData(Prefix); - Fn->setPrologueData(Prologue); - ForwardRefAttrGroups[Fn] = FwdRefAttrGrps; - - // Add all of the arguments we parsed to the function. - Function::arg_iterator ArgIt = Fn->arg_begin(); - for (unsigned i = 0, e = ArgList.size(); i != e; ++i, ++ArgIt) { - // If the argument has a name, insert it into the argument symbol table. - if (ArgList[i].Name.empty()) continue; - - // Set the name, if it conflicted, it will be auto-renamed. - ArgIt->setName(ArgList[i].Name); - - if (ArgIt->getName() != ArgList[i].Name) + ForwardRefValIDs.erase(I); + } + } + + if (!Fn) + Fn = Function::Create(FT, GlobalValue::ExternalLinkage, AddrSpace, + FunctionName, M); + else // Move the forward-reference to the correct spot in the module. + M->getFunctionList().splice(M->end(), M->getFunctionList(), Fn); + + assert(Fn->getAddressSpace() == AddrSpace && "Created function in wrong AS"); + + if (FunctionName.empty()) + NumberedVals.push_back(Fn); + + Fn->setLinkage((GlobalValue::LinkageTypes)Linkage); + maybeSetDSOLocal(DSOLocal, *Fn); + Fn->setVisibility((GlobalValue::VisibilityTypes)Visibility); + Fn->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); + Fn->setCallingConv(CC); + Fn->setAttributes(PAL); + Fn->setUnnamedAddr(UnnamedAddr); + Fn->setAlignment(MaybeAlign(Alignment)); + Fn->setSection(Section); + Fn->setPartition(Partition); + Fn->setComdat(C); + Fn->setPersonalityFn(PersonalityFn); + if (!GC.empty()) Fn->setGC(GC); + Fn->setPrefixData(Prefix); + Fn->setPrologueData(Prologue); + ForwardRefAttrGroups[Fn] = FwdRefAttrGrps; + + // Add all of the arguments we parsed to the function. + Function::arg_iterator ArgIt = Fn->arg_begin(); + for (unsigned i = 0, e = ArgList.size(); i != e; ++i, ++ArgIt) { + // If the argument has a name, insert it into the argument symbol table. + if (ArgList[i].Name.empty()) continue; + + // Set the name, if it conflicted, it will be auto-renamed. + ArgIt->setName(ArgList[i].Name); + + if (ArgIt->getName() != ArgList[i].Name) return error(ArgList[i].Loc, "redefinition of argument '%" + ArgList[i].Name + "'"); - } - + } + if (IsDefine) - return false; - - // Check the declaration has no block address forward references. - ValID ID; - if (FunctionName.empty()) { - ID.Kind = ValID::t_GlobalID; - ID.UIntVal = NumberedVals.size() - 1; - } else { - ID.Kind = ValID::t_GlobalName; - ID.StrVal = FunctionName; - } - auto Blocks = ForwardRefBlockAddresses.find(ID); - if (Blocks != ForwardRefBlockAddresses.end()) + return false; + + // Check the declaration has no block address forward references. + ValID ID; + if (FunctionName.empty()) { + ID.Kind = ValID::t_GlobalID; + ID.UIntVal = NumberedVals.size() - 1; + } else { + ID.Kind = ValID::t_GlobalName; + ID.StrVal = FunctionName; + } + auto Blocks = ForwardRefBlockAddresses.find(ID); + if (Blocks != ForwardRefBlockAddresses.end()) return error(Blocks->first.Loc, - "cannot take blockaddress inside a declaration"); - return false; -} - -bool LLParser::PerFunctionState::resolveForwardRefBlockAddresses() { - ValID ID; - if (FunctionNumber == -1) { - ID.Kind = ValID::t_GlobalName; - ID.StrVal = std::string(F.getName()); - } else { - ID.Kind = ValID::t_GlobalID; - ID.UIntVal = FunctionNumber; - } - - auto Blocks = P.ForwardRefBlockAddresses.find(ID); - if (Blocks == P.ForwardRefBlockAddresses.end()) - return false; - - for (const auto &I : Blocks->second) { - const ValID &BBID = I.first; - GlobalValue *GV = I.second; - - assert((BBID.Kind == ValID::t_LocalID || BBID.Kind == ValID::t_LocalName) && - "Expected local id or name"); - BasicBlock *BB; - if (BBID.Kind == ValID::t_LocalName) + "cannot take blockaddress inside a declaration"); + return false; +} + +bool LLParser::PerFunctionState::resolveForwardRefBlockAddresses() { + ValID ID; + if (FunctionNumber == -1) { + ID.Kind = ValID::t_GlobalName; + ID.StrVal = std::string(F.getName()); + } else { + ID.Kind = ValID::t_GlobalID; + ID.UIntVal = FunctionNumber; + } + + auto Blocks = P.ForwardRefBlockAddresses.find(ID); + if (Blocks == P.ForwardRefBlockAddresses.end()) + return false; + + for (const auto &I : Blocks->second) { + const ValID &BBID = I.first; + GlobalValue *GV = I.second; + + assert((BBID.Kind == ValID::t_LocalID || BBID.Kind == ValID::t_LocalName) && + "Expected local id or name"); + BasicBlock *BB; + if (BBID.Kind == ValID::t_LocalName) BB = getBB(BBID.StrVal, BBID.Loc); - else + else BB = getBB(BBID.UIntVal, BBID.Loc); - if (!BB) + if (!BB) return P.error(BBID.Loc, "referenced value is not a basic block"); - - GV->replaceAllUsesWith(BlockAddress::get(&F, BB)); - GV->eraseFromParent(); - } - - P.ForwardRefBlockAddresses.erase(Blocks); - return false; -} - + + GV->replaceAllUsesWith(BlockAddress::get(&F, BB)); + GV->eraseFromParent(); + } + + P.ForwardRefBlockAddresses.erase(Blocks); + return false; +} + /// parseFunctionBody -/// ::= '{' BasicBlock+ UseListOrderDirective* '}' +/// ::= '{' BasicBlock+ UseListOrderDirective* '}' bool LLParser::parseFunctionBody(Function &Fn) { - if (Lex.getKind() != lltok::lbrace) + if (Lex.getKind() != lltok::lbrace) return tokError("expected '{' in function body"); - Lex.Lex(); // eat the {. - - int FunctionNumber = -1; - if (!Fn.hasName()) FunctionNumber = NumberedVals.size()-1; - - PerFunctionState PFS(*this, Fn, FunctionNumber); - - // Resolve block addresses and allow basic blocks to be forward-declared - // within this function. - if (PFS.resolveForwardRefBlockAddresses()) - return true; - SaveAndRestore<PerFunctionState *> ScopeExit(BlockAddressPFS, &PFS); - - // We need at least one basic block. - if (Lex.getKind() == lltok::rbrace || Lex.getKind() == lltok::kw_uselistorder) + Lex.Lex(); // eat the {. + + int FunctionNumber = -1; + if (!Fn.hasName()) FunctionNumber = NumberedVals.size()-1; + + PerFunctionState PFS(*this, Fn, FunctionNumber); + + // Resolve block addresses and allow basic blocks to be forward-declared + // within this function. + if (PFS.resolveForwardRefBlockAddresses()) + return true; + SaveAndRestore<PerFunctionState *> ScopeExit(BlockAddressPFS, &PFS); + + // We need at least one basic block. + if (Lex.getKind() == lltok::rbrace || Lex.getKind() == lltok::kw_uselistorder) return tokError("function body requires at least one basic block"); - - while (Lex.getKind() != lltok::rbrace && - Lex.getKind() != lltok::kw_uselistorder) + + while (Lex.getKind() != lltok::rbrace && + Lex.getKind() != lltok::kw_uselistorder) if (parseBasicBlock(PFS)) return true; - - while (Lex.getKind() != lltok::rbrace) + + while (Lex.getKind() != lltok::rbrace) if (parseUseListOrder(&PFS)) - return true; - - // Eat the }. - Lex.Lex(); - - // Verify function is ok. + return true; + + // Eat the }. + Lex.Lex(); + + // Verify function is ok. return PFS.finishFunction(); -} - +} + /// parseBasicBlock -/// ::= (LabelStr|LabelID)? Instruction* +/// ::= (LabelStr|LabelID)? Instruction* bool LLParser::parseBasicBlock(PerFunctionState &PFS) { - // If this basic block starts out with a name, remember it. - std::string Name; - int NameID = -1; - LocTy NameLoc = Lex.getLoc(); - if (Lex.getKind() == lltok::LabelStr) { - Name = Lex.getStrVal(); - Lex.Lex(); - } else if (Lex.getKind() == lltok::LabelID) { - NameID = Lex.getUIntVal(); - Lex.Lex(); - } - + // If this basic block starts out with a name, remember it. + std::string Name; + int NameID = -1; + LocTy NameLoc = Lex.getLoc(); + if (Lex.getKind() == lltok::LabelStr) { + Name = Lex.getStrVal(); + Lex.Lex(); + } else if (Lex.getKind() == lltok::LabelID) { + NameID = Lex.getUIntVal(); + Lex.Lex(); + } + BasicBlock *BB = PFS.defineBB(Name, NameID, NameLoc); - if (!BB) - return true; - - std::string NameStr; - + if (!BB) + return true; + + std::string NameStr; + // parse the instructions in this block until we get a terminator. - Instruction *Inst; - do { - // This instruction may have three possibilities for a name: a) none - // specified, b) name specified "%foo =", c) number specified: "%4 =". - LocTy NameLoc = Lex.getLoc(); - int NameID = -1; - NameStr = ""; - - if (Lex.getKind() == lltok::LocalVarID) { - NameID = Lex.getUIntVal(); - Lex.Lex(); + Instruction *Inst; + do { + // This instruction may have three possibilities for a name: a) none + // specified, b) name specified "%foo =", c) number specified: "%4 =". + LocTy NameLoc = Lex.getLoc(); + int NameID = -1; + NameStr = ""; + + if (Lex.getKind() == lltok::LocalVarID) { + NameID = Lex.getUIntVal(); + Lex.Lex(); if (parseToken(lltok::equal, "expected '=' after instruction id")) - return true; - } else if (Lex.getKind() == lltok::LocalVar) { - NameStr = Lex.getStrVal(); - Lex.Lex(); + return true; + } else if (Lex.getKind() == lltok::LocalVar) { + NameStr = Lex.getStrVal(); + Lex.Lex(); if (parseToken(lltok::equal, "expected '=' after instruction name")) - return true; - } - + return true; + } + switch (parseInstruction(Inst, BB, PFS)) { default: llvm_unreachable("Unknown parseInstruction result!"); - case InstError: return true; - case InstNormal: - BB->getInstList().push_back(Inst); - - // With a normal result, we check to see if the instruction is followed by - // a comma and metadata. - if (EatIfPresent(lltok::comma)) + case InstError: return true; + case InstNormal: + BB->getInstList().push_back(Inst); + + // With a normal result, we check to see if the instruction is followed by + // a comma and metadata. + if (EatIfPresent(lltok::comma)) if (parseInstructionMetadata(*Inst)) - return true; - break; - case InstExtraComma: - BB->getInstList().push_back(Inst); - - // If the instruction parser ate an extra comma at the end of it, it - // *must* be followed by metadata. + return true; + break; + case InstExtraComma: + BB->getInstList().push_back(Inst); + + // If the instruction parser ate an extra comma at the end of it, it + // *must* be followed by metadata. if (parseInstructionMetadata(*Inst)) - return true; - break; - } - - // Set the name on the instruction. + return true; + break; + } + + // Set the name on the instruction. if (PFS.setInstName(NameID, NameStr, NameLoc, Inst)) return true; - } while (!Inst->isTerminator()); - - return false; -} - -//===----------------------------------------------------------------------===// -// Instruction Parsing. -//===----------------------------------------------------------------------===// - + } while (!Inst->isTerminator()); + + return false; +} + +//===----------------------------------------------------------------------===// +// Instruction Parsing. +//===----------------------------------------------------------------------===// + /// parseInstruction - parse one of the many different instructions. -/// +/// int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB, - PerFunctionState &PFS) { - lltok::Kind Token = Lex.getKind(); - if (Token == lltok::Eof) + PerFunctionState &PFS) { + lltok::Kind Token = Lex.getKind(); + if (Token == lltok::Eof) return tokError("found end of file when expecting more instructions"); - LocTy Loc = Lex.getLoc(); - unsigned KeywordVal = Lex.getUIntVal(); - Lex.Lex(); // Eat the keyword. - - switch (Token) { + LocTy Loc = Lex.getLoc(); + unsigned KeywordVal = Lex.getUIntVal(); + Lex.Lex(); // Eat the keyword. + + switch (Token) { default: return error(Loc, "expected instruction opcode"); - // Terminator Instructions. - case lltok::kw_unreachable: Inst = new UnreachableInst(Context); return false; + // Terminator Instructions. + case lltok::kw_unreachable: Inst = new UnreachableInst(Context); return false; case lltok::kw_ret: return parseRet(Inst, BB, PFS); case lltok::kw_br: @@ -6065,107 +6065,107 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB, return parseCleanupPad(Inst, PFS); case lltok::kw_callbr: return parseCallBr(Inst, PFS); - // Unary Operators. - case lltok::kw_fneg: { - FastMathFlags FMF = EatFastMathFlagsIfPresent(); + // Unary Operators. + case lltok::kw_fneg: { + FastMathFlags FMF = EatFastMathFlagsIfPresent(); int Res = parseUnaryOp(Inst, PFS, KeywordVal, /*IsFP*/ true); - if (Res != 0) - return Res; - if (FMF.any()) - Inst->setFastMathFlags(FMF); - return false; - } - // Binary Operators. - case lltok::kw_add: - case lltok::kw_sub: - case lltok::kw_mul: - case lltok::kw_shl: { - bool NUW = EatIfPresent(lltok::kw_nuw); - bool NSW = EatIfPresent(lltok::kw_nsw); - if (!NUW) NUW = EatIfPresent(lltok::kw_nuw); - + if (Res != 0) + return Res; + if (FMF.any()) + Inst->setFastMathFlags(FMF); + return false; + } + // Binary Operators. + case lltok::kw_add: + case lltok::kw_sub: + case lltok::kw_mul: + case lltok::kw_shl: { + bool NUW = EatIfPresent(lltok::kw_nuw); + bool NSW = EatIfPresent(lltok::kw_nsw); + if (!NUW) NUW = EatIfPresent(lltok::kw_nuw); + if (parseArithmetic(Inst, PFS, KeywordVal, /*IsFP*/ false)) return true; - - if (NUW) cast<BinaryOperator>(Inst)->setHasNoUnsignedWrap(true); - if (NSW) cast<BinaryOperator>(Inst)->setHasNoSignedWrap(true); - return false; - } - case lltok::kw_fadd: - case lltok::kw_fsub: - case lltok::kw_fmul: - case lltok::kw_fdiv: - case lltok::kw_frem: { - FastMathFlags FMF = EatFastMathFlagsIfPresent(); + + if (NUW) cast<BinaryOperator>(Inst)->setHasNoUnsignedWrap(true); + if (NSW) cast<BinaryOperator>(Inst)->setHasNoSignedWrap(true); + return false; + } + case lltok::kw_fadd: + case lltok::kw_fsub: + case lltok::kw_fmul: + case lltok::kw_fdiv: + case lltok::kw_frem: { + FastMathFlags FMF = EatFastMathFlagsIfPresent(); int Res = parseArithmetic(Inst, PFS, KeywordVal, /*IsFP*/ true); - if (Res != 0) - return Res; - if (FMF.any()) - Inst->setFastMathFlags(FMF); - return 0; - } - - case lltok::kw_sdiv: - case lltok::kw_udiv: - case lltok::kw_lshr: - case lltok::kw_ashr: { - bool Exact = EatIfPresent(lltok::kw_exact); - + if (Res != 0) + return Res; + if (FMF.any()) + Inst->setFastMathFlags(FMF); + return 0; + } + + case lltok::kw_sdiv: + case lltok::kw_udiv: + case lltok::kw_lshr: + case lltok::kw_ashr: { + bool Exact = EatIfPresent(lltok::kw_exact); + if (parseArithmetic(Inst, PFS, KeywordVal, /*IsFP*/ false)) return true; - if (Exact) cast<BinaryOperator>(Inst)->setIsExact(true); - return false; - } - - case lltok::kw_urem: + if (Exact) cast<BinaryOperator>(Inst)->setIsExact(true); + return false; + } + + case lltok::kw_urem: case lltok::kw_srem: return parseArithmetic(Inst, PFS, KeywordVal, /*IsFP*/ false); - case lltok::kw_and: - case lltok::kw_or: + case lltok::kw_and: + case lltok::kw_or: case lltok::kw_xor: return parseLogical(Inst, PFS, KeywordVal); case lltok::kw_icmp: return parseCompare(Inst, PFS, KeywordVal); - case lltok::kw_fcmp: { - FastMathFlags FMF = EatFastMathFlagsIfPresent(); + case lltok::kw_fcmp: { + FastMathFlags FMF = EatFastMathFlagsIfPresent(); int Res = parseCompare(Inst, PFS, KeywordVal); - if (Res != 0) - return Res; - if (FMF.any()) - Inst->setFastMathFlags(FMF); - return 0; - } - - // Casts. - case lltok::kw_trunc: - case lltok::kw_zext: - case lltok::kw_sext: - case lltok::kw_fptrunc: - case lltok::kw_fpext: - case lltok::kw_bitcast: - case lltok::kw_addrspacecast: - case lltok::kw_uitofp: - case lltok::kw_sitofp: - case lltok::kw_fptoui: - case lltok::kw_fptosi: - case lltok::kw_inttoptr: + if (Res != 0) + return Res; + if (FMF.any()) + Inst->setFastMathFlags(FMF); + return 0; + } + + // Casts. + case lltok::kw_trunc: + case lltok::kw_zext: + case lltok::kw_sext: + case lltok::kw_fptrunc: + case lltok::kw_fpext: + case lltok::kw_bitcast: + case lltok::kw_addrspacecast: + case lltok::kw_uitofp: + case lltok::kw_sitofp: + case lltok::kw_fptoui: + case lltok::kw_fptosi: + case lltok::kw_inttoptr: case lltok::kw_ptrtoint: return parseCast(Inst, PFS, KeywordVal); - // Other. - case lltok::kw_select: { - FastMathFlags FMF = EatFastMathFlagsIfPresent(); + // Other. + case lltok::kw_select: { + FastMathFlags FMF = EatFastMathFlagsIfPresent(); int Res = parseSelect(Inst, PFS); - if (Res != 0) - return Res; - if (FMF.any()) { - if (!isa<FPMathOperator>(Inst)) + if (Res != 0) + return Res; + if (FMF.any()) { + if (!isa<FPMathOperator>(Inst)) return error(Loc, "fast-math-flags specified for select without " - "floating-point scalar or vector return type"); - Inst->setFastMathFlags(FMF); - } - return 0; - } + "floating-point scalar or vector return type"); + Inst->setFastMathFlags(FMF); + } + return 0; + } case lltok::kw_va_arg: return parseVAArg(Inst, PFS); case lltok::kw_extractelement: @@ -6174,24 +6174,24 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB, return parseInsertElement(Inst, PFS); case lltok::kw_shufflevector: return parseShuffleVector(Inst, PFS); - case lltok::kw_phi: { - FastMathFlags FMF = EatFastMathFlagsIfPresent(); + case lltok::kw_phi: { + FastMathFlags FMF = EatFastMathFlagsIfPresent(); int Res = parsePHI(Inst, PFS); - if (Res != 0) - return Res; - if (FMF.any()) { - if (!isa<FPMathOperator>(Inst)) + if (Res != 0) + return Res; + if (FMF.any()) { + if (!isa<FPMathOperator>(Inst)) return error(Loc, "fast-math-flags specified for phi without " - "floating-point scalar or vector return type"); - Inst->setFastMathFlags(FMF); - } - return 0; - } + "floating-point scalar or vector return type"); + Inst->setFastMathFlags(FMF); + } + return 0; + } case lltok::kw_landingpad: return parseLandingPad(Inst, PFS); case lltok::kw_freeze: return parseFreeze(Inst, PFS); - // Call. + // Call. case lltok::kw_call: return parseCall(Inst, PFS, CallInst::TCK_None); case lltok::kw_tail: @@ -6200,7 +6200,7 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB, return parseCall(Inst, PFS, CallInst::TCK_MustTail); case lltok::kw_notail: return parseCall(Inst, PFS, CallInst::TCK_NoTail); - // Memory. + // Memory. case lltok::kw_alloca: return parseAlloc(Inst, PFS); case lltok::kw_load: @@ -6219,1235 +6219,1235 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB, return parseExtractValue(Inst, PFS); case lltok::kw_insertvalue: return parseInsertValue(Inst, PFS); - } -} - + } +} + /// parseCmpPredicate - parse an integer or fp predicate, based on Kind. bool LLParser::parseCmpPredicate(unsigned &P, unsigned Opc) { - if (Opc == Instruction::FCmp) { - switch (Lex.getKind()) { + if (Opc == Instruction::FCmp) { + switch (Lex.getKind()) { default: return tokError("expected fcmp predicate (e.g. 'oeq')"); - case lltok::kw_oeq: P = CmpInst::FCMP_OEQ; break; - case lltok::kw_one: P = CmpInst::FCMP_ONE; break; - case lltok::kw_olt: P = CmpInst::FCMP_OLT; break; - case lltok::kw_ogt: P = CmpInst::FCMP_OGT; break; - case lltok::kw_ole: P = CmpInst::FCMP_OLE; break; - case lltok::kw_oge: P = CmpInst::FCMP_OGE; break; - case lltok::kw_ord: P = CmpInst::FCMP_ORD; break; - case lltok::kw_uno: P = CmpInst::FCMP_UNO; break; - case lltok::kw_ueq: P = CmpInst::FCMP_UEQ; break; - case lltok::kw_une: P = CmpInst::FCMP_UNE; break; - case lltok::kw_ult: P = CmpInst::FCMP_ULT; break; - case lltok::kw_ugt: P = CmpInst::FCMP_UGT; break; - case lltok::kw_ule: P = CmpInst::FCMP_ULE; break; - case lltok::kw_uge: P = CmpInst::FCMP_UGE; break; - case lltok::kw_true: P = CmpInst::FCMP_TRUE; break; - case lltok::kw_false: P = CmpInst::FCMP_FALSE; break; - } - } else { - switch (Lex.getKind()) { + case lltok::kw_oeq: P = CmpInst::FCMP_OEQ; break; + case lltok::kw_one: P = CmpInst::FCMP_ONE; break; + case lltok::kw_olt: P = CmpInst::FCMP_OLT; break; + case lltok::kw_ogt: P = CmpInst::FCMP_OGT; break; + case lltok::kw_ole: P = CmpInst::FCMP_OLE; break; + case lltok::kw_oge: P = CmpInst::FCMP_OGE; break; + case lltok::kw_ord: P = CmpInst::FCMP_ORD; break; + case lltok::kw_uno: P = CmpInst::FCMP_UNO; break; + case lltok::kw_ueq: P = CmpInst::FCMP_UEQ; break; + case lltok::kw_une: P = CmpInst::FCMP_UNE; break; + case lltok::kw_ult: P = CmpInst::FCMP_ULT; break; + case lltok::kw_ugt: P = CmpInst::FCMP_UGT; break; + case lltok::kw_ule: P = CmpInst::FCMP_ULE; break; + case lltok::kw_uge: P = CmpInst::FCMP_UGE; break; + case lltok::kw_true: P = CmpInst::FCMP_TRUE; break; + case lltok::kw_false: P = CmpInst::FCMP_FALSE; break; + } + } else { + switch (Lex.getKind()) { default: return tokError("expected icmp predicate (e.g. 'eq')"); - case lltok::kw_eq: P = CmpInst::ICMP_EQ; break; - case lltok::kw_ne: P = CmpInst::ICMP_NE; break; - case lltok::kw_slt: P = CmpInst::ICMP_SLT; break; - case lltok::kw_sgt: P = CmpInst::ICMP_SGT; break; - case lltok::kw_sle: P = CmpInst::ICMP_SLE; break; - case lltok::kw_sge: P = CmpInst::ICMP_SGE; break; - case lltok::kw_ult: P = CmpInst::ICMP_ULT; break; - case lltok::kw_ugt: P = CmpInst::ICMP_UGT; break; - case lltok::kw_ule: P = CmpInst::ICMP_ULE; break; - case lltok::kw_uge: P = CmpInst::ICMP_UGE; break; - } - } - Lex.Lex(); - return false; -} - -//===----------------------------------------------------------------------===// -// Terminator Instructions. -//===----------------------------------------------------------------------===// - + case lltok::kw_eq: P = CmpInst::ICMP_EQ; break; + case lltok::kw_ne: P = CmpInst::ICMP_NE; break; + case lltok::kw_slt: P = CmpInst::ICMP_SLT; break; + case lltok::kw_sgt: P = CmpInst::ICMP_SGT; break; + case lltok::kw_sle: P = CmpInst::ICMP_SLE; break; + case lltok::kw_sge: P = CmpInst::ICMP_SGE; break; + case lltok::kw_ult: P = CmpInst::ICMP_ULT; break; + case lltok::kw_ugt: P = CmpInst::ICMP_UGT; break; + case lltok::kw_ule: P = CmpInst::ICMP_ULE; break; + case lltok::kw_uge: P = CmpInst::ICMP_UGE; break; + } + } + Lex.Lex(); + return false; +} + +//===----------------------------------------------------------------------===// +// Terminator Instructions. +//===----------------------------------------------------------------------===// + /// parseRet - parse a return instruction. -/// ::= 'ret' void (',' !dbg, !1)* -/// ::= 'ret' TypeAndValue (',' !dbg, !1)* +/// ::= 'ret' void (',' !dbg, !1)* +/// ::= 'ret' TypeAndValue (',' !dbg, !1)* bool LLParser::parseRet(Instruction *&Inst, BasicBlock *BB, - PerFunctionState &PFS) { - SMLoc TypeLoc = Lex.getLoc(); - Type *Ty = nullptr; + PerFunctionState &PFS) { + SMLoc TypeLoc = Lex.getLoc(); + Type *Ty = nullptr; if (parseType(Ty, true /*void allowed*/)) return true; - - Type *ResType = PFS.getFunction().getReturnType(); - - if (Ty->isVoidTy()) { - if (!ResType->isVoidTy()) + + Type *ResType = PFS.getFunction().getReturnType(); + + if (Ty->isVoidTy()) { + if (!ResType->isVoidTy()) return error(TypeLoc, "value doesn't match function result type '" + getTypeString(ResType) + "'"); - - Inst = ReturnInst::Create(Context); - return false; - } - - Value *RV; + + Inst = ReturnInst::Create(Context); + return false; + } + + Value *RV; if (parseValue(Ty, RV, PFS)) return true; - - if (ResType != RV->getType()) + + if (ResType != RV->getType()) return error(TypeLoc, "value doesn't match function result type '" + getTypeString(ResType) + "'"); - - Inst = ReturnInst::Create(Context, RV); - return false; -} - + + Inst = ReturnInst::Create(Context, RV); + return false; +} + /// parseBr -/// ::= 'br' TypeAndValue -/// ::= 'br' TypeAndValue ',' TypeAndValue ',' TypeAndValue +/// ::= 'br' TypeAndValue +/// ::= 'br' TypeAndValue ',' TypeAndValue ',' TypeAndValue bool LLParser::parseBr(Instruction *&Inst, PerFunctionState &PFS) { - LocTy Loc, Loc2; - Value *Op0; - BasicBlock *Op1, *Op2; + LocTy Loc, Loc2; + Value *Op0; + BasicBlock *Op1, *Op2; if (parseTypeAndValue(Op0, Loc, PFS)) return true; - - if (BasicBlock *BB = dyn_cast<BasicBlock>(Op0)) { - Inst = BranchInst::Create(BB); - return false; - } - - if (Op0->getType() != Type::getInt1Ty(Context)) + + if (BasicBlock *BB = dyn_cast<BasicBlock>(Op0)) { + Inst = BranchInst::Create(BB); + return false; + } + + if (Op0->getType() != Type::getInt1Ty(Context)) return error(Loc, "branch condition must have 'i1' type"); - + if (parseToken(lltok::comma, "expected ',' after branch condition") || parseTypeAndBasicBlock(Op1, Loc, PFS) || parseToken(lltok::comma, "expected ',' after true destination") || parseTypeAndBasicBlock(Op2, Loc2, PFS)) - return true; - - Inst = BranchInst::Create(Op1, Op2, Op0); - return false; -} - + return true; + + Inst = BranchInst::Create(Op1, Op2, Op0); + return false; +} + /// parseSwitch -/// Instruction -/// ::= 'switch' TypeAndValue ',' TypeAndValue '[' JumpTable ']' -/// JumpTable -/// ::= (TypeAndValue ',' TypeAndValue)* +/// Instruction +/// ::= 'switch' TypeAndValue ',' TypeAndValue '[' JumpTable ']' +/// JumpTable +/// ::= (TypeAndValue ',' TypeAndValue)* bool LLParser::parseSwitch(Instruction *&Inst, PerFunctionState &PFS) { - LocTy CondLoc, BBLoc; - Value *Cond; - BasicBlock *DefaultBB; + LocTy CondLoc, BBLoc; + Value *Cond; + BasicBlock *DefaultBB; if (parseTypeAndValue(Cond, CondLoc, PFS) || parseToken(lltok::comma, "expected ',' after switch condition") || parseTypeAndBasicBlock(DefaultBB, BBLoc, PFS) || parseToken(lltok::lsquare, "expected '[' with switch table")) - return true; - - if (!Cond->getType()->isIntegerTy()) + return true; + + if (!Cond->getType()->isIntegerTy()) return error(CondLoc, "switch condition must have integer type"); - + // parse the jump table pairs. - SmallPtrSet<Value*, 32> SeenCases; - SmallVector<std::pair<ConstantInt*, BasicBlock*>, 32> Table; - while (Lex.getKind() != lltok::rsquare) { - Value *Constant; - BasicBlock *DestBB; - + SmallPtrSet<Value*, 32> SeenCases; + SmallVector<std::pair<ConstantInt*, BasicBlock*>, 32> Table; + while (Lex.getKind() != lltok::rsquare) { + Value *Constant; + BasicBlock *DestBB; + if (parseTypeAndValue(Constant, CondLoc, PFS) || parseToken(lltok::comma, "expected ',' after case value") || parseTypeAndBasicBlock(DestBB, PFS)) - return true; - - if (!SeenCases.insert(Constant).second) + return true; + + if (!SeenCases.insert(Constant).second) return error(CondLoc, "duplicate case value in switch"); - if (!isa<ConstantInt>(Constant)) + if (!isa<ConstantInt>(Constant)) return error(CondLoc, "case value is not a constant integer"); - - Table.push_back(std::make_pair(cast<ConstantInt>(Constant), DestBB)); - } - - Lex.Lex(); // Eat the ']'. - - SwitchInst *SI = SwitchInst::Create(Cond, DefaultBB, Table.size()); - for (unsigned i = 0, e = Table.size(); i != e; ++i) - SI->addCase(Table[i].first, Table[i].second); - Inst = SI; - return false; -} - + + Table.push_back(std::make_pair(cast<ConstantInt>(Constant), DestBB)); + } + + Lex.Lex(); // Eat the ']'. + + SwitchInst *SI = SwitchInst::Create(Cond, DefaultBB, Table.size()); + for (unsigned i = 0, e = Table.size(); i != e; ++i) + SI->addCase(Table[i].first, Table[i].second); + Inst = SI; + return false; +} + /// parseIndirectBr -/// Instruction -/// ::= 'indirectbr' TypeAndValue ',' '[' LabelList ']' +/// Instruction +/// ::= 'indirectbr' TypeAndValue ',' '[' LabelList ']' bool LLParser::parseIndirectBr(Instruction *&Inst, PerFunctionState &PFS) { - LocTy AddrLoc; - Value *Address; + LocTy AddrLoc; + Value *Address; if (parseTypeAndValue(Address, AddrLoc, PFS) || parseToken(lltok::comma, "expected ',' after indirectbr address") || parseToken(lltok::lsquare, "expected '[' with indirectbr")) - return true; - - if (!Address->getType()->isPointerTy()) + return true; + + if (!Address->getType()->isPointerTy()) return error(AddrLoc, "indirectbr address must have pointer type"); - + // parse the destination list. - SmallVector<BasicBlock*, 16> DestList; - - if (Lex.getKind() != lltok::rsquare) { - BasicBlock *DestBB; + SmallVector<BasicBlock*, 16> DestList; + + if (Lex.getKind() != lltok::rsquare) { + BasicBlock *DestBB; if (parseTypeAndBasicBlock(DestBB, PFS)) - return true; - DestList.push_back(DestBB); - - while (EatIfPresent(lltok::comma)) { + return true; + DestList.push_back(DestBB); + + while (EatIfPresent(lltok::comma)) { if (parseTypeAndBasicBlock(DestBB, PFS)) - return true; - DestList.push_back(DestBB); - } - } - + return true; + DestList.push_back(DestBB); + } + } + if (parseToken(lltok::rsquare, "expected ']' at end of block list")) - return true; - - IndirectBrInst *IBI = IndirectBrInst::Create(Address, DestList.size()); - for (unsigned i = 0, e = DestList.size(); i != e; ++i) - IBI->addDestination(DestList[i]); - Inst = IBI; - return false; -} - + return true; + + IndirectBrInst *IBI = IndirectBrInst::Create(Address, DestList.size()); + for (unsigned i = 0, e = DestList.size(); i != e; ++i) + IBI->addDestination(DestList[i]); + Inst = IBI; + return false; +} + /// parseInvoke -/// ::= 'invoke' OptionalCallingConv OptionalAttrs Type Value ParamList -/// OptionalAttrs 'to' TypeAndValue 'unwind' TypeAndValue +/// ::= 'invoke' OptionalCallingConv OptionalAttrs Type Value ParamList +/// OptionalAttrs 'to' TypeAndValue 'unwind' TypeAndValue bool LLParser::parseInvoke(Instruction *&Inst, PerFunctionState &PFS) { - LocTy CallLoc = Lex.getLoc(); - AttrBuilder RetAttrs, FnAttrs; - std::vector<unsigned> FwdRefAttrGrps; - LocTy NoBuiltinLoc; - unsigned CC; - unsigned InvokeAddrSpace; - Type *RetType = nullptr; - LocTy RetTypeLoc; - ValID CalleeID; - SmallVector<ParamInfo, 16> ArgList; - SmallVector<OperandBundleDef, 2> BundleList; - - BasicBlock *NormalBB, *UnwindBB; + LocTy CallLoc = Lex.getLoc(); + AttrBuilder RetAttrs, FnAttrs; + std::vector<unsigned> FwdRefAttrGrps; + LocTy NoBuiltinLoc; + unsigned CC; + unsigned InvokeAddrSpace; + Type *RetType = nullptr; + LocTy RetTypeLoc; + ValID CalleeID; + SmallVector<ParamInfo, 16> ArgList; + SmallVector<OperandBundleDef, 2> BundleList; + + BasicBlock *NormalBB, *UnwindBB; if (parseOptionalCallingConv(CC) || parseOptionalReturnAttrs(RetAttrs) || parseOptionalProgramAddrSpace(InvokeAddrSpace) || parseType(RetType, RetTypeLoc, true /*void allowed*/) || parseValID(CalleeID) || parseParameterList(ArgList, PFS) || parseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false, - NoBuiltinLoc) || + NoBuiltinLoc) || parseOptionalOperandBundles(BundleList, PFS) || parseToken(lltok::kw_to, "expected 'to' in invoke") || parseTypeAndBasicBlock(NormalBB, PFS) || parseToken(lltok::kw_unwind, "expected 'unwind' in invoke") || parseTypeAndBasicBlock(UnwindBB, PFS)) - return true; - - // If RetType is a non-function pointer type, then this is the short syntax - // for the call, which means that RetType is just the return type. Infer the - // rest of the function argument types from the arguments that are present. - FunctionType *Ty = dyn_cast<FunctionType>(RetType); - if (!Ty) { - // Pull out the types of all of the arguments... - std::vector<Type*> ParamTypes; - for (unsigned i = 0, e = ArgList.size(); i != e; ++i) - ParamTypes.push_back(ArgList[i].V->getType()); - - if (!FunctionType::isValidReturnType(RetType)) + return true; + + // If RetType is a non-function pointer type, then this is the short syntax + // for the call, which means that RetType is just the return type. Infer the + // rest of the function argument types from the arguments that are present. + FunctionType *Ty = dyn_cast<FunctionType>(RetType); + if (!Ty) { + // Pull out the types of all of the arguments... + std::vector<Type*> ParamTypes; + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) + ParamTypes.push_back(ArgList[i].V->getType()); + + if (!FunctionType::isValidReturnType(RetType)) return error(RetTypeLoc, "Invalid result type for LLVM function"); - - Ty = FunctionType::get(RetType, ParamTypes, false); - } - - CalleeID.FTy = Ty; - - // Look up the callee. - Value *Callee; + + Ty = FunctionType::get(RetType, ParamTypes, false); + } + + CalleeID.FTy = Ty; + + // Look up the callee. + Value *Callee; if (convertValIDToValue(PointerType::get(Ty, InvokeAddrSpace), CalleeID, - Callee, &PFS, /*IsCall=*/true)) - return true; - - // Set up the Attribute for the function. - SmallVector<Value *, 8> Args; - SmallVector<AttributeSet, 8> ArgAttrs; - - // Loop through FunctionType's arguments and ensure they are specified - // correctly. Also, gather any parameter attributes. - FunctionType::param_iterator I = Ty->param_begin(); - FunctionType::param_iterator E = Ty->param_end(); - for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { - Type *ExpectedTy = nullptr; - if (I != E) { - ExpectedTy = *I++; - } else if (!Ty->isVarArg()) { + Callee, &PFS, /*IsCall=*/true)) + return true; + + // Set up the Attribute for the function. + SmallVector<Value *, 8> Args; + SmallVector<AttributeSet, 8> ArgAttrs; + + // Loop through FunctionType's arguments and ensure they are specified + // correctly. Also, gather any parameter attributes. + FunctionType::param_iterator I = Ty->param_begin(); + FunctionType::param_iterator E = Ty->param_end(); + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { + Type *ExpectedTy = nullptr; + if (I != E) { + ExpectedTy = *I++; + } else if (!Ty->isVarArg()) { return error(ArgList[i].Loc, "too many arguments specified"); - } - - if (ExpectedTy && ExpectedTy != ArgList[i].V->getType()) + } + + if (ExpectedTy && ExpectedTy != ArgList[i].V->getType()) return error(ArgList[i].Loc, "argument is not of expected type '" + getTypeString(ExpectedTy) + "'"); - Args.push_back(ArgList[i].V); - ArgAttrs.push_back(ArgList[i].Attrs); - } - - if (I != E) + Args.push_back(ArgList[i].V); + ArgAttrs.push_back(ArgList[i].Attrs); + } + + if (I != E) return error(CallLoc, "not enough parameters specified for call"); - - if (FnAttrs.hasAlignmentAttr()) + + if (FnAttrs.hasAlignmentAttr()) return error(CallLoc, "invoke instructions may not have an alignment"); - - // Finish off the Attribute and check them - AttributeList PAL = - AttributeList::get(Context, AttributeSet::get(Context, FnAttrs), - AttributeSet::get(Context, RetAttrs), ArgAttrs); - - InvokeInst *II = - InvokeInst::Create(Ty, Callee, NormalBB, UnwindBB, Args, BundleList); - II->setCallingConv(CC); - II->setAttributes(PAL); - ForwardRefAttrGroups[II] = FwdRefAttrGrps; - Inst = II; - return false; -} - + + // Finish off the Attribute and check them + AttributeList PAL = + AttributeList::get(Context, AttributeSet::get(Context, FnAttrs), + AttributeSet::get(Context, RetAttrs), ArgAttrs); + + InvokeInst *II = + InvokeInst::Create(Ty, Callee, NormalBB, UnwindBB, Args, BundleList); + II->setCallingConv(CC); + II->setAttributes(PAL); + ForwardRefAttrGroups[II] = FwdRefAttrGrps; + Inst = II; + return false; +} + /// parseResume -/// ::= 'resume' TypeAndValue +/// ::= 'resume' TypeAndValue bool LLParser::parseResume(Instruction *&Inst, PerFunctionState &PFS) { - Value *Exn; LocTy ExnLoc; + Value *Exn; LocTy ExnLoc; if (parseTypeAndValue(Exn, ExnLoc, PFS)) - return true; - - ResumeInst *RI = ResumeInst::Create(Exn); - Inst = RI; - return false; -} - + return true; + + ResumeInst *RI = ResumeInst::Create(Exn); + Inst = RI; + return false; +} + bool LLParser::parseExceptionArgs(SmallVectorImpl<Value *> &Args, - PerFunctionState &PFS) { + PerFunctionState &PFS) { if (parseToken(lltok::lsquare, "expected '[' in catchpad/cleanuppad")) - return true; - - while (Lex.getKind() != lltok::rsquare) { - // If this isn't the first argument, we need a comma. - if (!Args.empty() && + return true; + + while (Lex.getKind() != lltok::rsquare) { + // If this isn't the first argument, we need a comma. + if (!Args.empty() && parseToken(lltok::comma, "expected ',' in argument list")) - return true; - + return true; + // parse the argument. - LocTy ArgLoc; - Type *ArgTy = nullptr; + LocTy ArgLoc; + Type *ArgTy = nullptr; if (parseType(ArgTy, ArgLoc)) - return true; - - Value *V; - if (ArgTy->isMetadataTy()) { + return true; + + Value *V; + if (ArgTy->isMetadataTy()) { if (parseMetadataAsValue(V, PFS)) - return true; - } else { + return true; + } else { if (parseValue(ArgTy, V, PFS)) - return true; - } - Args.push_back(V); - } - - Lex.Lex(); // Lex the ']'. - return false; -} - + return true; + } + Args.push_back(V); + } + + Lex.Lex(); // Lex the ']'. + return false; +} + /// parseCleanupRet -/// ::= 'cleanupret' from Value unwind ('to' 'caller' | TypeAndValue) +/// ::= 'cleanupret' from Value unwind ('to' 'caller' | TypeAndValue) bool LLParser::parseCleanupRet(Instruction *&Inst, PerFunctionState &PFS) { - Value *CleanupPad = nullptr; - + Value *CleanupPad = nullptr; + if (parseToken(lltok::kw_from, "expected 'from' after cleanupret")) - return true; - + return true; + if (parseValue(Type::getTokenTy(Context), CleanupPad, PFS)) - return true; - + return true; + if (parseToken(lltok::kw_unwind, "expected 'unwind' in cleanupret")) - return true; - - BasicBlock *UnwindBB = nullptr; - if (Lex.getKind() == lltok::kw_to) { - Lex.Lex(); + return true; + + BasicBlock *UnwindBB = nullptr; + if (Lex.getKind() == lltok::kw_to) { + Lex.Lex(); if (parseToken(lltok::kw_caller, "expected 'caller' in cleanupret")) - return true; - } else { + return true; + } else { if (parseTypeAndBasicBlock(UnwindBB, PFS)) { - return true; - } - } - - Inst = CleanupReturnInst::Create(CleanupPad, UnwindBB); - return false; -} - + return true; + } + } + + Inst = CleanupReturnInst::Create(CleanupPad, UnwindBB); + return false; +} + /// parseCatchRet -/// ::= 'catchret' from Parent Value 'to' TypeAndValue +/// ::= 'catchret' from Parent Value 'to' TypeAndValue bool LLParser::parseCatchRet(Instruction *&Inst, PerFunctionState &PFS) { - Value *CatchPad = nullptr; - + Value *CatchPad = nullptr; + if (parseToken(lltok::kw_from, "expected 'from' after catchret")) - return true; - + return true; + if (parseValue(Type::getTokenTy(Context), CatchPad, PFS)) - return true; - - BasicBlock *BB; + return true; + + BasicBlock *BB; if (parseToken(lltok::kw_to, "expected 'to' in catchret") || parseTypeAndBasicBlock(BB, PFS)) return true; - - Inst = CatchReturnInst::Create(CatchPad, BB); - return false; -} - + + Inst = CatchReturnInst::Create(CatchPad, BB); + return false; +} + /// parseCatchSwitch -/// ::= 'catchswitch' within Parent +/// ::= 'catchswitch' within Parent bool LLParser::parseCatchSwitch(Instruction *&Inst, PerFunctionState &PFS) { - Value *ParentPad; - + Value *ParentPad; + if (parseToken(lltok::kw_within, "expected 'within' after catchswitch")) - return true; - - if (Lex.getKind() != lltok::kw_none && Lex.getKind() != lltok::LocalVar && - Lex.getKind() != lltok::LocalVarID) + return true; + + if (Lex.getKind() != lltok::kw_none && Lex.getKind() != lltok::LocalVar && + Lex.getKind() != lltok::LocalVarID) return tokError("expected scope value for catchswitch"); - + if (parseValue(Type::getTokenTy(Context), ParentPad, PFS)) - return true; - + return true; + if (parseToken(lltok::lsquare, "expected '[' with catchswitch labels")) - return true; - - SmallVector<BasicBlock *, 32> Table; - do { - BasicBlock *DestBB; + return true; + + SmallVector<BasicBlock *, 32> Table; + do { + BasicBlock *DestBB; if (parseTypeAndBasicBlock(DestBB, PFS)) - return true; - Table.push_back(DestBB); - } while (EatIfPresent(lltok::comma)); - + return true; + Table.push_back(DestBB); + } while (EatIfPresent(lltok::comma)); + if (parseToken(lltok::rsquare, "expected ']' after catchswitch labels")) - return true; - + return true; + if (parseToken(lltok::kw_unwind, "expected 'unwind' after catchswitch scope")) - return true; - - BasicBlock *UnwindBB = nullptr; - if (EatIfPresent(lltok::kw_to)) { + return true; + + BasicBlock *UnwindBB = nullptr; + if (EatIfPresent(lltok::kw_to)) { if (parseToken(lltok::kw_caller, "expected 'caller' in catchswitch")) - return true; - } else { + return true; + } else { if (parseTypeAndBasicBlock(UnwindBB, PFS)) - return true; - } - - auto *CatchSwitch = - CatchSwitchInst::Create(ParentPad, UnwindBB, Table.size()); - for (BasicBlock *DestBB : Table) - CatchSwitch->addHandler(DestBB); - Inst = CatchSwitch; - return false; -} - + return true; + } + + auto *CatchSwitch = + CatchSwitchInst::Create(ParentPad, UnwindBB, Table.size()); + for (BasicBlock *DestBB : Table) + CatchSwitch->addHandler(DestBB); + Inst = CatchSwitch; + return false; +} + /// parseCatchPad -/// ::= 'catchpad' ParamList 'to' TypeAndValue 'unwind' TypeAndValue +/// ::= 'catchpad' ParamList 'to' TypeAndValue 'unwind' TypeAndValue bool LLParser::parseCatchPad(Instruction *&Inst, PerFunctionState &PFS) { - Value *CatchSwitch = nullptr; - + Value *CatchSwitch = nullptr; + if (parseToken(lltok::kw_within, "expected 'within' after catchpad")) - return true; - - if (Lex.getKind() != lltok::LocalVar && Lex.getKind() != lltok::LocalVarID) + return true; + + if (Lex.getKind() != lltok::LocalVar && Lex.getKind() != lltok::LocalVarID) return tokError("expected scope value for catchpad"); - + if (parseValue(Type::getTokenTy(Context), CatchSwitch, PFS)) - return true; - - SmallVector<Value *, 8> Args; + return true; + + SmallVector<Value *, 8> Args; if (parseExceptionArgs(Args, PFS)) - return true; - - Inst = CatchPadInst::Create(CatchSwitch, Args); - return false; -} - + return true; + + Inst = CatchPadInst::Create(CatchSwitch, Args); + return false; +} + /// parseCleanupPad -/// ::= 'cleanuppad' within Parent ParamList +/// ::= 'cleanuppad' within Parent ParamList bool LLParser::parseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) { - Value *ParentPad = nullptr; - + Value *ParentPad = nullptr; + if (parseToken(lltok::kw_within, "expected 'within' after cleanuppad")) - return true; - - if (Lex.getKind() != lltok::kw_none && Lex.getKind() != lltok::LocalVar && - Lex.getKind() != lltok::LocalVarID) + return true; + + if (Lex.getKind() != lltok::kw_none && Lex.getKind() != lltok::LocalVar && + Lex.getKind() != lltok::LocalVarID) return tokError("expected scope value for cleanuppad"); - + if (parseValue(Type::getTokenTy(Context), ParentPad, PFS)) - return true; - - SmallVector<Value *, 8> Args; + return true; + + SmallVector<Value *, 8> Args; if (parseExceptionArgs(Args, PFS)) - return true; - - Inst = CleanupPadInst::Create(ParentPad, Args); - return false; -} - -//===----------------------------------------------------------------------===// -// Unary Operators. -//===----------------------------------------------------------------------===// - + return true; + + Inst = CleanupPadInst::Create(ParentPad, Args); + return false; +} + +//===----------------------------------------------------------------------===// +// Unary Operators. +//===----------------------------------------------------------------------===// + /// parseUnaryOp -/// ::= UnaryOp TypeAndValue ',' Value -/// -/// If IsFP is false, then any integer operand is allowed, if it is true, any fp -/// operand is allowed. +/// ::= UnaryOp TypeAndValue ',' Value +/// +/// If IsFP is false, then any integer operand is allowed, if it is true, any fp +/// operand is allowed. bool LLParser::parseUnaryOp(Instruction *&Inst, PerFunctionState &PFS, - unsigned Opc, bool IsFP) { - LocTy Loc; Value *LHS; + unsigned Opc, bool IsFP) { + LocTy Loc; Value *LHS; if (parseTypeAndValue(LHS, Loc, PFS)) - return true; - - bool Valid = IsFP ? LHS->getType()->isFPOrFPVectorTy() - : LHS->getType()->isIntOrIntVectorTy(); - - if (!Valid) + return true; + + bool Valid = IsFP ? LHS->getType()->isFPOrFPVectorTy() + : LHS->getType()->isIntOrIntVectorTy(); + + if (!Valid) return error(Loc, "invalid operand type for instruction"); - - Inst = UnaryOperator::Create((Instruction::UnaryOps)Opc, LHS); - return false; -} - + + Inst = UnaryOperator::Create((Instruction::UnaryOps)Opc, LHS); + return false; +} + /// parseCallBr -/// ::= 'callbr' OptionalCallingConv OptionalAttrs Type Value ParamList -/// OptionalAttrs OptionalOperandBundles 'to' TypeAndValue -/// '[' LabelList ']' +/// ::= 'callbr' OptionalCallingConv OptionalAttrs Type Value ParamList +/// OptionalAttrs OptionalOperandBundles 'to' TypeAndValue +/// '[' LabelList ']' bool LLParser::parseCallBr(Instruction *&Inst, PerFunctionState &PFS) { - LocTy CallLoc = Lex.getLoc(); - AttrBuilder RetAttrs, FnAttrs; - std::vector<unsigned> FwdRefAttrGrps; - LocTy NoBuiltinLoc; - unsigned CC; - Type *RetType = nullptr; - LocTy RetTypeLoc; - ValID CalleeID; - SmallVector<ParamInfo, 16> ArgList; - SmallVector<OperandBundleDef, 2> BundleList; - - BasicBlock *DefaultDest; + LocTy CallLoc = Lex.getLoc(); + AttrBuilder RetAttrs, FnAttrs; + std::vector<unsigned> FwdRefAttrGrps; + LocTy NoBuiltinLoc; + unsigned CC; + Type *RetType = nullptr; + LocTy RetTypeLoc; + ValID CalleeID; + SmallVector<ParamInfo, 16> ArgList; + SmallVector<OperandBundleDef, 2> BundleList; + + BasicBlock *DefaultDest; if (parseOptionalCallingConv(CC) || parseOptionalReturnAttrs(RetAttrs) || parseType(RetType, RetTypeLoc, true /*void allowed*/) || parseValID(CalleeID) || parseParameterList(ArgList, PFS) || parseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false, - NoBuiltinLoc) || + NoBuiltinLoc) || parseOptionalOperandBundles(BundleList, PFS) || parseToken(lltok::kw_to, "expected 'to' in callbr") || parseTypeAndBasicBlock(DefaultDest, PFS) || parseToken(lltok::lsquare, "expected '[' in callbr")) - return true; - + return true; + // parse the destination list. - SmallVector<BasicBlock *, 16> IndirectDests; - - if (Lex.getKind() != lltok::rsquare) { - BasicBlock *DestBB; + SmallVector<BasicBlock *, 16> IndirectDests; + + if (Lex.getKind() != lltok::rsquare) { + BasicBlock *DestBB; if (parseTypeAndBasicBlock(DestBB, PFS)) - return true; - IndirectDests.push_back(DestBB); - - while (EatIfPresent(lltok::comma)) { + return true; + IndirectDests.push_back(DestBB); + + while (EatIfPresent(lltok::comma)) { if (parseTypeAndBasicBlock(DestBB, PFS)) - return true; - IndirectDests.push_back(DestBB); - } - } - + return true; + IndirectDests.push_back(DestBB); + } + } + if (parseToken(lltok::rsquare, "expected ']' at end of block list")) - return true; - - // If RetType is a non-function pointer type, then this is the short syntax - // for the call, which means that RetType is just the return type. Infer the - // rest of the function argument types from the arguments that are present. - FunctionType *Ty = dyn_cast<FunctionType>(RetType); - if (!Ty) { - // Pull out the types of all of the arguments... - std::vector<Type *> ParamTypes; - for (unsigned i = 0, e = ArgList.size(); i != e; ++i) - ParamTypes.push_back(ArgList[i].V->getType()); - - if (!FunctionType::isValidReturnType(RetType)) + return true; + + // If RetType is a non-function pointer type, then this is the short syntax + // for the call, which means that RetType is just the return type. Infer the + // rest of the function argument types from the arguments that are present. + FunctionType *Ty = dyn_cast<FunctionType>(RetType); + if (!Ty) { + // Pull out the types of all of the arguments... + std::vector<Type *> ParamTypes; + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) + ParamTypes.push_back(ArgList[i].V->getType()); + + if (!FunctionType::isValidReturnType(RetType)) return error(RetTypeLoc, "Invalid result type for LLVM function"); - - Ty = FunctionType::get(RetType, ParamTypes, false); - } - - CalleeID.FTy = Ty; - - // Look up the callee. - Value *Callee; + + Ty = FunctionType::get(RetType, ParamTypes, false); + } + + CalleeID.FTy = Ty; + + // Look up the callee. + Value *Callee; if (convertValIDToValue(PointerType::getUnqual(Ty), CalleeID, Callee, &PFS, - /*IsCall=*/true)) - return true; - - // Set up the Attribute for the function. - SmallVector<Value *, 8> Args; - SmallVector<AttributeSet, 8> ArgAttrs; - - // Loop through FunctionType's arguments and ensure they are specified - // correctly. Also, gather any parameter attributes. - FunctionType::param_iterator I = Ty->param_begin(); - FunctionType::param_iterator E = Ty->param_end(); - for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { - Type *ExpectedTy = nullptr; - if (I != E) { - ExpectedTy = *I++; - } else if (!Ty->isVarArg()) { + /*IsCall=*/true)) + return true; + + // Set up the Attribute for the function. + SmallVector<Value *, 8> Args; + SmallVector<AttributeSet, 8> ArgAttrs; + + // Loop through FunctionType's arguments and ensure they are specified + // correctly. Also, gather any parameter attributes. + FunctionType::param_iterator I = Ty->param_begin(); + FunctionType::param_iterator E = Ty->param_end(); + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { + Type *ExpectedTy = nullptr; + if (I != E) { + ExpectedTy = *I++; + } else if (!Ty->isVarArg()) { return error(ArgList[i].Loc, "too many arguments specified"); - } - - if (ExpectedTy && ExpectedTy != ArgList[i].V->getType()) + } + + if (ExpectedTy && ExpectedTy != ArgList[i].V->getType()) return error(ArgList[i].Loc, "argument is not of expected type '" + - getTypeString(ExpectedTy) + "'"); - Args.push_back(ArgList[i].V); - ArgAttrs.push_back(ArgList[i].Attrs); - } - - if (I != E) + getTypeString(ExpectedTy) + "'"); + Args.push_back(ArgList[i].V); + ArgAttrs.push_back(ArgList[i].Attrs); + } + + if (I != E) return error(CallLoc, "not enough parameters specified for call"); - - if (FnAttrs.hasAlignmentAttr()) + + if (FnAttrs.hasAlignmentAttr()) return error(CallLoc, "callbr instructions may not have an alignment"); - - // Finish off the Attribute and check them - AttributeList PAL = - AttributeList::get(Context, AttributeSet::get(Context, FnAttrs), - AttributeSet::get(Context, RetAttrs), ArgAttrs); - - CallBrInst *CBI = - CallBrInst::Create(Ty, Callee, DefaultDest, IndirectDests, Args, - BundleList); - CBI->setCallingConv(CC); - CBI->setAttributes(PAL); - ForwardRefAttrGroups[CBI] = FwdRefAttrGrps; - Inst = CBI; - return false; -} - -//===----------------------------------------------------------------------===// -// Binary Operators. -//===----------------------------------------------------------------------===// - + + // Finish off the Attribute and check them + AttributeList PAL = + AttributeList::get(Context, AttributeSet::get(Context, FnAttrs), + AttributeSet::get(Context, RetAttrs), ArgAttrs); + + CallBrInst *CBI = + CallBrInst::Create(Ty, Callee, DefaultDest, IndirectDests, Args, + BundleList); + CBI->setCallingConv(CC); + CBI->setAttributes(PAL); + ForwardRefAttrGroups[CBI] = FwdRefAttrGrps; + Inst = CBI; + return false; +} + +//===----------------------------------------------------------------------===// +// Binary Operators. +//===----------------------------------------------------------------------===// + /// parseArithmetic -/// ::= ArithmeticOps TypeAndValue ',' Value -/// -/// If IsFP is false, then any integer operand is allowed, if it is true, any fp -/// operand is allowed. +/// ::= ArithmeticOps TypeAndValue ',' Value +/// +/// If IsFP is false, then any integer operand is allowed, if it is true, any fp +/// operand is allowed. bool LLParser::parseArithmetic(Instruction *&Inst, PerFunctionState &PFS, - unsigned Opc, bool IsFP) { - LocTy Loc; Value *LHS, *RHS; + unsigned Opc, bool IsFP) { + LocTy Loc; Value *LHS, *RHS; if (parseTypeAndValue(LHS, Loc, PFS) || parseToken(lltok::comma, "expected ',' in arithmetic operation") || parseValue(LHS->getType(), RHS, PFS)) - return true; - - bool Valid = IsFP ? LHS->getType()->isFPOrFPVectorTy() - : LHS->getType()->isIntOrIntVectorTy(); - - if (!Valid) + return true; + + bool Valid = IsFP ? LHS->getType()->isFPOrFPVectorTy() + : LHS->getType()->isIntOrIntVectorTy(); + + if (!Valid) return error(Loc, "invalid operand type for instruction"); - - Inst = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); - return false; -} - + + Inst = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); + return false; +} + /// parseLogical -/// ::= ArithmeticOps TypeAndValue ',' Value { +/// ::= ArithmeticOps TypeAndValue ',' Value { bool LLParser::parseLogical(Instruction *&Inst, PerFunctionState &PFS, - unsigned Opc) { - LocTy Loc; Value *LHS, *RHS; + unsigned Opc) { + LocTy Loc; Value *LHS, *RHS; if (parseTypeAndValue(LHS, Loc, PFS) || parseToken(lltok::comma, "expected ',' in logical operation") || parseValue(LHS->getType(), RHS, PFS)) - return true; - - if (!LHS->getType()->isIntOrIntVectorTy()) + return true; + + if (!LHS->getType()->isIntOrIntVectorTy()) return error(Loc, "instruction requires integer or integer vector operands"); - - Inst = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); - return false; -} - + + Inst = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); + return false; +} + /// parseCompare -/// ::= 'icmp' IPredicates TypeAndValue ',' Value -/// ::= 'fcmp' FPredicates TypeAndValue ',' Value +/// ::= 'icmp' IPredicates TypeAndValue ',' Value +/// ::= 'fcmp' FPredicates TypeAndValue ',' Value bool LLParser::parseCompare(Instruction *&Inst, PerFunctionState &PFS, - unsigned Opc) { + unsigned Opc) { // parse the integer/fp comparison predicate. - LocTy Loc; - unsigned Pred; - Value *LHS, *RHS; + LocTy Loc; + unsigned Pred; + Value *LHS, *RHS; if (parseCmpPredicate(Pred, Opc) || parseTypeAndValue(LHS, Loc, PFS) || parseToken(lltok::comma, "expected ',' after compare value") || parseValue(LHS->getType(), RHS, PFS)) - return true; - - if (Opc == Instruction::FCmp) { - if (!LHS->getType()->isFPOrFPVectorTy()) + return true; + + if (Opc == Instruction::FCmp) { + if (!LHS->getType()->isFPOrFPVectorTy()) return error(Loc, "fcmp requires floating point operands"); - Inst = new FCmpInst(CmpInst::Predicate(Pred), LHS, RHS); - } else { - assert(Opc == Instruction::ICmp && "Unknown opcode for CmpInst!"); - if (!LHS->getType()->isIntOrIntVectorTy() && - !LHS->getType()->isPtrOrPtrVectorTy()) + Inst = new FCmpInst(CmpInst::Predicate(Pred), LHS, RHS); + } else { + assert(Opc == Instruction::ICmp && "Unknown opcode for CmpInst!"); + if (!LHS->getType()->isIntOrIntVectorTy() && + !LHS->getType()->isPtrOrPtrVectorTy()) return error(Loc, "icmp requires integer operands"); - Inst = new ICmpInst(CmpInst::Predicate(Pred), LHS, RHS); - } - return false; -} - -//===----------------------------------------------------------------------===// -// Other Instructions. -//===----------------------------------------------------------------------===// - + Inst = new ICmpInst(CmpInst::Predicate(Pred), LHS, RHS); + } + return false; +} + +//===----------------------------------------------------------------------===// +// Other Instructions. +//===----------------------------------------------------------------------===// + /// parseCast -/// ::= CastOpc TypeAndValue 'to' Type +/// ::= CastOpc TypeAndValue 'to' Type bool LLParser::parseCast(Instruction *&Inst, PerFunctionState &PFS, - unsigned Opc) { - LocTy Loc; - Value *Op; - Type *DestTy = nullptr; + unsigned Opc) { + LocTy Loc; + Value *Op; + Type *DestTy = nullptr; if (parseTypeAndValue(Op, Loc, PFS) || parseToken(lltok::kw_to, "expected 'to' after cast value") || parseType(DestTy)) - return true; - - if (!CastInst::castIsValid((Instruction::CastOps)Opc, Op, DestTy)) { - CastInst::castIsValid((Instruction::CastOps)Opc, Op, DestTy); + return true; + + if (!CastInst::castIsValid((Instruction::CastOps)Opc, Op, DestTy)) { + CastInst::castIsValid((Instruction::CastOps)Opc, Op, DestTy); return error(Loc, "invalid cast opcode for cast from '" + getTypeString(Op->getType()) + "' to '" + getTypeString(DestTy) + "'"); - } - Inst = CastInst::Create((Instruction::CastOps)Opc, Op, DestTy); - return false; -} - + } + Inst = CastInst::Create((Instruction::CastOps)Opc, Op, DestTy); + return false; +} + /// parseSelect -/// ::= 'select' TypeAndValue ',' TypeAndValue ',' TypeAndValue +/// ::= 'select' TypeAndValue ',' TypeAndValue ',' TypeAndValue bool LLParser::parseSelect(Instruction *&Inst, PerFunctionState &PFS) { - LocTy Loc; - Value *Op0, *Op1, *Op2; + LocTy Loc; + Value *Op0, *Op1, *Op2; if (parseTypeAndValue(Op0, Loc, PFS) || parseToken(lltok::comma, "expected ',' after select condition") || parseTypeAndValue(Op1, PFS) || parseToken(lltok::comma, "expected ',' after select value") || parseTypeAndValue(Op2, PFS)) - return true; - - if (const char *Reason = SelectInst::areInvalidOperands(Op0, Op1, Op2)) + return true; + + if (const char *Reason = SelectInst::areInvalidOperands(Op0, Op1, Op2)) return error(Loc, Reason); - - Inst = SelectInst::Create(Op0, Op1, Op2); - return false; -} - + + Inst = SelectInst::Create(Op0, Op1, Op2); + return false; +} + /// parseVAArg -/// ::= 'va_arg' TypeAndValue ',' Type +/// ::= 'va_arg' TypeAndValue ',' Type bool LLParser::parseVAArg(Instruction *&Inst, PerFunctionState &PFS) { - Value *Op; - Type *EltTy = nullptr; - LocTy TypeLoc; + Value *Op; + Type *EltTy = nullptr; + LocTy TypeLoc; if (parseTypeAndValue(Op, PFS) || parseToken(lltok::comma, "expected ',' after vaarg operand") || parseType(EltTy, TypeLoc)) - return true; - - if (!EltTy->isFirstClassType()) + return true; + + if (!EltTy->isFirstClassType()) return error(TypeLoc, "va_arg requires operand with first class type"); - - Inst = new VAArgInst(Op, EltTy); - return false; -} - + + Inst = new VAArgInst(Op, EltTy); + return false; +} + /// parseExtractElement -/// ::= 'extractelement' TypeAndValue ',' TypeAndValue +/// ::= 'extractelement' TypeAndValue ',' TypeAndValue bool LLParser::parseExtractElement(Instruction *&Inst, PerFunctionState &PFS) { - LocTy Loc; - Value *Op0, *Op1; + LocTy Loc; + Value *Op0, *Op1; if (parseTypeAndValue(Op0, Loc, PFS) || parseToken(lltok::comma, "expected ',' after extract value") || parseTypeAndValue(Op1, PFS)) - return true; - - if (!ExtractElementInst::isValidOperands(Op0, Op1)) + return true; + + if (!ExtractElementInst::isValidOperands(Op0, Op1)) return error(Loc, "invalid extractelement operands"); - - Inst = ExtractElementInst::Create(Op0, Op1); - return false; -} - + + Inst = ExtractElementInst::Create(Op0, Op1); + return false; +} + /// parseInsertElement -/// ::= 'insertelement' TypeAndValue ',' TypeAndValue ',' TypeAndValue +/// ::= 'insertelement' TypeAndValue ',' TypeAndValue ',' TypeAndValue bool LLParser::parseInsertElement(Instruction *&Inst, PerFunctionState &PFS) { - LocTy Loc; - Value *Op0, *Op1, *Op2; + LocTy Loc; + Value *Op0, *Op1, *Op2; if (parseTypeAndValue(Op0, Loc, PFS) || parseToken(lltok::comma, "expected ',' after insertelement value") || parseTypeAndValue(Op1, PFS) || parseToken(lltok::comma, "expected ',' after insertelement value") || parseTypeAndValue(Op2, PFS)) - return true; - - if (!InsertElementInst::isValidOperands(Op0, Op1, Op2)) + return true; + + if (!InsertElementInst::isValidOperands(Op0, Op1, Op2)) return error(Loc, "invalid insertelement operands"); - - Inst = InsertElementInst::Create(Op0, Op1, Op2); - return false; -} - + + Inst = InsertElementInst::Create(Op0, Op1, Op2); + return false; +} + /// parseShuffleVector -/// ::= 'shufflevector' TypeAndValue ',' TypeAndValue ',' TypeAndValue +/// ::= 'shufflevector' TypeAndValue ',' TypeAndValue ',' TypeAndValue bool LLParser::parseShuffleVector(Instruction *&Inst, PerFunctionState &PFS) { - LocTy Loc; - Value *Op0, *Op1, *Op2; + LocTy Loc; + Value *Op0, *Op1, *Op2; if (parseTypeAndValue(Op0, Loc, PFS) || parseToken(lltok::comma, "expected ',' after shuffle mask") || parseTypeAndValue(Op1, PFS) || parseToken(lltok::comma, "expected ',' after shuffle value") || parseTypeAndValue(Op2, PFS)) - return true; - - if (!ShuffleVectorInst::isValidOperands(Op0, Op1, Op2)) + return true; + + if (!ShuffleVectorInst::isValidOperands(Op0, Op1, Op2)) return error(Loc, "invalid shufflevector operands"); - - Inst = new ShuffleVectorInst(Op0, Op1, Op2); - return false; -} - + + Inst = new ShuffleVectorInst(Op0, Op1, Op2); + return false; +} + /// parsePHI -/// ::= 'phi' Type '[' Value ',' Value ']' (',' '[' Value ',' Value ']')* +/// ::= 'phi' Type '[' Value ',' Value ']' (',' '[' Value ',' Value ']')* int LLParser::parsePHI(Instruction *&Inst, PerFunctionState &PFS) { - Type *Ty = nullptr; LocTy TypeLoc; - Value *Op0, *Op1; - + Type *Ty = nullptr; LocTy TypeLoc; + Value *Op0, *Op1; + if (parseType(Ty, TypeLoc) || parseToken(lltok::lsquare, "expected '[' in phi value list") || parseValue(Ty, Op0, PFS) || parseToken(lltok::comma, "expected ',' after insertelement value") || parseValue(Type::getLabelTy(Context), Op1, PFS) || parseToken(lltok::rsquare, "expected ']' in phi value list")) - return true; - - bool AteExtraComma = false; - SmallVector<std::pair<Value*, BasicBlock*>, 16> PHIVals; - - while (true) { - PHIVals.push_back(std::make_pair(Op0, cast<BasicBlock>(Op1))); - - if (!EatIfPresent(lltok::comma)) - break; - - if (Lex.getKind() == lltok::MetadataVar) { - AteExtraComma = true; - break; - } - + return true; + + bool AteExtraComma = false; + SmallVector<std::pair<Value*, BasicBlock*>, 16> PHIVals; + + while (true) { + PHIVals.push_back(std::make_pair(Op0, cast<BasicBlock>(Op1))); + + if (!EatIfPresent(lltok::comma)) + break; + + if (Lex.getKind() == lltok::MetadataVar) { + AteExtraComma = true; + break; + } + if (parseToken(lltok::lsquare, "expected '[' in phi value list") || parseValue(Ty, Op0, PFS) || parseToken(lltok::comma, "expected ',' after insertelement value") || parseValue(Type::getLabelTy(Context), Op1, PFS) || parseToken(lltok::rsquare, "expected ']' in phi value list")) - return true; - } - - if (!Ty->isFirstClassType()) + return true; + } + + if (!Ty->isFirstClassType()) return error(TypeLoc, "phi node must have first class type"); - - PHINode *PN = PHINode::Create(Ty, PHIVals.size()); - for (unsigned i = 0, e = PHIVals.size(); i != e; ++i) - PN->addIncoming(PHIVals[i].first, PHIVals[i].second); - Inst = PN; - return AteExtraComma ? InstExtraComma : InstNormal; -} - + + PHINode *PN = PHINode::Create(Ty, PHIVals.size()); + for (unsigned i = 0, e = PHIVals.size(); i != e; ++i) + PN->addIncoming(PHIVals[i].first, PHIVals[i].second); + Inst = PN; + return AteExtraComma ? InstExtraComma : InstNormal; +} + /// parseLandingPad -/// ::= 'landingpad' Type 'personality' TypeAndValue 'cleanup'? Clause+ -/// Clause -/// ::= 'catch' TypeAndValue -/// ::= 'filter' -/// ::= 'filter' TypeAndValue ( ',' TypeAndValue )* +/// ::= 'landingpad' Type 'personality' TypeAndValue 'cleanup'? Clause+ +/// Clause +/// ::= 'catch' TypeAndValue +/// ::= 'filter' +/// ::= 'filter' TypeAndValue ( ',' TypeAndValue )* bool LLParser::parseLandingPad(Instruction *&Inst, PerFunctionState &PFS) { - Type *Ty = nullptr; LocTy TyLoc; - + Type *Ty = nullptr; LocTy TyLoc; + if (parseType(Ty, TyLoc)) - return true; - - std::unique_ptr<LandingPadInst> LP(LandingPadInst::Create(Ty, 0)); - LP->setCleanup(EatIfPresent(lltok::kw_cleanup)); - - while (Lex.getKind() == lltok::kw_catch || Lex.getKind() == lltok::kw_filter){ - LandingPadInst::ClauseType CT; - if (EatIfPresent(lltok::kw_catch)) - CT = LandingPadInst::Catch; - else if (EatIfPresent(lltok::kw_filter)) - CT = LandingPadInst::Filter; - else + return true; + + std::unique_ptr<LandingPadInst> LP(LandingPadInst::Create(Ty, 0)); + LP->setCleanup(EatIfPresent(lltok::kw_cleanup)); + + while (Lex.getKind() == lltok::kw_catch || Lex.getKind() == lltok::kw_filter){ + LandingPadInst::ClauseType CT; + if (EatIfPresent(lltok::kw_catch)) + CT = LandingPadInst::Catch; + else if (EatIfPresent(lltok::kw_filter)) + CT = LandingPadInst::Filter; + else return tokError("expected 'catch' or 'filter' clause type"); - - Value *V; - LocTy VLoc; + + Value *V; + LocTy VLoc; if (parseTypeAndValue(V, VLoc, PFS)) - return true; - - // A 'catch' type expects a non-array constant. A filter clause expects an - // array constant. - if (CT == LandingPadInst::Catch) { - if (isa<ArrayType>(V->getType())) + return true; + + // A 'catch' type expects a non-array constant. A filter clause expects an + // array constant. + if (CT == LandingPadInst::Catch) { + if (isa<ArrayType>(V->getType())) error(VLoc, "'catch' clause has an invalid type"); - } else { - if (!isa<ArrayType>(V->getType())) + } else { + if (!isa<ArrayType>(V->getType())) error(VLoc, "'filter' clause has an invalid type"); - } - - Constant *CV = dyn_cast<Constant>(V); - if (!CV) + } + + Constant *CV = dyn_cast<Constant>(V); + if (!CV) return error(VLoc, "clause argument must be a constant"); - LP->addClause(CV); - } - - Inst = LP.release(); - return false; -} - + LP->addClause(CV); + } + + Inst = LP.release(); + return false; +} + /// parseFreeze -/// ::= 'freeze' Type Value +/// ::= 'freeze' Type Value bool LLParser::parseFreeze(Instruction *&Inst, PerFunctionState &PFS) { - LocTy Loc; - Value *Op; + LocTy Loc; + Value *Op; if (parseTypeAndValue(Op, Loc, PFS)) - return true; - - Inst = new FreezeInst(Op); - return false; -} - + return true; + + Inst = new FreezeInst(Op); + return false; +} + /// parseCall -/// ::= 'call' OptionalFastMathFlags OptionalCallingConv -/// OptionalAttrs Type Value ParameterList OptionalAttrs -/// ::= 'tail' 'call' OptionalFastMathFlags OptionalCallingConv -/// OptionalAttrs Type Value ParameterList OptionalAttrs -/// ::= 'musttail' 'call' OptionalFastMathFlags OptionalCallingConv -/// OptionalAttrs Type Value ParameterList OptionalAttrs -/// ::= 'notail' 'call' OptionalFastMathFlags OptionalCallingConv -/// OptionalAttrs Type Value ParameterList OptionalAttrs +/// ::= 'call' OptionalFastMathFlags OptionalCallingConv +/// OptionalAttrs Type Value ParameterList OptionalAttrs +/// ::= 'tail' 'call' OptionalFastMathFlags OptionalCallingConv +/// OptionalAttrs Type Value ParameterList OptionalAttrs +/// ::= 'musttail' 'call' OptionalFastMathFlags OptionalCallingConv +/// OptionalAttrs Type Value ParameterList OptionalAttrs +/// ::= 'notail' 'call' OptionalFastMathFlags OptionalCallingConv +/// OptionalAttrs Type Value ParameterList OptionalAttrs bool LLParser::parseCall(Instruction *&Inst, PerFunctionState &PFS, - CallInst::TailCallKind TCK) { - AttrBuilder RetAttrs, FnAttrs; - std::vector<unsigned> FwdRefAttrGrps; - LocTy BuiltinLoc; - unsigned CallAddrSpace; - unsigned CC; - Type *RetType = nullptr; - LocTy RetTypeLoc; - ValID CalleeID; - SmallVector<ParamInfo, 16> ArgList; - SmallVector<OperandBundleDef, 2> BundleList; - LocTy CallLoc = Lex.getLoc(); - - if (TCK != CallInst::TCK_None && + CallInst::TailCallKind TCK) { + AttrBuilder RetAttrs, FnAttrs; + std::vector<unsigned> FwdRefAttrGrps; + LocTy BuiltinLoc; + unsigned CallAddrSpace; + unsigned CC; + Type *RetType = nullptr; + LocTy RetTypeLoc; + ValID CalleeID; + SmallVector<ParamInfo, 16> ArgList; + SmallVector<OperandBundleDef, 2> BundleList; + LocTy CallLoc = Lex.getLoc(); + + if (TCK != CallInst::TCK_None && parseToken(lltok::kw_call, - "expected 'tail call', 'musttail call', or 'notail call'")) - return true; - - FastMathFlags FMF = EatFastMathFlagsIfPresent(); - + "expected 'tail call', 'musttail call', or 'notail call'")) + return true; + + FastMathFlags FMF = EatFastMathFlagsIfPresent(); + if (parseOptionalCallingConv(CC) || parseOptionalReturnAttrs(RetAttrs) || parseOptionalProgramAddrSpace(CallAddrSpace) || parseType(RetType, RetTypeLoc, true /*void allowed*/) || parseValID(CalleeID) || parseParameterList(ArgList, PFS, TCK == CallInst::TCK_MustTail, - PFS.getFunction().isVarArg()) || + PFS.getFunction().isVarArg()) || parseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false, BuiltinLoc) || parseOptionalOperandBundles(BundleList, PFS)) - return true; - - // If RetType is a non-function pointer type, then this is the short syntax - // for the call, which means that RetType is just the return type. Infer the - // rest of the function argument types from the arguments that are present. - FunctionType *Ty = dyn_cast<FunctionType>(RetType); - if (!Ty) { - // Pull out the types of all of the arguments... - std::vector<Type*> ParamTypes; - for (unsigned i = 0, e = ArgList.size(); i != e; ++i) - ParamTypes.push_back(ArgList[i].V->getType()); - - if (!FunctionType::isValidReturnType(RetType)) + return true; + + // If RetType is a non-function pointer type, then this is the short syntax + // for the call, which means that RetType is just the return type. Infer the + // rest of the function argument types from the arguments that are present. + FunctionType *Ty = dyn_cast<FunctionType>(RetType); + if (!Ty) { + // Pull out the types of all of the arguments... + std::vector<Type*> ParamTypes; + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) + ParamTypes.push_back(ArgList[i].V->getType()); + + if (!FunctionType::isValidReturnType(RetType)) return error(RetTypeLoc, "Invalid result type for LLVM function"); - - Ty = FunctionType::get(RetType, ParamTypes, false); - } - - CalleeID.FTy = Ty; - - // Look up the callee. - Value *Callee; + + Ty = FunctionType::get(RetType, ParamTypes, false); + } + + CalleeID.FTy = Ty; + + // Look up the callee. + Value *Callee; if (convertValIDToValue(PointerType::get(Ty, CallAddrSpace), CalleeID, Callee, - &PFS, /*IsCall=*/true)) - return true; - - // Set up the Attribute for the function. - SmallVector<AttributeSet, 8> Attrs; - - SmallVector<Value*, 8> Args; - - // Loop through FunctionType's arguments and ensure they are specified - // correctly. Also, gather any parameter attributes. - FunctionType::param_iterator I = Ty->param_begin(); - FunctionType::param_iterator E = Ty->param_end(); - for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { - Type *ExpectedTy = nullptr; - if (I != E) { - ExpectedTy = *I++; - } else if (!Ty->isVarArg()) { + &PFS, /*IsCall=*/true)) + return true; + + // Set up the Attribute for the function. + SmallVector<AttributeSet, 8> Attrs; + + SmallVector<Value*, 8> Args; + + // Loop through FunctionType's arguments and ensure they are specified + // correctly. Also, gather any parameter attributes. + FunctionType::param_iterator I = Ty->param_begin(); + FunctionType::param_iterator E = Ty->param_end(); + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { + Type *ExpectedTy = nullptr; + if (I != E) { + ExpectedTy = *I++; + } else if (!Ty->isVarArg()) { return error(ArgList[i].Loc, "too many arguments specified"); - } - - if (ExpectedTy && ExpectedTy != ArgList[i].V->getType()) + } + + if (ExpectedTy && ExpectedTy != ArgList[i].V->getType()) return error(ArgList[i].Loc, "argument is not of expected type '" + getTypeString(ExpectedTy) + "'"); - Args.push_back(ArgList[i].V); - Attrs.push_back(ArgList[i].Attrs); - } - - if (I != E) + Args.push_back(ArgList[i].V); + Attrs.push_back(ArgList[i].Attrs); + } + + if (I != E) return error(CallLoc, "not enough parameters specified for call"); - - if (FnAttrs.hasAlignmentAttr()) + + if (FnAttrs.hasAlignmentAttr()) return error(CallLoc, "call instructions may not have an alignment"); - - // Finish off the Attribute and check them - AttributeList PAL = - AttributeList::get(Context, AttributeSet::get(Context, FnAttrs), - AttributeSet::get(Context, RetAttrs), Attrs); - - CallInst *CI = CallInst::Create(Ty, Callee, Args, BundleList); - CI->setTailCallKind(TCK); - CI->setCallingConv(CC); - if (FMF.any()) { - if (!isa<FPMathOperator>(CI)) { - CI->deleteValue(); + + // Finish off the Attribute and check them + AttributeList PAL = + AttributeList::get(Context, AttributeSet::get(Context, FnAttrs), + AttributeSet::get(Context, RetAttrs), Attrs); + + CallInst *CI = CallInst::Create(Ty, Callee, Args, BundleList); + CI->setTailCallKind(TCK); + CI->setCallingConv(CC); + if (FMF.any()) { + if (!isa<FPMathOperator>(CI)) { + CI->deleteValue(); return error(CallLoc, "fast-math-flags specified for call without " "floating-point scalar or vector return type"); - } - CI->setFastMathFlags(FMF); - } - CI->setAttributes(PAL); - ForwardRefAttrGroups[CI] = FwdRefAttrGrps; - Inst = CI; - return false; -} - -//===----------------------------------------------------------------------===// -// Memory Instructions. -//===----------------------------------------------------------------------===// - + } + CI->setFastMathFlags(FMF); + } + CI->setAttributes(PAL); + ForwardRefAttrGroups[CI] = FwdRefAttrGrps; + Inst = CI; + return false; +} + +//===----------------------------------------------------------------------===// +// Memory Instructions. +//===----------------------------------------------------------------------===// + /// parseAlloc -/// ::= 'alloca' 'inalloca'? 'swifterror'? Type (',' TypeAndValue)? -/// (',' 'align' i32)? (',', 'addrspace(n))? +/// ::= 'alloca' 'inalloca'? 'swifterror'? Type (',' TypeAndValue)? +/// (',' 'align' i32)? (',', 'addrspace(n))? int LLParser::parseAlloc(Instruction *&Inst, PerFunctionState &PFS) { - Value *Size = nullptr; - LocTy SizeLoc, TyLoc, ASLoc; - MaybeAlign Alignment; - unsigned AddrSpace = 0; - Type *Ty = nullptr; - - bool IsInAlloca = EatIfPresent(lltok::kw_inalloca); - bool IsSwiftError = EatIfPresent(lltok::kw_swifterror); - + Value *Size = nullptr; + LocTy SizeLoc, TyLoc, ASLoc; + MaybeAlign Alignment; + unsigned AddrSpace = 0; + Type *Ty = nullptr; + + bool IsInAlloca = EatIfPresent(lltok::kw_inalloca); + bool IsSwiftError = EatIfPresent(lltok::kw_swifterror); + if (parseType(Ty, TyLoc)) return true; - - if (Ty->isFunctionTy() || !PointerType::isValidElementType(Ty)) + + if (Ty->isFunctionTy() || !PointerType::isValidElementType(Ty)) return error(TyLoc, "invalid type for alloca"); - - bool AteExtraComma = false; - if (EatIfPresent(lltok::comma)) { - if (Lex.getKind() == lltok::kw_align) { + + bool AteExtraComma = false; + if (EatIfPresent(lltok::comma)) { + if (Lex.getKind() == lltok::kw_align) { if (parseOptionalAlignment(Alignment)) - return true; + return true; if (parseOptionalCommaAddrSpace(AddrSpace, ASLoc, AteExtraComma)) - return true; - } else if (Lex.getKind() == lltok::kw_addrspace) { - ASLoc = Lex.getLoc(); + return true; + } else if (Lex.getKind() == lltok::kw_addrspace) { + ASLoc = Lex.getLoc(); if (parseOptionalAddrSpace(AddrSpace)) - return true; - } else if (Lex.getKind() == lltok::MetadataVar) { - AteExtraComma = true; - } else { + return true; + } else if (Lex.getKind() == lltok::MetadataVar) { + AteExtraComma = true; + } else { if (parseTypeAndValue(Size, SizeLoc, PFS)) - return true; - if (EatIfPresent(lltok::comma)) { - if (Lex.getKind() == lltok::kw_align) { + return true; + if (EatIfPresent(lltok::comma)) { + if (Lex.getKind() == lltok::kw_align) { if (parseOptionalAlignment(Alignment)) - return true; + return true; if (parseOptionalCommaAddrSpace(AddrSpace, ASLoc, AteExtraComma)) - return true; - } else if (Lex.getKind() == lltok::kw_addrspace) { - ASLoc = Lex.getLoc(); + return true; + } else if (Lex.getKind() == lltok::kw_addrspace) { + ASLoc = Lex.getLoc(); if (parseOptionalAddrSpace(AddrSpace)) - return true; - } else if (Lex.getKind() == lltok::MetadataVar) { - AteExtraComma = true; - } - } - } - } - - if (Size && !Size->getType()->isIntegerTy()) + return true; + } else if (Lex.getKind() == lltok::MetadataVar) { + AteExtraComma = true; + } + } + } + } + + if (Size && !Size->getType()->isIntegerTy()) return error(SizeLoc, "element count must have integer type"); - - SmallPtrSet<Type *, 4> Visited; - if (!Alignment && !Ty->isSized(&Visited)) + + SmallPtrSet<Type *, 4> Visited; + if (!Alignment && !Ty->isSized(&Visited)) return error(TyLoc, "Cannot allocate unsized type"); - if (!Alignment) - Alignment = M->getDataLayout().getPrefTypeAlign(Ty); - AllocaInst *AI = new AllocaInst(Ty, AddrSpace, Size, *Alignment); - AI->setUsedWithInAlloca(IsInAlloca); - AI->setSwiftError(IsSwiftError); - Inst = AI; - return AteExtraComma ? InstExtraComma : InstNormal; -} - + if (!Alignment) + Alignment = M->getDataLayout().getPrefTypeAlign(Ty); + AllocaInst *AI = new AllocaInst(Ty, AddrSpace, Size, *Alignment); + AI->setUsedWithInAlloca(IsInAlloca); + AI->setSwiftError(IsSwiftError); + Inst = AI; + return AteExtraComma ? InstExtraComma : InstNormal; +} + /// parseLoad -/// ::= 'load' 'volatile'? TypeAndValue (',' 'align' i32)? -/// ::= 'load' 'atomic' 'volatile'? TypeAndValue -/// 'singlethread'? AtomicOrdering (',' 'align' i32)? +/// ::= 'load' 'volatile'? TypeAndValue (',' 'align' i32)? +/// ::= 'load' 'atomic' 'volatile'? TypeAndValue +/// 'singlethread'? AtomicOrdering (',' 'align' i32)? int LLParser::parseLoad(Instruction *&Inst, PerFunctionState &PFS) { - Value *Val; LocTy Loc; - MaybeAlign Alignment; - bool AteExtraComma = false; - bool isAtomic = false; - AtomicOrdering Ordering = AtomicOrdering::NotAtomic; - SyncScope::ID SSID = SyncScope::System; - - if (Lex.getKind() == lltok::kw_atomic) { - isAtomic = true; - Lex.Lex(); - } - - bool isVolatile = false; - if (Lex.getKind() == lltok::kw_volatile) { - isVolatile = true; - Lex.Lex(); - } - - Type *Ty; - LocTy ExplicitTypeLoc = Lex.getLoc(); + Value *Val; LocTy Loc; + MaybeAlign Alignment; + bool AteExtraComma = false; + bool isAtomic = false; + AtomicOrdering Ordering = AtomicOrdering::NotAtomic; + SyncScope::ID SSID = SyncScope::System; + + if (Lex.getKind() == lltok::kw_atomic) { + isAtomic = true; + Lex.Lex(); + } + + bool isVolatile = false; + if (Lex.getKind() == lltok::kw_volatile) { + isVolatile = true; + Lex.Lex(); + } + + Type *Ty; + LocTy ExplicitTypeLoc = Lex.getLoc(); if (parseType(Ty) || parseToken(lltok::comma, "expected comma after load's type") || parseTypeAndValue(Val, Loc, PFS) || parseScopeAndOrdering(isAtomic, SSID, Ordering) || parseOptionalCommaAlign(Alignment, AteExtraComma)) - return true; - - if (!Val->getType()->isPointerTy() || !Ty->isFirstClassType()) + return true; + + if (!Val->getType()->isPointerTy() || !Ty->isFirstClassType()) return error(Loc, "load operand must be a pointer to a first class type"); - if (isAtomic && !Alignment) + if (isAtomic && !Alignment) return error(Loc, "atomic load must have explicit non-zero alignment"); - if (Ordering == AtomicOrdering::Release || - Ordering == AtomicOrdering::AcquireRelease) + if (Ordering == AtomicOrdering::Release || + Ordering == AtomicOrdering::AcquireRelease) return error(Loc, "atomic load cannot use Release ordering"); - - if (Ty != cast<PointerType>(Val->getType())->getElementType()) + + if (Ty != cast<PointerType>(Val->getType())->getElementType()) return error(ExplicitTypeLoc, - "explicit pointee type doesn't match operand's pointee type"); - SmallPtrSet<Type *, 4> Visited; - if (!Alignment && !Ty->isSized(&Visited)) + "explicit pointee type doesn't match operand's pointee type"); + SmallPtrSet<Type *, 4> Visited; + if (!Alignment && !Ty->isSized(&Visited)) return error(ExplicitTypeLoc, "loading unsized types is not allowed"); - if (!Alignment) - Alignment = M->getDataLayout().getABITypeAlign(Ty); - Inst = new LoadInst(Ty, Val, "", isVolatile, *Alignment, Ordering, SSID); - return AteExtraComma ? InstExtraComma : InstNormal; -} - + if (!Alignment) + Alignment = M->getDataLayout().getABITypeAlign(Ty); + Inst = new LoadInst(Ty, Val, "", isVolatile, *Alignment, Ordering, SSID); + return AteExtraComma ? InstExtraComma : InstNormal; +} + /// parseStore - -/// ::= 'store' 'volatile'? TypeAndValue ',' TypeAndValue (',' 'align' i32)? -/// ::= 'store' 'atomic' 'volatile'? TypeAndValue ',' TypeAndValue -/// 'singlethread'? AtomicOrdering (',' 'align' i32)? + +/// ::= 'store' 'volatile'? TypeAndValue ',' TypeAndValue (',' 'align' i32)? +/// ::= 'store' 'atomic' 'volatile'? TypeAndValue ',' TypeAndValue +/// 'singlethread'? AtomicOrdering (',' 'align' i32)? int LLParser::parseStore(Instruction *&Inst, PerFunctionState &PFS) { - Value *Val, *Ptr; LocTy Loc, PtrLoc; - MaybeAlign Alignment; - bool AteExtraComma = false; - bool isAtomic = false; - AtomicOrdering Ordering = AtomicOrdering::NotAtomic; - SyncScope::ID SSID = SyncScope::System; - - if (Lex.getKind() == lltok::kw_atomic) { - isAtomic = true; - Lex.Lex(); - } - - bool isVolatile = false; - if (Lex.getKind() == lltok::kw_volatile) { - isVolatile = true; - Lex.Lex(); - } - + Value *Val, *Ptr; LocTy Loc, PtrLoc; + MaybeAlign Alignment; + bool AteExtraComma = false; + bool isAtomic = false; + AtomicOrdering Ordering = AtomicOrdering::NotAtomic; + SyncScope::ID SSID = SyncScope::System; + + if (Lex.getKind() == lltok::kw_atomic) { + isAtomic = true; + Lex.Lex(); + } + + bool isVolatile = false; + if (Lex.getKind() == lltok::kw_volatile) { + isVolatile = true; + Lex.Lex(); + } + if (parseTypeAndValue(Val, Loc, PFS) || parseToken(lltok::comma, "expected ',' after store operand") || parseTypeAndValue(Ptr, PtrLoc, PFS) || parseScopeAndOrdering(isAtomic, SSID, Ordering) || parseOptionalCommaAlign(Alignment, AteExtraComma)) - return true; - - if (!Ptr->getType()->isPointerTy()) + return true; + + if (!Ptr->getType()->isPointerTy()) return error(PtrLoc, "store operand must be a pointer"); - if (!Val->getType()->isFirstClassType()) + if (!Val->getType()->isFirstClassType()) return error(Loc, "store operand must be a first class value"); - if (cast<PointerType>(Ptr->getType())->getElementType() != Val->getType()) + if (cast<PointerType>(Ptr->getType())->getElementType() != Val->getType()) return error(Loc, "stored value and pointer type do not match"); - if (isAtomic && !Alignment) + if (isAtomic && !Alignment) return error(Loc, "atomic store must have explicit non-zero alignment"); - if (Ordering == AtomicOrdering::Acquire || - Ordering == AtomicOrdering::AcquireRelease) + if (Ordering == AtomicOrdering::Acquire || + Ordering == AtomicOrdering::AcquireRelease) return error(Loc, "atomic store cannot use Acquire ordering"); - SmallPtrSet<Type *, 4> Visited; - if (!Alignment && !Val->getType()->isSized(&Visited)) + SmallPtrSet<Type *, 4> Visited; + if (!Alignment && !Val->getType()->isSized(&Visited)) return error(Loc, "storing unsized types is not allowed"); - if (!Alignment) - Alignment = M->getDataLayout().getABITypeAlign(Val->getType()); - - Inst = new StoreInst(Val, Ptr, isVolatile, *Alignment, Ordering, SSID); - return AteExtraComma ? InstExtraComma : InstNormal; -} - + if (!Alignment) + Alignment = M->getDataLayout().getABITypeAlign(Val->getType()); + + Inst = new StoreInst(Val, Ptr, isVolatile, *Alignment, Ordering, SSID); + return AteExtraComma ? InstExtraComma : InstNormal; +} + /// parseCmpXchg -/// ::= 'cmpxchg' 'weak'? 'volatile'? TypeAndValue ',' TypeAndValue ',' -/// TypeAndValue 'singlethread'? AtomicOrdering AtomicOrdering +/// ::= 'cmpxchg' 'weak'? 'volatile'? TypeAndValue ',' TypeAndValue ',' +/// TypeAndValue 'singlethread'? AtomicOrdering AtomicOrdering int LLParser::parseCmpXchg(Instruction *&Inst, PerFunctionState &PFS) { - Value *Ptr, *Cmp, *New; LocTy PtrLoc, CmpLoc, NewLoc; - bool AteExtraComma = false; - AtomicOrdering SuccessOrdering = AtomicOrdering::NotAtomic; - AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic; - SyncScope::ID SSID = SyncScope::System; - bool isVolatile = false; - bool isWeak = false; - - if (EatIfPresent(lltok::kw_weak)) - isWeak = true; - - if (EatIfPresent(lltok::kw_volatile)) - isVolatile = true; - + Value *Ptr, *Cmp, *New; LocTy PtrLoc, CmpLoc, NewLoc; + bool AteExtraComma = false; + AtomicOrdering SuccessOrdering = AtomicOrdering::NotAtomic; + AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic; + SyncScope::ID SSID = SyncScope::System; + bool isVolatile = false; + bool isWeak = false; + + if (EatIfPresent(lltok::kw_weak)) + isWeak = true; + + if (EatIfPresent(lltok::kw_volatile)) + isVolatile = true; + if (parseTypeAndValue(Ptr, PtrLoc, PFS) || parseToken(lltok::comma, "expected ',' after cmpxchg address") || parseTypeAndValue(Cmp, CmpLoc, PFS) || @@ -7455,429 +7455,429 @@ int LLParser::parseCmpXchg(Instruction *&Inst, PerFunctionState &PFS) { parseTypeAndValue(New, NewLoc, PFS) || parseScopeAndOrdering(true /*Always atomic*/, SSID, SuccessOrdering) || parseOrdering(FailureOrdering)) - return true; - - if (SuccessOrdering == AtomicOrdering::Unordered || - FailureOrdering == AtomicOrdering::Unordered) + return true; + + if (SuccessOrdering == AtomicOrdering::Unordered || + FailureOrdering == AtomicOrdering::Unordered) return tokError("cmpxchg cannot be unordered"); - if (isStrongerThan(FailureOrdering, SuccessOrdering)) + if (isStrongerThan(FailureOrdering, SuccessOrdering)) return tokError("cmpxchg failure argument shall be no stronger than the " - "success argument"); - if (FailureOrdering == AtomicOrdering::Release || - FailureOrdering == AtomicOrdering::AcquireRelease) + "success argument"); + if (FailureOrdering == AtomicOrdering::Release || + FailureOrdering == AtomicOrdering::AcquireRelease) return tokError( - "cmpxchg failure ordering cannot include release semantics"); - if (!Ptr->getType()->isPointerTy()) + "cmpxchg failure ordering cannot include release semantics"); + if (!Ptr->getType()->isPointerTy()) return error(PtrLoc, "cmpxchg operand must be a pointer"); - if (cast<PointerType>(Ptr->getType())->getElementType() != Cmp->getType()) + if (cast<PointerType>(Ptr->getType())->getElementType() != Cmp->getType()) return error(CmpLoc, "compare value and pointer type do not match"); - if (cast<PointerType>(Ptr->getType())->getElementType() != New->getType()) + if (cast<PointerType>(Ptr->getType())->getElementType() != New->getType()) return error(NewLoc, "new value and pointer type do not match"); - if (!New->getType()->isFirstClassType()) + if (!New->getType()->isFirstClassType()) return error(NewLoc, "cmpxchg operand must be a first class value"); - - Align Alignment( - PFS.getFunction().getParent()->getDataLayout().getTypeStoreSize( - Cmp->getType())); - - AtomicCmpXchgInst *CXI = new AtomicCmpXchgInst( - Ptr, Cmp, New, Alignment, SuccessOrdering, FailureOrdering, SSID); - CXI->setVolatile(isVolatile); - CXI->setWeak(isWeak); - Inst = CXI; - return AteExtraComma ? InstExtraComma : InstNormal; -} - + + Align Alignment( + PFS.getFunction().getParent()->getDataLayout().getTypeStoreSize( + Cmp->getType())); + + AtomicCmpXchgInst *CXI = new AtomicCmpXchgInst( + Ptr, Cmp, New, Alignment, SuccessOrdering, FailureOrdering, SSID); + CXI->setVolatile(isVolatile); + CXI->setWeak(isWeak); + Inst = CXI; + return AteExtraComma ? InstExtraComma : InstNormal; +} + /// parseAtomicRMW -/// ::= 'atomicrmw' 'volatile'? BinOp TypeAndValue ',' TypeAndValue -/// 'singlethread'? AtomicOrdering +/// ::= 'atomicrmw' 'volatile'? BinOp TypeAndValue ',' TypeAndValue +/// 'singlethread'? AtomicOrdering int LLParser::parseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS) { - Value *Ptr, *Val; LocTy PtrLoc, ValLoc; - bool AteExtraComma = false; - AtomicOrdering Ordering = AtomicOrdering::NotAtomic; - SyncScope::ID SSID = SyncScope::System; - bool isVolatile = false; - bool IsFP = false; - AtomicRMWInst::BinOp Operation; - - if (EatIfPresent(lltok::kw_volatile)) - isVolatile = true; - - switch (Lex.getKind()) { + Value *Ptr, *Val; LocTy PtrLoc, ValLoc; + bool AteExtraComma = false; + AtomicOrdering Ordering = AtomicOrdering::NotAtomic; + SyncScope::ID SSID = SyncScope::System; + bool isVolatile = false; + bool IsFP = false; + AtomicRMWInst::BinOp Operation; + + if (EatIfPresent(lltok::kw_volatile)) + isVolatile = true; + + switch (Lex.getKind()) { default: return tokError("expected binary operation in atomicrmw"); - case lltok::kw_xchg: Operation = AtomicRMWInst::Xchg; break; - case lltok::kw_add: Operation = AtomicRMWInst::Add; break; - case lltok::kw_sub: Operation = AtomicRMWInst::Sub; break; - case lltok::kw_and: Operation = AtomicRMWInst::And; break; - case lltok::kw_nand: Operation = AtomicRMWInst::Nand; break; - case lltok::kw_or: Operation = AtomicRMWInst::Or; break; - case lltok::kw_xor: Operation = AtomicRMWInst::Xor; break; - case lltok::kw_max: Operation = AtomicRMWInst::Max; break; - case lltok::kw_min: Operation = AtomicRMWInst::Min; break; - case lltok::kw_umax: Operation = AtomicRMWInst::UMax; break; - case lltok::kw_umin: Operation = AtomicRMWInst::UMin; break; - case lltok::kw_fadd: - Operation = AtomicRMWInst::FAdd; - IsFP = true; - break; - case lltok::kw_fsub: - Operation = AtomicRMWInst::FSub; - IsFP = true; - break; - } - Lex.Lex(); // Eat the operation. - + case lltok::kw_xchg: Operation = AtomicRMWInst::Xchg; break; + case lltok::kw_add: Operation = AtomicRMWInst::Add; break; + case lltok::kw_sub: Operation = AtomicRMWInst::Sub; break; + case lltok::kw_and: Operation = AtomicRMWInst::And; break; + case lltok::kw_nand: Operation = AtomicRMWInst::Nand; break; + case lltok::kw_or: Operation = AtomicRMWInst::Or; break; + case lltok::kw_xor: Operation = AtomicRMWInst::Xor; break; + case lltok::kw_max: Operation = AtomicRMWInst::Max; break; + case lltok::kw_min: Operation = AtomicRMWInst::Min; break; + case lltok::kw_umax: Operation = AtomicRMWInst::UMax; break; + case lltok::kw_umin: Operation = AtomicRMWInst::UMin; break; + case lltok::kw_fadd: + Operation = AtomicRMWInst::FAdd; + IsFP = true; + break; + case lltok::kw_fsub: + Operation = AtomicRMWInst::FSub; + IsFP = true; + break; + } + Lex.Lex(); // Eat the operation. + if (parseTypeAndValue(Ptr, PtrLoc, PFS) || parseToken(lltok::comma, "expected ',' after atomicrmw address") || parseTypeAndValue(Val, ValLoc, PFS) || parseScopeAndOrdering(true /*Always atomic*/, SSID, Ordering)) - return true; - - if (Ordering == AtomicOrdering::Unordered) + return true; + + if (Ordering == AtomicOrdering::Unordered) return tokError("atomicrmw cannot be unordered"); - if (!Ptr->getType()->isPointerTy()) + if (!Ptr->getType()->isPointerTy()) return error(PtrLoc, "atomicrmw operand must be a pointer"); - if (cast<PointerType>(Ptr->getType())->getElementType() != Val->getType()) + if (cast<PointerType>(Ptr->getType())->getElementType() != Val->getType()) return error(ValLoc, "atomicrmw value and pointer type do not match"); - - if (Operation == AtomicRMWInst::Xchg) { - if (!Val->getType()->isIntegerTy() && - !Val->getType()->isFloatingPointTy()) { + + if (Operation == AtomicRMWInst::Xchg) { + if (!Val->getType()->isIntegerTy() && + !Val->getType()->isFloatingPointTy()) { return error(ValLoc, "atomicrmw " + AtomicRMWInst::getOperationName(Operation) + " operand must be an integer or floating point type"); - } - } else if (IsFP) { - if (!Val->getType()->isFloatingPointTy()) { + } + } else if (IsFP) { + if (!Val->getType()->isFloatingPointTy()) { return error(ValLoc, "atomicrmw " + AtomicRMWInst::getOperationName(Operation) + " operand must be a floating point type"); - } - } else { - if (!Val->getType()->isIntegerTy()) { + } + } else { + if (!Val->getType()->isIntegerTy()) { return error(ValLoc, "atomicrmw " + AtomicRMWInst::getOperationName(Operation) + " operand must be an integer"); - } - } - - unsigned Size = Val->getType()->getPrimitiveSizeInBits(); - if (Size < 8 || (Size & (Size - 1))) + } + } + + unsigned Size = Val->getType()->getPrimitiveSizeInBits(); + if (Size < 8 || (Size & (Size - 1))) return error(ValLoc, "atomicrmw operand must be power-of-two byte-sized" - " integer"); - Align Alignment( - PFS.getFunction().getParent()->getDataLayout().getTypeStoreSize( - Val->getType())); - AtomicRMWInst *RMWI = - new AtomicRMWInst(Operation, Ptr, Val, Alignment, Ordering, SSID); - RMWI->setVolatile(isVolatile); - Inst = RMWI; - return AteExtraComma ? InstExtraComma : InstNormal; -} - + " integer"); + Align Alignment( + PFS.getFunction().getParent()->getDataLayout().getTypeStoreSize( + Val->getType())); + AtomicRMWInst *RMWI = + new AtomicRMWInst(Operation, Ptr, Val, Alignment, Ordering, SSID); + RMWI->setVolatile(isVolatile); + Inst = RMWI; + return AteExtraComma ? InstExtraComma : InstNormal; +} + /// parseFence -/// ::= 'fence' 'singlethread'? AtomicOrdering +/// ::= 'fence' 'singlethread'? AtomicOrdering int LLParser::parseFence(Instruction *&Inst, PerFunctionState &PFS) { - AtomicOrdering Ordering = AtomicOrdering::NotAtomic; - SyncScope::ID SSID = SyncScope::System; + AtomicOrdering Ordering = AtomicOrdering::NotAtomic; + SyncScope::ID SSID = SyncScope::System; if (parseScopeAndOrdering(true /*Always atomic*/, SSID, Ordering)) - return true; - - if (Ordering == AtomicOrdering::Unordered) + return true; + + if (Ordering == AtomicOrdering::Unordered) return tokError("fence cannot be unordered"); - if (Ordering == AtomicOrdering::Monotonic) + if (Ordering == AtomicOrdering::Monotonic) return tokError("fence cannot be monotonic"); - - Inst = new FenceInst(Context, Ordering, SSID); - return InstNormal; -} - + + Inst = new FenceInst(Context, Ordering, SSID); + return InstNormal; +} + /// parseGetElementPtr -/// ::= 'getelementptr' 'inbounds'? TypeAndValue (',' TypeAndValue)* +/// ::= 'getelementptr' 'inbounds'? TypeAndValue (',' TypeAndValue)* int LLParser::parseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { - Value *Ptr = nullptr; - Value *Val = nullptr; - LocTy Loc, EltLoc; - - bool InBounds = EatIfPresent(lltok::kw_inbounds); - - Type *Ty = nullptr; - LocTy ExplicitTypeLoc = Lex.getLoc(); + Value *Ptr = nullptr; + Value *Val = nullptr; + LocTy Loc, EltLoc; + + bool InBounds = EatIfPresent(lltok::kw_inbounds); + + Type *Ty = nullptr; + LocTy ExplicitTypeLoc = Lex.getLoc(); if (parseType(Ty) || parseToken(lltok::comma, "expected comma after getelementptr's type") || parseTypeAndValue(Ptr, Loc, PFS)) - return true; - - Type *BaseType = Ptr->getType(); - PointerType *BasePointerType = dyn_cast<PointerType>(BaseType->getScalarType()); - if (!BasePointerType) + return true; + + Type *BaseType = Ptr->getType(); + PointerType *BasePointerType = dyn_cast<PointerType>(BaseType->getScalarType()); + if (!BasePointerType) return error(Loc, "base of getelementptr must be a pointer"); - - if (Ty != BasePointerType->getElementType()) + + if (Ty != BasePointerType->getElementType()) return error(ExplicitTypeLoc, - "explicit pointee type doesn't match operand's pointee type"); - - SmallVector<Value*, 16> Indices; - bool AteExtraComma = false; - // GEP returns a vector of pointers if at least one of parameters is a vector. - // All vector parameters should have the same vector width. - ElementCount GEPWidth = BaseType->isVectorTy() - ? cast<VectorType>(BaseType)->getElementCount() + "explicit pointee type doesn't match operand's pointee type"); + + SmallVector<Value*, 16> Indices; + bool AteExtraComma = false; + // GEP returns a vector of pointers if at least one of parameters is a vector. + // All vector parameters should have the same vector width. + ElementCount GEPWidth = BaseType->isVectorTy() + ? cast<VectorType>(BaseType)->getElementCount() : ElementCount::getFixed(0); - - while (EatIfPresent(lltok::comma)) { - if (Lex.getKind() == lltok::MetadataVar) { - AteExtraComma = true; - break; - } + + while (EatIfPresent(lltok::comma)) { + if (Lex.getKind() == lltok::MetadataVar) { + AteExtraComma = true; + break; + } if (parseTypeAndValue(Val, EltLoc, PFS)) return true; - if (!Val->getType()->isIntOrIntVectorTy()) + if (!Val->getType()->isIntOrIntVectorTy()) return error(EltLoc, "getelementptr index must be an integer"); - - if (auto *ValVTy = dyn_cast<VectorType>(Val->getType())) { - ElementCount ValNumEl = ValVTy->getElementCount(); + + if (auto *ValVTy = dyn_cast<VectorType>(Val->getType())) { + ElementCount ValNumEl = ValVTy->getElementCount(); if (GEPWidth != ElementCount::getFixed(0) && GEPWidth != ValNumEl) return error( EltLoc, "getelementptr vector index has a wrong number of elements"); - GEPWidth = ValNumEl; - } - Indices.push_back(Val); - } - - SmallPtrSet<Type*, 4> Visited; - if (!Indices.empty() && !Ty->isSized(&Visited)) + GEPWidth = ValNumEl; + } + Indices.push_back(Val); + } + + SmallPtrSet<Type*, 4> Visited; + if (!Indices.empty() && !Ty->isSized(&Visited)) return error(Loc, "base element of getelementptr must be sized"); - - if (!GetElementPtrInst::getIndexedType(Ty, Indices)) + + if (!GetElementPtrInst::getIndexedType(Ty, Indices)) return error(Loc, "invalid getelementptr indices"); - Inst = GetElementPtrInst::Create(Ty, Ptr, Indices); - if (InBounds) - cast<GetElementPtrInst>(Inst)->setIsInBounds(true); - return AteExtraComma ? InstExtraComma : InstNormal; -} - + Inst = GetElementPtrInst::Create(Ty, Ptr, Indices); + if (InBounds) + cast<GetElementPtrInst>(Inst)->setIsInBounds(true); + return AteExtraComma ? InstExtraComma : InstNormal; +} + /// parseExtractValue -/// ::= 'extractvalue' TypeAndValue (',' uint32)+ +/// ::= 'extractvalue' TypeAndValue (',' uint32)+ int LLParser::parseExtractValue(Instruction *&Inst, PerFunctionState &PFS) { - Value *Val; LocTy Loc; - SmallVector<unsigned, 4> Indices; - bool AteExtraComma; + Value *Val; LocTy Loc; + SmallVector<unsigned, 4> Indices; + bool AteExtraComma; if (parseTypeAndValue(Val, Loc, PFS) || parseIndexList(Indices, AteExtraComma)) - return true; - - if (!Val->getType()->isAggregateType()) + return true; + + if (!Val->getType()->isAggregateType()) return error(Loc, "extractvalue operand must be aggregate type"); - - if (!ExtractValueInst::getIndexedType(Val->getType(), Indices)) + + if (!ExtractValueInst::getIndexedType(Val->getType(), Indices)) return error(Loc, "invalid indices for extractvalue"); - Inst = ExtractValueInst::Create(Val, Indices); - return AteExtraComma ? InstExtraComma : InstNormal; -} - + Inst = ExtractValueInst::Create(Val, Indices); + return AteExtraComma ? InstExtraComma : InstNormal; +} + /// parseInsertValue -/// ::= 'insertvalue' TypeAndValue ',' TypeAndValue (',' uint32)+ +/// ::= 'insertvalue' TypeAndValue ',' TypeAndValue (',' uint32)+ int LLParser::parseInsertValue(Instruction *&Inst, PerFunctionState &PFS) { - Value *Val0, *Val1; LocTy Loc0, Loc1; - SmallVector<unsigned, 4> Indices; - bool AteExtraComma; + Value *Val0, *Val1; LocTy Loc0, Loc1; + SmallVector<unsigned, 4> Indices; + bool AteExtraComma; if (parseTypeAndValue(Val0, Loc0, PFS) || parseToken(lltok::comma, "expected comma after insertvalue operand") || parseTypeAndValue(Val1, Loc1, PFS) || parseIndexList(Indices, AteExtraComma)) - return true; - - if (!Val0->getType()->isAggregateType()) + return true; + + if (!Val0->getType()->isAggregateType()) return error(Loc0, "insertvalue operand must be aggregate type"); - - Type *IndexedType = ExtractValueInst::getIndexedType(Val0->getType(), Indices); - if (!IndexedType) + + Type *IndexedType = ExtractValueInst::getIndexedType(Val0->getType(), Indices); + if (!IndexedType) return error(Loc0, "invalid indices for insertvalue"); - if (IndexedType != Val1->getType()) + if (IndexedType != Val1->getType()) return error(Loc1, "insertvalue operand and field disagree in type: '" + - getTypeString(Val1->getType()) + "' instead of '" + - getTypeString(IndexedType) + "'"); - Inst = InsertValueInst::Create(Val0, Val1, Indices); - return AteExtraComma ? InstExtraComma : InstNormal; -} - -//===----------------------------------------------------------------------===// -// Embedded metadata. -//===----------------------------------------------------------------------===// - + getTypeString(Val1->getType()) + "' instead of '" + + getTypeString(IndexedType) + "'"); + Inst = InsertValueInst::Create(Val0, Val1, Indices); + return AteExtraComma ? InstExtraComma : InstNormal; +} + +//===----------------------------------------------------------------------===// +// Embedded metadata. +//===----------------------------------------------------------------------===// + /// parseMDNodeVector -/// ::= { Element (',' Element)* } -/// Element -/// ::= 'null' | TypeAndValue +/// ::= { Element (',' Element)* } +/// Element +/// ::= 'null' | TypeAndValue bool LLParser::parseMDNodeVector(SmallVectorImpl<Metadata *> &Elts) { if (parseToken(lltok::lbrace, "expected '{' here")) - return true; - - // Check for an empty list. - if (EatIfPresent(lltok::rbrace)) - return false; - - do { - // Null is a special case since it is typeless. - if (EatIfPresent(lltok::kw_null)) { - Elts.push_back(nullptr); - continue; - } - - Metadata *MD; + return true; + + // Check for an empty list. + if (EatIfPresent(lltok::rbrace)) + return false; + + do { + // Null is a special case since it is typeless. + if (EatIfPresent(lltok::kw_null)) { + Elts.push_back(nullptr); + continue; + } + + Metadata *MD; if (parseMetadata(MD, nullptr)) - return true; - Elts.push_back(MD); - } while (EatIfPresent(lltok::comma)); - + return true; + Elts.push_back(MD); + } while (EatIfPresent(lltok::comma)); + return parseToken(lltok::rbrace, "expected end of metadata node"); -} - -//===----------------------------------------------------------------------===// -// Use-list order directives. -//===----------------------------------------------------------------------===// -bool LLParser::sortUseListOrder(Value *V, ArrayRef<unsigned> Indexes, - SMLoc Loc) { - if (V->use_empty()) +} + +//===----------------------------------------------------------------------===// +// Use-list order directives. +//===----------------------------------------------------------------------===// +bool LLParser::sortUseListOrder(Value *V, ArrayRef<unsigned> Indexes, + SMLoc Loc) { + if (V->use_empty()) return error(Loc, "value has no uses"); - - unsigned NumUses = 0; - SmallDenseMap<const Use *, unsigned, 16> Order; - for (const Use &U : V->uses()) { - if (++NumUses > Indexes.size()) - break; - Order[&U] = Indexes[NumUses - 1]; - } - if (NumUses < 2) + + unsigned NumUses = 0; + SmallDenseMap<const Use *, unsigned, 16> Order; + for (const Use &U : V->uses()) { + if (++NumUses > Indexes.size()) + break; + Order[&U] = Indexes[NumUses - 1]; + } + if (NumUses < 2) return error(Loc, "value only has one use"); - if (Order.size() != Indexes.size() || NumUses > Indexes.size()) + if (Order.size() != Indexes.size() || NumUses > Indexes.size()) return error(Loc, - "wrong number of indexes, expected " + Twine(V->getNumUses())); - - V->sortUseList([&](const Use &L, const Use &R) { - return Order.lookup(&L) < Order.lookup(&R); - }); - return false; -} - + "wrong number of indexes, expected " + Twine(V->getNumUses())); + + V->sortUseList([&](const Use &L, const Use &R) { + return Order.lookup(&L) < Order.lookup(&R); + }); + return false; +} + /// parseUseListOrderIndexes -/// ::= '{' uint32 (',' uint32)+ '}' +/// ::= '{' uint32 (',' uint32)+ '}' bool LLParser::parseUseListOrderIndexes(SmallVectorImpl<unsigned> &Indexes) { - SMLoc Loc = Lex.getLoc(); + SMLoc Loc = Lex.getLoc(); if (parseToken(lltok::lbrace, "expected '{' here")) - return true; - if (Lex.getKind() == lltok::rbrace) - return Lex.Error("expected non-empty list of uselistorder indexes"); - - // Use Offset, Max, and IsOrdered to check consistency of indexes. The - // indexes should be distinct numbers in the range [0, size-1], and should - // not be in order. - unsigned Offset = 0; - unsigned Max = 0; - bool IsOrdered = true; - assert(Indexes.empty() && "Expected empty order vector"); - do { - unsigned Index; + return true; + if (Lex.getKind() == lltok::rbrace) + return Lex.Error("expected non-empty list of uselistorder indexes"); + + // Use Offset, Max, and IsOrdered to check consistency of indexes. The + // indexes should be distinct numbers in the range [0, size-1], and should + // not be in order. + unsigned Offset = 0; + unsigned Max = 0; + bool IsOrdered = true; + assert(Indexes.empty() && "Expected empty order vector"); + do { + unsigned Index; if (parseUInt32(Index)) - return true; - - // Update consistency checks. - Offset += Index - Indexes.size(); - Max = std::max(Max, Index); - IsOrdered &= Index == Indexes.size(); - - Indexes.push_back(Index); - } while (EatIfPresent(lltok::comma)); - + return true; + + // Update consistency checks. + Offset += Index - Indexes.size(); + Max = std::max(Max, Index); + IsOrdered &= Index == Indexes.size(); + + Indexes.push_back(Index); + } while (EatIfPresent(lltok::comma)); + if (parseToken(lltok::rbrace, "expected '}' here")) - return true; - - if (Indexes.size() < 2) + return true; + + if (Indexes.size() < 2) return error(Loc, "expected >= 2 uselistorder indexes"); - if (Offset != 0 || Max >= Indexes.size()) + if (Offset != 0 || Max >= Indexes.size()) return error(Loc, "expected distinct uselistorder indexes in range [0, size)"); - if (IsOrdered) + if (IsOrdered) return error(Loc, "expected uselistorder indexes to change the order"); - - return false; -} - + + return false; +} + /// parseUseListOrder -/// ::= 'uselistorder' Type Value ',' UseListOrderIndexes +/// ::= 'uselistorder' Type Value ',' UseListOrderIndexes bool LLParser::parseUseListOrder(PerFunctionState *PFS) { - SMLoc Loc = Lex.getLoc(); + SMLoc Loc = Lex.getLoc(); if (parseToken(lltok::kw_uselistorder, "expected uselistorder directive")) - return true; - - Value *V; - SmallVector<unsigned, 16> Indexes; + return true; + + Value *V; + SmallVector<unsigned, 16> Indexes; if (parseTypeAndValue(V, PFS) || parseToken(lltok::comma, "expected comma in uselistorder directive") || parseUseListOrderIndexes(Indexes)) - return true; - - return sortUseListOrder(V, Indexes, Loc); -} - + return true; + + return sortUseListOrder(V, Indexes, Loc); +} + /// parseUseListOrderBB -/// ::= 'uselistorder_bb' @foo ',' %bar ',' UseListOrderIndexes +/// ::= 'uselistorder_bb' @foo ',' %bar ',' UseListOrderIndexes bool LLParser::parseUseListOrderBB() { - assert(Lex.getKind() == lltok::kw_uselistorder_bb); - SMLoc Loc = Lex.getLoc(); - Lex.Lex(); - - ValID Fn, Label; - SmallVector<unsigned, 16> Indexes; + assert(Lex.getKind() == lltok::kw_uselistorder_bb); + SMLoc Loc = Lex.getLoc(); + Lex.Lex(); + + ValID Fn, Label; + SmallVector<unsigned, 16> Indexes; if (parseValID(Fn) || parseToken(lltok::comma, "expected comma in uselistorder_bb directive") || parseValID(Label) || parseToken(lltok::comma, "expected comma in uselistorder_bb directive") || parseUseListOrderIndexes(Indexes)) - return true; - - // Check the function. - GlobalValue *GV; - if (Fn.Kind == ValID::t_GlobalName) - GV = M->getNamedValue(Fn.StrVal); - else if (Fn.Kind == ValID::t_GlobalID) - GV = Fn.UIntVal < NumberedVals.size() ? NumberedVals[Fn.UIntVal] : nullptr; - else + return true; + + // Check the function. + GlobalValue *GV; + if (Fn.Kind == ValID::t_GlobalName) + GV = M->getNamedValue(Fn.StrVal); + else if (Fn.Kind == ValID::t_GlobalID) + GV = Fn.UIntVal < NumberedVals.size() ? NumberedVals[Fn.UIntVal] : nullptr; + else return error(Fn.Loc, "expected function name in uselistorder_bb"); - if (!GV) + if (!GV) return error(Fn.Loc, "invalid function forward reference in uselistorder_bb"); - auto *F = dyn_cast<Function>(GV); - if (!F) + auto *F = dyn_cast<Function>(GV); + if (!F) return error(Fn.Loc, "expected function name in uselistorder_bb"); - if (F->isDeclaration()) + if (F->isDeclaration()) return error(Fn.Loc, "invalid declaration in uselistorder_bb"); - - // Check the basic block. - if (Label.Kind == ValID::t_LocalID) + + // Check the basic block. + if (Label.Kind == ValID::t_LocalID) return error(Label.Loc, "invalid numeric label in uselistorder_bb"); - if (Label.Kind != ValID::t_LocalName) + if (Label.Kind != ValID::t_LocalName) return error(Label.Loc, "expected basic block name in uselistorder_bb"); - Value *V = F->getValueSymbolTable()->lookup(Label.StrVal); - if (!V) + Value *V = F->getValueSymbolTable()->lookup(Label.StrVal); + if (!V) return error(Label.Loc, "invalid basic block in uselistorder_bb"); - if (!isa<BasicBlock>(V)) + if (!isa<BasicBlock>(V)) return error(Label.Loc, "expected basic block in uselistorder_bb"); - - return sortUseListOrder(V, Indexes, Loc); -} - -/// ModuleEntry -/// ::= 'module' ':' '(' 'path' ':' STRINGCONSTANT ',' 'hash' ':' Hash ')' -/// Hash ::= '(' UInt32 ',' UInt32 ',' UInt32 ',' UInt32 ',' UInt32 ')' + + return sortUseListOrder(V, Indexes, Loc); +} + +/// ModuleEntry +/// ::= 'module' ':' '(' 'path' ':' STRINGCONSTANT ',' 'hash' ':' Hash ')' +/// Hash ::= '(' UInt32 ',' UInt32 ',' UInt32 ',' UInt32 ',' UInt32 ')' bool LLParser::parseModuleEntry(unsigned ID) { - assert(Lex.getKind() == lltok::kw_module); - Lex.Lex(); - - std::string Path; + assert(Lex.getKind() == lltok::kw_module); + Lex.Lex(); + + std::string Path; if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here") || parseToken(lltok::kw_path, "expected 'path' here") || @@ -7887,645 +7887,645 @@ bool LLParser::parseModuleEntry(unsigned ID) { parseToken(lltok::kw_hash, "expected 'hash' here") || parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here")) - return true; - - ModuleHash Hash; + return true; + + ModuleHash Hash; if (parseUInt32(Hash[0]) || parseToken(lltok::comma, "expected ',' here") || parseUInt32(Hash[1]) || parseToken(lltok::comma, "expected ',' here") || parseUInt32(Hash[2]) || parseToken(lltok::comma, "expected ',' here") || parseUInt32(Hash[3]) || parseToken(lltok::comma, "expected ',' here") || parseUInt32(Hash[4])) - return true; - + return true; + if (parseToken(lltok::rparen, "expected ')' here") || parseToken(lltok::rparen, "expected ')' here")) - return true; - - auto ModuleEntry = Index->addModule(Path, ID, Hash); - ModuleIdMap[ID] = ModuleEntry->first(); - - return false; -} - -/// TypeIdEntry -/// ::= 'typeid' ':' '(' 'name' ':' STRINGCONSTANT ',' TypeIdSummary ')' + return true; + + auto ModuleEntry = Index->addModule(Path, ID, Hash); + ModuleIdMap[ID] = ModuleEntry->first(); + + return false; +} + +/// TypeIdEntry +/// ::= 'typeid' ':' '(' 'name' ':' STRINGCONSTANT ',' TypeIdSummary ')' bool LLParser::parseTypeIdEntry(unsigned ID) { - assert(Lex.getKind() == lltok::kw_typeid); - Lex.Lex(); - - std::string Name; + assert(Lex.getKind() == lltok::kw_typeid); + Lex.Lex(); + + std::string Name; if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here") || parseToken(lltok::kw_name, "expected 'name' here") || parseToken(lltok::colon, "expected ':' here") || parseStringConstant(Name)) - return true; - - TypeIdSummary &TIS = Index->getOrInsertTypeIdSummary(Name); + return true; + + TypeIdSummary &TIS = Index->getOrInsertTypeIdSummary(Name); if (parseToken(lltok::comma, "expected ',' here") || parseTypeIdSummary(TIS) || parseToken(lltok::rparen, "expected ')' here")) - return true; - - // Check if this ID was forward referenced, and if so, update the - // corresponding GUIDs. - auto FwdRefTIDs = ForwardRefTypeIds.find(ID); - if (FwdRefTIDs != ForwardRefTypeIds.end()) { - for (auto TIDRef : FwdRefTIDs->second) { - assert(!*TIDRef.first && - "Forward referenced type id GUID expected to be 0"); - *TIDRef.first = GlobalValue::getGUID(Name); - } - ForwardRefTypeIds.erase(FwdRefTIDs); - } - - return false; -} - -/// TypeIdSummary -/// ::= 'summary' ':' '(' TypeTestResolution [',' OptionalWpdResolutions]? ')' + return true; + + // Check if this ID was forward referenced, and if so, update the + // corresponding GUIDs. + auto FwdRefTIDs = ForwardRefTypeIds.find(ID); + if (FwdRefTIDs != ForwardRefTypeIds.end()) { + for (auto TIDRef : FwdRefTIDs->second) { + assert(!*TIDRef.first && + "Forward referenced type id GUID expected to be 0"); + *TIDRef.first = GlobalValue::getGUID(Name); + } + ForwardRefTypeIds.erase(FwdRefTIDs); + } + + return false; +} + +/// TypeIdSummary +/// ::= 'summary' ':' '(' TypeTestResolution [',' OptionalWpdResolutions]? ')' bool LLParser::parseTypeIdSummary(TypeIdSummary &TIS) { if (parseToken(lltok::kw_summary, "expected 'summary' here") || parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here") || parseTypeTestResolution(TIS.TTRes)) - return true; - - if (EatIfPresent(lltok::comma)) { - // Expect optional wpdResolutions field + return true; + + if (EatIfPresent(lltok::comma)) { + // Expect optional wpdResolutions field if (parseOptionalWpdResolutions(TIS.WPDRes)) - return true; - } - + return true; + } + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - return false; -} - -static ValueInfo EmptyVI = - ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8); - -/// TypeIdCompatibleVtableEntry -/// ::= 'typeidCompatibleVTable' ':' '(' 'name' ':' STRINGCONSTANT ',' -/// TypeIdCompatibleVtableInfo -/// ')' + return true; + + return false; +} + +static ValueInfo EmptyVI = + ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8); + +/// TypeIdCompatibleVtableEntry +/// ::= 'typeidCompatibleVTable' ':' '(' 'name' ':' STRINGCONSTANT ',' +/// TypeIdCompatibleVtableInfo +/// ')' bool LLParser::parseTypeIdCompatibleVtableEntry(unsigned ID) { - assert(Lex.getKind() == lltok::kw_typeidCompatibleVTable); - Lex.Lex(); - - std::string Name; + assert(Lex.getKind() == lltok::kw_typeidCompatibleVTable); + Lex.Lex(); + + std::string Name; if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here") || parseToken(lltok::kw_name, "expected 'name' here") || parseToken(lltok::colon, "expected ':' here") || parseStringConstant(Name)) - return true; - - TypeIdCompatibleVtableInfo &TI = - Index->getOrInsertTypeIdCompatibleVtableSummary(Name); + return true; + + TypeIdCompatibleVtableInfo &TI = + Index->getOrInsertTypeIdCompatibleVtableSummary(Name); if (parseToken(lltok::comma, "expected ',' here") || parseToken(lltok::kw_summary, "expected 'summary' here") || parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here")) - return true; - - IdToIndexMapType IdToIndexMap; + return true; + + IdToIndexMapType IdToIndexMap; // parse each call edge - do { - uint64_t Offset; + do { + uint64_t Offset; if (parseToken(lltok::lparen, "expected '(' here") || parseToken(lltok::kw_offset, "expected 'offset' here") || parseToken(lltok::colon, "expected ':' here") || parseUInt64(Offset) || parseToken(lltok::comma, "expected ',' here")) - return true; - - LocTy Loc = Lex.getLoc(); - unsigned GVId; - ValueInfo VI; + return true; + + LocTy Loc = Lex.getLoc(); + unsigned GVId; + ValueInfo VI; if (parseGVReference(VI, GVId)) - return true; - - // Keep track of the TypeIdCompatibleVtableInfo array index needing a - // forward reference. We will save the location of the ValueInfo needing an - // update, but can only do so once the std::vector is finalized. - if (VI == EmptyVI) - IdToIndexMap[GVId].push_back(std::make_pair(TI.size(), Loc)); - TI.push_back({Offset, VI}); - + return true; + + // Keep track of the TypeIdCompatibleVtableInfo array index needing a + // forward reference. We will save the location of the ValueInfo needing an + // update, but can only do so once the std::vector is finalized. + if (VI == EmptyVI) + IdToIndexMap[GVId].push_back(std::make_pair(TI.size(), Loc)); + TI.push_back({Offset, VI}); + if (parseToken(lltok::rparen, "expected ')' in call")) - return true; - } while (EatIfPresent(lltok::comma)); - - // Now that the TI vector is finalized, it is safe to save the locations - // of any forward GV references that need updating later. - for (auto I : IdToIndexMap) { + return true; + } while (EatIfPresent(lltok::comma)); + + // Now that the TI vector is finalized, it is safe to save the locations + // of any forward GV references that need updating later. + for (auto I : IdToIndexMap) { auto &Infos = ForwardRefValueInfos[I.first]; - for (auto P : I.second) { - assert(TI[P.first].VTableVI == EmptyVI && - "Forward referenced ValueInfo expected to be empty"); + for (auto P : I.second) { + assert(TI[P.first].VTableVI == EmptyVI && + "Forward referenced ValueInfo expected to be empty"); Infos.emplace_back(&TI[P.first].VTableVI, P.second); - } - } - + } + } + if (parseToken(lltok::rparen, "expected ')' here") || parseToken(lltok::rparen, "expected ')' here")) - return true; - - // Check if this ID was forward referenced, and if so, update the - // corresponding GUIDs. - auto FwdRefTIDs = ForwardRefTypeIds.find(ID); - if (FwdRefTIDs != ForwardRefTypeIds.end()) { - for (auto TIDRef : FwdRefTIDs->second) { - assert(!*TIDRef.first && - "Forward referenced type id GUID expected to be 0"); - *TIDRef.first = GlobalValue::getGUID(Name); - } - ForwardRefTypeIds.erase(FwdRefTIDs); - } - - return false; -} - -/// TypeTestResolution -/// ::= 'typeTestRes' ':' '(' 'kind' ':' -/// ( 'unsat' | 'byteArray' | 'inline' | 'single' | 'allOnes' ) ',' -/// 'sizeM1BitWidth' ':' SizeM1BitWidth [',' 'alignLog2' ':' UInt64]? -/// [',' 'sizeM1' ':' UInt64]? [',' 'bitMask' ':' UInt8]? -/// [',' 'inlinesBits' ':' UInt64]? ')' + return true; + + // Check if this ID was forward referenced, and if so, update the + // corresponding GUIDs. + auto FwdRefTIDs = ForwardRefTypeIds.find(ID); + if (FwdRefTIDs != ForwardRefTypeIds.end()) { + for (auto TIDRef : FwdRefTIDs->second) { + assert(!*TIDRef.first && + "Forward referenced type id GUID expected to be 0"); + *TIDRef.first = GlobalValue::getGUID(Name); + } + ForwardRefTypeIds.erase(FwdRefTIDs); + } + + return false; +} + +/// TypeTestResolution +/// ::= 'typeTestRes' ':' '(' 'kind' ':' +/// ( 'unsat' | 'byteArray' | 'inline' | 'single' | 'allOnes' ) ',' +/// 'sizeM1BitWidth' ':' SizeM1BitWidth [',' 'alignLog2' ':' UInt64]? +/// [',' 'sizeM1' ':' UInt64]? [',' 'bitMask' ':' UInt8]? +/// [',' 'inlinesBits' ':' UInt64]? ')' bool LLParser::parseTypeTestResolution(TypeTestResolution &TTRes) { if (parseToken(lltok::kw_typeTestRes, "expected 'typeTestRes' here") || parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here") || parseToken(lltok::kw_kind, "expected 'kind' here") || parseToken(lltok::colon, "expected ':' here")) - return true; - - switch (Lex.getKind()) { - case lltok::kw_unknown: - TTRes.TheKind = TypeTestResolution::Unknown; - break; - case lltok::kw_unsat: - TTRes.TheKind = TypeTestResolution::Unsat; - break; - case lltok::kw_byteArray: - TTRes.TheKind = TypeTestResolution::ByteArray; - break; - case lltok::kw_inline: - TTRes.TheKind = TypeTestResolution::Inline; - break; - case lltok::kw_single: - TTRes.TheKind = TypeTestResolution::Single; - break; - case lltok::kw_allOnes: - TTRes.TheKind = TypeTestResolution::AllOnes; - break; - default: + return true; + + switch (Lex.getKind()) { + case lltok::kw_unknown: + TTRes.TheKind = TypeTestResolution::Unknown; + break; + case lltok::kw_unsat: + TTRes.TheKind = TypeTestResolution::Unsat; + break; + case lltok::kw_byteArray: + TTRes.TheKind = TypeTestResolution::ByteArray; + break; + case lltok::kw_inline: + TTRes.TheKind = TypeTestResolution::Inline; + break; + case lltok::kw_single: + TTRes.TheKind = TypeTestResolution::Single; + break; + case lltok::kw_allOnes: + TTRes.TheKind = TypeTestResolution::AllOnes; + break; + default: return error(Lex.getLoc(), "unexpected TypeTestResolution kind"); - } - Lex.Lex(); - + } + Lex.Lex(); + if (parseToken(lltok::comma, "expected ',' here") || parseToken(lltok::kw_sizeM1BitWidth, "expected 'sizeM1BitWidth' here") || parseToken(lltok::colon, "expected ':' here") || parseUInt32(TTRes.SizeM1BitWidth)) - return true; - + return true; + // parse optional fields - while (EatIfPresent(lltok::comma)) { - switch (Lex.getKind()) { - case lltok::kw_alignLog2: - Lex.Lex(); + while (EatIfPresent(lltok::comma)) { + switch (Lex.getKind()) { + case lltok::kw_alignLog2: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseUInt64(TTRes.AlignLog2)) - return true; - break; - case lltok::kw_sizeM1: - Lex.Lex(); + return true; + break; + case lltok::kw_sizeM1: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseUInt64(TTRes.SizeM1)) - return true; - break; - case lltok::kw_bitMask: { - unsigned Val; - Lex.Lex(); + return true; + break; + case lltok::kw_bitMask: { + unsigned Val; + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseUInt32(Val)) - return true; - assert(Val <= 0xff); - TTRes.BitMask = (uint8_t)Val; - break; - } - case lltok::kw_inlineBits: - Lex.Lex(); + return true; + assert(Val <= 0xff); + TTRes.BitMask = (uint8_t)Val; + break; + } + case lltok::kw_inlineBits: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseUInt64(TTRes.InlineBits)) - return true; - break; - default: + return true; + break; + default: return error(Lex.getLoc(), "expected optional TypeTestResolution field"); - } - } - + } + } + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - return false; -} - -/// OptionalWpdResolutions -/// ::= 'wpsResolutions' ':' '(' WpdResolution [',' WpdResolution]* ')' -/// WpdResolution ::= '(' 'offset' ':' UInt64 ',' WpdRes ')' + return true; + + return false; +} + +/// OptionalWpdResolutions +/// ::= 'wpsResolutions' ':' '(' WpdResolution [',' WpdResolution]* ')' +/// WpdResolution ::= '(' 'offset' ':' UInt64 ',' WpdRes ')' bool LLParser::parseOptionalWpdResolutions( - std::map<uint64_t, WholeProgramDevirtResolution> &WPDResMap) { + std::map<uint64_t, WholeProgramDevirtResolution> &WPDResMap) { if (parseToken(lltok::kw_wpdResolutions, "expected 'wpdResolutions' here") || parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here")) - return true; - - do { - uint64_t Offset; - WholeProgramDevirtResolution WPDRes; + return true; + + do { + uint64_t Offset; + WholeProgramDevirtResolution WPDRes; if (parseToken(lltok::lparen, "expected '(' here") || parseToken(lltok::kw_offset, "expected 'offset' here") || parseToken(lltok::colon, "expected ':' here") || parseUInt64(Offset) || parseToken(lltok::comma, "expected ',' here") || parseWpdRes(WPDRes) || parseToken(lltok::rparen, "expected ')' here")) - return true; - WPDResMap[Offset] = WPDRes; - } while (EatIfPresent(lltok::comma)); - + return true; + WPDResMap[Offset] = WPDRes; + } while (EatIfPresent(lltok::comma)); + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - return false; -} - -/// WpdRes -/// ::= 'wpdRes' ':' '(' 'kind' ':' 'indir' -/// [',' OptionalResByArg]? ')' -/// ::= 'wpdRes' ':' '(' 'kind' ':' 'singleImpl' -/// ',' 'singleImplName' ':' STRINGCONSTANT ',' -/// [',' OptionalResByArg]? ')' -/// ::= 'wpdRes' ':' '(' 'kind' ':' 'branchFunnel' -/// [',' OptionalResByArg]? ')' + return true; + + return false; +} + +/// WpdRes +/// ::= 'wpdRes' ':' '(' 'kind' ':' 'indir' +/// [',' OptionalResByArg]? ')' +/// ::= 'wpdRes' ':' '(' 'kind' ':' 'singleImpl' +/// ',' 'singleImplName' ':' STRINGCONSTANT ',' +/// [',' OptionalResByArg]? ')' +/// ::= 'wpdRes' ':' '(' 'kind' ':' 'branchFunnel' +/// [',' OptionalResByArg]? ')' bool LLParser::parseWpdRes(WholeProgramDevirtResolution &WPDRes) { if (parseToken(lltok::kw_wpdRes, "expected 'wpdRes' here") || parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here") || parseToken(lltok::kw_kind, "expected 'kind' here") || parseToken(lltok::colon, "expected ':' here")) - return true; - - switch (Lex.getKind()) { - case lltok::kw_indir: - WPDRes.TheKind = WholeProgramDevirtResolution::Indir; - break; - case lltok::kw_singleImpl: - WPDRes.TheKind = WholeProgramDevirtResolution::SingleImpl; - break; - case lltok::kw_branchFunnel: - WPDRes.TheKind = WholeProgramDevirtResolution::BranchFunnel; - break; - default: + return true; + + switch (Lex.getKind()) { + case lltok::kw_indir: + WPDRes.TheKind = WholeProgramDevirtResolution::Indir; + break; + case lltok::kw_singleImpl: + WPDRes.TheKind = WholeProgramDevirtResolution::SingleImpl; + break; + case lltok::kw_branchFunnel: + WPDRes.TheKind = WholeProgramDevirtResolution::BranchFunnel; + break; + default: return error(Lex.getLoc(), "unexpected WholeProgramDevirtResolution kind"); - } - Lex.Lex(); - + } + Lex.Lex(); + // parse optional fields - while (EatIfPresent(lltok::comma)) { - switch (Lex.getKind()) { - case lltok::kw_singleImplName: - Lex.Lex(); + while (EatIfPresent(lltok::comma)) { + switch (Lex.getKind()) { + case lltok::kw_singleImplName: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':' here") || parseStringConstant(WPDRes.SingleImplName)) - return true; - break; - case lltok::kw_resByArg: + return true; + break; + case lltok::kw_resByArg: if (parseOptionalResByArg(WPDRes.ResByArg)) - return true; - break; - default: + return true; + break; + default: return error(Lex.getLoc(), - "expected optional WholeProgramDevirtResolution field"); - } - } - + "expected optional WholeProgramDevirtResolution field"); + } + } + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - return false; -} - -/// OptionalResByArg -/// ::= 'wpdRes' ':' '(' ResByArg[, ResByArg]* ')' -/// ResByArg ::= Args ',' 'byArg' ':' '(' 'kind' ':' -/// ( 'indir' | 'uniformRetVal' | 'UniqueRetVal' | -/// 'virtualConstProp' ) -/// [',' 'info' ':' UInt64]? [',' 'byte' ':' UInt32]? -/// [',' 'bit' ':' UInt32]? ')' + return true; + + return false; +} + +/// OptionalResByArg +/// ::= 'wpdRes' ':' '(' ResByArg[, ResByArg]* ')' +/// ResByArg ::= Args ',' 'byArg' ':' '(' 'kind' ':' +/// ( 'indir' | 'uniformRetVal' | 'UniqueRetVal' | +/// 'virtualConstProp' ) +/// [',' 'info' ':' UInt64]? [',' 'byte' ':' UInt32]? +/// [',' 'bit' ':' UInt32]? ')' bool LLParser::parseOptionalResByArg( - std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg> - &ResByArg) { + std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg> + &ResByArg) { if (parseToken(lltok::kw_resByArg, "expected 'resByArg' here") || parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here")) - return true; - - do { - std::vector<uint64_t> Args; + return true; + + do { + std::vector<uint64_t> Args; if (parseArgs(Args) || parseToken(lltok::comma, "expected ',' here") || parseToken(lltok::kw_byArg, "expected 'byArg here") || parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here") || parseToken(lltok::kw_kind, "expected 'kind' here") || parseToken(lltok::colon, "expected ':' here")) - return true; - - WholeProgramDevirtResolution::ByArg ByArg; - switch (Lex.getKind()) { - case lltok::kw_indir: - ByArg.TheKind = WholeProgramDevirtResolution::ByArg::Indir; - break; - case lltok::kw_uniformRetVal: - ByArg.TheKind = WholeProgramDevirtResolution::ByArg::UniformRetVal; - break; - case lltok::kw_uniqueRetVal: - ByArg.TheKind = WholeProgramDevirtResolution::ByArg::UniqueRetVal; - break; - case lltok::kw_virtualConstProp: - ByArg.TheKind = WholeProgramDevirtResolution::ByArg::VirtualConstProp; - break; - default: + return true; + + WholeProgramDevirtResolution::ByArg ByArg; + switch (Lex.getKind()) { + case lltok::kw_indir: + ByArg.TheKind = WholeProgramDevirtResolution::ByArg::Indir; + break; + case lltok::kw_uniformRetVal: + ByArg.TheKind = WholeProgramDevirtResolution::ByArg::UniformRetVal; + break; + case lltok::kw_uniqueRetVal: + ByArg.TheKind = WholeProgramDevirtResolution::ByArg::UniqueRetVal; + break; + case lltok::kw_virtualConstProp: + ByArg.TheKind = WholeProgramDevirtResolution::ByArg::VirtualConstProp; + break; + default: return error(Lex.getLoc(), - "unexpected WholeProgramDevirtResolution::ByArg kind"); - } - Lex.Lex(); - + "unexpected WholeProgramDevirtResolution::ByArg kind"); + } + Lex.Lex(); + // parse optional fields - while (EatIfPresent(lltok::comma)) { - switch (Lex.getKind()) { - case lltok::kw_info: - Lex.Lex(); + while (EatIfPresent(lltok::comma)) { + switch (Lex.getKind()) { + case lltok::kw_info: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':' here") || parseUInt64(ByArg.Info)) - return true; - break; - case lltok::kw_byte: - Lex.Lex(); + return true; + break; + case lltok::kw_byte: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':' here") || parseUInt32(ByArg.Byte)) - return true; - break; - case lltok::kw_bit: - Lex.Lex(); + return true; + break; + case lltok::kw_bit: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':' here") || parseUInt32(ByArg.Bit)) - return true; - break; - default: + return true; + break; + default: return error(Lex.getLoc(), - "expected optional whole program devirt field"); - } - } - + "expected optional whole program devirt field"); + } + } + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - ResByArg[Args] = ByArg; - } while (EatIfPresent(lltok::comma)); - + return true; + + ResByArg[Args] = ByArg; + } while (EatIfPresent(lltok::comma)); + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - return false; -} - -/// OptionalResByArg -/// ::= 'args' ':' '(' UInt64[, UInt64]* ')' + return true; + + return false; +} + +/// OptionalResByArg +/// ::= 'args' ':' '(' UInt64[, UInt64]* ')' bool LLParser::parseArgs(std::vector<uint64_t> &Args) { if (parseToken(lltok::kw_args, "expected 'args' here") || parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here")) - return true; - - do { - uint64_t Val; + return true; + + do { + uint64_t Val; if (parseUInt64(Val)) - return true; - Args.push_back(Val); - } while (EatIfPresent(lltok::comma)); - + return true; + Args.push_back(Val); + } while (EatIfPresent(lltok::comma)); + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - return false; -} - -static const auto FwdVIRef = (GlobalValueSummaryMapTy::value_type *)-8; - -static void resolveFwdRef(ValueInfo *Fwd, ValueInfo &Resolved) { - bool ReadOnly = Fwd->isReadOnly(); - bool WriteOnly = Fwd->isWriteOnly(); - assert(!(ReadOnly && WriteOnly)); - *Fwd = Resolved; - if (ReadOnly) - Fwd->setReadOnly(); - if (WriteOnly) - Fwd->setWriteOnly(); -} - -/// Stores the given Name/GUID and associated summary into the Index. -/// Also updates any forward references to the associated entry ID. + return true; + + return false; +} + +static const auto FwdVIRef = (GlobalValueSummaryMapTy::value_type *)-8; + +static void resolveFwdRef(ValueInfo *Fwd, ValueInfo &Resolved) { + bool ReadOnly = Fwd->isReadOnly(); + bool WriteOnly = Fwd->isWriteOnly(); + assert(!(ReadOnly && WriteOnly)); + *Fwd = Resolved; + if (ReadOnly) + Fwd->setReadOnly(); + if (WriteOnly) + Fwd->setWriteOnly(); +} + +/// Stores the given Name/GUID and associated summary into the Index. +/// Also updates any forward references to the associated entry ID. void LLParser::addGlobalValueToIndex( - std::string Name, GlobalValue::GUID GUID, GlobalValue::LinkageTypes Linkage, - unsigned ID, std::unique_ptr<GlobalValueSummary> Summary) { - // First create the ValueInfo utilizing the Name or GUID. - ValueInfo VI; - if (GUID != 0) { - assert(Name.empty()); - VI = Index->getOrInsertValueInfo(GUID); - } else { - assert(!Name.empty()); - if (M) { - auto *GV = M->getNamedValue(Name); - assert(GV); - VI = Index->getOrInsertValueInfo(GV); - } else { - assert( - (!GlobalValue::isLocalLinkage(Linkage) || !SourceFileName.empty()) && - "Need a source_filename to compute GUID for local"); - GUID = GlobalValue::getGUID( - GlobalValue::getGlobalIdentifier(Name, Linkage, SourceFileName)); - VI = Index->getOrInsertValueInfo(GUID, Index->saveString(Name)); - } - } - - // Resolve forward references from calls/refs - auto FwdRefVIs = ForwardRefValueInfos.find(ID); - if (FwdRefVIs != ForwardRefValueInfos.end()) { - for (auto VIRef : FwdRefVIs->second) { - assert(VIRef.first->getRef() == FwdVIRef && - "Forward referenced ValueInfo expected to be empty"); - resolveFwdRef(VIRef.first, VI); - } - ForwardRefValueInfos.erase(FwdRefVIs); - } - - // Resolve forward references from aliases - auto FwdRefAliasees = ForwardRefAliasees.find(ID); - if (FwdRefAliasees != ForwardRefAliasees.end()) { - for (auto AliaseeRef : FwdRefAliasees->second) { - assert(!AliaseeRef.first->hasAliasee() && - "Forward referencing alias already has aliasee"); - assert(Summary && "Aliasee must be a definition"); - AliaseeRef.first->setAliasee(VI, Summary.get()); - } - ForwardRefAliasees.erase(FwdRefAliasees); - } - - // Add the summary if one was provided. - if (Summary) - Index->addGlobalValueSummary(VI, std::move(Summary)); - - // Save the associated ValueInfo for use in later references by ID. - if (ID == NumberedValueInfos.size()) - NumberedValueInfos.push_back(VI); - else { - // Handle non-continuous numbers (to make test simplification easier). - if (ID > NumberedValueInfos.size()) - NumberedValueInfos.resize(ID + 1); - NumberedValueInfos[ID] = VI; - } -} - + std::string Name, GlobalValue::GUID GUID, GlobalValue::LinkageTypes Linkage, + unsigned ID, std::unique_ptr<GlobalValueSummary> Summary) { + // First create the ValueInfo utilizing the Name or GUID. + ValueInfo VI; + if (GUID != 0) { + assert(Name.empty()); + VI = Index->getOrInsertValueInfo(GUID); + } else { + assert(!Name.empty()); + if (M) { + auto *GV = M->getNamedValue(Name); + assert(GV); + VI = Index->getOrInsertValueInfo(GV); + } else { + assert( + (!GlobalValue::isLocalLinkage(Linkage) || !SourceFileName.empty()) && + "Need a source_filename to compute GUID for local"); + GUID = GlobalValue::getGUID( + GlobalValue::getGlobalIdentifier(Name, Linkage, SourceFileName)); + VI = Index->getOrInsertValueInfo(GUID, Index->saveString(Name)); + } + } + + // Resolve forward references from calls/refs + auto FwdRefVIs = ForwardRefValueInfos.find(ID); + if (FwdRefVIs != ForwardRefValueInfos.end()) { + for (auto VIRef : FwdRefVIs->second) { + assert(VIRef.first->getRef() == FwdVIRef && + "Forward referenced ValueInfo expected to be empty"); + resolveFwdRef(VIRef.first, VI); + } + ForwardRefValueInfos.erase(FwdRefVIs); + } + + // Resolve forward references from aliases + auto FwdRefAliasees = ForwardRefAliasees.find(ID); + if (FwdRefAliasees != ForwardRefAliasees.end()) { + for (auto AliaseeRef : FwdRefAliasees->second) { + assert(!AliaseeRef.first->hasAliasee() && + "Forward referencing alias already has aliasee"); + assert(Summary && "Aliasee must be a definition"); + AliaseeRef.first->setAliasee(VI, Summary.get()); + } + ForwardRefAliasees.erase(FwdRefAliasees); + } + + // Add the summary if one was provided. + if (Summary) + Index->addGlobalValueSummary(VI, std::move(Summary)); + + // Save the associated ValueInfo for use in later references by ID. + if (ID == NumberedValueInfos.size()) + NumberedValueInfos.push_back(VI); + else { + // Handle non-continuous numbers (to make test simplification easier). + if (ID > NumberedValueInfos.size()) + NumberedValueInfos.resize(ID + 1); + NumberedValueInfos[ID] = VI; + } +} + /// parseSummaryIndexFlags -/// ::= 'flags' ':' UInt64 +/// ::= 'flags' ':' UInt64 bool LLParser::parseSummaryIndexFlags() { - assert(Lex.getKind() == lltok::kw_flags); - Lex.Lex(); - + assert(Lex.getKind() == lltok::kw_flags); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' here")) - return true; - uint64_t Flags; + return true; + uint64_t Flags; if (parseUInt64(Flags)) - return true; + return true; if (Index) Index->setFlags(Flags); - return false; -} - + return false; +} + /// parseBlockCount -/// ::= 'blockcount' ':' UInt64 +/// ::= 'blockcount' ':' UInt64 bool LLParser::parseBlockCount() { - assert(Lex.getKind() == lltok::kw_blockcount); - Lex.Lex(); - + assert(Lex.getKind() == lltok::kw_blockcount); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' here")) - return true; - uint64_t BlockCount; + return true; + uint64_t BlockCount; if (parseUInt64(BlockCount)) - return true; + return true; if (Index) Index->setBlockCount(BlockCount); - return false; -} - + return false; +} + /// parseGVEntry -/// ::= 'gv' ':' '(' ('name' ':' STRINGCONSTANT | 'guid' ':' UInt64) -/// [',' 'summaries' ':' Summary[',' Summary]* ]? ')' -/// Summary ::= '(' (FunctionSummary | VariableSummary | AliasSummary) ')' +/// ::= 'gv' ':' '(' ('name' ':' STRINGCONSTANT | 'guid' ':' UInt64) +/// [',' 'summaries' ':' Summary[',' Summary]* ]? ')' +/// Summary ::= '(' (FunctionSummary | VariableSummary | AliasSummary) ')' bool LLParser::parseGVEntry(unsigned ID) { - assert(Lex.getKind() == lltok::kw_gv); - Lex.Lex(); - + assert(Lex.getKind() == lltok::kw_gv); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here")) - return true; - - std::string Name; - GlobalValue::GUID GUID = 0; - switch (Lex.getKind()) { - case lltok::kw_name: - Lex.Lex(); + return true; + + std::string Name; + GlobalValue::GUID GUID = 0; + switch (Lex.getKind()) { + case lltok::kw_name: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':' here") || parseStringConstant(Name)) - return true; - // Can't create GUID/ValueInfo until we have the linkage. - break; - case lltok::kw_guid: - Lex.Lex(); + return true; + // Can't create GUID/ValueInfo until we have the linkage. + break; + case lltok::kw_guid: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':' here") || parseUInt64(GUID)) - return true; - break; - default: + return true; + break; + default: return error(Lex.getLoc(), "expected name or guid tag"); - } - - if (!EatIfPresent(lltok::comma)) { - // No summaries. Wrap up. + } + + if (!EatIfPresent(lltok::comma)) { + // No summaries. Wrap up. if (parseToken(lltok::rparen, "expected ')' here")) - return true; - // This was created for a call to an external or indirect target. - // A GUID with no summary came from a VALUE_GUID record, dummy GUID - // created for indirect calls with VP. A Name with no GUID came from - // an external definition. We pass ExternalLinkage since that is only - // used when the GUID must be computed from Name, and in that case - // the symbol must have external linkage. + return true; + // This was created for a call to an external or indirect target. + // A GUID with no summary came from a VALUE_GUID record, dummy GUID + // created for indirect calls with VP. A Name with no GUID came from + // an external definition. We pass ExternalLinkage since that is only + // used when the GUID must be computed from Name, and in that case + // the symbol must have external linkage. addGlobalValueToIndex(Name, GUID, GlobalValue::ExternalLinkage, ID, - nullptr); - return false; - } - - // Have a list of summaries + nullptr); + return false; + } + + // Have a list of summaries if (parseToken(lltok::kw_summaries, "expected 'summaries' here") || parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here")) - return true; - do { - switch (Lex.getKind()) { - case lltok::kw_function: + return true; + do { + switch (Lex.getKind()) { + case lltok::kw_function: if (parseFunctionSummary(Name, GUID, ID)) - return true; - break; - case lltok::kw_variable: + return true; + break; + case lltok::kw_variable: if (parseVariableSummary(Name, GUID, ID)) - return true; - break; - case lltok::kw_alias: + return true; + break; + case lltok::kw_alias: if (parseAliasSummary(Name, GUID, ID)) - return true; - break; - default: + return true; + break; + default: return error(Lex.getLoc(), "expected summary type"); - } - } while (EatIfPresent(lltok::comma)); - + } + } while (EatIfPresent(lltok::comma)); + if (parseToken(lltok::rparen, "expected ')' here") || parseToken(lltok::rparen, "expected ')' here")) - return true; - - return false; -} - -/// FunctionSummary -/// ::= 'function' ':' '(' 'module' ':' ModuleReference ',' GVFlags -/// ',' 'insts' ':' UInt32 [',' OptionalFFlags]? [',' OptionalCalls]? -/// [',' OptionalTypeIdInfo]? [',' OptionalParamAccesses]? -/// [',' OptionalRefs]? ')' + return true; + + return false; +} + +/// FunctionSummary +/// ::= 'function' ':' '(' 'module' ':' ModuleReference ',' GVFlags +/// ',' 'insts' ':' UInt32 [',' OptionalFFlags]? [',' OptionalCalls]? +/// [',' OptionalTypeIdInfo]? [',' OptionalParamAccesses]? +/// [',' OptionalRefs]? ')' bool LLParser::parseFunctionSummary(std::string Name, GlobalValue::GUID GUID, - unsigned ID) { - assert(Lex.getKind() == lltok::kw_function); - Lex.Lex(); - - StringRef ModulePath; - GlobalValueSummary::GVFlags GVFlags = GlobalValueSummary::GVFlags( - /*Linkage=*/GlobalValue::ExternalLinkage, /*NotEligibleToImport=*/false, - /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false); - unsigned InstCount; - std::vector<FunctionSummary::EdgeTy> Calls; - FunctionSummary::TypeIdInfo TypeIdInfo; - std::vector<FunctionSummary::ParamAccess> ParamAccesses; - std::vector<ValueInfo> Refs; - // Default is all-zeros (conservative values). - FunctionSummary::FFlags FFlags = {}; + unsigned ID) { + assert(Lex.getKind() == lltok::kw_function); + Lex.Lex(); + + StringRef ModulePath; + GlobalValueSummary::GVFlags GVFlags = GlobalValueSummary::GVFlags( + /*Linkage=*/GlobalValue::ExternalLinkage, /*NotEligibleToImport=*/false, + /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false); + unsigned InstCount; + std::vector<FunctionSummary::EdgeTy> Calls; + FunctionSummary::TypeIdInfo TypeIdInfo; + std::vector<FunctionSummary::ParamAccess> ParamAccesses; + std::vector<ValueInfo> Refs; + // Default is all-zeros (conservative values). + FunctionSummary::FFlags FFlags = {}; if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here") || parseModuleReference(ModulePath) || @@ -8533,126 +8533,126 @@ bool LLParser::parseFunctionSummary(std::string Name, GlobalValue::GUID GUID, parseToken(lltok::comma, "expected ',' here") || parseToken(lltok::kw_insts, "expected 'insts' here") || parseToken(lltok::colon, "expected ':' here") || parseUInt32(InstCount)) - return true; - + return true; + // parse optional fields - while (EatIfPresent(lltok::comma)) { - switch (Lex.getKind()) { - case lltok::kw_funcFlags: + while (EatIfPresent(lltok::comma)) { + switch (Lex.getKind()) { + case lltok::kw_funcFlags: if (parseOptionalFFlags(FFlags)) - return true; - break; - case lltok::kw_calls: + return true; + break; + case lltok::kw_calls: if (parseOptionalCalls(Calls)) - return true; - break; - case lltok::kw_typeIdInfo: + return true; + break; + case lltok::kw_typeIdInfo: if (parseOptionalTypeIdInfo(TypeIdInfo)) - return true; - break; - case lltok::kw_refs: + return true; + break; + case lltok::kw_refs: if (parseOptionalRefs(Refs)) - return true; - break; - case lltok::kw_params: + return true; + break; + case lltok::kw_params: if (parseOptionalParamAccesses(ParamAccesses)) - return true; - break; - default: + return true; + break; + default: return error(Lex.getLoc(), "expected optional function summary field"); - } - } - + } + } + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - auto FS = std::make_unique<FunctionSummary>( - GVFlags, InstCount, FFlags, /*EntryCount=*/0, std::move(Refs), - std::move(Calls), std::move(TypeIdInfo.TypeTests), - std::move(TypeIdInfo.TypeTestAssumeVCalls), - std::move(TypeIdInfo.TypeCheckedLoadVCalls), - std::move(TypeIdInfo.TypeTestAssumeConstVCalls), - std::move(TypeIdInfo.TypeCheckedLoadConstVCalls), - std::move(ParamAccesses)); - - FS->setModulePath(ModulePath); - + return true; + + auto FS = std::make_unique<FunctionSummary>( + GVFlags, InstCount, FFlags, /*EntryCount=*/0, std::move(Refs), + std::move(Calls), std::move(TypeIdInfo.TypeTests), + std::move(TypeIdInfo.TypeTestAssumeVCalls), + std::move(TypeIdInfo.TypeCheckedLoadVCalls), + std::move(TypeIdInfo.TypeTestAssumeConstVCalls), + std::move(TypeIdInfo.TypeCheckedLoadConstVCalls), + std::move(ParamAccesses)); + + FS->setModulePath(ModulePath); + addGlobalValueToIndex(Name, GUID, (GlobalValue::LinkageTypes)GVFlags.Linkage, - ID, std::move(FS)); - - return false; -} - -/// VariableSummary -/// ::= 'variable' ':' '(' 'module' ':' ModuleReference ',' GVFlags -/// [',' OptionalRefs]? ')' + ID, std::move(FS)); + + return false; +} + +/// VariableSummary +/// ::= 'variable' ':' '(' 'module' ':' ModuleReference ',' GVFlags +/// [',' OptionalRefs]? ')' bool LLParser::parseVariableSummary(std::string Name, GlobalValue::GUID GUID, - unsigned ID) { - assert(Lex.getKind() == lltok::kw_variable); - Lex.Lex(); - - StringRef ModulePath; - GlobalValueSummary::GVFlags GVFlags = GlobalValueSummary::GVFlags( - /*Linkage=*/GlobalValue::ExternalLinkage, /*NotEligibleToImport=*/false, - /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false); - GlobalVarSummary::GVarFlags GVarFlags(/*ReadOnly*/ false, - /* WriteOnly */ false, - /* Constant */ false, - GlobalObject::VCallVisibilityPublic); - std::vector<ValueInfo> Refs; - VTableFuncList VTableFuncs; + unsigned ID) { + assert(Lex.getKind() == lltok::kw_variable); + Lex.Lex(); + + StringRef ModulePath; + GlobalValueSummary::GVFlags GVFlags = GlobalValueSummary::GVFlags( + /*Linkage=*/GlobalValue::ExternalLinkage, /*NotEligibleToImport=*/false, + /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false); + GlobalVarSummary::GVarFlags GVarFlags(/*ReadOnly*/ false, + /* WriteOnly */ false, + /* Constant */ false, + GlobalObject::VCallVisibilityPublic); + std::vector<ValueInfo> Refs; + VTableFuncList VTableFuncs; if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here") || parseModuleReference(ModulePath) || parseToken(lltok::comma, "expected ',' here") || parseGVFlags(GVFlags) || parseToken(lltok::comma, "expected ',' here") || parseGVarFlags(GVarFlags)) - return true; - + return true; + // parse optional fields - while (EatIfPresent(lltok::comma)) { - switch (Lex.getKind()) { - case lltok::kw_vTableFuncs: + while (EatIfPresent(lltok::comma)) { + switch (Lex.getKind()) { + case lltok::kw_vTableFuncs: if (parseOptionalVTableFuncs(VTableFuncs)) - return true; - break; - case lltok::kw_refs: + return true; + break; + case lltok::kw_refs: if (parseOptionalRefs(Refs)) - return true; - break; - default: + return true; + break; + default: return error(Lex.getLoc(), "expected optional variable summary field"); - } - } - + } + } + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - auto GS = - std::make_unique<GlobalVarSummary>(GVFlags, GVarFlags, std::move(Refs)); - - GS->setModulePath(ModulePath); - GS->setVTableFuncs(std::move(VTableFuncs)); - + return true; + + auto GS = + std::make_unique<GlobalVarSummary>(GVFlags, GVarFlags, std::move(Refs)); + + GS->setModulePath(ModulePath); + GS->setVTableFuncs(std::move(VTableFuncs)); + addGlobalValueToIndex(Name, GUID, (GlobalValue::LinkageTypes)GVFlags.Linkage, - ID, std::move(GS)); - - return false; -} - -/// AliasSummary -/// ::= 'alias' ':' '(' 'module' ':' ModuleReference ',' GVFlags ',' -/// 'aliasee' ':' GVReference ')' + ID, std::move(GS)); + + return false; +} + +/// AliasSummary +/// ::= 'alias' ':' '(' 'module' ':' ModuleReference ',' GVFlags ',' +/// 'aliasee' ':' GVReference ')' bool LLParser::parseAliasSummary(std::string Name, GlobalValue::GUID GUID, - unsigned ID) { - assert(Lex.getKind() == lltok::kw_alias); - LocTy Loc = Lex.getLoc(); - Lex.Lex(); - - StringRef ModulePath; - GlobalValueSummary::GVFlags GVFlags = GlobalValueSummary::GVFlags( - /*Linkage=*/GlobalValue::ExternalLinkage, /*NotEligibleToImport=*/false, - /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false); + unsigned ID) { + assert(Lex.getKind() == lltok::kw_alias); + LocTy Loc = Lex.getLoc(); + Lex.Lex(); + + StringRef ModulePath; + GlobalValueSummary::GVFlags GVFlags = GlobalValueSummary::GVFlags( + /*Linkage=*/GlobalValue::ExternalLinkage, /*NotEligibleToImport=*/false, + /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false); if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here") || parseModuleReference(ModulePath) || @@ -8660,387 +8660,387 @@ bool LLParser::parseAliasSummary(std::string Name, GlobalValue::GUID GUID, parseToken(lltok::comma, "expected ',' here") || parseToken(lltok::kw_aliasee, "expected 'aliasee' here") || parseToken(lltok::colon, "expected ':' here")) - return true; - - ValueInfo AliaseeVI; - unsigned GVId; + return true; + + ValueInfo AliaseeVI; + unsigned GVId; if (parseGVReference(AliaseeVI, GVId)) - return true; - + return true; + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - auto AS = std::make_unique<AliasSummary>(GVFlags); - - AS->setModulePath(ModulePath); - - // Record forward reference if the aliasee is not parsed yet. - if (AliaseeVI.getRef() == FwdVIRef) { + return true; + + auto AS = std::make_unique<AliasSummary>(GVFlags); + + AS->setModulePath(ModulePath); + + // Record forward reference if the aliasee is not parsed yet. + if (AliaseeVI.getRef() == FwdVIRef) { ForwardRefAliasees[GVId].emplace_back(AS.get(), Loc); - } else { - auto Summary = Index->findSummaryInModule(AliaseeVI, ModulePath); - assert(Summary && "Aliasee must be a definition"); - AS->setAliasee(AliaseeVI, Summary); - } - + } else { + auto Summary = Index->findSummaryInModule(AliaseeVI, ModulePath); + assert(Summary && "Aliasee must be a definition"); + AS->setAliasee(AliaseeVI, Summary); + } + addGlobalValueToIndex(Name, GUID, (GlobalValue::LinkageTypes)GVFlags.Linkage, - ID, std::move(AS)); - - return false; -} - -/// Flag -/// ::= [0|1] + ID, std::move(AS)); + + return false; +} + +/// Flag +/// ::= [0|1] bool LLParser::parseFlag(unsigned &Val) { - if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) return tokError("expected integer"); - Val = (unsigned)Lex.getAPSIntVal().getBoolValue(); - Lex.Lex(); - return false; -} - -/// OptionalFFlags -/// := 'funcFlags' ':' '(' ['readNone' ':' Flag]? -/// [',' 'readOnly' ':' Flag]? [',' 'noRecurse' ':' Flag]? -/// [',' 'returnDoesNotAlias' ':' Flag]? ')' -/// [',' 'noInline' ':' Flag]? ')' -/// [',' 'alwaysInline' ':' Flag]? ')' - + Val = (unsigned)Lex.getAPSIntVal().getBoolValue(); + Lex.Lex(); + return false; +} + +/// OptionalFFlags +/// := 'funcFlags' ':' '(' ['readNone' ':' Flag]? +/// [',' 'readOnly' ':' Flag]? [',' 'noRecurse' ':' Flag]? +/// [',' 'returnDoesNotAlias' ':' Flag]? ')' +/// [',' 'noInline' ':' Flag]? ')' +/// [',' 'alwaysInline' ':' Flag]? ')' + bool LLParser::parseOptionalFFlags(FunctionSummary::FFlags &FFlags) { - assert(Lex.getKind() == lltok::kw_funcFlags); - Lex.Lex(); - + assert(Lex.getKind() == lltok::kw_funcFlags); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' in funcFlags") | parseToken(lltok::lparen, "expected '(' in funcFlags")) - return true; - - do { - unsigned Val = 0; - switch (Lex.getKind()) { - case lltok::kw_readNone: - Lex.Lex(); + return true; + + do { + unsigned Val = 0; + switch (Lex.getKind()) { + case lltok::kw_readNone: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseFlag(Val)) - return true; - FFlags.ReadNone = Val; - break; - case lltok::kw_readOnly: - Lex.Lex(); + return true; + FFlags.ReadNone = Val; + break; + case lltok::kw_readOnly: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseFlag(Val)) - return true; - FFlags.ReadOnly = Val; - break; - case lltok::kw_noRecurse: - Lex.Lex(); + return true; + FFlags.ReadOnly = Val; + break; + case lltok::kw_noRecurse: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseFlag(Val)) - return true; - FFlags.NoRecurse = Val; - break; - case lltok::kw_returnDoesNotAlias: - Lex.Lex(); + return true; + FFlags.NoRecurse = Val; + break; + case lltok::kw_returnDoesNotAlias: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseFlag(Val)) - return true; - FFlags.ReturnDoesNotAlias = Val; - break; - case lltok::kw_noInline: - Lex.Lex(); + return true; + FFlags.ReturnDoesNotAlias = Val; + break; + case lltok::kw_noInline: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseFlag(Val)) - return true; - FFlags.NoInline = Val; - break; - case lltok::kw_alwaysInline: - Lex.Lex(); + return true; + FFlags.NoInline = Val; + break; + case lltok::kw_alwaysInline: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseFlag(Val)) - return true; - FFlags.AlwaysInline = Val; - break; - default: + return true; + FFlags.AlwaysInline = Val; + break; + default: return error(Lex.getLoc(), "expected function flag type"); - } - } while (EatIfPresent(lltok::comma)); - + } + } while (EatIfPresent(lltok::comma)); + if (parseToken(lltok::rparen, "expected ')' in funcFlags")) - return true; - - return false; -} - -/// OptionalCalls -/// := 'calls' ':' '(' Call [',' Call]* ')' -/// Call ::= '(' 'callee' ':' GVReference -/// [( ',' 'hotness' ':' Hotness | ',' 'relbf' ':' UInt32 )]? ')' + return true; + + return false; +} + +/// OptionalCalls +/// := 'calls' ':' '(' Call [',' Call]* ')' +/// Call ::= '(' 'callee' ':' GVReference +/// [( ',' 'hotness' ':' Hotness | ',' 'relbf' ':' UInt32 )]? ')' bool LLParser::parseOptionalCalls(std::vector<FunctionSummary::EdgeTy> &Calls) { - assert(Lex.getKind() == lltok::kw_calls); - Lex.Lex(); - + assert(Lex.getKind() == lltok::kw_calls); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' in calls") | parseToken(lltok::lparen, "expected '(' in calls")) - return true; - - IdToIndexMapType IdToIndexMap; + return true; + + IdToIndexMapType IdToIndexMap; // parse each call edge - do { - ValueInfo VI; + do { + ValueInfo VI; if (parseToken(lltok::lparen, "expected '(' in call") || parseToken(lltok::kw_callee, "expected 'callee' in call") || parseToken(lltok::colon, "expected ':'")) - return true; - - LocTy Loc = Lex.getLoc(); - unsigned GVId; + return true; + + LocTy Loc = Lex.getLoc(); + unsigned GVId; if (parseGVReference(VI, GVId)) - return true; - - CalleeInfo::HotnessType Hotness = CalleeInfo::HotnessType::Unknown; - unsigned RelBF = 0; - if (EatIfPresent(lltok::comma)) { - // Expect either hotness or relbf - if (EatIfPresent(lltok::kw_hotness)) { + return true; + + CalleeInfo::HotnessType Hotness = CalleeInfo::HotnessType::Unknown; + unsigned RelBF = 0; + if (EatIfPresent(lltok::comma)) { + // Expect either hotness or relbf + if (EatIfPresent(lltok::kw_hotness)) { if (parseToken(lltok::colon, "expected ':'") || parseHotness(Hotness)) - return true; - } else { + return true; + } else { if (parseToken(lltok::kw_relbf, "expected relbf") || parseToken(lltok::colon, "expected ':'") || parseUInt32(RelBF)) - return true; - } - } - // Keep track of the Call array index needing a forward reference. - // We will save the location of the ValueInfo needing an update, but - // can only do so once the std::vector is finalized. - if (VI.getRef() == FwdVIRef) - IdToIndexMap[GVId].push_back(std::make_pair(Calls.size(), Loc)); - Calls.push_back(FunctionSummary::EdgeTy{VI, CalleeInfo(Hotness, RelBF)}); - + return true; + } + } + // Keep track of the Call array index needing a forward reference. + // We will save the location of the ValueInfo needing an update, but + // can only do so once the std::vector is finalized. + if (VI.getRef() == FwdVIRef) + IdToIndexMap[GVId].push_back(std::make_pair(Calls.size(), Loc)); + Calls.push_back(FunctionSummary::EdgeTy{VI, CalleeInfo(Hotness, RelBF)}); + if (parseToken(lltok::rparen, "expected ')' in call")) - return true; - } while (EatIfPresent(lltok::comma)); - - // Now that the Calls vector is finalized, it is safe to save the locations - // of any forward GV references that need updating later. - for (auto I : IdToIndexMap) { + return true; + } while (EatIfPresent(lltok::comma)); + + // Now that the Calls vector is finalized, it is safe to save the locations + // of any forward GV references that need updating later. + for (auto I : IdToIndexMap) { auto &Infos = ForwardRefValueInfos[I.first]; - for (auto P : I.second) { - assert(Calls[P.first].first.getRef() == FwdVIRef && - "Forward referenced ValueInfo expected to be empty"); + for (auto P : I.second) { + assert(Calls[P.first].first.getRef() == FwdVIRef && + "Forward referenced ValueInfo expected to be empty"); Infos.emplace_back(&Calls[P.first].first, P.second); - } - } - + } + } + if (parseToken(lltok::rparen, "expected ')' in calls")) - return true; - - return false; -} - -/// Hotness -/// := ('unknown'|'cold'|'none'|'hot'|'critical') + return true; + + return false; +} + +/// Hotness +/// := ('unknown'|'cold'|'none'|'hot'|'critical') bool LLParser::parseHotness(CalleeInfo::HotnessType &Hotness) { - switch (Lex.getKind()) { - case lltok::kw_unknown: - Hotness = CalleeInfo::HotnessType::Unknown; - break; - case lltok::kw_cold: - Hotness = CalleeInfo::HotnessType::Cold; - break; - case lltok::kw_none: - Hotness = CalleeInfo::HotnessType::None; - break; - case lltok::kw_hot: - Hotness = CalleeInfo::HotnessType::Hot; - break; - case lltok::kw_critical: - Hotness = CalleeInfo::HotnessType::Critical; - break; - default: + switch (Lex.getKind()) { + case lltok::kw_unknown: + Hotness = CalleeInfo::HotnessType::Unknown; + break; + case lltok::kw_cold: + Hotness = CalleeInfo::HotnessType::Cold; + break; + case lltok::kw_none: + Hotness = CalleeInfo::HotnessType::None; + break; + case lltok::kw_hot: + Hotness = CalleeInfo::HotnessType::Hot; + break; + case lltok::kw_critical: + Hotness = CalleeInfo::HotnessType::Critical; + break; + default: return error(Lex.getLoc(), "invalid call edge hotness"); - } - Lex.Lex(); - return false; -} - -/// OptionalVTableFuncs -/// := 'vTableFuncs' ':' '(' VTableFunc [',' VTableFunc]* ')' -/// VTableFunc ::= '(' 'virtFunc' ':' GVReference ',' 'offset' ':' UInt64 ')' + } + Lex.Lex(); + return false; +} + +/// OptionalVTableFuncs +/// := 'vTableFuncs' ':' '(' VTableFunc [',' VTableFunc]* ')' +/// VTableFunc ::= '(' 'virtFunc' ':' GVReference ',' 'offset' ':' UInt64 ')' bool LLParser::parseOptionalVTableFuncs(VTableFuncList &VTableFuncs) { - assert(Lex.getKind() == lltok::kw_vTableFuncs); - Lex.Lex(); - + assert(Lex.getKind() == lltok::kw_vTableFuncs); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' in vTableFuncs") | parseToken(lltok::lparen, "expected '(' in vTableFuncs")) - return true; - - IdToIndexMapType IdToIndexMap; + return true; + + IdToIndexMapType IdToIndexMap; // parse each virtual function pair - do { - ValueInfo VI; + do { + ValueInfo VI; if (parseToken(lltok::lparen, "expected '(' in vTableFunc") || parseToken(lltok::kw_virtFunc, "expected 'callee' in vTableFunc") || parseToken(lltok::colon, "expected ':'")) - return true; - - LocTy Loc = Lex.getLoc(); - unsigned GVId; + return true; + + LocTy Loc = Lex.getLoc(); + unsigned GVId; if (parseGVReference(VI, GVId)) - return true; - - uint64_t Offset; + return true; + + uint64_t Offset; if (parseToken(lltok::comma, "expected comma") || parseToken(lltok::kw_offset, "expected offset") || parseToken(lltok::colon, "expected ':'") || parseUInt64(Offset)) - return true; - - // Keep track of the VTableFuncs array index needing a forward reference. - // We will save the location of the ValueInfo needing an update, but - // can only do so once the std::vector is finalized. - if (VI == EmptyVI) - IdToIndexMap[GVId].push_back(std::make_pair(VTableFuncs.size(), Loc)); - VTableFuncs.push_back({VI, Offset}); - + return true; + + // Keep track of the VTableFuncs array index needing a forward reference. + // We will save the location of the ValueInfo needing an update, but + // can only do so once the std::vector is finalized. + if (VI == EmptyVI) + IdToIndexMap[GVId].push_back(std::make_pair(VTableFuncs.size(), Loc)); + VTableFuncs.push_back({VI, Offset}); + if (parseToken(lltok::rparen, "expected ')' in vTableFunc")) - return true; - } while (EatIfPresent(lltok::comma)); - - // Now that the VTableFuncs vector is finalized, it is safe to save the - // locations of any forward GV references that need updating later. - for (auto I : IdToIndexMap) { + return true; + } while (EatIfPresent(lltok::comma)); + + // Now that the VTableFuncs vector is finalized, it is safe to save the + // locations of any forward GV references that need updating later. + for (auto I : IdToIndexMap) { auto &Infos = ForwardRefValueInfos[I.first]; - for (auto P : I.second) { - assert(VTableFuncs[P.first].FuncVI == EmptyVI && - "Forward referenced ValueInfo expected to be empty"); + for (auto P : I.second) { + assert(VTableFuncs[P.first].FuncVI == EmptyVI && + "Forward referenced ValueInfo expected to be empty"); Infos.emplace_back(&VTableFuncs[P.first].FuncVI, P.second); - } - } - + } + } + if (parseToken(lltok::rparen, "expected ')' in vTableFuncs")) - return true; - - return false; -} - -/// ParamNo := 'param' ':' UInt64 + return true; + + return false; +} + +/// ParamNo := 'param' ':' UInt64 bool LLParser::parseParamNo(uint64_t &ParamNo) { if (parseToken(lltok::kw_param, "expected 'param' here") || parseToken(lltok::colon, "expected ':' here") || parseUInt64(ParamNo)) - return true; - return false; -} - -/// ParamAccessOffset := 'offset' ':' '[' APSINTVAL ',' APSINTVAL ']' + return true; + return false; +} + +/// ParamAccessOffset := 'offset' ':' '[' APSINTVAL ',' APSINTVAL ']' bool LLParser::parseParamAccessOffset(ConstantRange &Range) { - APSInt Lower; - APSInt Upper; - auto ParseAPSInt = [&](APSInt &Val) { - if (Lex.getKind() != lltok::APSInt) + APSInt Lower; + APSInt Upper; + auto ParseAPSInt = [&](APSInt &Val) { + if (Lex.getKind() != lltok::APSInt) return tokError("expected integer"); - Val = Lex.getAPSIntVal(); - Val = Val.extOrTrunc(FunctionSummary::ParamAccess::RangeWidth); - Val.setIsSigned(true); - Lex.Lex(); - return false; - }; + Val = Lex.getAPSIntVal(); + Val = Val.extOrTrunc(FunctionSummary::ParamAccess::RangeWidth); + Val.setIsSigned(true); + Lex.Lex(); + return false; + }; if (parseToken(lltok::kw_offset, "expected 'offset' here") || parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lsquare, "expected '[' here") || ParseAPSInt(Lower) || parseToken(lltok::comma, "expected ',' here") || ParseAPSInt(Upper) || parseToken(lltok::rsquare, "expected ']' here")) - return true; - - ++Upper; - Range = - (Lower == Upper && !Lower.isMaxValue()) - ? ConstantRange::getEmpty(FunctionSummary::ParamAccess::RangeWidth) - : ConstantRange(Lower, Upper); - - return false; -} - -/// ParamAccessCall -/// := '(' 'callee' ':' GVReference ',' ParamNo ',' ParamAccessOffset ')' + return true; + + ++Upper; + Range = + (Lower == Upper && !Lower.isMaxValue()) + ? ConstantRange::getEmpty(FunctionSummary::ParamAccess::RangeWidth) + : ConstantRange(Lower, Upper); + + return false; +} + +/// ParamAccessCall +/// := '(' 'callee' ':' GVReference ',' ParamNo ',' ParamAccessOffset ')' bool LLParser::parseParamAccessCall(FunctionSummary::ParamAccess::Call &Call, IdLocListType &IdLocList) { if (parseToken(lltok::lparen, "expected '(' here") || parseToken(lltok::kw_callee, "expected 'callee' here") || parseToken(lltok::colon, "expected ':' here")) - return true; - - unsigned GVId; - ValueInfo VI; + return true; + + unsigned GVId; + ValueInfo VI; LocTy Loc = Lex.getLoc(); if (parseGVReference(VI, GVId)) - return true; - + return true; + Call.Callee = VI; IdLocList.emplace_back(GVId, Loc); - + if (parseToken(lltok::comma, "expected ',' here") || parseParamNo(Call.ParamNo) || parseToken(lltok::comma, "expected ',' here") || parseParamAccessOffset(Call.Offsets)) - return true; - + return true; + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - return false; -} - -/// ParamAccess -/// := '(' ParamNo ',' ParamAccessOffset [',' OptionalParamAccessCalls]? ')' -/// OptionalParamAccessCalls := '(' Call [',' Call]* ')' + return true; + + return false; +} + +/// ParamAccess +/// := '(' ParamNo ',' ParamAccessOffset [',' OptionalParamAccessCalls]? ')' +/// OptionalParamAccessCalls := '(' Call [',' Call]* ')' bool LLParser::parseParamAccess(FunctionSummary::ParamAccess &Param, IdLocListType &IdLocList) { if (parseToken(lltok::lparen, "expected '(' here") || parseParamNo(Param.ParamNo) || parseToken(lltok::comma, "expected ',' here") || parseParamAccessOffset(Param.Use)) - return true; - - if (EatIfPresent(lltok::comma)) { + return true; + + if (EatIfPresent(lltok::comma)) { if (parseToken(lltok::kw_calls, "expected 'calls' here") || parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here")) - return true; - do { - FunctionSummary::ParamAccess::Call Call; + return true; + do { + FunctionSummary::ParamAccess::Call Call; if (parseParamAccessCall(Call, IdLocList)) - return true; - Param.Calls.push_back(Call); - } while (EatIfPresent(lltok::comma)); - + return true; + Param.Calls.push_back(Call); + } while (EatIfPresent(lltok::comma)); + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - } - + return true; + } + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - return false; -} - -/// OptionalParamAccesses -/// := 'params' ':' '(' ParamAccess [',' ParamAccess]* ')' + return true; + + return false; +} + +/// OptionalParamAccesses +/// := 'params' ':' '(' ParamAccess [',' ParamAccess]* ')' bool LLParser::parseOptionalParamAccesses( - std::vector<FunctionSummary::ParamAccess> &Params) { - assert(Lex.getKind() == lltok::kw_params); - Lex.Lex(); - + std::vector<FunctionSummary::ParamAccess> &Params) { + assert(Lex.getKind() == lltok::kw_params); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here")) - return true; - + return true; + IdLocListType VContexts; size_t CallsNum = 0; - do { - FunctionSummary::ParamAccess ParamAccess; + do { + FunctionSummary::ParamAccess ParamAccess; if (parseParamAccess(ParamAccess, VContexts)) - return true; + return true; CallsNum += ParamAccess.Calls.size(); assert(VContexts.size() == CallsNum); Params.emplace_back(std::move(ParamAccess)); - } while (EatIfPresent(lltok::comma)); - + } while (EatIfPresent(lltok::comma)); + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - + return true; + // Now that the Params is finalized, it is safe to save the locations // of any forward GV references that need updating later. IdLocListType::const_iterator ItContext = VContexts.begin(); @@ -9054,435 +9054,435 @@ bool LLParser::parseOptionalParamAccesses( } assert(ItContext == VContexts.end()); - return false; -} - -/// OptionalRefs -/// := 'refs' ':' '(' GVReference [',' GVReference]* ')' + return false; +} + +/// OptionalRefs +/// := 'refs' ':' '(' GVReference [',' GVReference]* ')' bool LLParser::parseOptionalRefs(std::vector<ValueInfo> &Refs) { - assert(Lex.getKind() == lltok::kw_refs); - Lex.Lex(); - + assert(Lex.getKind() == lltok::kw_refs); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' in refs") || parseToken(lltok::lparen, "expected '(' in refs")) - return true; - - struct ValueContext { - ValueInfo VI; - unsigned GVId; - LocTy Loc; - }; - std::vector<ValueContext> VContexts; + return true; + + struct ValueContext { + ValueInfo VI; + unsigned GVId; + LocTy Loc; + }; + std::vector<ValueContext> VContexts; // parse each ref edge - do { - ValueContext VC; - VC.Loc = Lex.getLoc(); + do { + ValueContext VC; + VC.Loc = Lex.getLoc(); if (parseGVReference(VC.VI, VC.GVId)) - return true; - VContexts.push_back(VC); - } while (EatIfPresent(lltok::comma)); - - // Sort value contexts so that ones with writeonly - // and readonly ValueInfo are at the end of VContexts vector. - // See FunctionSummary::specialRefCounts() - llvm::sort(VContexts, [](const ValueContext &VC1, const ValueContext &VC2) { - return VC1.VI.getAccessSpecifier() < VC2.VI.getAccessSpecifier(); - }); - - IdToIndexMapType IdToIndexMap; - for (auto &VC : VContexts) { - // Keep track of the Refs array index needing a forward reference. - // We will save the location of the ValueInfo needing an update, but - // can only do so once the std::vector is finalized. - if (VC.VI.getRef() == FwdVIRef) - IdToIndexMap[VC.GVId].push_back(std::make_pair(Refs.size(), VC.Loc)); - Refs.push_back(VC.VI); - } - - // Now that the Refs vector is finalized, it is safe to save the locations - // of any forward GV references that need updating later. - for (auto I : IdToIndexMap) { + return true; + VContexts.push_back(VC); + } while (EatIfPresent(lltok::comma)); + + // Sort value contexts so that ones with writeonly + // and readonly ValueInfo are at the end of VContexts vector. + // See FunctionSummary::specialRefCounts() + llvm::sort(VContexts, [](const ValueContext &VC1, const ValueContext &VC2) { + return VC1.VI.getAccessSpecifier() < VC2.VI.getAccessSpecifier(); + }); + + IdToIndexMapType IdToIndexMap; + for (auto &VC : VContexts) { + // Keep track of the Refs array index needing a forward reference. + // We will save the location of the ValueInfo needing an update, but + // can only do so once the std::vector is finalized. + if (VC.VI.getRef() == FwdVIRef) + IdToIndexMap[VC.GVId].push_back(std::make_pair(Refs.size(), VC.Loc)); + Refs.push_back(VC.VI); + } + + // Now that the Refs vector is finalized, it is safe to save the locations + // of any forward GV references that need updating later. + for (auto I : IdToIndexMap) { auto &Infos = ForwardRefValueInfos[I.first]; - for (auto P : I.second) { - assert(Refs[P.first].getRef() == FwdVIRef && - "Forward referenced ValueInfo expected to be empty"); + for (auto P : I.second) { + assert(Refs[P.first].getRef() == FwdVIRef && + "Forward referenced ValueInfo expected to be empty"); Infos.emplace_back(&Refs[P.first], P.second); - } - } - + } + } + if (parseToken(lltok::rparen, "expected ')' in refs")) - return true; - - return false; -} - -/// OptionalTypeIdInfo -/// := 'typeidinfo' ':' '(' [',' TypeTests]? [',' TypeTestAssumeVCalls]? -/// [',' TypeCheckedLoadVCalls]? [',' TypeTestAssumeConstVCalls]? -/// [',' TypeCheckedLoadConstVCalls]? ')' + return true; + + return false; +} + +/// OptionalTypeIdInfo +/// := 'typeidinfo' ':' '(' [',' TypeTests]? [',' TypeTestAssumeVCalls]? +/// [',' TypeCheckedLoadVCalls]? [',' TypeTestAssumeConstVCalls]? +/// [',' TypeCheckedLoadConstVCalls]? ')' bool LLParser::parseOptionalTypeIdInfo( - FunctionSummary::TypeIdInfo &TypeIdInfo) { - assert(Lex.getKind() == lltok::kw_typeIdInfo); - Lex.Lex(); - + FunctionSummary::TypeIdInfo &TypeIdInfo) { + assert(Lex.getKind() == lltok::kw_typeIdInfo); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' in typeIdInfo")) - return true; - - do { - switch (Lex.getKind()) { - case lltok::kw_typeTests: + return true; + + do { + switch (Lex.getKind()) { + case lltok::kw_typeTests: if (parseTypeTests(TypeIdInfo.TypeTests)) - return true; - break; - case lltok::kw_typeTestAssumeVCalls: + return true; + break; + case lltok::kw_typeTestAssumeVCalls: if (parseVFuncIdList(lltok::kw_typeTestAssumeVCalls, - TypeIdInfo.TypeTestAssumeVCalls)) - return true; - break; - case lltok::kw_typeCheckedLoadVCalls: + TypeIdInfo.TypeTestAssumeVCalls)) + return true; + break; + case lltok::kw_typeCheckedLoadVCalls: if (parseVFuncIdList(lltok::kw_typeCheckedLoadVCalls, - TypeIdInfo.TypeCheckedLoadVCalls)) - return true; - break; - case lltok::kw_typeTestAssumeConstVCalls: + TypeIdInfo.TypeCheckedLoadVCalls)) + return true; + break; + case lltok::kw_typeTestAssumeConstVCalls: if (parseConstVCallList(lltok::kw_typeTestAssumeConstVCalls, - TypeIdInfo.TypeTestAssumeConstVCalls)) - return true; - break; - case lltok::kw_typeCheckedLoadConstVCalls: + TypeIdInfo.TypeTestAssumeConstVCalls)) + return true; + break; + case lltok::kw_typeCheckedLoadConstVCalls: if (parseConstVCallList(lltok::kw_typeCheckedLoadConstVCalls, - TypeIdInfo.TypeCheckedLoadConstVCalls)) - return true; - break; - default: + TypeIdInfo.TypeCheckedLoadConstVCalls)) + return true; + break; + default: return error(Lex.getLoc(), "invalid typeIdInfo list type"); - } - } while (EatIfPresent(lltok::comma)); - + } + } while (EatIfPresent(lltok::comma)); + if (parseToken(lltok::rparen, "expected ')' in typeIdInfo")) - return true; - - return false; -} - -/// TypeTests -/// ::= 'typeTests' ':' '(' (SummaryID | UInt64) -/// [',' (SummaryID | UInt64)]* ')' + return true; + + return false; +} + +/// TypeTests +/// ::= 'typeTests' ':' '(' (SummaryID | UInt64) +/// [',' (SummaryID | UInt64)]* ')' bool LLParser::parseTypeTests(std::vector<GlobalValue::GUID> &TypeTests) { - assert(Lex.getKind() == lltok::kw_typeTests); - Lex.Lex(); - + assert(Lex.getKind() == lltok::kw_typeTests); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' in typeIdInfo")) - return true; - - IdToIndexMapType IdToIndexMap; - do { - GlobalValue::GUID GUID = 0; - if (Lex.getKind() == lltok::SummaryID) { - unsigned ID = Lex.getUIntVal(); - LocTy Loc = Lex.getLoc(); - // Keep track of the TypeTests array index needing a forward reference. - // We will save the location of the GUID needing an update, but - // can only do so once the std::vector is finalized. - IdToIndexMap[ID].push_back(std::make_pair(TypeTests.size(), Loc)); - Lex.Lex(); + return true; + + IdToIndexMapType IdToIndexMap; + do { + GlobalValue::GUID GUID = 0; + if (Lex.getKind() == lltok::SummaryID) { + unsigned ID = Lex.getUIntVal(); + LocTy Loc = Lex.getLoc(); + // Keep track of the TypeTests array index needing a forward reference. + // We will save the location of the GUID needing an update, but + // can only do so once the std::vector is finalized. + IdToIndexMap[ID].push_back(std::make_pair(TypeTests.size(), Loc)); + Lex.Lex(); } else if (parseUInt64(GUID)) - return true; - TypeTests.push_back(GUID); - } while (EatIfPresent(lltok::comma)); - - // Now that the TypeTests vector is finalized, it is safe to save the - // locations of any forward GV references that need updating later. - for (auto I : IdToIndexMap) { + return true; + TypeTests.push_back(GUID); + } while (EatIfPresent(lltok::comma)); + + // Now that the TypeTests vector is finalized, it is safe to save the + // locations of any forward GV references that need updating later. + for (auto I : IdToIndexMap) { auto &Ids = ForwardRefTypeIds[I.first]; - for (auto P : I.second) { - assert(TypeTests[P.first] == 0 && - "Forward referenced type id GUID expected to be 0"); + for (auto P : I.second) { + assert(TypeTests[P.first] == 0 && + "Forward referenced type id GUID expected to be 0"); Ids.emplace_back(&TypeTests[P.first], P.second); - } - } - + } + } + if (parseToken(lltok::rparen, "expected ')' in typeIdInfo")) - return true; - - return false; -} - -/// VFuncIdList -/// ::= Kind ':' '(' VFuncId [',' VFuncId]* ')' + return true; + + return false; +} + +/// VFuncIdList +/// ::= Kind ':' '(' VFuncId [',' VFuncId]* ')' bool LLParser::parseVFuncIdList( - lltok::Kind Kind, std::vector<FunctionSummary::VFuncId> &VFuncIdList) { - assert(Lex.getKind() == Kind); - Lex.Lex(); - + lltok::Kind Kind, std::vector<FunctionSummary::VFuncId> &VFuncIdList) { + assert(Lex.getKind() == Kind); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here")) - return true; - - IdToIndexMapType IdToIndexMap; - do { - FunctionSummary::VFuncId VFuncId; + return true; + + IdToIndexMapType IdToIndexMap; + do { + FunctionSummary::VFuncId VFuncId; if (parseVFuncId(VFuncId, IdToIndexMap, VFuncIdList.size())) - return true; - VFuncIdList.push_back(VFuncId); - } while (EatIfPresent(lltok::comma)); - + return true; + VFuncIdList.push_back(VFuncId); + } while (EatIfPresent(lltok::comma)); + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - // Now that the VFuncIdList vector is finalized, it is safe to save the - // locations of any forward GV references that need updating later. - for (auto I : IdToIndexMap) { + return true; + + // Now that the VFuncIdList vector is finalized, it is safe to save the + // locations of any forward GV references that need updating later. + for (auto I : IdToIndexMap) { auto &Ids = ForwardRefTypeIds[I.first]; - for (auto P : I.second) { - assert(VFuncIdList[P.first].GUID == 0 && - "Forward referenced type id GUID expected to be 0"); + for (auto P : I.second) { + assert(VFuncIdList[P.first].GUID == 0 && + "Forward referenced type id GUID expected to be 0"); Ids.emplace_back(&VFuncIdList[P.first].GUID, P.second); - } - } - - return false; -} - -/// ConstVCallList -/// ::= Kind ':' '(' ConstVCall [',' ConstVCall]* ')' + } + } + + return false; +} + +/// ConstVCallList +/// ::= Kind ':' '(' ConstVCall [',' ConstVCall]* ')' bool LLParser::parseConstVCallList( - lltok::Kind Kind, - std::vector<FunctionSummary::ConstVCall> &ConstVCallList) { - assert(Lex.getKind() == Kind); - Lex.Lex(); - + lltok::Kind Kind, + std::vector<FunctionSummary::ConstVCall> &ConstVCallList) { + assert(Lex.getKind() == Kind); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here")) - return true; - - IdToIndexMapType IdToIndexMap; - do { - FunctionSummary::ConstVCall ConstVCall; + return true; + + IdToIndexMapType IdToIndexMap; + do { + FunctionSummary::ConstVCall ConstVCall; if (parseConstVCall(ConstVCall, IdToIndexMap, ConstVCallList.size())) - return true; - ConstVCallList.push_back(ConstVCall); - } while (EatIfPresent(lltok::comma)); - + return true; + ConstVCallList.push_back(ConstVCall); + } while (EatIfPresent(lltok::comma)); + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - // Now that the ConstVCallList vector is finalized, it is safe to save the - // locations of any forward GV references that need updating later. - for (auto I : IdToIndexMap) { + return true; + + // Now that the ConstVCallList vector is finalized, it is safe to save the + // locations of any forward GV references that need updating later. + for (auto I : IdToIndexMap) { auto &Ids = ForwardRefTypeIds[I.first]; - for (auto P : I.second) { - assert(ConstVCallList[P.first].VFunc.GUID == 0 && - "Forward referenced type id GUID expected to be 0"); + for (auto P : I.second) { + assert(ConstVCallList[P.first].VFunc.GUID == 0 && + "Forward referenced type id GUID expected to be 0"); Ids.emplace_back(&ConstVCallList[P.first].VFunc.GUID, P.second); - } - } - - return false; -} - -/// ConstVCall -/// ::= '(' VFuncId ',' Args ')' + } + } + + return false; +} + +/// ConstVCall +/// ::= '(' VFuncId ',' Args ')' bool LLParser::parseConstVCall(FunctionSummary::ConstVCall &ConstVCall, - IdToIndexMapType &IdToIndexMap, unsigned Index) { + IdToIndexMapType &IdToIndexMap, unsigned Index) { if (parseToken(lltok::lparen, "expected '(' here") || parseVFuncId(ConstVCall.VFunc, IdToIndexMap, Index)) - return true; - - if (EatIfPresent(lltok::comma)) + return true; + + if (EatIfPresent(lltok::comma)) if (parseArgs(ConstVCall.Args)) - return true; - + return true; + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - return false; -} - -/// VFuncId -/// ::= 'vFuncId' ':' '(' (SummaryID | 'guid' ':' UInt64) ',' -/// 'offset' ':' UInt64 ')' + return true; + + return false; +} + +/// VFuncId +/// ::= 'vFuncId' ':' '(' (SummaryID | 'guid' ':' UInt64) ',' +/// 'offset' ':' UInt64 ')' bool LLParser::parseVFuncId(FunctionSummary::VFuncId &VFuncId, - IdToIndexMapType &IdToIndexMap, unsigned Index) { - assert(Lex.getKind() == lltok::kw_vFuncId); - Lex.Lex(); - + IdToIndexMapType &IdToIndexMap, unsigned Index) { + assert(Lex.getKind() == lltok::kw_vFuncId); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here")) - return true; - - if (Lex.getKind() == lltok::SummaryID) { - VFuncId.GUID = 0; - unsigned ID = Lex.getUIntVal(); - LocTy Loc = Lex.getLoc(); - // Keep track of the array index needing a forward reference. - // We will save the location of the GUID needing an update, but - // can only do so once the caller's std::vector is finalized. - IdToIndexMap[ID].push_back(std::make_pair(Index, Loc)); - Lex.Lex(); + return true; + + if (Lex.getKind() == lltok::SummaryID) { + VFuncId.GUID = 0; + unsigned ID = Lex.getUIntVal(); + LocTy Loc = Lex.getLoc(); + // Keep track of the array index needing a forward reference. + // We will save the location of the GUID needing an update, but + // can only do so once the caller's std::vector is finalized. + IdToIndexMap[ID].push_back(std::make_pair(Index, Loc)); + Lex.Lex(); } else if (parseToken(lltok::kw_guid, "expected 'guid' here") || parseToken(lltok::colon, "expected ':' here") || parseUInt64(VFuncId.GUID)) - return true; - + return true; + if (parseToken(lltok::comma, "expected ',' here") || parseToken(lltok::kw_offset, "expected 'offset' here") || parseToken(lltok::colon, "expected ':' here") || parseUInt64(VFuncId.Offset) || parseToken(lltok::rparen, "expected ')' here")) - return true; - - return false; -} - -/// GVFlags -/// ::= 'flags' ':' '(' 'linkage' ':' OptionalLinkageAux ',' -/// 'notEligibleToImport' ':' Flag ',' 'live' ':' Flag ',' -/// 'dsoLocal' ':' Flag ',' 'canAutoHide' ':' Flag ')' + return true; + + return false; +} + +/// GVFlags +/// ::= 'flags' ':' '(' 'linkage' ':' OptionalLinkageAux ',' +/// 'notEligibleToImport' ':' Flag ',' 'live' ':' Flag ',' +/// 'dsoLocal' ':' Flag ',' 'canAutoHide' ':' Flag ')' bool LLParser::parseGVFlags(GlobalValueSummary::GVFlags &GVFlags) { - assert(Lex.getKind() == lltok::kw_flags); - Lex.Lex(); - + assert(Lex.getKind() == lltok::kw_flags); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here")) - return true; - - do { - unsigned Flag = 0; - switch (Lex.getKind()) { - case lltok::kw_linkage: - Lex.Lex(); + return true; + + do { + unsigned Flag = 0; + switch (Lex.getKind()) { + case lltok::kw_linkage: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'")) - return true; - bool HasLinkage; - GVFlags.Linkage = parseOptionalLinkageAux(Lex.getKind(), HasLinkage); - assert(HasLinkage && "Linkage not optional in summary entry"); - Lex.Lex(); - break; - case lltok::kw_notEligibleToImport: - Lex.Lex(); + return true; + bool HasLinkage; + GVFlags.Linkage = parseOptionalLinkageAux(Lex.getKind(), HasLinkage); + assert(HasLinkage && "Linkage not optional in summary entry"); + Lex.Lex(); + break; + case lltok::kw_notEligibleToImport: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseFlag(Flag)) - return true; - GVFlags.NotEligibleToImport = Flag; - break; - case lltok::kw_live: - Lex.Lex(); + return true; + GVFlags.NotEligibleToImport = Flag; + break; + case lltok::kw_live: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseFlag(Flag)) - return true; - GVFlags.Live = Flag; - break; - case lltok::kw_dsoLocal: - Lex.Lex(); + return true; + GVFlags.Live = Flag; + break; + case lltok::kw_dsoLocal: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseFlag(Flag)) - return true; - GVFlags.DSOLocal = Flag; - break; - case lltok::kw_canAutoHide: - Lex.Lex(); + return true; + GVFlags.DSOLocal = Flag; + break; + case lltok::kw_canAutoHide: + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseFlag(Flag)) - return true; - GVFlags.CanAutoHide = Flag; - break; - default: + return true; + GVFlags.CanAutoHide = Flag; + break; + default: return error(Lex.getLoc(), "expected gv flag type"); - } - } while (EatIfPresent(lltok::comma)); - + } + } while (EatIfPresent(lltok::comma)); + if (parseToken(lltok::rparen, "expected ')' here")) - return true; - - return false; -} - -/// GVarFlags -/// ::= 'varFlags' ':' '(' 'readonly' ':' Flag -/// ',' 'writeonly' ':' Flag -/// ',' 'constant' ':' Flag ')' + return true; + + return false; +} + +/// GVarFlags +/// ::= 'varFlags' ':' '(' 'readonly' ':' Flag +/// ',' 'writeonly' ':' Flag +/// ',' 'constant' ':' Flag ')' bool LLParser::parseGVarFlags(GlobalVarSummary::GVarFlags &GVarFlags) { - assert(Lex.getKind() == lltok::kw_varFlags); - Lex.Lex(); - + assert(Lex.getKind() == lltok::kw_varFlags); + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here")) - return true; - - auto ParseRest = [this](unsigned int &Val) { - Lex.Lex(); + return true; + + auto ParseRest = [this](unsigned int &Val) { + Lex.Lex(); if (parseToken(lltok::colon, "expected ':'")) - return true; + return true; return parseFlag(Val); - }; - - do { - unsigned Flag = 0; - switch (Lex.getKind()) { - case lltok::kw_readonly: - if (ParseRest(Flag)) - return true; - GVarFlags.MaybeReadOnly = Flag; - break; - case lltok::kw_writeonly: - if (ParseRest(Flag)) - return true; - GVarFlags.MaybeWriteOnly = Flag; - break; - case lltok::kw_constant: - if (ParseRest(Flag)) - return true; - GVarFlags.Constant = Flag; - break; - case lltok::kw_vcall_visibility: - if (ParseRest(Flag)) - return true; - GVarFlags.VCallVisibility = Flag; - break; - default: + }; + + do { + unsigned Flag = 0; + switch (Lex.getKind()) { + case lltok::kw_readonly: + if (ParseRest(Flag)) + return true; + GVarFlags.MaybeReadOnly = Flag; + break; + case lltok::kw_writeonly: + if (ParseRest(Flag)) + return true; + GVarFlags.MaybeWriteOnly = Flag; + break; + case lltok::kw_constant: + if (ParseRest(Flag)) + return true; + GVarFlags.Constant = Flag; + break; + case lltok::kw_vcall_visibility: + if (ParseRest(Flag)) + return true; + GVarFlags.VCallVisibility = Flag; + break; + default: return error(Lex.getLoc(), "expected gvar flag type"); - } - } while (EatIfPresent(lltok::comma)); + } + } while (EatIfPresent(lltok::comma)); return parseToken(lltok::rparen, "expected ')' here"); -} - -/// ModuleReference -/// ::= 'module' ':' UInt +} + +/// ModuleReference +/// ::= 'module' ':' UInt bool LLParser::parseModuleReference(StringRef &ModulePath) { // parse module id. if (parseToken(lltok::kw_module, "expected 'module' here") || parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::SummaryID, "expected module ID")) - return true; - - unsigned ModuleID = Lex.getUIntVal(); - auto I = ModuleIdMap.find(ModuleID); - // We should have already parsed all module IDs - assert(I != ModuleIdMap.end()); - ModulePath = I->second; - return false; -} - -/// GVReference -/// ::= SummaryID + return true; + + unsigned ModuleID = Lex.getUIntVal(); + auto I = ModuleIdMap.find(ModuleID); + // We should have already parsed all module IDs + assert(I != ModuleIdMap.end()); + ModulePath = I->second; + return false; +} + +/// GVReference +/// ::= SummaryID bool LLParser::parseGVReference(ValueInfo &VI, unsigned &GVId) { - bool WriteOnly = false, ReadOnly = EatIfPresent(lltok::kw_readonly); - if (!ReadOnly) - WriteOnly = EatIfPresent(lltok::kw_writeonly); + bool WriteOnly = false, ReadOnly = EatIfPresent(lltok::kw_readonly); + if (!ReadOnly) + WriteOnly = EatIfPresent(lltok::kw_writeonly); if (parseToken(lltok::SummaryID, "expected GV ID")) - return true; - - GVId = Lex.getUIntVal(); - // Check if we already have a VI for this GV - if (GVId < NumberedValueInfos.size()) { - assert(NumberedValueInfos[GVId].getRef() != FwdVIRef); - VI = NumberedValueInfos[GVId]; - } else - // We will create a forward reference to the stored location. - VI = ValueInfo(false, FwdVIRef); - - if (ReadOnly) - VI.setReadOnly(); - if (WriteOnly) - VI.setWriteOnly(); - return false; -} + return true; + + GVId = Lex.getUIntVal(); + // Check if we already have a VI for this GV + if (GVId < NumberedValueInfos.size()) { + assert(NumberedValueInfos[GVId].getRef() != FwdVIRef); + VI = NumberedValueInfos[GVId]; + } else + // We will create a forward reference to the stored location. + VI = ValueInfo(false, FwdVIRef); + + if (ReadOnly) + VI.setReadOnly(); + if (WriteOnly) + VI.setWriteOnly(); + return false; +} diff --git a/contrib/libs/llvm12/lib/AsmParser/LLParser.h b/contrib/libs/llvm12/lib/AsmParser/LLParser.h index 65a71355ea..aa79823ce9 100644 --- a/contrib/libs/llvm12/lib/AsmParser/LLParser.h +++ b/contrib/libs/llvm12/lib/AsmParser/LLParser.h @@ -1,298 +1,298 @@ -//===-- LLParser.h - Parser Class -------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the parser class for .ll files. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_ASMPARSER_LLPARSER_H -#define LLVM_LIB_ASMPARSER_LLPARSER_H - -#include "LLLexer.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/AsmParser/Parser.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/ModuleSummaryIndex.h" -#include "llvm/IR/Operator.h" -#include "llvm/IR/Type.h" -#include <map> - -namespace llvm { - class Module; - class Function; - class Value; - class BasicBlock; - class Instruction; - class Constant; - class GlobalValue; - class Comdat; - class MDString; - class MDNode; - struct SlotMapping; - - /// ValID - Represents a reference of a definition of some sort with no type. - /// There are several cases where we have to parse the value but where the - /// type can depend on later context. This may either be a numeric reference - /// or a symbolic (%var) reference. This is just a discriminated union. - struct ValID { - enum { - t_LocalID, t_GlobalID, // ID in UIntVal. - t_LocalName, t_GlobalName, // Name in StrVal. - t_APSInt, t_APFloat, // Value in APSIntVal/APFloatVal. +//===-- LLParser.h - Parser Class -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the parser class for .ll files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_ASMPARSER_LLPARSER_H +#define LLVM_LIB_ASMPARSER_LLPARSER_H + +#include "LLLexer.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/AsmParser/Parser.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/ModuleSummaryIndex.h" +#include "llvm/IR/Operator.h" +#include "llvm/IR/Type.h" +#include <map> + +namespace llvm { + class Module; + class Function; + class Value; + class BasicBlock; + class Instruction; + class Constant; + class GlobalValue; + class Comdat; + class MDString; + class MDNode; + struct SlotMapping; + + /// ValID - Represents a reference of a definition of some sort with no type. + /// There are several cases where we have to parse the value but where the + /// type can depend on later context. This may either be a numeric reference + /// or a symbolic (%var) reference. This is just a discriminated union. + struct ValID { + enum { + t_LocalID, t_GlobalID, // ID in UIntVal. + t_LocalName, t_GlobalName, // Name in StrVal. + t_APSInt, t_APFloat, // Value in APSIntVal/APFloatVal. t_Null, t_Undef, t_Zero, t_None, t_Poison, // No value. - t_EmptyArray, // No value: [] - t_Constant, // Value in ConstantVal. - t_InlineAsm, // Value in FTy/StrVal/StrVal2/UIntVal. - t_ConstantStruct, // Value in ConstantStructElts. - t_PackedConstantStruct // Value in ConstantStructElts. - } Kind = t_LocalID; - - LLLexer::LocTy Loc; - unsigned UIntVal; - FunctionType *FTy = nullptr; - std::string StrVal, StrVal2; - APSInt APSIntVal; - APFloat APFloatVal{0.0}; - Constant *ConstantVal; - std::unique_ptr<Constant *[]> ConstantStructElts; - - ValID() = default; - ValID(const ValID &RHS) - : Kind(RHS.Kind), Loc(RHS.Loc), UIntVal(RHS.UIntVal), FTy(RHS.FTy), - StrVal(RHS.StrVal), StrVal2(RHS.StrVal2), APSIntVal(RHS.APSIntVal), - APFloatVal(RHS.APFloatVal), ConstantVal(RHS.ConstantVal) { - assert(!RHS.ConstantStructElts); - } - - bool operator<(const ValID &RHS) const { - if (Kind == t_LocalID || Kind == t_GlobalID) - return UIntVal < RHS.UIntVal; - assert((Kind == t_LocalName || Kind == t_GlobalName || - Kind == t_ConstantStruct || Kind == t_PackedConstantStruct) && - "Ordering not defined for this ValID kind yet"); - return StrVal < RHS.StrVal; - } - }; - - class LLParser { - public: - typedef LLLexer::LocTy LocTy; - private: - LLVMContext &Context; - LLLexer Lex; - // Module being parsed, null if we are only parsing summary index. - Module *M; - // Summary index being parsed, null if we are only parsing Module. - ModuleSummaryIndex *Index; - SlotMapping *Slots; - - // Instruction metadata resolution. Each instruction can have a list of - // MDRef info associated with them. - // - // The simpler approach of just creating temporary MDNodes and then calling - // RAUW on them when the definition is processed doesn't work because some - // instruction metadata kinds, such as dbg, get stored in the IR in an - // "optimized" format which doesn't participate in the normal value use - // lists. This means that RAUW doesn't work, even on temporary MDNodes - // which otherwise support RAUW. Instead, we defer resolving MDNode - // references until the definitions have been processed. - struct MDRef { - SMLoc Loc; - unsigned MDKind, MDSlot; - }; - - SmallVector<Instruction*, 64> InstsWithTBAATag; - - // Type resolution handling data structures. The location is set when we - // have processed a use of the type but not a definition yet. - StringMap<std::pair<Type*, LocTy> > NamedTypes; - std::map<unsigned, std::pair<Type*, LocTy> > NumberedTypes; - - std::map<unsigned, TrackingMDNodeRef> NumberedMetadata; - std::map<unsigned, std::pair<TempMDTuple, LocTy>> ForwardRefMDNodes; - - // Global Value reference information. - std::map<std::string, std::pair<GlobalValue*, LocTy> > ForwardRefVals; - std::map<unsigned, std::pair<GlobalValue*, LocTy> > ForwardRefValIDs; - std::vector<GlobalValue*> NumberedVals; - - // Comdat forward reference information. - std::map<std::string, LocTy> ForwardRefComdats; - - // References to blockaddress. The key is the function ValID, the value is - // a list of references to blocks in that function. - std::map<ValID, std::map<ValID, GlobalValue *>> ForwardRefBlockAddresses; - class PerFunctionState; - /// Reference to per-function state to allow basic blocks to be - /// forward-referenced by blockaddress instructions within the same - /// function. - PerFunctionState *BlockAddressPFS; - - // Attribute builder reference information. - std::map<Value*, std::vector<unsigned> > ForwardRefAttrGroups; - std::map<unsigned, AttrBuilder> NumberedAttrBuilders; - - // Summary global value reference information. - std::map<unsigned, std::vector<std::pair<ValueInfo *, LocTy>>> - ForwardRefValueInfos; - std::map<unsigned, std::vector<std::pair<AliasSummary *, LocTy>>> - ForwardRefAliasees; - std::vector<ValueInfo> NumberedValueInfos; - - // Summary type id reference information. - std::map<unsigned, std::vector<std::pair<GlobalValue::GUID *, LocTy>>> - ForwardRefTypeIds; - - // Map of module ID to path. - std::map<unsigned, StringRef> ModuleIdMap; - - /// Only the llvm-as tool may set this to false to bypass - /// UpgradeDebuginfo so it can generate broken bitcode. - bool UpgradeDebugInfo; - - std::string SourceFileName; - - public: - LLParser(StringRef F, SourceMgr &SM, SMDiagnostic &Err, Module *M, - ModuleSummaryIndex *Index, LLVMContext &Context, - SlotMapping *Slots = nullptr) - : Context(Context), Lex(F, SM, Err, Context), M(M), Index(Index), - Slots(Slots), BlockAddressPFS(nullptr) {} - bool Run( + t_EmptyArray, // No value: [] + t_Constant, // Value in ConstantVal. + t_InlineAsm, // Value in FTy/StrVal/StrVal2/UIntVal. + t_ConstantStruct, // Value in ConstantStructElts. + t_PackedConstantStruct // Value in ConstantStructElts. + } Kind = t_LocalID; + + LLLexer::LocTy Loc; + unsigned UIntVal; + FunctionType *FTy = nullptr; + std::string StrVal, StrVal2; + APSInt APSIntVal; + APFloat APFloatVal{0.0}; + Constant *ConstantVal; + std::unique_ptr<Constant *[]> ConstantStructElts; + + ValID() = default; + ValID(const ValID &RHS) + : Kind(RHS.Kind), Loc(RHS.Loc), UIntVal(RHS.UIntVal), FTy(RHS.FTy), + StrVal(RHS.StrVal), StrVal2(RHS.StrVal2), APSIntVal(RHS.APSIntVal), + APFloatVal(RHS.APFloatVal), ConstantVal(RHS.ConstantVal) { + assert(!RHS.ConstantStructElts); + } + + bool operator<(const ValID &RHS) const { + if (Kind == t_LocalID || Kind == t_GlobalID) + return UIntVal < RHS.UIntVal; + assert((Kind == t_LocalName || Kind == t_GlobalName || + Kind == t_ConstantStruct || Kind == t_PackedConstantStruct) && + "Ordering not defined for this ValID kind yet"); + return StrVal < RHS.StrVal; + } + }; + + class LLParser { + public: + typedef LLLexer::LocTy LocTy; + private: + LLVMContext &Context; + LLLexer Lex; + // Module being parsed, null if we are only parsing summary index. + Module *M; + // Summary index being parsed, null if we are only parsing Module. + ModuleSummaryIndex *Index; + SlotMapping *Slots; + + // Instruction metadata resolution. Each instruction can have a list of + // MDRef info associated with them. + // + // The simpler approach of just creating temporary MDNodes and then calling + // RAUW on them when the definition is processed doesn't work because some + // instruction metadata kinds, such as dbg, get stored in the IR in an + // "optimized" format which doesn't participate in the normal value use + // lists. This means that RAUW doesn't work, even on temporary MDNodes + // which otherwise support RAUW. Instead, we defer resolving MDNode + // references until the definitions have been processed. + struct MDRef { + SMLoc Loc; + unsigned MDKind, MDSlot; + }; + + SmallVector<Instruction*, 64> InstsWithTBAATag; + + // Type resolution handling data structures. The location is set when we + // have processed a use of the type but not a definition yet. + StringMap<std::pair<Type*, LocTy> > NamedTypes; + std::map<unsigned, std::pair<Type*, LocTy> > NumberedTypes; + + std::map<unsigned, TrackingMDNodeRef> NumberedMetadata; + std::map<unsigned, std::pair<TempMDTuple, LocTy>> ForwardRefMDNodes; + + // Global Value reference information. + std::map<std::string, std::pair<GlobalValue*, LocTy> > ForwardRefVals; + std::map<unsigned, std::pair<GlobalValue*, LocTy> > ForwardRefValIDs; + std::vector<GlobalValue*> NumberedVals; + + // Comdat forward reference information. + std::map<std::string, LocTy> ForwardRefComdats; + + // References to blockaddress. The key is the function ValID, the value is + // a list of references to blocks in that function. + std::map<ValID, std::map<ValID, GlobalValue *>> ForwardRefBlockAddresses; + class PerFunctionState; + /// Reference to per-function state to allow basic blocks to be + /// forward-referenced by blockaddress instructions within the same + /// function. + PerFunctionState *BlockAddressPFS; + + // Attribute builder reference information. + std::map<Value*, std::vector<unsigned> > ForwardRefAttrGroups; + std::map<unsigned, AttrBuilder> NumberedAttrBuilders; + + // Summary global value reference information. + std::map<unsigned, std::vector<std::pair<ValueInfo *, LocTy>>> + ForwardRefValueInfos; + std::map<unsigned, std::vector<std::pair<AliasSummary *, LocTy>>> + ForwardRefAliasees; + std::vector<ValueInfo> NumberedValueInfos; + + // Summary type id reference information. + std::map<unsigned, std::vector<std::pair<GlobalValue::GUID *, LocTy>>> + ForwardRefTypeIds; + + // Map of module ID to path. + std::map<unsigned, StringRef> ModuleIdMap; + + /// Only the llvm-as tool may set this to false to bypass + /// UpgradeDebuginfo so it can generate broken bitcode. + bool UpgradeDebugInfo; + + std::string SourceFileName; + + public: + LLParser(StringRef F, SourceMgr &SM, SMDiagnostic &Err, Module *M, + ModuleSummaryIndex *Index, LLVMContext &Context, + SlotMapping *Slots = nullptr) + : Context(Context), Lex(F, SM, Err, Context), M(M), Index(Index), + Slots(Slots), BlockAddressPFS(nullptr) {} + bool Run( bool UpgradeDebugInfo, DataLayoutCallbackTy DataLayoutCallback = [](StringRef) { return None; }); - - bool parseStandaloneConstantValue(Constant *&C, const SlotMapping *Slots); - - bool parseTypeAtBeginning(Type *&Ty, unsigned &Read, - const SlotMapping *Slots); - - LLVMContext &getContext() { return Context; } - - private: + + bool parseStandaloneConstantValue(Constant *&C, const SlotMapping *Slots); + + bool parseTypeAtBeginning(Type *&Ty, unsigned &Read, + const SlotMapping *Slots); + + LLVMContext &getContext() { return Context; } + + private: bool error(LocTy L, const Twine &Msg) const { return Lex.Error(L, Msg); } bool tokError(const Twine &Msg) const { return error(Lex.getLoc(), Msg); } - - /// Restore the internal name and slot mappings using the mappings that - /// were created at an earlier parsing stage. - void restoreParsingState(const SlotMapping *Slots); - + + /// Restore the internal name and slot mappings using the mappings that + /// were created at an earlier parsing stage. + void restoreParsingState(const SlotMapping *Slots); + /// getGlobalVal - Get a value with the specified name or ID, creating a - /// forward reference record if needed. This can return null if the value - /// exists but does not have the right type. + /// forward reference record if needed. This can return null if the value + /// exists but does not have the right type. GlobalValue *getGlobalVal(const std::string &N, Type *Ty, LocTy Loc, - bool IsCall); + bool IsCall); GlobalValue *getGlobalVal(unsigned ID, Type *Ty, LocTy Loc, bool IsCall); - - /// Get a Comdat with the specified name, creating a forward reference - /// record if needed. - Comdat *getComdat(const std::string &Name, LocTy Loc); - - // Helper Routines. + + /// Get a Comdat with the specified name, creating a forward reference + /// record if needed. + Comdat *getComdat(const std::string &Name, LocTy Loc); + + // Helper Routines. bool parseToken(lltok::Kind T, const char *ErrMsg); - bool EatIfPresent(lltok::Kind T) { - if (Lex.getKind() != T) return false; - Lex.Lex(); - return true; - } - - FastMathFlags EatFastMathFlagsIfPresent() { - FastMathFlags FMF; - while (true) - switch (Lex.getKind()) { - case lltok::kw_fast: FMF.setFast(); Lex.Lex(); continue; - case lltok::kw_nnan: FMF.setNoNaNs(); Lex.Lex(); continue; - case lltok::kw_ninf: FMF.setNoInfs(); Lex.Lex(); continue; - case lltok::kw_nsz: FMF.setNoSignedZeros(); Lex.Lex(); continue; - case lltok::kw_arcp: FMF.setAllowReciprocal(); Lex.Lex(); continue; - case lltok::kw_contract: - FMF.setAllowContract(true); - Lex.Lex(); - continue; - case lltok::kw_reassoc: FMF.setAllowReassoc(); Lex.Lex(); continue; - case lltok::kw_afn: FMF.setApproxFunc(); Lex.Lex(); continue; - default: return FMF; - } - return FMF; - } - + bool EatIfPresent(lltok::Kind T) { + if (Lex.getKind() != T) return false; + Lex.Lex(); + return true; + } + + FastMathFlags EatFastMathFlagsIfPresent() { + FastMathFlags FMF; + while (true) + switch (Lex.getKind()) { + case lltok::kw_fast: FMF.setFast(); Lex.Lex(); continue; + case lltok::kw_nnan: FMF.setNoNaNs(); Lex.Lex(); continue; + case lltok::kw_ninf: FMF.setNoInfs(); Lex.Lex(); continue; + case lltok::kw_nsz: FMF.setNoSignedZeros(); Lex.Lex(); continue; + case lltok::kw_arcp: FMF.setAllowReciprocal(); Lex.Lex(); continue; + case lltok::kw_contract: + FMF.setAllowContract(true); + Lex.Lex(); + continue; + case lltok::kw_reassoc: FMF.setAllowReassoc(); Lex.Lex(); continue; + case lltok::kw_afn: FMF.setApproxFunc(); Lex.Lex(); continue; + default: return FMF; + } + return FMF; + } + bool parseOptionalToken(lltok::Kind T, bool &Present, - LocTy *Loc = nullptr) { - if (Lex.getKind() != T) { - Present = false; - } else { - if (Loc) - *Loc = Lex.getLoc(); - Lex.Lex(); - Present = true; - } - return false; - } + LocTy *Loc = nullptr) { + if (Lex.getKind() != T) { + Present = false; + } else { + if (Loc) + *Loc = Lex.getLoc(); + Lex.Lex(); + Present = true; + } + return false; + } bool parseStringConstant(std::string &Result); bool parseUInt32(unsigned &Val); bool parseUInt32(unsigned &Val, LocTy &Loc) { - Loc = Lex.getLoc(); + Loc = Lex.getLoc(); return parseUInt32(Val); - } + } bool parseUInt64(uint64_t &Val); bool parseUInt64(uint64_t &Val, LocTy &Loc) { - Loc = Lex.getLoc(); + Loc = Lex.getLoc(); return parseUInt64(Val); - } + } bool parseFlag(unsigned &Val); - + bool parseStringAttribute(AttrBuilder &B); - + bool parseTLSModel(GlobalVariable::ThreadLocalMode &TLM); bool parseOptionalThreadLocal(GlobalVariable::ThreadLocalMode &TLM); bool parseOptionalUnnamedAddr(GlobalVariable::UnnamedAddr &UnnamedAddr); bool parseOptionalAddrSpace(unsigned &AddrSpace, unsigned DefaultAS = 0); bool parseOptionalProgramAddrSpace(unsigned &AddrSpace) { return parseOptionalAddrSpace( - AddrSpace, M->getDataLayout().getProgramAddressSpace()); - }; + AddrSpace, M->getDataLayout().getProgramAddressSpace()); + }; bool parseOptionalParamAttrs(AttrBuilder &B); bool parseOptionalReturnAttrs(AttrBuilder &B); bool parseOptionalLinkage(unsigned &Res, bool &HasLinkage, - unsigned &Visibility, unsigned &DLLStorageClass, - bool &DSOLocal); + unsigned &Visibility, unsigned &DLLStorageClass, + bool &DSOLocal); void parseOptionalDSOLocal(bool &DSOLocal); void parseOptionalVisibility(unsigned &Res); void parseOptionalDLLStorageClass(unsigned &Res); bool parseOptionalCallingConv(unsigned &CC); bool parseOptionalAlignment(MaybeAlign &Alignment, - bool AllowParens = false); + bool AllowParens = false); bool parseOptionalDerefAttrBytes(lltok::Kind AttrKind, uint64_t &Bytes); bool parseScopeAndOrdering(bool IsAtomic, SyncScope::ID &SSID, - AtomicOrdering &Ordering); + AtomicOrdering &Ordering); bool parseScope(SyncScope::ID &SSID); bool parseOrdering(AtomicOrdering &Ordering); bool parseOptionalStackAlignment(unsigned &Alignment); bool parseOptionalCommaAlign(MaybeAlign &Alignment, bool &AteExtraComma); bool parseOptionalCommaAddrSpace(unsigned &AddrSpace, LocTy &Loc, - bool &AteExtraComma); + bool &AteExtraComma); bool parseOptionalCommaInAlloca(bool &IsInAlloca); - bool parseAllocSizeArguments(unsigned &BaseSizeArg, - Optional<unsigned> &HowManyArg); + bool parseAllocSizeArguments(unsigned &BaseSizeArg, + Optional<unsigned> &HowManyArg); bool parseIndexList(SmallVectorImpl<unsigned> &Indices, - bool &AteExtraComma); + bool &AteExtraComma); bool parseIndexList(SmallVectorImpl<unsigned> &Indices) { - bool AteExtraComma; + bool AteExtraComma; if (parseIndexList(Indices, AteExtraComma)) return true; - if (AteExtraComma) + if (AteExtraComma) return tokError("expected index"); - return false; - } - - // Top-Level Entities + return false; + } + + // Top-Level Entities bool parseTopLevelEntities(); bool validateEndOfModule(bool UpgradeDebugInfo); bool validateEndOfIndex(); @@ -305,34 +305,34 @@ namespace llvm { bool parseNamedType(); bool parseDeclare(); bool parseDefine(); - + bool parseGlobalType(bool &IsConstant); bool parseUnnamedGlobal(); bool parseNamedGlobal(); bool parseGlobal(const std::string &Name, LocTy NameLoc, unsigned Linkage, - bool HasLinkage, unsigned Visibility, - unsigned DLLStorageClass, bool DSOLocal, - GlobalVariable::ThreadLocalMode TLM, - GlobalVariable::UnnamedAddr UnnamedAddr); - bool parseIndirectSymbol(const std::string &Name, LocTy NameLoc, - unsigned L, unsigned Visibility, - unsigned DLLStorageClass, bool DSOLocal, - GlobalVariable::ThreadLocalMode TLM, - GlobalVariable::UnnamedAddr UnnamedAddr); - bool parseComdat(); + bool HasLinkage, unsigned Visibility, + unsigned DLLStorageClass, bool DSOLocal, + GlobalVariable::ThreadLocalMode TLM, + GlobalVariable::UnnamedAddr UnnamedAddr); + bool parseIndirectSymbol(const std::string &Name, LocTy NameLoc, + unsigned L, unsigned Visibility, + unsigned DLLStorageClass, bool DSOLocal, + GlobalVariable::ThreadLocalMode TLM, + GlobalVariable::UnnamedAddr UnnamedAddr); + bool parseComdat(); bool parseStandaloneMetadata(); bool parseNamedMetadata(); bool parseMDString(MDString *&Result); bool parseMDNodeID(MDNode *&Result); bool parseUnnamedAttrGrp(); bool parseFnAttributeValuePairs(AttrBuilder &B, - std::vector<unsigned> &FwdRefAttrGrps, - bool inAttrGrp, LocTy &BuiltinLoc); + std::vector<unsigned> &FwdRefAttrGrps, + bool inAttrGrp, LocTy &BuiltinLoc); bool parseRequiredTypeAttr(Type *&Result, lltok::Kind AttrName); bool parsePreallocated(Type *&Result); bool parseByRef(Type *&Result); - - // Module Summary Index Parsing. + + // Module Summary Index Parsing. bool skipModuleSummaryEntry(); bool parseSummaryEntry(); bool parseModuleEntry(unsigned ID); @@ -352,19 +352,19 @@ namespace llvm { bool parseOptionalTypeIdInfo(FunctionSummary::TypeIdInfo &TypeIdInfo); bool parseTypeTests(std::vector<GlobalValue::GUID> &TypeTests); bool parseVFuncIdList(lltok::Kind Kind, - std::vector<FunctionSummary::VFuncId> &VFuncIdList); + std::vector<FunctionSummary::VFuncId> &VFuncIdList); bool parseConstVCallList( - lltok::Kind Kind, - std::vector<FunctionSummary::ConstVCall> &ConstVCallList); - using IdToIndexMapType = - std::map<unsigned, std::vector<std::pair<unsigned, LocTy>>>; + lltok::Kind Kind, + std::vector<FunctionSummary::ConstVCall> &ConstVCallList); + using IdToIndexMapType = + std::map<unsigned, std::vector<std::pair<unsigned, LocTy>>>; bool parseConstVCall(FunctionSummary::ConstVCall &ConstVCall, - IdToIndexMapType &IdToIndexMap, unsigned Index); + IdToIndexMapType &IdToIndexMap, unsigned Index); bool parseVFuncId(FunctionSummary::VFuncId &VFuncId, - IdToIndexMapType &IdToIndexMap, unsigned Index); + IdToIndexMapType &IdToIndexMap, unsigned Index); bool parseOptionalVTableFuncs(VTableFuncList &VTableFuncs); bool parseOptionalParamAccesses( - std::vector<FunctionSummary::ParamAccess> &Params); + std::vector<FunctionSummary::ParamAccess> &Params); bool parseParamNo(uint64_t &ParamNo); using IdLocListType = std::vector<std::pair<unsigned, LocTy>>; bool parseParamAccess(FunctionSummary::ParamAccess &Param, @@ -378,143 +378,143 @@ namespace llvm { bool parseTypeIdCompatibleVtableEntry(unsigned ID); bool parseTypeTestResolution(TypeTestResolution &TTRes); bool parseOptionalWpdResolutions( - std::map<uint64_t, WholeProgramDevirtResolution> &WPDResMap); + std::map<uint64_t, WholeProgramDevirtResolution> &WPDResMap); bool parseWpdRes(WholeProgramDevirtResolution &WPDRes); bool parseOptionalResByArg( - std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg> - &ResByArg); + std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg> + &ResByArg); bool parseArgs(std::vector<uint64_t> &Args); void addGlobalValueToIndex(std::string Name, GlobalValue::GUID, - GlobalValue::LinkageTypes Linkage, unsigned ID, - std::unique_ptr<GlobalValueSummary> Summary); - - // Type Parsing. + GlobalValue::LinkageTypes Linkage, unsigned ID, + std::unique_ptr<GlobalValueSummary> Summary); + + // Type Parsing. bool parseType(Type *&Result, const Twine &Msg, bool AllowVoid = false); bool parseType(Type *&Result, bool AllowVoid = false) { return parseType(Result, "expected type", AllowVoid); - } + } bool parseType(Type *&Result, const Twine &Msg, LocTy &Loc, - bool AllowVoid = false) { - Loc = Lex.getLoc(); + bool AllowVoid = false) { + Loc = Lex.getLoc(); return parseType(Result, Msg, AllowVoid); - } + } bool parseType(Type *&Result, LocTy &Loc, bool AllowVoid = false) { - Loc = Lex.getLoc(); + Loc = Lex.getLoc(); return parseType(Result, AllowVoid); - } + } bool parseAnonStructType(Type *&Result, bool Packed); bool parseStructBody(SmallVectorImpl<Type *> &Body); bool parseStructDefinition(SMLoc TypeLoc, StringRef Name, std::pair<Type *, LocTy> &Entry, - Type *&ResultTy); - + Type *&ResultTy); + bool parseArrayVectorType(Type *&Result, bool IsVector); bool parseFunctionType(Type *&Result); - - // Function Semantic Analysis. - class PerFunctionState { - LLParser &P; - Function &F; - std::map<std::string, std::pair<Value*, LocTy> > ForwardRefVals; - std::map<unsigned, std::pair<Value*, LocTy> > ForwardRefValIDs; - std::vector<Value*> NumberedVals; - - /// FunctionNumber - If this is an unnamed function, this is the slot - /// number of it, otherwise it is -1. - int FunctionNumber; - public: - PerFunctionState(LLParser &p, Function &f, int functionNumber); - ~PerFunctionState(); - - Function &getFunction() const { return F; } - + + // Function Semantic Analysis. + class PerFunctionState { + LLParser &P; + Function &F; + std::map<std::string, std::pair<Value*, LocTy> > ForwardRefVals; + std::map<unsigned, std::pair<Value*, LocTy> > ForwardRefValIDs; + std::vector<Value*> NumberedVals; + + /// FunctionNumber - If this is an unnamed function, this is the slot + /// number of it, otherwise it is -1. + int FunctionNumber; + public: + PerFunctionState(LLParser &p, Function &f, int functionNumber); + ~PerFunctionState(); + + Function &getFunction() const { return F; } + bool finishFunction(); - - /// GetVal - Get a value with the specified name or ID, creating a - /// forward reference record if needed. This can return null if the value - /// exists but does not have the right type. + + /// GetVal - Get a value with the specified name or ID, creating a + /// forward reference record if needed. This can return null if the value + /// exists but does not have the right type. Value *getVal(const std::string &Name, Type *Ty, LocTy Loc, bool IsCall); Value *getVal(unsigned ID, Type *Ty, LocTy Loc, bool IsCall); - + /// setInstName - After an instruction is parsed and inserted into its - /// basic block, this installs its name. + /// basic block, this installs its name. bool setInstName(int NameID, const std::string &NameStr, LocTy NameLoc, - Instruction *Inst); - - /// GetBB - Get a basic block with the specified name or ID, creating a - /// forward reference record if needed. This can return null if the value - /// is not a BasicBlock. + Instruction *Inst); + + /// GetBB - Get a basic block with the specified name or ID, creating a + /// forward reference record if needed. This can return null if the value + /// is not a BasicBlock. BasicBlock *getBB(const std::string &Name, LocTy Loc); BasicBlock *getBB(unsigned ID, LocTy Loc); - - /// DefineBB - Define the specified basic block, which is either named or - /// unnamed. If there is an error, this returns null otherwise it returns - /// the block being defined. + + /// DefineBB - Define the specified basic block, which is either named or + /// unnamed. If there is an error, this returns null otherwise it returns + /// the block being defined. BasicBlock *defineBB(const std::string &Name, int NameID, LocTy Loc); - - bool resolveForwardRefBlockAddresses(); - }; - + + bool resolveForwardRefBlockAddresses(); + }; + bool convertValIDToValue(Type *Ty, ValID &ID, Value *&V, - PerFunctionState *PFS, bool IsCall); - - Value *checkValidVariableType(LocTy Loc, const Twine &Name, Type *Ty, - Value *Val, bool IsCall); - - bool parseConstantValue(Type *Ty, Constant *&C); + PerFunctionState *PFS, bool IsCall); + + Value *checkValidVariableType(LocTy Loc, const Twine &Name, Type *Ty, + Value *Val, bool IsCall); + + bool parseConstantValue(Type *Ty, Constant *&C); bool parseValue(Type *Ty, Value *&V, PerFunctionState *PFS); bool parseValue(Type *Ty, Value *&V, PerFunctionState &PFS) { return parseValue(Ty, V, &PFS); - } - + } + bool parseValue(Type *Ty, Value *&V, LocTy &Loc, PerFunctionState &PFS) { - Loc = Lex.getLoc(); + Loc = Lex.getLoc(); return parseValue(Ty, V, &PFS); - } - + } + bool parseTypeAndValue(Value *&V, PerFunctionState *PFS); bool parseTypeAndValue(Value *&V, PerFunctionState &PFS) { return parseTypeAndValue(V, &PFS); - } + } bool parseTypeAndValue(Value *&V, LocTy &Loc, PerFunctionState &PFS) { - Loc = Lex.getLoc(); + Loc = Lex.getLoc(); return parseTypeAndValue(V, PFS); - } + } bool parseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc, - PerFunctionState &PFS); + PerFunctionState &PFS); bool parseTypeAndBasicBlock(BasicBlock *&BB, PerFunctionState &PFS) { - LocTy Loc; + LocTy Loc; return parseTypeAndBasicBlock(BB, Loc, PFS); - } - - struct ParamInfo { - LocTy Loc; - Value *V; - AttributeSet Attrs; - ParamInfo(LocTy loc, Value *v, AttributeSet attrs) - : Loc(loc), V(v), Attrs(attrs) {} - }; + } + + struct ParamInfo { + LocTy Loc; + Value *V; + AttributeSet Attrs; + ParamInfo(LocTy loc, Value *v, AttributeSet attrs) + : Loc(loc), V(v), Attrs(attrs) {} + }; bool parseParameterList(SmallVectorImpl<ParamInfo> &ArgList, PerFunctionState &PFS, bool IsMustTailCall = false, - bool InVarArgsFunc = false); - - bool + bool InVarArgsFunc = false); + + bool parseOptionalOperandBundles(SmallVectorImpl<OperandBundleDef> &BundleList, - PerFunctionState &PFS); - + PerFunctionState &PFS); + bool parseExceptionArgs(SmallVectorImpl<Value *> &Args, - PerFunctionState &PFS); - - // Constant Parsing. + PerFunctionState &PFS); + + // Constant Parsing. bool parseValID(ValID &ID, PerFunctionState *PFS = nullptr); bool parseGlobalValue(Type *Ty, Constant *&C); bool parseGlobalTypeAndValue(Constant *&V); bool parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts, - Optional<unsigned> *InRangeOp = nullptr); - bool parseOptionalComdat(StringRef GlobalName, Comdat *&C); + Optional<unsigned> *InRangeOp = nullptr); + bool parseOptionalComdat(StringRef GlobalName, Comdat *&C); bool parseMetadataAsValue(Value *&V, PerFunctionState &PFS); bool parseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg, - PerFunctionState *PFS); + PerFunctionState *PFS); bool parseMetadata(Metadata *&MD, PerFunctionState *PFS); bool parseMDTuple(MDNode *&MD, bool IsDistinct = false); bool parseMDNode(MDNode *&N); @@ -524,42 +524,42 @@ namespace llvm { bool parseInstructionMetadata(Instruction &Inst); bool parseGlobalObjectMetadataAttachment(GlobalObject &GO); bool parseOptionalFunctionMetadata(Function &F); - - template <class FieldTy> + + template <class FieldTy> bool parseMDField(LocTy Loc, StringRef Name, FieldTy &Result); template <class FieldTy> bool parseMDField(StringRef Name, FieldTy &Result); template <class ParserTy> bool parseMDFieldsImplBody(ParserTy ParseField); - template <class ParserTy> + template <class ParserTy> bool parseMDFieldsImpl(ParserTy ParseField, LocTy &ClosingLoc); bool parseSpecializedMDNode(MDNode *&N, bool IsDistinct = false); - -#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ + +#define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ bool parse##CLASS(MDNode *&Result, bool IsDistinct); -#include "llvm/IR/Metadata.def" - - // Function Parsing. - struct ArgInfo { - LocTy Loc; - Type *Ty; - AttributeSet Attrs; - std::string Name; - ArgInfo(LocTy L, Type *ty, AttributeSet Attr, const std::string &N) - : Loc(L), Ty(ty), Attrs(Attr), Name(N) {} - }; +#include "llvm/IR/Metadata.def" + + // Function Parsing. + struct ArgInfo { + LocTy Loc; + Type *Ty; + AttributeSet Attrs; + std::string Name; + ArgInfo(LocTy L, Type *ty, AttributeSet Attr, const std::string &N) + : Loc(L), Ty(ty), Attrs(Attr), Name(N) {} + }; bool parseArgumentList(SmallVectorImpl<ArgInfo> &ArgList, bool &IsVarArg); bool parseFunctionHeader(Function *&Fn, bool IsDefine); bool parseFunctionBody(Function &Fn); bool parseBasicBlock(PerFunctionState &PFS); - - enum TailCallType { TCT_None, TCT_Tail, TCT_MustTail }; - - // Instruction Parsing. Each instruction parsing routine can return with a - // normal result, an error result, or return having eaten an extra comma. - enum InstResult { InstNormal = 0, InstError = 1, InstExtraComma = 2 }; + + enum TailCallType { TCT_None, TCT_Tail, TCT_MustTail }; + + // Instruction Parsing. Each instruction parsing routine can return with a + // normal result, an error result, or return having eaten an extra comma. + enum InstResult { InstNormal = 0, InstError = 1, InstExtraComma = 2 }; int parseInstruction(Instruction *&Inst, BasicBlock *BB, - PerFunctionState &PFS); + PerFunctionState &PFS); bool parseCmpPredicate(unsigned &P, unsigned Opc); - + bool parseRet(Instruction *&Inst, BasicBlock *BB, PerFunctionState &PFS); bool parseBr(Instruction *&Inst, PerFunctionState &PFS); bool parseSwitch(Instruction *&Inst, PerFunctionState &PFS); @@ -572,9 +572,9 @@ namespace llvm { bool parseCatchPad(Instruction *&Inst, PerFunctionState &PFS); bool parseCleanupPad(Instruction *&Inst, PerFunctionState &PFS); bool parseCallBr(Instruction *&Inst, PerFunctionState &PFS); - + bool parseUnaryOp(Instruction *&Inst, PerFunctionState &PFS, unsigned Opc, - bool IsFP); + bool IsFP); bool parseArithmetic(Instruction *&Inst, PerFunctionState &PFS, unsigned Opc, bool IsFP); bool parseLogical(Instruction *&Inst, PerFunctionState &PFS, unsigned Opc); @@ -588,7 +588,7 @@ namespace llvm { int parsePHI(Instruction *&Inst, PerFunctionState &PFS); bool parseLandingPad(Instruction *&Inst, PerFunctionState &PFS); bool parseCall(Instruction *&Inst, PerFunctionState &PFS, - CallInst::TailCallKind TCK); + CallInst::TailCallKind TCK); int parseAlloc(Instruction *&Inst, PerFunctionState &PFS); int parseLoad(Instruction *&Inst, PerFunctionState &PFS); int parseStore(Instruction *&Inst, PerFunctionState &PFS); @@ -599,13 +599,13 @@ namespace llvm { int parseExtractValue(Instruction *&Inst, PerFunctionState &PFS); int parseInsertValue(Instruction *&Inst, PerFunctionState &PFS); bool parseFreeze(Instruction *&I, PerFunctionState &PFS); - - // Use-list order directives. + + // Use-list order directives. bool parseUseListOrder(PerFunctionState *PFS = nullptr); bool parseUseListOrderBB(); bool parseUseListOrderIndexes(SmallVectorImpl<unsigned> &Indexes); - bool sortUseListOrder(Value *V, ArrayRef<unsigned> Indexes, SMLoc Loc); - }; -} // End llvm namespace - -#endif + bool sortUseListOrder(Value *V, ArrayRef<unsigned> Indexes, SMLoc Loc); + }; +} // End llvm namespace + +#endif diff --git a/contrib/libs/llvm12/lib/AsmParser/LLToken.h b/contrib/libs/llvm12/lib/AsmParser/LLToken.h index 67af90b73f..5149f86183 100644 --- a/contrib/libs/llvm12/lib/AsmParser/LLToken.h +++ b/contrib/libs/llvm12/lib/AsmParser/LLToken.h @@ -1,491 +1,491 @@ -//===- LLToken.h - Token Codes for LLVM Assembly Files ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file defines the enums for the .ll lexer. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_ASMPARSER_LLTOKEN_H -#define LLVM_LIB_ASMPARSER_LLTOKEN_H - -namespace llvm { -namespace lltok { -enum Kind { - // Markers - Eof, - Error, - - // Tokens with no info. - dotdotdot, // ... - equal, - comma, // = , - star, // * - lsquare, - rsquare, // [ ] - lbrace, - rbrace, // { } - less, - greater, // < > - lparen, - rparen, // ( ) - exclaim, // ! - bar, // | - colon, // : - - kw_vscale, - kw_x, - kw_true, - kw_false, - kw_declare, - kw_define, - kw_global, - kw_constant, - - kw_dso_local, - kw_dso_preemptable, - - kw_private, - kw_internal, - kw_linkonce, - kw_linkonce_odr, - kw_weak, // Used as a linkage, and a modifier for "cmpxchg". - kw_weak_odr, - kw_appending, - kw_dllimport, - kw_dllexport, - kw_common, - kw_available_externally, - kw_default, - kw_hidden, - kw_protected, - kw_unnamed_addr, - kw_local_unnamed_addr, - kw_externally_initialized, - kw_extern_weak, - kw_external, - kw_thread_local, - kw_localdynamic, - kw_initialexec, - kw_localexec, - kw_zeroinitializer, - kw_undef, +//===- LLToken.h - Token Codes for LLVM Assembly Files ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the enums for the .ll lexer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_ASMPARSER_LLTOKEN_H +#define LLVM_LIB_ASMPARSER_LLTOKEN_H + +namespace llvm { +namespace lltok { +enum Kind { + // Markers + Eof, + Error, + + // Tokens with no info. + dotdotdot, // ... + equal, + comma, // = , + star, // * + lsquare, + rsquare, // [ ] + lbrace, + rbrace, // { } + less, + greater, // < > + lparen, + rparen, // ( ) + exclaim, // ! + bar, // | + colon, // : + + kw_vscale, + kw_x, + kw_true, + kw_false, + kw_declare, + kw_define, + kw_global, + kw_constant, + + kw_dso_local, + kw_dso_preemptable, + + kw_private, + kw_internal, + kw_linkonce, + kw_linkonce_odr, + kw_weak, // Used as a linkage, and a modifier for "cmpxchg". + kw_weak_odr, + kw_appending, + kw_dllimport, + kw_dllexport, + kw_common, + kw_available_externally, + kw_default, + kw_hidden, + kw_protected, + kw_unnamed_addr, + kw_local_unnamed_addr, + kw_externally_initialized, + kw_extern_weak, + kw_external, + kw_thread_local, + kw_localdynamic, + kw_initialexec, + kw_localexec, + kw_zeroinitializer, + kw_undef, kw_poison, - kw_null, - kw_none, - kw_to, - kw_caller, - kw_within, - kw_from, - kw_tail, - kw_musttail, - kw_notail, - kw_target, - kw_triple, - kw_source_filename, - kw_unwind, - kw_deplibs, // FIXME: Remove in 4.0 - kw_datalayout, - kw_volatile, - kw_atomic, - kw_unordered, - kw_monotonic, - kw_acquire, - kw_release, - kw_acq_rel, - kw_seq_cst, - kw_syncscope, - kw_nnan, - kw_ninf, - kw_nsz, - kw_arcp, - kw_contract, - kw_reassoc, - kw_afn, - kw_fast, - kw_nuw, - kw_nsw, - kw_exact, - kw_inbounds, - kw_inrange, - kw_align, - kw_addrspace, - kw_section, - kw_partition, - kw_alias, - kw_ifunc, - kw_module, - kw_asm, - kw_sideeffect, - kw_alignstack, - kw_inteldialect, - kw_gc, - kw_prefix, - kw_prologue, - kw_c, - - kw_cc, - kw_ccc, - kw_fastcc, - kw_coldcc, - kw_intel_ocl_bicc, - kw_cfguard_checkcc, - kw_x86_stdcallcc, - kw_x86_fastcallcc, - kw_x86_thiscallcc, - kw_x86_vectorcallcc, - kw_x86_regcallcc, - kw_arm_apcscc, - kw_arm_aapcscc, - kw_arm_aapcs_vfpcc, - kw_aarch64_vector_pcs, - kw_aarch64_sve_vector_pcs, - kw_msp430_intrcc, - kw_avr_intrcc, - kw_avr_signalcc, - kw_ptx_kernel, - kw_ptx_device, - kw_spir_kernel, - kw_spir_func, - kw_x86_64_sysvcc, - kw_win64cc, - kw_webkit_jscc, - kw_anyregcc, - kw_swiftcc, - kw_preserve_mostcc, - kw_preserve_allcc, - kw_ghccc, - kw_x86_intrcc, - kw_hhvmcc, - kw_hhvm_ccc, - kw_cxx_fast_tlscc, - kw_amdgpu_vs, - kw_amdgpu_ls, - kw_amdgpu_hs, - kw_amdgpu_es, - kw_amdgpu_gs, - kw_amdgpu_ps, - kw_amdgpu_cs, - kw_amdgpu_kernel, + kw_null, + kw_none, + kw_to, + kw_caller, + kw_within, + kw_from, + kw_tail, + kw_musttail, + kw_notail, + kw_target, + kw_triple, + kw_source_filename, + kw_unwind, + kw_deplibs, // FIXME: Remove in 4.0 + kw_datalayout, + kw_volatile, + kw_atomic, + kw_unordered, + kw_monotonic, + kw_acquire, + kw_release, + kw_acq_rel, + kw_seq_cst, + kw_syncscope, + kw_nnan, + kw_ninf, + kw_nsz, + kw_arcp, + kw_contract, + kw_reassoc, + kw_afn, + kw_fast, + kw_nuw, + kw_nsw, + kw_exact, + kw_inbounds, + kw_inrange, + kw_align, + kw_addrspace, + kw_section, + kw_partition, + kw_alias, + kw_ifunc, + kw_module, + kw_asm, + kw_sideeffect, + kw_alignstack, + kw_inteldialect, + kw_gc, + kw_prefix, + kw_prologue, + kw_c, + + kw_cc, + kw_ccc, + kw_fastcc, + kw_coldcc, + kw_intel_ocl_bicc, + kw_cfguard_checkcc, + kw_x86_stdcallcc, + kw_x86_fastcallcc, + kw_x86_thiscallcc, + kw_x86_vectorcallcc, + kw_x86_regcallcc, + kw_arm_apcscc, + kw_arm_aapcscc, + kw_arm_aapcs_vfpcc, + kw_aarch64_vector_pcs, + kw_aarch64_sve_vector_pcs, + kw_msp430_intrcc, + kw_avr_intrcc, + kw_avr_signalcc, + kw_ptx_kernel, + kw_ptx_device, + kw_spir_kernel, + kw_spir_func, + kw_x86_64_sysvcc, + kw_win64cc, + kw_webkit_jscc, + kw_anyregcc, + kw_swiftcc, + kw_preserve_mostcc, + kw_preserve_allcc, + kw_ghccc, + kw_x86_intrcc, + kw_hhvmcc, + kw_hhvm_ccc, + kw_cxx_fast_tlscc, + kw_amdgpu_vs, + kw_amdgpu_ls, + kw_amdgpu_hs, + kw_amdgpu_es, + kw_amdgpu_gs, + kw_amdgpu_ps, + kw_amdgpu_cs, + kw_amdgpu_kernel, kw_amdgpu_gfx, - kw_tailcc, - - // Attributes: - kw_attributes, - kw_allocsize, - kw_alwaysinline, - kw_argmemonly, - kw_sanitize_address, - kw_sanitize_hwaddress, - kw_sanitize_memtag, - kw_builtin, - kw_byval, - kw_inalloca, - kw_cold, - kw_convergent, - kw_dereferenceable, - kw_dereferenceable_or_null, - kw_inaccessiblememonly, - kw_inaccessiblemem_or_argmemonly, - kw_inlinehint, - kw_inreg, - kw_jumptable, - kw_minsize, - kw_naked, - kw_nest, - kw_noalias, - kw_noundef, - kw_nobuiltin, + kw_tailcc, + + // Attributes: + kw_attributes, + kw_allocsize, + kw_alwaysinline, + kw_argmemonly, + kw_sanitize_address, + kw_sanitize_hwaddress, + kw_sanitize_memtag, + kw_builtin, + kw_byval, + kw_inalloca, + kw_cold, + kw_convergent, + kw_dereferenceable, + kw_dereferenceable_or_null, + kw_inaccessiblememonly, + kw_inaccessiblemem_or_argmemonly, + kw_inlinehint, + kw_inreg, + kw_jumptable, + kw_minsize, + kw_naked, + kw_nest, + kw_noalias, + kw_noundef, + kw_nobuiltin, kw_nocallback, - kw_nocapture, - kw_noduplicate, - kw_nofree, - kw_noimplicitfloat, - kw_noinline, - kw_norecurse, - kw_nonlazybind, - kw_nomerge, - kw_nonnull, + kw_nocapture, + kw_noduplicate, + kw_nofree, + kw_noimplicitfloat, + kw_noinline, + kw_norecurse, + kw_nonlazybind, + kw_nomerge, + kw_nonnull, kw_noprofile, - kw_noredzone, - kw_noreturn, - kw_nosync, - kw_nocf_check, - kw_nounwind, - kw_null_pointer_is_valid, - kw_optforfuzzing, - kw_optnone, - kw_optsize, - kw_preallocated, - kw_readnone, - kw_readonly, - kw_returned, - kw_returns_twice, - kw_signext, - kw_speculatable, - kw_ssp, - kw_sspreq, - kw_sspstrong, - kw_safestack, - kw_shadowcallstack, - kw_sret, - kw_sanitize_thread, - kw_sanitize_memory, - kw_speculative_load_hardening, - kw_strictfp, - kw_swifterror, - kw_swiftself, - kw_uwtable, - kw_willreturn, - kw_writeonly, - kw_zeroext, - kw_immarg, + kw_noredzone, + kw_noreturn, + kw_nosync, + kw_nocf_check, + kw_nounwind, + kw_null_pointer_is_valid, + kw_optforfuzzing, + kw_optnone, + kw_optsize, + kw_preallocated, + kw_readnone, + kw_readonly, + kw_returned, + kw_returns_twice, + kw_signext, + kw_speculatable, + kw_ssp, + kw_sspreq, + kw_sspstrong, + kw_safestack, + kw_shadowcallstack, + kw_sret, + kw_sanitize_thread, + kw_sanitize_memory, + kw_speculative_load_hardening, + kw_strictfp, + kw_swifterror, + kw_swiftself, + kw_uwtable, + kw_willreturn, + kw_writeonly, + kw_zeroext, + kw_immarg, kw_byref, kw_mustprogress, - - kw_type, - kw_opaque, - - kw_comdat, - - // Comdat types - kw_any, - kw_exactmatch, - kw_largest, - kw_noduplicates, - kw_samesize, - - kw_eq, - kw_ne, - kw_slt, - kw_sgt, - kw_sle, - kw_sge, - kw_ult, - kw_ugt, - kw_ule, - kw_uge, - kw_oeq, - kw_one, - kw_olt, - kw_ogt, - kw_ole, - kw_oge, - kw_ord, - kw_uno, - kw_ueq, - kw_une, - - // atomicrmw operations that aren't also instruction keywords. - kw_xchg, - kw_nand, - kw_max, - kw_min, - kw_umax, - kw_umin, - - // Instruction Opcodes (Opcode in UIntVal). - kw_fneg, - kw_add, - kw_fadd, - kw_sub, - kw_fsub, - kw_mul, - kw_fmul, - kw_udiv, - kw_sdiv, - kw_fdiv, - kw_urem, - kw_srem, - kw_frem, - kw_shl, - kw_lshr, - kw_ashr, - kw_and, - kw_or, - kw_xor, - kw_icmp, - kw_fcmp, - - kw_phi, - kw_call, - kw_trunc, - kw_zext, - kw_sext, - kw_fptrunc, - kw_fpext, - kw_uitofp, - kw_sitofp, - kw_fptoui, - kw_fptosi, - kw_inttoptr, - kw_ptrtoint, - kw_bitcast, - kw_addrspacecast, - kw_select, - kw_va_arg, - - kw_landingpad, - kw_personality, - kw_cleanup, - kw_catch, - kw_filter, - - kw_ret, - kw_br, - kw_switch, - kw_indirectbr, - kw_invoke, - kw_resume, - kw_unreachable, - kw_cleanupret, - kw_catchswitch, - kw_catchret, - kw_catchpad, - kw_cleanuppad, - kw_callbr, - - kw_alloca, - kw_load, - kw_store, - kw_fence, - kw_cmpxchg, - kw_atomicrmw, - kw_getelementptr, - - kw_extractelement, - kw_insertelement, - kw_shufflevector, - kw_extractvalue, - kw_insertvalue, - kw_blockaddress, + + kw_type, + kw_opaque, + + kw_comdat, + + // Comdat types + kw_any, + kw_exactmatch, + kw_largest, + kw_noduplicates, + kw_samesize, + + kw_eq, + kw_ne, + kw_slt, + kw_sgt, + kw_sle, + kw_sge, + kw_ult, + kw_ugt, + kw_ule, + kw_uge, + kw_oeq, + kw_one, + kw_olt, + kw_ogt, + kw_ole, + kw_oge, + kw_ord, + kw_uno, + kw_ueq, + kw_une, + + // atomicrmw operations that aren't also instruction keywords. + kw_xchg, + kw_nand, + kw_max, + kw_min, + kw_umax, + kw_umin, + + // Instruction Opcodes (Opcode in UIntVal). + kw_fneg, + kw_add, + kw_fadd, + kw_sub, + kw_fsub, + kw_mul, + kw_fmul, + kw_udiv, + kw_sdiv, + kw_fdiv, + kw_urem, + kw_srem, + kw_frem, + kw_shl, + kw_lshr, + kw_ashr, + kw_and, + kw_or, + kw_xor, + kw_icmp, + kw_fcmp, + + kw_phi, + kw_call, + kw_trunc, + kw_zext, + kw_sext, + kw_fptrunc, + kw_fpext, + kw_uitofp, + kw_sitofp, + kw_fptoui, + kw_fptosi, + kw_inttoptr, + kw_ptrtoint, + kw_bitcast, + kw_addrspacecast, + kw_select, + kw_va_arg, + + kw_landingpad, + kw_personality, + kw_cleanup, + kw_catch, + kw_filter, + + kw_ret, + kw_br, + kw_switch, + kw_indirectbr, + kw_invoke, + kw_resume, + kw_unreachable, + kw_cleanupret, + kw_catchswitch, + kw_catchret, + kw_catchpad, + kw_cleanuppad, + kw_callbr, + + kw_alloca, + kw_load, + kw_store, + kw_fence, + kw_cmpxchg, + kw_atomicrmw, + kw_getelementptr, + + kw_extractelement, + kw_insertelement, + kw_shufflevector, + kw_extractvalue, + kw_insertvalue, + kw_blockaddress, kw_dso_local_equivalent, - - kw_freeze, - - // Metadata types. - kw_distinct, - - // Use-list order directives. - kw_uselistorder, - kw_uselistorder_bb, - - // Summary index keywords - kw_path, - kw_hash, - kw_gv, - kw_guid, - kw_name, - kw_summaries, - kw_flags, - kw_blockcount, - kw_linkage, - kw_notEligibleToImport, - kw_live, - kw_dsoLocal, - kw_canAutoHide, - kw_function, - kw_insts, - kw_funcFlags, - kw_readNone, - kw_readOnly, - kw_noRecurse, - kw_returnDoesNotAlias, - kw_noInline, - kw_alwaysInline, - kw_calls, - kw_callee, - kw_params, - kw_param, - kw_hotness, - kw_unknown, - kw_hot, - kw_critical, - kw_relbf, - kw_variable, - kw_vTableFuncs, - kw_virtFunc, - kw_aliasee, - kw_refs, - kw_typeIdInfo, - kw_typeTests, - kw_typeTestAssumeVCalls, - kw_typeCheckedLoadVCalls, - kw_typeTestAssumeConstVCalls, - kw_typeCheckedLoadConstVCalls, - kw_vFuncId, - kw_offset, - kw_args, - kw_typeid, - kw_typeidCompatibleVTable, - kw_summary, - kw_typeTestRes, - kw_kind, - kw_unsat, - kw_byteArray, - kw_inline, - kw_single, - kw_allOnes, - kw_sizeM1BitWidth, - kw_alignLog2, - kw_sizeM1, - kw_bitMask, - kw_inlineBits, - kw_vcall_visibility, - kw_wpdResolutions, - kw_wpdRes, - kw_indir, - kw_singleImpl, - kw_branchFunnel, - kw_singleImplName, - kw_resByArg, - kw_byArg, - kw_uniformRetVal, - kw_uniqueRetVal, - kw_virtualConstProp, - kw_info, - kw_byte, - kw_bit, - kw_varFlags, - - // Unsigned Valued tokens (UIntVal). - LabelID, // 42: - GlobalID, // @42 - LocalVarID, // %42 - AttrGrpID, // #42 - SummaryID, // ^42 - - // String valued tokens (StrVal). - LabelStr, // foo: - GlobalVar, // @foo @"foo" - ComdatVar, // $foo - LocalVar, // %foo %"foo" - MetadataVar, // !foo - StringConstant, // "foo" - DwarfTag, // DW_TAG_foo - DwarfAttEncoding, // DW_ATE_foo - DwarfVirtuality, // DW_VIRTUALITY_foo - DwarfLang, // DW_LANG_foo - DwarfCC, // DW_CC_foo - EmissionKind, // lineTablesOnly - NameTableKind, // GNU - DwarfOp, // DW_OP_foo - DIFlag, // DIFlagFoo - DISPFlag, // DISPFlagFoo - DwarfMacinfo, // DW_MACINFO_foo - ChecksumKind, // CSK_foo - - // Type valued tokens (TyVal). - Type, - - APFloat, // APFloatVal - APSInt // APSInt -}; -} // end namespace lltok -} // end namespace llvm - -#endif + + kw_freeze, + + // Metadata types. + kw_distinct, + + // Use-list order directives. + kw_uselistorder, + kw_uselistorder_bb, + + // Summary index keywords + kw_path, + kw_hash, + kw_gv, + kw_guid, + kw_name, + kw_summaries, + kw_flags, + kw_blockcount, + kw_linkage, + kw_notEligibleToImport, + kw_live, + kw_dsoLocal, + kw_canAutoHide, + kw_function, + kw_insts, + kw_funcFlags, + kw_readNone, + kw_readOnly, + kw_noRecurse, + kw_returnDoesNotAlias, + kw_noInline, + kw_alwaysInline, + kw_calls, + kw_callee, + kw_params, + kw_param, + kw_hotness, + kw_unknown, + kw_hot, + kw_critical, + kw_relbf, + kw_variable, + kw_vTableFuncs, + kw_virtFunc, + kw_aliasee, + kw_refs, + kw_typeIdInfo, + kw_typeTests, + kw_typeTestAssumeVCalls, + kw_typeCheckedLoadVCalls, + kw_typeTestAssumeConstVCalls, + kw_typeCheckedLoadConstVCalls, + kw_vFuncId, + kw_offset, + kw_args, + kw_typeid, + kw_typeidCompatibleVTable, + kw_summary, + kw_typeTestRes, + kw_kind, + kw_unsat, + kw_byteArray, + kw_inline, + kw_single, + kw_allOnes, + kw_sizeM1BitWidth, + kw_alignLog2, + kw_sizeM1, + kw_bitMask, + kw_inlineBits, + kw_vcall_visibility, + kw_wpdResolutions, + kw_wpdRes, + kw_indir, + kw_singleImpl, + kw_branchFunnel, + kw_singleImplName, + kw_resByArg, + kw_byArg, + kw_uniformRetVal, + kw_uniqueRetVal, + kw_virtualConstProp, + kw_info, + kw_byte, + kw_bit, + kw_varFlags, + + // Unsigned Valued tokens (UIntVal). + LabelID, // 42: + GlobalID, // @42 + LocalVarID, // %42 + AttrGrpID, // #42 + SummaryID, // ^42 + + // String valued tokens (StrVal). + LabelStr, // foo: + GlobalVar, // @foo @"foo" + ComdatVar, // $foo + LocalVar, // %foo %"foo" + MetadataVar, // !foo + StringConstant, // "foo" + DwarfTag, // DW_TAG_foo + DwarfAttEncoding, // DW_ATE_foo + DwarfVirtuality, // DW_VIRTUALITY_foo + DwarfLang, // DW_LANG_foo + DwarfCC, // DW_CC_foo + EmissionKind, // lineTablesOnly + NameTableKind, // GNU + DwarfOp, // DW_OP_foo + DIFlag, // DIFlagFoo + DISPFlag, // DISPFlagFoo + DwarfMacinfo, // DW_MACINFO_foo + ChecksumKind, // CSK_foo + + // Type valued tokens (TyVal). + Type, + + APFloat, // APFloatVal + APSInt // APSInt +}; +} // end namespace lltok +} // end namespace llvm + +#endif diff --git a/contrib/libs/llvm12/lib/AsmParser/Parser.cpp b/contrib/libs/llvm12/lib/AsmParser/Parser.cpp index fb98646201..8147620181 100644 --- a/contrib/libs/llvm12/lib/AsmParser/Parser.cpp +++ b/contrib/libs/llvm12/lib/AsmParser/Parser.cpp @@ -1,221 +1,221 @@ -//===- Parser.cpp - Main dispatch module for the Parser library -----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This library implements the functionality defined in llvm/AsmParser/Parser.h -// -//===----------------------------------------------------------------------===// - -#include "llvm/AsmParser/Parser.h" -#include "LLParser.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/ModuleSummaryIndex.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SourceMgr.h" -#include <cstring> -#include <system_error> - -using namespace llvm; - -static bool parseAssemblyInto(MemoryBufferRef F, Module *M, - ModuleSummaryIndex *Index, SMDiagnostic &Err, - SlotMapping *Slots, bool UpgradeDebugInfo, - DataLayoutCallbackTy DataLayoutCallback) { - SourceMgr SM; - std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(F); - SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); - - LLVMContext Context; - return LLParser(F.getBuffer(), SM, Err, M, Index, - M ? M->getContext() : Context, Slots) - .Run(UpgradeDebugInfo, DataLayoutCallback); -} - -bool llvm::parseAssemblyInto(MemoryBufferRef F, Module *M, - ModuleSummaryIndex *Index, SMDiagnostic &Err, - SlotMapping *Slots, - DataLayoutCallbackTy DataLayoutCallback) { - return ::parseAssemblyInto(F, M, Index, Err, Slots, - /*UpgradeDebugInfo*/ true, DataLayoutCallback); -} - -std::unique_ptr<Module> -llvm::parseAssembly(MemoryBufferRef F, SMDiagnostic &Err, LLVMContext &Context, - SlotMapping *Slots, - DataLayoutCallbackTy DataLayoutCallback) { - std::unique_ptr<Module> M = - std::make_unique<Module>(F.getBufferIdentifier(), Context); - - if (parseAssemblyInto(F, M.get(), nullptr, Err, Slots, DataLayoutCallback)) - return nullptr; - - return M; -} - -std::unique_ptr<Module> llvm::parseAssemblyFile(StringRef Filename, - SMDiagnostic &Err, - LLVMContext &Context, - SlotMapping *Slots) { - ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = - MemoryBuffer::getFileOrSTDIN(Filename); - if (std::error_code EC = FileOrErr.getError()) { - Err = SMDiagnostic(Filename, SourceMgr::DK_Error, - "Could not open input file: " + EC.message()); - return nullptr; - } - - return parseAssembly(FileOrErr.get()->getMemBufferRef(), Err, Context, Slots); -} - -static ParsedModuleAndIndex -parseAssemblyWithIndex(MemoryBufferRef F, SMDiagnostic &Err, - LLVMContext &Context, SlotMapping *Slots, - bool UpgradeDebugInfo, - DataLayoutCallbackTy DataLayoutCallback) { - std::unique_ptr<Module> M = - std::make_unique<Module>(F.getBufferIdentifier(), Context); - std::unique_ptr<ModuleSummaryIndex> Index = - std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/true); - - if (parseAssemblyInto(F, M.get(), Index.get(), Err, Slots, UpgradeDebugInfo, - DataLayoutCallback)) - return {nullptr, nullptr}; - - return {std::move(M), std::move(Index)}; -} - -ParsedModuleAndIndex llvm::parseAssemblyWithIndex(MemoryBufferRef F, - SMDiagnostic &Err, - LLVMContext &Context, - SlotMapping *Slots) { - return ::parseAssemblyWithIndex(F, Err, Context, Slots, - /*UpgradeDebugInfo*/ true, - [](StringRef) { return None; }); -} - -static ParsedModuleAndIndex -parseAssemblyFileWithIndex(StringRef Filename, SMDiagnostic &Err, - LLVMContext &Context, SlotMapping *Slots, - bool UpgradeDebugInfo, - DataLayoutCallbackTy DataLayoutCallback) { - ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = - MemoryBuffer::getFileOrSTDIN(Filename); - if (std::error_code EC = FileOrErr.getError()) { - Err = SMDiagnostic(Filename, SourceMgr::DK_Error, - "Could not open input file: " + EC.message()); - return {nullptr, nullptr}; - } - - return parseAssemblyWithIndex(FileOrErr.get()->getMemBufferRef(), Err, - Context, Slots, UpgradeDebugInfo, - DataLayoutCallback); -} - -ParsedModuleAndIndex -llvm::parseAssemblyFileWithIndex(StringRef Filename, SMDiagnostic &Err, - LLVMContext &Context, SlotMapping *Slots, - DataLayoutCallbackTy DataLayoutCallback) { - return ::parseAssemblyFileWithIndex(Filename, Err, Context, Slots, - /*UpgradeDebugInfo*/ true, - DataLayoutCallback); -} - -ParsedModuleAndIndex llvm::parseAssemblyFileWithIndexNoUpgradeDebugInfo( - StringRef Filename, SMDiagnostic &Err, LLVMContext &Context, - SlotMapping *Slots, DataLayoutCallbackTy DataLayoutCallback) { - return ::parseAssemblyFileWithIndex(Filename, Err, Context, Slots, - /*UpgradeDebugInfo*/ false, - DataLayoutCallback); -} - -std::unique_ptr<Module> llvm::parseAssemblyString(StringRef AsmString, - SMDiagnostic &Err, - LLVMContext &Context, - SlotMapping *Slots) { - MemoryBufferRef F(AsmString, "<string>"); - return parseAssembly(F, Err, Context, Slots); -} - -static bool parseSummaryIndexAssemblyInto(MemoryBufferRef F, - ModuleSummaryIndex &Index, - SMDiagnostic &Err) { - SourceMgr SM; - std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(F); - SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); - - // The parser holds a reference to a context that is unused when parsing the - // index, but we need to initialize it. - LLVMContext unusedContext; - return LLParser(F.getBuffer(), SM, Err, nullptr, &Index, unusedContext) - .Run(true, [](StringRef) { return None; }); -} - -std::unique_ptr<ModuleSummaryIndex> -llvm::parseSummaryIndexAssembly(MemoryBufferRef F, SMDiagnostic &Err) { - std::unique_ptr<ModuleSummaryIndex> Index = - std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false); - - if (parseSummaryIndexAssemblyInto(F, *Index, Err)) - return nullptr; - - return Index; -} - -std::unique_ptr<ModuleSummaryIndex> -llvm::parseSummaryIndexAssemblyFile(StringRef Filename, SMDiagnostic &Err) { - ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = - MemoryBuffer::getFileOrSTDIN(Filename); - if (std::error_code EC = FileOrErr.getError()) { - Err = SMDiagnostic(Filename, SourceMgr::DK_Error, - "Could not open input file: " + EC.message()); - return nullptr; - } - - return parseSummaryIndexAssembly(FileOrErr.get()->getMemBufferRef(), Err); -} - -Constant *llvm::parseConstantValue(StringRef Asm, SMDiagnostic &Err, - const Module &M, const SlotMapping *Slots) { - SourceMgr SM; - std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm); - SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); - Constant *C; - if (LLParser(Asm, SM, Err, const_cast<Module *>(&M), nullptr, M.getContext()) - .parseStandaloneConstantValue(C, Slots)) - return nullptr; - return C; -} - -Type *llvm::parseType(StringRef Asm, SMDiagnostic &Err, const Module &M, - const SlotMapping *Slots) { - unsigned Read; - Type *Ty = parseTypeAtBeginning(Asm, Read, Err, M, Slots); - if (!Ty) - return nullptr; - if (Read != Asm.size()) { - SourceMgr SM; - std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm); - SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); - Err = SM.GetMessage(SMLoc::getFromPointer(Asm.begin() + Read), - SourceMgr::DK_Error, "expected end of string"); - return nullptr; - } - return Ty; -} -Type *llvm::parseTypeAtBeginning(StringRef Asm, unsigned &Read, - SMDiagnostic &Err, const Module &M, - const SlotMapping *Slots) { - SourceMgr SM; - std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm); - SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); - Type *Ty; - if (LLParser(Asm, SM, Err, const_cast<Module *>(&M), nullptr, M.getContext()) - .parseTypeAtBeginning(Ty, Read, Slots)) - return nullptr; - return Ty; -} +//===- Parser.cpp - Main dispatch module for the Parser library -----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This library implements the functionality defined in llvm/AsmParser/Parser.h +// +//===----------------------------------------------------------------------===// + +#include "llvm/AsmParser/Parser.h" +#include "LLParser.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/ModuleSummaryIndex.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include <cstring> +#include <system_error> + +using namespace llvm; + +static bool parseAssemblyInto(MemoryBufferRef F, Module *M, + ModuleSummaryIndex *Index, SMDiagnostic &Err, + SlotMapping *Slots, bool UpgradeDebugInfo, + DataLayoutCallbackTy DataLayoutCallback) { + SourceMgr SM; + std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(F); + SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); + + LLVMContext Context; + return LLParser(F.getBuffer(), SM, Err, M, Index, + M ? M->getContext() : Context, Slots) + .Run(UpgradeDebugInfo, DataLayoutCallback); +} + +bool llvm::parseAssemblyInto(MemoryBufferRef F, Module *M, + ModuleSummaryIndex *Index, SMDiagnostic &Err, + SlotMapping *Slots, + DataLayoutCallbackTy DataLayoutCallback) { + return ::parseAssemblyInto(F, M, Index, Err, Slots, + /*UpgradeDebugInfo*/ true, DataLayoutCallback); +} + +std::unique_ptr<Module> +llvm::parseAssembly(MemoryBufferRef F, SMDiagnostic &Err, LLVMContext &Context, + SlotMapping *Slots, + DataLayoutCallbackTy DataLayoutCallback) { + std::unique_ptr<Module> M = + std::make_unique<Module>(F.getBufferIdentifier(), Context); + + if (parseAssemblyInto(F, M.get(), nullptr, Err, Slots, DataLayoutCallback)) + return nullptr; + + return M; +} + +std::unique_ptr<Module> llvm::parseAssemblyFile(StringRef Filename, + SMDiagnostic &Err, + LLVMContext &Context, + SlotMapping *Slots) { + ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = + MemoryBuffer::getFileOrSTDIN(Filename); + if (std::error_code EC = FileOrErr.getError()) { + Err = SMDiagnostic(Filename, SourceMgr::DK_Error, + "Could not open input file: " + EC.message()); + return nullptr; + } + + return parseAssembly(FileOrErr.get()->getMemBufferRef(), Err, Context, Slots); +} + +static ParsedModuleAndIndex +parseAssemblyWithIndex(MemoryBufferRef F, SMDiagnostic &Err, + LLVMContext &Context, SlotMapping *Slots, + bool UpgradeDebugInfo, + DataLayoutCallbackTy DataLayoutCallback) { + std::unique_ptr<Module> M = + std::make_unique<Module>(F.getBufferIdentifier(), Context); + std::unique_ptr<ModuleSummaryIndex> Index = + std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/true); + + if (parseAssemblyInto(F, M.get(), Index.get(), Err, Slots, UpgradeDebugInfo, + DataLayoutCallback)) + return {nullptr, nullptr}; + + return {std::move(M), std::move(Index)}; +} + +ParsedModuleAndIndex llvm::parseAssemblyWithIndex(MemoryBufferRef F, + SMDiagnostic &Err, + LLVMContext &Context, + SlotMapping *Slots) { + return ::parseAssemblyWithIndex(F, Err, Context, Slots, + /*UpgradeDebugInfo*/ true, + [](StringRef) { return None; }); +} + +static ParsedModuleAndIndex +parseAssemblyFileWithIndex(StringRef Filename, SMDiagnostic &Err, + LLVMContext &Context, SlotMapping *Slots, + bool UpgradeDebugInfo, + DataLayoutCallbackTy DataLayoutCallback) { + ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = + MemoryBuffer::getFileOrSTDIN(Filename); + if (std::error_code EC = FileOrErr.getError()) { + Err = SMDiagnostic(Filename, SourceMgr::DK_Error, + "Could not open input file: " + EC.message()); + return {nullptr, nullptr}; + } + + return parseAssemblyWithIndex(FileOrErr.get()->getMemBufferRef(), Err, + Context, Slots, UpgradeDebugInfo, + DataLayoutCallback); +} + +ParsedModuleAndIndex +llvm::parseAssemblyFileWithIndex(StringRef Filename, SMDiagnostic &Err, + LLVMContext &Context, SlotMapping *Slots, + DataLayoutCallbackTy DataLayoutCallback) { + return ::parseAssemblyFileWithIndex(Filename, Err, Context, Slots, + /*UpgradeDebugInfo*/ true, + DataLayoutCallback); +} + +ParsedModuleAndIndex llvm::parseAssemblyFileWithIndexNoUpgradeDebugInfo( + StringRef Filename, SMDiagnostic &Err, LLVMContext &Context, + SlotMapping *Slots, DataLayoutCallbackTy DataLayoutCallback) { + return ::parseAssemblyFileWithIndex(Filename, Err, Context, Slots, + /*UpgradeDebugInfo*/ false, + DataLayoutCallback); +} + +std::unique_ptr<Module> llvm::parseAssemblyString(StringRef AsmString, + SMDiagnostic &Err, + LLVMContext &Context, + SlotMapping *Slots) { + MemoryBufferRef F(AsmString, "<string>"); + return parseAssembly(F, Err, Context, Slots); +} + +static bool parseSummaryIndexAssemblyInto(MemoryBufferRef F, + ModuleSummaryIndex &Index, + SMDiagnostic &Err) { + SourceMgr SM; + std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(F); + SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); + + // The parser holds a reference to a context that is unused when parsing the + // index, but we need to initialize it. + LLVMContext unusedContext; + return LLParser(F.getBuffer(), SM, Err, nullptr, &Index, unusedContext) + .Run(true, [](StringRef) { return None; }); +} + +std::unique_ptr<ModuleSummaryIndex> +llvm::parseSummaryIndexAssembly(MemoryBufferRef F, SMDiagnostic &Err) { + std::unique_ptr<ModuleSummaryIndex> Index = + std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false); + + if (parseSummaryIndexAssemblyInto(F, *Index, Err)) + return nullptr; + + return Index; +} + +std::unique_ptr<ModuleSummaryIndex> +llvm::parseSummaryIndexAssemblyFile(StringRef Filename, SMDiagnostic &Err) { + ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = + MemoryBuffer::getFileOrSTDIN(Filename); + if (std::error_code EC = FileOrErr.getError()) { + Err = SMDiagnostic(Filename, SourceMgr::DK_Error, + "Could not open input file: " + EC.message()); + return nullptr; + } + + return parseSummaryIndexAssembly(FileOrErr.get()->getMemBufferRef(), Err); +} + +Constant *llvm::parseConstantValue(StringRef Asm, SMDiagnostic &Err, + const Module &M, const SlotMapping *Slots) { + SourceMgr SM; + std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm); + SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); + Constant *C; + if (LLParser(Asm, SM, Err, const_cast<Module *>(&M), nullptr, M.getContext()) + .parseStandaloneConstantValue(C, Slots)) + return nullptr; + return C; +} + +Type *llvm::parseType(StringRef Asm, SMDiagnostic &Err, const Module &M, + const SlotMapping *Slots) { + unsigned Read; + Type *Ty = parseTypeAtBeginning(Asm, Read, Err, M, Slots); + if (!Ty) + return nullptr; + if (Read != Asm.size()) { + SourceMgr SM; + std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm); + SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); + Err = SM.GetMessage(SMLoc::getFromPointer(Asm.begin() + Read), + SourceMgr::DK_Error, "expected end of string"); + return nullptr; + } + return Ty; +} +Type *llvm::parseTypeAtBeginning(StringRef Asm, unsigned &Read, + SMDiagnostic &Err, const Module &M, + const SlotMapping *Slots) { + SourceMgr SM; + std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm); + SM.AddNewSourceBuffer(std::move(Buf), SMLoc()); + Type *Ty; + if (LLParser(Asm, SM, Err, const_cast<Module *>(&M), nullptr, M.getContext()) + .parseTypeAtBeginning(Ty, Read, Slots)) + return nullptr; + return Ty; +} diff --git a/contrib/libs/llvm12/lib/AsmParser/ya.make b/contrib/libs/llvm12/lib/AsmParser/ya.make index 8bf73335e8..a84b5563eb 100644 --- a/contrib/libs/llvm12/lib/AsmParser/ya.make +++ b/contrib/libs/llvm12/lib/AsmParser/ya.make @@ -1,36 +1,36 @@ -# Generated by devtools/yamaker. - -LIBRARY() - +# Generated by devtools/yamaker. + +LIBRARY() + OWNER( orivej g:cpp-contrib ) - + LICENSE(Apache-2.0 WITH LLVM-exception) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -PEERDIR( +PEERDIR( contrib/libs/llvm12 contrib/libs/llvm12/include contrib/libs/llvm12/lib/BinaryFormat contrib/libs/llvm12/lib/IR contrib/libs/llvm12/lib/Support -) - +) + ADDINCL( contrib/libs/llvm12/lib/AsmParser ) - -NO_COMPILER_WARNINGS() - -NO_UTIL() - -SRCS( - LLLexer.cpp - LLParser.cpp - Parser.cpp -) - -END() + +NO_COMPILER_WARNINGS() + +NO_UTIL() + +SRCS( + LLLexer.cpp + LLParser.cpp + Parser.cpp +) + +END() |