llir / llvm

Library for interacting with LLVM IR in pure Go.
https://llir.github.io/document/
BSD Zero Clause License
1.18k stars 78 forks source link

update llir/llvm to support 13.0 #205

Closed dannypsnl closed 2 years ago

dannypsnl commented 3 years ago

LLVM 13.0 was released today: https://github.com/llvm/llvm-project/releases/tag/llvmorg-13.0.0

$ wget https://github.com/llvm/llvm-project/archive/llvmorg-12.0.1.tar.gz
$ wget https://github.com/llvm/llvm-project/archive/llvmorg-13.0.0.tar.gz
$ tar zxf llvmorg-12.0.1.tar.gz
$ tar zxf llvmorg-13.0.0.tar.gz
$ git diff llvm-project-llvmorg-12.0.1/llvm/lib/AsmParser llvm-project-llvmorg-13.0.0/llvm/lib/AsmParser
dannypsnl commented 2 years ago

Diff

```diff diff --git a/llvm-project-llvmorg-12.0.1/llvm/lib/AsmParser/LLLexer.cpp b/llvm-project-llvmorg-13.0.0/llvm/lib/AsmParser/LLLexer.cpp index 427de74..4f72c6f 100644 --- a/llvm-project-llvmorg-12.0.1/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm-project-llvmorg-13.0.0/llvm/lib/AsmParser/LLLexer.cpp @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -#include "LLLexer.h" +#include "llvm/AsmParser/LLLexer.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" @@ -543,7 +543,6 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(triple); KEYWORD(source_filename); KEYWORD(unwind); - KEYWORD(deplibs); // FIXME: Remove in 4.0. KEYWORD(datalayout); KEYWORD(volatile); KEYWORD(atomic); @@ -609,6 +608,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(x86_regcallcc); KEYWORD(webkit_jscc); KEYWORD(swiftcc); + KEYWORD(swifttailcc); KEYWORD(anyregcc); KEYWORD(preserve_mostcc); KEYWORD(preserve_allcc); @@ -643,6 +643,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(convergent); KEYWORD(dereferenceable); KEYWORD(dereferenceable_or_null); + KEYWORD(elementtype); KEYWORD(inaccessiblememonly); KEYWORD(inaccessiblemem_or_argmemonly); KEYWORD(inlinehint); @@ -670,6 +671,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(nocf_check); KEYWORD(noundef); KEYWORD(nounwind); + KEYWORD(nosanitize_coverage); KEYWORD(null_pointer_is_valid); KEYWORD(optforfuzzing); KEYWORD(optnone); @@ -696,7 +698,9 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(speculative_load_hardening); KEYWORD(swifterror); KEYWORD(swiftself); + KEYWORD(swiftasync); KEYWORD(uwtable); + KEYWORD(vscale_range); KEYWORD(willreturn); KEYWORD(writeonly); KEYWORD(zeroext); @@ -713,7 +717,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(any); KEYWORD(exactmatch); KEYWORD(largest); - KEYWORD(noduplicates); + KEYWORD(nodeduplicate); KEYWORD(samesize); KEYWORD(eq); KEYWORD(ne); KEYWORD(slt); KEYWORD(sgt); KEYWORD(sle); @@ -751,6 +755,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(flags); KEYWORD(blockcount); KEYWORD(linkage); + KEYWORD(visibility); KEYWORD(notEligibleToImport); KEYWORD(live); KEYWORD(dsoLocal); @@ -843,6 +848,7 @@ lltok::Kind LLLexer::LexIdentifier() { TYPEKEYWORD("x86_mmx", Type::getX86_MMXTy(Context)); TYPEKEYWORD("x86_amx", Type::getX86_AMXTy(Context)); TYPEKEYWORD("token", Type::getTokenTy(Context)); + TYPEKEYWORD("ptr", PointerType::getUnqual(Context)); #undef TYPEKEYWORD diff --git a/llvm-project-llvmorg-12.0.1/llvm/lib/AsmParser/LLLexer.h b/llvm-project-llvmorg-12.0.1/llvm/lib/AsmParser/LLLexer.h deleted file mode 100644 index c97d978..0000000 --- a/llvm-project-llvmorg-12.0.1/llvm/lib/AsmParser/LLLexer.h +++ /dev/null @@ -1,104 +0,0 @@ -//===- LLLexer.h - Lexer for LLVM Assembly Files ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This class represents the Lexer for .ll files. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_ASMPARSER_LLLEXER_H -#define LLVM_LIB_ASMPARSER_LLLEXER_H - -#include "LLToken.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/ADT/APSInt.h" -#include "llvm/Support/SMLoc.h" -#include - -namespace llvm { - class Type; - class SMDiagnostic; - class SourceMgr; - class LLVMContext; - - class LLLexer { - const char *CurPtr; - StringRef CurBuf; - SMDiagnostic &ErrorInfo; - SourceMgr &SM; - LLVMContext &Context; - - // Information about the current token. - const char *TokStart; - lltok::Kind CurKind; - std::string StrVal; - unsigned UIntVal; - Type *TyVal; - APFloat APFloatVal; - APSInt APSIntVal; - - // When false (default), an identifier ending in ':' is a label token. - // When true, the ':' is treated as a separate token. - bool IgnoreColonInIdentifiers; - - public: - explicit LLLexer(StringRef StartBuf, SourceMgr &SM, SMDiagnostic &, - LLVMContext &C); - - lltok::Kind Lex() { - return CurKind = LexToken(); - } - - typedef SMLoc LocTy; - LocTy getLoc() const { return SMLoc::getFromPointer(TokStart); } - lltok::Kind getKind() const { return CurKind; } - const std::string &getStrVal() const { return StrVal; } - Type *getTyVal() const { return TyVal; } - unsigned getUIntVal() const { return UIntVal; } - const APSInt &getAPSIntVal() const { return APSIntVal; } - const APFloat &getAPFloatVal() const { return APFloatVal; } - - void setIgnoreColonInIdentifiers(bool val) { - IgnoreColonInIdentifiers = val; - } - - bool Error(LocTy ErrorLoc, const Twine &Msg) const; - bool Error(const Twine &Msg) const { return Error(getLoc(), Msg); } - - void Warning(LocTy WarningLoc, const Twine &Msg) const; - void Warning(const Twine &Msg) const { return Warning(getLoc(), Msg); } - - private: - lltok::Kind LexToken(); - - int getNextChar(); - void SkipLineComment(); - lltok::Kind ReadString(lltok::Kind kind); - bool ReadVarName(); - - lltok::Kind LexIdentifier(); - lltok::Kind LexDigitOrNegative(); - lltok::Kind LexPositive(); - lltok::Kind LexAt(); - lltok::Kind LexDollar(); - lltok::Kind LexExclaim(); - lltok::Kind LexPercent(); - lltok::Kind LexUIntID(lltok::Kind Token); - lltok::Kind LexVar(lltok::Kind Var, lltok::Kind VarID); - lltok::Kind LexQuote(); - lltok::Kind Lex0x(); - lltok::Kind LexHash(); - lltok::Kind LexCaret(); - - uint64_t atoull(const char *Buffer, const char *End); - uint64_t HexIntToVal(const char *Buffer, const char *End); - void HexToIntPair(const char *Buffer, const char *End, uint64_t Pair[2]); - void FP80HexToIntPair(const char *Buffer, const char *End, uint64_t Pair[2]); - }; -} // end namespace llvm - -#endif diff --git a/llvm-project-llvmorg-12.0.1/llvm/lib/AsmParser/LLParser.cpp b/llvm-project-llvmorg-13.0.0/llvm/lib/AsmParser/LLParser.cpp index 2a3fb8f..799cb03 100644 --- a/llvm-project-llvmorg-12.0.1/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm-project-llvmorg-13.0.0/llvm/lib/AsmParser/LLParser.cpp @@ -10,13 +10,13 @@ // //===----------------------------------------------------------------------===// -#include "LLParser.h" -#include "LLToken.h" +#include "llvm/AsmParser/LLParser.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/AsmParser/LLToken.h" #include "llvm/AsmParser/SlotMapping.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/IR/Argument.h" @@ -32,6 +32,7 @@ #include "llvm/IR/GlobalIFunc.h" #include "llvm/IR/GlobalObject.h" #include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" @@ -356,10 +357,6 @@ bool LLParser::parseTopLevelEntities() { if (parseModuleAsm()) return true; break; - case lltok::kw_deplibs: - if (parseDepLibs()) - return true; - break; case lltok::LocalVarID: if (parseUnnamedType()) return true; @@ -459,29 +456,6 @@ bool LLParser::parseSourceFileName() { 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() { @@ -694,8 +668,8 @@ bool LLParser::parseComdat() { case lltok::kw_largest: SK = Comdat::Largest; break; - case lltok::kw_noduplicates: - SK = Comdat::NoDuplicates; + case lltok::kw_nodeduplicate: + SK = Comdat::NoDeduplicate; break; case lltok::kw_samesize: SK = Comdat::SameSize; @@ -776,6 +750,11 @@ bool LLParser::parseNamedMetadata() { Lex.getStrVal() == "DIExpression") { if (parseDIExpression(N, /*IsDistinct=*/false)) return true; + // DIArgLists should only appear inline in a function, as they may + // contain LocalAsMetadata arguments which require a function context. + } else if (Lex.getKind() == lltok::MetadataVar && + Lex.getStrVal() == "DIArgList") { + return tokError("found DIArgList outside of function"); } else if (parseToken(lltok::exclaim, "Expected '!' here") || parseMDNodeID(N)) { return true; @@ -926,6 +905,14 @@ static void maybeSetDSOLocal(bool DSOLocal, GlobalValue &GV) { GV.setDSOLocal(true); } +static std::string typeComparisonErrorMessage(StringRef Message, Type *Ty1, + Type *Ty2) { + std::string ErrString; + raw_string_ostream ErrOS(ErrString); + ErrOS << Message << " (" << *Ty1 << " vs " << *Ty2 << ")"; + return ErrOS.str(); +} + /// parseIndirectSymbol: /// ::= GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier /// OptionalVisibility OptionalDLLStorageClass @@ -980,7 +967,7 @@ bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc, } else { // The bitcast dest type is not present, it is implied by the dest type. ValID ID; - if (parseValID(ID)) + if (parseValID(ID, /*PFS=*/nullptr)) return true; if (ID.Kind != ValID::t_Constant) return error(AliaseeLoc, "invalid aliasee"); @@ -993,23 +980,30 @@ bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc, 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->isOpaqueOrPointeeTypeMatches(Ty)) { + return error( + ExplicitTypeLoc, + typeComparisonErrorMessage( + "explicit pointee type doesn't match operand's pointee type", Ty, + PTy->getElementType())); + } - if (!IsAlias && !PTy->getElementType()->isFunctionTy()) + if (!IsAlias && !PTy->getElementType()->isFunctionTy()) { return error(ExplicitTypeLoc, "explicit pointee type should be a function type"); + } GlobalValue *GVal = nullptr; // See if the alias was forward referenced, if so, prepare to replace the // forward reference. if (!Name.empty()) { - GVal = M->getNamedValue(Name); - if (GVal) { - if (!ForwardRefVals.erase(Name)) - return error(NameLoc, "redefinition of global '@" + Name + "'"); + auto I = ForwardRefVals.find(Name); + if (I != ForwardRefVals.end()) { + GVal = I->second.first; + ForwardRefVals.erase(Name); + } else if (M->getNamedValue(Name)) { + return error(NameLoc, "redefinition of global '@" + Name + "'"); } } else { auto I = ForwardRefValIDs.find(NumberedVals.size()); @@ -1131,10 +1125,12 @@ bool LLParser::parseGlobal(const std::string &Name, LocTy NameLoc, // 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 + "'"); + auto I = ForwardRefVals.find(Name); + if (I != ForwardRefVals.end()) { + GVal = I->second.first; + ForwardRefVals.erase(I); + } else if (M->getNamedValue(Name)) { + return error(NameLoc, "redefinition of global '@" + Name + "'"); } } else { auto I = ForwardRefValIDs.find(NumberedVals.size()); @@ -1144,22 +1140,9 @@ bool LLParser::parseGlobal(const std::string &Name, LocTy NameLoc, } } - 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(GVal); - - // Move the forward-reference to the correct spot in the module. - M->getGlobalList().splice(M->global_end(), M->getGlobalList(), GV); - } + GlobalVariable *GV = new GlobalVariable( + *M, Ty, false, GlobalValue::ExternalLinkage, nullptr, Name, nullptr, + GlobalVariable::NotThreadLocal, AddrSpace); if (Name.empty()) NumberedVals.push_back(GV); @@ -1176,6 +1159,16 @@ bool LLParser::parseGlobal(const std::string &Name, LocTy NameLoc, GV->setThreadLocalMode(TLM); GV->setUnnamedAddr(UnnamedAddr); + if (GVal) { + if (!GVal->getType()->isOpaque() && GVal->getValueType() != Ty) + return error( + TyLoc, + "forward reference and definition of global have different types"); + + GVal->replaceAllUsesWith(GV); + GVal->eraseFromParent(); + } + // parse attributes on the global. while (Lex.getKind() == lltok::comma) { Lex.Lex(); @@ -1250,201 +1243,144 @@ bool LLParser::parseUnnamedAttrGrp() { return false; } +static Attribute::AttrKind tokenToAttribute(lltok::Kind Kind) { + switch (Kind) { +#define GET_ATTR_NAMES +#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) \ + case lltok::kw_##DISPLAY_NAME: \ + return Attribute::ENUM_NAME; +#include "llvm/IR/Attributes.inc" + default: + return Attribute::None; + } +} + +bool LLParser::parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B, + bool InAttrGroup) { + if (Attribute::isTypeAttrKind(Attr)) + return parseRequiredTypeAttr(B, Lex.getKind(), Attr); + + switch (Attr) { + case Attribute::Alignment: { + MaybeAlign Alignment; + if (InAttrGroup) { + uint32_t Value = 0; + Lex.Lex(); + if (parseToken(lltok::equal, "expected '=' here") || parseUInt32(Value)) + return true; + Alignment = Align(Value); + } else { + if (parseOptionalAlignment(Alignment, true)) + return true; + } + B.addAlignmentAttr(Alignment); + return false; + } + case Attribute::StackAlignment: { + unsigned Alignment; + if (InAttrGroup) { + Lex.Lex(); + if (parseToken(lltok::equal, "expected '=' here") || + parseUInt32(Alignment)) + return true; + } else { + if (parseOptionalStackAlignment(Alignment)) + return true; + } + B.addStackAlignmentAttr(Alignment); + return false; + } + case Attribute::AllocSize: { + unsigned ElemSizeArg; + Optional NumElemsArg; + if (parseAllocSizeArguments(ElemSizeArg, NumElemsArg)) + return true; + B.addAllocSizeAttr(ElemSizeArg, NumElemsArg); + return false; + } + case Attribute::VScaleRange: { + unsigned MinValue, MaxValue; + if (parseVScaleRangeArguments(MinValue, MaxValue)) + return true; + B.addVScaleRangeAttr(MinValue, MaxValue); + return false; + } + case Attribute::Dereferenceable: { + uint64_t Bytes; + if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes)) + return true; + B.addDereferenceableAttr(Bytes); + return false; + } + case Attribute::DereferenceableOrNull: { + uint64_t Bytes; + if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes)) + return true; + B.addDereferenceableOrNullAttr(Bytes); + return false; + } + default: + B.addAttribute(Attr); + Lex.Lex(); + return false; + } +} + /// parseFnAttributeValuePairs /// ::= | '=' bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B, std::vector &FwdRefAttrGrps, - bool inAttrGrp, LocTy &BuiltinLoc) { + 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; + if (Token == lltok::rbrace) + return HaveError; // Finished. + + if (Token == lltok::StringConstant) { + if (parseStringAttribute(B)) + return true; + continue; + } - case lltok::AttrGrpID: { + if (Token == lltok::AttrGrpID) { // Allow a function to reference an attribute group: // // define void @foo() #1 { ... } - if (inAttrGrp) + 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. - MaybeAlign Alignment; - if (inAttrGrp) { - Lex.Lex(); - uint32_t Value = 0; - if (parseToken(lltok::equal, "expected '=' here") || parseUInt32(Value)) - return true; - Alignment = Align(Value); } else { - if (parseOptionalAlignment(Alignment)) - return true; + // Save the reference to the attribute group. We'll fill it in later. + FwdRefAttrGrps.push_back(Lex.getUIntVal()); } - 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 NumElemsArg; - // inAttrGrp doesn't matter; we only support allocsize(a[, b]) - if (parseAllocSizeArguments(ElemSizeArg, NumElemsArg)) - return true; - B.addAllocSizeAttr(ElemSizeArg, NumElemsArg); + Lex.Lex(); continue; } - case lltok::kw_alwaysinline: B.addAttribute(Attribute::AlwaysInline); break; - case lltok::kw_argmemonly: B.addAttribute(Attribute::ArgMemOnly); break; - case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break; - case lltok::kw_cold: B.addAttribute(Attribute::Cold); break; - case lltok::kw_hot: B.addAttribute(Attribute::Hot); break; - case lltok::kw_convergent: B.addAttribute(Attribute::Convergent); break; - case lltok::kw_inaccessiblememonly: - B.addAttribute(Attribute::InaccessibleMemOnly); break; - case lltok::kw_inaccessiblemem_or_argmemonly: - B.addAttribute(Attribute::InaccessibleMemOrArgMemOnly); break; - case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break; - case lltok::kw_jumptable: B.addAttribute(Attribute::JumpTable); break; - case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break; - case lltok::kw_mustprogress: - B.addAttribute(Attribute::MustProgress); - break; - case lltok::kw_naked: B.addAttribute(Attribute::Naked); break; - case lltok::kw_nobuiltin: B.addAttribute(Attribute::NoBuiltin); break; - case lltok::kw_nocallback: - B.addAttribute(Attribute::NoCallback); - break; - case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); break; - case lltok::kw_nofree: B.addAttribute(Attribute::NoFree); break; - case lltok::kw_noimplicitfloat: - B.addAttribute(Attribute::NoImplicitFloat); break; - case lltok::kw_noinline: B.addAttribute(Attribute::NoInline); break; - case lltok::kw_nonlazybind: B.addAttribute(Attribute::NonLazyBind); break; - case lltok::kw_nomerge: B.addAttribute(Attribute::NoMerge); break; - case lltok::kw_noredzone: B.addAttribute(Attribute::NoRedZone); break; - case lltok::kw_noreturn: B.addAttribute(Attribute::NoReturn); break; - case lltok::kw_nosync: B.addAttribute(Attribute::NoSync); break; - case lltok::kw_nocf_check: B.addAttribute(Attribute::NoCfCheck); break; - case lltok::kw_noprofile: B.addAttribute(Attribute::NoProfile); break; - case lltok::kw_norecurse: B.addAttribute(Attribute::NoRecurse); break; - case lltok::kw_nounwind: B.addAttribute(Attribute::NoUnwind); break; - case lltok::kw_null_pointer_is_valid: - B.addAttribute(Attribute::NullPointerIsValid); break; - case lltok::kw_optforfuzzing: - B.addAttribute(Attribute::OptForFuzzing); break; - case lltok::kw_optnone: B.addAttribute(Attribute::OptimizeNone); break; - case lltok::kw_optsize: B.addAttribute(Attribute::OptimizeForSize); break; - case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break; - case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break; - case lltok::kw_returns_twice: - B.addAttribute(Attribute::ReturnsTwice); break; - case lltok::kw_speculatable: B.addAttribute(Attribute::Speculatable); break; - case lltok::kw_ssp: B.addAttribute(Attribute::StackProtect); break; - case lltok::kw_sspreq: B.addAttribute(Attribute::StackProtectReq); break; - case lltok::kw_sspstrong: - B.addAttribute(Attribute::StackProtectStrong); break; - case lltok::kw_safestack: B.addAttribute(Attribute::SafeStack); break; - case lltok::kw_shadowcallstack: - B.addAttribute(Attribute::ShadowCallStack); break; - case lltok::kw_sanitize_address: - B.addAttribute(Attribute::SanitizeAddress); break; - case lltok::kw_sanitize_hwaddress: - B.addAttribute(Attribute::SanitizeHWAddress); break; - case lltok::kw_sanitize_memtag: - B.addAttribute(Attribute::SanitizeMemTag); break; - case lltok::kw_sanitize_thread: - B.addAttribute(Attribute::SanitizeThread); break; - case lltok::kw_sanitize_memory: - B.addAttribute(Attribute::SanitizeMemory); break; - case lltok::kw_speculative_load_hardening: - B.addAttribute(Attribute::SpeculativeLoadHardening); - break; - case lltok::kw_strictfp: B.addAttribute(Attribute::StrictFP); break; - case lltok::kw_uwtable: B.addAttribute(Attribute::UWTable); break; - case lltok::kw_willreturn: B.addAttribute(Attribute::WillReturn); break; - case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break; - case lltok::kw_preallocated: { - Type *Ty; - if (parsePreallocated(Ty)) - return true; - B.addPreallocatedAttr(Ty); - 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_noundef: - case lltok::kw_nocapture: - case lltok::kw_nonnull: - case lltok::kw_returned: - case lltok::kw_sret: - case lltok::kw_swifterror: - case lltok::kw_swiftself: - case lltok::kw_immarg: - case lltok::kw_byref: - HaveError |= - error(Lex.getLoc(), - "invalid use of parameter-only attribute on a function"); - break; + SMLoc Loc = Lex.getLoc(); + if (Token == lltok::kw_builtin) + BuiltinLoc = Loc; + + Attribute::AttrKind Attr = tokenToAttribute(Token); + if (Attr == Attribute::None) { + if (!InAttrGrp) + return HaveError; + return error(Lex.getLoc(), "unterminated attribute group"); } - // parsePreallocated() consumes token - if (Token != lltok::kw_preallocated) - Lex.Lex(); + if (parseEnumAttribute(Attr, B, InAttrGrp)) + return true; + + // As a hack, we allow function alignment to be initially parsed as an + // attribute on a function declaration/definition or added to an attribute + // group and later moved to the alignment field. + if (!Attribute::canUseAsFnAttr(Attr) && Attr != Attribute::Alignment) + HaveError |= error(Loc, "this attribute does not apply to functions"); } } @@ -1452,37 +1388,40 @@ bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B, // GlobalValue Reference/Resolution Routines. //===----------------------------------------------------------------------===// -static inline GlobalValue *createGlobalFwdRef(Module *M, PointerType *PTy, - const std::string &Name) { - if (auto *FT = dyn_cast(PTy->getElementType())) +static inline GlobalValue *createGlobalFwdRef(Module *M, PointerType *PTy) { + // For opaque pointers, the used global type does not matter. We will later + // RAUW it with a global/function of the correct type. + if (PTy->isOpaque()) + return new GlobalVariable(*M, Type::getInt8Ty(M->getContext()), false, + GlobalValue::ExternalWeakLinkage, nullptr, "", + nullptr, GlobalVariable::NotThreadLocal, + PTy->getAddressSpace()); + + if (auto *FT = dyn_cast(PTy->getPointerElementType())) return Function::Create(FT, GlobalValue::ExternalWeakLinkage, - PTy->getAddressSpace(), Name, M); + PTy->getAddressSpace(), "", M); else - return new GlobalVariable(*M, PTy->getElementType(), false, - GlobalValue::ExternalWeakLinkage, nullptr, Name, + return new GlobalVariable(*M, PTy->getPointerElementType(), false, + GlobalValue::ExternalWeakLinkage, nullptr, "", nullptr, GlobalVariable::NotThreadLocal, PTy->getAddressSpace()); } Value *LLParser::checkValidVariableType(LocTy Loc, const Twine &Name, Type *Ty, Value *Val, bool IsCall) { - if (Val->getType() == Ty) + Type *ValTy = Val->getType(); + if (ValTy == Ty) + return Val; + // For calls, we also allow opaque pointers. + if (IsCall && ValTy == PointerType::get(Ty->getContext(), + Ty->getPointerAddressSpace())) return Val; - // For calls we also accept variables in the program address space. - Type *SuggestedTy = Ty; - if (IsCall && isa(Ty)) { - Type *TyInProgAS = cast(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) + "'"); + getTypeString(Ty) + "'"); return nullptr; } @@ -1678,254 +1617,32 @@ bool LLParser::parseStringAttribute(AttrBuilder &B) { return false; } -/// parseOptionalParamAttrs - parse a potentially empty list of parameter -/// attributes. -bool LLParser::parseOptionalParamAttrs(AttrBuilder &B) { +/// Parse a potentially empty list of parameter or return attributes. +bool LLParser::parseOptionalParamOrReturnAttrs(AttrBuilder &B, bool IsParam) { bool HaveError = false; B.clear(); while (true) { lltok::Kind Token = Lex.getKind(); - switch (Token) { - default: // End of attributes. - return HaveError; - case lltok::StringConstant: { + if (Token == lltok::StringConstant) { if (parseStringAttribute(B)) return true; continue; } - case lltok::kw_align: { - MaybeAlign Alignment; - if (parseOptionalAlignment(Alignment, true)) - return true; - B.addAlignmentAttr(Alignment); - continue; - } - case lltok::kw_byval: { - Type *Ty; - if (parseRequiredTypeAttr(Ty, lltok::kw_byval)) - return true; - B.addByValAttr(Ty); - continue; - } - case lltok::kw_sret: { - Type *Ty; - if (parseRequiredTypeAttr(Ty, lltok::kw_sret)) - return true; - B.addStructRetAttr(Ty); - continue; - } - case lltok::kw_preallocated: { - Type *Ty; - if (parsePreallocated(Ty)) - return true; - B.addPreallocatedAttr(Ty); - continue; - } - case lltok::kw_dereferenceable: { - uint64_t Bytes; - if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes)) - return true; - B.addDereferenceableAttr(Bytes); - continue; - } - case lltok::kw_dereferenceable_or_null: { - uint64_t Bytes; - if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes)) - return true; - B.addDereferenceableOrNullAttr(Bytes); - continue; - } - case lltok::kw_byref: { - Type *Ty; - if (parseByRef(Ty)) - return true; - B.addByRefAttr(Ty); - continue; - } - case lltok::kw_inalloca: B.addAttribute(Attribute::InAlloca); break; - case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; - case lltok::kw_nest: B.addAttribute(Attribute::Nest); break; - case lltok::kw_noundef: - B.addAttribute(Attribute::NoUndef); - break; - case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; - case lltok::kw_nocapture: B.addAttribute(Attribute::NoCapture); break; - case lltok::kw_nofree: B.addAttribute(Attribute::NoFree); break; - case lltok::kw_nonnull: B.addAttribute(Attribute::NonNull); break; - case lltok::kw_readnone: B.addAttribute(Attribute::ReadNone); break; - case lltok::kw_readonly: B.addAttribute(Attribute::ReadOnly); break; - case lltok::kw_returned: B.addAttribute(Attribute::Returned); break; - case lltok::kw_signext: B.addAttribute(Attribute::SExt); break; - case lltok::kw_swifterror: B.addAttribute(Attribute::SwiftError); break; - case lltok::kw_swiftself: B.addAttribute(Attribute::SwiftSelf); break; - case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break; - case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break; - case lltok::kw_immarg: B.addAttribute(Attribute::ImmArg); break; - - case lltok::kw_alignstack: - case lltok::kw_alwaysinline: - case lltok::kw_argmemonly: - case lltok::kw_builtin: - case lltok::kw_inlinehint: - case lltok::kw_jumptable: - case lltok::kw_minsize: - case lltok::kw_mustprogress: - case lltok::kw_naked: - case lltok::kw_nobuiltin: - case lltok::kw_noduplicate: - case lltok::kw_noimplicitfloat: - case lltok::kw_noinline: - case lltok::kw_nonlazybind: - case lltok::kw_nomerge: - case lltok::kw_noprofile: - case lltok::kw_noredzone: - case lltok::kw_noreturn: - case lltok::kw_nocf_check: - case lltok::kw_nounwind: - case lltok::kw_optforfuzzing: - case lltok::kw_optnone: - case lltok::kw_optsize: - case lltok::kw_returns_twice: - case lltok::kw_sanitize_address: - case lltok::kw_sanitize_hwaddress: - case lltok::kw_sanitize_memtag: - case lltok::kw_sanitize_memory: - case lltok::kw_sanitize_thread: - case lltok::kw_speculative_load_hardening: - case lltok::kw_ssp: - case lltok::kw_sspreq: - case lltok::kw_sspstrong: - case lltok::kw_safestack: - case lltok::kw_shadowcallstack: - case lltok::kw_strictfp: - case lltok::kw_uwtable: - 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. + SMLoc Loc = Lex.getLoc(); + Attribute::AttrKind Attr = tokenToAttribute(Token); + if (Attr == Attribute::None) 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: { - MaybeAlign Alignment; - if (parseOptionalAlignment(Alignment)) - return true; - B.addAlignmentAttr(Alignment); - continue; - } - case lltok::kw_inreg: B.addAttribute(Attribute::InReg); break; - case lltok::kw_noalias: B.addAttribute(Attribute::NoAlias); break; - case lltok::kw_noundef: - B.addAttribute(Attribute::NoUndef); - break; - case lltok::kw_nonnull: B.addAttribute(Attribute::NonNull); break; - case lltok::kw_signext: B.addAttribute(Attribute::SExt); break; - case lltok::kw_zeroext: B.addAttribute(Attribute::ZExt); break; - - // error handling. - case lltok::kw_byval: - case lltok::kw_inalloca: - case lltok::kw_nest: - case lltok::kw_nocapture: - case lltok::kw_returned: - case lltok::kw_sret: - case lltok::kw_swifterror: - case lltok::kw_swiftself: - case lltok::kw_immarg: - case lltok::kw_byref: - HaveError |= - error(Lex.getLoc(), "invalid use of parameter-only attribute"); - break; - case lltok::kw_alignstack: - case lltok::kw_alwaysinline: - case lltok::kw_argmemonly: - case lltok::kw_builtin: - case lltok::kw_cold: - case lltok::kw_inlinehint: - case lltok::kw_jumptable: - case lltok::kw_minsize: - case lltok::kw_mustprogress: - case lltok::kw_naked: - case lltok::kw_nobuiltin: - case lltok::kw_noduplicate: - case lltok::kw_noimplicitfloat: - case lltok::kw_noinline: - case lltok::kw_nonlazybind: - case lltok::kw_nomerge: - case lltok::kw_noprofile: - case lltok::kw_noredzone: - case lltok::kw_noreturn: - case lltok::kw_nocf_check: - case lltok::kw_nounwind: - case lltok::kw_optforfuzzing: - case lltok::kw_optnone: - case lltok::kw_optsize: - case lltok::kw_returns_twice: - case lltok::kw_sanitize_address: - case lltok::kw_sanitize_hwaddress: - case lltok::kw_sanitize_memtag: - case lltok::kw_sanitize_memory: - case lltok::kw_sanitize_thread: - case lltok::kw_speculative_load_hardening: - case lltok::kw_ssp: - case lltok::kw_sspreq: - case lltok::kw_sspstrong: - case lltok::kw_safestack: - case lltok::kw_shadowcallstack: - case lltok::kw_strictfp: - case lltok::kw_uwtable: - 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"); - break; - case lltok::kw_preallocated: - HaveError |= - error(Lex.getLoc(), - "invalid use of parameter-only/call site-only attribute"); - break; - } + if (parseEnumAttribute(Attr, B, /* InAttrGroup */ false)) + return true; - Lex.Lex(); + if (IsParam && !Attribute::canUseAsParamAttr(Attr)) + HaveError |= error(Loc, "this attribute does not apply to parameters"); + if (!IsParam && !Attribute::canUseAsRetAttr(Attr)) + HaveError |= error(Loc, "this attribute does not apply to return values"); } } @@ -2081,6 +1798,7 @@ void LLParser::parseOptionalDLLStorageClass(unsigned &Res) { /// ::= 'preserve_allcc' /// ::= 'ghccc' /// ::= 'swiftcc' +/// ::= 'swifttailcc' /// ::= 'x86_intrcc' /// ::= 'hhvmcc' /// ::= 'hhvm_ccc' @@ -2131,6 +1849,7 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) { case lltok::kw_preserve_allcc: CC = CallingConv::PreserveAll; break; case lltok::kw_ghccc: CC = CallingConv::GHC; break; case lltok::kw_swiftcc: CC = CallingConv::Swift; break; + case lltok::kw_swifttailcc: CC = CallingConv::SwiftTail; break; case lltok::kw_x86_intrcc: CC = CallingConv::X86_INTR; break; case lltok::kw_hhvmcc: CC = CallingConv::HHVM; break; case lltok::kw_hhvm_ccc: CC = CallingConv::HHVM_C; break; @@ -2350,6 +2069,29 @@ bool LLParser::parseAllocSizeArguments(unsigned &BaseSizeArg, return false; } +bool LLParser::parseVScaleRangeArguments(unsigned &MinValue, + unsigned &MaxValue) { + Lex.Lex(); + + auto StartParen = Lex.getLoc(); + if (!EatIfPresent(lltok::lparen)) + return error(StartParen, "expected '('"); + + if (parseUInt32(MinValue)) + return true; + + if (EatIfPresent(lltok::comma)) { + if (parseUInt32(MaxValue)) + return true; + } else + MaxValue = MinValue; + + auto EndParen = Lex.getLoc(); + if (!EatIfPresent(lltok::rparen)) + return error(EndParen, "expected ')'"); + return false; +} + /// parseScopeAndOrdering /// if isAtomic: ::= SyncScope? AtomicOrdering /// else: ::= @@ -2532,6 +2274,26 @@ bool LLParser::parseType(Type *&Result, const Twine &Msg, bool AllowVoid) { } } + // Handle (explicit) opaque pointer types (not --force-opaque-pointers). + // + // Type ::= ptr ('addrspace' '(' uint32 ')')? + if (Result->isOpaquePointerTy()) { + unsigned AddrSpace; + if (parseOptionalAddrSpace(AddrSpace)) + return true; + Result = PointerType::get(getContext(), AddrSpace); + + // Give a nice error for 'ptr*'. + if (Lex.getKind() == lltok::star) + return tokError("ptr* is invalid - use ptr instead"); + + // Fall through to parsing the type suffixes only if this 'ptr' is a + // function return. Otherwise, return success, implicitly rejecting other + // suffixes. + if (Lex.getKind() != lltok::lparen) + return false; + } + // parse the type suffixes. while (true) { switch (Lex.getKind()) { @@ -2637,29 +2399,20 @@ bool LLParser::parseParameterList(SmallVectorImpl &ArgList, /// parseRequiredTypeAttr /// ::= attrname() -bool LLParser::parseRequiredTypeAttr(Type *&Result, lltok::Kind AttrName) { - Result = nullptr; - if (!EatIfPresent(AttrName)) +bool LLParser::parseRequiredTypeAttr(AttrBuilder &B, lltok::Kind AttrToken, + Attribute::AttrKind AttrKind) { + Type *Ty = nullptr; + if (!EatIfPresent(AttrToken)) return true; if (!EatIfPresent(lltok::lparen)) return error(Lex.getLoc(), "expected '('"); - if (parseType(Result)) + if (parseType(Ty)) return true; if (!EatIfPresent(lltok::rparen)) return error(Lex.getLoc(), "expected ')'"); - return false; -} -/// parsePreallocated -/// ::= preallocated() -bool LLParser::parsePreallocated(Type *&Result) { - return parseRequiredTypeAttr(Result, lltok::kw_preallocated); -} - -/// parseByRef -/// ::= byref() -bool LLParser::parseByRef(Type *&Result) { - return parseRequiredTypeAttr(Result, lltok::kw_byref); + B.addTypeAttr(AttrKind, Ty); + return false; } /// parseOptionalOperandBundles @@ -3241,7 +2994,7 @@ BasicBlock *LLParser::PerFunctionState::defineBB(const std::string &Name, /// sanity. PFS is used to convert function-local operands of metadata (since /// metadata operands are not just parsed here but also converted to values). /// PFS can be null when we are not parsing metadata values inside a function. -bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS) { +bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) { ID.Loc = Lex.getLoc(); switch (Lex.getKind()) { default: @@ -3389,18 +3142,19 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS) { case lltok::kw_asm: { // ValID ::= 'asm' SideEffect? AlignStack? IntelDialect? STRINGCONSTANT ',' // STRINGCONSTANT - bool HasSideEffect, AlignStack, AsmDialect; + bool HasSideEffect, AlignStack, AsmDialect, CanThrow; Lex.Lex(); if (parseOptionalToken(lltok::kw_sideeffect, HasSideEffect) || parseOptionalToken(lltok::kw_alignstack, AlignStack) || parseOptionalToken(lltok::kw_inteldialect, AsmDialect) || + parseOptionalToken(lltok::kw_unwind, CanThrow) || parseStringConstant(ID.StrVal) || parseToken(lltok::comma, "expected comma in inline asm expression") || parseToken(lltok::StringConstant, "expected constraint string")) return true; ID.StrVal2 = Lex.getStrVal(); - ID.UIntVal = unsigned(HasSideEffect) | (unsigned(AlignStack)<<1) | - (unsigned(AsmDialect)<<2); + ID.UIntVal = unsigned(HasSideEffect) | (unsigned(AlignStack) << 1) | + (unsigned(AsmDialect) << 2) | (unsigned(CanThrow) << 3); ID.Kind = ValID::t_InlineAsm; return false; } @@ -3412,10 +3166,10 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS) { ValID Fn, Label; if (parseToken(lltok::lparen, "expected '(' in block address expression") || - parseValID(Fn) || + parseValID(Fn, PFS) || parseToken(lltok::comma, "expected comma in block address expression") || - parseValID(Label) || + parseValID(Label, PFS) || parseToken(lltok::rparen, "expected ')' in block address expression")) return true; @@ -3450,9 +3204,27 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS) { std::map())) .first->second.insert(std::make_pair(std::move(Label), nullptr)) .first->second; - if (!FwdRef) - FwdRef = new GlobalVariable(*M, Type::getInt8Ty(Context), false, - GlobalValue::InternalLinkage, nullptr, ""); + if (!FwdRef) { + unsigned FwdDeclAS; + if (ExpectedTy) { + // If we know the type that the blockaddress is being assigned to, + // we can use the address space of that type. + if (!ExpectedTy->isPointerTy()) + return error(ID.Loc, + "type of blockaddress must be a pointer and not '" + + getTypeString(ExpectedTy) + "'"); + FwdDeclAS = ExpectedTy->getPointerAddressSpace(); + } else if (PFS) { + // Otherwise, we default the address space of the current function. + FwdDeclAS = PFS->getFunction().getAddressSpace(); + } else { + llvm_unreachable("Unknown address space for blockaddress"); + } + FwdRef = new GlobalVariable( + *M, Type::getInt8Ty(Context), false, GlobalValue::InternalLinkage, + nullptr, "", nullptr, GlobalValue::NotThreadLocal, FwdDeclAS); + } + ID.ConstantVal = FwdRef; ID.Kind = ValID::t_Constant; return false; @@ -3489,7 +3261,7 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS) { ValID Fn; - if (parseValID(Fn)) + if (parseValID(Fn, PFS)) return true; if (Fn.Kind != ValID::t_GlobalID && Fn.Kind != ValID::t_GlobalName) @@ -3788,10 +3560,13 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS) { Type *BaseType = Elts[0]->getType(); auto *BasePointerType = cast(BaseType->getScalarType()); - if (Ty != BasePointerType->getElementType()) + if (!BasePointerType->isOpaqueOrPointeeTypeMatches(Ty)) { return error( ExplicitTypeLoc, - "explicit pointee type doesn't match operand's pointee type"); + typeComparisonErrorMessage( + "explicit pointee type doesn't match operand's pointee type", + Ty, BasePointerType->getElementType())); + } unsigned GEPWidth = BaseType->isVectorTy() @@ -3876,7 +3651,7 @@ bool LLParser::parseGlobalValue(Type *Ty, Constant *&C) { C = nullptr; ValID ID; Value *V = nullptr; - bool Parsed = parseValID(ID) || + bool Parsed = parseValID(ID, /*PFS=*/nullptr, Ty) || convertValIDToValue(Ty, ID, V, nullptr, /*IsCall=*/false); if (V && !(C = dyn_cast(V))) return error(ID.Loc, "global values must be constants"); @@ -4666,11 +4441,6 @@ bool LLParser::parseDISubrange(MDNode *&Result, bool IsDistinct) { Metadata *LowerBound = nullptr; Metadata *UpperBound = nullptr; Metadata *Stride = nullptr; - if (count.isMDSignedField()) - Count = ConstantAsMetadata::get(ConstantInt::getSigned( - Type::getInt64Ty(Context), count.getMDSignedValue())); - else if (count.isMDField()) - Count = count.getMDFieldValue(); auto convToMetadata = [&](MDSignedOrMDField Bound) -> Metadata * { if (Bound.isMDSignedField()) @@ -4681,6 +4451,7 @@ bool LLParser::parseDISubrange(MDNode *&Result, bool IsDistinct) { return nullptr; }; + Count = convToMetadata(count); LowerBound = convToMetadata(lowerBound); UpperBound = convToMetadata(upperBound); Stride = convToMetadata(stride); @@ -5297,6 +5068,36 @@ bool LLParser::parseDIExpression(MDNode *&Result, bool IsDistinct) { return false; } +bool LLParser::parseDIArgList(MDNode *&Result, bool IsDistinct) { + return parseDIArgList(Result, IsDistinct, nullptr); +} +/// ParseDIArgList: +/// ::= !DIArgList(i32 7, i64 %0) +bool LLParser::parseDIArgList(MDNode *&Result, bool IsDistinct, + PerFunctionState *PFS) { + assert(PFS && "Expected valid function state"); + assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name"); + Lex.Lex(); + + if (parseToken(lltok::lparen, "expected '(' here")) + return true; + + SmallVector Args; + if (Lex.getKind() != lltok::rparen) + do { + Metadata *MD; + if (parseValueAsMetadata(MD, "expected value-as-metadata operand", PFS)) + return true; + Args.push_back(dyn_cast(MD)); + } while (EatIfPresent(lltok::comma)); + + if (parseToken(lltok::rparen, "expected ')' here")) + return true; + + Result = GET_OR_DISTINCT(DIArgList, (Context, Args)); + return false; +} + /// parseDIGlobalVariableExpression: /// ::= !DIGlobalVariableExpression(var: !0, expr: !1) bool LLParser::parseDIGlobalVariableExpression(MDNode *&Result, @@ -5407,8 +5208,14 @@ bool LLParser::parseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg, bool LLParser::parseMetadata(Metadata *&MD, PerFunctionState *PFS) { if (Lex.getKind() == lltok::MetadataVar) { MDNode *N; - if (parseSpecializedMDNode(N)) + // DIArgLists are a special case, as they are a list of ValueAsMetadata and + // so parsing this requires a Function State. + if (Lex.getStrVal() == "DIArgList") { + if (parseDIArgList(N, false, PFS)) + return true; + } else if (parseSpecializedMDNode(N)) { return true; + } MD = N; return false; } @@ -5465,9 +5272,9 @@ bool LLParser::convertValIDToValue(Type *Ty, ValID &ID, Value *&V, case ValID::t_InlineAsm: { if (!ID.FTy || !InlineAsm::Verify(ID.FTy, ID.StrVal2)) return error(ID.Loc, "invalid type for inline asm constraint string"); - V = InlineAsm::get(ID.FTy, ID.StrVal, ID.StrVal2, ID.UIntVal & 1, - (ID.UIntVal >> 1) & 1, - (InlineAsm::AsmDialect(ID.UIntVal >> 2))); + V = InlineAsm::get( + ID.FTy, ID.StrVal, ID.StrVal2, ID.UIntVal & 1, (ID.UIntVal >> 1) & 1, + InlineAsm::AsmDialect((ID.UIntVal >> 2) & 1), (ID.UIntVal >> 3) & 1); return false; } case ValID::t_GlobalName: @@ -5553,7 +5360,9 @@ bool LLParser::convertValIDToValue(Type *Ty, ValID &ID, Value *&V, return false; case ValID::t_Constant: if (ID.ConstantVal->getType() != Ty) - return error(ID.Loc, "constant expression type mismatch"); + return error(ID.Loc, "constant expression type mismatch: got type '" + + getTypeString(ID.ConstantVal->getType()) + + "' but expected '" + getTypeString(Ty) + "'"); V = ID.ConstantVal; return false; case ValID::t_ConstantStruct: @@ -5613,7 +5422,7 @@ bool LLParser::parseConstantValue(Type *Ty, Constant *&C) { bool LLParser::parseValue(Type *Ty, Value *&V, PerFunctionState *PFS) { V = nullptr; ValID ID; - return parseValID(ID, PFS) || + return parseValID(ID, PFS, Ty) || convertValIDToValue(Ty, ID, V, PFS, /*IsCall=*/false); } @@ -5769,24 +5578,27 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine) { PointerType *PFT = PointerType::get(FT, AddrSpace); Fn = nullptr; + GlobalValue *FwdFn = nullptr; if (!FunctionName.empty()) { // If this was a definition of a forward reference, remove the definition // from the forward reference table and fill in the forward ref. auto FRVI = ForwardRefVals.find(FunctionName); if (FRVI != ForwardRefVals.end()) { - Fn = M->getFunction(FunctionName); - if (!Fn) - return error(FRVI->second.second, "invalid forward reference to " - "function as global value!"); - if (Fn->getType() != PFT) - return error(FRVI->second.second, - "invalid forward reference to " - "function '" + - FunctionName + - "' with wrong type: " - "expected '" + - getTypeString(PFT) + "' but was '" + - getTypeString(Fn->getType()) + "'"); + FwdFn = FRVI->second.first; + if (!FwdFn->getType()->isOpaque()) { + if (!FwdFn->getType()->getPointerElementType()->isFunctionTy()) + return error(FRVI->second.second, "invalid forward reference to " + "function as global value!"); + if (FwdFn->getType() != PFT) + return error(FRVI->second.second, + "invalid forward reference to " + "function '" + + FunctionName + + "' with wrong type: " + "expected '" + + getTypeString(PFT) + "' but was '" + + getTypeString(FwdFn->getType()) + "'"); + } ForwardRefVals.erase(FRVI); } else if ((Fn = M->getFunction(FunctionName))) { // Reject redefinitions. @@ -5801,23 +5613,20 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine) { // types agree. auto I = ForwardRefValIDs.find(NumberedVals.size()); if (I != ForwardRefValIDs.end()) { - Fn = cast(I->second.first); - if (Fn->getType() != PFT) + FwdFn = cast(I->second.first); + if (!FwdFn->getType()->isOpaque() && FwdFn->getType() != PFT) return error(NameLoc, "type of definition and forward reference of '@" + Twine(NumberedVals.size()) + "' disagree: " "expected '" + getTypeString(PFT) + "' but was '" + - getTypeString(Fn->getType()) + "'"); + getTypeString(FwdFn->getType()) + "'"); ForwardRefValIDs.erase(I); } } - if (!Fn) - Fn = Function::Create(FT, GlobalValue::ExternalLinkage, AddrSpace, - FunctionName, M); - else // Move the forward-reference to the correct spot in the module. - M->getFunctionList().splice(M->end(), M->getFunctionList(), Fn); + Fn = Function::Create(FT, GlobalValue::ExternalLinkage, AddrSpace, + FunctionName, M); assert(Fn->getAddressSpace() == AddrSpace && "Created function in wrong AS"); @@ -5855,6 +5664,11 @@ bool LLParser::parseFunctionHeader(Function *&Fn, bool IsDefine) { "redefinition of argument '%" + ArgList[i].Name + "'"); } + if (FwdFn) { + FwdFn->replaceAllUsesWith(Fn); + FwdFn->eraseFromParent(); + } + if (IsDefine) return false; @@ -5902,7 +5716,12 @@ bool LLParser::PerFunctionState::resolveForwardRefBlockAddresses() { if (!BB) return P.error(BBID.Loc, "referenced value is not a basic block"); - GV->replaceAllUsesWith(BlockAddress::get(&F, BB)); + Value *ResolvedVal = BlockAddress::get(&F, BB); + ResolvedVal = P.checkValidVariableType(BBID.Loc, BBID.StrVal, GV->getType(), + ResolvedVal, false); + if (!ResolvedVal) + return true; + GV->replaceAllUsesWith(ResolvedVal); GV->eraseFromParent(); } @@ -6437,7 +6256,7 @@ bool LLParser::parseInvoke(Instruction *&Inst, PerFunctionState &PFS) { if (parseOptionalCallingConv(CC) || parseOptionalReturnAttrs(RetAttrs) || parseOptionalProgramAddrSpace(InvokeAddrSpace) || parseType(RetType, RetTypeLoc, true /*void allowed*/) || - parseValID(CalleeID) || parseParameterList(ArgList, PFS) || + parseValID(CalleeID, &PFS) || parseParameterList(ArgList, PFS) || parseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false, NoBuiltinLoc) || parseOptionalOperandBundles(BundleList, PFS) || @@ -6745,7 +6564,7 @@ bool LLParser::parseCallBr(Instruction *&Inst, PerFunctionState &PFS) { BasicBlock *DefaultDest; if (parseOptionalCallingConv(CC) || parseOptionalReturnAttrs(RetAttrs) || parseType(RetType, RetTypeLoc, true /*void allowed*/) || - parseValID(CalleeID) || parseParameterList(ArgList, PFS) || + parseValID(CalleeID, &PFS) || parseParameterList(ArgList, PFS) || parseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false, NoBuiltinLoc) || parseOptionalOperandBundles(BundleList, PFS) || @@ -7172,7 +6991,7 @@ bool LLParser::parseCall(Instruction *&Inst, PerFunctionState &PFS, if (parseOptionalCallingConv(CC) || parseOptionalReturnAttrs(RetAttrs) || parseOptionalProgramAddrSpace(CallAddrSpace) || parseType(RetType, RetTypeLoc, true /*void allowed*/) || - parseValID(CalleeID) || + parseValID(CalleeID, &PFS) || parseParameterList(ArgList, PFS, TCK == CallInst::TCK_MustTail, PFS.getFunction().isVarArg()) || parseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false, BuiltinLoc) || @@ -7366,9 +7185,13 @@ int LLParser::parseLoad(Instruction *&Inst, PerFunctionState &PFS) { Ordering == AtomicOrdering::AcquireRelease) return error(Loc, "atomic load cannot use Release ordering"); - if (Ty != cast(Val->getType())->getElementType()) - return error(ExplicitTypeLoc, - "explicit pointee type doesn't match operand's pointee type"); + if (!cast(Val->getType())->isOpaqueOrPointeeTypeMatches(Ty)) { + return error( + ExplicitTypeLoc, + typeComparisonErrorMessage( + "explicit pointee type doesn't match operand's pointee type", Ty, + cast(Val->getType())->getElementType())); + } SmallPtrSet Visited; if (!Alignment && !Ty->isSized(&Visited)) return error(ExplicitTypeLoc, "loading unsized types is not allowed"); @@ -7413,7 +7236,8 @@ int LLParser::parseStore(Instruction *&Inst, PerFunctionState &PFS) { return error(PtrLoc, "store operand must be a pointer"); if (!Val->getType()->isFirstClassType()) return error(Loc, "store operand must be a first class value"); - if (cast(Ptr->getType())->getElementType() != Val->getType()) + if (!cast(Ptr->getType()) + ->isOpaqueOrPointeeTypeMatches(Val->getType())) return error(Loc, "stored value and pointer type do not match"); if (isAtomic && !Alignment) return error(Loc, "atomic store must have explicit non-zero alignment"); @@ -7432,7 +7256,8 @@ int LLParser::parseStore(Instruction *&Inst, PerFunctionState &PFS) { /// parseCmpXchg /// ::= 'cmpxchg' 'weak'? 'volatile'? TypeAndValue ',' TypeAndValue ',' -/// TypeAndValue 'singlethread'? AtomicOrdering AtomicOrdering +/// TypeAndValue 'singlethread'? AtomicOrdering AtomicOrdering ',' +/// 'Align'? int LLParser::parseCmpXchg(Instruction *&Inst, PerFunctionState &PFS) { Value *Ptr, *Cmp, *New; LocTy PtrLoc, CmpLoc, NewLoc; bool AteExtraComma = false; @@ -7441,6 +7266,7 @@ int LLParser::parseCmpXchg(Instruction *&Inst, PerFunctionState &PFS) { SyncScope::ID SSID = SyncScope::System; bool isVolatile = false; bool isWeak = false; + MaybeAlign Alignment; if (EatIfPresent(lltok::kw_weak)) isWeak = true; @@ -7454,36 +7280,37 @@ int LLParser::parseCmpXchg(Instruction *&Inst, PerFunctionState &PFS) { parseToken(lltok::comma, "expected ',' after cmpxchg cmp operand") || parseTypeAndValue(New, NewLoc, PFS) || parseScopeAndOrdering(true /*Always atomic*/, SSID, SuccessOrdering) || - parseOrdering(FailureOrdering)) + parseOrdering(FailureOrdering) || + parseOptionalCommaAlign(Alignment, AteExtraComma)) return true; - if (SuccessOrdering == AtomicOrdering::Unordered || - FailureOrdering == AtomicOrdering::Unordered) - return tokError("cmpxchg cannot be unordered"); - if (isStrongerThan(FailureOrdering, SuccessOrdering)) - return tokError("cmpxchg failure argument shall be no stronger than the " - "success argument"); - if (FailureOrdering == AtomicOrdering::Release || - FailureOrdering == AtomicOrdering::AcquireRelease) - return tokError( - "cmpxchg failure ordering cannot include release semantics"); + if (!AtomicCmpXchgInst::isValidSuccessOrdering(SuccessOrdering)) + return tokError("invalid cmpxchg success ordering"); + if (!AtomicCmpXchgInst::isValidFailureOrdering(FailureOrdering)) + return tokError("invalid cmpxchg failure ordering"); if (!Ptr->getType()->isPointerTy()) return error(PtrLoc, "cmpxchg operand must be a pointer"); - if (cast(Ptr->getType())->getElementType() != Cmp->getType()) + if (!cast(Ptr->getType()) + ->isOpaqueOrPointeeTypeMatches(Cmp->getType())) return error(CmpLoc, "compare value and pointer type do not match"); - if (cast(Ptr->getType())->getElementType() != New->getType()) + if (!cast(Ptr->getType()) + ->isOpaqueOrPointeeTypeMatches(New->getType())) return error(NewLoc, "new value and pointer type do not match"); + if (Cmp->getType() != New->getType()) + return error(NewLoc, "compare value and new value type do not match"); if (!New->getType()->isFirstClassType()) return error(NewLoc, "cmpxchg operand must be a first class value"); - Align Alignment( + const Align DefaultAlignment( PFS.getFunction().getParent()->getDataLayout().getTypeStoreSize( Cmp->getType())); AtomicCmpXchgInst *CXI = new AtomicCmpXchgInst( - Ptr, Cmp, New, Alignment, SuccessOrdering, FailureOrdering, SSID); + Ptr, Cmp, New, Alignment.getValueOr(DefaultAlignment), SuccessOrdering, + FailureOrdering, SSID); CXI->setVolatile(isVolatile); CXI->setWeak(isWeak); + Inst = CXI; return AteExtraComma ? InstExtraComma : InstNormal; } @@ -7499,6 +7326,7 @@ int LLParser::parseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS) { bool isVolatile = false; bool IsFP = false; AtomicRMWInst::BinOp Operation; + MaybeAlign Alignment; if (EatIfPresent(lltok::kw_volatile)) isVolatile = true; @@ -7531,14 +7359,16 @@ int LLParser::parseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS) { if (parseTypeAndValue(Ptr, PtrLoc, PFS) || parseToken(lltok::comma, "expected ',' after atomicrmw address") || parseTypeAndValue(Val, ValLoc, PFS) || - parseScopeAndOrdering(true /*Always atomic*/, SSID, Ordering)) + parseScopeAndOrdering(true /*Always atomic*/, SSID, Ordering) || + parseOptionalCommaAlign(Alignment, AteExtraComma)) return true; if (Ordering == AtomicOrdering::Unordered) return tokError("atomicrmw cannot be unordered"); if (!Ptr->getType()->isPointerTy()) return error(PtrLoc, "atomicrmw operand must be a pointer"); - if (cast(Ptr->getType())->getElementType() != Val->getType()) + if (!cast(Ptr->getType()) + ->isOpaqueOrPointeeTypeMatches(Val->getType())) return error(ValLoc, "atomicrmw value and pointer type do not match"); if (Operation == AtomicRMWInst::Xchg) { @@ -7566,11 +7396,12 @@ int LLParser::parseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS) { if (Size < 8 || (Size & (Size - 1))) return error(ValLoc, "atomicrmw operand must be power-of-two byte-sized" " integer"); - Align Alignment( + const Align DefaultAlignment( PFS.getFunction().getParent()->getDataLayout().getTypeStoreSize( Val->getType())); AtomicRMWInst *RMWI = - new AtomicRMWInst(Operation, Ptr, Val, Alignment, Ordering, SSID); + new AtomicRMWInst(Operation, Ptr, Val, + Alignment.getValueOr(DefaultAlignment), Ordering, SSID); RMWI->setVolatile(isVolatile); Inst = RMWI; return AteExtraComma ? InstExtraComma : InstNormal; @@ -7614,9 +7445,13 @@ int LLParser::parseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { if (!BasePointerType) return error(Loc, "base of getelementptr must be a pointer"); - if (Ty != BasePointerType->getElementType()) - return error(ExplicitTypeLoc, - "explicit pointee type doesn't match operand's pointee type"); + if (!BasePointerType->isOpaqueOrPointeeTypeMatches(Ty)) { + return error( + ExplicitTypeLoc, + typeComparisonErrorMessage( + "explicit pointee type doesn't match operand's pointee type", Ty, + BasePointerType->getElementType())); + } SmallVector Indices; bool AteExtraComma = false; @@ -7832,9 +7667,9 @@ bool LLParser::parseUseListOrderBB() { ValID Fn, Label; SmallVector Indexes; - if (parseValID(Fn) || + if (parseValID(Fn, /*PFS=*/nullptr) || parseToken(lltok::comma, "expected comma in uselistorder_bb directive") || - parseValID(Label) || + parseValID(Label, /*PFS=*/nullptr) || parseToken(lltok::comma, "expected comma in uselistorder_bb directive") || parseUseListOrderIndexes(Indexes)) return true; @@ -8517,7 +8352,8 @@ bool LLParser::parseFunctionSummary(std::string Name, GlobalValue::GUID GUID, StringRef ModulePath; GlobalValueSummary::GVFlags GVFlags = GlobalValueSummary::GVFlags( - /*Linkage=*/GlobalValue::ExternalLinkage, /*NotEligibleToImport=*/false, + GlobalValue::ExternalLinkage, GlobalValue::DefaultVisibility, + /*NotEligibleToImport=*/false, /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false); unsigned InstCount; std::vector Calls; @@ -8593,7 +8429,8 @@ bool LLParser::parseVariableSummary(std::string Name, GlobalValue::GUID GUID, StringRef ModulePath; GlobalValueSummary::GVFlags GVFlags = GlobalValueSummary::GVFlags( - /*Linkage=*/GlobalValue::ExternalLinkage, /*NotEligibleToImport=*/false, + GlobalValue::ExternalLinkage, GlobalValue::DefaultVisibility, + /*NotEligibleToImport=*/false, /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false); GlobalVarSummary::GVarFlags GVarFlags(/*ReadOnly*/ false, /* WriteOnly */ false, @@ -8651,7 +8488,8 @@ bool LLParser::parseAliasSummary(std::string Name, GlobalValue::GUID GUID, StringRef ModulePath; GlobalValueSummary::GVFlags GVFlags = GlobalValueSummary::GVFlags( - /*Linkage=*/GlobalValue::ExternalLinkage, /*NotEligibleToImport=*/false, + GlobalValue::ExternalLinkage, GlobalValue::DefaultVisibility, + /*NotEligibleToImport=*/false, /*Live=*/false, /*IsLocal=*/false, /*CanAutoHide=*/false); if (parseToken(lltok::colon, "expected ':' here") || parseToken(lltok::lparen, "expected '(' here") || @@ -9035,6 +8873,7 @@ bool LLParser::parseOptionalParamAccesses( return true; CallsNum += ParamAccess.Calls.size(); assert(VContexts.size() == CallsNum); + (void)CallsNum; Params.emplace_back(std::move(ParamAccess)); } while (EatIfPresent(lltok::comma)); @@ -9339,8 +9178,9 @@ bool LLParser::parseVFuncId(FunctionSummary::VFuncId &VFuncId, /// GVFlags /// ::= 'flags' ':' '(' 'linkage' ':' OptionalLinkageAux ',' -/// 'notEligibleToImport' ':' Flag ',' 'live' ':' Flag ',' -/// 'dsoLocal' ':' Flag ',' 'canAutoHide' ':' Flag ')' +/// 'visibility' ':' Flag 'notEligibleToImport' ':' Flag ',' +/// 'live' ':' Flag ',' 'dsoLocal' ':' Flag ',' +/// 'canAutoHide' ':' Flag ',' ')' bool LLParser::parseGVFlags(GlobalValueSummary::GVFlags &GVFlags) { assert(Lex.getKind() == lltok::kw_flags); Lex.Lex(); @@ -9361,6 +9201,13 @@ bool LLParser::parseGVFlags(GlobalValueSummary::GVFlags &GVFlags) { assert(HasLinkage && "Linkage not optional in summary entry"); Lex.Lex(); break; + case lltok::kw_visibility: + Lex.Lex(); + if (parseToken(lltok::colon, "expected ':'")) + return true; + parseOptionalVisibility(Flag); + GVFlags.Visibility = Flag; + break; case lltok::kw_notEligibleToImport: Lex.Lex(); if (parseToken(lltok::colon, "expected ':'") || parseFlag(Flag)) ```
mewmew commented 2 years ago

Diff

Great @dannypsnl! Feel free to create a llvm13 branch if you feel like. The diff can be added as a file on this branch to track progress like last time.

Cheers, Robin

suhabe commented 2 years ago

Is LLVM 13 and LLVM 14 supported now? If not, how can I help?

dannypsnl commented 2 years ago

No, llvm13 is in progress, but https://github.com/llir/llvm/issues/205#issuecomment-944248246 has a hidden difference in syntax changes, after updating grammar, you will back and update this difference(@mewmew maybe that should be recorded in llvm13 branch? So anyone can update it, not only me).

You will modify https://github.com/llir/grammar/blob/master/ll.tm to handle those new syntaxes in llir. Generate command is make gen, but I already forget how to get ./tools/textmapper. This is the grammar for the parser generator.

After generating parser by generator, you might need to update https://github.com/llir/llvm/tree/master/ir for Go representation of llir, interface method LLString is the point.

mewmew commented 2 years ago

Is LLVM 13 and LLVM 14 supported now? If not, how can I help?

Hi @suhabe,

Glad to see you take an interest in the project :)

As noticed, @dannypsnl has started work on LLVM 13. For the last few releases of llir/llvm @dannypsnl has been the one doing the majority of the work. I've mostly updated test cases and helped coordinate a bit.

However, work on LLVM 13 and upwards have been put on hold as both @dannypsnl and I are busy in life. Since this is a hobby project, other life priorities take precedence, as they should :)

If you feel like working on integrating LLVM 13/14 support into llir/llvm, then you are most welcome to give it a go!

There is a wealth of comments written on how to update llir/llvm to newer versions. Please take inspiration from the following:

There are four sub-steps:

Feel free to give it a go!

If you struggle with getting Textmapper up and running, just give me a ping and I'll get you up to speed.

Wish you happy coding and a most wonderful summer ahead :)

Cheers, Robin

mewmew commented 2 years ago

No, llvm13 is in progress, but https://github.com/llir/llvm/issues/205#issuecomment-944248246 has a hidden difference in syntax changes, after updating grammar, you will back and update this difference(@mewmew maybe that should be recorded in llvm13 branch? So anyone can update it, not only me).

@dannypsnl, is the llvm13.diff up to date? If so, it's already tracked in the llvm13 branch :) If not, then feel free to update it based on the <details> field of the linked comment https://github.com/llir/llvm/issues/205#issuecomment-944248246.

Cheers, Robin

dannypsnl commented 2 years ago

Oh! Then I think it's up to date

Robin @.***>於 2022年5月1日 週日,下午8:20寫道:

No, llvm13 is in progress, but #205 (comment) https://github.com/llir/llvm/issues/205#issuecomment-944248246 has a hidden difference in syntax changes, after updating grammar, you will back and update this @.*** https://github.com/mewmew maybe that should be recorded in llvm13 branch? So anyone can update it, not only me).

@dannypsnl https://github.com/dannypsnl, is the llvm13.diff https://github.com/llir/llvm/blob/llvm13/llvm13.diff up to date? If so, it's already tracked in the llvm13 branch https://github.com/llir/llvm/tree/llvm13 :) If not, then feel free to update it based on the

field of the linked comment #205 (comment) https://github.com/llir/llvm/issues/205#issuecomment-944248246 .

Cheers, Robin

— Reply to this email directly, view it on GitHub https://github.com/llir/llvm/issues/205#issuecomment-1114221731, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFH4GH56C3CYQOB3G44FIMTVHZZKRANCNFSM5FAD6Q5A . You are receiving this because you were mentioned.Message ID: @.***>

mewmew commented 2 years ago

Is LLVM 13 and LLVM 14 supported now? If not, how can I help?

@suhabe, now LLVM 13.0 is supported; as of llir/llvm version 0.3.5.

Edit: LLVM 14.0 is supported as of llir/llvm version 0.3.6 (see #221).

mewmew commented 2 years ago

@dannypsnl thanks for doing the initial work on the LLVM 13.0 release of llir/llvm! We've now got support for both LLVM 13.0 and LLVM 14.0 in llir/llvm.

Wish you a happy summer!

Cheers, Robin

mewmew commented 2 years ago

@dannypsnl, could you prepare the v0.3.5 (LLVM 13.0) and v0.3.6 (LLVM 14.0) releases so they show up on https://github.com/llir/llvm/releases? (I've not done that before)

Cheers, Robin

dannypsnl commented 2 years ago

Sure~~~

dannypsnl commented 2 years ago

Done!