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/LLParser.cpp | |
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/LLParser.cpp')
-rw-r--r-- | contrib/libs/llvm12/lib/AsmParser/LLParser.cpp | 14970 |
1 files changed, 7485 insertions, 7485 deletions
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; +} |