| //===-- 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 "llvm/ADT/DenseMap.h" |
| #include "llvm/ADT/None.h" |
| #include "llvm/ADT/Optional.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/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/Instruction.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/Operator.h" |
| #include "llvm/IR/Type.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() { |
| // Prime the lexer. |
| Lex.Lex(); |
| |
| if (Context.shouldDiscardValueNames()) |
| return Error( |
| Lex.getLoc(), |
| "Can't read textual IR with a Context that discards named Values"); |
| |
| return ParseTopLevelEntities() || ValidateEndOfModule() || |
| 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 sanity checks at the end of the |
| /// module. |
| bool LLParser::ValidateEndOfModule() { |
| 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()) |
| 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 |
| 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()) |
| 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::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::kw_target: if (ParseTargetDefinition()) return true; break; |
| case lltok::kw_source_filename: |
| if (ParseSourceFileName()) |
| return true; |
| break; |
| case lltok::kw_deplibs: if (ParseDepLibs()) 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; |
| if (DataLayoutStr.empty()) |
| 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; |
| } |
| |
| /// 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(); |
| 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; |
| if (ParseStringConstant(Str)) return true; |
| } while (EatIfPresent(lltok::comma)); |
| |
| return ParseToken(lltok::rsquare, "expected ']' at end of list"); |
| } |
| |
| /// 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; |
| |
| 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); |
| } |
| |
| /// 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; |
| |
| 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(); |
| |
| 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_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 |
| 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; |
| } 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 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) |
| return TokError( |
| "Expected 'gv', 'module', or 'typeid' at the start of summary entry"); |
| 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(); |
| |
| switch (Lex.getKind()) { |
| case lltok::kw_gv: |
| return ParseGVEntry(SummaryID); |
| case lltok::kw_module: |
| return ParseModuleEntry(SummaryID); |
| case lltok::kw_typeid: |
| return ParseTypeIdEntry(SummaryID); |
| break; |
| default: |
| return Error(Lex.getLoc(), "unexpected summary kind"); |
| } |
| Lex.setIgnoreColonInIdentifiers(false); |
| return false; |
| } |
| |
| 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 |
| /// |
| /// IndirectSymbol |
| /// ::= TypeAndValue |
| /// |
| /// 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)) |
| 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)) |
| 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 && Ty != PTy->getElementType()) |
| return Error( |
| ExplicitTypeLoc, |
| "explicit pointee type doesn't match operand's pointee type"); |
| |
| 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)) |
| 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); |
| |
| 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; |
| } |
| |
| /// 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()) { |
| 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) |
| 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); |
| |
| // 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_align) { |
| unsigned 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; |
| } |
| |
| /// 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::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) |
| 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: { |
| 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. |
| unsigned Alignment; |
| if (inAttrGrp) { |
| Lex.Lex(); |
| if (ParseToken(lltok::equal, "expected '=' here") || |
| ParseUInt32(Alignment)) |
| return true; |
| } else { |
| if (ParseOptionalAlignment(Alignment)) |
| 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 { |
| 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; |
| 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_naked: B.addAttribute(Attribute::Naked); break; |
| case lltok::kw_nobuiltin: B.addAttribute(Attribute::NoBuiltin); break; |
| case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); 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_noredzone: B.addAttribute(Attribute::NoRedZone); break; |
| case lltok::kw_noreturn: B.addAttribute(Attribute::NoReturn); break; |
| case lltok::kw_nocf_check: B.addAttribute(Attribute::NoCfCheck); break; |
| case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break; |
| case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); 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_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_writeonly: B.addAttribute(Attribute::WriteOnly); break; |
| |
| // Error handling. |
| 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_nocapture: |
| case lltok::kw_nonnull: |
| case lltok::kw_returned: |
| case lltok::kw_sret: |
| case lltok::kw_swifterror: |
| case lltok::kw_swiftself: |
| HaveError |= |
| Error(Lex.getLoc(), |
| "invalid use of parameter-only attribute on a function"); |
| break; |
| } |
| |
| 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 |
| Error(Loc, "'" + Name + "' defined with type '" + |
| 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. |
| GlobalValue *LLParser::GetGlobalVal(const std::string &Name, Type *Ty, |
| 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; |
| } |
| |
| GlobalValue *LLParser::GetGlobalVal(unsigned ID, Type *Ty, LocTy Loc, |
| 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. |
| //===----------------------------------------------------------------------===// |
| |
| /// 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; |
| } |
| |
| /// 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: { |
| if (ParseStringAttribute(B)) |
| return true; |
| continue; |
| } |
| case lltok::kw_align: { |
| unsigned Alignment; |
| if (ParseOptionalAlignment(Alignment)) |
| return true; |
| B.addAlignmentAttr(Alignment); |
| continue; |
| } |
| case lltok::kw_byval: B.addAttribute(Attribute::ByVal); break; |
| 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; |
| if (ParseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes)) |
| return true; |
| B.addDereferenceableOrNullAttr(Bytes); |
| 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_noalias: B.addAttribute(Attribute::NoAlias); break; |
| case lltok::kw_nocapture: B.addAttribute(Attribute::NoCapture); 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_sret: B.addAttribute(Attribute::StructRet); 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_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_naked: |
| case lltok::kw_nobuiltin: |
| case lltok::kw_noduplicate: |
| case lltok::kw_noimplicitfloat: |
| case lltok::kw_noinline: |
| case lltok::kw_nonlazybind: |
| 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_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(); |
| } |
| } |
| |
| /// 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: { |
| if (ParseStringAttribute(B)) |
| 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; |
| if (ParseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes)) |
| return true; |
| B.addDereferenceableOrNullAttr(Bytes); |
| continue; |
| } |
| case lltok::kw_align: { |
| unsigned 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_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: |
| 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: |
| 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_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_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: |
| HaveError |= Error(Lex.getLoc(), "invalid use of attribute on return type"); |
| } |
| |
| 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' |
| 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' |
| /// ::= 'x86_stdcallcc' |
| /// ::= 'x86_fastcallcc' |
| /// ::= 'x86_thiscallcc' |
| /// ::= 'x86_vectorcallcc' |
| /// ::= 'arm_apcscc' |
| /// ::= 'arm_aapcscc' |
| /// ::= 'arm_aapcs_vfpcc' |
| /// ::= 'aarch64_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' |
| /// ::= '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_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_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_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_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(unsigned &Alignment) { |
| Alignment = 0; |
| if (!EatIfPresent(lltok::kw_align)) |
| return false; |
| LocTy AlignLoc = Lex.getLoc(); |
| if (ParseUInt32(Alignment)) return true; |
| if (!isPowerOf2_32(Alignment)) |
| return Error(AlignLoc, "alignment is not a power of two"); |
| if (Alignment > Value::MaximumAlignment) |
| return Error(AlignLoc, "huge alignments are not supported yet"); |
| 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(unsigned &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; |
| } |
| |
| /// 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(); |
| 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; |
| } |
| |
| /// 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){ |
| 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(); |
| } |
| |
| 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 { |
| 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 '>' |
| bool LLParser::ParseArrayVectorType(Type *&Result, bool isVector) { |
| 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)); |
| } 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. |
| |
| |