| //===-- 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 "llvm/AsmParser/LLParser.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/LLToken.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/Instructions.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) { |
| if (parseTargetDefinitions()) |
| 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; |
| if (parseType(Ty) || parseConstantValue(Ty, C)) |
| 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; |
| 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()))); |
| } |
| |
| /// validateEndOfModule - Do final validity and basic correctness checks at the |
| /// end of the 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.getFnAttrs()); |
| AS = AS.removeFnAttributes(Context); |
| |
| 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.addFnAttributes(Context, AttributeSet::get(Context, FnAttrs)); |
| Fn->setAttributes(AS); |
| } else if (CallInst *CI = dyn_cast<CallInst>(V)) { |
| AttributeList AS = CI->getAttributes(); |
| AttrBuilder FnAttrs(AS.getFnAttrs()); |
| AS = AS.removeFnAttributes(Context); |
| FnAttrs.merge(B); |
| AS = AS.addFnAttributes(Context, AttributeSet::get(Context, FnAttrs)); |
| CI->setAttributes(AS); |
| } else if (InvokeInst *II = dyn_cast<InvokeInst>(V)) { |
| AttributeList AS = II->getAttributes(); |
| AttrBuilder FnAttrs(AS.getFnAttrs()); |
| AS = AS.removeFnAttributes(Context); |
| FnAttrs.merge(B); |
| AS = AS.addFnAttributes(Context, AttributeSet::get(Context, FnAttrs)); |
| II->setAttributes(AS); |
| } else if (CallBrInst *CBI = dyn_cast<CallBrInst>(V)) { |
| AttributeList AS = CBI->getAttributes(); |
| AttrBuilder FnAttrs(AS.getFnAttrs()); |
| AS = AS.removeFnAttributes(Context); |
| FnAttrs.merge(B); |
| AS = AS.addFnAttributes(Context, 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()) |
| 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()) |
| return error(I->second.second, |
| "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()) |
| return error(ForwardRefVals.begin()->second.second, |
| "use of undefined value '@" + ForwardRefVals.begin()->first + |
| "'"); |
| |
| if (!ForwardRefValIDs.empty()) |
| return error(ForwardRefValIDs.begin()->second.second, |
| "use of undefined value '@" + |
| Twine(ForwardRefValIDs.begin()->first) + "'"); |
| |
| if (!ForwardRefMDNodes.empty()) |
| return error(ForwardRefMDNodes.begin()->second.second, |
| "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. We use |
| // make_early_inc_range here because we may remove some functions. |
| for (Function &F : llvm::make_early_inc_range(*M)) |
| UpgradeCallsToIntrinsic(&F); |
| |
| // 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 (Function &F : llvm::make_early_inc_range(*M)) { |
| 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 basic correctness checks at the end of the index. |
| bool LLParser::validateEndOfIndex() { |
| 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()) |
| return error(ForwardRefAliasees.begin()->second.front().second, |
| "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 |
| //===----------------------------------------------------------------------===// |
| |
| bool LLParser::parseTargetDefinitions() { |
| while (true) { |
| switch (Lex.getKind()) { |
| case lltok::kw_target: |
| if (parseTargetDefinition()) |
| return true; |
| break; |
| case lltok::kw_source_filename: |
| if (parseSourceFileName()) |
| 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 (parseSummaryEntry()) |
| return true; |
| break; |
| case lltok::kw_source_filename: |
| if (parseSourceFileName()) |
| 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::kw_declare: |
| if (parseDeclare()) |
| return true; |
| break; |
| case lltok::kw_define: |
| if (parseDefine()) |
| return true; |
| break; |
| case lltok::kw_module: |
| if (parseModuleAsm()) |
| return true; |
| break; |
| case lltok::LocalVarID: |
| if (parseUnnamedType()) |
| return true; |
| break; |
| case lltok::LocalVar: |
| if (parseNamedType()) |
| return true; |
| break; |
| case lltok::GlobalID: |
| if (parseUnnamedGlobal()) |
| return true; |
| break; |
| case lltok::GlobalVar: |
| if (parseNamedGlobal()) |
| return true; |
| break; |
| case lltok::ComdatVar: if (parseComdat()) return true; break; |
| case lltok::exclaim: |
| if (parseStandaloneMetadata()) |
| return true; |
| break; |
| case lltok::SummaryID: |
| if (parseSummaryEntry()) |
| return true; |
| break; |
| case lltok::MetadataVar: |
| if (parseNamedMetadata()) |
| return true; |
| break; |
| case lltok::kw_attributes: |
| if (parseUnnamedAttrGrp()) |
| return true; |
| break; |
| case lltok::kw_uselistorder: |
| if (parseUseListOrder()) |
| return true; |
| break; |
| case lltok::kw_uselistorder_bb: |
| if (parseUseListOrderBB()) |
| return true; |
| break; |
| } |
| } |
| } |
| |
| /// toplevelentity |
| /// ::= 'module' 'asm' STRINGCONSTANT |
| bool LLParser::parseModuleAsm() { |
| 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 |
| bool LLParser::parseTargetDefinition() { |
| assert(Lex.getKind() == lltok::kw_target); |
| std::string Str; |
| switch (Lex.Lex()) { |
| default: |
| return tokError("unknown target property"); |
| 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(); |
| if (parseToken(lltok::equal, "expected '=' after target datalayout") || |
| parseStringConstant(Str)) |
| return true; |
| M->setDataLayout(Str); |
| return false; |
| } |
| } |
| |
| /// toplevelentity |
| /// ::= 'source_filename' '=' STRINGCONSTANT |
| bool LLParser::parseSourceFileName() { |
| 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; |
| } |
| |
| /// parseUnnamedType: |
| /// ::= LocalVarID '=' 'type' type |
| bool LLParser::parseUnnamedType() { |
| 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; |
| if (parseStructDefinition(TypeLoc, "", NumberedTypes[TypeID], Result)) |
| return true; |
| |
| 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 |
| bool LLParser::parseNamedType() { |
| 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; |
| if (parseStructDefinition(NameLoc, Name, NamedTypes[Name], Result)) |
| return true; |
| |
| 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 |
| 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; |
| if (parseMetadataAttachment(MDK, N)) |
| 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)* '{' ... |
| bool LLParser::parseDefine() { |
| assert(Lex.getKind() == lltok::kw_define); |
| Lex.Lex(); |
| |
| Function *F; |
| return parseFunctionHeader(F, true) || parseOptionalFunctionMetadata(*F) || |
| parseFunctionBody(*F); |
| } |
| |
| /// parseGlobalType |
| /// ::= '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; |
| return tokError("expected 'global' or 'constant'"); |
| } |
| 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; |
| } |
| |
| /// parseUnnamedGlobal: |
| /// OptionalVisibility (ALIAS | IFUNC) ... |
| /// OptionalLinkage OptionalPreemptionSpecifier OptionalVisibility |
| /// OptionalDLLStorageClass |
| /// ... -> global variable |
| /// GlobalID '=' OptionalVisibility (ALIAS | IFUNC) ... |
| /// GlobalID '=' OptionalLinkage OptionalPreemptionSpecifier |
| /// OptionalVisibility |
| /// 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) |
| return error(Lex.getLoc(), |
| "variable expected to be numbered '%" + Twine(VarID) + "'"); |
| 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; |
| if (parseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass, |
| DSOLocal) || |
| parseOptionalThreadLocal(TLM) || parseOptionalUnnamedAddr(UnnamedAddr)) |
| return true; |
| |
| switch (Lex.getKind()) { |
| default: |
| return parseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility, |
| DLLStorageClass, DSOLocal, TLM, UnnamedAddr); |
| case lltok::kw_alias: |
| case lltok::kw_ifunc: |
| return parseAliasOrIFunc(Name, NameLoc, Linkage, Visibility, |
| DLLStorageClass, DSOLocal, TLM, UnnamedAddr); |
| } |
| } |
| |
| /// parseNamedGlobal: |
| /// 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; |
| if (parseToken(lltok::equal, "expected '=' in global variable") || |
| parseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass, |
| DSOLocal) || |
| parseOptionalThreadLocal(TLM) || parseOptionalUnnamedAddr(UnnamedAddr)) |
| return true; |
| |
| switch (Lex.getKind()) { |
| default: |
| return parseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility, |
| DLLStorageClass, DSOLocal, TLM, UnnamedAddr); |
| case lltok::kw_alias: |
| case lltok::kw_ifunc: |
| return parseAliasOrIFunc(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; |
| |
| if (parseToken(lltok::kw_comdat, "expected comdat keyword")) |
| return tokError("expected comdat type"); |
| |
| 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_nodeduplicate: |
| SK = Comdat::NoDeduplicate; |
| 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 |
| bool LLParser::parseMDString(MDString *&Result) { |
| std::string Str; |
| if (parseStringConstant(Str)) |
| return true; |
| Result = MDString::get(Context, Str); |
| return false; |
| } |
| |
| // MDNode: |
| // ::= '!' MDNodeNumber |
| bool LLParser::parseMDNodeID(MDNode *&Result) { |
| // !{ ..., !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; |
| } |
| |
| /// parseNamedMetadata: |
| /// !foo = !{ !1, !2 } |
| bool LLParser::parseNamedMetadata() { |
| 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; |
| // 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") { |
| if (parseDIExpression(N, /*IsDistinct=*/false)) |
| return true; |
| // DIArgLists should only appear inline in a function, as they may |
| // contain LocalAsMetadata arguments which require a function context. |
| } else if (Lex.getKind() == lltok::MetadataVar && |
| Lex.getStrVal() == "DIArgList") { |
| return tokError("found DIArgList outside of function"); |
| } else if (parseToken(lltok::exclaim, "Expected '!' here") || |
| parseMDNodeID(N)) { |
| return true; |
| } |
| NMD->addOperand(N); |
| } while (EatIfPresent(lltok::comma)); |
| |
| return parseToken(lltok::rbrace, "expected end of metadata node"); |
| } |
| |
| /// parseStandaloneMetadata: |
| /// !42 = !{...} |
| bool LLParser::parseStandaloneMetadata() { |
| 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 tokError("unexpected type in metadata definition"); |
| |
| bool IsDistinct = EatIfPresent(lltok::kw_distinct); |
| if (Lex.getKind() == lltok::MetadataVar) { |
| if (parseSpecializedMDNode(Init, IsDistinct)) |
| 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 tokError("Metadata id is already used"); |
| 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 |
| // 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 && |
| Lex.getKind() != lltok::kw_typeid && Lex.getKind() != lltok::kw_flags && |
| Lex.getKind() != lltok::kw_blockcount) |
| return tokError( |
| "Expected 'gv', 'module', 'typeid', 'flags' or 'blockcount' at the " |
| "start of summary entry"); |
| if (Lex.getKind() == lltok::kw_flags) |
| return parseSummaryIndexFlags(); |
| if (Lex.getKind() == lltok::kw_blockcount) |
| return parseBlockCount(); |
| 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 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 |
| 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(); |
| if (parseToken(lltok::equal, "expected '=' here")) |
| 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: |
| result = parseGVEntry(SummaryID); |
| break; |
| case lltok::kw_module: |
| result = parseModuleEntry(SummaryID); |
| break; |
| case lltok::kw_typeid: |
| result = parseTypeIdEntry(SummaryID); |
| break; |
| case lltok::kw_typeidCompatibleVTable: |
| result = parseTypeIdCompatibleVtableEntry(SummaryID); |
| break; |
| case lltok::kw_flags: |
| result = parseSummaryIndexFlags(); |
| break; |
| case lltok::kw_blockcount: |
| result = parseBlockCount(); |
| 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); |
| } |
| |
| static std::string typeComparisonErrorMessage(StringRef Message, Type *Ty1, |
| Type *Ty2) { |
| std::string ErrString; |
| raw_string_ostream ErrOS(ErrString); |
| ErrOS << Message << " (" << *Ty1 << " vs " << *Ty2 << ")"; |
| return ErrOS.str(); |
| } |
| |
| /// parseAliasOrIFunc: |
| /// ::= GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier |
| /// OptionalVisibility OptionalDLLStorageClass |
| /// OptionalThreadLocal OptionalUnnamedAddr |
| /// 'alias|ifunc' AliaseeOrResolver SymbolAttrs* |
| /// |
| /// AliaseeOrResolver |
| /// ::= TypeAndValue |
| /// |
| /// SymbolAttrs |
| /// ::= ',' 'partition' StringConstant |
| /// |
| /// Everything through OptionalUnnamedAddr has already been parsed. |
| /// |
| bool LLParser::parseAliasOrIFunc(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)) |
| return error(NameLoc, |
| "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) { |
| if (parseGlobalTypeAndValue(Aliasee)) |
| return true; |
| } else { |
| // The bitcast dest type is not present, it is implied by the dest type. |
| ValID ID; |
| if (parseValID(ID, /*PFS=*/nullptr)) |
| 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) |
| return error(AliaseeLoc, "An alias or ifunc must have pointer type"); |
| unsigned AddrSpace = PTy->getAddressSpace(); |
| |
| if (IsAlias && !PTy->isOpaqueOrPointeeTypeMatches(Ty)) { |
| return error( |
| ExplicitTypeLoc, |
| typeComparisonErrorMessage( |
| "explicit pointee type doesn't match operand's pointee type", Ty, |
| PTy->getElementType())); |
| } |
| |
| 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()) { |
| auto I = ForwardRefVals.find(Name); |
| if (I != ForwardRefVals.end()) { |
| GVal = I->second.first; |
| ForwardRefVals.erase(Name); |
| } else if (M->getNamedValue(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/ifunc but do not insert it into the module yet. |
| std::unique_ptr<GlobalAlias> GA; |
| std::unique_ptr<GlobalIFunc> GI; |
| GlobalValue *GV; |
| if (IsAlias) { |
| GA.reset(GlobalAlias::create(Ty, AddrSpace, |
| (GlobalValue::LinkageTypes)Linkage, Name, |
| Aliasee, /*Parent*/ nullptr)); |
| GV = GA.get(); |
| } else { |
| GI.reset(GlobalIFunc::create(Ty, AddrSpace, |
| (GlobalValue::LinkageTypes)Linkage, Name, |
| Aliasee, /*Parent*/ nullptr)); |
| GV = GI.get(); |
| } |
| GV->setThreadLocalMode(TLM); |
| GV->setVisibility((GlobalValue::VisibilityTypes)Visibility); |
| GV->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass); |
| GV->setUnnamedAddr(UnnamedAddr); |
| maybeSetDSOLocal(DSOLocal, *GV); |
| |
| // 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(); |
| GV->setPartition(Lex.getStrVal()); |
| if (parseToken(lltok::StringConstant, "expected partition string")) |
| return true; |
| } else { |
| return tokError("unknown alias or ifunc property!"); |
| } |
| } |
| |
| if (Name.empty()) |
| NumberedVals.push_back(GV); |
| |
| if (GVal) { |
| // Verify that types agree. |
| if (GVal->getType() != GV->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(GV); |
| GVal->eraseFromParent(); |
| } |
| |
| // Insert into the module, we know its name won't collide now. |
| if (IsAlias) |
| M->getAliasList().push_back(GA.release()); |
| else |
| M->getIFuncList().push_back(GI.release()); |
| assert(GV->getName() == Name && "Should not be a name conflict!"); |
| |
| 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. |
| /// |
| 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)) |
| return error(NameLoc, |
| "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) || |
| 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)) { |
| if (parseGlobalValue(Ty, Init)) |
| 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()) { |
| auto I = ForwardRefVals.find(Name); |
| if (I != ForwardRefVals.end()) { |
| GVal = I->second.first; |
| ForwardRefVals.erase(I); |
| } else if (M->getNamedValue(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 = new GlobalVariable( |
| *M, Ty, false, GlobalValue::ExternalLinkage, nullptr, Name, nullptr, |
| GlobalVariable::NotThreadLocal, AddrSpace); |
| |
| 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); |
| |
| if (GVal) { |
| if (!GVal->getType()->isOpaque() && GVal->getValueType() != Ty) |
| return error( |
| TyLoc, |
| "forward reference and definition of global have different types"); |
| |
| GVal->replaceAllUsesWith(GV); |
| GVal->eraseFromParent(); |
| } |
| |
| // parse attributes on the global. |
| 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()); |
| if (parseToken(lltok::StringConstant, "expected partition string")) |
| 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) { |
| if (parseGlobalObjectMetadataAttachment(*GV)) |
| 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; |
| if (parseFnAttributeValuePairs(Attrs, FwdRefAttrGrps, false, BuiltinLoc)) |
| return true; |
| if (Attrs.hasAttributes() || !FwdRefAttrGrps.empty()) { |
| GV->setAttributes(AttributeSet::get(Context, Attrs)); |
| ForwardRefAttrGroups[GV] = FwdRefAttrGrps; |
| } |
| |
| return false; |
| } |
| |
| /// parseUnnamedAttrGrp |
| /// ::= 'attributes' AttrGrpID '=' '{' AttrValPair+ '}' |
| bool LLParser::parseUnnamedAttrGrp() { |
| 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(); |
| |
| if (parseToken(lltok::equal, "expected '=' here") || |
| parseToken(lltok::lbrace, "expected '{' here") || |
| parseFnAttributeValuePairs(NumberedAttrBuilders[VarID], unused, true, |
| BuiltinLoc) || |
| parseToken(lltok::rbrace, "expected end of attribute group")) |
| return true; |
| |
| if (!NumberedAttrBuilders[VarID].hasAttributes()) |
| return error(AttrGrpLoc, "attribute group has no attributes"); |
| |
| return false; |
| } |
| |
| static Attribute::AttrKind tokenToAttribute(lltok::Kind Kind) { |
| switch (Kind) { |
| #define GET_ATTR_NAMES |
| #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \ |
| case lltok::kw_##DISPLAY_NAME: \ |
| return Attribute::ENUM_NAME; |
| #include "llvm/IR/Attributes.inc" |
| default: |
| return Attribute::None; |
| } |
| } |
| |
| bool LLParser::parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B, |
| bool InAttrGroup) { |
| if (Attribute::isTypeAttrKind(Attr)) |
| return parseRequiredTypeAttr(B, Lex.getKind(), Attr); |
| |
| switch (Attr) { |
| case Attribute::Alignment: { |
| MaybeAlign Alignment; |
| if (InAttrGroup) { |
| uint32_t Value = 0; |
| Lex.Lex(); |
| if (parseToken(lltok::equal, "expected '=' here") || parseUInt32(Value)) |
| return true; |
| Alignment = Align(Value); |
| } else { |
| if (parseOptionalAlignment(Alignment, true)) |
| return true; |
| } |
| B.addAlignmentAttr(Alignment); |
| return false; |
| } |
| case Attribute::StackAlignment: { |
| unsigned Alignment; |
| if (InAttrGroup) { |
| Lex.Lex(); |
| if (parseToken(lltok::equal, "expected '=' here") || |
| parseUInt32(Alignment)) |
| return true; |
| } else { |
| if (parseOptionalStackAlignment(Alignment)) |
| return true; |
| } |
| B.addStackAlignmentAttr(Alignment); |
| return false; |
| } |
| case Attribute::AllocSize: { |
| unsigned ElemSizeArg; |
| Optional<unsigned> NumElemsArg; |
| if (parseAllocSizeArguments(ElemSizeArg, NumElemsArg)) |
| return true; |
| B.addAllocSizeAttr(ElemSizeArg, NumElemsArg); |
| return false; |
| } |
| case Attribute::VScaleRange: { |
| unsigned MinValue, MaxValue; |
| if (parseVScaleRangeArguments(MinValue, MaxValue)) |
| return true; |
| B.addVScaleRangeAttr(MinValue, MaxValue); |
| return false; |
| } |
| case Attribute::Dereferenceable: { |
| uint64_t Bytes; |
| if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes)) |
| return true; |
| B.addDereferenceableAttr(Bytes); |
| return false; |
| } |
| case Attribute::DereferenceableOrNull: { |
| uint64_t Bytes; |
| if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes)) |
| return true; |
| B.addDereferenceableOrNullAttr(Bytes); |
| return false; |
| } |
| default: |
| B.addAttribute(Attr); |
| Lex.Lex(); |
| return false; |
| } |
| } |
| |
| /// parseFnAttributeValuePairs |
| /// ::= <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::rbrace) |
| return HaveError; // Finished. |
| |
| if (Token == lltok::StringConstant) { |
| if (parseStringAttribute(B)) |
| return true; |
| continue; |
| } |
| |
| if (Token == 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"); |
| } else { |
| // Save the reference to the attribute group. We'll fill it in later. |
| FwdRefAttrGrps.push_back(Lex.getUIntVal()); |
| } |
| Lex.Lex(); |
| continue; |
| } |
| |
| SMLoc Loc = Lex.getLoc(); |
| if (Token == lltok::kw_builtin) |
| BuiltinLoc = Loc; |
| |
| Attribute::AttrKind Attr = tokenToAttribute(Token); |
| if (Attr == Attribute::None) { |
| if (!InAttrGrp) |
| return HaveError; |
| return error(Lex.getLoc(), "unterminated attribute group"); |
| } |
| |
| if (parseEnumAttribute(Attr, B, InAttrGrp)) |
| return true; |
| |
| // 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. |
| if (!Attribute::canUseAsFnAttr(Attr) && Attr != Attribute::Alignment) |
| HaveError |= error(Loc, "this attribute does not apply to functions"); |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // GlobalValue Reference/Resolution Routines. |
| //===----------------------------------------------------------------------===// |
| |
| static inline GlobalValue *createGlobalFwdRef(Module *M, PointerType *PTy) { |
| // For opaque pointers, the used global type does not matter. We will later |
| // RAUW it with a global/function of the correct type. |
| if (PTy->isOpaque()) |
| return new GlobalVariable(*M, Type::getInt8Ty(M->getContext()), false, |
| GlobalValue::ExternalWeakLinkage, nullptr, "", |
| nullptr, GlobalVariable::NotThreadLocal, |
| PTy->getAddressSpace()); |
| |
| if (auto *FT = dyn_cast<FunctionType>(PTy->getPointerElementType())) |
| return Function::Create(FT, GlobalValue::ExternalWeakLinkage, |
| PTy->getAddressSpace(), "", M); |
| else |
| return new GlobalVariable(*M, PTy->getPointerElementType(), false, |
| GlobalValue::ExternalWeakLinkage, nullptr, "", |
| nullptr, GlobalVariable::NotThreadLocal, |
| PTy->getAddressSpace()); |
| } |
| |
| Value *LLParser::checkValidVariableType(LocTy Loc, const Twine &Name, Type *Ty, |
| Value *Val) { |
| Type *ValTy = Val->getType(); |
| if (ValTy == Ty) |
| return Val; |
| if (Ty->isLabelTy()) |
| error(Loc, "'" + Name + "' is not a basic block"); |
| else |
| error(Loc, "'" + Name + "' defined with type '" + |
| getTypeString(Val->getType()) + "' but expected '" + |
| getTypeString(Ty) + "'"); |
| 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. |
| GlobalValue *LLParser::getGlobalVal(const std::string &Name, Type *Ty, |
| LocTy Loc) { |
| 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)); |
| |
| // Otherwise, create a new forward reference for this value and remember it. |
| GlobalValue *FwdVal = createGlobalFwdRef(M, PTy); |
| ForwardRefVals[Name] = std::make_pair(FwdVal, Loc); |
| return FwdVal; |
| } |
| |
| GlobalValue *LLParser::getGlobalVal(unsigned ID, Type *Ty, LocTy Loc) { |
| 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)); |
| |
| // 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. |
| bool LLParser::parseToken(lltok::Kind T, const char *ErrMsg) { |
| if (Lex.getKind() != T) |
| return tokError(ErrMsg); |
| Lex.Lex(); |
| return false; |
| } |
| |
| /// parseStringConstant |
| /// ::= StringConstant |
| bool LLParser::parseStringConstant(std::string &Result) { |
| if (Lex.getKind() != lltok::StringConstant) |
| return tokError("expected string constant"); |
| Result = Lex.getStrVal(); |
| Lex.Lex(); |
| return false; |
| } |
| |
| /// parseUInt32 |
| /// ::= uint32 |
| bool LLParser::parseUInt32(uint32_t &Val) { |
| if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) |
| return tokError("expected integer"); |
| 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; |
| } |
| |
| /// parseUInt64 |
| /// ::= uint64 |
| bool LLParser::parseUInt64(uint64_t &Val) { |
| if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) |
| return tokError("expected integer"); |
| Val = Lex.getAPSIntVal().getLimitedValue(); |
| Lex.Lex(); |
| return false; |
| } |
| |
| /// parseTLSModel |
| /// := 'localdynamic' |
| /// := 'initialexec' |
| /// := 'localexec' |
| bool LLParser::parseTLSModel(GlobalVariable::ThreadLocalMode &TLM) { |
| 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; |
| } |
| |
| /// parseOptionalThreadLocal |
| /// := /*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(); |
| return parseTLSModel(TLM) || |
| parseToken(lltok::rparen, "expected ')' after thread local model"); |
| } |
| return false; |
| } |
| |
| /// parseOptionalAddrSpace |
| /// := /*empty*/ |
| /// := 'addrspace' '(' uint32 ')' |
| bool LLParser::parseOptionalAddrSpace(unsigned &AddrSpace, unsigned DefaultAS) { |
| 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 |
| bool LLParser::parseStringAttribute(AttrBuilder &B) { |
| std::string Attr = Lex.getStrVal(); |
| Lex.Lex(); |
| std::string Val; |
| if (EatIfPresent(lltok::equal) && parseStringConstant(Val)) |
| return true; |
| B.addAttribute(Attr, Val); |
| return false; |
| } |
| |
| /// Parse a potentially empty list of parameter or return attributes. |
| bool LLParser::parseOptionalParamOrReturnAttrs(AttrBuilder &B, bool IsParam) { |
| bool HaveError = false; |
| |
| B.clear(); |
| |
| while (true) { |
| lltok::Kind Token = Lex.getKind(); |
| if (Token == lltok::StringConstant) { |
| if (parseStringAttribute(B)) |
| return true; |
| continue; |
| } |
| |
| SMLoc Loc = Lex.getLoc(); |
| Attribute::AttrKind Attr = tokenToAttribute(Token); |
| if (Attr == Attribute::None) |
| return HaveError; |
| |
| if (parseEnumAttribute(Attr, B, /* InAttrGroup */ false)) |
| return true; |
| |
| if (IsParam && !Attribute::canUseAsParamAttr(Attr)) |
| HaveError |= error(Loc, "this attribute does not apply to parameters"); |
| if (!IsParam && !Attribute::canUseAsRetAttr(Attr)) |
| HaveError |= error(Loc, "this attribute does not apply to return values"); |
| } |
| } |
| |
| 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' |
| bool LLParser::parseOptionalLinkage(unsigned &Res, bool &HasLinkage, |
| unsigned &Visibility, |
| unsigned &DLLStorageClass, bool &DSOLocal) { |
| Res = parseOptionalLinkageAux(Lex.getKind(), HasLinkage); |
| if (HasLinkage) |
| Lex.Lex(); |
| parseOptionalDSOLocal(DSOLocal); |
| parseOptionalVisibility(Visibility); |
| parseOptionalDLLStorageClass(DLLStorageClass); |
| |
| if (DSOLocal && DLLStorageClass == GlobalValue::DLLImportStorageClass) { |
| return error(Lex.getLoc(), "dso_location and DLL-StorageClass mismatch"); |
| } |
| |
| 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; |
| } |
| } |
| |
| /// parseOptionalVisibility |
| /// ::= /*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(); |
| } |
| |
| /// parseOptionalDLLStorageClass |
| /// ::= /*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(); |
| } |
| |
| /// 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' |
| /// ::= 'swifttailcc' |
| /// ::= '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_swifttailcc: CC = CallingConv::SwiftTail; 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(); |
| return parseUInt32(CC); |
| } |
| } |
| |
| Lex.Lex(); |
| return false; |
| } |
| |
| /// parseMetadataAttachment |
| /// ::= !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(); |
| |
| return parseMDNode(MD); |
| } |
| |
| /// parseInstructionMetadata |
| /// ::= !dbg !42 (',' !dbg !57)* |
| bool LLParser::parseInstructionMetadata(Instruction &Inst) { |
| do { |
| if (Lex.getKind() != lltok::MetadataVar) |
| return tokError("expected metadata after comma"); |
| |
| 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; |
| } |
| |
| /// parseGlobalObjectMetadataAttachment |
| /// ::= !dbg !57 |
| bool LLParser::parseGlobalObjectMetadataAttachment(GlobalObject &GO) { |
| unsigned MDK; |
| MDNode *N; |
| if (parseMetadataAttachment(MDK, N)) |
| return true; |
| |
| GO.addMetadata(MDK, *N); |
| return false; |
| } |
| |
| /// parseOptionalFunctionMetadata |
| /// ::= (!dbg !57)* |
| bool LLParser::parseOptionalFunctionMetadata(Function &F) { |
| while (Lex.getKind() == lltok::MetadataVar) |
| if (parseGlobalObjectMetadataAttachment(F)) |
| return true; |
| return false; |
| } |
| |
| /// parseOptionalAlignment |
| /// ::= /* empty */ |
| /// ::= 'align' 4 |
| bool LLParser::parseOptionalAlignment(MaybeAlign &Alignment, bool AllowParens) { |
| Alignment = None; |
| if (!EatIfPresent(lltok::kw_align)) |
| return false; |
| LocTy AlignLoc = Lex.getLoc(); |
| uint64_t Value = 0; |
| |
| LocTy ParenLoc = Lex.getLoc(); |
| bool HaveParens = false; |
| if (AllowParens) { |
| if (EatIfPresent(lltok::lparen)) |
| HaveParens = true; |
| } |
| |
| if (parseUInt64(Value)) |
| return true; |
| |
| if (HaveParens && !EatIfPresent(lltok::rparen)) |
| return error(ParenLoc, "expected ')'"); |
| |
| if (!isPowerOf2_64(Value)) |
| return error(AlignLoc, "alignment is not a power of two"); |
| if (Value > Value::MaximumAlignment) |
| return error(AlignLoc, "huge alignments are not supported yet"); |
| Alignment = Align(Value); |
| return false; |
| } |
| |
| /// parseOptionalDerefAttrBytes |
| /// ::= /* 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)) |
| return error(ParenLoc, "expected '('"); |
| LocTy DerefLoc = Lex.getLoc(); |
| if (parseUInt64(Bytes)) |
| return true; |
| ParenLoc = Lex.getLoc(); |
| if (!EatIfPresent(lltok::rparen)) |
| return error(ParenLoc, "expected ')'"); |
| if (!Bytes) |
| return error(DerefLoc, "dereferenceable bytes must be non-zero"); |
| return false; |
| } |
| |
| /// parseOptionalCommaAlign |
| /// ::= |
| /// ::= ',' 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) |
| return error(Lex.getLoc(), "expected metadata or 'align'"); |
| |
| if (parseOptionalAlignment(Alignment)) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /// parseOptionalCommaAddrSpace |
| /// ::= |
| /// ::= ',' 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) |
| 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 error(StartParen, "expected '('"); |
| |
| if (parseUInt32(BaseSizeArg)) |
| return true; |
| |
| if (EatIfPresent(lltok::comma)) { |
| auto HowManyAt = Lex.getLoc(); |
| unsigned HowMany; |
| if (parseUInt32(HowMany)) |
| 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)) |
| return error(EndParen, "expected ')'"); |
| return false; |
| } |
| |
| bool LLParser::parseVScaleRangeArguments(unsigned &MinValue, |
| unsigned &MaxValue) { |
| Lex.Lex(); |
| |
| auto StartParen = Lex.getLoc(); |
| if (!EatIfPresent(lltok::lparen)) |
| return error(StartParen, "expected '('"); |
| |
| if (parseUInt32(MinValue)) |
| return true; |
| |
| if (EatIfPresent(lltok::comma)) { |
| if (parseUInt32(MaxValue)) |
| return true; |
| } else |
| MaxValue = MinValue; |
| |
| auto EndParen = Lex.getLoc(); |
| if (!EatIfPresent(lltok::rparen)) |
| return error(EndParen, "expected ')'"); |
| return false; |
| } |
| |
| /// parseScopeAndOrdering |
| /// if isAtomic: ::= SyncScope? AtomicOrdering |
| /// else: ::= |
| /// |
| /// This sets Scope and Ordering to the parsed values. |
| bool LLParser::parseScopeAndOrdering(bool IsAtomic, SyncScope::ID &SSID, |
| AtomicOrdering &Ordering) { |
| if (!IsAtomic) |
| return false; |
| |
| return parseScope(SSID) || parseOrdering(Ordering); |
| } |
| |
| /// parseScope |
| /// ::= 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)) |
| return error(StartParenAt, "Expected '(' in syncscope"); |
| |
| 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)) |
| return error(EndParenAt, "Expected ')' in syncscope"); |
| |
| SSID = Context.getOrInsertSyncScopeID(SSN); |
| } |
| |
| return false; |
| } |
| |
| /// parseOrdering |
| /// ::= AtomicOrdering |
| /// |
| /// This sets Ordering to the parsed value. |
| bool LLParser::parseOrdering(AtomicOrdering &Ordering) { |
| 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; |
| } |
| |
| /// parseOptionalStackAlignment |
| /// ::= /* 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)) |
| return error(ParenLoc, "expected '('"); |
| LocTy AlignLoc = Lex.getLoc(); |
| if (parseUInt32(Alignment)) |
| return true; |
| ParenLoc = Lex.getLoc(); |
| if (!EatIfPresent(lltok::rparen)) |
| return error(ParenLoc, "expected ')'"); |
| if (!isPowerOf2_32(Alignment)) |
| return error(AlignLoc, "stack alignment is not a power of two"); |
| 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. |
| /// |
| /// parseIndexList |
| /// ::= (',' uint32)+ |
| /// |
| bool LLParser::parseIndexList(SmallVectorImpl<unsigned> &Indices, |
| 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) { |
| if (Indices.empty()) |
| return tokError("expected index"); |
| AteExtraComma = true; |
| return false; |
| } |
| unsigned Idx = 0; |
| if (parseUInt32(Idx)) |
| return true; |
| 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: |
| return tokError(Msg); |
| case lltok::Type: |
| // Type ::= 'float' | 'void' (etc) |
| Result = Lex.getTyVal(); |
| Lex.Lex(); |
| |
| // Handle "ptr" opaque pointer type. |
| // |
| // Type ::= ptr ('addrspace' '(' uint32 ')')? |
| if (Result->isOpaquePointerTy()) { |
| unsigned AddrSpace; |
| if (parseOptionalAddrSpace(AddrSpace)) |
| return true; |
| Result = PointerType::get(getContext(), AddrSpace); |
| |
| // Give a nice error for 'ptr*'. |
| if (Lex.getKind() == lltok::star) |
| return tokError("ptr* is invalid - use ptr instead"); |
| |
| // Fall through to parsing the type suffixes only if this 'ptr' is a |
| // function return. Otherwise, return success, implicitly rejecting other |
| // suffixes. |
| if (Lex.getKind() != lltok::lparen) |
| return false; |
| } |
| break; |
| case lltok::lbrace: |
| // Type ::= StructType |
| if (parseAnonStructType(Result, false)) |
| 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) { |
| if (parseAnonStructType(Result, true) || |
| parseToken(lltok::greater, "expected '>' at end of packed struct")) |
| 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; |
| } |
| } |
| |
| // parse the type suffixes. |
| 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 tokError("basic block pointers are invalid"); |
| if (Result->isVoidTy()) |
| return tokError("pointers to void are invalid - use i8* instead"); |
| 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()) |
| return tokError("basic block pointers are invalid"); |
| if (Result->isVoidTy()) |
| return tokError("pointers to void are invalid; use i8* instead"); |
| if (!PointerType::isValidElementType(Result)) |
| return tokError("pointer to this type is invalid"); |
| 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: |
| if (parseFunctionType(Result)) |
| return true; |
| break; |
| } |
| } |
| } |
| |
| /// parseParameterList |
| /// ::= '(' ')' |
| /// ::= '(' Arg (',' Arg)* ')' |
| /// Arg |
| /// ::= Type OptionalAttributes Value OptionalAttributes |
| bool LLParser::parseParameterList(SmallVectorImpl<ParamInfo> &ArgList, |
| 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() && |
| parseToken(lltok::comma, "expected ',' in argument list")) |
| 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) |
| return tokError(Twine(Msg) + "non-musttail call"); |
| if (!InVarArgsFunc) |
| return tokError(Twine(Msg) + "musttail call in non-varargs function"); |
| 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; |
| if (parseType(ArgTy, ArgLoc)) |
| return true; |
| |
| if (ArgTy->isMetadataTy()) { |
| if (parseMetadataAsValue(V, PFS)) |
| 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 tokError("expected '...' at end of argument list for musttail call " |
| "in varargs function"); |
| |
| Lex.Lex(); // Lex the ')'. |
| return false; |
| } |
| |
| /// parseRequiredTypeAttr |
| /// ::= attrname(<ty>) |
| bool LLParser::parseRequiredTypeAttr(AttrBuilder &B, lltok::Kind AttrToken, |
| Attribute::AttrKind AttrKind) { |
| Type *Ty = nullptr; |
| if (!EatIfPresent(AttrToken)) |
| return true; |
| if (!EatIfPresent(lltok::lparen)) |
| return error(Lex.getLoc(), "expected '('"); |
| if (parseType(Ty)) |
| return true; |
| if (!EatIfPresent(lltok::rparen)) |
| return error(Lex.getLoc(), "expected ')'"); |
| |
| B.addTypeAttr(AttrKind, Ty); |
| return false; |
| } |
| |
| /// parseOptionalOperandBundles |
| /// ::= /*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() && |
| parseToken(lltok::comma, "expected ',' in input list")) |
| return true; |
| |
| std::string Tag; |
| if (parseStringConstant(Tag)) |
| 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() && |
| parseToken(lltok::comma, "expected ',' in input list")) |
| 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 error(BeginLoc, "operand bundle set must not be empty"); |
| |
| Lex.Lex(); // Lex the ']'. |
| return false; |
| } |
| |
| /// parseArgumentList - parse the argument list for a function type or function |
| /// prototype. |
| /// ::= '(' ArgTypeListI ')' |
| /// ArgTypeListI |
| /// ::= /*empty*/ |
| /// ::= '...' |
| /// ::= ArgTypeList ',' '...' |
| /// ::= ArgType (',' ArgType)* |
| /// |
| bool LLParser::parseArgumentList(SmallVectorImpl<ArgInfo> &ArgList, |
| bool &IsVarArg) { |
| 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) { |
| IsVarArg = true; |
| 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()) |
| 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) |
| return error(TypeLoc, "argument expected to be numbered '%" + |
| 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)) { |
| IsVarArg = true; |
| break; |
| } |
| |
| // Otherwise must be an argument type. |
| TypeLoc = Lex.getLoc(); |
| if (parseType(ArgTy) || parseOptionalParamAttrs(Attrs)) |
| return true; |
| |
| 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) |
| return error(TypeLoc, "argument expected to be numbered '%" + |
| 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)); |
| } |
| } |
| |
| return parseToken(lltok::rparen, "expected ')' at end of argument list"); |
| } |
| |
| /// parseFunctionType |
| /// ::= Type ArgumentList OptionalAttrs |
| bool LLParser::parseFunctionType(Type *&Result) { |
| assert(Lex.getKind() == lltok::lparen); |
| |
| if (!FunctionType::isValidReturnType(Result)) |
| return tokError("invalid function return type"); |
| |
| 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 error(ArgList[i].Loc, "argument name invalid in function type"); |
| 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); |
| |
| Result = FunctionType::get(Result, ArgListTy, IsVarArg); |
| return false; |
| } |
| |
| /// parseAnonStructType - parse an anonymous struct type, which is inlined into |
| /// other structs. |
| bool LLParser::parseAnonStructType(Type *&Result, bool Packed) { |
| SmallVector<Type*, 8> Elts; |
| if (parseStructBody(Elts)) |
| return true; |
| |
| 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()) |
| 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) |
| return error(TypeLoc, "forward references to non-struct type"); |
| |
| 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; |
| if (parseStructBody(Body) || |
| (isPacked && parseToken(lltok::greater, "expected '>' in packed struct"))) |
| return true; |
| |
| STy->setBody(Body, isPacked); |
| ResultTy = STy; |
| return false; |
| } |
| |
| /// parseStructType: Handles packed and unpacked types. </> parsed elsewhere. |
| /// 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; |
| if (parseType(Ty)) |
| return true; |
| Body.push_back(Ty); |
| |
| if (!StructType::isValidElementType(Ty)) |
| return error(EltTyLoc, "invalid element type for struct"); |
| |
| while (EatIfPresent(lltok::comma)) { |
| EltTyLoc = Lex.getLoc(); |
| if (parseType(Ty)) |
| return true; |
| |
| if (!StructType::isValidElementType(Ty)) |
| return error(EltTyLoc, "invalid element type for struct"); |
| |
| 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 '>' |
| bool LLParser::parseArrayVectorType(Type *&Result, bool IsVector) { |
| bool Scalable = false; |
| |
| if (IsVector && Lex.getKind() == lltok::kw_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 tokError("expected number in address space"); |
| |
| 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; |
| if (parseType(EltTy)) |
| return true; |
| |
| if (parseToken(IsVector ? lltok::greater : lltok::rsquare, |
| "expected end of sequential type")) |
| return true; |
| |
| if (IsVector) { |
| if (Size == 0) |
| return error(SizeLoc, "zero element vector is illegal"); |
| if ((unsigned)Size != Size) |
| return error(SizeLoc, "size too large for vector"); |
| if (!VectorType::isValidElementType(EltTy)) |
| return error(TypeLoc, "invalid vector element type"); |
| 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(); |
| } |
| } |
| |
| bool LLParser::PerFunctionState::finishFunction() { |
| if (!ForwardRefVals.empty()) |
| return P.error(ForwardRefVals.begin()->second.second, |
| "use of undefined value '%" + ForwardRefVals.begin()->first + |
| "'"); |
| if (!ForwardRefValIDs.empty()) |
| return P.error(ForwardRefValIDs.begin()->second.second, |
| "use of undefined value '%" + |
| Twine(ForwardRefValIDs.begin()->first) + "'"); |
| 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. |
| Value *LLParser::PerFunctionState::getVal(const std::string &Name, Type *Ty, |
| LocTy Loc) { |
| // 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); |
|