GithubHelp home page GithubHelp logo

Comments (12)

mewmew avatar mewmew commented on June 13, 2024 2

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).

from llvm.

dannypsnl avatar dannypsnl commented on June 13, 2024 1

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 <string>
-
-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<GlobalVariable>(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<unsigned> NumElemsArg;
+    if (parseAllocSizeArguments(ElemSizeArg, NumElemsArg))
+      return true;
+    B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
+    return false;
+  }
+  case Attribute::VScaleRange: {
+    unsigned MinValue, MaxValue;
+    if (parseVScaleRangeArguments(MinValue, MaxValue))
+      return true;
+    B.addVScaleRangeAttr(MinValue, MaxValue);
+    return false;
+  }
+  case Attribute::Dereferenceable: {
+    uint64_t Bytes;
+    if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes))
+      return true;
+    B.addDereferenceableAttr(Bytes);
+    return false;
+  }
+  case Attribute::DereferenceableOrNull: {
+    uint64_t Bytes;
+    if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable_or_null, Bytes))
+      return true;
+    B.addDereferenceableOrNullAttr(Bytes);
+    return false;
+  }
+  default:
+    B.addAttribute(Attr);
+    Lex.Lex();
+    return false;
+  }
+}
+
 /// parseFnAttributeValuePairs
 ///   ::= <attr> | <attr> '=' <value>
 bool LLParser::parseFnAttributeValuePairs(AttrBuilder &B,
                                           std::vector<unsigned> &FwdRefAttrGrps,
-                                          bool inAttrGrp, LocTy &BuiltinLoc) {
+                                          bool 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<unsigned> 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<FunctionType>(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<FunctionType>(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<PointerType>(Ty)) {
-    Type *TyInProgAS = cast<PointerType>(Ty)->getElementType()->getPointerTo(
-        M->getDataLayout().getProgramAddressSpace());
-    SuggestedTy = TyInProgAS;
-    if (Val->getType() == TyInProgAS)
-      return Val;
-  }
   if (Ty->isLabelTy())
     error(Loc, "'" + Name + "' is not a basic block");
   else
     error(Loc, "'" + Name + "' defined with type '" +
                    getTypeString(Val->getType()) + "' but expected '" +
-                   getTypeString(SuggestedTy) + "'");
+                   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<ParamInfo> &ArgList,
 
 /// parseRequiredTypeAttr
 ///   ::= attrname(<ty>)
-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(<ty>)
-bool LLParser::parsePreallocated(Type *&Result) {
-  return parseRequiredTypeAttr(Result, lltok::kw_preallocated);
-}
-
-/// parseByRef
-///   ::= byref(<type>)
-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<ValID, GlobalValue *>()))
               .first->second.insert(std::make_pair(std::move(Label), nullptr))
               .first->second;
-      if (!FwdRef)
-        FwdRef = new GlobalVariable(*M, Type::getInt8Ty(Context), false,
-                                    GlobalValue::InternalLinkage, nullptr, "");
+      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<PointerType>(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<Constant>(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<ValueAsMetadata *, 4> 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<ValueAsMetadata>(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<Function>(I->second.first);
-      if (Fn->getType() != PFT)
+      FwdFn = cast<Function>(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<PointerType>(Val->getType())->getElementType())
-    return error(ExplicitTypeLoc,
-                 "explicit pointee type doesn't match operand's pointee type");
+  if (!cast<PointerType>(Val->getType())->isOpaqueOrPointeeTypeMatches(Ty)) {
+    return error(
+        ExplicitTypeLoc,
+        typeComparisonErrorMessage(
+            "explicit pointee type doesn't match operand's pointee type", Ty,
+            cast<PointerType>(Val->getType())->getElementType()));
+  }
   SmallPtrSet<Type *, 4> 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<PointerType>(Ptr->getType())->getElementType() != Val->getType())
+  if (!cast<PointerType>(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<PointerType>(Ptr->getType())->getElementType() != Cmp->getType())
+  if (!cast<PointerType>(Ptr->getType())
+           ->isOpaqueOrPointeeTypeMatches(Cmp->getType()))
     return error(CmpLoc, "compare value and pointer type do not match");
-  if (cast<PointerType>(Ptr->getType())->getElementType() != New->getType())
+  if (!cast<PointerType>(Ptr->getType())
+           ->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<PointerType>(Ptr->getType())->getElementType() != Val->getType())
+  if (!cast<PointerType>(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<Value*, 16> Indices;
   bool AteExtraComma = false;
@@ -7832,9 +7667,9 @@ bool LLParser::parseUseListOrderBB() {
 
   ValID Fn, Label;
   SmallVector<unsigned, 16> 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<FunctionSummary::EdgeTy> 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))

from llvm.

dannypsnl avatar dannypsnl commented on June 13, 2024 1

Sure~~~

from llvm.

dannypsnl avatar dannypsnl commented on June 13, 2024 1

Done!

from llvm.

mewmew avatar mewmew commented on June 13, 2024

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

from llvm.

suhabe avatar suhabe commented on June 13, 2024

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

from llvm.

dannypsnl avatar dannypsnl commented on June 13, 2024

No, llvm13 is in progress, but #205 (comment) 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.

from llvm.

mewmew avatar mewmew commented on June 13, 2024

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:

  • meta issue detailing how to update llir/llvm to a new LLVM release version: see #128

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

from llvm.

mewmew avatar mewmew commented on June 13, 2024

No, llvm13 is in progress, but #205 (comment) 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 #205 (comment).

Cheers,
Robin

from llvm.

dannypsnl avatar dannypsnl commented on June 13, 2024

from llvm.

mewmew avatar mewmew commented on June 13, 2024

@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

from llvm.

mewmew avatar mewmew commented on June 13, 2024

@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

from llvm.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.