diff options
Diffstat (limited to 'llvm/lib/AsmParser')
| -rw-r--r-- | llvm/lib/AsmParser/LLLexer.cpp | 26 | ||||
| -rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 822 | ||||
| -rw-r--r-- | llvm/lib/AsmParser/Parser.cpp | 15 |
3 files changed, 695 insertions, 168 deletions
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index c9a982693fa7..a9cac4de0c2f 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -597,6 +597,8 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(arm_aapcs_vfpcc); KEYWORD(aarch64_vector_pcs); KEYWORD(aarch64_sve_vector_pcs); + KEYWORD(aarch64_sme_preservemost_from_x0); + KEYWORD(aarch64_sme_preservemost_from_x2); KEYWORD(msp430_intrcc); KEYWORD(avr_intrcc); KEYWORD(avr_signalcc); @@ -642,6 +644,15 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(DISPLAY_NAME); #include "llvm/IR/Attributes.inc" + KEYWORD(read); + KEYWORD(write); + KEYWORD(readwrite); + KEYWORD(argmem); + KEYWORD(inaccessiblemem); + KEYWORD(argmemonly); + KEYWORD(inaccessiblememonly); + KEYWORD(inaccessiblemem_or_argmemonly); + KEYWORD(type); KEYWORD(opaque); @@ -661,6 +672,8 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(xchg); KEYWORD(nand); KEYWORD(max); KEYWORD(min); KEYWORD(umax); KEYWORD(umin); KEYWORD(fmax); KEYWORD(fmin); + KEYWORD(uinc_wrap); + KEYWORD(udec_wrap); KEYWORD(vscale); KEYWORD(x); @@ -761,6 +774,14 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(byte); KEYWORD(bit); KEYWORD(varFlags); + KEYWORD(callsites); + KEYWORD(clones); + KEYWORD(stackIds); + KEYWORD(allocs); + KEYWORD(versions); + KEYWORD(memProf); + KEYWORD(notcold); + KEYWORD(notcoldandcold); #undef KEYWORD @@ -788,10 +809,7 @@ lltok::Kind LLLexer::LexIdentifier() { TYPEKEYWORD("token", Type::getTokenTy(Context)); if (Keyword == "ptr") { - // setOpaquePointers() must be called before creating any pointer types. - if (!Context.hasSetOpaquePointersValue()) { - Context.setOpaquePointers(true); - } else if (Context.supportsTypedPointers()) { + if (Context.supportsTypedPointers()) { Warning("ptr type is only supported in -opaque-pointers mode"); return lltok::Error; } diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index fd502eded0a0..7f451620a08e 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -13,7 +13,7 @@ #include "llvm/AsmParser/LLParser.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/None.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/AsmParser/LLToken.h" @@ -43,11 +43,13 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/ModRef.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> #include <cstring> +#include <optional> #include <vector> using namespace llvm; @@ -59,31 +61,9 @@ static std::string getTypeString(Type *T) { return Tmp.str(); } -static void setContextOpaquePointers(LLLexer &L, LLVMContext &C) { - while (true) { - lltok::Kind K = L.Lex(); - // LLLexer will set the opaque pointers option in LLVMContext if it sees an - // explicit "ptr". - if (K == lltok::star || K == lltok::Error || K == lltok::Eof || - isa_and_nonnull<PointerType>(L.getTyVal())) { - if (K == lltok::star) - C.setOpaquePointers(false); - return; - } - } -} - /// Run: module ::= toplevelentity* bool LLParser::Run(bool UpgradeDebugInfo, DataLayoutCallbackTy DataLayoutCallback) { - // If we haven't decided on whether or not we're using opaque pointers, do a - // quick lex over the tokens to see if we explicitly construct any typed or - // opaque pointer types. - // Don't bail out on an error so we do the same work in the parsing below - // regardless of if --opaque-pointers is set. - if (!Context.hasSetOpaquePointersValue()) - setContextOpaquePointers(OPLex, Context); - // Prime the lexer. Lex.Lex(); @@ -93,11 +73,8 @@ bool LLParser::Run(bool UpgradeDebugInfo, "Can't read textual IR with a Context that discards named Values"); if (M) { - if (parseTargetDefinitions()) + if (parseTargetDefinitions(DataLayoutCallback)) return true; - - if (auto LayoutOverride = DataLayoutCallback(M->getTargetTriple())) - M->setDataLayout(*LayoutOverride); } return parseTopLevelEntities() || validateEndOfModule(UpgradeDebugInfo) || @@ -172,8 +149,8 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) { // If the alignment was parsed as an attribute, move to the alignment // field. - if (FnAttrs.hasAlignmentAttr()) { - Fn->setAlignment(FnAttrs.getAlignment()); + if (MaybeAlign A = FnAttrs.getAlignment()) { + Fn->setAlignment(A); FnAttrs.removeAttribute(Attribute::Alignment); } @@ -215,6 +192,44 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) { return error(ForwardRefBlockAddresses.begin()->first.Loc, "expected function name in blockaddress"); + auto ResolveForwardRefDSOLocalEquivalents = [&](const ValID &GVRef, + GlobalValue *FwdRef) { + GlobalValue *GV = nullptr; + if (GVRef.Kind == ValID::t_GlobalName) { + GV = M->getNamedValue(GVRef.StrVal); + } else if (GVRef.UIntVal < NumberedVals.size()) { + GV = dyn_cast<GlobalValue>(NumberedVals[GVRef.UIntVal]); + } + + if (!GV) + return error(GVRef.Loc, "unknown function '" + GVRef.StrVal + + "' referenced by dso_local_equivalent"); + + if (!GV->getValueType()->isFunctionTy()) + return error(GVRef.Loc, + "expected a function, alias to function, or ifunc " + "in dso_local_equivalent"); + + auto *Equiv = DSOLocalEquivalent::get(GV); + FwdRef->replaceAllUsesWith(Equiv); + FwdRef->eraseFromParent(); + return false; + }; + + // If there are entries in ForwardRefDSOLocalEquivalentIDs/Names at this + // point, they are references after the function was defined. Resolve those + // now. + for (auto &Iter : ForwardRefDSOLocalEquivalentIDs) { + if (ResolveForwardRefDSOLocalEquivalents(Iter.first, Iter.second)) + return true; + } + for (auto &Iter : ForwardRefDSOLocalEquivalentNames) { + if (ResolveForwardRefDSOLocalEquivalents(Iter.first, Iter.second)) + return true; + } + ForwardRefDSOLocalEquivalentIDs.clear(); + ForwardRefDSOLocalEquivalentNames.clear(); + for (const auto &NT : NumberedTypes) if (NT.second.second.isValid()) return error(NT.second.second, @@ -265,16 +280,6 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) { 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); - F.eraseFromParent(); - } - } - if (UpgradeDebugInfo) llvm::UpgradeDebugInfo(*M); @@ -323,11 +328,19 @@ bool LLParser::validateEndOfIndex() { // Top-Level Entities //===----------------------------------------------------------------------===// -bool LLParser::parseTargetDefinitions() { - while (true) { +bool LLParser::parseTargetDefinitions(DataLayoutCallbackTy DataLayoutCallback) { + // Delay parsing of the data layout string until the target triple is known. + // Then, pass both the the target triple and the tentative data layout string + // to DataLayoutCallback, allowing to override the DL string. + // This enables importing modules with invalid DL strings. + std::string TentativeDLStr = M->getDataLayoutStr(); + LocTy DLStrLoc; + + bool Done = false; + while (!Done) { switch (Lex.getKind()) { case lltok::kw_target: - if (parseTargetDefinition()) + if (parseTargetDefinition(TentativeDLStr, DLStrLoc)) return true; break; case lltok::kw_source_filename: @@ -335,9 +348,21 @@ bool LLParser::parseTargetDefinitions() { return true; break; default: - return false; + Done = true; } } + // Run the override callback to potentially change the data layout string, and + // parse the data layout string. + if (auto LayoutOverride = + DataLayoutCallback(M->getTargetTriple(), TentativeDLStr)) { + TentativeDLStr = *LayoutOverride; + DLStrLoc = {}; + } + Expected<DataLayout> MaybeDL = DataLayout::parse(TentativeDLStr); + if (!MaybeDL) + return error(DLStrLoc, toString(MaybeDL.takeError())); + M->setDataLayout(MaybeDL.get()); + return false; } bool LLParser::parseTopLevelEntities() { @@ -441,7 +466,8 @@ bool LLParser::parseModuleAsm() { /// toplevelentity /// ::= 'target' 'triple' '=' STRINGCONSTANT /// ::= 'target' 'datalayout' '=' STRINGCONSTANT -bool LLParser::parseTargetDefinition() { +bool LLParser::parseTargetDefinition(std::string &TentativeDLStr, + LocTy &DLStrLoc) { assert(Lex.getKind() == lltok::kw_target); std::string Str; switch (Lex.Lex()) { @@ -458,13 +484,9 @@ bool LLParser::parseTargetDefinition() { Lex.Lex(); if (parseToken(lltok::equal, "expected '=' after target datalayout")) return true; - LocTy Loc = Lex.getLoc(); - if (parseStringConstant(Str)) + DLStrLoc = Lex.getLoc(); + if (parseStringConstant(TentativeDLStr)) return true; - Expected<DataLayout> MaybeDL = DataLayout::parse(Str); - if (!MaybeDL) - return error(Loc, toString(MaybeDL.takeError())); - M->setDataLayout(MaybeDL.get()); return false; } } @@ -752,7 +774,7 @@ bool LLParser::parseMDNodeID(MDNode *&Result) { // Otherwise, create MDNode forward reference. auto &FwdRef = ForwardRefMDNodes[MID]; - FwdRef = std::make_pair(MDTuple::getTemporary(Context, None), IDLoc); + FwdRef = std::make_pair(MDTuple::getTemporary(Context, std::nullopt), IDLoc); Result = FwdRef.first.get(); NumberedMetadata[MID].reset(Result); @@ -823,7 +845,18 @@ bool LLParser::parseStandaloneMetadata() { // See if this was forward referenced, if so, handle it. auto FI = ForwardRefMDNodes.find(MetadataID); if (FI != ForwardRefMDNodes.end()) { - FI->second.first->replaceAllUsesWith(Init); + auto *ToReplace = FI->second.first.get(); + // DIAssignID has its own special forward-reference "replacement" for + // attachments (the temporary attachments are never actually attached). + if (isa<DIAssignID>(Init)) { + for (auto *Inst : TempDIAssignIDAttachments[ToReplace]) { + assert(!Inst->getMetadata(LLVMContext::MD_DIAssignID) && + "Inst unexpectedly already has DIAssignID attachment"); + Inst->setMetadata(LLVMContext::MD_DIAssignID, Init); + } + } + + ToReplace->replaceAllUsesWith(Init); ForwardRefMDNodes.erase(FI); assert(NumberedMetadata[MetadataID] == Init && "Tracking VH didn't work"); @@ -929,6 +962,10 @@ static bool isValidVisibilityForLinkage(unsigned V, unsigned L) { return !GlobalValue::isLocalLinkage((GlobalValue::LinkageTypes)L) || (GlobalValue::VisibilityTypes)V == GlobalValue::DefaultVisibility; } +static bool isValidDLLStorageClassForLinkage(unsigned S, unsigned L) { + return !GlobalValue::isLocalLinkage((GlobalValue::LinkageTypes)L) || + (GlobalValue::DLLStorageClassTypes)S == GlobalValue::DefaultStorageClass; +} // If there was an explicit dso_local, update GV. In the absence of an explicit // dso_local we keep the default value. @@ -982,6 +1019,10 @@ bool LLParser::parseAliasOrIFunc(const std::string &Name, LocTy NameLoc, return error(NameLoc, "symbol with local linkage must have default visibility"); + if (!isValidDLLStorageClassForLinkage(DLLStorageClass, L)) + return error(NameLoc, + "symbol with local linkage cannot have a DLL storage class"); + Type *Ty; LocTy ExplicitTypeLoc = Lex.getLoc(); if (parseType(Ty) || @@ -1169,6 +1210,10 @@ bool LLParser::parseGlobal(const std::string &Name, LocTy NameLoc, return error(NameLoc, "symbol with local linkage must have default visibility"); + if (!isValidDLLStorageClassForLinkage(DLLStorageClass, Linkage)) + return error(NameLoc, + "symbol with local linkage cannot have a DLL storage class"); + unsigned AddrSpace; bool IsConstant, IsExternallyInitialized; LocTy IsExternallyInitializedLoc; @@ -1374,7 +1419,7 @@ bool LLParser::parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B, } case Attribute::AllocSize: { unsigned ElemSizeArg; - Optional<unsigned> NumElemsArg; + std::optional<unsigned> NumElemsArg; if (parseAllocSizeArguments(ElemSizeArg, NumElemsArg)) return true; B.addAllocSizeAttr(ElemSizeArg, NumElemsArg); @@ -1385,7 +1430,7 @@ bool LLParser::parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B, if (parseVScaleRangeArguments(MinValue, MaxValue)) return true; B.addVScaleRangeAttr(MinValue, - MaxValue > 0 ? MaxValue : Optional<unsigned>()); + MaxValue > 0 ? MaxValue : std::optional<unsigned>()); return false; } case Attribute::Dereferenceable: { @@ -1416,6 +1461,13 @@ bool LLParser::parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B, B.addAllocKindAttr(Kind); return false; } + case Attribute::Memory: { + std::optional<MemoryEffects> ME = parseMemoryAttr(); + if (!ME) + return true; + B.addMemoryAttr(*ME); + return false; + } default: B.addAttribute(Attr); Lex.Lex(); @@ -1423,6 +1475,31 @@ bool LLParser::parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B, } } +static bool upgradeMemoryAttr(MemoryEffects &ME, lltok::Kind Kind) { + switch (Kind) { + case lltok::kw_readnone: + ME &= MemoryEffects::none(); + return true; + case lltok::kw_readonly: + ME &= MemoryEffects::readOnly(); + return true; + case lltok::kw_writeonly: + ME &= MemoryEffects::writeOnly(); + return true; + case lltok::kw_argmemonly: + ME &= MemoryEffects::argMemOnly(); + return true; + case lltok::kw_inaccessiblememonly: + ME &= MemoryEffects::inaccessibleMemOnly(); + return true; + case lltok::kw_inaccessiblemem_or_argmemonly: + ME &= MemoryEffects::inaccessibleOrArgMemOnly(); + return true; + default: + return false; + } +} + /// parseFnAttributeValuePairs /// ::= <attr> | <attr> '=' <value> bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B, @@ -1432,10 +1509,11 @@ bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B, B.clear(); + MemoryEffects ME = MemoryEffects::unknown(); while (true) { lltok::Kind Token = Lex.getKind(); if (Token == lltok::rbrace) - return HaveError; // Finished. + break; // Finished. if (Token == lltok::StringConstant) { if (parseStringAttribute(B)) @@ -1463,10 +1541,15 @@ bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B, if (Token == lltok::kw_builtin) BuiltinLoc = Loc; + if (upgradeMemoryAttr(ME, Token)) { + Lex.Lex(); + continue; + } + Attribute::AttrKind Attr = tokenToAttribute(Token); if (Attr == Attribute::None) { if (!InAttrGrp) - return HaveError; + break; return error(Lex.getLoc(), "unterminated attribute group"); } @@ -1479,6 +1562,10 @@ bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B, if (!Attribute::canUseAsFnAttr(Attr) && Attr != Attribute::Alignment) HaveError |= error(Loc, "this attribute does not apply to functions"); } + + if (ME != MemoryEffects::unknown()) + B.addMemoryAttr(ME); + return HaveError; } //===----------------------------------------------------------------------===// @@ -1691,8 +1778,34 @@ bool LLParser::parseOptionalAddrSpace(unsigned &AddrSpace, unsigned DefaultAS) { AddrSpace = DefaultAS; if (!EatIfPresent(lltok::kw_addrspace)) return false; + + auto ParseAddrspaceValue = [&](unsigned &AddrSpace) -> bool { + if (Lex.getKind() == lltok::StringConstant) { + auto AddrSpaceStr = Lex.getStrVal(); + if (AddrSpaceStr == "A") { + AddrSpace = M->getDataLayout().getAllocaAddrSpace(); + } else if (AddrSpaceStr == "G") { + AddrSpace = M->getDataLayout().getDefaultGlobalsAddressSpace(); + } else if (AddrSpaceStr == "P") { + AddrSpace = M->getDataLayout().getProgramAddressSpace(); + } else { + return tokError("invalid symbolic addrspace '" + AddrSpaceStr + "'"); + } + Lex.Lex(); + return false; + } + if (Lex.getKind() != lltok::APSInt) + return tokError("expected integer or string constant"); + SMLoc Loc = Lex.getLoc(); + if (parseUInt32(AddrSpace)) + return true; + if (!isUInt<24>(AddrSpace)) + return error(Loc, "invalid address space, must be a 24-bit integer"); + return false; + }; + return parseToken(lltok::lparen, "expected '(' in address space") || - parseUInt32(AddrSpace) || + ParseAddrspaceValue(AddrSpace) || parseToken(lltok::rparen, "expected ')' in address space"); } @@ -1875,6 +1988,8 @@ void LLParser::parseOptionalDLLStorageClass(unsigned &Res) { /// ::= 'arm_aapcs_vfpcc' /// ::= 'aarch64_vector_pcs' /// ::= 'aarch64_sve_vector_pcs' +/// ::= 'aarch64_sme_preservemost_from_x0' +/// ::= 'aarch64_sme_preservemost_from_x2' /// ::= 'msp430_intrcc' /// ::= 'avr_intrcc' /// ::= 'avr_signalcc' @@ -1925,6 +2040,12 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) { case lltok::kw_aarch64_sve_vector_pcs: CC = CallingConv::AArch64_SVE_VectorCall; break; + case lltok::kw_aarch64_sme_preservemost_from_x0: + CC = CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X0; + break; + case lltok::kw_aarch64_sme_preservemost_from_x2: + CC = CallingConv::AArch64_SME_ABI_Support_Routines_PreserveMost_From_X2; + 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; @@ -1990,7 +2111,11 @@ bool LLParser::parseInstructionMetadata(Instruction &Inst) { if (parseMetadataAttachment(MDK, N)) return true; - Inst.setMetadata(MDK, N); + if (MDK == LLVMContext::MD_DIAssignID) + TempDIAssignIDAttachments[N].push_back(&Inst); + else + Inst.setMetadata(MDK, N); + if (MDK == LLVMContext::MD_tbaa) InstsWithTBAATag.push_back(&Inst); @@ -2024,7 +2149,7 @@ bool LLParser::parseOptionalFunctionMetadata(Function &F) { /// ::= /* empty */ /// ::= 'align' 4 bool LLParser::parseOptionalAlignment(MaybeAlign &Alignment, bool AllowParens) { - Alignment = None; + Alignment = std::nullopt; if (!EatIfPresent(lltok::kw_align)) return false; LocTy AlignLoc = Lex.getLoc(); @@ -2129,6 +2254,87 @@ bool LLParser::parseAllocKind(AllocFnKind &Kind) { return false; } +static std::optional<MemoryEffects::Location> keywordToLoc(lltok::Kind Tok) { + switch (Tok) { + case lltok::kw_argmem: + return MemoryEffects::ArgMem; + case lltok::kw_inaccessiblemem: + return MemoryEffects::InaccessibleMem; + default: + return std::nullopt; + } +} + +static std::optional<ModRefInfo> keywordToModRef(lltok::Kind Tok) { + switch (Tok) { + case lltok::kw_none: + return ModRefInfo::NoModRef; + case lltok::kw_read: + return ModRefInfo::Ref; + case lltok::kw_write: + return ModRefInfo::Mod; + case lltok::kw_readwrite: + return ModRefInfo::ModRef; + default: + return std::nullopt; + } +} + +std::optional<MemoryEffects> LLParser::parseMemoryAttr() { + MemoryEffects ME = MemoryEffects::none(); + + // We use syntax like memory(argmem: read), so the colon should not be + // interpreted as a label terminator. + Lex.setIgnoreColonInIdentifiers(true); + auto _ = make_scope_exit([&] { Lex.setIgnoreColonInIdentifiers(false); }); + + Lex.Lex(); + if (!EatIfPresent(lltok::lparen)) { + tokError("expected '('"); + return std::nullopt; + } + + bool SeenLoc = false; + do { + std::optional<MemoryEffects::Location> Loc = keywordToLoc(Lex.getKind()); + if (Loc) { + Lex.Lex(); + if (!EatIfPresent(lltok::colon)) { + tokError("expected ':' after location"); + return std::nullopt; + } + } + + std::optional<ModRefInfo> MR = keywordToModRef(Lex.getKind()); + if (!MR) { + if (!Loc) + tokError("expected memory location (argmem, inaccessiblemem) " + "or access kind (none, read, write, readwrite)"); + else + tokError("expected access kind (none, read, write, readwrite)"); + return std::nullopt; + } + + Lex.Lex(); + if (Loc) { + SeenLoc = true; + ME = ME.getWithModRef(*Loc, *MR); + } else { + if (SeenLoc) { + tokError("default access kind must be specified first"); + return std::nullopt; + } + ME = MemoryEffects(*MR); + } + + if (EatIfPresent(lltok::rparen)) + return ME; + } while (EatIfPresent(lltok::comma)); + + tokError("unterminated memory attribute"); + return std::nullopt; +} + /// parseOptionalCommaAlign /// ::= /// ::= ',' align 4 @@ -2183,7 +2389,7 @@ bool LLParser::parseOptionalCommaAddrSpace(unsigned &AddrSpace, LocTy &Loc, } bool LLParser::parseAllocSizeArguments(unsigned &BaseSizeArg, - Optional<unsigned> &HowManyArg) { + std::optional<unsigned> &HowManyArg) { Lex.Lex(); auto StartParen = Lex.getLoc(); @@ -2203,7 +2409,7 @@ bool LLParser::parseAllocSizeArguments(unsigned &BaseSizeArg, "'allocsize' indices can't refer to the same parameter"); HowManyArg = HowMany; } else - HowManyArg = None; + HowManyArg = std::nullopt; auto EndParen = Lex.getLoc(); if (!EatIfPresent(lltok::rparen)) @@ -2384,6 +2590,12 @@ bool LLParser::parseType(Type *&Result, const Twine &Msg, bool AllowVoid) { return false; } break; + case lltok::kw_target: { + // Type ::= TargetExtType + if (parseTargetExtType(Result)) + return true; + break; + } case lltok::lbrace: // Type ::= StructType if (parseAnonStructType(Result, false)) @@ -2891,6 +3103,60 @@ bool LLParser::parseArrayVectorType(Type *&Result, bool IsVector) { return false; } +/// parseTargetExtType - handle target extension type syntax +/// TargetExtType +/// ::= 'target' '(' STRINGCONSTANT TargetExtTypeParams TargetExtIntParams ')' +/// +/// TargetExtTypeParams +/// ::= /*empty*/ +/// ::= ',' Type TargetExtTypeParams +/// +/// TargetExtIntParams +/// ::= /*empty*/ +/// ::= ',' uint32 TargetExtIntParams +bool LLParser::parseTargetExtType(Type *&Result) { + Lex.Lex(); // Eat the 'target' keyword. + + // Get the mandatory type name. + std::string TypeName; + if (parseToken(lltok::lparen, "expected '(' in target extension type") || + parseStringConstant(TypeName)) + return true; + + // Parse all of the integer and type parameters at the same time; the use of + // SeenInt will allow us to catch cases where type parameters follow integer + // parameters. + SmallVector<Type *> TypeParams; + SmallVector<unsigned> IntParams; + bool SeenInt = false; + while (Lex.getKind() == lltok::comma) { + Lex.Lex(); // Eat the comma. + + if (Lex.getKind() == lltok::APSInt) { + SeenInt = true; + unsigned IntVal; + if (parseUInt32(IntVal)) + return true; + IntParams.push_back(IntVal); + } else if (SeenInt) { + // The only other kind of parameter we support is type parameters, which + // must precede the integer parameters. This is therefore an error. + return tokError("expected uint32 param"); + } else { + Type *TypeParam; + if (parseType(TypeParam, /*AllowVoid=*/true)) + return true; + TypeParams.push_back(TypeParam); + } + } + + if (parseToken(lltok::rparen, "expected ')' in target extension type")) + return true; + + Result = TargetExtType::get(Context, TypeName, TypeParams, IntParams); + return false; +} + //===----------------------------------------------------------------------===// // Function Semantic Analysis. //===----------------------------------------------------------------------===// @@ -3112,7 +3378,7 @@ BasicBlock *LLParser::PerFunctionState::defineBB(const std::string &Name, // Move the block to the end of the function. Forward ref'd blocks are // inserted wherever they happen to be referenced. - F.getBasicBlockList().splice(F.end(), F.getBasicBlockList(), BB); + F.splice(F.end(), &F, BB->getIterator()); // Remove the block from forward ref sets. if (Name.empty()) { @@ -3420,7 +3686,22 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) { GV = M->getNamedValue(Fn.StrVal); } - assert(GV && "Could not find a corresponding global variable"); + if (!GV) { + // Make a placeholder global variable as a placeholder for this reference. + auto &FwdRefMap = (Fn.Kind == ValID::t_GlobalID) + ? ForwardRefDSOLocalEquivalentIDs + : ForwardRefDSOLocalEquivalentNames; + GlobalValue *&FwdRef = FwdRefMap.try_emplace(Fn, nullptr).first->second; + if (!FwdRef) { + FwdRef = new GlobalVariable(*M, Type::getInt8Ty(Context), false, + GlobalValue::InternalLinkage, nullptr, "", + nullptr, GlobalValue::NotThreadLocal); + } + + ID.ConstantVal = FwdRef; + ID.Kind = ValID::t_Constant; + return false; + } if (!GV->getValueType()->isFunctionTy()) return error(Fn.Loc, "expected a function, alias to function, or ifunc " @@ -3499,6 +3780,8 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) { return error(ID.Loc, "fdiv constexprs are no longer supported"); case lltok::kw_frem: return error(ID.Loc, "frem constexprs are no longer supported"); + case lltok::kw_fneg: + return error(ID.Loc, "fneg constexprs are no longer supported"); case lltok::kw_icmp: case lltok::kw_fcmp: { unsigned PredVal, Opc = Lex.getUIntVal(); @@ -3532,30 +3815,6 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) { return false; } - // Unary Operators. - case lltok::kw_fneg: { - unsigned Opc = Lex.getUIntVal(); - Constant *Val; - Lex.Lex(); - if (parseToken(lltok::lparen, "expected '(' in unary constantexpr") || - parseGlobalTypeAndValue(Val) || - parseToken(lltok::rparen, "expected ')' in unary constantexpr")) - return true; - - // Check that the type is valid for the operator. - switch (Opc) { - case Instruction::FNeg: - if (!Val->getType()->isFPOrFPVectorTy()) - return error(ID.Loc, "constexpr requires fp operands"); - break; - default: llvm_unreachable("Unknown unary operator!"); - } - unsigned Flags = 0; - Constant *C = ConstantExpr::get(Opc, Val, Flags); - ID.ConstantVal = C; - ID.Kind = ValID::t_Constant; - return false; - } // Binary Operators. case lltok::kw_add: case lltok::kw_sub: @@ -3673,7 +3932,7 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) { return true; } - Optional<unsigned> InRangeOp; + std::optional<unsigned> InRangeOp; if (parseGlobalValueVector( Elts, Opc == Instruction::GetElementPtr ? &InRangeOp : nullptr) || parseToken(lltok::rparen, "expected ')' in constantexpr")) @@ -3816,7 +4075,7 @@ bool LLParser::parseOptionalComdat(StringRef GlobalName, Comdat *&C) { /// ::= /*empty*/ /// ::= [inrange] TypeAndValue (',' [inrange] TypeAndValue)* bool LLParser::parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts, - Optional<unsigned> *InRangeOp) { + std::optional<unsigned> *InRangeOp) { // Empty list. if (Lex.getKind() == lltok::rbrace || Lex.getKind() == lltok::rsquare || @@ -4408,7 +4667,7 @@ bool LLParser::parseMDField(LocTy Loc, StringRef Name, MDFieldList &Result) { template <> bool LLParser::parseMDField(LocTy Loc, StringRef Name, ChecksumKindField &Result) { - Optional<DIFile::ChecksumKind> CSKind = + std::optional<DIFile::ChecksumKind> CSKind = DIFile::getChecksumKind(Lex.getStrVal()); if (Lex.getKind() != lltok::ChecksumKind || !CSKind) @@ -4515,6 +4774,24 @@ bool LLParser::parseDILocation(MDNode *&Result, bool IsDistinct) { return false; } +/// parseDIAssignID: +/// ::= distinct !DIAssignID() +bool LLParser::parseDIAssignID(MDNode *&Result, bool IsDistinct) { + if (!IsDistinct) + return Lex.Error("missing 'distinct', required for !DIAssignID()"); + + Lex.Lex(); + + // Now eat the parens. + if (parseToken(lltok::lparen, "expected '(' here")) + return true; + if (parseToken(lltok::rparen, "expected ')' here")) + return true; + + Result = DIAssignID::getDistinct(Context); + return false; +} + /// parseGenericDINode: /// ::= !GenericDINode(tag: 15, header: "...", operands: {...}) bool LLParser::parseGenericDINode(MDNode *&Result, bool IsDistinct) { @@ -4690,7 +4967,7 @@ bool LLParser::parseDIDerivedType(MDNode *&Result, bool IsDistinct) { PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS - Optional<unsigned> DWARFAddressSpace; + std::optional<unsigned> DWARFAddressSpace; if (dwarfAddressSpace.Val != UINT32_MAX) DWARFAddressSpace = dwarfAddressSpace.Val; @@ -4790,17 +5067,17 @@ bool LLParser::parseDIFile(MDNode *&Result, bool IsDistinct) { PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS - Optional<DIFile::ChecksumInfo<MDString *>> OptChecksum; + std::optional<DIFile::ChecksumInfo<MDString *>> OptChecksum; if (checksumkind.Seen && checksum.Seen) OptChecksum.emplace(checksumkind.Val, checksum.Val); else if (checksumkind.Seen || checksum.Seen) return Lex.Error("'checksumkind' and 'checksum' must be provided together"); - Optional<MDString *> OptSource; + MDString *Source = nullptr; if (source.Seen) - OptSource = source.Val; - Result = GET_OR_DISTINCT(DIFile, (Context, filename.Val, directory.Val, - OptChecksum, OptSource)); + Source = source.Val; + Result = GET_OR_DISTINCT( + DIFile, (Context, filename.Val, directory.Val, OptChecksum, Source)); return false; } @@ -5469,6 +5746,9 @@ bool LLParser::convertValIDToValue(Type *Ty, ValID &ID, Value *&V, // FIXME: LabelTy should not be a first-class type. if (!Ty->isFirstClassType() || Ty->isLabelTy()) return error(ID.Loc, "invalid type for null constant"); + if (auto *TETy = dyn_cast<TargetExtType>(Ty)) + if (!TETy->hasProperty(TargetExtType::HasZeroInit)) + return error(ID.Loc, "invalid type for null constant"); V = Constant::getNullValue(Ty); return false; case ValID::t_None: @@ -5507,7 +5787,7 @@ bool LLParser::convertValIDToValue(Type *Ty, ValID &ID, Value *&V, " of struct initializer doesn't match struct element type"); V = ConstantStruct::get( - ST, makeArrayRef(ID.ConstantStructElts.get(), ID.UIntVal)); + ST, ArrayRef(ID.ConstantStructElts.get(), ID.UIntVal)); } else return error(ID.Loc, "constant expression type mismatch"); return false; @@ -5617,6 +5897,10 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine) { return error(LinkageLoc, "symbol with local linkage must have default visibility"); + if (!isValidDLLStorageClassForLinkage(DLLStorageClass, Linkage)) + return error(LinkageLoc, + "symbol with local linkage cannot have a DLL storage class"); + if (!FunctionType::isValidReturnType(RetType)) return error(RetTypeLoc, "invalid function return type"); @@ -5676,8 +5960,8 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine) { return error(BuiltinLoc, "'builtin' attribute not valid on function"); // If the alignment was parsed as an attribute, move to the alignment field. - if (FuncAttrs.hasAlignmentAttr()) { - Alignment = FuncAttrs.getAlignment(); + if (MaybeAlign A = FuncAttrs.getAlignment()) { + Alignment = A; FuncAttrs.removeAttribute(Attribute::Alignment); } @@ -5868,7 +6152,7 @@ bool LLParser::parseFunctionBody(Function &Fn) { // within this function. if (PFS.resolveForwardRefBlockAddresses()) return true; - SaveAndRestore<PerFunctionState *> ScopeExit(BlockAddressPFS, &PFS); + SaveAndRestore ScopeExit(BlockAddressPFS, &PFS); // We need at least one basic block. if (Lex.getKind() == lltok::rbrace || Lex.getKind() == lltok::kw_uselistorder) @@ -5937,7 +6221,7 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { llvm_unreachable("Unknown parseInstruction result!"); case InstError: return true; case InstNormal: - BB->getInstList().push_back(Inst); + Inst->insertInto(BB, BB->end()); // With a normal result, we check to see if the instruction is followed by // a comma and metadata. @@ -5946,7 +6230,7 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { return true; break; case InstExtraComma: - BB->getInstList().push_back(Inst); + Inst->insertInto(BB, BB->end()); // If the instruction parser ate an extra comma at the end of it, it // *must* be followed by metadata. @@ -6359,6 +6643,27 @@ bool LLParser::parseIndirectBr(Instruction *&Inst, PerFunctionState &PFS) { return false; } +// If RetType is a non-function pointer type, then this is the short syntax +// for the call, which means that RetType is just the return type. Infer the +// rest of the function argument types from the arguments that are present. +bool LLParser::resolveFunctionType(Type *RetType, + const SmallVector<ParamInfo, 16> &ArgList, + FunctionType *&FuncTy) { + FuncTy = dyn_cast<FunctionType>(RetType); + if (!FuncTy) { + // Pull out the types of all of the arguments... + std::vector<Type*> ParamTypes; + for (unsigned i = 0, e = ArgList.size(); i != e; ++i) + ParamTypes.push_back(ArgList[i].V->getType()); + + if (!FunctionType::isValidReturnType(RetType)) + return true; + + FuncTy = FunctionType::get(RetType, ParamTypes, false); + } + return false; +} + /// parseInvoke /// ::= 'invoke' OptionalCallingConv OptionalAttrs Type Value ParamList /// OptionalAttrs 'to' TypeAndValue 'unwind' TypeAndValue @@ -6392,18 +6697,9 @@ bool LLParser::parseInvoke(Instruction *&Inst, PerFunctionState &PFS) { // If RetType is a non-function pointer type, then this is the short syntax // for the call, which means that RetType is just the return type. Infer the // rest of the function argument types from the arguments that are present. - FunctionType *Ty = dyn_cast<FunctionType>(RetType); - if (!Ty) { - // Pull out the types of all of the arguments... - std::vector<Type*> ParamTypes; - for (unsigned i = 0, e = ArgList.size(); i != e; ++i) - ParamTypes.push_back(ArgList[i].V->getType()); - - if (!FunctionType::isValidReturnType(RetType)) - return error(RetTypeLoc, "Invalid result type for LLVM function"); - - Ty = FunctionType::get(RetType, ParamTypes, false); - } + FunctionType *Ty; + if (resolveFunctionType(RetType, ArgList, Ty)) + return error(RetTypeLoc, "Invalid result type for LLVM function"); CalleeID.FTy = Ty; @@ -6439,9 +6735,6 @@ bool LLParser::parseInvoke(Instruction *&Inst, PerFunctionState &PFS) { if (I != E) return error(CallLoc, "not enough parameters specified for call"); - if (FnAttrs.hasAlignmentAttr()) - return error(CallLoc, "invoke instructions may not have an alignment"); - // Finish off the Attribute and check them AttributeList PAL = AttributeList::get(Context, AttributeSet::get(Context, FnAttrs), @@ -6718,18 +7011,9 @@ bool LLParser::parseCallBr(Instruction *&Inst, PerFunctionState &PFS) { // If RetType is a non-function pointer type, then this is the short syntax // for the call, which means that RetType is just the return type. Infer the // rest of the function argument types from the arguments that are present. - FunctionType *Ty = dyn_cast<FunctionType>(RetType); - if (!Ty) { - // Pull out the types of all of the arguments... - std::vector<Type *> ParamTypes; - for (unsigned i = 0, e = ArgList.size(); i != e; ++i) - ParamTypes.push_back(ArgList[i].V->getType()); - - if (!FunctionType::isValidReturnType(RetType)) - return error(RetTypeLoc, "Invalid result type for LLVM function"); - - Ty = FunctionType::get(RetType, ParamTypes, false); - } + FunctionType *Ty; + if (resolveFunctionType(RetType, ArgList, Ty)) + return error(RetTypeLoc, "Invalid result type for LLVM function"); CalleeID.FTy = Ty; @@ -6764,9 +7048,6 @@ bool LLParser::parseCallBr(Instruction *&Inst, PerFunctionState &PFS) { if (I != E) return error(CallLoc, "not enough parameters specified for call"); - if (FnAttrs.hasAlignmentAttr()) - return error(CallLoc, "callbr instructions may not have an alignment"); - // Finish off the Attribute and check them AttributeList PAL = AttributeList::get(Context, AttributeSet::get(Context, FnAttrs), @@ -6979,21 +7260,22 @@ int LLParser::parsePHI(Instruction *&Inst, PerFunctionState &PFS) { Type *Ty = nullptr; LocTy TypeLoc; Value *Op0, *Op1; - if (parseType(Ty, TypeLoc) || - parseToken(lltok::lsquare, "expected '[' in phi value list") || - parseValue(Ty, Op0, PFS) || - parseToken(lltok::comma, "expected ',' after insertelement value") || - parseValue(Type::getLabelTy(Context), Op1, PFS) || - parseToken(lltok::rsquare, "expected ']' in phi value list")) + if (parseType(Ty, TypeLoc)) return true; + if (!Ty->isFirstClassType()) + return error(TypeLoc, "phi node must have first class type"); + + bool First = true; bool AteExtraComma = false; SmallVector<std::pair<Value*, BasicBlock*>, 16> PHIVals; while (true) { - PHIVals.push_back(std::make_pair(Op0, cast<BasicBlock>(Op1))); - - if (!EatIfPresent(lltok::comma)) + if (First) { + if (Lex.getKind() != lltok::lsquare) + break; + First = false; + } else if (!EatIfPresent(lltok::comma)) break; if (Lex.getKind() == lltok::MetadataVar) { @@ -7007,10 +7289,9 @@ int LLParser::parsePHI(Instruction *&Inst, PerFunctionState &PFS) { parseValue(Type::getLabelTy(Context), Op1, PFS) || parseToken(lltok::rsquare, "expected ']' in phi value list")) return true; - } - if (!Ty->isFirstClassType()) - return error(TypeLoc, "phi node must have first class type"); + PHIVals.push_back(std::make_pair(Op0, cast<BasicBlock>(Op1))); + } PHINode *PN = PHINode::Create(Ty, PHIVals.size()); for (unsigned i = 0, e = PHIVals.size(); i != e; ++i) @@ -7123,18 +7404,9 @@ bool LLParser::parseCall(Instruction *&Inst, PerFunctionState &PFS, // If RetType is a non-function pointer type, then this is the short syntax // for the call, which means that RetType is just the return type. Infer the // rest of the function argument types from the arguments that are present. - FunctionType *Ty = dyn_cast<FunctionType>(RetType); - if (!Ty) { - // Pull out the types of all of the arguments... - std::vector<Type*> ParamTypes; - for (unsigned i = 0, e = ArgList.size(); i != e; ++i) - ParamTypes.push_back(ArgList[i].V->getType()); - - if (!FunctionType::isValidReturnType(RetType)) - return error(RetTypeLoc, "Invalid result type for LLVM function"); - - Ty = FunctionType::get(RetType, ParamTypes, false); - } + FunctionType *Ty; + if (resolveFunctionType(RetType, ArgList, Ty)) + return error(RetTypeLoc, "Invalid result type for LLVM function"); CalleeID.FTy = Ty; @@ -7171,9 +7443,6 @@ bool LLParser::parseCall(Instruction *&Inst, PerFunctionState &PFS, if (I != E) return error(CallLoc, "not enough parameters specified for call"); - if (FnAttrs.hasAlignmentAttr()) - return error(CallLoc, "call instructions may not have an alignment"); - // Finish off the Attribute and check them AttributeList PAL = AttributeList::get(Context, AttributeSet::get(Context, FnAttrs), @@ -7467,6 +7736,12 @@ int LLParser::parseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS) { case lltok::kw_min: Operation = AtomicRMWInst::Min; break; case lltok::kw_umax: Operation = AtomicRMWInst::UMax; break; case lltok::kw_umin: Operation = AtomicRMWInst::UMin; break; + case lltok::kw_uinc_wrap: + Operation = AtomicRMWInst::UIncWrap; + break; + case lltok::kw_udec_wrap: + Operation = AtomicRMWInst::UDecWrap; + break; case lltok::kw_fadd: Operation = AtomicRMWInst::FAdd; IsFP = true; @@ -8494,6 +8769,8 @@ bool LLParser::parseFunctionSummary(std::string Name, GlobalValue::GUID GUID, FunctionSummary::TypeIdInfo TypeIdInfo; std::vector<FunctionSummary::ParamAccess> ParamAccesses; std::vector<ValueInfo> Refs; + std::vector<CallsiteInfo> Callsites; + std::vector<AllocInfo> Allocs; // Default is all-zeros (conservative values). FunctionSummary::FFlags FFlags = {}; if (parseToken(lltok::colon, "expected ':' here") || @@ -8528,6 +8805,14 @@ bool LLParser::parseFunctionSummary(std::string Name, GlobalValue::GUID GUID, if (parseOptionalParamAccesses(ParamAccesses)) return true; break; + case lltok::kw_allocs: + if (parseOptionalAllocs(Allocs)) + return true; + break; + case lltok::kw_callsites: + if (parseOptionalCallsites(Callsites)) + return true; + break; default: return error(Lex.getLoc(), "expected optional function summary field"); } @@ -8543,7 +8828,7 @@ bool LLParser::parseFunctionSummary(std::string Name, GlobalValue::GUID GUID, std::move(TypeIdInfo.TypeCheckedLoadVCalls), std::move(TypeIdInfo.TypeTestAssumeConstVCalls), std::move(TypeIdInfo.TypeCheckedLoadConstVCalls), - std::move(ParamAccesses)); + std::move(ParamAccesses), std::move(Callsites), std::move(Allocs)); FS->setModulePath(ModulePath); @@ -9495,3 +9780,220 @@ bool LLParser::parseGVReference(ValueInfo &VI, unsigned &GVId) { VI.setWriteOnly(); return false; } + +/// OptionalAllocs +/// := 'allocs' ':' '(' Alloc [',' Alloc]* ')' +/// Alloc ::= '(' 'versions' ':' '(' Version [',' Version]* ')' +/// ',' MemProfs ')' +/// Version ::= UInt32 +bool LLParser::parseOptionalAllocs(std::vector<AllocInfo> &Allocs) { + assert(Lex.getKind() == lltok::kw_allocs); + Lex.Lex(); + + if (parseToken(lltok::colon, "expected ':' in allocs") || + parseToken(lltok::lparen, "expected '(' in allocs")) + return true; + + // parse each alloc + do { + if (parseToken(lltok::lparen, "expected '(' in alloc") || + parseToken(lltok::kw_versions, "expected 'versions' in alloc") || + parseToken(lltok::colon, "expected ':'") || + parseToken(lltok::lparen, "expected '(' in versions")) + return true; + + SmallVector<uint8_t> Versions; + do { + uint8_t V = 0; + if (parseAllocType(V)) + return true; + Versions.push_back(V); + } while (EatIfPresent(lltok::comma)); + + if (parseToken(lltok::rparen, "expected ')' in versions") || + parseToken(lltok::comma, "expected ',' in alloc")) + return true; + + std::vector<MIBInfo> MIBs; + if (parseMemProfs(MIBs)) + return true; + + Allocs.push_back({Versions, MIBs}); + + if (parseToken(lltok::rparen, "expected ')' in alloc")) + return true; + } while (EatIfPresent(lltok::comma)); + + if (parseToken(lltok::rparen, "expected ')' in allocs")) + return true; + + return false; +} + +/// MemProfs +/// := 'memProf' ':' '(' MemProf [',' MemProf]* ')' +/// MemProf ::= '(' 'type' ':' AllocType +/// ',' 'stackIds' ':' '(' StackId [',' StackId]* ')' ')' +/// StackId ::= UInt64 +bool LLParser::parseMemProfs(std::vector<MIBInfo> &MIBs) { + assert(Lex.getKind() == lltok::kw_memProf); + Lex.Lex(); + + if (parseToken(lltok::colon, "expected ':' in memprof") || + parseToken(lltok::lparen, "expected '(' in memprof")) + return true; + + // parse each MIB + do { + if (parseToken(lltok::lparen, "expected '(' in memprof") || + parseToken(lltok::kw_type, "expected 'type' in memprof") || + parseToken(lltok::colon, "expected ':'")) + return true; + + uint8_t AllocType; + if (parseAllocType(AllocType)) + return true; + + if (parseToken(lltok::comma, "expected ',' in memprof") || + parseToken(lltok::kw_stackIds, "expected 'stackIds' in memprof") || + parseToken(lltok::colon, "expected ':'") || + parseToken(lltok::lparen, "expected '(' in stackIds")) + return true; + + SmallVector<unsigned> StackIdIndices; + do { + uint64_t StackId = 0; + if (parseUInt64(StackId)) + return true; + StackIdIndices.push_back(Index->addOrGetStackIdIndex(StackId)); + } while (EatIfPresent(lltok::comma)); + + if (parseToken(lltok::rparen, "expected ')' in stackIds")) + return true; + + MIBs.push_back({(AllocationType)AllocType, StackIdIndices}); + + if (parseToken(lltok::rparen, "expected ')' in memprof")) + return true; + } while (EatIfPresent(lltok::comma)); + + if (parseToken(lltok::rparen, "expected ')' in memprof")) + return true; + + return false; +} + +/// AllocType +/// := ('none'|'notcold'|'cold'|'notcoldandcold') +bool LLParser::parseAllocType(uint8_t &AllocType) { + switch (Lex.getKind()) { + case lltok::kw_none: + AllocType = (uint8_t)AllocationType::None; + break; + case lltok::kw_notcold: + AllocType = (uint8_t)AllocationType::NotCold; + break; + case lltok::kw_cold: + AllocType = (uint8_t)AllocationType::Cold; + break; + case lltok::kw_notcoldandcold: + AllocType = + (uint8_t)AllocationType::NotCold | (uint8_t)AllocationType::Cold; + break; + default: + return error(Lex.getLoc(), "invalid alloc type"); + } + Lex.Lex(); + return false; +} + +/// OptionalCallsites +/// := 'callsites' ':' '(' Callsite [',' Callsite]* ')' +/// Callsite ::= '(' 'callee' ':' GVReference +/// ',' 'clones' ':' '(' Version [',' Version]* ')' +/// ',' 'stackIds' ':' '(' StackId [',' StackId]* ')' ')' +/// Version ::= UInt32 +/// StackId ::= UInt64 +bool LLParser::parseOptionalCallsites(std::vector<CallsiteInfo> &Callsites) { + assert(Lex.getKind() == lltok::kw_callsites); + Lex.Lex(); + + if (parseToken(lltok::colon, "expected ':' in callsites") || + parseToken(lltok::lparen, "expected '(' in callsites")) + return true; + + IdToIndexMapType IdToIndexMap; + // parse each callsite + do { + if (parseToken(lltok::lparen, "expected '(' in callsite") || + parseToken(lltok::kw_callee, "expected 'callee' in callsite") || + parseToken(lltok::colon, "expected ':'")) + return true; + + ValueInfo VI; + unsigned GVId = 0; + LocTy Loc = Lex.getLoc(); + if (!EatIfPresent(lltok::kw_null)) { + if (parseGVReference(VI, GVId)) + return true; + } + + if (parseToken(lltok::comma, "expected ',' in callsite") || + parseToken(lltok::kw_clones, "expected 'clones' in callsite") || + parseToken(lltok::colon, "expected ':'") || + parseToken(lltok::lparen, "expected '(' in clones")) + return true; + + SmallVector<unsigned> Clones; + do { + unsigned V = 0; + if (parseUInt32(V)) + return true; + Clones.push_back(V); + } while (EatIfPresent(lltok::comma)); + + if (parseToken(lltok::rparen, "expected ')' in clones") || + parseToken(lltok::comma, "expected ',' in callsite") || + parseToken(lltok::kw_stackIds, "expected 'stackIds' in callsite") || + parseToken(lltok::colon, "expected ':'") || + parseToken(lltok::lparen, "expected '(' in stackIds")) + return true; + + SmallVector<unsigned> StackIdIndices; + do { + uint64_t StackId = 0; + if (parseUInt64(StackId)) + return true; + StackIdIndices.push_back(Index->addOrGetStackIdIndex(StackId)); + } while (EatIfPresent(lltok::comma)); + + if (parseToken(lltok::rparen, "expected ')' in stackIds")) + return true; + + // Keep track of the Callsites array index needing a forward reference. + // We will save the location of the ValueInfo needing an update, but + // can only do so once the SmallVector is finalized. + if (VI.getRef() == FwdVIRef) + IdToIndexMap[GVId].push_back(std::make_pair(Callsites.size(), Loc)); + Callsites.push_back({VI, Clones, StackIdIndices}); + + if (parseToken(lltok::rparen, "expected ')' in callsite")) + return true; + } while (EatIfPresent(lltok::comma)); + + // Now that the Callsites vector is finalized, it is safe to save the + // locations of any forward GV references that need updating later. + for (auto I : IdToIndexMap) { + auto &Infos = ForwardRefValueInfos[I.first]; + for (auto P : I.second) { + assert(Callsites[P.first].Callee.getRef() == FwdVIRef && + "Forward referenced ValueInfo expected to be empty"); + Infos.emplace_back(&Callsites[P.first].Callee, P.second); + } + } + + if (parseToken(lltok::rparen, "expected ')' in callsites")) + return true; + + return false; +} diff --git a/llvm/lib/AsmParser/Parser.cpp b/llvm/lib/AsmParser/Parser.cpp index 95b9079f0f9c..035eea81378e 100644 --- a/llvm/lib/AsmParser/Parser.cpp +++ b/llvm/lib/AsmParser/Parser.cpp @@ -91,9 +91,10 @@ ParsedModuleAndIndex llvm::parseAssemblyWithIndex(MemoryBufferRef F, SMDiagnostic &Err, LLVMContext &Context, SlotMapping *Slots) { - return ::parseAssemblyWithIndex(F, Err, Context, Slots, - /*UpgradeDebugInfo*/ true, - [](StringRef) { return None; }); + return ::parseAssemblyWithIndex( + F, Err, Context, Slots, + /*UpgradeDebugInfo*/ true, + [](StringRef, StringRef) { return std::nullopt; }); } static ParsedModuleAndIndex @@ -150,7 +151,7 @@ static bool parseSummaryIndexAssemblyInto(MemoryBufferRef F, // index, but we need to initialize it. LLVMContext unusedContext; return LLParser(F.getBuffer(), SM, Err, nullptr, &Index, unusedContext) - .Run(true, [](StringRef) { return None; }); + .Run(true, [](StringRef, StringRef) { return std::nullopt; }); } std::unique_ptr<ModuleSummaryIndex> @@ -177,6 +178,12 @@ llvm::parseSummaryIndexAssemblyFile(StringRef Filename, SMDiagnostic &Err) { return parseSummaryIndexAssembly(FileOrErr.get()->getMemBufferRef(), Err); } +std::unique_ptr<ModuleSummaryIndex> +llvm::parseSummaryIndexAssemblyString(StringRef AsmString, SMDiagnostic &Err) { + MemoryBufferRef F(AsmString, "<string>"); + return parseSummaryIndexAssembly(F, Err); +} + Constant *llvm::parseConstantValue(StringRef Asm, SMDiagnostic &Err, const Module &M, const SlotMapping *Slots) { SourceMgr SM; |
