Importing rustc-1.56.0

Change-Id: I98941481270706fa55f8fb2cb91686ae3bd30f38
diff --git a/src/llvm-project/llvm/tools/bugpoint/CrashDebugger.cpp b/src/llvm-project/llvm/tools/bugpoint/CrashDebugger.cpp
index d06bca9..2601ee3 100644
--- a/src/llvm-project/llvm/tools/bugpoint/CrashDebugger.cpp
+++ b/src/llvm-project/llvm/tools/bugpoint/CrashDebugger.cpp
@@ -425,7 +425,7 @@
 }
 /// ReduceCrashingBlocks reducer - This works by setting the terminators of
 /// all terminators except the specified basic blocks to a 'ret' instruction,
-/// then running the simplify-cfg pass.  This has the effect of chopping up
+/// then running the simplifycfg pass.  This has the effect of chopping up
 /// the CFG really fast which can reduce large functions quickly.
 ///
 class ReduceCrashingBlocks : public ListReducer<const BasicBlock *> {
diff --git a/src/llvm-project/llvm/tools/bugpoint/FindBugs.cpp b/src/llvm-project/llvm/tools/bugpoint/FindBugs.cpp
index 2b1146d..7713290 100644
--- a/src/llvm-project/llvm/tools/bugpoint/FindBugs.cpp
+++ b/src/llvm-project/llvm/tools/bugpoint/FindBugs.cpp
@@ -41,7 +41,7 @@
     //
     // Step 1: Randomize the order of the optimizer passes.
     //
-    std::shuffle(PassesToRun.begin(), PassesToRun.end(), randomness);
+    llvm::shuffle(PassesToRun.begin(), PassesToRun.end(), randomness);
 
     //
     // Step 2: Run optimizer passes on the program and check for success.
diff --git a/src/llvm-project/llvm/tools/bugpoint/ListReducer.h b/src/llvm-project/llvm/tools/bugpoint/ListReducer.h
index 04f2207..06f8ddb 100644
--- a/src/llvm-project/llvm/tools/bugpoint/ListReducer.h
+++ b/src/llvm-project/llvm/tools/bugpoint/ListReducer.h
@@ -92,7 +92,7 @@
       // distribution (improving the speed of convergence).
       if (ShufflingEnabled && NumOfIterationsWithoutProgress > MaxIterations) {
         std::vector<ElTy> ShuffledList(TheList);
-        std::shuffle(ShuffledList.begin(), ShuffledList.end(), randomness);
+        llvm::shuffle(ShuffledList.begin(), ShuffledList.end(), randomness);
         errs() << "\n\n*** Testing shuffled set...\n\n";
         // Check that random shuffle doesn't lose the bug
         Expected<TestResult> Result = doTest(ShuffledList, empty);
diff --git a/src/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp b/src/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp
index c4ea1da..b81ab07 100644
--- a/src/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp
+++ b/src/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp
@@ -607,12 +607,12 @@
 
 static bool IsARMArchitecture(std::vector<StringRef> Args) {
   for (size_t I = 0; I < Args.size(); ++I) {
-    if (!Args[I].equals_lower("-arch"))
+    if (!Args[I].equals_insensitive("-arch"))
       continue;
     ++I;
     if (I == Args.size())
       break;
-    if (Args[I].startswith_lower("arm"))
+    if (Args[I].startswith_insensitive("arm"))
       return true;
   }
 
diff --git a/src/llvm-project/llvm/tools/dsymutil/DebugMap.h b/src/llvm-project/llvm/tools/dsymutil/DebugMap.h
index ee552ed..e4fbaa8 100644
--- a/src/llvm-project/llvm/tools/dsymutil/DebugMap.h
+++ b/src/llvm-project/llvm/tools/dsymutil/DebugMap.h
@@ -114,9 +114,7 @@
 
   const Triple &getTriple() const { return BinaryTriple; }
 
-  const ArrayRef<uint8_t> getUUID() const {
-    return ArrayRef<uint8_t>(BinaryUUID);
-  }
+  ArrayRef<uint8_t> getUUID() const { return ArrayRef<uint8_t>(BinaryUUID); }
 
   StringRef getBinaryPath() const { return BinaryPath; }
 
diff --git a/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
index 29408e7..ca14548 100644
--- a/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -167,7 +167,7 @@
     return true;
 
   Streamer = std::make_unique<DwarfStreamer>(
-      Options.FileType, OutFile, Options.Translator, Options.Minimize,
+      Options.FileType, OutFile, Options.Translator,
       [&](const Twine &Error, StringRef Context, const DWARFDie *) {
         error(Error, Context);
       },
@@ -252,7 +252,10 @@
   }
 
   std::error_code EC;
-  raw_fd_ostream OS(Options.NoOutput ? "-" : Path.str(), EC, sys::fs::OF_None);
+  raw_fd_ostream OS(Options.NoOutput ? "-" : Path.str(), EC,
+                    Options.RemarksFormat == remarks::Format::Bitstream
+                        ? sys::fs::OF_None
+                        : sys::fs::OF_Text);
   if (EC)
     return errorCodeToError(EC);
 
@@ -322,6 +325,7 @@
   GeneralLinker.setNumThreads(Options.Threads);
   GeneralLinker.setAccelTableKind(Options.TheAccelTableKind);
   GeneralLinker.setPrependPath(Options.PrependPath);
+  GeneralLinker.setKeepFunctionForStatic(Options.KeepFunctionForStatic);
   if (Options.Translator)
     GeneralLinker.setStringsTranslator(TranslationLambda);
   GeneralLinker.setWarningHandler(
@@ -611,49 +615,56 @@
   return FoundValidRelocs;
 }
 
-bool DwarfLinkerForBinary::AddressManager::hasValidDebugAddrRelocationAt(
-    uint64_t Offset) {
-  auto It = std::lower_bound(ValidDebugAddrRelocs.begin(),
-                             ValidDebugAddrRelocs.end(), Offset);
-  return It != ValidDebugAddrRelocs.end();
+std::vector<DwarfLinkerForBinary::AddressManager::ValidReloc>
+DwarfLinkerForBinary::AddressManager::getRelocations(
+    const std::vector<ValidReloc> &Relocs, uint64_t StartPos, uint64_t EndPos) {
+  std::vector<DwarfLinkerForBinary::AddressManager::ValidReloc> Res;
+
+  auto CurReloc = partition_point(Relocs, [StartPos](const ValidReloc &Reloc) {
+    return Reloc.Offset < StartPos;
+  });
+
+  while (CurReloc != Relocs.end() && CurReloc->Offset >= StartPos &&
+         CurReloc->Offset < EndPos) {
+    Res.push_back(*CurReloc);
+    CurReloc++;
+  }
+
+  return Res;
 }
 
-bool DwarfLinkerForBinary::AddressManager::hasValidDebugInfoRelocationAt(
-    uint64_t StartOffset, uint64_t EndOffset, CompileUnit::DIEInfo &Info) {
-  assert(NextValidReloc == 0 ||
-         StartOffset > ValidDebugInfoRelocs[NextValidReloc - 1].Offset);
-  if (NextValidReloc >= ValidDebugInfoRelocs.size())
-    return false;
-
-  uint64_t RelocOffset = ValidDebugInfoRelocs[NextValidReloc].Offset;
-
-  // We might need to skip some relocs that we didn't consider. For
-  // example the high_pc of a discarded DIE might contain a reloc that
-  // is in the list because it actually corresponds to the start of a
-  // function that is in the debug map.
-  while (RelocOffset < StartOffset &&
-         NextValidReloc < ValidDebugInfoRelocs.size() - 1)
-    RelocOffset = ValidDebugInfoRelocs[++NextValidReloc].Offset;
-
-  if (RelocOffset < StartOffset || RelocOffset >= EndOffset)
-    return false;
-
-  const auto &ValidReloc = ValidDebugInfoRelocs[NextValidReloc++];
-  const auto &Mapping = ValidReloc.Mapping->getValue();
-  const uint64_t BinaryAddress = Mapping.BinaryAddress;
+void DwarfLinkerForBinary::AddressManager::printReloc(const ValidReloc &Reloc) {
+  const auto &Mapping = Reloc.Mapping->getValue();
   const uint64_t ObjectAddress = Mapping.ObjectAddress
                                      ? uint64_t(*Mapping.ObjectAddress)
                                      : std::numeric_limits<uint64_t>::max();
-  if (Linker.Options.Verbose)
-    outs() << "Found valid debug map entry: " << ValidReloc.Mapping->getKey()
-           << "\t"
-           << format("0x%016" PRIx64 " => 0x%016" PRIx64 "\n", ObjectAddress,
-                     BinaryAddress);
 
-  Info.AddrAdjust = BinaryAddress + ValidReloc.Addend;
-  if (Mapping.ObjectAddress)
-    Info.AddrAdjust -= ObjectAddress;
+  outs() << "Found valid debug map entry: " << Reloc.Mapping->getKey() << "\t"
+         << format("0x%016" PRIx64 " => 0x%016" PRIx64 "\n", ObjectAddress,
+                   uint64_t(Mapping.BinaryAddress));
+}
+
+void DwarfLinkerForBinary::AddressManager::fillDieInfo(
+    const ValidReloc &Reloc, CompileUnit::DIEInfo &Info) {
+  Info.AddrAdjust = relocate(Reloc);
+  if (Reloc.Mapping->getValue().ObjectAddress)
+    Info.AddrAdjust -= uint64_t(*Reloc.Mapping->getValue().ObjectAddress);
   Info.InDebugMap = true;
+}
+
+bool DwarfLinkerForBinary::AddressManager::hasValidRelocationAt(
+    const std::vector<ValidReloc> &AllRelocs, uint64_t StartOffset,
+    uint64_t EndOffset, CompileUnit::DIEInfo &Info) {
+  std::vector<ValidReloc> Relocs =
+      getRelocations(AllRelocs, StartOffset, EndOffset);
+
+  if (Relocs.size() == 0)
+    return false;
+
+  if (Linker.Options.Verbose)
+    printReloc(Relocs[0]);
+  fillDieInfo(Relocs[0], Info);
+
   return true;
 }
 
@@ -693,8 +704,8 @@
       getAttributeOffsets(Abbrev, *LocationIdx, Offset, *DIE.getDwarfUnit());
 
   // FIXME: Support relocations debug_addr.
-  return hasValidDebugInfoRelocationAt(LocationOffset, LocationEndOffset,
-                                       MyInfo);
+  return hasValidRelocationAt(ValidDebugInfoRelocs, LocationOffset,
+                              LocationEndOffset, MyInfo);
 }
 
 bool DwarfLinkerForBinary::AddressManager::hasLiveAddressRange(
@@ -712,16 +723,31 @@
     uint64_t LowPcOffset, LowPcEndOffset;
     std::tie(LowPcOffset, LowPcEndOffset) =
         getAttributeOffsets(Abbrev, *LowPcIdx, Offset, *DIE.getDwarfUnit());
-    return hasValidDebugInfoRelocationAt(LowPcOffset, LowPcEndOffset, MyInfo);
+    return hasValidRelocationAt(ValidDebugInfoRelocs, LowPcOffset,
+                                LowPcEndOffset, MyInfo);
   }
 
   if (Form == dwarf::DW_FORM_addrx) {
     Optional<DWARFFormValue> AddrValue = DIE.find(dwarf::DW_AT_low_pc);
-    return hasValidDebugAddrRelocationAt(*AddrValue->getAsAddress());
+    if (Optional<uint64_t> AddrOffsetSectionBase =
+            DIE.getDwarfUnit()->getAddrOffsetSectionBase()) {
+      uint64_t StartOffset = *AddrOffsetSectionBase + AddrValue->getRawUValue();
+      uint64_t EndOffset =
+          StartOffset + DIE.getDwarfUnit()->getAddressByteSize();
+      return hasValidRelocationAt(ValidDebugAddrRelocs, StartOffset, EndOffset,
+                                  MyInfo);
+    } else
+      Linker.reportWarning("no base offset for address table", SrcFileName);
   }
 
   return false;
 }
+
+uint64_t
+DwarfLinkerForBinary::AddressManager::relocate(const ValidReloc &Reloc) const {
+  return Reloc.Mapping->getValue().BinaryAddress + Reloc.Addend;
+}
+
 /// Apply the valid relocations found by findValidRelocs() to
 /// the buffer \p Data, taking into account that Data is at \p BaseOffset
 /// in the debug_info section.
@@ -733,49 +759,36 @@
 bool DwarfLinkerForBinary::AddressManager::applyValidRelocs(
     MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) {
   assert(areRelocationsResolved());
-  assert((NextValidReloc == 0 ||
-          BaseOffset > ValidDebugInfoRelocs[NextValidReloc - 1].Offset) &&
-         "BaseOffset should only be increasing.");
-  if (NextValidReloc >= ValidDebugInfoRelocs.size())
-    return false;
+  std::vector<ValidReloc> Relocs = getRelocations(
+      ValidDebugInfoRelocs, BaseOffset, BaseOffset + Data.size());
 
-  // Skip relocs that haven't been applied.
-  while (NextValidReloc < ValidDebugInfoRelocs.size() &&
-         ValidDebugInfoRelocs[NextValidReloc].Offset < BaseOffset)
-    ++NextValidReloc;
-
-  bool Applied = false;
-  uint64_t EndOffset = BaseOffset + Data.size();
-  while (NextValidReloc < ValidDebugInfoRelocs.size() &&
-         ValidDebugInfoRelocs[NextValidReloc].Offset >= BaseOffset &&
-         ValidDebugInfoRelocs[NextValidReloc].Offset < EndOffset) {
-    const auto &ValidReloc = ValidDebugInfoRelocs[NextValidReloc++];
-    assert(ValidReloc.Offset - BaseOffset < Data.size());
-    assert(ValidReloc.Offset - BaseOffset + ValidReloc.Size <= Data.size());
+  for (const ValidReloc &CurReloc : Relocs) {
+    assert(CurReloc.Offset - BaseOffset < Data.size());
+    assert(CurReloc.Offset - BaseOffset + CurReloc.Size <= Data.size());
     char Buf[8];
-    uint64_t Value = ValidReloc.Mapping->getValue().BinaryAddress;
-    Value += ValidReloc.Addend;
-    for (unsigned I = 0; I != ValidReloc.Size; ++I) {
-      unsigned Index = IsLittleEndian ? I : (ValidReloc.Size - I - 1);
+    uint64_t Value = relocate(CurReloc);
+    for (unsigned I = 0; I != CurReloc.Size; ++I) {
+      unsigned Index = IsLittleEndian ? I : (CurReloc.Size - I - 1);
       Buf[I] = uint8_t(Value >> (Index * 8));
     }
-    assert(ValidReloc.Size <= sizeof(Buf));
-    memcpy(&Data[ValidReloc.Offset - BaseOffset], Buf, ValidReloc.Size);
-    Applied = true;
+    assert(CurReloc.Size <= sizeof(Buf));
+    memcpy(&Data[CurReloc.Offset - BaseOffset], Buf, CurReloc.Size);
   }
 
-  return Applied;
+  return Relocs.size() > 0;
 }
 
 llvm::Expected<uint64_t>
-DwarfLinkerForBinary::AddressManager::relocateIndexedAddr(uint64_t Offset) {
-  auto It = std::lower_bound(ValidDebugAddrRelocs.begin(),
-                             ValidDebugAddrRelocs.end(), Offset);
-  if (It == ValidDebugAddrRelocs.end())
+DwarfLinkerForBinary::AddressManager::relocateIndexedAddr(uint64_t StartOffset,
+                                                          uint64_t EndOffset) {
+  std::vector<ValidReloc> Relocs =
+      getRelocations(ValidDebugAddrRelocs, StartOffset, EndOffset);
+  if (Relocs.size() == 0)
     return createStringError(
         std::make_error_code(std::errc::invalid_argument),
-        "no relocation for offset %llu in debug_addr section", Offset);
-  return It->Mapping->getValue().BinaryAddress + It->Addend;
+        "no relocation for offset %llu in debug_addr section", StartOffset);
+
+  return relocate(Relocs[0]);
 }
 
 bool linkDwarf(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
diff --git a/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.h b/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.h
index c6c07d6..dc4691b 100644
--- a/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.h
+++ b/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.h
@@ -82,18 +82,33 @@
     std::vector<ValidReloc> ValidDebugAddrRelocs;
     /// }
 
-    /// Index into ValidRelocs of the next relocation to consider. As we walk
-    /// the DIEs in acsending file offset and as ValidRelocs is sorted by file
-    /// offset, keeping this index up to date is all we have to do to have a
-    /// cheap lookup during the root DIE selection and during DIE cloning.
-    unsigned NextValidReloc = 0;
-
     RangesTy AddressRanges;
 
+    StringRef SrcFileName;
+
+    /// Returns list of valid relocations from \p Relocs,
+    /// between \p StartOffset and \p NextOffset.
+    ///
+    /// \returns true if any relocation is found.
+    std::vector<ValidReloc>
+    getRelocations(const std::vector<ValidReloc> &Relocs, uint64_t StartPos,
+                   uint64_t EndPos);
+
+    /// Resolve specified relocation \p Reloc.
+    ///
+    /// \returns resolved value.
+    uint64_t relocate(const ValidReloc &Reloc) const;
+
+    /// Fill \p Info with address information for the specified \p Reloc.
+    void fillDieInfo(const ValidReloc &Reloc, CompileUnit::DIEInfo &Info);
+
+    /// Print contents of debug map entry for the specified \p Reloc.
+    void printReloc(const ValidReloc &Reloc);
+
   public:
     AddressManager(DwarfLinkerForBinary &Linker, const object::ObjectFile &Obj,
                    const DebugMapObject &DMO)
-        : Linker(Linker) {
+        : Linker(Linker), SrcFileName(DMO.getObjectFilename()) {
       findValidRelocsInDebugSections(Obj, DMO);
 
       // Iterate over the debug map entries and put all the ones that are
@@ -125,9 +140,7 @@
 
     virtual bool areRelocationsResolved() const override { return true; }
 
-    bool hasValidRelocs(bool ResetRelocsPtr = true) override {
-      if (ResetRelocsPtr)
-        NextValidReloc = 0;
+    bool hasValidRelocs() override {
       return !ValidDebugInfoRelocs.empty() || !ValidDebugAddrRelocs.empty();
     }
 
@@ -149,18 +162,13 @@
                               std::vector<ValidReloc> &ValidRelocs);
     /// @}
 
-    /// Checks that there is a relocation in the debug_addr section  against a
+    /// Checks that there is a relocation in the \p Relocs array against a
     /// debug map entry between \p StartOffset and \p NextOffset.
     ///
-    /// This function must be called with offsets in strictly ascending order
-    /// because it never looks back at relocations it already 'went past'.
     /// \returns true and sets Info.InDebugMap if it is the case.
-    bool hasValidDebugInfoRelocationAt(uint64_t StartOffset, uint64_t EndOffset,
-                                       CompileUnit::DIEInfo &Info);
-
-    /// Checks that there is a relocation in the debug_addr section against a
-    /// debug map entry at the given offset.
-    bool hasValidDebugAddrRelocationAt(uint64_t Offset);
+    bool hasValidRelocationAt(const std::vector<ValidReloc> &Relocs,
+                              uint64_t StartOffset, uint64_t EndOffset,
+                              CompileUnit::DIEInfo &Info);
 
     bool hasLiveMemoryLocation(const DWARFDie &DIE,
                                CompileUnit::DIEInfo &Info) override;
@@ -170,7 +178,8 @@
     bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
                           bool IsLittleEndian) override;
 
-    llvm::Expected<uint64_t> relocateIndexedAddr(uint64_t Offset) override;
+    llvm::Expected<uint64_t> relocateIndexedAddr(uint64_t StartOffset,
+                                                 uint64_t EndOffset) override;
 
     RangesTy &getValidAddressRanges() override { return AddressRanges; }
 
@@ -178,7 +187,6 @@
       AddressRanges.clear();
       ValidDebugInfoRelocs.clear();
       ValidDebugAddrRelocs.clear();
-      NextValidReloc = 0;
     }
   };
 
diff --git a/src/llvm-project/llvm/tools/dsymutil/LinkUtils.h b/src/llvm-project/llvm/tools/dsymutil/LinkUtils.h
index 52b3635..872a65d 100644
--- a/src/llvm-project/llvm/tools/dsymutil/LinkUtils.h
+++ b/src/llvm-project/llvm/tools/dsymutil/LinkUtils.h
@@ -39,12 +39,13 @@
   /// Update
   bool Update = false;
 
-  /// Minimize
-  bool Minimize = false;
-
   /// Do not check swiftmodule timestamp
   bool NoTimestamp = false;
 
+  /// Whether we want a static variable to force us to keep its enclosing
+  /// function.
+  bool KeepFunctionForStatic = false;
+
   /// Number of threads.
   unsigned Threads = 1;
 
diff --git a/src/llvm-project/llvm/tools/dsymutil/MachODebugMapParser.cpp b/src/llvm-project/llvm/tools/dsymutil/MachODebugMapParser.cpp
index fccf2f5..ba2f9a1 100644
--- a/src/llvm-project/llvm/tools/dsymutil/MachODebugMapParser.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/MachODebugMapParser.cpp
@@ -462,6 +462,19 @@
     }
   }
 
+  // ThinLTO adds a unique suffix to exported private symbols.
+  if (ObjectSymIt == CurrentObjectAddresses.end()) {
+    for (auto Iter = CurrentObjectAddresses.begin();
+         Iter != CurrentObjectAddresses.end(); ++Iter) {
+      llvm::StringRef SymbolName = Iter->getKey();
+      auto Pos = SymbolName.rfind(".llvm.");
+      if (Pos != llvm::StringRef::npos && SymbolName.substr(0, Pos) == Name) {
+        ObjectSymIt = Iter;
+        break;
+      }
+    }
+  }
+
   if (ObjectSymIt == CurrentObjectAddresses.end()) {
     Warning("could not find object file symbol for symbol " + Twine(Name));
     return;
diff --git a/src/llvm-project/llvm/tools/dsymutil/Options.td b/src/llvm-project/llvm/tools/dsymutil/Options.td
index 7bd21b0..67eac56 100644
--- a/src/llvm-project/llvm/tools/dsymutil/Options.td
+++ b/src/llvm-project/llvm/tools/dsymutil/Options.td
@@ -24,6 +24,10 @@
   HelpText<"Enable verbose mode.">,
   Group<grp_general>;
 
+def keep_func_for_static: F<"keep-function-for-static">,
+  HelpText<"Make a static variable keep the enclosing function even if it would have been omitted otherwise.">,
+  Group<grp_general>;
+
 def statistics: F<"statistics">,
   HelpText<"Print statistics about the contribution of each object file to "
            "the linked debug info. This prints a table after linking with the "
@@ -81,19 +85,6 @@
   HelpText<"Alias for --flat">,
   Group<grp_general>;
 
-def minimize: F<"minimize">,
-  HelpText<"When used when creating a dSYM file with Apple accelerator tables, "
-           "this option will suppress the emission of the .debug_inlines, "
-           ".debug_pubnames, and .debug_pubtypes sections since dsymutil "
-           "has better equivalents: .apple_names and .apple_types. When used in "
-           "conjunction with --update option, this option will cause redundant "
-           "accelerator tables to be removed.">,
-  Group<grp_general>;
-def: Flag<["-"], "z">,
-  Alias<minimize>,
-  HelpText<"Alias for --minimize">,
-  Group<grp_general>;
-
 def update: F<"update">,
   HelpText<"Updates existing dSYM files to contain the latest accelerator tables and other DWARF optimizations.">,
   Group<grp_general>;
@@ -146,7 +137,7 @@
 
 def accelerator: Separate<["--", "-"], "accelerator">,
   MetaVarName<"<accelerator type>">,
-  HelpText<"Specify the desired type of accelerator table. Valid options are 'Apple', 'Dwarf' and 'Default'">,
+  HelpText<"Specify the desired type of accelerator table. Valid options are 'Apple' (.apple_names, .apple_namespaces, .apple_types, .apple_objc), 'Dwarf' (.debug_names), 'Pub' (.debug_pubnames, .debug_pubtypes) and 'Default'">,
   Group<grp_general>;
 def: Joined<["--", "-"], "accelerator=">, Alias<accelerator>;
 
diff --git a/src/llvm-project/llvm/tools/dsymutil/dsymutil.cpp b/src/llvm-project/llvm/tools/dsymutil/dsymutil.cpp
index 347b2dd..2a8e317 100644
--- a/src/llvm-project/llvm/tools/dsymutil/dsymutil.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/dsymutil.cpp
@@ -91,6 +91,7 @@
   bool InputIsYAMLDebugMap = false;
   bool PaperTrailWarnings = false;
   bool Verify = false;
+  bool ForceKeepFunctionForStatic = false;
   std::string SymbolMap;
   std::string OutputFile;
   std::string Toolchain;
@@ -200,11 +201,13 @@
       return AccelTableKind::Apple;
     if (S == "Dwarf")
       return AccelTableKind::Dwarf;
+    if (S == "Pub")
+      return AccelTableKind::Pub;
     if (S == "Default")
       return AccelTableKind::Default;
     return make_error<StringError>(
         "invalid accelerator type specified: '" + S +
-            "'. Support values are 'Apple', 'Dwarf' and 'Default'.",
+            "'. Support values are 'Apple', 'Dwarf', 'Pub' and 'Default'.",
         inconvertibleErrorCode());
   }
   return AccelTableKind::Default;
@@ -222,13 +225,14 @@
   Options.PaperTrailWarnings = Args.hasArg(OPT_papertrail);
   Options.Verify = Args.hasArg(OPT_verify);
 
-  Options.LinkOpts.Minimize = Args.hasArg(OPT_minimize);
   Options.LinkOpts.NoODR = Args.hasArg(OPT_no_odr);
   Options.LinkOpts.NoOutput = Args.hasArg(OPT_no_output);
   Options.LinkOpts.NoTimestamp = Args.hasArg(OPT_no_swiftmodule_timestamp);
   Options.LinkOpts.Update = Args.hasArg(OPT_update);
   Options.LinkOpts.Verbose = Args.hasArg(OPT_verbose);
   Options.LinkOpts.Statistics = Args.hasArg(OPT_statistics);
+  Options.LinkOpts.KeepFunctionForStatic =
+      Args.hasArg(OPT_keep_func_for_static);
 
   if (opt::Arg *ReproducerPath = Args.getLastArg(OPT_use_reproducer)) {
     Options.ReproMode = ReproducerMode::Use;
@@ -312,7 +316,7 @@
   SmallString<128> InfoPlist(BundleRoot);
   sys::path::append(InfoPlist, "Contents/Info.plist");
   std::error_code EC;
-  raw_fd_ostream PL(InfoPlist, EC, sys::fs::OF_Text);
+  raw_fd_ostream PL(InfoPlist, EC, sys::fs::OF_TextWithCRLF);
   if (EC)
     return make_error<StringError>(
         "cannot create Plist: " + toString(errorCodeToError(EC)), EC);
@@ -432,6 +436,11 @@
       (Options.LinkOpts.Update || !Options.SymbolMap.empty()))
     return OutputLocation(std::string(InputFile));
 
+  // When dumping the debug map, just return an empty output location. This
+  // allows us to compute the output location once.
+  if (Options.DumpDebugMap)
+    return OutputLocation("");
+
   // If a flat dSYM has been requested, things are pretty simple.
   if (Options.Flat) {
     if (Options.OutputFile.empty()) {
@@ -489,25 +498,25 @@
   }
 
   if (Args.hasArg(OPT_help)) {
-    T.PrintHelp(
+    T.printHelp(
         outs(), (std::string(argv[0]) + " [options] <input files>").c_str(),
         "manipulate archived DWARF debug symbol files.\n\n"
         "dsymutil links the DWARF debug information found in the object files\n"
         "for the executable <input file> by using debug symbols information\n"
         "contained in its symbol table.\n",
         false);
-    return 0;
+    return EXIT_SUCCESS;
   }
 
   if (Args.hasArg(OPT_version)) {
     cl::PrintVersionMessage();
-    return 0;
+    return EXIT_SUCCESS;
   }
 
   auto OptionsOrErr = getOptions(Args);
   if (!OptionsOrErr) {
     WithColor::error() << toString(OptionsOrErr.takeError());
-    return 1;
+    return EXIT_FAILURE;
   }
 
   auto &Options = *OptionsOrErr;
@@ -521,7 +530,7 @@
       Reproducer::createReproducer(Options.ReproMode, Options.ReproducerPath);
   if (!Repro) {
     WithColor::error() << toString(Repro.takeError());
-    return 1;
+    return EXIT_FAILURE;
   }
 
   Options.LinkOpts.VFS = (*Repro)->getVFS();
@@ -530,7 +539,7 @@
     if (Arch != "*" && Arch != "all" &&
         !object::MachOObjectFile::isValidArch(Arch)) {
       WithColor::error() << "unsupported cpu architecture: '" << Arch << "'\n";
-      return 1;
+      return EXIT_FAILURE;
     }
 
   SymbolMapLoader SymMapLoader(Options.SymbolMap);
@@ -540,7 +549,7 @@
     if (Options.DumpStab) {
       if (!dumpStab(Options.LinkOpts.VFS, InputFile, Options.Archs,
                     Options.LinkOpts.PrependPath))
-        return 1;
+        return EXIT_FAILURE;
       continue;
     }
 
@@ -552,7 +561,7 @@
     if (auto EC = DebugMapPtrsOrErr.getError()) {
       WithColor::error() << "cannot parse the debug map for '" << InputFile
                          << "': " << EC.message() << '\n';
-      return 1;
+      return EXIT_FAILURE;
     }
 
     // Remember the number of debug maps that are being processed to decide how
@@ -570,12 +579,21 @@
     // Ensure that the debug map is not empty (anymore).
     if (DebugMapPtrsOrErr->empty()) {
       WithColor::error() << "no architecture to link\n";
-      return 1;
+      return EXIT_FAILURE;
     }
 
     // Shared a single binary holder for all the link steps.
     BinaryHolder BinHolder(Options.LinkOpts.VFS);
 
+    // Compute the output location and update the resource directory.
+    Expected<OutputLocation> OutputLocationOrErr =
+        getOutputFileName(InputFile, Options);
+    if (!OutputLocationOrErr) {
+      WithColor::error() << toString(OutputLocationOrErr.takeError());
+      return EXIT_FAILURE;
+    }
+    Options.LinkOpts.ResourceDir = OutputLocationOrErr->getResourceDir();
+
     // Statistics only require different architectures to be processed
     // sequentially, the link itself can still happen in parallel. Change the
     // thread pool strategy here instead of modifying LinkOpts.Threads.
@@ -617,14 +635,6 @@
       // types don't work with std::bind in the ThreadPool implementation.
       std::shared_ptr<raw_fd_ostream> OS;
 
-      Expected<OutputLocation> OutputLocationOrErr =
-          getOutputFileName(InputFile, Options);
-      if (!OutputLocationOrErr) {
-        WithColor::error() << toString(OutputLocationOrErr.takeError());
-        return 1;
-      }
-      Options.LinkOpts.ResourceDir = OutputLocationOrErr->getResourceDir();
-
       std::string OutputFile = OutputLocationOrErr->DWARFFile;
       if (NeedsTempFiles) {
         TempFiles.emplace_back(Map->getTriple().getArchName().str());
@@ -632,7 +642,7 @@
         auto E = TempFiles.back().createTempFile();
         if (E) {
           WithColor::error() << toString(std::move(E));
-          return 1;
+          return EXIT_FAILURE;
         }
 
         auto &TempFile = *(TempFiles.back().File);
@@ -645,7 +655,7 @@
             Options.LinkOpts.NoOutput ? "-" : OutputFile, EC, sys::fs::OF_None);
         if (EC) {
           WithColor::error() << OutputFile << ": " << EC.message();
-          return 1;
+          return EXIT_FAILURE;
         }
       }
 
@@ -671,21 +681,28 @@
     Threads.wait();
 
     if (!AllOK)
-      return 1;
+      return EXIT_FAILURE;
 
     if (NeedsTempFiles) {
-      Expected<OutputLocation> OutputLocationOrErr =
-          getOutputFileName(InputFile, Options);
-      if (!OutputLocationOrErr) {
-        WithColor::error() << toString(OutputLocationOrErr.takeError());
-        return 1;
-      }
       if (!MachOUtils::generateUniversalBinary(TempFiles,
                                                OutputLocationOrErr->DWARFFile,
                                                Options.LinkOpts, SDKPath))
-        return 1;
+        return EXIT_FAILURE;
+    }
+
+    // The Mach-O object file format is limited to 4GB. Make sure that we print
+    // an error when we emit an invalid Mach-O companion file. Leave the
+    // invalid object file around on disk for inspection.
+    ErrorOr<vfs::Status> stat =
+        Options.LinkOpts.VFS->status(OutputLocationOrErr->DWARFFile);
+    if (stat) {
+      if (stat->getSize() > std::numeric_limits<uint32_t>::max()) {
+        WithColor::error() << "the linked debug info exceeds the 4GB Mach-O "
+                              "object file format.";
+        return EXIT_FAILURE;
+      }
     }
   }
 
-  return 0;
+  return EXIT_SUCCESS;
 }
diff --git a/src/llvm-project/llvm/tools/gold/gold-plugin.cpp b/src/llvm-project/llvm/tools/gold/gold-plugin.cpp
index 94a26bb..6bcb1e4 100644
--- a/src/llvm-project/llvm/tools/gold/gold-plugin.cpp
+++ b/src/llvm-project/llvm/tools/gold/gold-plugin.cpp
@@ -623,8 +623,10 @@
     sym.comdat_key = nullptr;
     int CI = Sym.getComdatIndex();
     if (CI != -1) {
-      StringRef C = Obj->getComdatTable()[CI];
-      sym.comdat_key = strdup(C.str().c_str());
+      // Not setting comdat_key for nodeduplicate ensuress we don't deduplicate.
+      std::pair<StringRef, Comdat::SelectionKind> C = Obj->getComdatTable()[CI];
+      if (C.second != Comdat::NoDeduplicate)
+        sym.comdat_key = strdup(C.first.str().c_str());
     }
 
     sym.resolution = LDPR_UNKNOWN;
@@ -748,12 +750,15 @@
 
     case LDPR_RESOLVED_IR:
     case LDPR_RESOLVED_EXEC:
-    case LDPR_RESOLVED_DYN:
     case LDPR_PREEMPTED_IR:
     case LDPR_PREEMPTED_REG:
     case LDPR_UNDEF:
       break;
 
+    case LDPR_RESOLVED_DYN:
+      R.ExportDynamic = true;
+      break;
+
     case LDPR_PREVAILING_DEF_IRONLY:
       R.Prevailing = !isUndefined(Sym);
       break;
@@ -765,6 +770,9 @@
 
     case LDPR_PREVAILING_DEF_IRONLY_EXP:
       R.Prevailing = !isUndefined(Sym);
+      // Identify symbols exported dynamically, and that therefore could be
+      // referenced by a shared library not visible to the linker.
+      R.ExportDynamic = true;
       if (!Res.CanOmitFromDynSym)
         R.VisibleToRegularObj = true;
       break;
@@ -912,7 +920,10 @@
   case options::OT_BC_ONLY:
     Conf.PostInternalizeModuleHook = [](size_t Task, const Module &M) {
       std::error_code EC;
-      raw_fd_ostream OS(output_name, EC, sys::fs::OpenFlags::OF_None);
+      SmallString<128> TaskFilename;
+      getOutputFileName(output_name, /* TempOutFile */ false, TaskFilename,
+                        Task);
+      raw_fd_ostream OS(TaskFilename, EC, sys::fs::OpenFlags::OF_None);
       if (EC)
         message(LDPL_FATAL, "Failed to write the output file.");
       WriteBitcodeToFile(M, OS, /* ShouldPreserveUseListOrder */ false);
diff --git a/src/llvm-project/llvm/tools/llc/llc.cpp b/src/llvm-project/llvm/tools/llc/llc.cpp
index 48f0adf..6a1e2ba 100644
--- a/src/llvm-project/llvm/tools/llc/llc.cpp
+++ b/src/llvm-project/llvm/tools/llc/llc.cpp
@@ -126,9 +126,10 @@
 static cl::opt<bool> ShowMCEncoding("show-mc-encoding", cl::Hidden,
                                     cl::desc("Show encoding in .s output"));
 
-static cl::opt<bool> EnableDwarfDirectory(
-    "enable-dwarf-directory", cl::Hidden,
-    cl::desc("Use .file directives with an explicit directory."));
+static cl::opt<bool>
+    DwarfDirectory("dwarf-directory", cl::Hidden,
+                   cl::desc("Use .file directives with an explicit directory"),
+                   cl::init(true));
 
 static cl::opt<bool> AsmVerbose("asm-verbose",
                                 cl::desc("Add comments to directives."),
@@ -276,7 +277,7 @@
   std::error_code EC;
   sys::fs::OpenFlags OpenFlags = sys::fs::OF_None;
   if (!Binary)
-    OpenFlags |= sys::fs::OF_Text;
+    OpenFlags |= sys::fs::OF_TextWithCRLF;
   auto FDOut = std::make_unique<ToolOutputFile>(OutputFilename, EC, OpenFlags);
   if (EC) {
     reportError(EC.message());
@@ -290,6 +291,22 @@
   bool *HasError;
   LLCDiagnosticHandler(bool *HasErrorPtr) : HasError(HasErrorPtr) {}
   bool handleDiagnostics(const DiagnosticInfo &DI) override {
+    if (DI.getKind() == llvm::DK_SrcMgr) {
+      const auto &DISM = cast<DiagnosticInfoSrcMgr>(DI);
+      const SMDiagnostic &SMD = DISM.getSMDiag();
+
+      if (SMD.getKind() == SourceMgr::DK_Error)
+        *HasError = true;
+
+      SMD.print(nullptr, errs());
+
+      // For testing purposes, we print the LocCookie here.
+      if (DISM.isInlineAsmDiag() && DISM.getLocCookie())
+        WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n";
+
+      return true;
+    }
+
     if (DI.getSeverity() == DS_Error)
       *HasError = true;
 
@@ -305,19 +322,6 @@
   }
 };
 
-static void InlineAsmDiagHandler(const SMDiagnostic &SMD, void *Context,
-                                 unsigned LocCookie) {
-  bool *HasError = static_cast<bool *>(Context);
-  if (SMD.getKind() == SourceMgr::DK_Error)
-    *HasError = true;
-
-  SMD.print(nullptr, errs());
-
-  // For testing purposes, we print the LocCookie here.
-  if (LocCookie)
-    WithColor::note() << "!srcloc = " << LocCookie << "\n";
-}
-
 // main - Entry point for the llc compiler.
 //
 int main(int argc, char **argv) {
@@ -349,8 +353,10 @@
   initializeVectorization(*Registry);
   initializeScalarizeMaskedMemIntrinLegacyPassPass(*Registry);
   initializeExpandReductionsPass(*Registry);
+  initializeExpandVectorPredicationPass(*Registry);
   initializeHardwareLoopsPass(*Registry);
   initializeTransformUtils(*Registry);
+  initializeReplaceWithVeclibLegacyPass(*Registry);
 
   // Initialize debugging passes.
   initializeScavengerTestPass(*Registry);
@@ -366,7 +372,6 @@
   bool HasError = false;
   Context.setDiagnosticHandler(
       std::make_unique<LLCDiagnosticHandler>(&HasError));
-  Context.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, &HasError);
 
   Expected<std::unique_ptr<ToolOutputFile>> RemarksFileOrErr =
       setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses,
@@ -469,7 +474,7 @@
         TargetMachine::parseBinutilsVersion(BinutilsVersion);
     Options.DisableIntegratedAS = NoIntegratedAssembler;
     Options.MCOptions.ShowMCEncoding = ShowMCEncoding;
-    Options.MCOptions.MCUseDwarfDirectory = EnableDwarfDirectory;
+    Options.MCOptions.MCUseDwarfDirectory = DwarfDirectory;
     Options.MCOptions.AsmVerbose = AsmVerbose;
     Options.MCOptions.PreserveAsmComments = PreserveComments;
     Options.MCOptions.IASSearchPaths = IncludeDirs;
diff --git a/src/llvm-project/llvm/tools/lli/CMakeLists.txt b/src/llvm-project/llvm/tools/lli/CMakeLists.txt
index 098e9dd..90797cc 100644
--- a/src/llvm-project/llvm/tools/lli/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/lli/CMakeLists.txt
@@ -8,6 +8,7 @@
   ExecutionEngine
   IRReader
   Interpreter
+  JITLink
   MC
   MCJIT
   Object
@@ -50,6 +51,7 @@
 
 add_llvm_tool(lli
   lli.cpp
+  ExecutionUtils.cpp
 
   DEPENDS
   intrinsics_gen
diff --git a/src/llvm-project/llvm/tools/lli/ExecutionUtils.cpp b/src/llvm-project/llvm/tools/lli/ExecutionUtils.cpp
new file mode 100644
index 0000000..55370ed
--- /dev/null
+++ b/src/llvm-project/llvm/tools/lli/ExecutionUtils.cpp
@@ -0,0 +1,146 @@
+//===---- ExecutionUtils.cpp - Utilities for executing functions in lli ---===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "ExecutionUtils.h"
+
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <cstdint>
+#include <vector>
+
+// Declarations follow the GDB JIT interface (version 1, 2009) and must match
+// those of the DYLD used for testing. See:
+//
+//   llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp
+//   llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp
+//
+typedef enum {
+  JIT_NOACTION = 0,
+  JIT_REGISTER_FN,
+  JIT_UNREGISTER_FN
+} jit_actions_t;
+
+struct jit_code_entry {
+  struct jit_code_entry *next_entry;
+  struct jit_code_entry *prev_entry;
+  const char *symfile_addr;
+  uint64_t symfile_size;
+};
+
+struct jit_descriptor {
+  uint32_t version;
+  // This should be jit_actions_t, but we want to be specific about the
+  // bit-width.
+  uint32_t action_flag;
+  struct jit_code_entry *relevant_entry;
+  struct jit_code_entry *first_entry;
+};
+
+namespace llvm {
+
+template <typename... Ts> static void outsv(const char *Fmt, Ts &&...Vals) {
+  outs() << formatv(Fmt, Vals...);
+}
+
+static const char *actionFlagToStr(uint32_t ActionFlag) {
+  switch (ActionFlag) {
+  case JIT_NOACTION:
+    return "JIT_NOACTION";
+  case JIT_REGISTER_FN:
+    return "JIT_REGISTER_FN";
+  case JIT_UNREGISTER_FN:
+    return "JIT_UNREGISTER_FN";
+  }
+  return "<invalid action_flag>";
+}
+
+// Sample output:
+//
+//   Reading __jit_debug_descriptor at 0x0000000000404048
+//
+//   Version: 0
+//   Action: JIT_REGISTER_FN
+//
+//         Entry               Symbol File         Size  Previous Entry
+//   [ 0]  0x0000000000451290  0x0000000000002000   200  0x0000000000000000
+//   [ 1]  0x0000000000451260  0x0000000000001000   100  0x0000000000451290
+//   ...
+//
+static void dumpDebugDescriptor(void *Addr) {
+  outsv("Reading __jit_debug_descriptor at {0}\n\n", Addr);
+
+  jit_descriptor *Descriptor = reinterpret_cast<jit_descriptor *>(Addr);
+  outsv("Version: {0}\n", Descriptor->version);
+  outsv("Action: {0}\n\n", actionFlagToStr(Descriptor->action_flag));
+  outsv("{0,11}  {1,24}  {2,15}  {3,14}\n", "Entry", "Symbol File", "Size",
+        "Previous Entry");
+
+  unsigned Idx = 0;
+  for (auto *Entry = Descriptor->first_entry; Entry; Entry = Entry->next_entry)
+    outsv("[{0,2}]  {1:X16}  {2:X16}  {3,8:D}  {4}\n", Idx++, Entry,
+          reinterpret_cast<const void *>(Entry->symfile_addr),
+          Entry->symfile_size, Entry->prev_entry);
+}
+
+static LLIBuiltinFunctionGenerator *Generator = nullptr;
+
+static void dumpDebugObjects(void *Addr) {
+  jit_descriptor *Descriptor = reinterpret_cast<jit_descriptor *>(Addr);
+  for (auto *Entry = Descriptor->first_entry; Entry; Entry = Entry->next_entry)
+    Generator->appendDebugObject(Entry->symfile_addr, Entry->symfile_size);
+}
+
+LLIBuiltinFunctionGenerator::LLIBuiltinFunctionGenerator(
+    std::vector<BuiltinFunctionKind> Enabled, orc::MangleAndInterner &Mangle)
+    : TestOut(nullptr) {
+  Generator = this;
+  for (BuiltinFunctionKind F : Enabled) {
+    switch (F) {
+    case BuiltinFunctionKind::DumpDebugDescriptor:
+      expose(Mangle("__dump_jit_debug_descriptor"), &dumpDebugDescriptor);
+      break;
+    case BuiltinFunctionKind::DumpDebugObjects:
+      expose(Mangle("__dump_jit_debug_objects"), &dumpDebugObjects);
+      TestOut = createToolOutput();
+      break;
+    }
+  }
+}
+
+Error LLIBuiltinFunctionGenerator::tryToGenerate(
+    orc::LookupState &LS, orc::LookupKind K, orc::JITDylib &JD,
+    orc::JITDylibLookupFlags JDLookupFlags,
+    const orc::SymbolLookupSet &Symbols) {
+  orc::SymbolMap NewSymbols;
+  for (const auto &NameFlags : Symbols) {
+    auto It = BuiltinFunctions.find(NameFlags.first);
+    if (It != BuiltinFunctions.end())
+      NewSymbols.insert(*It);
+  }
+
+  if (NewSymbols.empty())
+    return Error::success();
+
+  return JD.define(absoluteSymbols(std::move(NewSymbols)));
+}
+
+// static
+std::unique_ptr<ToolOutputFile>
+LLIBuiltinFunctionGenerator::createToolOutput() {
+  std::error_code EC;
+  auto TestOut = std::make_unique<ToolOutputFile>("-", EC, sys::fs::OF_None);
+  if (EC) {
+    errs() << "Error creating tool output file: " << EC.message() << '\n';
+    exit(1);
+  }
+  return TestOut;
+}
+
+} // namespace llvm
diff --git a/src/llvm-project/llvm/tools/lli/ExecutionUtils.h b/src/llvm-project/llvm/tools/lli/ExecutionUtils.h
new file mode 100644
index 0000000..fcd1db0
--- /dev/null
+++ b/src/llvm-project/llvm/tools/lli/ExecutionUtils.h
@@ -0,0 +1,60 @@
+//===- ExecutionUtils.h - Utilities for executing code in lli ---*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains utilities for executing code in lli.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLI_EXECUTIONUTILS_H
+#define LLVM_TOOLS_LLI_EXECUTIONUTILS_H
+
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Mangling.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ToolOutputFile.h"
+
+#include <memory>
+#include <utility>
+
+namespace llvm {
+
+enum class BuiltinFunctionKind {
+  DumpDebugDescriptor,
+  DumpDebugObjects,
+};
+
+// Utility class to expose symbols for special-purpose functions to the JIT.
+class LLIBuiltinFunctionGenerator : public orc::DefinitionGenerator {
+public:
+  LLIBuiltinFunctionGenerator(std::vector<BuiltinFunctionKind> Enabled,
+                              orc::MangleAndInterner &Mangle);
+
+  Error tryToGenerate(orc::LookupState &LS, orc::LookupKind K,
+                      orc::JITDylib &JD, orc::JITDylibLookupFlags JDLookupFlags,
+                      const orc::SymbolLookupSet &Symbols) override;
+
+  void appendDebugObject(const char *Addr, size_t Size) {
+    TestOut->os().write(Addr, Size);
+  }
+
+private:
+  orc::SymbolMap BuiltinFunctions;
+  std::unique_ptr<ToolOutputFile> TestOut;
+
+  template <typename T> void expose(orc::SymbolStringPtr Name, T *Handler) {
+    BuiltinFunctions[Name] = JITEvaluatedSymbol(
+        pointerToJITTargetAddress(Handler), JITSymbolFlags::Exported);
+  }
+
+  static std::unique_ptr<ToolOutputFile> createToolOutput();
+};
+
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_LLI_EXECUTIONUTILS_H
diff --git a/src/llvm-project/llvm/tools/lli/lli.cpp b/src/llvm-project/llvm/tools/lli/lli.cpp
index 70c8381..af614c0 100644
--- a/src/llvm-project/llvm/tools/lli/lli.cpp
+++ b/src/llvm-project/llvm/tools/lli/lli.cpp
@@ -12,6 +12,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "ExecutionUtils.h"
 #include "RemoteJITUtils.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/Triple.h"
@@ -22,15 +23,21 @@
 #include "llvm/ExecutionEngine/GenericValue.h"
 #include "llvm/ExecutionEngine/Interpreter.h"
 #include "llvm/ExecutionEngine/JITEventListener.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
 #include "llvm/ExecutionEngine/MCJIT.h"
 #include "llvm/ExecutionEngine/ObjectCache.h"
+#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
 #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
+#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
+#include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h"
 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
-#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
 #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h"
 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
 #include "llvm/IR/IRBuilder.h"
@@ -76,7 +83,8 @@
 
 namespace {
 
-  enum class JITKind { MCJIT, OrcLazy };
+  enum class JITKind { MCJIT, Orc, OrcLazy };
+  enum class JITLinkerKind { Default, RuntimeDyld, JITLink };
 
   cl::opt<std::string>
   InputFile(cl::desc("<input bitcode>"), cl::Positional, cl::init("-"));
@@ -90,11 +98,22 @@
 
   cl::opt<JITKind> UseJITKind(
       "jit-kind", cl::desc("Choose underlying JIT kind."),
-      cl::init(JITKind::MCJIT),
+      cl::init(JITKind::Orc),
       cl::values(clEnumValN(JITKind::MCJIT, "mcjit", "MCJIT"),
+                 clEnumValN(JITKind::Orc, "orc", "Orc JIT"),
                  clEnumValN(JITKind::OrcLazy, "orc-lazy",
                             "Orc-based lazy JIT.")));
 
+  cl::opt<JITLinkerKind>
+      JITLinker("jit-linker", cl::desc("Choose the dynamic linker/loader."),
+                cl::init(JITLinkerKind::Default),
+                cl::values(clEnumValN(JITLinkerKind::Default, "default",
+                                      "Default for platform and JIT-kind"),
+                           clEnumValN(JITLinkerKind::RuntimeDyld, "rtdyld",
+                                      "RuntimeDyld"),
+                           clEnumValN(JITLinkerKind::JITLink, "jitlink",
+                                      "Orc-specific linker")));
+
   cl::opt<unsigned>
   LazyJITCompileThreads("compile-threads",
                         cl::desc("Choose the number of compile threads "
@@ -208,7 +227,7 @@
       cl::desc("Do not resolve lli process symbols in JIT'd code"),
       cl::init(false));
 
-  enum class LLJITPlatform { DetectHost, GenericIR, MachO };
+  enum class LLJITPlatform { Inactive, DetectHost, GenericIR };
 
   cl::opt<LLJITPlatform>
       Platform("lljit-platform", cl::desc("Platform to use with LLJIT"),
@@ -217,8 +236,8 @@
                                      "Select based on JIT target triple"),
                           clEnumValN(LLJITPlatform::GenericIR, "GenericIR",
                                      "Use LLJITGenericIRPlatform"),
-                          clEnumValN(LLJITPlatform::MachO, "MachO",
-                                     "Use LLJITMachOPlatform")),
+                          clEnumValN(LLJITPlatform::Inactive, "Inactive",
+                                     "Disable platform support explicitly")),
                cl::Hidden);
 
   enum class DumpKind {
@@ -243,9 +262,28 @@
                             "will overwrite existing files).")),
       cl::Hidden);
 
+  cl::list<BuiltinFunctionKind> GenerateBuiltinFunctions(
+      "generate",
+      cl::desc("Provide built-in functions for access by JITed code "
+               "(jit-kind=orc-lazy only)"),
+      cl::values(clEnumValN(BuiltinFunctionKind::DumpDebugDescriptor,
+                            "__dump_jit_debug_descriptor",
+                            "Dump __jit_debug_descriptor contents to stdout"),
+                 clEnumValN(BuiltinFunctionKind::DumpDebugObjects,
+                            "__dump_jit_debug_objects",
+                            "Dump __jit_debug_descriptor in-memory debug "
+                            "objects as tool output")),
+      cl::Hidden);
+
   ExitOnError ExitOnErr;
 }
 
+LLVM_ATTRIBUTE_USED void linkComponents() {
+  errs() << (void *)&llvm_orc_registerEHFrameSectionWrapper
+         << (void *)&llvm_orc_deregisterEHFrameSectionWrapper
+         << (void *)&llvm_orc_registerJITLoaderGDBWrapper;
+}
+
 //===----------------------------------------------------------------------===//
 // Object cache
 //
@@ -288,7 +326,8 @@
       return nullptr;
     // Load the object from the cache filename
     ErrorOr<std::unique_ptr<MemoryBuffer>> IRObjectBuffer =
-        MemoryBuffer::getFile(CacheName, -1, false);
+        MemoryBuffer::getFile(CacheName, /*IsText=*/false,
+                              /*RequiresNullTerminator=*/false);
     // If the file isn't there, that's OK.
     if (!IRObjectBuffer)
       return nullptr;
@@ -378,7 +417,7 @@
 }
 
 Error loadDylibs();
-int runOrcLazyJIT(const char *ProgName);
+int runOrcJIT(const char *ProgName);
 void disallowOrcOptions();
 
 //===----------------------------------------------------------------------===//
@@ -405,11 +444,12 @@
 
   ExitOnErr(loadDylibs());
 
-  if (UseJITKind == JITKind::OrcLazy)
-    return runOrcLazyJIT(argv[0]);
-  else
+  if (UseJITKind == JITKind::MCJIT)
     disallowOrcOptions();
+  else
+    return runOrcJIT(argv[0]);
 
+  // Old lli implementation based on ExecutionEngine and MCJIT.
   LLVMContext Context;
 
   // Load the bitcode...
@@ -677,7 +717,8 @@
     }
 
     // Create a remote target client running over the channel.
-    llvm::orc::ExecutionSession ES;
+    llvm::orc::ExecutionSession ES(
+        std::make_unique<orc::UnsupportedExecutorProcessControl>());
     ES.setErrorReporter([&](Error Err) { ExitOnErr(std::move(Err)); });
     typedef orc::remote::OrcRemoteTargetClient MyRemote;
     auto R = ExitOnErr(MyRemote::Create(*C, ES));
@@ -748,7 +789,8 @@
   case DumpKind::DumpModsToDisk:
     return [](Module &M) {
       std::error_code EC;
-      raw_fd_ostream Out(M.getModuleIdentifier() + ".ll", EC, sys::fs::OF_Text);
+      raw_fd_ostream Out(M.getModuleIdentifier() + ".ll", EC,
+                         sys::fs::OF_TextWithCRLF);
       if (EC) {
         errs() << "Couldn't open " << M.getModuleIdentifier()
                << " for dumping.\nError:" << EC.message() << "\n";
@@ -791,7 +833,7 @@
   return orc::ThreadSafeModule(std::move(M), std::move(TSCtx));
 }
 
-int runOrcLazyJIT(const char *ProgName) {
+int runOrcJIT(const char *ProgName) {
   // Start setting up the JIT environment.
 
   // Parse the main module.
@@ -829,6 +871,17 @@
       .setRelocationModel(codegen::getExplicitRelocModel())
       .setCodeModel(codegen::getExplicitCodeModel());
 
+  // FIXME: Setting a dummy call-through manager in non-lazy mode prevents the
+  // JIT builder to instantiate a default (which would fail with an error for
+  // unsupported architectures).
+  if (UseJITKind != JITKind::OrcLazy) {
+    auto ES = std::make_unique<orc::ExecutionSession>(
+        ExitOnErr(orc::SelfExecutorProcessControl::Create()));
+    Builder.setLazyCallthroughManager(
+        std::make_unique<orc::LazyCallThroughManager>(*ES, 0, nullptr));
+    Builder.setExecutionSession(std::move(ES));
+  }
+
   Builder.setLazyCompileFailureAddr(
       pointerToJITTargetAddress(exitOnLazyCallThroughFailure));
   Builder.setNumCompileThreads(LazyJITCompileThreads);
@@ -859,32 +912,43 @@
   // Set up LLJIT platform.
   {
     LLJITPlatform P = Platform;
-    if (P == LLJITPlatform::DetectHost) {
-      if (TT->isOSBinFormatMachO())
-        P = LLJITPlatform::MachO;
-      else
-        P = LLJITPlatform::GenericIR;
-    }
+    if (P == LLJITPlatform::DetectHost)
+      P = LLJITPlatform::GenericIR;
 
     switch (P) {
     case LLJITPlatform::GenericIR:
       // Nothing to do: LLJITBuilder will use this by default.
       break;
-    case LLJITPlatform::MachO:
-      Builder.setPlatformSetUp(orc::setUpMachOPlatform);
-      ExitOnErr(orc::enableObjCRegistration("libobjc.dylib"));
+    case LLJITPlatform::Inactive:
+      Builder.setPlatformSetUp(orc::setUpInactivePlatform);
       break;
     default:
       llvm_unreachable("Unrecognized platform value");
     }
   }
 
+  std::unique_ptr<orc::ExecutorProcessControl> EPC = nullptr;
+  if (JITLinker == JITLinkerKind::JITLink) {
+    EPC = ExitOnErr(orc::SelfExecutorProcessControl::Create(
+        std::make_shared<orc::SymbolStringPool>()));
+
+    Builder.setObjectLinkingLayerCreator([&EPC](orc::ExecutionSession &ES,
+                                                const Triple &) {
+      auto L = std::make_unique<orc::ObjectLinkingLayer>(ES, EPC->getMemMgr());
+      L->addPlugin(std::make_unique<orc::EHFrameRegistrationPlugin>(
+          ES, ExitOnErr(orc::EPCEHFrameRegistrar::Create(ES))));
+      L->addPlugin(std::make_unique<orc::DebugObjectManagerPlugin>(
+          ES, ExitOnErr(orc::createJITLoaderGDBRegistrar(ES))));
+      return L;
+    });
+  }
+
   auto J = ExitOnErr(Builder.create());
 
-  if (TT->isOSBinFormatELF())
-    static_cast<llvm::orc::RTDyldObjectLinkingLayer &>(J->getObjLinkingLayer())
-        .registerJITEventListener(
-            *JITEventListener::createGDBRegistrationListener());
+  auto *ObjLayer = &J->getObjLinkingLayer();
+  if (auto *RTDyldObjLayer = dyn_cast<orc::RTDyldObjectLinkingLayer>(ObjLayer))
+    RTDyldObjLayer->registerJITEventListener(
+        *JITEventListener::createGDBRegistrationListener());
 
   if (PerModuleLazy)
     J->setPartitionFunction(orc::CompileOnDemandLayer::compileWholeModule);
@@ -916,8 +980,22 @@
               return Name != MainName;
             })));
 
+  if (GenerateBuiltinFunctions.size() > 0)
+    J->getMainJITDylib().addGenerator(
+        std::make_unique<LLIBuiltinFunctionGenerator>(GenerateBuiltinFunctions,
+                                                      Mangle));
+
+  // Regular modules are greedy: They materialize as a whole and trigger
+  // materialization for all required symbols recursively. Lazy modules go
+  // through partitioning and they replace outgoing calls with reexport stubs
+  // that resolve on call-through.
+  auto AddModule = [&](orc::JITDylib &JD, orc::ThreadSafeModule M) {
+    return UseJITKind == JITKind::OrcLazy ? J->addLazyIRModule(JD, std::move(M))
+                                          : J->addIRModule(JD, std::move(M));
+  };
+
   // Add the main module.
-  ExitOnErr(J->addLazyIRModule(std::move(MainModule)));
+  ExitOnErr(AddModule(J->getMainJITDylib(), std::move(MainModule)));
 
   // Create JITDylibs and add any extra modules.
   {
@@ -945,7 +1023,7 @@
       assert(EMIdx != 0 && "ExtraModule should have index > 0");
       auto JDItr = std::prev(IdxToDylib.lower_bound(EMIdx));
       auto &JD = *JDItr->second;
-      ExitOnErr(J->addLazyIRModule(JD, std::move(M)));
+      ExitOnErr(AddModule(JD, std::move(M)));
     }
 
     for (auto EAItr = ExtraArchives.begin(), EAEnd = ExtraArchives.end();
@@ -978,13 +1056,19 @@
     AltEntryThreads.push_back(std::thread([EntryPoint]() { EntryPoint(); }));
   }
 
-  // Run main.
-  auto MainSym = ExitOnErr(J->lookup("main"));
+  // Resolve and run the main function.
+  JITEvaluatedSymbol MainSym = ExitOnErr(J->lookup(EntryFunc));
+  int Result;
 
-  typedef int (*MainFnPtr)(int, char *[]);
-  auto Result = orc::runAsMain(
-      jitTargetAddressToFunction<MainFnPtr>(MainSym.getAddress()), InputArgv,
-      StringRef(InputFile));
+  if (EPC) {
+    // ExecutorProcessControl-based execution with JITLink.
+    Result = ExitOnErr(EPC->runAsMain(MainSym.getAddress(), InputArgv));
+  } else {
+    // Manual in-process execution with RuntimeDyld.
+    using MainFnTy = int(int, char *[]);
+    auto MainFn = jitTargetAddressToFunction<MainFnTy *>(MainSym.getAddress());
+    Result = orc::runAsMain(MainFn, InputArgv, StringRef(InputFile));
+  }
 
   // Wait for -entry-point threads.
   for (auto &AltEntryThread : AltEntryThreads)
diff --git a/src/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp b/src/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp
index 4c26c8c..0e1dce6 100644
--- a/src/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/src/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -126,9 +126,9 @@
 )";
 
 static void printHelpMessage() {
-  if (Stem.contains_lower("ranlib"))
+  if (Stem.contains_insensitive("ranlib"))
     outs() << RanlibHelp;
-  else if (Stem.contains_lower("ar"))
+  else if (Stem.contains_insensitive("ar"))
     outs() << ArHelp;
 }
 
@@ -270,7 +270,8 @@
 }
 
 static object::Archive &readLibrary(const Twine &Library) {
-  auto BufOrErr = MemoryBuffer::getFile(Library, -1, false);
+  auto BufOrErr = MemoryBuffer::getFile(Library, /*IsText=*/false,
+                                        /*RequiresNullTerminator=*/false);
   failIfError(BufOrErr.getError(), "could not open library " + Library);
   ArchiveBuffers.push_back(std::move(*BufOrErr));
   auto LibOrErr =
@@ -995,8 +996,8 @@
 static int performOperation(ArchiveOperation Operation,
                             std::vector<NewArchiveMember> *NewMembers) {
   // Create or open the archive object.
-  ErrorOr<std::unique_ptr<MemoryBuffer>> Buf =
-      MemoryBuffer::getFile(ArchiveName, -1, false);
+  ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(
+      ArchiveName, /*IsText=*/false, /*RequiresNullTerminator=*/false);
   std::error_code EC = Buf.getError();
   if (EC && EC != errc::no_such_file_or_directory)
     fail("unable to open '" + ArchiveName + "': " + EC.message());
@@ -1275,7 +1276,7 @@
     // Lib.exe -> lib (see D44808, MSBuild runs Lib.exe)
     // dlltool.exe -> dlltool
     // arm-pokymllib32-linux-gnueabi-llvm-ar-10 -> ar
-    auto I = Stem.rfind_lower(Tool);
+    auto I = Stem.rfind_insensitive(Tool);
     return I != StringRef::npos &&
            (I + Tool.size() == Stem.size() || !isAlnum(Stem[I + Tool.size()]));
   };
diff --git a/src/llvm-project/llvm/tools/llvm-as/llvm-as.cpp b/src/llvm-project/llvm/tools/llvm-as/llvm-as.cpp
index f2b5289..307a7f9 100644
--- a/src/llvm-project/llvm/tools/llvm-as/llvm-as.cpp
+++ b/src/llvm-project/llvm/tools/llvm-as/llvm-as.cpp
@@ -115,9 +115,9 @@
 
 int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
-  LLVMContext Context;
   cl::HideUnrelatedOptions(AsCat);
   cl::ParseCommandLineOptions(argc, argv, "llvm .ll -> .bc assembler\n");
+  LLVMContext Context;
 
   // Parse the file now...
   SMDiagnostic Err;
diff --git a/src/llvm-project/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/src/llvm-project/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
index 639a6d1..f4851bf 100644
--- a/src/llvm-project/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -32,37 +32,48 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 #include <memory>
 using namespace llvm;
 
-static cl::opt<std::string>
-    InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
+static cl::OptionCategory BCAnalyzerCategory("BC Analyzer Options");
 
-static cl::opt<bool> Dump("dump", cl::desc("Dump low level bitcode trace"));
+static cl::opt<std::string> InputFilename(cl::Positional,
+                                          cl::desc("<input bitcode>"),
+                                          cl::init("-"),
+                                          cl::cat(BCAnalyzerCategory));
+
+static cl::opt<bool> Dump("dump", cl::desc("Dump low level bitcode trace"),
+                          cl::cat(BCAnalyzerCategory));
 
 //===----------------------------------------------------------------------===//
 // Bitcode specific analysis.
 //===----------------------------------------------------------------------===//
 
 static cl::opt<bool> NoHistogram("disable-histogram",
-                                 cl::desc("Do not print per-code histogram"));
+                                 cl::desc("Do not print per-code histogram"),
+                                 cl::cat(BCAnalyzerCategory));
 
 static cl::opt<bool> NonSymbolic("non-symbolic",
                                  cl::desc("Emit numeric info in dump even if"
-                                          " symbolic info is available"));
+                                          " symbolic info is available"),
+                                 cl::cat(BCAnalyzerCategory));
 
 static cl::opt<std::string>
     BlockInfoFilename("block-info",
-                      cl::desc("Use the BLOCK_INFO from the given file"));
+                      cl::desc("Use the BLOCK_INFO from the given file"),
+                      cl::cat(BCAnalyzerCategory));
 
 static cl::opt<bool>
     ShowBinaryBlobs("show-binary-blobs",
-                    cl::desc("Print binary blobs using hex escapes"));
+                    cl::desc("Print binary blobs using hex escapes"),
+                    cl::cat(BCAnalyzerCategory));
 
 static cl::opt<std::string> CheckHash(
     "check-hash",
-    cl::desc("Check module hash using the argument as a string table"));
+    cl::desc("Check module hash using the argument as a string table"),
+    cl::cat(BCAnalyzerCategory));
 
 static Error reportError(StringRef Message) {
   return createStringError(std::errc::illegal_byte_sequence, Message.data());
@@ -85,6 +96,8 @@
 
 int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
+
+  cl::HideUnrelatedOptions({&BCAnalyzerCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv, "llvm-bcanalyzer file analyzer\n");
   ExitOnError ExitOnErr("llvm-bcanalyzer: ");
 
diff --git a/src/llvm-project/llvm/tools/llvm-c-test/echo.cpp b/src/llvm-project/llvm/tools/llvm-c-test/echo.cpp
index a29f360..d54adeb 100644
--- a/src/llvm-project/llvm/tools/llvm-c-test/echo.cpp
+++ b/src/llvm-project/llvm/tools/llvm-c-test/echo.cpp
@@ -18,6 +18,7 @@
 #include "llvm-c/DebugInfo.h"
 #include "llvm-c/Target.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/ErrorHandling.h"
 
 #include <stdio.h>
@@ -653,6 +654,7 @@
         LLVMAtomicOrdering Ord = LLVMGetOrdering(Src);
         LLVMBool SingleThread = LLVMIsAtomicSingleThread(Src);
         Dst = LLVMBuildAtomicRMW(Builder, BinOp, Ptr, Val, Ord, SingleThread);
+        LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
         LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
         LLVMSetValueName2(Dst, Name, NameLen);
         break;
@@ -667,6 +669,7 @@
 
         Dst = LLVMBuildAtomicCmpXchg(Builder, Ptr, Cmp, New, Succ, Fail,
                                      SingleThread);
+        LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
         LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
         LLVMSetWeak(Dst, LLVMGetWeak(Src));
         LLVMSetValueName2(Dst, Name, NameLen);
diff --git a/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/CMakeLists.txt
index 41d55ed..679bffe 100644
--- a/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/CMakeLists.txt
@@ -1,16 +1,4 @@
-add_library(LLVMCFIVerify
-  STATIC
-  FileAnalysis.cpp
-  FileAnalysis.h
-  GraphBuilder.cpp
-  GraphBuilder.h
-  )
-
-llvm_update_compile_flags(LLVMCFIVerify)
-if (LLVM_LINK_LLVM_DYLIB)
-  set(libs LLVM)
-else()
-  llvm_map_components_to_libnames(libs
+set(LLVM_LINK_COMPONENTS
     DebugInfoDWARF
     MC
     MCParser
@@ -18,6 +6,11 @@
     Support
     Symbolize
     )
-endif()
-target_link_libraries(LLVMCFIVerify ${libs})
-set_target_properties(LLVMCFIVerify PROPERTIES FOLDER "Libraries")
+
+add_llvm_library(LLVMCFIVerify
+  STATIC
+  FileAnalysis.cpp
+  FileAnalysis.h
+  GraphBuilder.cpp
+  GraphBuilder.h
+  )
diff --git a/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp b/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
index 100f5d8..e1bca0d 100644
--- a/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
@@ -374,7 +374,9 @@
   MCPU = "";
   std::string ErrorString;
 
-  Symbolizer.reset(new LLVMSymbolizer());
+  LLVMSymbolizer::Options Opt;
+  Opt.UseSymbolTable = false;
+  Symbolizer.reset(new LLVMSymbolizer(Opt));
 
   ObjectTarget =
       TargetRegistry::lookupTarget(ArchName, ObjectTriple, ErrorString);
@@ -405,7 +407,8 @@
   if (!MII)
     return make_error<UnsupportedDisassembly>("Failed to initialise MII.");
 
-  Context.reset(new MCContext(AsmInfo.get(), RegisterInfo.get(), &MOFI));
+  Context.reset(new MCContext(Triple(TripleName), AsmInfo.get(),
+                              RegisterInfo.get(), SubtargetInfo.get()));
 
   Disassembler.reset(
       ObjectTarget->createMCDisassembler(*SubtargetInfo, *Context));
diff --git a/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.h b/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.h
index 27135c0..b256f7e 100644
--- a/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.h
+++ b/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.h
@@ -207,7 +207,6 @@
   std::unique_ptr<const MCAsmInfo> AsmInfo;
   std::unique_ptr<MCSubtargetInfo> SubtargetInfo;
   std::unique_ptr<const MCInstrInfo> MII;
-  MCObjectFileInfo MOFI;
   std::unique_ptr<MCContext> Context;
   std::unique_ptr<const MCDisassembler> Disassembler;
   std::unique_ptr<const MCInstrAnalysis> MIA;
diff --git a/src/llvm-project/llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp b/src/llvm-project/llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp
index 1331442..3cb0e84 100644
--- a/src/llvm-project/llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cfi-verify/llvm-cfi-verify.cpp
@@ -32,21 +32,24 @@
 using namespace llvm::object;
 using namespace llvm::cfi_verify;
 
+static cl::OptionCategory CFIVerifyCategory("CFI Verify Options");
+
 cl::opt<std::string> InputFilename(cl::Positional, cl::desc("<input file>"),
-                                   cl::Required);
+                                   cl::Required, cl::cat(CFIVerifyCategory));
 cl::opt<std::string> BlacklistFilename(cl::Positional,
                                        cl::desc("[blacklist file]"),
-                                       cl::init("-"));
+                                       cl::init("-"),
+                                       cl::cat(CFIVerifyCategory));
 cl::opt<bool> PrintGraphs(
     "print-graphs",
     cl::desc("Print graphs around indirect CF instructions in DOT format."),
-    cl::init(false));
+    cl::init(false), cl::cat(CFIVerifyCategory));
 cl::opt<unsigned> PrintBlameContext(
     "blame-context",
     cl::desc("Print the blame context (if possible) for BAD instructions. This "
              "specifies the number of lines of context to include, where zero "
              "disables this feature."),
-    cl::init(0));
+    cl::init(0), cl::cat(CFIVerifyCategory));
 cl::opt<unsigned> PrintBlameContextAll(
     "blame-context-all",
     cl::desc("Prints the blame context (if possible) for ALL instructions. "
@@ -54,9 +57,9 @@
              "instructions (see --blame-context). If --blame-context is "
              "unspecified, it prints this number of contextual lines for BAD "
              "instructions as well."),
-    cl::init(0));
+    cl::init(0), cl::cat(CFIVerifyCategory));
 cl::opt<bool> Summarize("summarize", cl::desc("Print the summary only."),
-                        cl::init(false));
+                        cl::init(false), cl::cat(CFIVerifyCategory));
 
 ExitOnError ExitOnErr;
 
@@ -245,6 +248,7 @@
 }
 
 int main(int argc, char **argv) {
+  cl::HideUnrelatedOptions({&CFIVerifyCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(
       argc, argv,
       "Identifies whether Control Flow Integrity protects all indirect control "
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp b/src/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
index baa9688..02c0106 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -80,6 +80,12 @@
   /// directory, recursively collect all of the paths within the directory.
   void collectPaths(const std::string &Path);
 
+  /// Check if the two given files are the same file.
+  bool isEquivalentFile(StringRef FilePath1, StringRef FilePath2);
+
+  /// Retrieve a file status with a cache.
+  Optional<sys::fs::file_status> getFileStatus(StringRef FilePath);
+
   /// Return a memory buffer for the given source file.
   ErrorOr<const MemoryBuffer &> getSourceFile(StringRef SourceFile);
 
@@ -153,6 +159,9 @@
   /// remapped to, when using -path-equivalence.
   Optional<std::pair<std::string, std::string>> PathRemapping;
 
+  /// File status cache used when finding the same file.
+  StringMap<Optional<sys::fs::file_status>> FileStatusCache;
+
   /// The architecture the coverage mapping data targets.
   std::vector<StringRef> CoverageArches;
 
@@ -239,6 +248,27 @@
   }
 }
 
+Optional<sys::fs::file_status>
+CodeCoverageTool::getFileStatus(StringRef FilePath) {
+  auto It = FileStatusCache.try_emplace(FilePath);
+  auto &CachedStatus = It.first->getValue();
+  if (!It.second)
+    return CachedStatus;
+
+  sys::fs::file_status Status;
+  if (!sys::fs::status(FilePath, Status))
+    CachedStatus = Status;
+  return CachedStatus;
+}
+
+bool CodeCoverageTool::isEquivalentFile(StringRef FilePath1,
+                                        StringRef FilePath2) {
+  auto Status1 = getFileStatus(FilePath1);
+  auto Status2 = getFileStatus(FilePath2);
+  return Status1.hasValue() && Status2.hasValue() &&
+         sys::fs::equivalent(Status1.getValue(), Status2.getValue());
+}
+
 ErrorOr<const MemoryBuffer &>
 CodeCoverageTool::getSourceFile(StringRef SourceFile) {
   // If we've remapped filenames, look up the real location for this file.
@@ -249,7 +279,7 @@
       SourceFile = Loc->second;
   }
   for (const auto &Files : LoadedSourceFiles)
-    if (sys::fs::equivalent(SourceFile, Files.first))
+    if (isEquivalentFile(SourceFile, Files.first))
       return *Files.second;
   auto Buffer = MemoryBuffer::getFile(SourceFile);
   if (auto EC = Buffer.getError()) {
@@ -404,7 +434,8 @@
       warning("profile data may be out of date - object is newer",
               ObjectFilename);
   auto CoverageOrErr =
-      CoverageMapping::load(ObjectFilenames, PGOFilename, CoverageArches);
+      CoverageMapping::load(ObjectFilenames, PGOFilename, CoverageArches,
+                            ViewOpts.CompilationDirectory);
   if (Error E = CoverageOrErr.takeError()) {
     error("Failed to load coverage: " + toString(std::move(E)),
           join(ObjectFilenames.begin(), ObjectFilenames.end(), ", "));
@@ -445,7 +476,7 @@
     SmallString<128> NativePath;
     sys::path::native(Path, NativePath);
     sys::path::remove_dots(NativePath, true);
-    if (!sys::path::is_separator(NativePath.back()))
+    if (!NativePath.empty() && !sys::path::is_separator(NativePath.back()))
       NativePath += sys::path::get_separator();
     return NativePath.c_str();
   };
@@ -709,6 +740,10 @@
   cl::alias NumThreadsA("j", cl::desc("Alias for --num-threads"),
                         cl::aliasopt(NumThreads));
 
+  cl::opt<std::string> CompilationDirectory(
+      "compilation-dir", cl::init(""),
+      cl::desc("Directory used as a base for relative coverage mapping paths"));
+
   auto commandLineParser = [&, this](int argc, const char **argv) -> int {
     cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
     ViewOpts.Debug = DebugDump;
@@ -843,6 +878,7 @@
     ViewOpts.ShowInstantiationSummary = InstantiationSummary;
     ViewOpts.ExportSummaryOnly = SummaryOnly;
     ViewOpts.NumThreads = NumThreads;
+    ViewOpts.CompilationDirectory = CompilationDirectory;
 
     return 0;
   };
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterJson.cpp b/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterJson.cpp
index d1446f3..d341abe 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterJson.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterJson.cpp
@@ -123,8 +123,7 @@
     // Recursively collect branches from nested expansions.
     auto NestedExpansions = ExpansionCoverage.getExpansions();
     auto NestedExBranches = collectNestedBranches(Coverage, NestedExpansions);
-    Branches.insert(Branches.end(), NestedExBranches.begin(),
-                    NestedExBranches.end());
+    append_range(Branches, NestedExBranches);
 
     // Add branches from this level of expansion.
     auto ExBranches = ExpansionCoverage.getBranches();
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterLcov.cpp b/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterLcov.cpp
index 99ca037..6cf5d92 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterLcov.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterLcov.cpp
@@ -91,8 +91,7 @@
     auto NestedExpansions = ExpansionCoverage.getExpansions();
     auto NestedExBranches = collectNestedBranches(Coverage, NestedExpansions,
                                                   ViewDepth + 1, SrcLine);
-    Branches.insert(Branches.end(), NestedExBranches.begin(),
-                    NestedExBranches.end());
+    append_range(Branches, NestedExBranches);
 
     // Add branches from this level of expansion.
     auto ExBranches = ExpansionCoverage.getBranches();
@@ -123,7 +122,7 @@
       collectNestedBranches(Coverage, FileCoverage.getExpansions());
 
   // Append Expansion Branches to Source Branches.
-  Branches.insert(Branches.end(), ExBranches.begin(), ExBranches.end());
+  append_range(Branches, ExBranches);
 
   // Sort branches based on line number to ensure branches corresponding to the
   // same source line are counted together.
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageViewOptions.h b/src/llvm-project/llvm/tools/llvm-cov/CoverageViewOptions.h
index eee4ba7..045fb17 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageViewOptions.h
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageViewOptions.h
@@ -49,6 +49,7 @@
   std::string ProjectTitle;
   std::string CreatedTimeStr;
   unsigned NumThreads;
+  std::string CompilationDirectory;
 
   /// Change the output's stream color if the colors are enabled.
   ColoredRawOstream colored_ostream(raw_ostream &OS,
diff --git a/src/llvm-project/llvm/tools/llvm-cov/TestingSupport.cpp b/src/llvm-project/llvm/tools/llvm-cov/TestingSupport.cpp
index b99bd83..9c6b25f 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/TestingSupport.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/TestingSupport.cpp
@@ -10,6 +10,7 @@
 #include "llvm/ProfileData/InstrProf.h"
 #include "llvm/Support/Alignment.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/raw_ostream.h"
 #include <functional>
@@ -47,7 +48,7 @@
 
   // Look for the sections that we are interested in.
   int FoundSectionCount = 0;
-  SectionRef ProfileNames, CoverageMapping;
+  SectionRef ProfileNames, CoverageMapping, CoverageRecords;
   auto ObjFormat = OF->getTripleObjectFormat();
   for (const auto &Section : OF->sections()) {
     StringRef Name;
@@ -64,16 +65,20 @@
     } else if (Name == llvm::getInstrProfSectionName(
                            IPSK_covmap, ObjFormat, /*AddSegmentInfo=*/false)) {
       CoverageMapping = Section;
+    } else if (Name == llvm::getInstrProfSectionName(
+                           IPSK_covfun, ObjFormat, /*AddSegmentInfo=*/false)) {
+      CoverageRecords = Section;
     } else
       continue;
     ++FoundSectionCount;
   }
-  if (FoundSectionCount != 2)
+  if (FoundSectionCount != 3)
     return 1;
 
   // Get the contents of the given sections.
   uint64_t ProfileNamesAddress = ProfileNames.getAddress();
   StringRef CoverageMappingData;
+  StringRef CoverageRecordsData;
   StringRef ProfileNamesData;
   if (Expected<StringRef> E = CoverageMapping.getContents())
     CoverageMappingData = *E;
@@ -81,6 +86,12 @@
     consumeError(E.takeError());
     return 1;
   }
+  if (Expected<StringRef> E = CoverageRecords.getContents())
+    CoverageRecordsData = *E;
+  else {
+    consumeError(E.takeError());
+    return 1;
+  }
   if (Expected<StringRef> E = ProfileNames.getContents())
     ProfileNamesData = *E;
   else {
@@ -103,6 +114,10 @@
   for (unsigned Pad = offsetToAlignment(OS.tell(), Align(8)); Pad; --Pad)
     OS.write(uint8_t(0));
   OS << CoverageMappingData;
+  // Coverage records data is expected to have an alignment of 8.
+  for (unsigned Pad = offsetToAlignment(OS.tell(), Align(8)); Pad; --Pad)
+    OS.write(uint8_t(0));
+  OS << CoverageRecordsData;
 
   return 0;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-cov/gcov.cpp b/src/llvm-project/llvm/tools/llvm-cov/gcov.cpp
index d42e7cd..9a1ebeb 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/gcov.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/gcov.cpp
@@ -46,7 +46,8 @@
   // Open .gcda and .gcda without requiring a NUL terminator. The concurrent
   // modification may nullify the NUL terminator condition.
   ErrorOr<std::unique_ptr<MemoryBuffer>> GCNO_Buff =
-      MemoryBuffer::getFileOrSTDIN(GCNO, -1, /*RequiresNullTerminator=*/false);
+      MemoryBuffer::getFileOrSTDIN(GCNO, /*IsText=*/false,
+                                   /*RequiresNullTerminator=*/false);
   if (std::error_code EC = GCNO_Buff.getError()) {
     errs() << GCNO << ": " << EC.message() << "\n";
     return;
@@ -58,7 +59,8 @@
   }
 
   ErrorOr<std::unique_ptr<MemoryBuffer>> GCDA_Buff =
-      MemoryBuffer::getFileOrSTDIN(GCDA, -1, /*RequiresNullTerminator=*/false);
+      MemoryBuffer::getFileOrSTDIN(GCDA, /*IsText=*/false,
+                                   /*RequiresNullTerminator=*/false);
   if (std::error_code EC = GCDA_Buff.getError()) {
     if (EC != errc::no_such_file_or_directory) {
       errs() << GCDA << ": " << EC.message() << "\n";
diff --git a/src/llvm-project/llvm/tools/llvm-cov/llvm-cov.cpp b/src/llvm-project/llvm/tools/llvm-cov/llvm-cov.cpp
index 172ec9f..0e320c0 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/llvm-cov.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/llvm-cov.cpp
@@ -60,7 +60,7 @@
   InitLLVM X(argc, argv);
 
   // If argv[0] is or ends with 'gcov', always be gcov compatible
-  if (sys::path::stem(argv[0]).endswith_lower("gcov"))
+  if (sys::path::stem(argv[0]).endswith_insensitive("gcov"))
     return gcovMain(argc, argv);
 
   // Check if we are invoking a specific tool command.
diff --git a/src/llvm-project/llvm/tools/llvm-cvtres/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-cvtres/CMakeLists.txt
index e912030..0898318 100644
--- a/src/llvm-project/llvm/tools/llvm-cvtres/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-cvtres/CMakeLists.txt
@@ -1,4 +1,5 @@
 set(LLVM_LINK_COMPONENTS
+  BinaryFormat
   Object
   Option
   Support
diff --git a/src/llvm-project/llvm/tools/llvm-cvtres/llvm-cvtres.cpp b/src/llvm-project/llvm/tools/llvm-cvtres/llvm-cvtres.cpp
index 11cfb46..24b3c65 100644
--- a/src/llvm-project/llvm/tools/llvm-cvtres/llvm-cvtres.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cvtres/llvm-cvtres.cpp
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/BinaryFormat/Magic.h"
 #include "llvm/Object/Binary.h"
 #include "llvm/Object/WindowsMachineFlag.h"
 #include "llvm/Object/WindowsResource.h"
@@ -75,6 +76,14 @@
   reportError(Twine(Input) + ": " + EC.message() + ".\n");
 }
 
+static void error(StringRef Input, Error EC) {
+  if (!EC)
+    return;
+  handleAllErrors(std::move(EC), [&](const ErrorInfoBase &EI) {
+    reportError(Twine(Input) + ": " + EI.message() + ".\n");
+  });
+}
+
 static void error(Error EC) {
   if (!EC)
     return;
@@ -95,6 +104,16 @@
   return std::move(EC.get());
 }
 
+template <typename T> T error(StringRef Input, Expected<T> EC) {
+  if (!EC)
+    error(Input, EC.takeError());
+  return std::move(EC.get());
+}
+
+template <typename T> T error(StringRef Input, ErrorOr<T> &&EC) {
+  return error(Input, errorOrToExpected(std::move(EC)));
+}
+
 int main(int Argc, const char **Argv) {
   InitLLVM X(Argc, Argv);
 
@@ -104,7 +123,7 @@
   opt::InputArgList InputArgs = T.ParseArgs(ArgsArr, MAI, MAC);
 
   if (InputArgs.hasArg(OPT_HELP)) {
-    T.PrintHelp(outs(), "llvm-cvtres [options] file...", "Resource Converter");
+    T.printHelp(outs(), "llvm-cvtres [options] file...", "Resource Converter");
     return 0;
   }
 
@@ -155,15 +174,17 @@
   WindowsResourceParser Parser;
 
   for (const auto &File : InputFiles) {
-    Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(File);
-    if (!BinaryOrErr)
-      reportError(File, errorToErrorCode(BinaryOrErr.takeError()));
-
-    Binary &Binary = *BinaryOrErr.get().getBinary();
-
-    WindowsResource *RF = dyn_cast<WindowsResource>(&Binary);
-    if (!RF)
+    std::unique_ptr<MemoryBuffer> Buffer = error(
+        File, MemoryBuffer::getFileOrSTDIN(File, /*IsText=*/false,
+                                           /*RequiresNullTerminator=*/false));
+    file_magic Type = identify_magic(Buffer->getMemBufferRef().getBuffer());
+    if (Type != file_magic::windows_resource)
       reportError(File + ": unrecognized file format.\n");
+    std::unique_ptr<WindowsResource> Binary = error(
+        File,
+        WindowsResource::createWindowsResource(Buffer->getMemBufferRef()));
+
+    WindowsResource *RF = Binary.get();
 
     if (Verbose) {
       int EntryNumber = 0;
@@ -199,12 +220,14 @@
   error(FileBuffer->commit());
 
   if (Verbose) {
-    Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(OutputFile);
-    if (!BinaryOrErr)
-      reportError(OutputFile, errorToErrorCode(BinaryOrErr.takeError()));
-    Binary &Binary = *BinaryOrErr.get().getBinary();
+    std::unique_ptr<MemoryBuffer> Buffer =
+        error(OutputFile,
+              MemoryBuffer::getFileOrSTDIN(OutputFile, /*IsText=*/false,
+                                           /*RequiresNullTerminator=*/false));
+
     ScopedPrinter W(errs());
-    W.printBinaryBlock("Output File Raw Data", Binary.getData());
+    W.printBinaryBlock("Output File Raw Data",
+                       Buffer->getMemBufferRef().getBuffer());
   }
 
   return 0;
diff --git a/src/llvm-project/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp b/src/llvm-project/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
index 03e1bab..f214288 100644
--- a/src/llvm-project/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
@@ -33,9 +33,10 @@
 using namespace llvm::support;
 
 namespace opts {
+cl::OptionCategory CXXDumpCategory("CXX Dump Options");
 cl::list<std::string> InputFilenames(cl::Positional,
                                      cl::desc("<input object files>"),
-                                     cl::ZeroOrMore);
+                                     cl::ZeroOrMore, cl::cat(CXXDumpCategory));
 } // namespace opts
 
 namespace llvm {
@@ -549,6 +550,7 @@
   // Register the target printer for --version.
   cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
 
+  cl::HideUnrelatedOptions({&opts::CXXDumpCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv, "LLVM C++ ABI Data Dumper\n");
 
   // Default to stdin if no filename is specified.
diff --git a/src/llvm-project/llvm/tools/llvm-cxxfilt/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-cxxfilt/CMakeLists.txt
index 2a78aca..07ba9f9 100644
--- a/src/llvm-project/llvm/tools/llvm-cxxfilt/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-cxxfilt/CMakeLists.txt
@@ -1,10 +1,18 @@
 set(LLVM_LINK_COMPONENTS
   Demangle
+  Option
   Support
   )
 
+set(LLVM_TARGET_DEFINITIONS Opts.td)
+tablegen(LLVM Opts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(CxxfiltOptsTableGen)
+
 add_llvm_tool(llvm-cxxfilt
   llvm-cxxfilt.cpp
+
+  DEPENDS
+  CxxfiltOptsTableGen
   )
 
 if(LLVM_INSTALL_BINUTILS_SYMLINKS)
diff --git a/src/llvm-project/llvm/tools/llvm-cxxfilt/Opts.td b/src/llvm-project/llvm/tools/llvm-cxxfilt/Opts.td
new file mode 100644
index 0000000..93f8652
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-cxxfilt/Opts.td
@@ -0,0 +1,28 @@
+include "llvm/Option/OptParser.td"
+
+class F<string letter, string help> : Flag<["-"], letter>, HelpText<help>;
+class FF<string name, string help> : Flag<["--"], name>, HelpText<help>;
+
+multiclass BB<string name, string help1, string help2> {
+  def NAME: Flag<["--"], name>, HelpText<help1>;
+  def no_ # NAME: Flag<["--"], "no-" # name>, HelpText<help2>;
+}
+
+multiclass Eq<string name, string help> {
+  def NAME #_EQ : Joined<["--"], name #"=">,
+                  HelpText<help>;
+  def : Separate<["--"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
+}
+
+def help : FF<"help", "Display this help">;
+defm strip_underscore : BB<"strip-underscore", "Strip the leading underscore", "Don't strip the leading underscore">;
+def types : FF<"types", "">;
+def version : FF<"version", "Display the version">;
+
+defm : Eq<"format", "Specify mangling format. Currently ignored because only 'gnu' is supported">;
+def : F<"s", "Alias for --format">;
+
+def : F<"_", "Alias for --strip-underscore">, Alias<strip_underscore>;
+def : F<"h", "Alias for --help">, Alias<help>;
+def : F<"n", "Alias for --no-strip-underscore">, Alias<no_strip_underscore>;
+def : F<"t", "Alias for --types">, Alias<types>;
diff --git a/src/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/src/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
index 93d6322..d8bf8db 100644
--- a/src/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
@@ -9,69 +9,59 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Demangle/Demangle.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cstdlib>
 #include <iostream>
 
 using namespace llvm;
 
-enum Style {
-  Auto,  ///< auto-detect mangling
-  GNU,   ///< GNU
-  Lucid, ///< Lucid compiler (lcc)
-  ARM,
-  HP,    ///< HP compiler (xCC)
-  EDG,   ///< EDG compiler
-  GNUv3, ///< GNU C++ v3 ABI
-  Java,  ///< Java (gcj)
-  GNAT   ///< ADA compiler (gnat)
+namespace {
+enum ID {
+  OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  OPT_##ID,
+#include "Opts.inc"
+#undef OPTION
 };
-static cl::opt<Style>
-    Format("format", cl::desc("decoration style"),
-           cl::values(clEnumValN(Auto, "auto", "auto-detect style"),
-                      clEnumValN(GNU, "gnu", "GNU (itanium) style")),
-           cl::init(Auto));
-static cl::alias FormatShort("s", cl::desc("alias for --format"),
-                             cl::aliasopt(Format));
 
-static cl::opt<bool> StripUnderscore("strip-underscore",
-                                     cl::desc("strip the leading underscore"),
-                                     cl::init(false));
-static cl::alias StripUnderscoreShort("_",
-                                      cl::desc("alias for --strip-underscore"),
-                                      cl::aliasopt(StripUnderscore));
-static cl::opt<bool>
-    NoStripUnderscore("no-strip-underscore",
-                      cl::desc("do not strip the leading underscore"),
-                      cl::init(false));
-static cl::alias
-    NoStripUnderscoreShort("n", cl::desc("alias for --no-strip-underscore"),
-                           cl::aliasopt(NoStripUnderscore));
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#include "Opts.inc"
+#undef PREFIX
 
-static cl::opt<bool>
-    Types("types",
-          cl::desc("attempt to demangle types as well as function names"),
-          cl::init(false));
-static cl::alias TypesShort("t", cl::desc("alias for --types"),
-                            cl::aliasopt(Types));
+const opt::OptTable::Info InfoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  {                                                                            \
+      PREFIX,      NAME,      HELPTEXT,                                        \
+      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
+      PARAM,       FLAGS,     OPT_##GROUP,                                     \
+      OPT_##ALIAS, ALIASARGS, VALUES},
+#include "Opts.inc"
+#undef OPTION
+};
 
-static cl::list<std::string>
-Decorated(cl::Positional, cl::desc("<mangled>"), cl::ZeroOrMore);
+class CxxfiltOptTable : public opt::OptTable {
+public:
+  CxxfiltOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+};
+} // namespace
 
-static cl::extrahelp
-    HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
+static bool StripUnderscore;
+static bool Types;
 
-static bool shouldStripUnderscore() {
-  if (StripUnderscore)
-    return true;
-  if (NoStripUnderscore)
-    return false;
-  // If none of them are set, use the default value for platform.
-  // macho has symbols prefix with "_" so strip by default.
-  return Triple(sys::getProcessTriple()).isOSBinFormatMachO();
+static StringRef ToolName;
+
+static void error(const Twine &Message) {
+  WithColor::error(errs(), ToolName) << Message << '\n';
+  exit(1);
 }
 
 static std::string demangle(const std::string &Mangled) {
@@ -79,7 +69,7 @@
   std::string Prefix;
 
   const char *DecoratedStr = Mangled.c_str();
-  if (shouldStripUnderscore())
+  if (StripUnderscore)
     if (DecoratedStr[0] == '_')
       ++DecoratedStr;
   size_t DecoratedLength = strlen(DecoratedStr);
@@ -97,6 +87,11 @@
     Undecorated = itaniumDemangle(DecoratedStr + 6, nullptr, nullptr, &Status);
   }
 
+  if (!Undecorated &&
+      (DecoratedLength >= 2 && strncmp(DecoratedStr, "_R", 2) == 0)) {
+    Undecorated = rustDemangle(DecoratedStr, nullptr, nullptr, &Status);
+  }
+
   std::string Result(Undecorated ? Prefix + Undecorated : Mangled);
   free(Undecorated);
   return Result;
@@ -154,9 +149,37 @@
 
 int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
+  BumpPtrAllocator A;
+  StringSaver Saver(A);
+  CxxfiltOptTable Tbl;
+  ToolName = argv[0];
+  opt::InputArgList Args = Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver,
+                                         [&](StringRef Msg) { error(Msg); });
+  if (Args.hasArg(OPT_help)) {
+    Tbl.printHelp(outs(),
+                  (Twine(ToolName) + " [options] <mangled>").str().c_str(),
+                  "LLVM symbol undecoration tool");
+    // TODO Replace this with OptTable API once it adds extrahelp support.
+    outs() << "\nPass @FILE as argument to read options from FILE.\n";
+    return 0;
+  }
+  if (Args.hasArg(OPT_version)) {
+    outs() << ToolName << '\n';
+    cl::PrintVersionMessage();
+    return 0;
+  }
 
-  cl::ParseCommandLineOptions(argc, argv, "llvm symbol undecoration tool\n");
+  // The default value depends on the default triple. Mach-O has symbols
+  // prefixed with "_", so strip by default.
+  if (opt::Arg *A =
+          Args.getLastArg(OPT_strip_underscore, OPT_no_strip_underscore))
+    StripUnderscore = A->getOption().matches(OPT_strip_underscore);
+  else
+    StripUnderscore = Triple(sys::getProcessTriple()).isOSBinFormatMachO();
 
+  Types = Args.hasArg(OPT_types);
+
+  std::vector<std::string> Decorated = Args.getAllArgValues(OPT_INPUT);
   if (Decorated.empty())
     for (std::string Mangled; std::getline(std::cin, Mangled);)
       demangleLine(llvm::outs(), Mangled, true);
diff --git a/src/llvm-project/llvm/tools/llvm-cxxmap/llvm-cxxmap.cpp b/src/llvm-project/llvm/tools/llvm-cxxmap/llvm-cxxmap.cpp
index b53a636..1e18e37 100644
--- a/src/llvm-project/llvm/tools/llvm-cxxmap/llvm-cxxmap.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cxxmap/llvm-cxxmap.cpp
@@ -11,10 +11,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LineIterator.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -24,23 +25,33 @@
 
 using namespace llvm;
 
+cl::OptionCategory CXXMapCategory("CXX Map Options");
+
 cl::opt<std::string> OldSymbolFile(cl::Positional, cl::Required,
-                                   cl::desc("<symbol-file>"));
+                                   cl::desc("<symbol-file>"),
+                                   cl::cat(CXXMapCategory));
 cl::opt<std::string> NewSymbolFile(cl::Positional, cl::Required,
-                                   cl::desc("<symbol-file>"));
+                                   cl::desc("<symbol-file>"),
+                                   cl::cat(CXXMapCategory));
 cl::opt<std::string> RemappingFile("remapping-file", cl::Required,
-                                   cl::desc("Remapping file"));
-cl::alias RemappingFileA("r", cl::aliasopt(RemappingFile));
+                                   cl::desc("Remapping file"),
+                                   cl::cat(CXXMapCategory));
+cl::alias RemappingFileA("r", cl::aliasopt(RemappingFile),
+                         cl::cat(CXXMapCategory));
 cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
-                                    cl::init("-"), cl::desc("Output file"));
-cl::alias OutputFilenameA("o", cl::aliasopt(OutputFilename));
+                                    cl::init("-"), cl::desc("Output file"),
+                                    cl::cat(CXXMapCategory));
+cl::alias OutputFilenameA("o", cl::aliasopt(OutputFilename),
+                          cl::cat(CXXMapCategory));
 
 cl::opt<bool> WarnAmbiguous(
     "Wambiguous",
-    cl::desc("Warn on equivalent symbols in the output symbol list"));
+    cl::desc("Warn on equivalent symbols in the output symbol list"),
+    cl::cat(CXXMapCategory));
 cl::opt<bool> WarnIncomplete(
     "Wincomplete",
-    cl::desc("Warn on input symbols missing from output symbol list"));
+    cl::desc("Warn on input symbols missing from output symbol list"),
+    cl::cat(CXXMapCategory));
 
 static void warn(Twine Message, Twine Whence = "",
                  std::string Hint = "") {
@@ -130,6 +141,7 @@
 int main(int argc, const char *argv[]) {
   InitLLVM X(argc, argv);
 
+  cl::HideUnrelatedOptions({&CXXMapCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv, "LLVM C++ mangled name remapper\n");
 
   auto OldSymbolBufOrError = MemoryBuffer::getFileOrSTDIN(OldSymbolFile);
@@ -145,7 +157,7 @@
     exitWithErrorCode(RemappingBufOrError.getError(), RemappingFile);
 
   std::error_code EC;
-  raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_Text);
+  raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF);
   if (EC)
     exitWithErrorCode(EC, OutputFilename);
 
diff --git a/src/llvm-project/llvm/tools/llvm-diff/DiffConsumer.cpp b/src/llvm-project/llvm/tools/llvm-diff/DiffConsumer.cpp
index 6228ff2..a703f42 100644
--- a/src/llvm-project/llvm/tools/llvm-diff/DiffConsumer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-diff/DiffConsumer.cpp
@@ -17,34 +17,33 @@
 
 using namespace llvm;
 
-static void ComputeNumbering(Function *F, DenseMap<Value*,unsigned> &Numbering){
+static void ComputeNumbering(const Function *F,
+                             DenseMap<const Value *, unsigned> &Numbering) {
   unsigned IN = 0;
 
   // Arguments get the first numbers.
-  for (Function::arg_iterator
-         AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI)
-    if (!AI->hasName())
-      Numbering[&*AI] = IN++;
+  for (const auto &Arg : F->args())
+    if (!Arg.hasName())
+      Numbering[&Arg] = IN++;
 
   // Walk the basic blocks in order.
-  for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) {
-    if (!FI->hasName())
-      Numbering[&*FI] = IN++;
+  for (const auto &Func : *F) {
+    if (!Func.hasName())
+      Numbering[&Func] = IN++;
 
     // Walk the instructions in order.
-    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI)
+    for (const auto &BB : Func)
       // void instructions don't get numbers.
-      if (!BI->hasName() && !BI->getType()->isVoidTy())
-        Numbering[&*BI] = IN++;
+      if (!BB.hasName() && !BB.getType()->isVoidTy())
+        Numbering[&BB] = IN++;
   }
 
   assert(!Numbering.empty() && "asked for numbering but numbering was no-op");
 }
 
-
 void Consumer::anchor() { }
 
-void DiffConsumer::printValue(Value *V, bool isL) {
+void DiffConsumer::printValue(const Value *V, bool isL) {
   if (V->hasName()) {
     out << (isa<GlobalValue>(V) ? '@' : '%') << V->getName();
     return;
@@ -99,16 +98,16 @@
       // Extra newline between functions.
       if (Differences) out << "\n";
 
-      Function *L = cast<Function>(I->L);
-      Function *R = cast<Function>(I->R);
+      const Function *L = cast<Function>(I->L);
+      const Function *R = cast<Function>(I->R);
       if (L->getName() != R->getName())
         out << "in function " << L->getName()
             << " / " << R->getName() << ":\n";
       else
         out << "in function " << L->getName() << ":\n";
     } else if (isa<BasicBlock>(I->L)) {
-      BasicBlock *L = cast<BasicBlock>(I->L);
-      BasicBlock *R = cast<BasicBlock>(I->R);
+      const BasicBlock *L = cast<BasicBlock>(I->L);
+      const BasicBlock *R = cast<BasicBlock>(I->R);
       if (L->hasName() && R->hasName() && L->getName() == R->getName())
         out << "  in block %" << L->getName() << ":\n";
       else {
@@ -139,7 +138,7 @@
   return Differences;
 }
 
-void DiffConsumer::enterContext(Value *L, Value *R) {
+void DiffConsumer::enterContext(const Value *L, const Value *R) {
   contexts.push_back(DiffContext(L, R));
   Indent += 2;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-diff/DiffConsumer.h b/src/llvm-project/llvm/tools/llvm-diff/DiffConsumer.h
index 6cb8f2e..f7b2f24 100644
--- a/src/llvm-project/llvm/tools/llvm-diff/DiffConsumer.h
+++ b/src/llvm-project/llvm/tools/llvm-diff/DiffConsumer.h
@@ -34,7 +34,7 @@
     /// Right are IR "containers" of some sort which are being
     /// considered for structural equivalence: global variables,
     /// functions, blocks, instructions, etc.
-    virtual void enterContext(Value *Left, Value *Right) = 0;
+    virtual void enterContext(const Value *Left, const Value *Right) = 0;
 
     /// Record that a local context has been exited.
     virtual void exitContext() = 0;
@@ -55,14 +55,14 @@
   class DiffConsumer : public Consumer {
   private:
     struct DiffContext {
-      DiffContext(Value *L, Value *R)
-        : L(L), R(R), Differences(false), IsFunction(isa<Function>(L)) {}
-      Value *L;
-      Value *R;
+      DiffContext(const Value *L, const Value *R)
+          : L(L), R(R), Differences(false), IsFunction(isa<Function>(L)) {}
+      const Value *L;
+      const Value *R;
       bool Differences;
       bool IsFunction;
-      DenseMap<Value*,unsigned> LNumbering;
-      DenseMap<Value*,unsigned> RNumbering;
+      DenseMap<const Value *, unsigned> LNumbering;
+      DenseMap<const Value *, unsigned> RNumbering;
     };
 
     raw_ostream &out;
@@ -70,7 +70,7 @@
     bool Differences;
     unsigned Indent;
 
-    void printValue(Value *V, bool isL);
+    void printValue(const Value *V, bool isL);
     void header();
     void indent();
 
@@ -79,7 +79,7 @@
       : out(errs()), Differences(false), Indent(0) {}
 
     bool hadDifferences() const;
-    void enterContext(Value *L, Value *R) override;
+    void enterContext(const Value *L, const Value *R) override;
     void exitContext() override;
     void log(StringRef text) override;
     void logf(const LogBuilder &Log) override;
diff --git a/src/llvm-project/llvm/tools/llvm-diff/DiffLog.cpp b/src/llvm-project/llvm/tools/llvm-diff/DiffLog.cpp
index 6484197..d31a345 100644
--- a/src/llvm-project/llvm/tools/llvm-diff/DiffLog.cpp
+++ b/src/llvm-project/llvm/tools/llvm-diff/DiffLog.cpp
@@ -24,18 +24,18 @@
 StringRef LogBuilder::getFormat() const { return Format; }
 
 unsigned LogBuilder::getNumArguments() const { return Arguments.size(); }
-Value *LogBuilder::getArgument(unsigned I) const { return Arguments[I]; }
+const Value *LogBuilder::getArgument(unsigned I) const { return Arguments[I]; }
 
 DiffLogBuilder::~DiffLogBuilder() { consumer.logd(*this); }
 
-void DiffLogBuilder::addMatch(Instruction *L, Instruction *R) {
+void DiffLogBuilder::addMatch(const Instruction *L, const Instruction *R) {
   Diff.push_back(DiffRecord(L, R));
 }
-void DiffLogBuilder::addLeft(Instruction *L) {
+void DiffLogBuilder::addLeft(const Instruction *L) {
   // HACK: VS 2010 has a bug in the stdlib that requires this.
   Diff.push_back(DiffRecord(L, DiffRecord::second_type(nullptr)));
 }
-void DiffLogBuilder::addRight(Instruction *R) {
+void DiffLogBuilder::addRight(const Instruction *R) {
   // HACK: VS 2010 has a bug in the stdlib that requires this.
   Diff.push_back(DiffRecord(DiffRecord::first_type(nullptr), R));
 }
@@ -46,5 +46,9 @@
   return (Diff[I].first ? (Diff[I].second ? DC_match : DC_left)
                         : DC_right);
 }
-Instruction *DiffLogBuilder::getLeft(unsigned I) const { return Diff[I].first; }
-Instruction *DiffLogBuilder::getRight(unsigned I) const { return Diff[I].second; }
+const Instruction *DiffLogBuilder::getLeft(unsigned I) const {
+  return Diff[I].first;
+}
+const Instruction *DiffLogBuilder::getRight(unsigned I) const {
+  return Diff[I].second;
+}
diff --git a/src/llvm-project/llvm/tools/llvm-diff/DiffLog.h b/src/llvm-project/llvm/tools/llvm-diff/DiffLog.h
index 0c89524..d8b07b9 100644
--- a/src/llvm-project/llvm/tools/llvm-diff/DiffLog.h
+++ b/src/llvm-project/llvm/tools/llvm-diff/DiffLog.h
@@ -34,7 +34,7 @@
     /// might be initializing this format.
     StringRef Format;
 
-    SmallVector<Value*, 4> Arguments;
+    SmallVector<const Value *, 4> Arguments;
 
   public:
     LogBuilder(Consumer &c, StringRef Format) : consumer(&c), Format(Format) {}
@@ -44,7 +44,7 @@
       L.consumer = nullptr;
     }
 
-    LogBuilder &operator<<(Value *V) {
+    LogBuilder &operator<<(const Value *V) {
       Arguments.push_back(V);
       return *this;
     }
@@ -53,12 +53,12 @@
 
     StringRef getFormat() const;
     unsigned getNumArguments() const;
-    Value *getArgument(unsigned I) const;
+    const Value *getArgument(unsigned I) const;
   };
 
   /// A temporary-object class for building up diff messages.
   class DiffLogBuilder {
-    typedef std::pair<Instruction*,Instruction*> DiffRecord;
+    typedef std::pair<const Instruction *, const Instruction *> DiffRecord;
     SmallVector<DiffRecord, 20> Diff;
 
     Consumer &consumer;
@@ -67,15 +67,15 @@
     DiffLogBuilder(Consumer &c) : consumer(c) {}
     ~DiffLogBuilder();
 
-    void addMatch(Instruction *L, Instruction *R);
+    void addMatch(const Instruction *L, const Instruction *R);
     // HACK: VS 2010 has a bug in the stdlib that requires this.
-    void addLeft(Instruction *L);
-    void addRight(Instruction *R);
+    void addLeft(const Instruction *L);
+    void addRight(const Instruction *R);
 
     unsigned getNumLines() const;
     DiffChange getLineKind(unsigned I) const;
-    Instruction *getLeft(unsigned I) const;
-    Instruction *getRight(unsigned I) const;
+    const Instruction *getLeft(unsigned I) const;
+    const Instruction *getRight(unsigned I) const;
   };
 
 }
diff --git a/src/llvm-project/llvm/tools/llvm-diff/DifferenceEngine.cpp b/src/llvm-project/llvm/tools/llvm-diff/DifferenceEngine.cpp
index 64c0dc6..eb746cd 100644
--- a/src/llvm-project/llvm/tools/llvm-diff/DifferenceEngine.cpp
+++ b/src/llvm-project/llvm/tools/llvm-diff/DifferenceEngine.cpp
@@ -113,22 +113,29 @@
 class FunctionDifferenceEngine {
   DifferenceEngine &Engine;
 
+  // Some initializers may reference the variable we're currently checking. This
+  // can cause an infinite loop. The Saved[LR]HS ivars can be checked to prevent
+  // recursing.
+  const Value *SavedLHS;
+  const Value *SavedRHS;
+
   /// The current mapping from old local values to new local values.
-  DenseMap<Value*, Value*> Values;
+  DenseMap<const Value *, const Value *> Values;
 
   /// The current mapping from old blocks to new blocks.
-  DenseMap<BasicBlock*, BasicBlock*> Blocks;
+  DenseMap<const BasicBlock *, const BasicBlock *> Blocks;
 
-  DenseSet<std::pair<Value*, Value*> > TentativeValues;
+  DenseSet<std::pair<const Value *, const Value *>> TentativeValues;
 
-  unsigned getUnprocPredCount(BasicBlock *Block) const {
+  unsigned getUnprocPredCount(const BasicBlock *Block) const {
     unsigned Count = 0;
-    for (pred_iterator I = pred_begin(Block), E = pred_end(Block); I != E; ++I)
+    for (const_pred_iterator I = pred_begin(Block), E = pred_end(Block); I != E;
+         ++I)
       if (!Blocks.count(*I)) Count++;
     return Count;
   }
 
-  typedef std::pair<BasicBlock*, BasicBlock*> BlockPair;
+  typedef std::pair<const BasicBlock *, const BasicBlock *> BlockPair;
 
   /// A type which sorts a priority queue by the number of unprocessed
   /// predecessor blocks it has remaining.
@@ -138,7 +145,7 @@
     const FunctionDifferenceEngine &fde;
     explicit QueueSorter(const FunctionDifferenceEngine &fde) : fde(fde) {}
 
-    bool operator()(const BlockPair &Old, const BlockPair &New) {
+    bool operator()(BlockPair &Old, BlockPair &New) {
       return fde.getUnprocPredCount(Old.first)
            < fde.getUnprocPredCount(New.first);
     }
@@ -151,8 +158,8 @@
   /// if they haven't already been processed.
   ///
   /// Returns true if there was a problem unifying them.
-  bool tryUnify(BasicBlock *L, BasicBlock *R) {
-    BasicBlock *&Ref = Blocks[L];
+  bool tryUnify(const BasicBlock *L, const BasicBlock *R) {
+    const BasicBlock *&Ref = Blocks[L];
 
     if (Ref) {
       if (Ref == R) return false;
@@ -167,10 +174,10 @@
     Queue.insert(BlockPair(L, R));
     return false;
   }
-  
+
   /// Unifies two instructions, given that they're known not to have
   /// structural differences.
-  void unify(Instruction *L, Instruction *R) {
+  void unify(const Instruction *L, const Instruction *R) {
     DifferenceEngine::Context C(Engine, L, R);
 
     bool Result = diff(L, R, true, true);
@@ -187,15 +194,15 @@
     }
   }
 
-  void diff(BasicBlock *L, BasicBlock *R) {
+  void diff(const BasicBlock *L, const BasicBlock *R) {
     DifferenceEngine::Context C(Engine, L, R);
 
-    BasicBlock::iterator LI = L->begin(), LE = L->end();
-    BasicBlock::iterator RI = R->begin();
+    BasicBlock::const_iterator LI = L->begin(), LE = L->end();
+    BasicBlock::const_iterator RI = R->begin();
 
     do {
       assert(LI != LE && RI != R->end());
-      Instruction *LeftI = &*LI, *RightI = &*RI;
+      const Instruction *LeftI = &*LI, *RightI = &*RI;
 
       // If the instructions differ, start the more sophisticated diff
       // algorithm at the start of the block.
@@ -219,10 +226,11 @@
       unify(&*LI, &*RI);
   }
 
-  bool matchForBlockDiff(Instruction *L, Instruction *R);
-  void runBlockDiff(BasicBlock::iterator LI, BasicBlock::iterator RI);
+  bool matchForBlockDiff(const Instruction *L, const Instruction *R);
+  void runBlockDiff(BasicBlock::const_iterator LI,
+                    BasicBlock::const_iterator RI);
 
-  bool diffCallSites(CallBase &L, CallBase &R, bool Complain) {
+  bool diffCallSites(const CallBase &L, const CallBase &R, bool Complain) {
     // FIXME: call attributes
     if (!equivalentAsOperands(L.getCalledOperand(), R.getCalledOperand())) {
       if (Complain) Engine.log("called functions differ");
@@ -242,7 +250,8 @@
     return false;
   }
 
-  bool diff(Instruction *L, Instruction *R, bool Complain, bool TryUnify) {
+  bool diff(const Instruction *L, const Instruction *R, bool Complain,
+            bool TryUnify) {
     // FIXME: metadata (if Complain is set)
 
     // Different opcodes always imply different operations.
@@ -273,8 +282,8 @@
 
     // Terminators.
     } else if (isa<InvokeInst>(L)) {
-      InvokeInst &LI = cast<InvokeInst>(*L);
-      InvokeInst &RI = cast<InvokeInst>(*R);
+      const InvokeInst &LI = cast<InvokeInst>(*L);
+      const InvokeInst &RI = cast<InvokeInst>(*R);
       if (diffCallSites(LI, RI, Complain))
         return true;
 
@@ -284,9 +293,30 @@
       }
       return false;
 
+    } else if (isa<CallBrInst>(L)) {
+      const CallBrInst &LI = cast<CallBrInst>(*L);
+      const CallBrInst &RI = cast<CallBrInst>(*R);
+      if (LI.getNumIndirectDests() != RI.getNumIndirectDests()) {
+        if (Complain)
+          Engine.log("callbr # of indirect destinations differ");
+        return true;
+      }
+
+      // Perform the "try unify" step so that we can equate the indirect
+      // destinations before checking the call site.
+      for (unsigned I = 0; I < LI.getNumIndirectDests(); I++)
+        tryUnify(LI.getIndirectDest(I), RI.getIndirectDest(I));
+
+      if (diffCallSites(LI, RI, Complain))
+        return true;
+
+      if (TryUnify)
+        tryUnify(LI.getDefaultDest(), RI.getDefaultDest());
+      return false;
+
     } else if (isa<BranchInst>(L)) {
-      BranchInst *LI = cast<BranchInst>(L);
-      BranchInst *RI = cast<BranchInst>(R);
+      const BranchInst *LI = cast<BranchInst>(L);
+      const BranchInst *RI = cast<BranchInst>(R);
       if (LI->isConditional() != RI->isConditional()) {
         if (Complain) Engine.log("branch conditionality differs");
         return true;
@@ -303,8 +333,8 @@
       return false;
 
     } else if (isa<IndirectBrInst>(L)) {
-      IndirectBrInst *LI = cast<IndirectBrInst>(L);
-      IndirectBrInst *RI = cast<IndirectBrInst>(R);
+      const IndirectBrInst *LI = cast<IndirectBrInst>(L);
+      const IndirectBrInst *RI = cast<IndirectBrInst>(R);
       if (LI->getNumDestinations() != RI->getNumDestinations()) {
         if (Complain) Engine.log("indirectbr # of destinations differ");
         return true;
@@ -323,8 +353,8 @@
       return false;
 
     } else if (isa<SwitchInst>(L)) {
-      SwitchInst *LI = cast<SwitchInst>(L);
-      SwitchInst *RI = cast<SwitchInst>(R);
+      const SwitchInst *LI = cast<SwitchInst>(L);
+      const SwitchInst *RI = cast<SwitchInst>(R);
       if (!equivalentAsOperands(LI->getCondition(), RI->getCondition())) {
         if (Complain) Engine.log("switch conditions differ");
         return true;
@@ -333,13 +363,13 @@
 
       bool Difference = false;
 
-      DenseMap<ConstantInt*,BasicBlock*> LCases;
+      DenseMap<const ConstantInt *, const BasicBlock *> LCases;
       for (auto Case : LI->cases())
         LCases[Case.getCaseValue()] = Case.getCaseSuccessor();
 
       for (auto Case : RI->cases()) {
-        ConstantInt *CaseValue = Case.getCaseValue();
-        BasicBlock *LCase = LCases[CaseValue];
+        const ConstantInt *CaseValue = Case.getCaseValue();
+        const BasicBlock *LCase = LCases[CaseValue];
         if (LCase) {
           if (TryUnify)
             tryUnify(LCase, Case.getCaseSuccessor());
@@ -351,8 +381,10 @@
         }
       }
       if (!Difference)
-        for (DenseMap<ConstantInt*,BasicBlock*>::iterator
-               I = LCases.begin(), E = LCases.end(); I != E; ++I) {
+        for (DenseMap<const ConstantInt *, const BasicBlock *>::iterator
+                 I = LCases.begin(),
+                 E = LCases.end();
+             I != E; ++I) {
           if (Complain)
             Engine.logf("left switch has extra case %l") << I->first;
           Difference = true;
@@ -378,14 +410,15 @@
     return false;
   }
 
-  bool equivalentAsOperands(Constant *L, Constant *R) {
+public:
+  bool equivalentAsOperands(const Constant *L, const Constant *R) {
     // Use equality as a preliminary filter.
     if (L == R)
       return true;
 
     if (L->getValueID() != R->getValueID())
       return false;
-    
+
     // Ask the engine about global values.
     if (isa<GlobalValue>(L))
       return Engine.equivalentAsOperands(cast<GlobalValue>(L),
@@ -409,8 +442,8 @@
 
     // If L and R are ConstantVectors, compare each element
     if (isa<ConstantVector>(L)) {
-      ConstantVector *CVL = cast<ConstantVector>(L);
-      ConstantVector *CVR = cast<ConstantVector>(R);
+      const ConstantVector *CVL = cast<ConstantVector>(L);
+      const ConstantVector *CVR = cast<ConstantVector>(R);
       if (CVL->getType()->getNumElements() != CVR->getType()->getNumElements())
         return false;
       for (unsigned i = 0; i < CVL->getType()->getNumElements(); i++) {
@@ -420,12 +453,68 @@
       return true;
     }
 
+    // If L and R are ConstantArrays, compare the element count and types.
+    if (isa<ConstantArray>(L)) {
+      const ConstantArray *CAL = cast<ConstantArray>(L);
+      const ConstantArray *CAR = cast<ConstantArray>(R);
+      // Sometimes a type may be equivalent, but not uniquified---e.g. it may
+      // contain a GEP instruction. Do a deeper comparison of the types.
+      if (CAL->getType()->getNumElements() != CAR->getType()->getNumElements())
+        return false;
+
+      for (unsigned I = 0; I < CAL->getType()->getNumElements(); ++I) {
+        if (!equivalentAsOperands(CAL->getAggregateElement(I),
+                                  CAR->getAggregateElement(I)))
+          return false;
+      }
+
+      return true;
+    }
+
+    // If L and R are ConstantStructs, compare each field and type.
+    if (isa<ConstantStruct>(L)) {
+      const ConstantStruct *CSL = cast<ConstantStruct>(L);
+      const ConstantStruct *CSR = cast<ConstantStruct>(R);
+
+      const StructType *LTy = cast<StructType>(CSL->getType());
+      const StructType *RTy = cast<StructType>(CSR->getType());
+
+      // The StructTypes should have the same attributes. Don't use
+      // isLayoutIdentical(), because that just checks the element pointers,
+      // which may not work here.
+      if (LTy->getNumElements() != RTy->getNumElements() ||
+          LTy->isPacked() != RTy->isPacked())
+        return false;
+
+      for (unsigned I = 0; I < LTy->getNumElements(); I++) {
+        const Value *LAgg = CSL->getAggregateElement(I);
+        const Value *RAgg = CSR->getAggregateElement(I);
+
+        if (LAgg == SavedLHS || RAgg == SavedRHS) {
+          if (LAgg != SavedLHS || RAgg != SavedRHS)
+            // If the left and right operands aren't both re-analyzing the
+            // variable, then the initialiers don't match, so report "false".
+            // Otherwise, we skip these operands..
+            return false;
+
+          continue;
+        }
+
+        if (!equivalentAsOperands(LAgg, RAgg)) {
+          return false;
+        }
+      }
+
+      return true;
+    }
+
     return false;
   }
 
-  bool equivalentAsOperands(ConstantExpr *L, ConstantExpr *R) {
+  bool equivalentAsOperands(const ConstantExpr *L, const ConstantExpr *R) {
     if (L == R)
       return true;
+
     if (L->getOpcode() != R->getOpcode())
       return false;
 
@@ -447,14 +536,28 @@
     if (L->getNumOperands() != R->getNumOperands())
       return false;
 
-    for (unsigned I = 0, E = L->getNumOperands(); I != E; ++I)
-      if (!equivalentAsOperands(L->getOperand(I), R->getOperand(I)))
+    for (unsigned I = 0, E = L->getNumOperands(); I != E; ++I) {
+      const auto *LOp = L->getOperand(I);
+      const auto *ROp = R->getOperand(I);
+
+      if (LOp == SavedLHS || ROp == SavedRHS) {
+        if (LOp != SavedLHS || ROp != SavedRHS)
+          // If the left and right operands aren't both re-analyzing the
+          // variable, then the initialiers don't match, so report "false".
+          // Otherwise, we skip these operands..
+          return false;
+
+        continue;
+      }
+
+      if (!equivalentAsOperands(LOp, ROp))
         return false;
+    }
 
     return true;
   }
 
-  bool equivalentAsOperands(Value *L, Value *R) {
+  bool equivalentAsOperands(const Value *L, const Value *R) {
     // Fall out if the values have different kind.
     // This possibly shouldn't take priority over oracles.
     if (L->getValueID() != R->getValueID())
@@ -483,17 +586,19 @@
   FunctionDifferenceEngine *this_() { return this; }
 
 public:
-  FunctionDifferenceEngine(DifferenceEngine &Engine) :
-    Engine(Engine), Queue(QueueSorter(*this_())) {}
+  FunctionDifferenceEngine(DifferenceEngine &Engine,
+                           const Value *SavedLHS = nullptr,
+                           const Value *SavedRHS = nullptr)
+      : Engine(Engine), SavedLHS(SavedLHS), SavedRHS(SavedRHS),
+        Queue(QueueSorter(*this_())) {}
 
-  void diff(Function *L, Function *R) {
+  void diff(const Function *L, const Function *R) {
     if (L->arg_size() != R->arg_size())
       Engine.log("different argument counts");
 
     // Map the arguments.
-    for (Function::arg_iterator
-           LI = L->arg_begin(), LE = L->arg_end(),
-           RI = R->arg_begin(), RE = R->arg_end();
+    for (Function::const_arg_iterator LI = L->arg_begin(), LE = L->arg_end(),
+                                      RI = R->arg_begin(), RE = R->arg_end();
          LI != LE && RI != RE; ++LI, ++RI)
       Values[&*LI] = &*RI;
 
@@ -509,15 +614,15 @@
   llvm::SmallVector<char, 8> Path; // actually of DifferenceEngine::DiffChange
 };
 
-bool FunctionDifferenceEngine::matchForBlockDiff(Instruction *L,
-                                                 Instruction *R) {
+bool FunctionDifferenceEngine::matchForBlockDiff(const Instruction *L,
+                                                 const Instruction *R) {
   return !diff(L, R, false, false);
 }
 
-void FunctionDifferenceEngine::runBlockDiff(BasicBlock::iterator LStart,
-                                            BasicBlock::iterator RStart) {
-  BasicBlock::iterator LE = LStart->getParent()->end();
-  BasicBlock::iterator RE = RStart->getParent()->end();
+void FunctionDifferenceEngine::runBlockDiff(BasicBlock::const_iterator LStart,
+                                            BasicBlock::const_iterator RStart) {
+  BasicBlock::const_iterator LE = LStart->getParent()->end();
+  BasicBlock::const_iterator RE = RStart->getParent()->end();
 
   unsigned NL = std::distance(LStart, LE);
 
@@ -540,14 +645,14 @@
       Cur[I].Path.push_back(DC_left);
   }
 
-  for (BasicBlock::iterator RI = RStart; RI != RE; ++RI) {
+  for (BasicBlock::const_iterator RI = RStart; RI != RE; ++RI) {
     // Initialize the first row.
     Next[0] = Cur[0];
     Next[0].Cost += RightCost;
     Next[0].Path.push_back(DC_right);
 
     unsigned Index = 1;
-    for (BasicBlock::iterator LI = LStart; LI != LE; ++LI, ++Index) {
+    for (BasicBlock::const_iterator LI = LStart; LI != LE; ++LI, ++Index) {
       if (matchForBlockDiff(&*LI, &*RI)) {
         Next[Index] = Cur[Index-1];
         Next[Index].Cost += MatchCost;
@@ -572,7 +677,7 @@
   TentativeValues.clear();
 
   SmallVectorImpl<char> &Path = Cur[NL].Path;
-  BasicBlock::iterator LI = LStart, RI = RStart;
+  BasicBlock::const_iterator LI = LStart, RI = RStart;
 
   DiffLogBuilder Diff(Engine.getConsumer());
 
@@ -595,7 +700,7 @@
     case DC_match:
       assert(LI != LE && RI != RE);
       {
-        Instruction *L = &*LI, *R = &*RI;
+        const Instruction *L = &*LI, *R = &*RI;
         unify(L, R);
         Diff.addMatch(L, R);
       }
@@ -628,16 +733,16 @@
   // If the terminators have different kinds, but one is an invoke and the
   // other is an unconditional branch immediately following a call, unify
   // the results and the destinations.
-  Instruction *LTerm = LStart->getParent()->getTerminator();
-  Instruction *RTerm = RStart->getParent()->getTerminator();
+  const Instruction *LTerm = LStart->getParent()->getTerminator();
+  const Instruction *RTerm = RStart->getParent()->getTerminator();
   if (isa<BranchInst>(LTerm) && isa<InvokeInst>(RTerm)) {
     if (cast<BranchInst>(LTerm)->isConditional()) return;
-    BasicBlock::iterator I = LTerm->getIterator();
+    BasicBlock::const_iterator I = LTerm->getIterator();
     if (I == LStart->getParent()->begin()) return;
     --I;
     if (!isa<CallInst>(*I)) return;
-    CallInst *LCall = cast<CallInst>(&*I);
-    InvokeInst *RInvoke = cast<InvokeInst>(RTerm);
+    const CallInst *LCall = cast<CallInst>(&*I);
+    const InvokeInst *RInvoke = cast<InvokeInst>(RTerm);
     if (!equivalentAsOperands(LCall->getCalledOperand(),
                               RInvoke->getCalledOperand()))
       return;
@@ -646,12 +751,12 @@
     tryUnify(LTerm->getSuccessor(0), RInvoke->getNormalDest());
   } else if (isa<InvokeInst>(LTerm) && isa<BranchInst>(RTerm)) {
     if (cast<BranchInst>(RTerm)->isConditional()) return;
-    BasicBlock::iterator I = RTerm->getIterator();
+    BasicBlock::const_iterator I = RTerm->getIterator();
     if (I == RStart->getParent()->begin()) return;
     --I;
     if (!isa<CallInst>(*I)) return;
-    CallInst *RCall = cast<CallInst>(I);
-    InvokeInst *LInvoke = cast<InvokeInst>(LTerm);
+    const CallInst *RCall = cast<CallInst>(I);
+    const InvokeInst *LInvoke = cast<InvokeInst>(LTerm);
     if (!equivalentAsOperands(LInvoke->getCalledOperand(),
                               RCall->getCalledOperand()))
       return;
@@ -660,12 +765,11 @@
     tryUnify(LInvoke->getNormalDest(), RTerm->getSuccessor(0));
   }
 }
-
 }
 
 void DifferenceEngine::Oracle::anchor() { }
 
-void DifferenceEngine::diff(Function *L, Function *R) {
+void DifferenceEngine::diff(const Function *L, const Function *R) {
   Context C(*this, L, R);
 
   // FIXME: types
@@ -683,15 +787,15 @@
     FunctionDifferenceEngine(*this).diff(L, R);
 }
 
-void DifferenceEngine::diff(Module *L, Module *R) {
+void DifferenceEngine::diff(const Module *L, const Module *R) {
   StringSet<> LNames;
-  SmallVector<std::pair<Function*,Function*>, 20> Queue;
+  SmallVector<std::pair<const Function *, const Function *>, 20> Queue;
 
   unsigned LeftAnonCount = 0;
   unsigned RightAnonCount = 0;
 
-  for (Module::iterator I = L->begin(), E = L->end(); I != E; ++I) {
-    Function *LFn = &*I;
+  for (Module::const_iterator I = L->begin(), E = L->end(); I != E; ++I) {
+    const Function *LFn = &*I;
     StringRef Name = LFn->getName();
     if (Name.empty()) {
       ++LeftAnonCount;
@@ -706,8 +810,8 @@
       logf("function %l exists only in left module") << LFn;
   }
 
-  for (Module::iterator I = R->begin(), E = R->end(); I != E; ++I) {
-    Function *RFn = &*I;
+  for (Module::const_iterator I = R->begin(), E = R->end(); I != E; ++I) {
+    const Function *RFn = &*I;
     StringRef Name = RFn->getName();
     if (Name.empty()) {
       ++RightAnonCount;
@@ -718,7 +822,6 @@
       logf("function %r exists only in right module") << RFn;
   }
 
-
   if (LeftAnonCount != 0 || RightAnonCount != 0) {
     SmallString<32> Tmp;
     logf(("not comparing " + Twine(LeftAnonCount) +
@@ -727,20 +830,24 @@
              .toStringRef(Tmp));
   }
 
-  for (SmallVectorImpl<std::pair<Function*,Function*> >::iterator
-         I = Queue.begin(), E = Queue.end(); I != E; ++I)
+  for (SmallVectorImpl<std::pair<const Function *, const Function *>>::iterator
+           I = Queue.begin(),
+           E = Queue.end();
+       I != E; ++I)
     diff(I->first, I->second);
 }
 
-bool DifferenceEngine::equivalentAsOperands(GlobalValue *L, GlobalValue *R) {
+bool DifferenceEngine::equivalentAsOperands(const GlobalValue *L,
+                                            const GlobalValue *R) {
   if (globalValueOracle) return (*globalValueOracle)(L, R);
 
   if (isa<GlobalVariable>(L) && isa<GlobalVariable>(R)) {
-    GlobalVariable *GVL = cast<GlobalVariable>(L);
-    GlobalVariable *GVR = cast<GlobalVariable>(R);
+    const GlobalVariable *GVL = cast<GlobalVariable>(L);
+    const GlobalVariable *GVR = cast<GlobalVariable>(R);
     if (GVL->hasLocalLinkage() && GVL->hasUniqueInitializer() &&
         GVR->hasLocalLinkage() && GVR->hasUniqueInitializer())
-      return GVL->getInitializer() == GVR->getInitializer();
+      return FunctionDifferenceEngine(*this, GVL, GVR)
+          .equivalentAsOperands(GVL->getInitializer(), GVR->getInitializer());
   }
 
   return L->getName() == R->getName();
diff --git a/src/llvm-project/llvm/tools/llvm-diff/DifferenceEngine.h b/src/llvm-project/llvm/tools/llvm-diff/DifferenceEngine.h
index da1b652..436a355 100644
--- a/src/llvm-project/llvm/tools/llvm-diff/DifferenceEngine.h
+++ b/src/llvm-project/llvm/tools/llvm-diff/DifferenceEngine.h
@@ -33,7 +33,8 @@
   public:
     /// A RAII object for recording the current context.
     struct Context {
-      Context(DifferenceEngine &Engine, Value *L, Value *R) : Engine(Engine) {
+      Context(DifferenceEngine &Engine, const Value *L, const Value *R)
+          : Engine(Engine) {
         Engine.consumer.enterContext(L, R);
       }
 
@@ -50,7 +51,7 @@
     class Oracle {
       virtual void anchor();
     public:
-      virtual bool operator()(Value *L, Value *R) = 0;
+      virtual bool operator()(const Value *L, const Value *R) = 0;
 
     protected:
       virtual ~Oracle() {}
@@ -59,8 +60,8 @@
     DifferenceEngine(Consumer &consumer)
       : consumer(consumer), globalValueOracle(nullptr) {}
 
-    void diff(Module *L, Module *R);
-    void diff(Function *L, Function *R);
+    void diff(const Module *L, const Module *R);
+    void diff(const Function *L, const Function *R);
     void log(StringRef text) {
       consumer.log(text);
     }
@@ -78,7 +79,7 @@
     }
 
     /// Determines whether two global values are equivalent.
-    bool equivalentAsOperands(GlobalValue *L, GlobalValue *R);
+    bool equivalentAsOperands(const GlobalValue *L, const GlobalValue *R);
 
   private:
     Consumer &consumer;
diff --git a/src/llvm-project/llvm/tools/llvm-diff/llvm-diff.cpp b/src/llvm-project/llvm/tools/llvm-diff/llvm-diff.cpp
index aaf7989..8a11179 100644
--- a/src/llvm-project/llvm/tools/llvm-diff/llvm-diff.cpp
+++ b/src/llvm-project/llvm/tools/llvm-diff/llvm-diff.cpp
@@ -55,16 +55,20 @@
     errs() << "No function named @" << Name << " in right module\n";
 }
 
+cl::OptionCategory DiffCategory("Diff Options");
+
 static cl::opt<std::string> LeftFilename(cl::Positional,
-                                         cl::desc("<first file>"),
-                                         cl::Required);
+                                         cl::desc("<first file>"), cl::Required,
+                                         cl::cat(DiffCategory));
 static cl::opt<std::string> RightFilename(cl::Positional,
                                           cl::desc("<second file>"),
-                                          cl::Required);
+                                          cl::Required, cl::cat(DiffCategory));
 static cl::list<std::string> GlobalsToCompare(cl::Positional,
-                                              cl::desc("<globals to compare>"));
+                                              cl::desc("<globals to compare>"),
+                                              cl::cat(DiffCategory));
 
 int main(int argc, char **argv) {
+  cl::HideUnrelatedOptions({&DiffCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv);
 
   LLVMContext Context;
diff --git a/src/llvm-project/llvm/tools/llvm-dis/llvm-dis.cpp b/src/llvm-project/llvm/tools/llvm-dis/llvm-dis.cpp
index 5d60946..62d165f 100644
--- a/src/llvm-project/llvm/tools/llvm-dis/llvm-dis.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dis/llvm-dis.cpp
@@ -35,37 +35,44 @@
 #include <system_error>
 using namespace llvm;
 
-static cl::opt<std::string>
-InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
+static cl::OptionCategory DisCategory("Disassembler Options");
 
-static cl::opt<std::string>
-OutputFilename("o", cl::desc("Override output filename"),
-               cl::value_desc("filename"));
+static cl::list<std::string> InputFilenames(cl::Positional, cl::ZeroOrMore,
+                                            cl::desc("[input bitcode]..."),
+                                            cl::cat(DisCategory));
 
-static cl::opt<bool>
-Force("f", cl::desc("Enable binary output on terminals"));
+static cl::opt<std::string> OutputFilename("o",
+                                           cl::desc("Override output filename"),
+                                           cl::value_desc("filename"),
+                                           cl::cat(DisCategory));
 
-static cl::opt<bool>
-DontPrint("disable-output", cl::desc("Don't output the .ll file"), cl::Hidden);
+static cl::opt<bool> Force("f", cl::desc("Enable binary output on terminals"),
+                           cl::cat(DisCategory));
+
+static cl::opt<bool> DontPrint("disable-output",
+                               cl::desc("Don't output the .ll file"),
+                               cl::Hidden, cl::cat(DisCategory));
 
 static cl::opt<bool>
     SetImporting("set-importing",
                  cl::desc("Set lazy loading to pretend to import a module"),
-                 cl::Hidden);
+                 cl::Hidden, cl::cat(DisCategory));
 
 static cl::opt<bool>
     ShowAnnotations("show-annotations",
-                    cl::desc("Add informational comments to the .ll file"));
+                    cl::desc("Add informational comments to the .ll file"),
+                    cl::cat(DisCategory));
 
 static cl::opt<bool> PreserveAssemblyUseListOrder(
     "preserve-ll-uselistorder",
     cl::desc("Preserve use-list order when writing LLVM assembly."),
-    cl::init(false), cl::Hidden);
+    cl::init(false), cl::Hidden, cl::cat(DisCategory));
 
 static cl::opt<bool>
     MaterializeMetadata("materialize-metadata",
                         cl::desc("Load module without materializing metadata, "
-                                 "then materialize only the metadata"));
+                                 "then materialize only the metadata"),
+                        cl::cat(DisCategory));
 
 namespace {
 
@@ -151,77 +158,89 @@
 
   ExitOnErr.setBanner(std::string(argv[0]) + ": error: ");
 
+  cl::HideUnrelatedOptions({&DisCategory, &getColorCategory()});
+  cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");
+
   LLVMContext Context;
   Context.setDiagnosticHandler(
       std::make_unique<LLVMDisDiagnosticHandler>(argv[0]));
-  cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");
 
-  std::unique_ptr<MemoryBuffer> MB =
-      ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(InputFilename)));
+  if (InputFilenames.size() < 1) {
+    InputFilenames.push_back("-");
+  } else if (InputFilenames.size() > 1 && !OutputFilename.empty()) {
+    errs()
+        << "error: output file name cannot be set for multiple input files\n";
+    return 1;
+  }
 
-  BitcodeFileContents IF = ExitOnErr(llvm::getBitcodeFileContents(*MB));
+  for (std::string InputFilename : InputFilenames) {
+    std::unique_ptr<MemoryBuffer> MB = ExitOnErr(
+        errorOrToExpected(MemoryBuffer::getFileOrSTDIN(InputFilename)));
 
-  const size_t N = IF.Mods.size();
+    BitcodeFileContents IF = ExitOnErr(llvm::getBitcodeFileContents(*MB));
 
-  if (OutputFilename == "-" && N > 1)
+    const size_t N = IF.Mods.size();
+
+    if (OutputFilename == "-" && N > 1)
       errs() << "only single module bitcode files can be written to stdout\n";
 
-  for (size_t i = 0; i < N; ++i) {
-    BitcodeModule MB = IF.Mods[i];
-    std::unique_ptr<Module> M = ExitOnErr(MB.getLazyModule(Context, MaterializeMetadata,
-                                          SetImporting));
-    if (MaterializeMetadata)
-      ExitOnErr(M->materializeMetadata());
-    else
-      ExitOnErr(M->materializeAll());
+    for (size_t I = 0; I < N; ++I) {
+      BitcodeModule MB = IF.Mods[I];
+      std::unique_ptr<Module> M = ExitOnErr(
+          MB.getLazyModule(Context, MaterializeMetadata, SetImporting));
+      if (MaterializeMetadata)
+        ExitOnErr(M->materializeMetadata());
+      else
+        ExitOnErr(M->materializeAll());
 
-    BitcodeLTOInfo LTOInfo = ExitOnErr(MB.getLTOInfo());
-    std::unique_ptr<ModuleSummaryIndex> Index;
-    if (LTOInfo.HasSummary)
-      Index = ExitOnErr(MB.getSummary());
+      BitcodeLTOInfo LTOInfo = ExitOnErr(MB.getLTOInfo());
+      std::unique_ptr<ModuleSummaryIndex> Index;
+      if (LTOInfo.HasSummary)
+        Index = ExitOnErr(MB.getSummary());
 
-    std::string FinalFilename(OutputFilename);
+      std::string FinalFilename(OutputFilename);
 
-    // Just use stdout.  We won't actually print anything on it.
-    if (DontPrint)
-      FinalFilename = "-";
-
-    if (FinalFilename.empty()) { // Unspecified output, infer it.
-      if (InputFilename == "-") {
+      // Just use stdout.  We won't actually print anything on it.
+      if (DontPrint)
         FinalFilename = "-";
+
+      if (FinalFilename.empty()) { // Unspecified output, infer it.
+        if (InputFilename == "-") {
+          FinalFilename = "-";
+        } else {
+          StringRef IFN = InputFilename;
+          FinalFilename = (IFN.endswith(".bc") ? IFN.drop_back(3) : IFN).str();
+          if (N > 1)
+            FinalFilename += std::string(".") + std::to_string(I);
+          FinalFilename += ".ll";
+        }
       } else {
-        StringRef IFN = InputFilename;
-        FinalFilename = (IFN.endswith(".bc") ? IFN.drop_back(3) : IFN).str();
         if (N > 1)
-          FinalFilename += std::string(".") + std::to_string(i);
-        FinalFilename += ".ll";
+          FinalFilename += std::string(".") + std::to_string(I);
       }
-    } else {
-      if (N > 1)
-        FinalFilename += std::string(".") + std::to_string(i);
+
+      std::error_code EC;
+      std::unique_ptr<ToolOutputFile> Out(
+          new ToolOutputFile(FinalFilename, EC, sys::fs::OF_TextWithCRLF));
+      if (EC) {
+        errs() << EC.message() << '\n';
+        return 1;
+      }
+
+      std::unique_ptr<AssemblyAnnotationWriter> Annotator;
+      if (ShowAnnotations)
+        Annotator.reset(new CommentWriter());
+
+      // All that llvm-dis does is write the assembly to a file.
+      if (!DontPrint) {
+        M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder);
+        if (Index)
+          Index->print(Out->os());
+      }
+
+      // Declare success.
+      Out->keep();
     }
-
-    std::error_code EC;
-    std::unique_ptr<ToolOutputFile> Out(
-        new ToolOutputFile(FinalFilename, EC, sys::fs::OF_Text));
-    if (EC) {
-      errs() << EC.message() << '\n';
-      return 1;
-    }
-
-    std::unique_ptr<AssemblyAnnotationWriter> Annotator;
-    if (ShowAnnotations)
-      Annotator.reset(new CommentWriter());
-
-    // All that llvm-dis does is write the assembly to a file.
-    if (!DontPrint) {
-      M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder);
-      if (Index)
-        Index->print(Out->os());
-    }
-
-    // Declare success.
-    Out->keep();
   }
 
   return 0;
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfdump/SectionSizes.cpp b/src/llvm-project/llvm/tools/llvm-dwarfdump/SectionSizes.cpp
index 8c456d5..731bf05 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfdump/SectionSizes.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwarfdump/SectionSizes.cpp
@@ -18,10 +18,8 @@
                                  const StringRef SectionNameTitle) {
   // The minimum column width should be the size of "SECTION".
   size_t Width = SectionNameTitle.size();
-  for (const auto &DebugSec : Sizes.DebugSectionSizes) {
-    StringRef SectionName = DebugSec.getKey();
-    Width = std::max(Width, SectionName.size());
-  }
+  for (const auto &It : Sizes.DebugSectionSizes)
+    Width = std::max(Width, It.first.size());
   return Width;
 }
 
@@ -29,8 +27,8 @@
                                  const StringRef SectionSizeTitle) {
   // The minimum column width should be the size of the column title.
   size_t Width = SectionSizeTitle.size();
-  for (const auto &DebugSec : Sizes.DebugSectionSizes) {
-    size_t NumWidth = std::to_string(DebugSec.getValue()).size();
+  for (const auto &It : Sizes.DebugSectionSizes) {
+    size_t NumWidth = std::to_string(It.second).size();
     Width = std::max(Width, NumWidth);
   }
   return Width;
@@ -59,13 +57,13 @@
     OS << "-";
   OS << '\n';
 
-  for (const auto &DebugSec : Sizes.DebugSectionSizes) {
-    OS << left_justify(DebugSec.getKey(), NameColWidth) << "  ";
+  for (const auto &It : Sizes.DebugSectionSizes) {
+    OS << left_justify(It.first, NameColWidth) << "  ";
 
-    auto NumBytes = std::to_string(DebugSec.getValue());
+    std::string NumBytes = std::to_string(It.second);
     OS << right_justify(NumBytes, SizeColWidth) << " ("
-       << format("%0.2f", DebugSec.getValue() /
-                              static_cast<double>(Sizes.TotalObjectSize) * 100)
+       << format("%0.2f",
+                 It.second / static_cast<double>(Sizes.TotalObjectSize) * 100)
        << "%)\n";
   }
 
@@ -95,11 +93,11 @@
     LLVM_DEBUG(dbgs() << SectionName.str() << ": " << Section.getSize()
                       << '\n');
 
-    if (!Section.isDebugSection(SectionName))
+    if (!Section.isDebugSection())
       continue;
 
     Sizes.TotalDebugSectionsSize += Section.getSize();
-    Sizes.DebugSectionSizes[SectionName] += Section.getSize();
+    Sizes.DebugSectionSizes[std::string(SectionName)] += Section.getSize();
   }
 }
 
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp b/src/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp
index 82da06e..19a971a 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp
@@ -8,9 +8,7 @@
 
 #include "llvm-dwarfdump.h"
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSet.h"
-#include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
 #include "llvm/Object/ObjectFile.h"
@@ -21,13 +19,23 @@
 using namespace llvm::dwarfdump;
 using namespace llvm::object;
 
+namespace {
 /// This represents the number of categories of debug location coverage being
 /// calculated. The first category is the number of variables with 0% location
 /// coverage, but the last category is the number of variables with 100%
 /// location coverage.
 constexpr int NumOfCoverageCategories = 12;
 
-namespace {
+/// This is used for zero location coverage bucket.
+constexpr unsigned ZeroCoverageBucket = 0;
+
+/// This represents variables DIE offsets.
+using AbstractOriginVarsTy = llvm::SmallVector<uint64_t>;
+/// This maps function DIE offset to its variables.
+using AbstractOriginVarsTyMap = llvm::DenseMap<uint64_t, AbstractOriginVarsTy>;
+/// This represents function DIE offsets containing an abstract_origin.
+using FunctionsWithAbstractOriginTy = llvm::SmallVector<uint64_t>;
+
 /// Holds statistics for one function (or other entity that has a PC range and
 /// contains variables, such as a compile unit).
 struct PerFunctionStats {
@@ -164,12 +172,14 @@
   };
 
   unsigned CoverageBucket = getCoverageBucket();
+
   VarParamLocStats[CoverageBucket]++;
   if (IsParam)
     ParamLocStats[CoverageBucket]++;
   else if (IsLocalVar)
     LocalVarLocStats[CoverageBucket]++;
 }
+
 /// Construct an identifier for a given DIE from its Prefix, Name, DeclFileName
 /// and DeclLine. The identifier aims to be unique for any unique entities,
 /// but keeping the same among different instances of the same entity.
@@ -210,12 +220,18 @@
 }
 
 /// Collect debug info quality metrics for one DIE.
-static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
-                               std::string VarPrefix, uint64_t BytesInScope,
-                               uint32_t InlineDepth,
+static void collectStatsForDie(DWARFDie Die, const std::string &FnPrefix,
+                               const std::string &VarPrefix,
+                               uint64_t BytesInScope, uint32_t InlineDepth,
                                StringMap<PerFunctionStats> &FnStatMap,
                                GlobalStats &GlobalStats,
-                               LocationStats &LocStats) {
+                               LocationStats &LocStats,
+                               AbstractOriginVarsTy *AbstractOriginVariables) {
+  const dwarf::Tag Tag = Die.getTag();
+  // Skip CU node.
+  if (Tag == dwarf::DW_TAG_compile_unit)
+    return;
+
   bool HasLoc = false;
   bool HasSrcLoc = false;
   bool HasType = false;
@@ -223,19 +239,22 @@
   uint64_t ScopeBytesCovered = 0;
   uint64_t BytesEntryValuesCovered = 0;
   auto &FnStats = FnStatMap[FnPrefix];
-  bool IsParam = Die.getTag() == dwarf::DW_TAG_formal_parameter;
-  bool IsLocalVar = Die.getTag() == dwarf::DW_TAG_variable;
-  bool IsConstantMember = Die.getTag() == dwarf::DW_TAG_member &&
+  bool IsParam = Tag == dwarf::DW_TAG_formal_parameter;
+  bool IsLocalVar = Tag == dwarf::DW_TAG_variable;
+  bool IsConstantMember = Tag == dwarf::DW_TAG_member &&
                           Die.find(dwarf::DW_AT_const_value);
 
-  if (Die.getTag() == dwarf::DW_TAG_call_site ||
-      Die.getTag() == dwarf::DW_TAG_GNU_call_site) {
+  // For zero covered inlined variables the locstats will be
+  // calculated later.
+  bool DeferLocStats = false;
+
+  if (Tag == dwarf::DW_TAG_call_site || Tag == dwarf::DW_TAG_GNU_call_site) {
     GlobalStats.CallSiteDIEs++;
     return;
   }
 
-  if (Die.getTag() == dwarf::DW_TAG_call_site_parameter ||
-      Die.getTag() == dwarf::DW_TAG_GNU_call_site_parameter) {
+  if (Tag == dwarf::DW_TAG_call_site_parameter ||
+      Tag == dwarf::DW_TAG_GNU_call_site_parameter) {
     GlobalStats.CallSiteParamDIEs++;
     return;
   }
@@ -256,6 +275,21 @@
   if (Die.findRecursively(dwarf::DW_AT_type))
     HasType = true;
 
+  if (Die.find(dwarf::DW_AT_abstract_origin)) {
+    if (Die.find(dwarf::DW_AT_location) || Die.find(dwarf::DW_AT_const_value)) {
+      if (AbstractOriginVariables) {
+        auto Offset = Die.find(dwarf::DW_AT_abstract_origin);
+        // Do not track this variable any more, since it has location
+        // coverage.
+        llvm::erase_value(*AbstractOriginVariables, (*Offset).getRawUValue());
+      }
+    } else {
+      // The locstats will be handled at the end of
+      // the collectStatsRecursive().
+      DeferLocStats = true;
+    }
+  }
+
   auto IsEntryValue = [&](ArrayRef<uint8_t> D) -> bool {
     DWARFUnit *U = Die.getDwarfUnit();
     DataExtractor Data(toStringRef(D),
@@ -315,7 +349,7 @@
   }
 
   // Calculate the debug location statistics.
-  if (BytesInScope) {
+  if (BytesInScope && !DeferLocStats) {
     LocStats.NumVarParam++;
     if (IsParam)
       LocStats.NumParam++;
@@ -389,27 +423,73 @@
   }
 }
 
+/// Recursively collect variables from subprogram with DW_AT_inline attribute.
+static void collectAbstractOriginFnInfo(
+    DWARFDie Die, uint64_t SPOffset,
+    AbstractOriginVarsTyMap &GlobalAbstractOriginFnInfo) {
+  DWARFDie Child = Die.getFirstChild();
+  while (Child) {
+    const dwarf::Tag ChildTag = Child.getTag();
+    if (ChildTag == dwarf::DW_TAG_formal_parameter ||
+        ChildTag == dwarf::DW_TAG_variable)
+      GlobalAbstractOriginFnInfo[SPOffset].push_back(Child.getOffset());
+    else if (ChildTag == dwarf::DW_TAG_lexical_block)
+      collectAbstractOriginFnInfo(Child, SPOffset, GlobalAbstractOriginFnInfo);
+    Child = Child.getSibling();
+  }
+}
+
 /// Recursively collect debug info quality metrics.
-static void collectStatsRecursive(DWARFDie Die, std::string FnPrefix,
-                                  std::string VarPrefix, uint64_t BytesInScope,
-                                  uint32_t InlineDepth,
-                                  StringMap<PerFunctionStats> &FnStatMap,
-                                  GlobalStats &GlobalStats,
-                                  LocationStats &LocStats) {
+static void collectStatsRecursive(
+    DWARFDie Die, std::string FnPrefix, std::string VarPrefix,
+    uint64_t BytesInScope, uint32_t InlineDepth,
+    StringMap<PerFunctionStats> &FnStatMap, GlobalStats &GlobalStats,
+    LocationStats &LocStats,
+    AbstractOriginVarsTyMap &GlobalAbstractOriginFnInfo,
+    FunctionsWithAbstractOriginTy &FnsWithAbstractOriginToBeProcessed,
+    AbstractOriginVarsTy *AbstractOriginVarsPtr = nullptr) {
+  // Skip NULL nodes.
+  if (Die.isNULL())
+    return;
+
   const dwarf::Tag Tag = Die.getTag();
   // Skip function types.
   if (Tag == dwarf::DW_TAG_subroutine_type)
     return;
 
   // Handle any kind of lexical scope.
+  const bool HasAbstractOrigin = Die.find(dwarf::DW_AT_abstract_origin) != None;
   const bool IsFunction = Tag == dwarf::DW_TAG_subprogram;
   const bool IsBlock = Tag == dwarf::DW_TAG_lexical_block;
   const bool IsInlinedFunction = Tag == dwarf::DW_TAG_inlined_subroutine;
-  if (IsFunction || IsInlinedFunction || IsBlock) {
+  // We want to know how many variables (with abstract_origin) don't have
+  // location info.
+  const bool IsCandidateForZeroLocCovTracking =
+      (IsInlinedFunction || (IsFunction && HasAbstractOrigin));
 
+  AbstractOriginVarsTy AbstractOriginVars;
+
+  // Get the vars of the inlined fn, so the locstats
+  // reports the missing vars (with coverage 0%).
+  if (IsCandidateForZeroLocCovTracking) {
+    auto OffsetFn = Die.find(dwarf::DW_AT_abstract_origin);
+    if (OffsetFn) {
+      uint64_t OffsetOfInlineFnCopy = (*OffsetFn).getRawUValue();
+      if (GlobalAbstractOriginFnInfo.count(OffsetOfInlineFnCopy)) {
+        AbstractOriginVars = GlobalAbstractOriginFnInfo[OffsetOfInlineFnCopy];
+        AbstractOriginVarsPtr = &AbstractOriginVars;
+      } else {
+        // This means that the DW_AT_inline fn copy is out of order,
+        // so this abstract origin instance will be processed later.
+        FnsWithAbstractOriginToBeProcessed.push_back(Die.getOffset());
+        AbstractOriginVarsPtr = nullptr;
+      }
+    }
+  }
+
+  if (IsFunction || IsInlinedFunction || IsBlock) {
     // Reset VarPrefix when entering a new function.
-    if (Die.getTag() == dwarf::DW_TAG_subprogram ||
-        Die.getTag() == dwarf::DW_TAG_inlined_subroutine)
+    if (IsFunction || IsInlinedFunction)
       VarPrefix = "v";
 
     // Ignore forward declarations.
@@ -434,9 +514,15 @@
 
     // Count the function.
     if (!IsBlock) {
-      // Skip over abstract origins.
-      if (Die.find(dwarf::DW_AT_inline))
+      // Skip over abstract origins, but collect variables
+      // from it so it can be used for location statistics
+      // for inlined instancies.
+      if (Die.find(dwarf::DW_AT_inline)) {
+        uint64_t SPOffset = Die.getOffset();
+        collectAbstractOriginFnInfo(Die, SPOffset, GlobalAbstractOriginFnInfo);
         return;
+      }
+
       std::string FnID = constructDieID(Die);
       // We've seen an instance of this function.
       auto &FnStats = FnStatMap[FnID];
@@ -465,7 +551,7 @@
   } else {
     // Not a scope, visit the Die itself. It could be a variable.
     collectStatsForDie(Die, FnPrefix, VarPrefix, BytesInScope, InlineDepth,
-                       FnStatMap, GlobalStats, LocStats);
+                       FnStatMap, GlobalStats, LocStats, AbstractOriginVarsPtr);
   }
 
   // Set InlineDepth correctly for child recursion
@@ -485,10 +571,33 @@
     if (Child.getTag() == dwarf::DW_TAG_formal_parameter)
       ChildVarPrefix += 'p' + toHex(FormalParameterIndex++) + '.';
 
-    collectStatsRecursive(Child, FnPrefix, ChildVarPrefix, BytesInScope,
-                          InlineDepth, FnStatMap, GlobalStats, LocStats);
+    collectStatsRecursive(
+        Child, FnPrefix, ChildVarPrefix, BytesInScope, InlineDepth, FnStatMap,
+        GlobalStats, LocStats, GlobalAbstractOriginFnInfo,
+        FnsWithAbstractOriginToBeProcessed, AbstractOriginVarsPtr);
     Child = Child.getSibling();
   }
+
+  if (!IsCandidateForZeroLocCovTracking)
+    return;
+
+  // After we have processed all vars of the inlined function (or function with
+  // an abstract_origin), we want to know how many variables have no location.
+  for (auto Offset : AbstractOriginVars) {
+    LocStats.NumVarParam++;
+    LocStats.VarParamLocStats[ZeroCoverageBucket]++;
+    auto FnDie = Die.getDwarfUnit()->getDIEForOffset(Offset);
+    if (!FnDie)
+      continue;
+    auto Tag = FnDie.getTag();
+    if (Tag == dwarf::DW_TAG_formal_parameter) {
+      LocStats.NumParam++;
+      LocStats.ParamLocStats[ZeroCoverageBucket]++;
+    } else if (Tag == dwarf::DW_TAG_variable) {
+      LocStats.NumVar++;
+      LocStats.LocalVarLocStats[ZeroCoverageBucket]++;
+    }
+  }
 }
 
 /// Print human-readable output.
@@ -536,9 +645,63 @@
 }
 
 static void printSectionSizes(json::OStream &J, const SectionSizes &Sizes) {
-  for (const auto &DebugSec : Sizes.DebugSectionSizes)
-    J.attribute((Twine("#bytes in ") + DebugSec.getKey()).str(),
-                int64_t(DebugSec.getValue()));
+  for (const auto &It : Sizes.DebugSectionSizes)
+    J.attribute((Twine("#bytes in ") + It.first).str(), int64_t(It.second));
+}
+
+/// Stop tracking variables that contain abstract_origin with a location.
+/// This is used for out-of-order DW_AT_inline subprograms only.
+static void updateVarsWithAbstractOriginLocCovInfo(
+    DWARFDie FnDieWithAbstractOrigin,
+    AbstractOriginVarsTy &AbstractOriginVars) {
+  DWARFDie Child = FnDieWithAbstractOrigin.getFirstChild();
+  while (Child) {
+    const dwarf::Tag ChildTag = Child.getTag();
+    if ((ChildTag == dwarf::DW_TAG_formal_parameter ||
+         ChildTag == dwarf::DW_TAG_variable) &&
+        (Child.find(dwarf::DW_AT_location) ||
+         Child.find(dwarf::DW_AT_const_value))) {
+      auto OffsetVar = Child.find(dwarf::DW_AT_abstract_origin);
+      if (OffsetVar)
+        llvm::erase_value(AbstractOriginVars, (*OffsetVar).getRawUValue());
+    } else if (ChildTag == dwarf::DW_TAG_lexical_block)
+      updateVarsWithAbstractOriginLocCovInfo(Child, AbstractOriginVars);
+    Child = Child.getSibling();
+  }
+}
+
+/// Collect zero location coverage for inlined variables which refer to
+/// a DW_AT_inline copy of subprogram that is out of order in the DWARF.
+/// Also cover the variables of a concrete function (represented with
+/// the DW_TAG_subprogram) with an abstract_origin attribute.
+static void collectZeroLocCovForVarsWithAbstractOrigin(
+    DWARFUnit *DwUnit, GlobalStats &GlobalStats, LocationStats &LocStats,
+    AbstractOriginVarsTyMap &GlobalAbstractOriginFnInfo,
+    FunctionsWithAbstractOriginTy &FnsWithAbstractOriginToBeProcessed) {
+  for (auto FnOffset : FnsWithAbstractOriginToBeProcessed) {
+    DWARFDie FnDieWithAbstractOrigin = DwUnit->getDIEForOffset(FnOffset);
+    auto FnCopy = FnDieWithAbstractOrigin.find(dwarf::DW_AT_abstract_origin);
+    AbstractOriginVarsTy AbstractOriginVars;
+    if (!FnCopy)
+      continue;
+
+    AbstractOriginVars = GlobalAbstractOriginFnInfo[(*FnCopy).getRawUValue()];
+    updateVarsWithAbstractOriginLocCovInfo(FnDieWithAbstractOrigin,
+                                           AbstractOriginVars);
+
+    for (auto Offset : AbstractOriginVars) {
+      LocStats.NumVarParam++;
+      LocStats.VarParamLocStats[ZeroCoverageBucket]++;
+      auto Tag = DwUnit->getDIEForOffset(Offset).getTag();
+      if (Tag == dwarf::DW_TAG_formal_parameter) {
+        LocStats.NumParam++;
+        LocStats.ParamLocStats[ZeroCoverageBucket]++;
+      } else if (Tag == dwarf::DW_TAG_variable) {
+        LocStats.NumVar++;
+        LocStats.LocalVarLocStats[ZeroCoverageBucket]++;
+      }
+    }
+  }
 }
 
 /// \}
@@ -558,10 +721,27 @@
   GlobalStats GlobalStats;
   LocationStats LocStats;
   StringMap<PerFunctionStats> Statistics;
-  for (const auto &CU : static_cast<DWARFContext *>(&DICtx)->compile_units())
-    if (DWARFDie CUDie = CU->getNonSkeletonUnitDIE(false))
+  for (const auto &CU : static_cast<DWARFContext *>(&DICtx)->compile_units()) {
+    if (DWARFDie CUDie = CU->getNonSkeletonUnitDIE(false)) {
+      // These variables are being reset for each CU, since there could be
+      // a situation where we have two subprogram DIEs with the same offsets
+      // in two diferent CUs, and we can end up using wrong variables info
+      // when trying to resolve abstract_origin attribute.
+      // TODO: Handle LTO cases where the abstract origin of
+      // the function is in a different CU than the one it's
+      // referenced from or inlined into.
+      AbstractOriginVarsTyMap GlobalAbstractOriginFnInfo;
+      FunctionsWithAbstractOriginTy FnsWithAbstractOriginToBeProcessed;
+
       collectStatsRecursive(CUDie, "/", "g", 0, 0, Statistics, GlobalStats,
-                            LocStats);
+                            LocStats, GlobalAbstractOriginFnInfo,
+                            FnsWithAbstractOriginToBeProcessed);
+
+      collectZeroLocCovForVarsWithAbstractOrigin(
+          CUDie.getDwarfUnit(), GlobalStats, LocStats,
+          GlobalAbstractOriginFnInfo, FnsWithAbstractOriginToBeProcessed);
+    }
+  }
 
   /// Collect the sizes of debug sections.
   SectionSizes Sizes;
@@ -570,7 +750,7 @@
   /// The version number should be increased every time the algorithm is changed
   /// (including bug fixes). New metrics may be added without increasing the
   /// version.
-  unsigned Version = 6;
+  unsigned Version = 8;
   unsigned VarParamTotal = 0;
   unsigned VarParamUnique = 0;
   unsigned VarParamWithLoc = 0;
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/src/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 4322f12..a324ff7 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -130,7 +130,8 @@
 
 static opt<bool> DumpAll("all", desc("Dump all debug info sections"),
                          cat(SectionCategory));
-static alias DumpAllAlias("a", desc("Alias for -all"), aliasopt(DumpAll));
+static alias DumpAllAlias("a", desc("Alias for --all"), aliasopt(DumpAll),
+                          cl::NotHidden);
 
 // Options for dumping specific sections.
 static unsigned DumpType = DIDT_Null;
@@ -143,7 +144,8 @@
 #include "llvm/BinaryFormat/Dwarf.def"
 #undef HANDLE_DWARF_SECTION
 
-static alias DumpDebugFrameAlias("eh-frame", desc("Alias for -debug-frame"),
+// The aliased DumpDebugFrame is created by the Dwarf.def x-macro just above.
+static alias DumpDebugFrameAlias("eh-frame", desc("Alias for --debug-frame"),
                                  NotHidden, cat(SectionCategory),
                                  aliasopt(DumpDebugFrame));
 static list<std::string>
@@ -164,19 +166,21 @@
               "accelerator tables are available, the slower but more complete "
               "-name option can be used instead."),
          value_desc("name"), cat(DwarfDumpCategory));
-static alias FindAlias("f", desc("Alias for -find."), aliasopt(Find));
+static alias FindAlias("f", desc("Alias for --find."), aliasopt(Find),
+                       cl::NotHidden);
 static opt<bool> IgnoreCase("ignore-case",
                             desc("Ignore case distinctions when searching."),
                             value_desc("i"), cat(DwarfDumpCategory));
-static alias IgnoreCaseAlias("i", desc("Alias for -ignore-case."),
-                             aliasopt(IgnoreCase));
+static alias IgnoreCaseAlias("i", desc("Alias for --ignore-case."),
+                             aliasopt(IgnoreCase), cl::NotHidden);
 static list<std::string> Name(
     "name",
     desc("Find and print all debug info entries whose name (DW_AT_name "
          "attribute) matches the exact text in <pattern>.  When used with the "
          "the -regex option <pattern> is interpreted as a regular expression."),
     value_desc("pattern"), cat(DwarfDumpCategory));
-static alias NameAlias("n", desc("Alias for -name"), aliasopt(Name));
+static alias NameAlias("n", desc("Alias for --name"), aliasopt(Name),
+                       cl::NotHidden);
 static opt<uint64_t>
     Lookup("lookup",
            desc("Lookup <address> in the debug information and print out any "
@@ -193,34 +197,36 @@
              desc("Treat any <pattern> strings as regular expressions when "
                   "searching instead of just as an exact string match."),
              cat(DwarfDumpCategory));
-static alias RegexAlias("x", desc("Alias for -regex"), aliasopt(UseRegex));
+static alias RegexAlias("x", desc("Alias for --regex"), aliasopt(UseRegex),
+                        cl::NotHidden);
 static opt<bool>
     ShowChildren("show-children",
                  desc("Show a debug info entry's children when selectively "
                       "printing entries."),
                  cat(DwarfDumpCategory));
-static alias ShowChildrenAlias("c", desc("Alias for -show-children."),
-                               aliasopt(ShowChildren));
+static alias ShowChildrenAlias("c", desc("Alias for --show-children."),
+                               aliasopt(ShowChildren), cl::NotHidden);
 static opt<bool>
     ShowParents("show-parents",
                 desc("Show a debug info entry's parents when selectively "
                      "printing entries."),
                 cat(DwarfDumpCategory));
-static alias ShowParentsAlias("p", desc("Alias for -show-parents."),
-                              aliasopt(ShowParents));
+static alias ShowParentsAlias("p", desc("Alias for --show-parents."),
+                              aliasopt(ShowParents), cl::NotHidden);
 static opt<bool>
     ShowForm("show-form",
              desc("Show DWARF form types after the DWARF attribute types."),
              cat(DwarfDumpCategory));
-static alias ShowFormAlias("F", desc("Alias for -show-form."),
-                           aliasopt(ShowForm), cat(DwarfDumpCategory));
+static alias ShowFormAlias("F", desc("Alias for --show-form."),
+                           aliasopt(ShowForm), cat(DwarfDumpCategory),
+                           cl::NotHidden);
 static opt<unsigned>
     ChildRecurseDepth("recurse-depth",
                       desc("Only recurse to a depth of N when displaying "
                            "children of debug info entries."),
                       cat(DwarfDumpCategory), init(-1U), value_desc("N"));
-static alias ChildRecurseDepthAlias("r", desc("Alias for -recurse-depth."),
-                                    aliasopt(ChildRecurseDepth));
+static alias ChildRecurseDepthAlias("r", desc("Alias for --recurse-depth."),
+                                    aliasopt(ChildRecurseDepth), cl::NotHidden);
 static opt<unsigned>
     ParentRecurseDepth("parent-recurse-depth",
                        desc("Only recurse to a depth of N when displaying "
@@ -245,25 +251,30 @@
                        cat(DwarfDumpCategory));
 static opt<bool> DumpUUID("uuid", desc("Show the UUID for each architecture."),
                           cat(DwarfDumpCategory));
-static alias DumpUUIDAlias("u", desc("Alias for -uuid."), aliasopt(DumpUUID));
+static alias DumpUUIDAlias("u", desc("Alias for --uuid."), aliasopt(DumpUUID),
+                           cl::NotHidden);
 static opt<bool> Verbose("verbose",
                          desc("Print more low-level encoding details."),
                          cat(DwarfDumpCategory));
-static alias VerboseAlias("v", desc("Alias for -verbose."), aliasopt(Verbose),
-                          cat(DwarfDumpCategory));
+static alias VerboseAlias("v", desc("Alias for --verbose."), aliasopt(Verbose),
+                          cat(DwarfDumpCategory), cl::NotHidden);
 static cl::extrahelp
     HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
 } // namespace
 /// @}
 //===----------------------------------------------------------------------===//
 
-static void error(StringRef Prefix, std::error_code EC) {
-  if (!EC)
+static void error(StringRef Prefix, Error Err) {
+  if (!Err)
     return;
-  WithColor::error() << Prefix << ": " << EC.message() << "\n";
+  WithColor::error() << Prefix << ": " << toString(std::move(Err)) << "\n";
   exit(1);
 }
 
+static void error(StringRef Prefix, std::error_code EC) {
+  error(Prefix, errorCodeToError(EC));
+}
+
 static DIDumpOptions getDumpOpts(DWARFContext &C) {
   DIDumpOptions DumpOpts;
   DumpOpts.DumpType = DumpType;
@@ -484,7 +495,7 @@
   // fails.
   raw_ostream &stream = Quiet ? nulls() : OS;
   stream << "Verifying " << Filename.str() << ":\tfile format "
-  << Obj.getFileFormatName() << "\n";
+         << Obj.getFileFormatName() << "\n";
   bool Result = DICtx.verify(stream, getDumpOpts(DICtx));
   if (Result)
     stream << "No errors.\n";
@@ -502,13 +513,13 @@
   Error Err = Error::success();
   for (auto Child : Arch.children(Err)) {
     auto BuffOrErr = Child.getMemoryBufferRef();
-    error(Filename, errorToErrorCode(BuffOrErr.takeError()));
+    error(Filename, BuffOrErr.takeError());
     auto NameOrErr = Child.getName();
-    error(Filename, errorToErrorCode(NameOrErr.takeError()));
+    error(Filename, NameOrErr.takeError());
     std::string Name = (Filename + "(" + NameOrErr.get() + ")").str();
     Result &= handleBuffer(Name, BuffOrErr.get(), HandleObj, OS);
   }
-  error(Filename, errorToErrorCode(std::move(Err)));
+  error(Filename, std::move(Err));
 
   return Result;
 }
@@ -516,7 +527,7 @@
 static bool handleBuffer(StringRef Filename, MemoryBufferRef Buffer,
                          HandlerFn HandleObj, raw_ostream &OS) {
   Expected<std::unique_ptr<Binary>> BinOrErr = object::createBinary(Buffer);
-  error(Filename, errorToErrorCode(BinOrErr.takeError()));
+  error(Filename, BinOrErr.takeError());
 
   bool Result = true;
   auto RecoverableErrorHandler = [&](Error E) {
@@ -530,8 +541,7 @@
       if (!HandleObj(*Obj, *DICtx, Filename, OS))
         Result = false;
     }
-  }
-  else if (auto *Fat = dyn_cast<MachOUniversalBinary>(BinOrErr->get()))
+  } else if (auto *Fat = dyn_cast<MachOUniversalBinary>(BinOrErr->get()))
     for (auto &ObjForArch : Fat->objects()) {
       std::string ObjName =
           (Filename + "(" + ObjForArch.getArchFlagName() + ")").str();
@@ -547,7 +557,7 @@
       } else
         consumeError(MachOOrErr.takeError());
       if (auto ArchiveOrErr = ObjForArch.getAsArchive()) {
-        error(ObjName, errorToErrorCode(ArchiveOrErr.takeError()));
+        error(ObjName, ArchiveOrErr.takeError());
         if (!handleArchive(ObjName, *ArchiveOrErr.get(), HandleObj, OS))
           Result = false;
         continue;
@@ -562,7 +572,7 @@
 static bool handleFile(StringRef Filename, HandlerFn HandleObj,
                        raw_ostream &OS) {
   ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
-  MemoryBuffer::getFileOrSTDIN(Filename);
+      MemoryBuffer::getFileOrSTDIN(Filename);
   error(Filename, BuffOrErr.getError());
   std::unique_ptr<MemoryBuffer> Buffer = std::move(BuffOrErr.get());
   return handleBuffer(Filename, *Buffer, HandleObj, OS);
@@ -613,7 +623,8 @@
   llvm::InitializeAllTargetInfos();
   llvm::InitializeAllTargetMCs();
 
-  HideUnrelatedOptions({&DwarfDumpCategory, &SectionCategory, &ColorCategory});
+  HideUnrelatedOptions(
+      {&DwarfDumpCategory, &SectionCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(
       argc, argv,
       "pretty-print DWARF debug information in object files"
@@ -628,8 +639,8 @@
   }
 
   std::error_code EC;
-  ToolOutputFile OutputFile(OutputFilename, EC, sys::fs::OF_Text);
-  error("Unable to open output file" + OutputFilename, EC);
+  ToolOutputFile OutputFile(OutputFilename, EC, sys::fs::OF_TextWithCRLF);
+  error("unable to open output file " + OutputFilename, EC);
   // Don't remove output file if we exit with an error.
   OutputFile.keep();
 
@@ -659,7 +670,8 @@
   }
 
   // Unless dumping a specific DIE, default to --show-children.
-  if (!ShowChildren && !Verify && !OffsetRequested && Name.empty() && Find.empty())
+  if (!ShowChildren && !Verify && !OffsetRequested && Name.empty() &&
+      Find.empty())
     ShowChildren = true;
 
   // Defaults to a.out if no filenames specified.
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.h b/src/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.h
index dc41298..cf7da56 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.h
+++ b/src/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.h
@@ -9,6 +9,8 @@
 #ifndef LLVM_TOOLS_LLVM_DWARFDUMP_LLVM_DWARFDUMP_H
 #define LLVM_TOOLS_LLVM_DWARFDUMP_LLVM_DWARFDUMP_H
 
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/Object/ObjectFile.h"
@@ -21,7 +23,7 @@
 struct SectionSizes {
   /// Map of .debug section names and their sizes across all such-named
   /// sections.
-  StringMap<uint64_t> DebugSectionSizes;
+  MapVector<std::string, uint64_t, StringMap<uint64_t>> DebugSectionSizes;
   /// Total number of bytes of all sections.
   uint64_t TotalObjectSize = 0;
   /// Total number of bytes of all debug sections.
diff --git a/src/llvm-project/llvm/tools/llvm-dwp/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-dwp/CMakeLists.txt
index bf40768..15210c4 100644
--- a/src/llvm-project/llvm/tools/llvm-dwp/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-dwp/CMakeLists.txt
@@ -1,19 +1,16 @@
 set(LLVM_LINK_COMPONENTS
-  AllTargetsAsmParsers
   AllTargetsCodeGens
   AllTargetsDescs
   AllTargetsInfos
-  AsmPrinter
   DebugInfoDWARF
+  DWP
   MC
   Object
   Support
-  Target
   )
 
 add_llvm_tool(llvm-dwp
   llvm-dwp.cpp
-  DWPError.cpp
 
   DEPENDS
   intrinsics_gen
diff --git a/src/llvm-project/llvm/tools/llvm-dwp/DWPError.cpp b/src/llvm-project/llvm/tools/llvm-dwp/DWPError.cpp
deleted file mode 100644
index 21d53ed..0000000
--- a/src/llvm-project/llvm/tools/llvm-dwp/DWPError.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "DWPError.h"
-using namespace llvm;
-char DWPError::ID;
diff --git a/src/llvm-project/llvm/tools/llvm-dwp/DWPError.h b/src/llvm-project/llvm/tools/llvm-dwp/DWPError.h
deleted file mode 100644
index 62025ed..0000000
--- a/src/llvm-project/llvm/tools/llvm-dwp/DWPError.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef TOOLS_LLVM_DWP_DWPERROR
-#define TOOLS_LLVM_DWP_DWPERROR
-
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <string>
-
-namespace llvm {
-class DWPError : public ErrorInfo<DWPError> {
-public:
-  DWPError(std::string Info) : Info(std::move(Info)) {}
-  void log(raw_ostream &OS) const override { OS << Info; }
-  std::error_code convertToErrorCode() const override {
-    llvm_unreachable("Not implemented");
-  }
-  static char ID;
-
-private:
-  std::string Info;
-};
-}
-
-#endif
diff --git a/src/llvm-project/llvm/tools/llvm-dwp/DWPStringPool.h b/src/llvm-project/llvm/tools/llvm-dwp/DWPStringPool.h
deleted file mode 100644
index e423076..0000000
--- a/src/llvm-project/llvm/tools/llvm-dwp/DWPStringPool.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef TOOLS_LLVM_DWP_DWPSTRINGPOOL
-#define TOOLS_LLVM_DWP_DWPSTRINGPOOL
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCStreamer.h"
-#include <cassert>
-
-namespace llvm {
-class DWPStringPool {
-
-  struct CStrDenseMapInfo {
-    static inline const char *getEmptyKey() {
-      return reinterpret_cast<const char *>(~static_cast<uintptr_t>(0));
-    }
-    static inline const char *getTombstoneKey() {
-      return reinterpret_cast<const char *>(~static_cast<uintptr_t>(1));
-    }
-    static unsigned getHashValue(const char *Val) {
-      assert(Val != getEmptyKey() && "Cannot hash the empty key!");
-      assert(Val != getTombstoneKey() && "Cannot hash the tombstone key!");
-      return (unsigned)hash_value(StringRef(Val));
-    }
-    static bool isEqual(const char *LHS, const char *RHS) {
-      if (RHS == getEmptyKey())
-        return LHS == getEmptyKey();
-      if (RHS == getTombstoneKey())
-        return LHS == getTombstoneKey();
-      return strcmp(LHS, RHS) == 0;
-    }
-  };
-
-  MCStreamer &Out;
-  MCSection *Sec;
-  DenseMap<const char *, uint32_t, CStrDenseMapInfo> Pool;
-  uint32_t Offset = 0;
-
-public:
-  DWPStringPool(MCStreamer &Out, MCSection *Sec) : Out(Out), Sec(Sec) {}
-
-  uint32_t getOffset(const char *Str, unsigned Length) {
-    assert(strlen(Str) + 1 == Length && "Ensure length hint is correct");
-
-    auto Pair = Pool.insert(std::make_pair(Str, Offset));
-    if (Pair.second) {
-      Out.SwitchSection(Sec);
-      Out.emitBytes(StringRef(Str, Length));
-      Offset += Length;
-    }
-
-    return Pair.first->second;
-  }
-};
-}
-
-#endif
diff --git a/src/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp b/src/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp
index d495bd3..1f58372 100644
--- a/src/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp
@@ -10,39 +10,22 @@
 // package files).
 //
 //===----------------------------------------------------------------------===//
-#include "DWPError.h"
-#include "DWPStringPool.h"
-#include "llvm/ADT/MapVector.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
-#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+#include "llvm/DWP/DWP.h"
+#include "llvm/DWP/DWPError.h"
+#include "llvm/DWP/DWPStringPool.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCCodeEmitter.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCInstrInfo.h"
-#include "llvm/MC/MCObjectFileInfo.h"
 #include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
-#include "llvm/Object/Decompressor.h"
-#include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/DataExtractor.h"
-#include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/ToolOutputFile.h"
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/raw_ostream.h"
 
 using namespace llvm;
 using namespace llvm::object;
@@ -64,449 +47,6 @@
                                            cl::value_desc("filename"),
                                            cl::cat(DwpCategory));
 
-static void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,
-                                   MCSection *StrOffsetSection,
-                                   StringRef CurStrSection,
-                                   StringRef CurStrOffsetSection) {
-  // Could possibly produce an error or warning if one of these was non-null but
-  // the other was null.
-  if (CurStrSection.empty() || CurStrOffsetSection.empty())
-    return;
-
-  DenseMap<uint64_t, uint32_t> OffsetRemapping;
-
-  DataExtractor Data(CurStrSection, true, 0);
-  uint64_t LocalOffset = 0;
-  uint64_t PrevOffset = 0;
-  while (const char *s = Data.getCStr(&LocalOffset)) {
-    OffsetRemapping[PrevOffset] =
-        Strings.getOffset(s, LocalOffset - PrevOffset);
-    PrevOffset = LocalOffset;
-  }
-
-  Data = DataExtractor(CurStrOffsetSection, true, 0);
-
-  Out.SwitchSection(StrOffsetSection);
-
-  uint64_t Offset = 0;
-  uint64_t Size = CurStrOffsetSection.size();
-  while (Offset < Size) {
-    auto OldOffset = Data.getU32(&Offset);
-    auto NewOffset = OffsetRemapping[OldOffset];
-    Out.emitIntValue(NewOffset, 4);
-  }
-}
-
-static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) {
-  uint64_t CurCode;
-  uint64_t Offset = 0;
-  DataExtractor AbbrevData(Abbrev, true, 0);
-  while ((CurCode = AbbrevData.getULEB128(&Offset)) != AbbrCode) {
-    // Tag
-    AbbrevData.getULEB128(&Offset);
-    // DW_CHILDREN
-    AbbrevData.getU8(&Offset);
-    // Attributes
-    while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset))
-      ;
-  }
-  return Offset;
-}
-
-struct CompileUnitIdentifiers {
-  uint64_t Signature = 0;
-  const char *Name = "";
-  const char *DWOName = "";
-};
-
-static Expected<const char *>
-getIndexedString(dwarf::Form Form, DataExtractor InfoData,
-                 uint64_t &InfoOffset, StringRef StrOffsets, StringRef Str) {
-  if (Form == dwarf::DW_FORM_string)
-    return InfoData.getCStr(&InfoOffset);
-  if (Form != dwarf::DW_FORM_GNU_str_index)
-    return make_error<DWPError>(
-        "string field encoded without DW_FORM_string or DW_FORM_GNU_str_index");
-  auto StrIndex = InfoData.getULEB128(&InfoOffset);
-  DataExtractor StrOffsetsData(StrOffsets, true, 0);
-  uint64_t StrOffsetsOffset = 4 * StrIndex;
-  uint64_t StrOffset = StrOffsetsData.getU32(&StrOffsetsOffset);
-  DataExtractor StrData(Str, true, 0);
-  return StrData.getCStr(&StrOffset);
-}
-
-static Expected<CompileUnitIdentifiers> getCUIdentifiers(StringRef Abbrev,
-                                                         StringRef Info,
-                                                         StringRef StrOffsets,
-                                                         StringRef Str) {
-  uint64_t Offset = 0;
-  DataExtractor InfoData(Info, true, 0);
-  dwarf::DwarfFormat Format = dwarf::DwarfFormat::DWARF32;
-  uint64_t Length = InfoData.getU32(&Offset);
-  CompileUnitIdentifiers ID;
-  Optional<uint64_t> Signature = None;
-  // If the length is 0xffffffff, then this indictes that this is a DWARF 64
-  // stream and the length is actually encoded into a 64 bit value that follows.
-  if (Length == 0xffffffffU) {
-    Format = dwarf::DwarfFormat::DWARF64;
-    Length = InfoData.getU64(&Offset);
-  }
-  uint16_t Version = InfoData.getU16(&Offset);
-  if (Version >= 5) {
-    auto UnitType = InfoData.getU8(&Offset);
-    if (UnitType != dwarf::DW_UT_split_compile)
-      return make_error<DWPError>(
-          std::string("unit type DW_UT_split_compile type not found in "
-                      "debug_info header. Unexpected unit type 0x" +
-                      utostr(UnitType) + " found"));
-  }
-  InfoData.getU32(&Offset); // Abbrev offset (should be zero)
-  uint8_t AddrSize = InfoData.getU8(&Offset);
-  if (Version >= 5)
-    Signature = InfoData.getU64(&Offset);
-  uint32_t AbbrCode = InfoData.getULEB128(&Offset);
-
-  DataExtractor AbbrevData(Abbrev, true, 0);
-  uint64_t AbbrevOffset = getCUAbbrev(Abbrev, AbbrCode);
-  auto Tag = static_cast<dwarf::Tag>(AbbrevData.getULEB128(&AbbrevOffset));
-  if (Tag != dwarf::DW_TAG_compile_unit)
-    return make_error<DWPError>("top level DIE is not a compile unit");
-  // DW_CHILDREN
-  AbbrevData.getU8(&AbbrevOffset);
-  uint32_t Name;
-  dwarf::Form Form;
-  while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) |
-         (Form = static_cast<dwarf::Form>(AbbrevData.getULEB128(&AbbrevOffset))) &&
-         (Name != 0 || Form != 0)) {
-    switch (Name) {
-    case dwarf::DW_AT_name: {
-      Expected<const char *> EName =
-          getIndexedString(Form, InfoData, Offset, StrOffsets, Str);
-      if (!EName)
-        return EName.takeError();
-      ID.Name = *EName;
-      break;
-    }
-    case dwarf::DW_AT_GNU_dwo_name:
-    case dwarf::DW_AT_dwo_name: {
-      Expected<const char *> EName =
-          getIndexedString(Form, InfoData, Offset, StrOffsets, Str);
-      if (!EName)
-        return EName.takeError();
-      ID.DWOName = *EName;
-      break;
-    }
-    case dwarf::DW_AT_GNU_dwo_id:
-      Signature = InfoData.getU64(&Offset);
-      break;
-    default:
-      DWARFFormValue::skipValue(Form, InfoData, &Offset,
-                                dwarf::FormParams({Version, AddrSize, Format}));
-    }
-  }
-  if (!Signature)
-    return make_error<DWPError>("compile unit missing dwo_id");
-  ID.Signature = *Signature;
-  return ID;
-}
-
-struct UnitIndexEntry {
-  DWARFUnitIndex::Entry::SectionContribution Contributions[8];
-  std::string Name;
-  std::string DWOName;
-  StringRef DWPName;
-};
-
-static bool isSupportedSectionKind(DWARFSectionKind Kind) {
-  return Kind != DW_SECT_EXT_unknown;
-}
-
-// Convert an internal section identifier into the index to use with
-// UnitIndexEntry::Contributions.
-static unsigned getContributionIndex(DWARFSectionKind Kind) {
-  // Assuming the pre-standard DWP format.
-  assert(serializeSectionKind(Kind, 2) >= DW_SECT_INFO);
-  return serializeSectionKind(Kind, 2) - DW_SECT_INFO;
-}
-
-// Convert a UnitIndexEntry::Contributions index to the corresponding on-disk
-// value of the section identifier.
-static unsigned getOnDiskSectionId(unsigned Index) {
-  return Index + DW_SECT_INFO;
-}
-
-static StringRef getSubsection(StringRef Section,
-                               const DWARFUnitIndex::Entry &Entry,
-                               DWARFSectionKind Kind) {
-  const auto *Off = Entry.getContribution(Kind);
-  if (!Off)
-    return StringRef();
-  return Section.substr(Off->Offset, Off->Length);
-}
-
-static void addAllTypesFromDWP(
-    MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
-    const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types,
-    const UnitIndexEntry &TUEntry, uint32_t &TypesOffset) {
-  Out.SwitchSection(OutputTypes);
-  for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) {
-    auto *I = E.getContributions();
-    if (!I)
-      continue;
-    auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry));
-    if (!P.second)
-      continue;
-    auto &Entry = P.first->second;
-    // Zero out the debug_info contribution
-    Entry.Contributions[0] = {};
-    for (auto Kind : TUIndex.getColumnKinds()) {
-      if (!isSupportedSectionKind(Kind))
-        continue;
-      auto &C = Entry.Contributions[getContributionIndex(Kind)];
-      C.Offset += I->Offset;
-      C.Length = I->Length;
-      ++I;
-    }
-    unsigned TypesIndex = getContributionIndex(DW_SECT_EXT_TYPES);
-    auto &C = Entry.Contributions[TypesIndex];
-    Out.emitBytes(Types.substr(
-        C.Offset - TUEntry.Contributions[TypesIndex].Offset, C.Length));
-    C.Offset = TypesOffset;
-    TypesOffset += C.Length;
-  }
-}
-
-static void addAllTypes(MCStreamer &Out,
-                        MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
-                        MCSection *OutputTypes,
-                        const std::vector<StringRef> &TypesSections,
-                        const UnitIndexEntry &CUEntry, uint32_t &TypesOffset) {
-  for (StringRef Types : TypesSections) {
-    Out.SwitchSection(OutputTypes);
-    uint64_t Offset = 0;
-    DataExtractor Data(Types, true, 0);
-    while (Data.isValidOffset(Offset)) {
-      UnitIndexEntry Entry = CUEntry;
-      // Zero out the debug_info contribution
-      Entry.Contributions[0] = {};
-      auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES)];
-      C.Offset = TypesOffset;
-      auto PrevOffset = Offset;
-      // Length of the unit, including the 4 byte length field.
-      C.Length = Data.getU32(&Offset) + 4;
-
-      Data.getU16(&Offset); // Version
-      Data.getU32(&Offset); // Abbrev offset
-      Data.getU8(&Offset);  // Address size
-      auto Signature = Data.getU64(&Offset);
-      Offset = PrevOffset + C.Length;
-
-      auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry));
-      if (!P.second)
-        continue;
-
-      Out.emitBytes(Types.substr(PrevOffset, C.Length));
-      TypesOffset += C.Length;
-    }
-  }
-}
-
-static void
-writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
-                const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
-                uint32_t DWARFUnitIndex::Entry::SectionContribution::*Field) {
-  for (const auto &E : IndexEntries)
-    for (size_t i = 0; i != array_lengthof(E.second.Contributions); ++i)
-      if (ContributionOffsets[i])
-        Out.emitIntValue(E.second.Contributions[i].*Field, 4);
-}
-
-static void
-writeIndex(MCStreamer &Out, MCSection *Section,
-           ArrayRef<unsigned> ContributionOffsets,
-           const MapVector<uint64_t, UnitIndexEntry> &IndexEntries) {
-  if (IndexEntries.empty())
-    return;
-
-  unsigned Columns = 0;
-  for (auto &C : ContributionOffsets)
-    if (C)
-      ++Columns;
-
-  std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
-  uint64_t Mask = Buckets.size() - 1;
-  size_t i = 0;
-  for (const auto &P : IndexEntries) {
-    auto S = P.first;
-    auto H = S & Mask;
-    auto HP = ((S >> 32) & Mask) | 1;
-    while (Buckets[H]) {
-      assert(S != IndexEntries.begin()[Buckets[H] - 1].first &&
-             "Duplicate unit");
-      H = (H + HP) & Mask;
-    }
-    Buckets[H] = i + 1;
-    ++i;
-  }
-
-  Out.SwitchSection(Section);
-  Out.emitIntValue(2, 4);                   // Version
-  Out.emitIntValue(Columns, 4);             // Columns
-  Out.emitIntValue(IndexEntries.size(), 4); // Num Units
-  Out.emitIntValue(Buckets.size(), 4);      // Num Buckets
-
-  // Write the signatures.
-  for (const auto &I : Buckets)
-    Out.emitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8);
-
-  // Write the indexes.
-  for (const auto &I : Buckets)
-    Out.emitIntValue(I, 4);
-
-  // Write the column headers (which sections will appear in the table)
-  for (size_t i = 0; i != ContributionOffsets.size(); ++i)
-    if (ContributionOffsets[i])
-      Out.emitIntValue(getOnDiskSectionId(i), 4);
-
-  // Write the offsets.
-  writeIndexTable(Out, ContributionOffsets, IndexEntries,
-                  &DWARFUnitIndex::Entry::SectionContribution::Offset);
-
-  // Write the lengths.
-  writeIndexTable(Out, ContributionOffsets, IndexEntries,
-                  &DWARFUnitIndex::Entry::SectionContribution::Length);
-}
-
-static std::string buildDWODescription(StringRef Name, StringRef DWPName,
-                                       StringRef DWOName) {
-  std::string Text = "\'";
-  Text += Name;
-  Text += '\'';
-  if (!DWPName.empty()) {
-    Text += " (from ";
-    if (!DWOName.empty()) {
-      Text += '\'';
-      Text += DWOName;
-      Text += "' in ";
-    }
-    Text += '\'';
-    Text += DWPName;
-    Text += "')";
-  }
-  return Text;
-}
-
-static Error createError(StringRef Name, Error E) {
-  return make_error<DWPError>(
-      ("failure while decompressing compressed section: '" + Name + "', " +
-       llvm::toString(std::move(E)))
-          .str());
-}
-
-static Error
-handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections,
-                        StringRef &Name, StringRef &Contents) {
-  if (!Decompressor::isGnuStyle(Name))
-    return Error::success();
-
-  Expected<Decompressor> Dec =
-      Decompressor::create(Name, Contents, false /*IsLE*/, false /*Is64Bit*/);
-  if (!Dec)
-    return createError(Name, Dec.takeError());
-
-  UncompressedSections.emplace_back();
-  if (Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
-    return createError(Name, std::move(E));
-
-  Name = Name.substr(2); // Drop ".z"
-  Contents = UncompressedSections.back();
-  return Error::success();
-}
-
-static Error handleSection(
-    const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
-    const MCSection *StrSection, const MCSection *StrOffsetSection,
-    const MCSection *TypesSection, const MCSection *CUIndexSection,
-    const MCSection *TUIndexSection, const SectionRef &Section, MCStreamer &Out,
-    std::deque<SmallString<32>> &UncompressedSections,
-    uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry,
-    StringRef &CurStrSection, StringRef &CurStrOffsetSection,
-    std::vector<StringRef> &CurTypesSection, StringRef &InfoSection,
-    StringRef &AbbrevSection, StringRef &CurCUIndexSection,
-    StringRef &CurTUIndexSection) {
-  if (Section.isBSS())
-    return Error::success();
-
-  if (Section.isVirtual())
-    return Error::success();
-
-  Expected<StringRef> NameOrErr = Section.getName();
-  if (!NameOrErr)
-    return NameOrErr.takeError();
-  StringRef Name = *NameOrErr;
-
-  Expected<StringRef> ContentsOrErr = Section.getContents();
-  if (!ContentsOrErr)
-    return ContentsOrErr.takeError();
-  StringRef Contents = *ContentsOrErr;
-
-  if (auto Err = handleCompressedSection(UncompressedSections, Name, Contents))
-    return Err;
-
-  Name = Name.substr(Name.find_first_not_of("._"));
-
-  auto SectionPair = KnownSections.find(Name);
-  if (SectionPair == KnownSections.end())
-    return Error::success();
-
-  if (DWARFSectionKind Kind = SectionPair->second.second) {
-    auto Index = getContributionIndex(Kind);
-    if (Kind != DW_SECT_EXT_TYPES) {
-      CurEntry.Contributions[Index].Offset = ContributionOffsets[Index];
-      ContributionOffsets[Index] +=
-          (CurEntry.Contributions[Index].Length = Contents.size());
-    }
-
-    switch (Kind) {
-    case DW_SECT_INFO:
-      InfoSection = Contents;
-      break;
-    case DW_SECT_ABBREV:
-      AbbrevSection = Contents;
-      break;
-    default:
-      break;
-    }
-  }
-
-  MCSection *OutSection = SectionPair->second.first;
-  if (OutSection == StrOffsetSection)
-    CurStrOffsetSection = Contents;
-  else if (OutSection == StrSection)
-    CurStrSection = Contents;
-  else if (OutSection == TypesSection)
-    CurTypesSection.push_back(Contents);
-  else if (OutSection == CUIndexSection)
-    CurCUIndexSection = Contents;
-  else if (OutSection == TUIndexSection)
-    CurTUIndexSection = Contents;
-  else {
-    Out.SwitchSection(OutSection);
-    Out.emitBytes(Contents);
-  }
-  return Error::success();
-}
-
-static Error
-buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
-                    const CompileUnitIdentifiers &ID, StringRef DWPName) {
-  return make_error<DWPError>(
-      std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " +
-      buildDWODescription(PrevE.second.Name, PrevE.second.DWPName,
-                          PrevE.second.DWOName) +
-      " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
-}
-
 static Expected<SmallVector<std::string, 16>>
 getDWOFilenames(StringRef ExecFilename) {
   auto ErrOrObj = object::ObjectFile::createObjectFile(ExecFilename);
@@ -536,160 +76,6 @@
   return std::move(DWOPaths);
 }
 
-static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
-  const auto &MCOFI = *Out.getContext().getObjectFileInfo();
-  MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
-  MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
-  MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection();
-  MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection();
-  MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection();
-  const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = {
-      {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}},
-      {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},
-      {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
-      {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}},
-      {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
-      {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
-      {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
-      {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},
-      {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
-
-  MapVector<uint64_t, UnitIndexEntry> IndexEntries;
-  MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
-
-  uint32_t ContributionOffsets[8] = {};
-
-  DWPStringPool Strings(Out, StrSection);
-
-  SmallVector<OwningBinary<object::ObjectFile>, 128> Objects;
-  Objects.reserve(Inputs.size());
-
-  std::deque<SmallString<32>> UncompressedSections;
-
-  for (const auto &Input : Inputs) {
-    auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
-    if (!ErrOrObj)
-      return ErrOrObj.takeError();
-
-    auto &Obj = *ErrOrObj->getBinary();
-    Objects.push_back(std::move(*ErrOrObj));
-
-    UnitIndexEntry CurEntry = {};
-
-    StringRef CurStrSection;
-    StringRef CurStrOffsetSection;
-    std::vector<StringRef> CurTypesSection;
-    StringRef InfoSection;
-    StringRef AbbrevSection;
-    StringRef CurCUIndexSection;
-    StringRef CurTUIndexSection;
-
-    for (const auto &Section : Obj.sections())
-      if (auto Err = handleSection(
-              KnownSections, StrSection, StrOffsetSection, TypesSection,
-              CUIndexSection, TUIndexSection, Section, Out,
-              UncompressedSections, ContributionOffsets, CurEntry,
-              CurStrSection, CurStrOffsetSection, CurTypesSection, InfoSection,
-              AbbrevSection, CurCUIndexSection, CurTUIndexSection))
-        return Err;
-
-    if (InfoSection.empty())
-      continue;
-
-    writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,
-                           CurStrOffsetSection);
-
-    if (CurCUIndexSection.empty()) {
-      Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
-          AbbrevSection, InfoSection, CurStrOffsetSection, CurStrSection);
-      if (!EID)
-        return createFileError(Input, EID.takeError());
-      const auto &ID = *EID;
-      auto P = IndexEntries.insert(std::make_pair(ID.Signature, CurEntry));
-      if (!P.second)
-        return buildDuplicateError(*P.first, ID, "");
-      P.first->second.Name = ID.Name;
-      P.first->second.DWOName = ID.DWOName;
-      addAllTypes(Out, TypeIndexEntries, TypesSection, CurTypesSection,
-                  CurEntry,
-                  ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]);
-      continue;
-    }
-
-    DWARFUnitIndex CUIndex(DW_SECT_INFO);
-    DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
-    if (!CUIndex.parse(CUIndexData))
-      return make_error<DWPError>("failed to parse cu_index");
-    if (CUIndex.getVersion() != 2)
-      return make_error<DWPError>(
-          "unsupported cu_index version: " + utostr(CUIndex.getVersion()) +
-          " (only version 2 is supported)");
-
-    for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
-      auto *I = E.getContributions();
-      if (!I)
-        continue;
-      auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry));
-      Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
-          getSubsection(AbbrevSection, E, DW_SECT_ABBREV),
-          getSubsection(InfoSection, E, DW_SECT_INFO),
-          getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS),
-          CurStrSection);
-      if (!EID)
-        return createFileError(Input, EID.takeError());
-      const auto &ID = *EID;
-      if (!P.second)
-        return buildDuplicateError(*P.first, ID, Input);
-      auto &NewEntry = P.first->second;
-      NewEntry.Name = ID.Name;
-      NewEntry.DWOName = ID.DWOName;
-      NewEntry.DWPName = Input;
-      for (auto Kind : CUIndex.getColumnKinds()) {
-        if (!isSupportedSectionKind(Kind))
-          continue;
-        auto &C = NewEntry.Contributions[getContributionIndex(Kind)];
-        C.Offset += I->Offset;
-        C.Length = I->Length;
-        ++I;
-      }
-    }
-
-    if (!CurTypesSection.empty()) {
-      if (CurTypesSection.size() != 1)
-        return make_error<DWPError>("multiple type unit sections in .dwp file");
-      DWARFUnitIndex TUIndex(DW_SECT_EXT_TYPES);
-      DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
-      if (!TUIndex.parse(TUIndexData))
-        return make_error<DWPError>("failed to parse tu_index");
-      if (TUIndex.getVersion() != 2)
-        return make_error<DWPError>(
-            "unsupported tu_index version: " + utostr(TUIndex.getVersion()) +
-            " (only version 2 is supported)");
-
-      addAllTypesFromDWP(
-          Out, TypeIndexEntries, TUIndex, TypesSection, CurTypesSection.front(),
-          CurEntry,
-          ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]);
-    }
-  }
-
-  // Lie about there being no info contributions so the TU index only includes
-  // the type unit contribution
-  ContributionOffsets[0] = 0;
-  writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
-             TypeIndexEntries);
-
-  // Lie about the type contribution
-  ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)] = 0;
-  // Unlie about the info contribution
-  ContributionOffsets[0] = 1;
-
-  writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
-             IndexEntries);
-
-  return Error::success();
-}
-
 static int error(const Twine &Error, const Twine &Context) {
   errs() << Twine("while processing ") + Context + ":\n";
   errs() << Twine("error: ") + Error + "\n";
@@ -707,6 +93,7 @@
 int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
 
+  cl::HideUnrelatedOptions({&DwpCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv, "merge split dwarf (.dwo) files\n");
 
   llvm::InitializeAllTargetInfos();
@@ -756,15 +143,16 @@
   if (!MAI)
     return error("no asm info for target " + TripleName, Context);
 
-  MCObjectFileInfo MOFI;
-  MCContext MC(MAI.get(), MRI.get(), &MOFI);
-  MOFI.InitMCObjectFileInfo(*ErrOrTriple, /*PIC*/ false, MC);
-
   std::unique_ptr<MCSubtargetInfo> MSTI(
       TheTarget->createMCSubtargetInfo(TripleName, "", ""));
   if (!MSTI)
     return error("no subtarget info for target " + TripleName, Context);
 
+  MCContext MC(*ErrOrTriple, MAI.get(), MRI.get(), MSTI.get());
+  std::unique_ptr<MCObjectFileInfo> MOFI(
+      TheTarget->createMCObjectFileInfo(MC, /*PIC=*/false));
+  MC.setObjectFileInfo(MOFI.get());
+
   MCTargetOptions Options;
   auto MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, Options);
   if (!MAB)
diff --git a/src/llvm-project/llvm/tools/llvm-elfabi/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-elfabi/CMakeLists.txt
deleted file mode 100644
index 43b4b5b..0000000
--- a/src/llvm-project/llvm/tools/llvm-elfabi/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-set(LLVM_LINK_COMPONENTS
-  InterfaceStub
-  Object
-  Support
-  TextAPI
-  )
-
-add_llvm_tool(llvm-elfabi
-  ErrorCollector.cpp
-  llvm-elfabi.cpp
-  )
diff --git a/src/llvm-project/llvm/tools/llvm-elfabi/llvm-elfabi.cpp b/src/llvm-project/llvm/tools/llvm-elfabi/llvm-elfabi.cpp
deleted file mode 100644
index 761c6a8..0000000
--- a/src/llvm-project/llvm/tools/llvm-elfabi/llvm-elfabi.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-//===- llvm-elfabi.cpp ----------------------------------------------------===//
-//
-// 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
-//
-//===-----------------------------------------------------------------------===/
-
-#include "ErrorCollector.h"
-#include "llvm/InterfaceStub/ELFObjHandler.h"
-#include "llvm/InterfaceStub/TBEHandler.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/raw_ostream.h"
-#include <string>
-
-namespace llvm {
-namespace elfabi {
-
-enum class FileFormat { TBE, ELF };
-
-} // end namespace elfabi
-} // end namespace llvm
-
-using namespace llvm;
-using namespace llvm::elfabi;
-
-// Command line flags:
-cl::opt<FileFormat> InputFileFormat(
-    cl::desc("Force input file format:"),
-    cl::values(clEnumValN(FileFormat::TBE, "tbe",
-                          "Read `input` as text-based ELF stub"),
-               clEnumValN(FileFormat::ELF, "elf",
-                          "Read `input` as ELF binary")));
-cl::opt<std::string> InputFilePath(cl::Positional, cl::desc("input"),
-                                   cl::Required);
-cl::opt<std::string>
-    EmitTBE("emit-tbe",
-            cl::desc("Emit a text-based ELF stub (.tbe) from the input file"),
-            cl::value_desc("path"));
-cl::opt<std::string>
-    SOName("soname",
-           cl::desc("Manually set the DT_SONAME entry of any emitted files"),
-           cl::value_desc("name"));
-cl::opt<ELFTarget> BinaryOutputTarget(
-    "output-target", cl::desc("Create a binary stub for the specified target"),
-    cl::values(clEnumValN(ELFTarget::ELF32LE, "elf32-little",
-                          "32-bit little-endian ELF stub"),
-               clEnumValN(ELFTarget::ELF32BE, "elf32-big",
-                          "32-bit big-endian ELF stub"),
-               clEnumValN(ELFTarget::ELF64LE, "elf64-little",
-                          "64-bit little-endian ELF stub"),
-               clEnumValN(ELFTarget::ELF64BE, "elf64-big",
-                          "64-bit big-endian ELF stub")));
-cl::opt<std::string> BinaryOutputFilePath(cl::Positional, cl::desc("output"));
-cl::opt<bool> WriteIfChanged(
-    "write-if-changed",
-    cl::desc("Write the output file only if it is new or has changed."));
-
-/// writeTBE() writes a Text-Based ELF stub to a file using the latest version
-/// of the YAML parser.
-static Error writeTBE(StringRef FilePath, ELFStub &Stub) {
-  // Write TBE to memory first.
-  std::string TBEStr;
-  raw_string_ostream OutStr(TBEStr);
-  Error YAMLErr = writeTBEToOutputStream(OutStr, Stub);
-  if (YAMLErr)
-    return YAMLErr;
-  OutStr.flush();
-
-  if (WriteIfChanged) {
-    if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
-            MemoryBuffer::getFile(FilePath)) {
-      // Compare TBE output with existing TBE file.
-      // If TBE file unchanged, abort updating.
-      if ((*BufOrError)->getBuffer() == TBEStr)
-        return Error::success();
-    }
-  }
-  // Open TBE file for writing.
-  std::error_code SysErr;
-  raw_fd_ostream Out(FilePath, SysErr);
-  if (SysErr)
-    return createStringError(SysErr, "Couldn't open `%s` for writing",
-                             FilePath.data());
-  Out << TBEStr;
-  return Error::success();
-}
-
-/// readInputFile populates an ELFStub by attempting to read the
-/// input file using both the TBE and binary ELF parsers.
-static Expected<std::unique_ptr<ELFStub>> readInputFile(StringRef FilePath) {
-  // Read in file.
-  ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
-      MemoryBuffer::getFile(FilePath);
-  if (!BufOrError) {
-    return createStringError(BufOrError.getError(), "Could not open `%s`",
-                             FilePath.data());
-  }
-
-  std::unique_ptr<MemoryBuffer> FileReadBuffer = std::move(*BufOrError);
-  ErrorCollector EC(/*UseFatalErrors=*/false);
-
-  // First try to read as a binary (fails fast if not binary).
-  if (InputFileFormat.getNumOccurrences() == 0 ||
-      InputFileFormat == FileFormat::ELF) {
-    Expected<std::unique_ptr<ELFStub>> StubFromELF =
-        readELFFile(FileReadBuffer->getMemBufferRef());
-    if (StubFromELF) {
-      return std::move(*StubFromELF);
-    }
-    EC.addError(StubFromELF.takeError(), "BinaryRead");
-  }
-
-  // Fall back to reading as a tbe.
-  if (InputFileFormat.getNumOccurrences() == 0 ||
-      InputFileFormat == FileFormat::TBE) {
-    Expected<std::unique_ptr<ELFStub>> StubFromTBE =
-        readTBEFromBuffer(FileReadBuffer->getBuffer());
-    if (StubFromTBE) {
-      return std::move(*StubFromTBE);
-    }
-    EC.addError(StubFromTBE.takeError(), "YamlParse");
-  }
-
-  // If both readers fail, build a new error that includes all information.
-  EC.addError(createStringError(errc::not_supported,
-                                "No file readers succeeded reading `%s` "
-                                "(unsupported/malformed file?)",
-                                FilePath.data()),
-              "ReadInputFile");
-  EC.escalateToFatal();
-  return EC.makeError();
-}
-
-static void fatalError(Error Err) {
-  WithColor::defaultErrorHandler(std::move(Err));
-  exit(1);
-}
-
-int main(int argc, char *argv[]) {
-  // Parse arguments.
-  cl::ParseCommandLineOptions(argc, argv);
-
-  Expected<std::unique_ptr<ELFStub>> StubOrErr = readInputFile(InputFilePath);
-  if (!StubOrErr)
-    fatalError(StubOrErr.takeError());
-
-  std::unique_ptr<ELFStub> TargetStub = std::move(StubOrErr.get());
-
-  // Change SoName before emitting stubs.
-  if (SOName.getNumOccurrences() == 1)
-    TargetStub->SoName = SOName;
-
-  if (EmitTBE.getNumOccurrences() == 1) {
-    TargetStub->TbeVersion = TBEVersionCurrent;
-    Error TBEWriteError = writeTBE(EmitTBE, *TargetStub);
-    if (TBEWriteError)
-      fatalError(std::move(TBEWriteError));
-  }
-
-  // Write out binary ELF stub.
-  if (BinaryOutputFilePath.getNumOccurrences() == 1) {
-    if (BinaryOutputTarget.getNumOccurrences() == 0)
-      fatalError(createStringError(errc::not_supported,
-                                   "no binary output target specified."));
-    Error BinaryWriteError = writeBinaryStub(
-        BinaryOutputFilePath, *TargetStub, BinaryOutputTarget, WriteIfChanged);
-    if (BinaryWriteError)
-      fatalError(std::move(BinaryWriteError));
-  }
-}
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-exegesis/CMakeLists.txt
index 0575f2a..f1e1784 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/CMakeLists.txt
@@ -1,4 +1,5 @@
 set(LLVM_LINK_COMPONENTS
+  MC
   MCParser
   Support
   native
@@ -7,6 +8,9 @@
 add_llvm_tool(llvm-exegesis
   DISABLE_LLVM_LINK_LLVM_DYLIB
   llvm-exegesis.cpp
+
+  DEPENDS
+  intrinsics_gen
   )
 
 add_subdirectory(lib)
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/AArch64/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-exegesis/lib/AArch64/CMakeLists.txt
index a251b8f..e416d80 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/AArch64/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/AArch64/CMakeLists.txt
@@ -3,16 +3,19 @@
   ${LLVM_BINARY_DIR}/lib/Target/AArch64
   )
 
-add_library(LLVMExegesisAArch64
-  STATIC
-  Target.cpp
-  )
-
-llvm_update_compile_flags(LLVMExegesisAArch64)
-llvm_map_components_to_libnames(libs
+set(LLVM_LINK_COMPONENTS
   AArch64
   Exegesis
+  Core
+  Support
   )
 
-target_link_libraries(LLVMExegesisAArch64 ${libs})
-set_target_properties(LLVMExegesisAArch64 PROPERTIES FOLDER "Libraries")
+add_llvm_library(LLVMExegesisAArch64
+  DISABLE_LLVM_LINK_LLVM_DYLIB
+  STATIC
+  Target.cpp
+
+  DEPENDS
+  intrinsics_gen
+  AArch64CommonTableGen
+  )
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.cpp
index ac21de1..be360b9 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.cpp
@@ -116,7 +116,7 @@
     raw_svector_ostream OSS(InstPrinterStr);
     InstPrinter_->printInst(&MI, 0, "", *SubtargetInfo_, OSS);
     Bytes = Bytes.drop_front(MISize);
-    Lines.emplace_back(StringRef(InstPrinterStr).trim());
+    Lines.emplace_back(InstPrinterStr.str().trim());
   }
   writeEscaped<Tag>(OS, join(Lines, Separator));
 }
@@ -154,7 +154,8 @@
 Analysis::Analysis(const Target &Target, std::unique_ptr<MCInstrInfo> InstrInfo,
                    const InstructionBenchmarkClustering &Clustering,
                    double AnalysisInconsistencyEpsilon,
-                   bool AnalysisDisplayUnstableOpcodes)
+                   bool AnalysisDisplayUnstableOpcodes,
+                   const std::string &ForceCpuName)
     : Clustering_(Clustering), InstrInfo_(std::move(InstrInfo)),
       AnalysisInconsistencyEpsilonSquared_(AnalysisInconsistencyEpsilon *
                                            AnalysisInconsistencyEpsilon),
@@ -163,18 +164,21 @@
     return;
 
   const InstructionBenchmark &FirstPoint = Clustering.getPoints().front();
+  const std::string CpuName =
+      ForceCpuName.empty() ? FirstPoint.CpuName : ForceCpuName;
   RegInfo_.reset(Target.createMCRegInfo(FirstPoint.LLVMTriple));
   MCTargetOptions MCOptions;
   AsmInfo_.reset(
       Target.createMCAsmInfo(*RegInfo_, FirstPoint.LLVMTriple, MCOptions));
-  SubtargetInfo_.reset(Target.createMCSubtargetInfo(FirstPoint.LLVMTriple,
-                                                    FirstPoint.CpuName, ""));
+  SubtargetInfo_.reset(
+      Target.createMCSubtargetInfo(FirstPoint.LLVMTriple, CpuName, ""));
   InstPrinter_.reset(Target.createMCInstPrinter(
       Triple(FirstPoint.LLVMTriple), 0 /*default variant*/, *AsmInfo_,
       *InstrInfo_, *RegInfo_));
 
-  Context_ = std::make_unique<MCContext>(AsmInfo_.get(), RegInfo_.get(),
-                                         &ObjectFileInfo_);
+  Context_ =
+      std::make_unique<MCContext>(Triple(FirstPoint.LLVMTriple), AsmInfo_.get(),
+                                  RegInfo_.get(), SubtargetInfo_.get());
   Disasm_.reset(Target.createMCDisassembler(*SubtargetInfo_, *Context_));
   assert(Disasm_ && "cannot create MCDisassembler. missing call to "
                     "InitializeXXXTargetDisassembler ?");
@@ -195,9 +199,8 @@
   OS << "\n";
 
   // Write the points.
-  const auto &Clusters = Clustering_.getValidClusters();
-  for (size_t I = 0, E = Clusters.size(); I < E; ++I) {
-    for (const size_t PointId : Clusters[I].PointIndices) {
+  for (const auto &ClusterIt : Clustering_.getValidClusters()) {
+    for (const size_t PointId : ClusterIt.PointIndices) {
       printInstructionRowCsv(PointId, OS);
     }
     OS << "\n\n";
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.h
index 4c1c864..9d8b04c 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.h
@@ -39,7 +39,8 @@
   Analysis(const Target &Target, std::unique_ptr<MCInstrInfo> InstrInfo,
            const InstructionBenchmarkClustering &Clustering,
            double AnalysisInconsistencyEpsilon,
-           bool AnalysisDisplayUnstableOpcodes);
+           bool AnalysisDisplayUnstableOpcodes,
+           const std::string &ForceCpuName = "");
 
   // Prints a csv of instructions for each cluster.
   struct PrintClusters {};
@@ -111,7 +112,6 @@
                     const char *Separator) const;
 
   const InstructionBenchmarkClustering &Clustering_;
-  MCObjectFileInfo ObjectFileInfo_;
   std::unique_ptr<MCContext> Context_;
   std::unique_ptr<MCSubtargetInfo> SubtargetInfo_;
   std::unique_ptr<MCInstrInfo> InstrInfo_;
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
index 5f22e2a..dbf0769 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
@@ -134,8 +134,8 @@
       OS << getRegName(MCOperand.getReg());
     } else if (MCOperand.isImm()) {
       serializeIntegerOperand(OS, MCOperand.getImm());
-    } else if (MCOperand.isFPImm()) {
-      serializeFPOperand(OS, MCOperand.getFPImm());
+    } else if (MCOperand.isDFPImm()) {
+      serializeFPOperand(OS, bit_cast<double>(MCOperand.getDFPImm()));
     } else {
       OS << kInvalidOperand;
     }
@@ -148,7 +148,7 @@
     if (tryDeserializeIntegerOperand(String, IntValue))
       return MCOperand::createImm(IntValue);
     if (tryDeserializeFPOperand(String, DoubleValue))
-      return MCOperand::createFPImm(DoubleValue);
+      return MCOperand::createDFPImm(bit_cast<uint64_t>(DoubleValue));
     if (auto RegNo = getRegNo(String))
       return MCOperand::createReg(*RegNo);
     if (String != kInvalidOperand)
@@ -255,7 +255,7 @@
                      raw_ostream &Out) {
     YamlContext &Context = getTypedContext(Ctx);
     Out << Context.getRegName(RV.Register) << "=0x"
-        << RV.Value.toString(kRadix, kSigned);
+        << toString(RV.Value, kRadix, kSigned);
   }
 
   static StringRef input(StringRef String, void *Ctx,
@@ -334,7 +334,7 @@
 Expected<InstructionBenchmark>
 InstructionBenchmark::readYaml(const LLVMState &State, StringRef Filename) {
   if (auto ExpectedMemoryBuffer =
-          errorOrToExpected(MemoryBuffer::getFile(Filename))) {
+          errorOrToExpected(MemoryBuffer::getFile(Filename, /*IsText=*/true))) {
     yaml::Input Yin(*ExpectedMemoryBuffer.get());
     YamlContext Context(State);
     InstructionBenchmark Benchmark;
@@ -351,7 +351,7 @@
 Expected<std::vector<InstructionBenchmark>>
 InstructionBenchmark::readYamls(const LLVMState &State, StringRef Filename) {
   if (auto ExpectedMemoryBuffer =
-          errorOrToExpected(MemoryBuffer::getFile(Filename))) {
+          errorOrToExpected(MemoryBuffer::getFile(Filename, /*IsText=*/true))) {
     yaml::Input Yin(*ExpectedMemoryBuffer.get());
     YamlContext Context(State);
     std::vector<InstructionBenchmark> Benchmarks;
@@ -401,8 +401,9 @@
       return Err;
   } else {
     int ResultFD = 0;
-    if (auto E = errorCodeToError(openFileForWrite(
-            Filename, ResultFD, sys::fs::CD_CreateAlways, sys::fs::OF_Text))) {
+    if (auto E = errorCodeToError(openFileForWrite(Filename, ResultFD,
+                                                   sys::fs::CD_CreateAlways,
+                                                   sys::fs::OF_TextWithCRLF))) {
       return E;
     }
     raw_fd_ostream Ostr(ResultFD, true /*shouldClose*/);
@@ -422,5 +423,11 @@
   MinValue = std::min(MinValue, BM.PerInstructionValue);
 }
 
+bool operator==(const BenchmarkMeasure &A, const BenchmarkMeasure &B) {
+  return std::tie(A.Key, A.PerInstructionValue, A.PerSnippetValue) ==
+         std::tie(B.Key, B.PerInstructionValue, B.PerSnippetValue);
+}
+
+
 } // namespace exegesis
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
index c883a34..436bd00 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
@@ -67,7 +67,7 @@
   const MCInst &keyInstruction() const { return Key.Instructions[0]; }
   // The number of instructions inside the repeated snippet. For example, if a
   // snippet of 3 instructions is repeated 4 times, this is 12.
-  int NumRepetitions = 0;
+  unsigned NumRepetitions = 0;
   enum RepetitionModeE { Duplicate, Loop, AggregateMin };
   // Note that measurements are per instruction.
   std::vector<BenchmarkMeasure> Measurements;
@@ -91,6 +91,8 @@
   class Error writeYaml(const LLVMState &State, const StringRef Filename);
 };
 
+bool operator==(const BenchmarkMeasure &A, const BenchmarkMeasure &B);
+
 //------------------------------------------------------------------------------
 // Utilities to work with Benchmark measures.
 
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index f3ce184..03e7ccc 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -133,7 +133,7 @@
 } // namespace
 
 Expected<InstructionBenchmark> BenchmarkRunner::runConfiguration(
-    const BenchmarkCode &BC, unsigned NumRepetitions,
+    const BenchmarkCode &BC, unsigned NumRepetitions, unsigned LoopBodySize,
     ArrayRef<std::unique_ptr<const SnippetRepetitor>> Repetitors,
     bool DumpObjectToDisk) const {
   InstructionBenchmark InstrBenchmark;
@@ -168,14 +168,16 @@
     // Assemble at least kMinInstructionsForSnippet instructions by repeating
     // the snippet for debug/analysis. This is so that the user clearly
     // understands that the inside instructions are repeated.
-    constexpr const int kMinInstructionsForSnippet = 16;
+    const int MinInstructionsForSnippet = 4 * Instructions.size();
+    const int LoopBodySizeForSnippet = 2 * Instructions.size();
     {
       SmallString<0> Buffer;
       raw_svector_ostream OS(Buffer);
       if (Error E = assembleToStream(
               State.getExegesisTarget(), State.createTargetMachine(),
               BC.LiveIns, BC.Key.RegisterInitialValues,
-              Repetitor->Repeat(Instructions, kMinInstructionsForSnippet),
+              Repetitor->Repeat(Instructions, MinInstructionsForSnippet,
+                                LoopBodySizeForSnippet),
               OS)) {
         return std::move(E);
       }
@@ -187,8 +189,8 @@
 
     // Assemble NumRepetitions instructions repetitions of the snippet for
     // measurements.
-    const auto Filler =
-        Repetitor->Repeat(Instructions, InstrBenchmark.NumRepetitions);
+    const auto Filler = Repetitor->Repeat(
+        Instructions, InstrBenchmark.NumRepetitions, LoopBodySize);
 
     object::OwningBinary<object::ObjectFile> ObjectFile;
     if (DumpObjectToDisk) {
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
index cc51b5b..b66902e 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
@@ -41,6 +41,7 @@
 
   Expected<InstructionBenchmark>
   runConfiguration(const BenchmarkCode &Configuration, unsigned NumRepetitions,
+                   unsigned LoopUnrollFactor,
                    ArrayRef<std::unique_ptr<const SnippetRepetitor>> Repetitors,
                    bool DumpObjectToDisk) const;
 
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-exegesis/lib/CMakeLists.txt
index 48896d4..2ca0ce4 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/CMakeLists.txt
@@ -19,7 +19,29 @@
 
 set(LLVM_EXEGESIS_TARGETS "${LLVM_EXEGESIS_TARGETS} ${TARGETS_TO_APPEND}" PARENT_SCOPE)
 
-add_library(LLVMExegesis
+set(LLVM_LINK_COMPONENTS
+  Analysis
+  CodeGen
+  Core
+  ExecutionEngine
+  GlobalISel
+  MC
+  MCDisassembler
+  MCJIT
+  MCParser
+  Object
+  ObjectYAML
+  RuntimeDyld
+  Support
+  )
+
+set(libs)
+if(LLVM_ENABLE_LIBPFM AND HAVE_LIBPFM)
+  list(APPEND libs pfm)
+endif()
+
+add_llvm_library(LLVMExegesis
+  DISABLE_LLVM_LINK_LLVM_DYLIB
   STATIC
   Analysis.cpp
   Assembler.cpp
@@ -42,28 +64,9 @@
   SnippetRepetitor.cpp
   Target.cpp
   UopsBenchmarkRunner.cpp
+
+  LINK_LIBS ${libs}
+
+  DEPENDS
+  intrinsics_gen
   )
-
-llvm_update_compile_flags(LLVMExegesis)
-llvm_map_components_to_libnames(libs
-  Analysis
-  CodeGen
-  Core
-  ExecutionEngine
-  GlobalISel
-  MC
-  MCDisassembler
-  MCJIT
-  MCParser
-  Object
-  ObjectYAML
-  RuntimeDyld
-  Support
-  )
-
-if(LLVM_ENABLE_LIBPFM AND HAVE_LIBPFM)
-  list(APPEND libs pfm)
-endif()
-
-target_link_libraries(LLVMExegesis ${libs})
-set_target_properties(LLVMExegesis PROPERTIES FOLDER "Libraries")
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/LlvmState.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
index c8ef642..eb492a5 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
@@ -61,9 +61,10 @@
 }
 
 bool LLVMState::canAssemble(const MCInst &Inst) const {
-  MCObjectFileInfo ObjectFileInfo;
-  MCContext Context(TheTargetMachine->getMCAsmInfo(),
-                    TheTargetMachine->getMCRegisterInfo(), &ObjectFileInfo);
+  MCContext Context(TheTargetMachine->getTargetTriple(),
+                    TheTargetMachine->getMCAsmInfo(),
+                    TheTargetMachine->getMCRegisterInfo(),
+                    TheTargetMachine->getMCSubtargetInfo());
   std::unique_ptr<const MCCodeEmitter> CodeEmitter(
       TheTargetMachine->getTarget().createMCCodeEmitter(
           *TheTargetMachine->getMCInstrInfo(), *TheTargetMachine->getMCRegisterInfo(),
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
index 674db3f..049cc68 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
@@ -374,8 +374,10 @@
     OS << MCRegisterInfo.getName(Op.getReg());
   else if (Op.isImm())
     OS << Op.getImm();
-  else if (Op.isFPImm())
-    OS << Op.getFPImm();
+  else if (Op.isDFPImm())
+    OS << bit_cast<double>(Op.getDFPImm());
+  else if (Op.isSFPImm())
+    OS << bit_cast<float>(Op.getSFPImm());
   else if (Op.isExpr())
     OS << "Expr";
   else if (Op.isInst())
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Mips/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Mips/CMakeLists.txt
index 79bd563..ecf6590 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Mips/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Mips/CMakeLists.txt
@@ -3,16 +3,19 @@
   ${LLVM_BINARY_DIR}/lib/Target/Mips
   )
 
-add_library(LLVMExegesisMips
-  STATIC
-  Target.cpp
-  )
-
-llvm_update_compile_flags(LLVMExegesisMips)
-llvm_map_components_to_libnames(libs
+set(LLVM_LINK_COMPONENTS
   Mips
   Exegesis
+  Core
+  Support
   )
 
-target_link_libraries(LLVMExegesisMips ${libs})
-set_target_properties(LLVMExegesisMips PROPERTIES FOLDER "Libraries")
+add_llvm_library(LLVMExegesisMips
+  DISABLE_LLVM_LINK_LLVM_DYLIB
+  STATIC
+  Target.cpp
+
+  DEPENDS
+  intrinsics_gen
+  MipsCommonTableGen
+  )
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp
index 58e1f4d..8a0b399 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp
@@ -12,9 +12,9 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/raw_ostream.h"
 #ifdef HAVE_LIBPFM
-#include "perfmon/perf_event.h"
-#include "perfmon/pfmlib.h"
-#include "perfmon/pfmlib_perf_event.h"
+#include <perfmon/perf_event.h>
+#include <perfmon/pfmlib.h>
+#include <perfmon/pfmlib_perf_event.h>
 #endif
 
 #include <cassert>
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/PowerPC/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-exegesis/lib/PowerPC/CMakeLists.txt
index 89e3343..29e7f57 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/PowerPC/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/PowerPC/CMakeLists.txt
@@ -3,16 +3,19 @@
   ${LLVM_BINARY_DIR}/lib/Target/PowerPC
   )
 
-add_library(LLVMExegesisPowerPC
-  STATIC
-  Target.cpp
-  )
-
-llvm_update_compile_flags(LLVMExegesisPowerPC)
-llvm_map_components_to_libnames(libs
+set(LLVM_LINK_COMPONENTS
   PowerPC
   Exegesis
+  Core
+  Support
   )
 
-target_link_libraries(LLVMExegesisPowerPC ${libs})
-set_target_properties(LLVMExegesisPowerPC PROPERTIES FOLDER "Libraries")
+add_llvm_library(LLVMExegesisPowerPC
+  DISABLE_LLVM_LINK_LLVM_DYLIB
+  STATIC
+  Target.cpp
+
+  DEPENDS
+  intrinsics_gen
+  PowerPCCommonTableGen
+  )
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
index 504e7bd..962136a 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -42,7 +42,7 @@
   std::vector<unsigned> Opcodes;
   Opcodes.resize(State.getInstrInfo().getNumOpcodes());
   std::iota(Opcodes.begin(), Opcodes.end(), 0U);
-  std::shuffle(Opcodes.begin(), Opcodes.end(), randomGenerator());
+  llvm::shuffle(Opcodes.begin(), Opcodes.end(), randomGenerator());
 
   std::vector<const Instruction *> AliasingInstructions;
   for (const unsigned OtherOpcode : Opcodes) {
@@ -51,7 +51,7 @@
     const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode);
     const MCInstrDesc &OtherInstrDesc = OtherInstr.Description;
     // Ignore instructions that we cannot run.
-    if (OtherInstrDesc.isPseudo() ||
+    if (OtherInstrDesc.isPseudo() || OtherInstrDesc.usesCustomInsertionHook() ||
         OtherInstrDesc.isBranch() || OtherInstrDesc.isIndirectBranch() ||
         OtherInstrDesc.isCall() || OtherInstrDesc.isReturn()) {
           continue;
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
index c71050c..f674beb 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
@@ -130,11 +130,13 @@
 
   BenchmarkCode Result;
 
-  MCObjectFileInfo ObjectFileInfo;
   const TargetMachine &TM = State.getTargetMachine();
-  MCContext Context(TM.getMCAsmInfo(), TM.getMCRegisterInfo(), &ObjectFileInfo);
-  ObjectFileInfo.InitMCObjectFileInfo(TM.getTargetTriple(), /*PIC*/ false,
-                                      Context);
+  MCContext Context(TM.getTargetTriple(), TM.getMCAsmInfo(),
+                    TM.getMCRegisterInfo(), TM.getMCSubtargetInfo());
+  std::unique_ptr<MCObjectFileInfo> ObjectFileInfo(
+      TM.getTarget().createMCObjectFileInfo(Context, /*PIC=*/false));
+  Context.setObjectFileInfo(ObjectFileInfo.get());
+  Context.initInlineSourceManager();
   BenchmarkCodeStreamer Streamer(&Context, TM.getMCRegisterInfo(), &Result);
 
   std::string Error;
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp
index c866e97..1851cb4 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp
@@ -11,6 +11,7 @@
 
 #include "SnippetRepetitor.h"
 #include "Target.h"
+#include "llvm/ADT/Sequence.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 
@@ -24,8 +25,8 @@
 
   // Repeats the snippet until there are at least MinInstructions in the
   // resulting code.
-  FillFunction Repeat(ArrayRef<MCInst> Instructions,
-                      unsigned MinInstructions) const override {
+  FillFunction Repeat(ArrayRef<MCInst> Instructions, unsigned MinInstructions,
+                      unsigned LoopBodySize) const override {
     return [Instructions, MinInstructions](FunctionFiller &Filler) {
       auto Entry = Filler.getEntry();
       if (!Instructions.empty()) {
@@ -53,17 +54,26 @@
             State.getTargetMachine().getTargetTriple())) {}
 
   // Loop over the snippet ceil(MinInstructions / Instructions.Size()) times.
-  FillFunction Repeat(ArrayRef<MCInst> Instructions,
-                      unsigned MinInstructions) const override {
-    return [this, Instructions, MinInstructions](FunctionFiller &Filler) {
+  FillFunction Repeat(ArrayRef<MCInst> Instructions, unsigned MinInstructions,
+                      unsigned LoopBodySize) const override {
+    return [this, Instructions, MinInstructions,
+            LoopBodySize](FunctionFiller &Filler) {
       const auto &ET = State.getExegesisTarget();
       auto Entry = Filler.getEntry();
       auto Loop = Filler.addBasicBlock();
       auto Exit = Filler.addBasicBlock();
 
+      const unsigned LoopUnrollFactor =
+          LoopBodySize <= Instructions.size()
+              ? 1
+              : divideCeil(LoopBodySize, Instructions.size());
+      assert(LoopUnrollFactor >= 1 && "Should end up with at least 1 snippet.");
+
       // Set loop counter to the right value:
-      const APInt LoopCount(32, (MinInstructions + Instructions.size() - 1) /
-                                    Instructions.size());
+      const APInt LoopCount(
+          32,
+          divideCeil(MinInstructions, LoopUnrollFactor * Instructions.size()));
+      assert(LoopCount.uge(1) && "Trip count should be at least 1.");
       for (const MCInst &Inst :
            ET.setRegTo(State.getSubtargetInfo(), LoopCounter, LoopCount))
         Entry.addInstruction(Inst);
@@ -78,7 +88,10 @@
         Loop.MBB->addLiveIn(Reg);
       for (const auto &LiveIn : Entry.MBB->liveins())
         Loop.MBB->addLiveIn(LiveIn);
-      Loop.addInstructions(Instructions);
+      for (auto _ : seq(0U, LoopUnrollFactor)) {
+        (void)_;
+        Loop.addInstructions(Instructions);
+      }
       ET.decrementLoopCounterAndJump(*Loop.MBB, *Loop.MBB,
                                      State.getInstrInfo());
 
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.h
index 038dcac..239fa25 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.h
@@ -39,7 +39,8 @@
   // Returns a functor that repeats `Instructions` so that the function executes
   // at least `MinInstructions` instructions.
   virtual FillFunction Repeat(ArrayRef<MCInst> Instructions,
-                              unsigned MinInstructions) const = 0;
+                              unsigned MinInstructions,
+                              unsigned LoopBodySize) const = 0;
 
   explicit SnippetRepetitor(const LLVMState &State) : State(State) {}
 
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/CMakeLists.txt
index ce3bbd5..da30b9b 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/CMakeLists.txt
@@ -3,17 +3,21 @@
   ${LLVM_BINARY_DIR}/lib/Target/X86
   )
 
-add_library(LLVMExegesisX86
+set(LLVM_LINK_COMPONENTS
+  X86
+  Exegesis
+  Core
+  Support
+  CodeGen
+  )
+
+add_llvm_library(LLVMExegesisX86
+  DISABLE_LLVM_LINK_LLVM_DYLIB
   STATIC
   Target.cpp
   X86Counter.cpp
-  )
 
-llvm_update_compile_flags(LLVMExegesisX86)
-llvm_map_components_to_libnames(libs
-  X86
-  Exegesis
+  DEPENDS
+  intrinsics_gen
+  X86CommonTableGen
   )
-
-target_link_libraries(LLVMExegesisX86 ${libs})
-set_target_properties(LLVMExegesisX86 PROPERTIES FOLDER "Libraries")
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
index 8839f00..1be119a 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
@@ -194,9 +194,25 @@
   const auto OpcodeName = Instr.Name;
   if ((Instr.Description.TSFlags & X86II::FormMask) == X86II::Pseudo)
     return "unsupported opcode: pseudo instruction";
-  if (OpcodeName.startswith("POP") || OpcodeName.startswith("PUSH") ||
-      OpcodeName.startswith("ADJCALLSTACK") || OpcodeName.startswith("LEAVE"))
+  if ((OpcodeName.startswith("POP") && !OpcodeName.startswith("POPCNT")) ||
+      OpcodeName.startswith("PUSH") || OpcodeName.startswith("ADJCALLSTACK") ||
+      OpcodeName.startswith("LEAVE"))
     return "unsupported opcode: Push/Pop/AdjCallStack/Leave";
+  switch (Instr.Description.Opcode) {
+  case X86::LFS16rm:
+  case X86::LFS32rm:
+  case X86::LFS64rm:
+  case X86::LGS16rm:
+  case X86::LGS32rm:
+  case X86::LGS64rm:
+  case X86::LSS16rm:
+  case X86::LSS32rm:
+  case X86::LSS64rm:
+  case X86::SYSENTER:
+    return "unsupported opcode";
+  default:
+    break;
+  }
   if (const auto reason = isInvalidMemoryInstr(Instr))
     return reason;
   // We do not handle instructions with OPERAND_PCREL.
@@ -902,9 +918,9 @@
       continue;
     case X86::OperandType::OPERAND_COND_CODE: {
       Exploration = true;
-      auto CondCodes = seq((int)X86::CondCode::COND_O,
-                           1 + (int)X86::CondCode::LAST_VALID_COND);
-      Choices.reserve(std::distance(CondCodes.begin(), CondCodes.end()));
+      auto CondCodes =
+          seq_inclusive(X86::CondCode::COND_O, X86::CondCode::LAST_VALID_COND);
+      Choices.reserve(CondCodes.size());
       for (int CondCode : CondCodes)
         Choices.emplace_back(MCOperand::createImm(CondCode));
       break;
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp
index 25ec4f8..3fee0e5 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp
@@ -8,17 +8,18 @@
 
 #include "X86Counter.h"
 
+#if defined(__linux__) && defined(HAVE_LIBPFM) &&                              \
+    defined(LIBPFM_HAS_FIELD_CYCLES)
+
 // FIXME: Use appropriate wrappers for poll.h and mman.h
 // to support Windows and remove this linux-only guard.
-#ifdef __linux__
+
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Errc.h"
 
-#ifdef HAVE_LIBPFM
-#include "perfmon/perf_event.h"
-#include "perfmon/pfmlib.h"
-#include "perfmon/pfmlib_perf_event.h"
-#endif // HAVE_LIBPFM
+#include <perfmon/perf_event.h>
+#include <perfmon/pfmlib.h>
+#include <perfmon/pfmlib_perf_event.h>
 
 #include <atomic>
 #include <chrono>
@@ -32,7 +33,6 @@
 #include <sys/mman.h>
 #include <unistd.h>
 
-#if defined(HAVE_LIBPFM) && defined(LIBPFM_HAS_FIELD_CYCLES)
 namespace llvm {
 namespace exegesis {
 
@@ -41,6 +41,10 @@
 static constexpr size_t kBufferPages = 8;
 static const size_t kDataBufferSize = kBufferPages * getpagesize();
 
+// First page is reserved for perf_event_mmap_page. Data buffer starts on
+// the next page, so we allocate one more page.
+static const size_t kMappedBufferSize = (kBufferPages + 1) * getpagesize();
+
 // Waits for the LBR perf events.
 static int pollLbrPerfEvent(const int FileDescriptor) {
   struct pollfd PollFd;
@@ -137,15 +141,16 @@
 
 X86LbrCounter::X86LbrCounter(pfm::PerfEvent &&NewEvent)
     : Counter(std::move(NewEvent)) {
-  // First page is reserved for perf_event_mmap_page. Data buffer starts on
-  // the next page, so we allocate one more page.
-  MMappedBuffer = mmap(nullptr, (kBufferPages + 1) * getpagesize(),
-                       PROT_READ | PROT_WRITE, MAP_SHARED, FileDescriptor, 0);
+  MMappedBuffer = mmap(nullptr, kMappedBufferSize, PROT_READ | PROT_WRITE,
+                       MAP_SHARED, FileDescriptor, 0);
   if (MMappedBuffer == MAP_FAILED)
     llvm::errs() << "Failed to mmap buffer.";
 }
 
-X86LbrCounter::~X86LbrCounter() { close(FileDescriptor); }
+X86LbrCounter::~X86LbrCounter() {
+  if (0 != munmap(MMappedBuffer, kMappedBufferSize))
+    llvm::errs() << "Failed to munmap buffer.";
+}
 
 void X86LbrCounter::start() {
   ioctl(FileDescriptor, PERF_EVENT_IOC_REFRESH, 1024 /* kMaxPollsPerFd */);
@@ -173,6 +178,7 @@
   }
 
   counter.stop();
+  (void)Sum;
 
   auto ResultOrError = counter.doReadCounter(nullptr, nullptr);
   if (ResultOrError)
@@ -251,5 +257,5 @@
 } // namespace exegesis
 } // namespace llvm
 
-#endif //  defined(HAVE_LIBPFM) && defined(LIBPFM_HAS_FIELD_CYCLES)
-#endif // __linux__
+#endif // defined(__linux__) && defined(HAVE_LIBPFM) &&
+       // defined(LIBPFM_HAS_FIELD_CYCLES)
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index 2d20d0e..220f404 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -32,6 +32,7 @@
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/SourceMgr.h"
@@ -115,6 +116,13 @@
                    cl::desc("number of time to repeat the asm snippet"),
                    cl::cat(BenchmarkOptions), cl::init(10000));
 
+static cl::opt<unsigned>
+    LoopBodySize("loop-body-size",
+                 cl::desc("when repeating the instruction snippet by looping "
+                          "over it, duplicate the snippet until the loop body "
+                          "contains at least this many instruction"),
+                 cl::cat(BenchmarkOptions), cl::init(0));
+
 static cl::opt<unsigned> MaxConfigsPerOpcode(
     "max-configs-per-opcode",
     cl::desc(
@@ -251,8 +259,9 @@
   const Instruction &Instr = State.getIC().getInstr(Opcode);
   const MCInstrDesc &InstrDesc = Instr.Description;
   // Ignore instructions that we cannot run.
-  if (InstrDesc.isPseudo())
-    return make_error<Failure>("Unsupported opcode: isPseudo");
+  if (InstrDesc.isPseudo() || InstrDesc.usesCustomInsertionHook())
+    return make_error<Failure>(
+        "Unsupported opcode: isPseudo/usesCustomInserter");
   if (InstrDesc.isBranch() || InstrDesc.isIndirectBranch())
     return make_error<Failure>("Unsupported opcode: isBranch/isIndirectBranch");
   if (InstrDesc.isCall() || InstrDesc.isReturn())
@@ -363,7 +372,7 @@
 
   for (const BenchmarkCode &Conf : Configurations) {
     InstructionBenchmark Result = ExitOnErr(Runner->runConfiguration(
-        Conf, NumRepetitions, Repetitors, DumpObjectToDisk));
+        Conf, NumRepetitions, LoopBodySize, Repetitors, DumpObjectToDisk));
     ExitOnFileError(BenchmarkFile, Result.writeYaml(State, BenchmarkFile));
   }
   exegesis::pfm::pfmTerminate();
@@ -435,7 +444,7 @@
 
   const Analysis Analyzer(*TheTarget, std::move(InstrInfo), Clustering,
                           AnalysisInconsistencyEpsilon,
-                          AnalysisDisplayUnstableOpcodes);
+                          AnalysisDisplayUnstableOpcodes, CpuName);
 
   maybeRunAnalysis<Analysis::PrintClusters>(Analyzer, "analysis clusters",
                                             AnalysisClustersOutputFile);
diff --git a/src/llvm-project/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp b/src/llvm-project/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
index 155eee0..1173ae9 100644
--- a/src/llvm-project/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
+++ b/src/llvm-project/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
@@ -30,6 +30,7 @@
 #include <algorithm>
 #include <cstring>
 #include <inttypes.h>
+#include <iostream>
 #include <map>
 #include <string>
 #include <system_error>
@@ -107,12 +108,20 @@
                     "number of cores on the current machine."),
                cl::value_desc("n"), cat(ConversionOptions));
 
+static opt<bool>
+    Quiet("quiet", desc("Do not output warnings about the debug information"),
+          cat(ConversionOptions));
+
 static list<uint64_t> LookupAddresses("address",
                                       desc("Lookup an address in a GSYM file"),
                                       cl::value_desc("addr"),
                                       cat(LookupOptions));
 
-
+static opt<bool> LookupAddressesFromStdin(
+    "addresses-from-stdin",
+    desc("Lookup addresses in a GSYM file that are read from stdin\nEach input "
+         "line is expected to be of the following format: <addr> <gsym-path>"),
+    cat(LookupOptions));
 
 } // namespace
 /// @}
@@ -133,7 +142,6 @@
   exit(1);
 }
 
-
 /// If the input path is a .dSYM bundle (as created by the dsymutil tool),
 /// replace it with individual entries for each of the object files inside the
 /// bundle otherwise return the input path.
@@ -271,14 +279,13 @@
   return llvm::None;
 }
 
-
 static llvm::Error handleObjectFile(ObjectFile &Obj,
                                     const std::string &OutFile) {
   auto ThreadCount =
       NumThreads > 0 ? NumThreads : std::thread::hardware_concurrency();
   auto &OS = outs();
 
-  GsymCreator Gsym;
+  GsymCreator Gsym(Quiet);
 
   // See if we can figure out the base address for a given object file, and if
   // we can, then set the base address to use to this value. This will ease
@@ -306,8 +313,7 @@
   if (!DICtx)
     return createStringError(std::errc::invalid_argument,
                              "unable to create DWARF context");
-  logAllUnhandledErrors(DICtx->loadRegisterInfo(Obj), OS,
-                        "DwarfTransformer: ");
+  logAllUnhandledErrors(DICtx->loadRegisterInfo(Obj), OS, "DwarfTransformer: ");
 
   // Make a DWARF transformer object and populate the ranges of the code
   // so we don't end up adding invalid functions to GSYM data.
@@ -330,8 +336,8 @@
     return Err;
 
   // Save the GSYM file to disk.
-  support::endianness Endian = Obj.makeTriple().isLittleEndian() ?
-      support::little : support::big;
+  support::endianness Endian =
+      Obj.makeTriple().isLittleEndian() ? support::little : support::big;
   if (auto Err = Gsym.save(OutFile.c_str(), Endian))
     return Err;
 
@@ -360,7 +366,7 @@
     // Iterate over all contained architectures and filter out any that were
     // not specified with the "--arch <arch>" option. If the --arch option was
     // not specified on the command line, we will process all architectures.
-    std::vector< std::unique_ptr<MachOObjectFile> > FilterObjs;
+    std::vector<std::unique_ptr<MachOObjectFile>> FilterObjs;
     for (auto &ObjForArch : Fat->objects()) {
       if (auto MachOOrErr = ObjForArch.getAsObjectFile()) {
         auto &Obj = **MachOOrErr;
@@ -375,7 +381,7 @@
                                         "no matching architectures found"));
 
     // Now handle each architecture we need to convert.
-    for (auto &Obj: FilterObjs) {
+    for (auto &Obj : FilterObjs) {
       Triple ObjTriple(Obj->getArchTriple());
       auto ArchName = ObjTriple.getArchName();
       std::string ArchOutFile(OutFile);
@@ -425,6 +431,27 @@
   return Error::success();
 }
 
+static void doLookup(GsymReader &Gsym, uint64_t Addr, raw_ostream &OS) {
+  if (auto Result = Gsym.lookup(Addr)) {
+    // If verbose is enabled dump the full function info for the address.
+    if (Verbose) {
+      if (auto FI = Gsym.getFunctionInfo(Addr)) {
+        OS << "FunctionInfo for " << HEX64(Addr) << ":\n";
+        Gsym.dump(OS, *FI);
+        OS << "\nLookupResult for " << HEX64(Addr) << ":\n";
+      }
+    }
+    OS << Result.get();
+  } else {
+    if (Verbose)
+      OS << "\nLookupResult for " << HEX64(Addr) << ":\n";
+    OS << HEX64(Addr) << ": ";
+    logAllUnhandledErrors(Result.takeError(), OS, "error: ");
+  }
+  if (Verbose)
+    OS << "\n";
+}
+
 int main(int argc, char const *argv[]) {
   // Print a stack trace if we signal out.
   sys::PrintStackTraceOnErrorSignal(argv[0]);
@@ -441,8 +468,7 @@
       "lookup addresses within that GSYM file.\n"
       "Use the --convert option to specify a file with option --out-file "
       "option to convert to GSYM format.\n";
-  HideUnrelatedOptions(
-      {&GeneralOptions, &ConversionOptions, &LookupOptions});
+  HideUnrelatedOptions({&GeneralOptions, &ConversionOptions, &LookupOptions});
   cl::ParseCommandLineOptions(argc, argv, Overview);
 
   if (Help) {
@@ -465,6 +491,50 @@
     return 0;
   }
 
+  if (LookupAddressesFromStdin) {
+    if (!LookupAddresses.empty() || !InputFilenames.empty()) {
+      OS << "error: no input files or addresses can be specified when using "
+            "the --addresses-from-stdin "
+            "option.\n";
+      return 1;
+    }
+
+    std::string InputLine;
+    std::string CurrentGSYMPath;
+    llvm::Optional<Expected<GsymReader>> CurrentGsym;
+
+    while (std::getline(std::cin, InputLine)) {
+      // Strip newline characters.
+      std::string StrippedInputLine(InputLine);
+      llvm::erase_if(StrippedInputLine,
+                     [](char c) { return c == '\r' || c == '\n'; });
+
+      StringRef AddrStr, GSYMPath;
+      std::tie(AddrStr, GSYMPath) =
+          llvm::StringRef{StrippedInputLine}.split(' ');
+
+      if (GSYMPath != CurrentGSYMPath) {
+        CurrentGsym = GsymReader::openFile(GSYMPath);
+        if (!*CurrentGsym)
+          error(GSYMPath, CurrentGsym->takeError());
+      }
+
+      uint64_t Addr;
+      if (AddrStr.getAsInteger(0, Addr)) {
+        OS << "error: invalid address " << AddrStr
+           << ", expected: Address GsymFile.\n";
+        return 1;
+      }
+
+      doLookup(**CurrentGsym, Addr, OS);
+
+      OS << "\n";
+      OS.flush();
+    }
+
+    return EXIT_SUCCESS;
+  }
+
   // Dump or access data inside GSYM files
   for (const auto &GSYMPath : InputFilenames) {
     auto Gsym = GsymReader::openFile(GSYMPath);
@@ -478,25 +548,8 @@
 
     // Lookup an address in a GSYM file and print any matches.
     OS << "Looking up addresses in \"" << GSYMPath << "\":\n";
-    for (auto Addr: LookupAddresses) {
-      if (auto Result = Gsym->lookup(Addr)) {
-        // If verbose is enabled dump the full function info for the address.
-        if (Verbose) {
-          if (auto FI = Gsym->getFunctionInfo(Addr)) {
-            OS << "FunctionInfo for " << HEX64(Addr) << ":\n";
-            Gsym->dump(OS, *FI);
-            OS << "\nLookupResult for " << HEX64(Addr) << ":\n";
-          }
-        }
-        OS << Result.get();
-      } else {
-        if (Verbose)
-          OS << "\nLookupResult for " << HEX64(Addr) << ":\n";
-        OS << HEX64(Addr) << ": ";
-        logAllUnhandledErrors(Result.takeError(), OS, "error: ");
-      }
-      if (Verbose)
-        OS << "\n";
+    for (auto Addr : LookupAddresses) {
+      doLookup(*Gsym, Addr, OS);
     }
   }
   return EXIT_SUCCESS;
diff --git a/src/llvm-project/llvm/tools/llvm-ifs/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-ifs/CMakeLists.txt
index 544b0e4..5a0cfb9 100644
--- a/src/llvm-project/llvm/tools/llvm-ifs/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-ifs/CMakeLists.txt
@@ -1,4 +1,6 @@
 set(LLVM_LINK_COMPONENTS
+  BinaryFormat
+  InterfaceStub  
   Object
   Support
   TextAPI
@@ -6,5 +8,6 @@
   )
 
 add_llvm_tool(llvm-ifs
+  ErrorCollector.cpp
   llvm-ifs.cpp
   )
diff --git a/src/llvm-project/llvm/tools/llvm-elfabi/ErrorCollector.cpp b/src/llvm-project/llvm/tools/llvm-ifs/ErrorCollector.cpp
similarity index 98%
rename from src/llvm-project/llvm/tools/llvm-elfabi/ErrorCollector.cpp
rename to src/llvm-project/llvm/tools/llvm-ifs/ErrorCollector.cpp
index a52aeff..087a30c 100644
--- a/src/llvm-project/llvm/tools/llvm-elfabi/ErrorCollector.cpp
+++ b/src/llvm-project/llvm/tools/llvm-ifs/ErrorCollector.cpp
@@ -14,7 +14,7 @@
 #include <vector>
 
 using namespace llvm;
-using namespace llvm::elfabi;
+using namespace llvm::ifs;
 
 void ErrorCollector::escalateToFatal() { ErrorsAreFatal = true; }
 
diff --git a/src/llvm-project/llvm/tools/llvm-elfabi/ErrorCollector.h b/src/llvm-project/llvm/tools/llvm-ifs/ErrorCollector.h
similarity index 93%
rename from src/llvm-project/llvm/tools/llvm-elfabi/ErrorCollector.h
rename to src/llvm-project/llvm/tools/llvm-ifs/ErrorCollector.h
index e2eb1c5..67996f4 100644
--- a/src/llvm-project/llvm/tools/llvm-elfabi/ErrorCollector.h
+++ b/src/llvm-project/llvm/tools/llvm-ifs/ErrorCollector.h
@@ -18,14 +18,14 @@
 ///
 //===-----------------------------------------------------------------------===/
 
-#ifndef LLVM_TOOLS_ELFABI_ERRORCOLLECTOR_H
-#define LLVM_TOOLS_ELFABI_ERRORCOLLECTOR_H
+#ifndef LLVM_TOOLS_LLVM_IFS_ERRORCOLLECTOR_H
+#define LLVM_TOOLS_LLVM_IFS_ERRORCOLLECTOR_H
 
 #include "llvm/Support/Error.h"
 #include <vector>
 
 namespace llvm {
-namespace elfabi {
+namespace ifs {
 
 class ErrorCollector {
 public:
@@ -68,7 +68,7 @@
   std::vector<std::string> Tags;
 };
 
-} // end namespace elfabi
+} // end namespace ifs
 } // end namespace llvm
 
-#endif // LLVM_TOOLS_ELFABI_ERRORCOLLECTOR_H
+#endif // LLVM_TOOLS_LLVM_IFS_ERRORCOLLECTOR_H
diff --git a/src/llvm-project/llvm/tools/llvm-ifs/llvm-ifs.cpp b/src/llvm-project/llvm/tools/llvm-ifs/llvm-ifs.cpp
index 4d9a5c3..7726996 100644
--- a/src/llvm-project/llvm/tools/llvm-ifs/llvm-ifs.cpp
+++ b/src/llvm-project/llvm/tools/llvm-ifs/llvm-ifs.cpp
@@ -6,9 +6,13 @@
 //
 //===-----------------------------------------------------------------------===/
 
+#include "ErrorCollector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/InterfaceStub/ELFObjHandler.h"
+#include "llvm/InterfaceStub/IFSHandler.h"
+#include "llvm/InterfaceStub/IFSStub.h"
 #include "llvm/ObjectYAML/yaml2obj.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
@@ -21,9 +25,9 @@
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/YAMLTraits.h"
 #include "llvm/Support/raw_ostream.h"
-#include "llvm/TextAPI/MachO/InterfaceFile.h"
-#include "llvm/TextAPI/MachO/TextAPIReader.h"
-#include "llvm/TextAPI/MachO/TextAPIWriter.h"
+#include "llvm/TextAPI/InterfaceFile.h"
+#include "llvm/TextAPI/TextAPIReader.h"
+#include "llvm/TextAPI/TextAPIWriter.h"
 #include <set>
 #include <string>
 #include <vector>
@@ -31,36 +35,82 @@
 using namespace llvm;
 using namespace llvm::yaml;
 using namespace llvm::MachO;
+using namespace llvm::ifs;
 
 #define DEBUG_TYPE "llvm-ifs"
 
 namespace {
-const VersionTuple IFSVersionCurrent(2, 0);
+const VersionTuple IfsVersionCurrent(3, 0);
+
+enum class FileFormat { IFS, ELF, TBD };
 } // end anonymous namespace
 
-static cl::opt<std::string> Action("action", cl::desc("<llvm-ifs action>"),
-                                   cl::value_desc("write-ifs | write-bin"),
-                                   cl::init("write-ifs"));
+cl::OptionCategory IfsCategory("Ifs Options");
 
-static cl::opt<std::string> ForceFormat("force-format",
-                                        cl::desc("<force object format>"),
-                                        cl::value_desc("ELF | TBD"),
-                                        cl::init(""));
-
-static cl::list<std::string> InputFilenames(cl::Positional,
-                                            cl::desc("<input ifs files>"),
-                                            cl::ZeroOrMore);
-
-static cl::opt<std::string> OutputFilename("o", cl::desc("<output file>"),
-                                           cl::value_desc("path"));
-
-enum class IFSSymbolType {
-  NoType = 0,
-  Object,
-  Func,
-  // Type information is 4 bits, so 16 is safely out of range.
-  Unknown = 16,
-};
+// TODO: Use OptTable for option parsing in the future.
+// Command line flags:
+cl::list<std::string> InputFilePaths(cl::Positional, cl::desc("input"),
+                                     cl::ZeroOrMore, cl::cat(IfsCategory));
+cl::opt<FileFormat> InputFormat(
+    "input-format", cl::desc("Specify the input file format"),
+    cl::values(clEnumValN(FileFormat::IFS, "IFS", "Text based ELF stub file"),
+               clEnumValN(FileFormat::ELF, "ELF", "ELF object file")),
+    cl::cat(IfsCategory));
+cl::opt<FileFormat> OutputFormat(
+    "output-format", cl::desc("Specify the output file format"),
+    cl::values(clEnumValN(FileFormat::IFS, "IFS", "Text based ELF stub file"),
+               clEnumValN(FileFormat::ELF, "ELF", "ELF stub file"),
+               clEnumValN(FileFormat::TBD, "TBD", "Apple TBD text stub file")),
+    cl::Required, cl::cat(IfsCategory));
+cl::opt<std::string> OptArch("arch",
+                             cl::desc("Specify the architecture, e.g. x86_64"),
+                             cl::cat(IfsCategory));
+cl::opt<IFSBitWidthType>
+    OptBitWidth("bitwidth", cl::desc("Specify the bit width"),
+                cl::values(clEnumValN(IFSBitWidthType::IFS32, "32", "32 bits"),
+                           clEnumValN(IFSBitWidthType::IFS64, "64", "64 bits")),
+                cl::cat(IfsCategory));
+cl::opt<IFSEndiannessType> OptEndianness(
+    "endianness", cl::desc("Specify the endianness"),
+    cl::values(clEnumValN(IFSEndiannessType::Little, "little", "Little Endian"),
+               clEnumValN(IFSEndiannessType::Big, "big", "Big Endian")),
+    cl::cat(IfsCategory));
+cl::opt<std::string> OptTargetTriple(
+    "target", cl::desc("Specify the target triple, e.g. x86_64-linux-gnu"),
+    cl::cat(IfsCategory));
+cl::opt<std::string> OptTargetTripleHint(
+    "hint-ifs-target",
+    cl::desc("When --output-format is 'IFS', this flag will hint the expected "
+             "target triple for IFS output"),
+    cl::cat(IfsCategory));
+cl::opt<bool> StripIFSArch(
+    "strip-ifs-arch",
+    cl::desc("Strip target architecture information away from IFS output"),
+    cl::cat(IfsCategory));
+cl::opt<bool> StripIFSBitWidth(
+    "strip-ifs-bitwidth",
+    cl::desc("Strip target bit width information away from IFS output"),
+    cl::cat(IfsCategory));
+cl::opt<bool> StripIFSEndiannessWidth(
+    "strip-ifs-endianness",
+    cl::desc("Strip target endianness information away from IFS output"),
+    cl::cat(IfsCategory));
+cl::opt<bool> StripIFSTarget(
+    "strip-ifs-target",
+    cl::desc("Strip all target information away from IFS output"),
+    cl::cat(IfsCategory));
+cl::opt<std::string>
+    SoName("soname",
+           cl::desc("Manually set the DT_SONAME entry of any emitted files"),
+           cl::value_desc("name"), cl::cat(IfsCategory));
+cl::opt<std::string> OutputFilePath("output", cl::desc("Output file"),
+                                    cl::cat(IfsCategory));
+cl::alias OutputFilePathA("o", cl::desc("Alias for --output"),
+                          cl::aliasopt(OutputFilePath), cl::cat(IfsCategory));
+cl::opt<bool> WriteIfChanged(
+    "write-if-changed",
+    cl::desc("Write the output file only if it is new or has changed."),
+    cl::cat(IfsCategory));
 
 static std::string getTypeName(IFSSymbolType Type) {
   switch (Type) {
@@ -70,131 +120,63 @@
     return "Func";
   case IFSSymbolType::Object:
     return "Object";
+  case IFSSymbolType::TLS:
+    return "TLS";
   case IFSSymbolType::Unknown:
     return "Unknown";
   }
   llvm_unreachable("Unexpected ifs symbol type.");
 }
 
-struct IFSSymbol {
-  IFSSymbol() = default;
-  IFSSymbol(std::string SymbolName) : Name(SymbolName) {}
-  std::string Name;
-  uint64_t Size;
-  IFSSymbolType Type;
-  bool Weak;
-  Optional<std::string> Warning;
-  bool operator<(const IFSSymbol &RHS) const { return Name < RHS.Name; }
-};
-
-LLVM_YAML_IS_SEQUENCE_VECTOR(IFSSymbol)
-
-namespace llvm {
-namespace yaml {
-/// YAML traits for IFSSymbolType.
-template <> struct ScalarEnumerationTraits<IFSSymbolType> {
-  static void enumeration(IO &IO, IFSSymbolType &SymbolType) {
-    IO.enumCase(SymbolType, "NoType", IFSSymbolType::NoType);
-    IO.enumCase(SymbolType, "Func", IFSSymbolType::Func);
-    IO.enumCase(SymbolType, "Object", IFSSymbolType::Object);
-    IO.enumCase(SymbolType, "Unknown", IFSSymbolType::Unknown);
-    // Treat other symbol types as noise, and map to Unknown.
-    if (!IO.outputting() && IO.matchEnumFallback())
-      SymbolType = IFSSymbolType::Unknown;
-  }
-};
-
-/// YAML traits for IFSSymbol.
-template <> struct MappingTraits<IFSSymbol> {
-  static void mapping(IO &IO, IFSSymbol &Symbol) {
-    IO.mapRequired("Name", Symbol.Name);
-    IO.mapRequired("Type", Symbol.Type);
-    // The need for symbol size depends on the symbol type.
-    if (Symbol.Type == IFSSymbolType::NoType)
-      IO.mapOptional("Size", Symbol.Size, (uint64_t)0);
-    else if (Symbol.Type == IFSSymbolType::Func)
-      Symbol.Size = 0;
-    else
-      IO.mapRequired("Size", Symbol.Size);
-    IO.mapOptional("Weak", Symbol.Weak, false);
-    IO.mapOptional("Warning", Symbol.Warning);
-  }
-
-  // Compacts symbol information into a single line.
-  static const bool flow = true;
-};
-
-} // namespace yaml
-} // namespace llvm
-
-// A cumulative representation of ELF stubs.
-// Both textual and binary stubs will read into and write from this object.
-class IFSStub {
-  // TODO: Add support for symbol versioning.
-public:
-  VersionTuple IfsVersion;
-  std::string Triple;
-  std::string ObjectFileFormat;
-  Optional<std::string> SOName;
-  std::vector<std::string> NeededLibs;
-  std::vector<IFSSymbol> Symbols;
-
-  IFSStub() = default;
-  IFSStub(const IFSStub &Stub)
-      : IfsVersion(Stub.IfsVersion), Triple(Stub.Triple),
-        ObjectFileFormat(Stub.ObjectFileFormat), SOName(Stub.SOName),
-        NeededLibs(Stub.NeededLibs), Symbols(Stub.Symbols) {}
-  IFSStub(IFSStub &&Stub)
-      : IfsVersion(std::move(Stub.IfsVersion)), Triple(std::move(Stub.Triple)),
-        ObjectFileFormat(std::move(Stub.ObjectFileFormat)),
-        SOName(std::move(Stub.SOName)), NeededLibs(std::move(Stub.NeededLibs)),
-        Symbols(std::move(Stub.Symbols)) {}
-};
-
-namespace llvm {
-namespace yaml {
-/// YAML traits for IFSStub objects.
-template <> struct MappingTraits<IFSStub> {
-  static void mapping(IO &IO, IFSStub &Stub) {
-    if (!IO.mapTag("!experimental-ifs-v2", true))
-      IO.setError("Not a .ifs YAML file.");
-
-    auto OldContext = IO.getContext();
-    IO.setContext(&Stub);
-    IO.mapRequired("IfsVersion", Stub.IfsVersion);
-    IO.mapOptional("Triple", Stub.Triple);
-    IO.mapOptional("ObjectFileFormat", Stub.ObjectFileFormat);
-    IO.mapOptional("SOName", Stub.SOName);
-    IO.mapOptional("NeededLibs", Stub.NeededLibs);
-    IO.mapRequired("Symbols", Stub.Symbols);
-    IO.setContext(&OldContext);
-  }
-};
-} // namespace yaml
-} // namespace llvm
-
 static Expected<std::unique_ptr<IFSStub>> readInputFile(StringRef FilePath) {
   // Read in file.
   ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
-      MemoryBuffer::getFileOrSTDIN(FilePath);
+      MemoryBuffer::getFileOrSTDIN(FilePath, /*IsText=*/true);
   if (!BufOrError)
     return createStringError(BufOrError.getError(), "Could not open `%s`",
                              FilePath.data());
 
   std::unique_ptr<MemoryBuffer> FileReadBuffer = std::move(*BufOrError);
-  yaml::Input YamlIn(FileReadBuffer->getBuffer());
-  std::unique_ptr<IFSStub> Stub(new IFSStub());
-  YamlIn >> *Stub;
+  ErrorCollector EC(/*UseFatalErrors=*/false);
 
-  if (std::error_code Err = YamlIn.error())
-    return createStringError(Err, "Failed reading Interface Stub File.");
+  // First try to read as a binary (fails fast if not binary).
+  if (InputFormat.getNumOccurrences() == 0 || InputFormat == FileFormat::ELF) {
+    Expected<std::unique_ptr<IFSStub>> StubFromELF =
+        readELFFile(FileReadBuffer->getMemBufferRef());
+    if (StubFromELF) {
+      (*StubFromELF)->IfsVersion = IfsVersionCurrent;
+      return std::move(*StubFromELF);
+    }
+    EC.addError(StubFromELF.takeError(), "BinaryRead");
+  }
 
-  if (Stub->IfsVersion > IFSVersionCurrent)
-    return make_error<StringError>(
-        "IFS version " + Stub->IfsVersion.getAsString() + " is unsupported.",
-        std::make_error_code(std::errc::invalid_argument));
+  // Fall back to reading as a ifs.
+  if (InputFormat.getNumOccurrences() == 0 || InputFormat == FileFormat::IFS) {
+    Expected<std::unique_ptr<IFSStub>> StubFromIFS =
+        readIFSFromBuffer(FileReadBuffer->getBuffer());
+    if (StubFromIFS) {
+      if ((*StubFromIFS)->IfsVersion > IfsVersionCurrent)
+        EC.addError(
+            createStringError(errc::not_supported,
+                              "IFS version " +
+                                  (*StubFromIFS)->IfsVersion.getAsString() +
+                                  " is unsupported."),
+            "ReadInputFile");
+      else
+        return std::move(*StubFromIFS);
+    } else {
+      EC.addError(StubFromIFS.takeError(), "YamlParse");
+    }
+  }
 
-  return std::move(Stub);
+  // If both readers fail, build a new error that includes all information.
+  EC.addError(createStringError(errc::not_supported,
+                                "No file readers succeeded reading `%s` "
+                                "(unsupported/malformed file?)",
+                                FilePath.data()),
+              "ReadInputFile");
+  EC.escalateToFatal();
+  return EC.makeError();
 }
 
 static int writeTbdStub(const Triple &T, const std::vector<IFSSymbol> &Symbols,
@@ -213,10 +195,6 @@
     if (T.isiOS())
       return llvm::MachO::PlatformKind::iOS;
 
-    // TODO: Add an option for ForceTriple, but keep ForceFormat for now.
-    if (ForceFormat == "TBD")
-      return llvm::MachO::PlatformKind::macOS;
-
     return createStringError(errc::not_supported, "Invalid Platform.\n");
   }(T);
 
@@ -259,154 +237,70 @@
   return 0;
 }
 
-static int writeElfStub(const Triple &T, const std::vector<IFSSymbol> &Symbols,
-                        const StringRef Format, raw_ostream &Out) {
-  SmallString<0> Storage;
-  Storage.clear();
-  raw_svector_ostream OS(Storage);
-
-  OS << "--- !ELF\n";
-  OS << "FileHeader:\n";
-  OS << "  Class:           ELFCLASS";
-  OS << (T.isArch64Bit() ? "64" : "32");
-  OS << "\n";
-  OS << "  Data:            ELFDATA2";
-  OS << (T.isLittleEndian() ? "LSB" : "MSB");
-  OS << "\n";
-  OS << "  Type:            ET_DYN\n";
-  OS << "  Machine:         "
-     << llvm::StringSwitch<llvm::StringRef>(T.getArchName())
-            .Case("x86_64", "EM_X86_64")
-            .Case("i386", "EM_386")
-            .Case("i686", "EM_386")
-            .Case("aarch64", "EM_AARCH64")
-            .Case("amdgcn", "EM_AMDGPU")
-            .Case("r600", "EM_AMDGPU")
-            .Case("arm", "EM_ARM")
-            .Case("thumb", "EM_ARM")
-            .Case("avr", "EM_AVR")
-            .Case("mips", "EM_MIPS")
-            .Case("mipsel", "EM_MIPS")
-            .Case("mips64", "EM_MIPS")
-            .Case("mips64el", "EM_MIPS")
-            .Case("msp430", "EM_MSP430")
-            .Case("ppc", "EM_PPC")
-            .Case("ppc64", "EM_PPC64")
-            .Case("ppc64le", "EM_PPC64")
-            .Case("x86", T.isOSIAMCU() ? "EM_IAMCU" : "EM_386")
-            .Case("x86_64", "EM_X86_64")
-            .Default("EM_NONE")
-     << "\nSections:"
-     << "\n  - Name:            .text"
-     << "\n    Type:            SHT_PROGBITS"
-     << "\n  - Name:            .data"
-     << "\n    Type:            SHT_PROGBITS"
-     << "\n  - Name:            .rodata"
-     << "\n    Type:            SHT_PROGBITS"
-     << "\nSymbols:\n";
-  for (const auto &Symbol : Symbols) {
-    OS << "  - Name:            " << Symbol.Name << "\n"
-       << "    Type:            STT_";
-    switch (Symbol.Type) {
-    default:
-    case IFSSymbolType::NoType:
-      OS << "NOTYPE";
-      break;
-    case IFSSymbolType::Object:
-      OS << "OBJECT";
-      break;
-    case IFSSymbolType::Func:
-      OS << "FUNC";
-      break;
-    }
-    OS << "\n    Section:         .text"
-       << "\n    Binding:         STB_" << (Symbol.Weak ? "WEAK" : "GLOBAL")
-       << "\n";
-  }
-  OS << "...\n";
-
-  std::string YamlStr = std::string(OS.str());
-
-  // Only or debugging. Not an offical format.
-  LLVM_DEBUG({
-    if (ForceFormat == "ELFOBJYAML") {
-      Out << YamlStr;
-      return 0;
-    }
-  });
-
-  yaml::Input YIn(YamlStr);
-  auto ErrHandler = [](const Twine &Msg) {
-    WithColor::error(errs(), "llvm-ifs") << Msg << "\n";
-  };
-  return convertYAML(YIn, Out, ErrHandler) ? 0 : 1;
+static void fatalError(Error Err) {
+  WithColor::defaultErrorHandler(std::move(Err));
+  exit(1);
 }
 
-static int writeIfso(const IFSStub &Stub, bool IsWriteIfs, raw_ostream &Out) {
-  if (IsWriteIfs) {
-    yaml::Output YamlOut(Out, NULL, /*WrapColumn =*/0);
-    YamlOut << const_cast<IFSStub &>(Stub);
-    return 0;
+/// writeIFS() writes a Text-Based ELF stub to a file using the latest version
+/// of the YAML parser.
+static Error writeIFS(StringRef FilePath, IFSStub &Stub) {
+  // Write IFS to memory first.
+  std::string IFSStr;
+  raw_string_ostream OutStr(IFSStr);
+  Error YAMLErr = writeIFSToOutputStream(OutStr, Stub);
+  if (YAMLErr)
+    return YAMLErr;
+  OutStr.flush();
+
+  if (WriteIfChanged) {
+    if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
+            MemoryBuffer::getFile(FilePath)) {
+      // Compare IFS output with the existing IFS file. If unchanged, avoid changing the file.
+      if ((*BufOrError)->getBuffer() == IFSStr)
+        return Error::success();
+    }
   }
-
-  std::string ObjectFileFormat =
-      ForceFormat.empty() ? Stub.ObjectFileFormat : ForceFormat;
-
-  if (ObjectFileFormat == "ELF" || ForceFormat == "ELFOBJYAML")
-    return writeElfStub(llvm::Triple(Stub.Triple), Stub.Symbols,
-                        Stub.ObjectFileFormat, Out);
-  if (ObjectFileFormat == "TBD")
-    return writeTbdStub(llvm::Triple(Stub.Triple), Stub.Symbols,
-                        Stub.ObjectFileFormat, Out);
-
-  WithColor::error()
-      << "Invalid ObjectFileFormat: Only ELF and TBD are supported.\n";
-  return -1;
+  // Open IFS file for writing.
+  std::error_code SysErr;
+  raw_fd_ostream Out(FilePath, SysErr);
+  if (SysErr)
+    return createStringError(SysErr, "Couldn't open `%s` for writing",
+                             FilePath.data());
+  Out << IFSStr;
+  return Error::success();
 }
 
-// TODO: Drop ObjectFileFormat, it can be subsumed from the triple.
-// New Interface Stubs Yaml Format:
-// --- !experimental-ifs-v2
-// IfsVersion: 2.0
-// Triple:          <llvm triple>
-// ObjectFileFormat: <ELF | others not yet supported>
-// Symbols:
-//   _ZSymbolName: { Type: <type> }
-// ...
-
 int main(int argc, char *argv[]) {
   // Parse arguments.
+  cl::HideUnrelatedOptions({&IfsCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv);
 
-  if (InputFilenames.empty())
-    InputFilenames.push_back("-");
+  if (InputFilePaths.empty())
+    InputFilePaths.push_back("-");
 
+  // If input files are more than one, they can only be IFS files.
+  if (InputFilePaths.size() > 1)
+    InputFormat.setValue(FileFormat::IFS);
+
+  // Attempt to merge input.
   IFSStub Stub;
   std::map<std::string, IFSSymbol> SymbolMap;
-
   std::string PreviousInputFilePath;
-  for (const std::string &InputFilePath : InputFilenames) {
+  for (const std::string &InputFilePath : InputFilePaths) {
     Expected<std::unique_ptr<IFSStub>> StubOrErr = readInputFile(InputFilePath);
-    if (!StubOrErr) {
-      WithColor::error() << StubOrErr.takeError() << "\n";
-      return -1;
-    }
-    std::unique_ptr<IFSStub> TargetStub = std::move(StubOrErr.get());
+    if (!StubOrErr)
+      fatalError(StubOrErr.takeError());
 
-    if (Stub.Triple.empty()) {
-      PreviousInputFilePath = InputFilePath;
+    std::unique_ptr<IFSStub> TargetStub = std::move(StubOrErr.get());
+    if (PreviousInputFilePath.empty()) {
       Stub.IfsVersion = TargetStub->IfsVersion;
-      Stub.Triple = TargetStub->Triple;
-      Stub.ObjectFileFormat = TargetStub->ObjectFileFormat;
-      Stub.SOName = TargetStub->SOName;
+      Stub.Target = TargetStub->Target;
+      Stub.SoName = TargetStub->SoName;
       Stub.NeededLibs = TargetStub->NeededLibs;
     } else {
-      Stub.ObjectFileFormat = !Stub.ObjectFileFormat.empty()
-                                  ? Stub.ObjectFileFormat
-                                  : TargetStub->ObjectFileFormat;
-
       if (Stub.IfsVersion != TargetStub->IfsVersion) {
-        if (Stub.IfsVersion.getMajor() != IFSVersionCurrent.getMajor()) {
+        if (Stub.IfsVersion.getMajor() != IfsVersionCurrent.getMajor()) {
           WithColor::error()
               << "Interface Stub: IfsVersion Mismatch."
               << "\nFilenames: " << PreviousInputFilePath << " "
@@ -417,29 +311,20 @@
         if (TargetStub->IfsVersion > Stub.IfsVersion)
           Stub.IfsVersion = TargetStub->IfsVersion;
       }
-      if (Stub.ObjectFileFormat != TargetStub->ObjectFileFormat &&
-          !TargetStub->ObjectFileFormat.empty()) {
-        WithColor::error() << "Interface Stub: ObjectFileFormat Mismatch."
+      if (Stub.Target != TargetStub->Target && !TargetStub->Target.empty()) {
+        WithColor::error() << "Interface Stub: Target Mismatch."
                            << "\nFilenames: " << PreviousInputFilePath << " "
-                           << InputFilePath << "\nObjectFileFormat Values: "
-                           << Stub.ObjectFileFormat << " "
-                           << TargetStub->ObjectFileFormat << "\n";
+                           << InputFilePath;
+        //  << "\nTriple Values: " << Stub.Triple << " "
+        //  << TargetStub->Triple << "\n";
         return -1;
       }
-      if (Stub.Triple != TargetStub->Triple && !TargetStub->Triple.empty()) {
-        WithColor::error() << "Interface Stub: Triple Mismatch."
+      if (Stub.SoName != TargetStub->SoName) {
+        WithColor::error() << "Interface Stub: SoName Mismatch."
                            << "\nFilenames: " << PreviousInputFilePath << " "
                            << InputFilePath
-                           << "\nTriple Values: " << Stub.Triple << " "
-                           << TargetStub->Triple << "\n";
-        return -1;
-      }
-      if (Stub.SOName != TargetStub->SOName) {
-        WithColor::error() << "Interface Stub: SOName Mismatch."
-                           << "\nFilenames: " << PreviousInputFilePath << " "
-                           << InputFilePath
-                           << "\nSOName Values: " << Stub.SOName << " "
-                           << TargetStub->SOName << "\n";
+                           << "\nSoName Values: " << Stub.SoName << " "
+                           << TargetStub->SoName << "\n";
         return -1;
       }
       if (Stub.NeededLibs != TargetStub->NeededLibs) {
@@ -487,26 +372,92 @@
     PreviousInputFilePath = InputFilePath;
   }
 
-  if (Stub.IfsVersion != IFSVersionCurrent)
-    if (Stub.IfsVersion.getMajor() != IFSVersionCurrent.getMajor()) {
+  if (Stub.IfsVersion != IfsVersionCurrent)
+    if (Stub.IfsVersion.getMajor() != IfsVersionCurrent.getMajor()) {
       WithColor::error() << "Interface Stub: Bad IfsVersion: "
                          << Stub.IfsVersion << ", llvm-ifs supported version: "
-                         << IFSVersionCurrent << ".\n";
+                         << IfsVersionCurrent << ".\n";
       return -1;
     }
 
   for (auto &Entry : SymbolMap)
     Stub.Symbols.push_back(Entry.second);
 
-  std::error_code SysErr;
+  // Change SoName before emitting stubs.
+  if (SoName.getNumOccurrences() == 1)
+    Stub.SoName = SoName;
+  Optional<IFSArch> OverrideArch;
+  Optional<IFSEndiannessType> OverrideEndianness;
+  Optional<IFSBitWidthType> OverrideBitWidth;
+  Optional<std::string> OverrideTriple;
+  if (OptArch.getNumOccurrences() == 1)
+    OverrideArch = ELF::convertArchNameToEMachine(OptArch.getValue());
+  if (OptEndianness.getNumOccurrences() == 1)
+    OverrideEndianness = OptEndianness.getValue();
+  if (OptBitWidth.getNumOccurrences() == 1)
+    OverrideBitWidth = OptBitWidth.getValue();
+  if (OptTargetTriple.getNumOccurrences() == 1)
+    OverrideTriple = OptTargetTriple.getValue();
+  Error OverrideError = overrideIFSTarget(
+      Stub, OverrideArch, OverrideEndianness, OverrideBitWidth, OverrideTriple);
+  if (OverrideError)
+    fatalError(std::move(OverrideError));
 
-  // Open file for writing.
-  raw_fd_ostream Out(OutputFilename, SysErr);
-  if (SysErr) {
-    WithColor::error() << "Couldn't open " << OutputFilename
-                       << " for writing.\n";
-    return -1;
+  switch (OutputFormat.getValue()) {
+  case FileFormat::TBD: {
+    std::error_code SysErr;
+    raw_fd_ostream Out(OutputFilePath, SysErr);
+    if (SysErr) {
+      WithColor::error() << "Couldn't open " << OutputFilePath
+                         << " for writing.\n";
+      return -1;
+    }
+    if (!Stub.Target.Triple) {
+      WithColor::error()
+          << "Triple should be defined when output format is TBD";
+      return -1;
+    }
+    return writeTbdStub(llvm::Triple(Stub.Target.Triple.getValue()),
+                        Stub.Symbols, "TBD", Out);
   }
+  case FileFormat::IFS: {
+    Stub.IfsVersion = IfsVersionCurrent;
+    if (InputFormat.getValue() == FileFormat::ELF &&
+        OptTargetTripleHint.getNumOccurrences() == 1) {
+      std::error_code HintEC(1, std::generic_category());
+      IFSTarget HintTarget = parseTriple(OptTargetTripleHint);
+      if (Stub.Target.Arch.getValue() != HintTarget.Arch.getValue())
+        fatalError(make_error<StringError>(
+            "Triple hint does not match the actual architecture", HintEC));
+      if (Stub.Target.Endianness.getValue() !=
+          HintTarget.Endianness.getValue())
+        fatalError(make_error<StringError>(
+            "Triple hint does not match the actual endianness", HintEC));
+      if (Stub.Target.BitWidth.getValue() != HintTarget.BitWidth.getValue())
+        fatalError(make_error<StringError>(
+            "Triple hint does not match the actual bit width", HintEC));
 
-  return writeIfso(Stub, (Action == "write-ifs"), Out);
+      stripIFSTarget(Stub, true, false, false, false);
+      Stub.Target.Triple = OptTargetTripleHint.getValue();
+    } else {
+      stripIFSTarget(Stub, StripIFSTarget, StripIFSArch,
+                     StripIFSEndiannessWidth, StripIFSBitWidth);
+    }
+    Error IFSWriteError = writeIFS(OutputFilePath.getValue(), Stub);
+    if (IFSWriteError)
+      fatalError(std::move(IFSWriteError));
+    break;
+  }
+  case FileFormat::ELF: {
+    Error TargetError = validateIFSTarget(Stub, true);
+    if (TargetError)
+      fatalError(std::move(TargetError));
+    Error BinaryWriteError =
+        writeBinaryStub(OutputFilePath, Stub, WriteIfChanged);
+    if (BinaryWriteError)
+      fatalError(std::move(BinaryWriteError));
+    break;
+  }
+  }
+  return 0;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-jitlink/CMakeLists.txt
index 90b4ca6..c9f9a53 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/CMakeLists.txt
@@ -24,6 +24,10 @@
   llvm-jitlink-macho.cpp
   )
 
+if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
+  target_link_libraries(llvm-jitlink PRIVATE network)
+endif()
+
 if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
   target_link_libraries(llvm-jitlink PRIVATE socket nsl)
 endif()
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
index beb73fb..5efdff6 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
@@ -116,11 +116,15 @@
           return make_error<StringError>("zero-fill atom in GOT section",
                                          inconvertibleErrorCode());
 
-        if (auto TS = getELFGOTTarget(G, Sym->getBlock()))
-          FileInfo.GOTEntryInfos[TS->getName()] = {Sym->getSymbolContent(),
-                                                   Sym->getAddress()};
-        else
-          return TS.takeError();
+        // If this is a GOT symbol with size (i.e. not the GOT start symbol)
+        // then add it to the GOT entry info table.
+        if (Sym->getSize() != 0) {
+          if (auto TS = getELFGOTTarget(G, Sym->getBlock()))
+            FileInfo.GOTEntryInfos[TS->getName()] = {Sym->getSymbolContent(),
+                                                     Sym->getAddress()};
+          else
+            return TS.takeError();
+        }
         SectionContainsContent = true;
       } else if (isStubsSection) {
         if (Sym->isSymbolZeroFill())
@@ -133,8 +137,9 @@
         else
           return TS.takeError();
         SectionContainsContent = true;
-      } else if (Sym->hasName()) {
-        dbgs() << "Symbol: " << Sym->getName() << "\n";
+      }
+
+      if (Sym->hasName()) {
         if (Sym->isSymbolZeroFill()) {
           S.SymbolInfos[Sym->getName()] = {Sym->getSize(), Sym->getAddress()};
           SectionContainsZeroFill = true;
@@ -159,7 +164,7 @@
       FileInfo.SectionInfos[Sec.getName()] = {SecSize, SecAddr};
     else
       FileInfo.SectionInfos[Sec.getName()] = {
-          StringRef(FirstSym->getBlock().getContent().data(), SecSize),
+          ArrayRef<char>(FirstSym->getBlock().getContent().data(), SecSize),
           SecAddr};
   }
 
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/CMakeLists.txt
index a183857..7e4570c 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/CMakeLists.txt
@@ -11,7 +11,10 @@
   intrinsics_gen
 )
 
-message(${CMAKE_SYSTEM_NAME})
+if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
+  target_link_libraries(llvm-jitlink-executor PRIVATE network)
+endif()
+
 if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
   target_link_libraries(llvm-jitlink-executor PRIVATE socket)
 endif()
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp
index fd7e30f..7f197a5 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp
@@ -12,15 +12,19 @@
 
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ExecutionEngine/Orc/Shared/FDRawByteChannel.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
 #include "llvm/Support/DynamicLibrary.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
+#include <cstring>
 #include <sstream>
 
 #ifdef LLVM_ON_UNIX
 
+#include <netdb.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
 
@@ -33,7 +37,8 @@
 
 LLVM_ATTRIBUTE_USED void linkComponents() {
   errs() << (void *)&llvm_orc_registerEHFrameSectionWrapper
-         << (void *)&llvm_orc_deregisterEHFrameSectionWrapper;
+         << (void *)&llvm_orc_deregisterEHFrameSectionWrapper
+         << (void *)&llvm_orc_registerJITLoaderGDBWrapper;
 }
 
 void printErrorAndExit(Twine ErrMsg) {
@@ -44,37 +49,58 @@
   exit(1);
 }
 
-int openListener(std::string Host, int Port) {
+int openListener(std::string Host, std::string PortStr) {
 #ifndef LLVM_ON_UNIX
   // FIXME: Add TCP support for Windows.
   printErrorAndExit("listen option not supported");
   return 0;
 #else
-  int SockFD = socket(PF_INET, SOCK_STREAM, 0);
-  struct sockaddr_in ServerAddr, ClientAddr;
-  socklen_t ClientAddrLen = sizeof(ClientAddr);
-  memset(&ServerAddr, 0, sizeof(ServerAddr));
-  ServerAddr.sin_family = PF_INET;
-  ServerAddr.sin_family = INADDR_ANY;
-  ServerAddr.sin_port = htons(Port);
+  addrinfo Hints{};
+  Hints.ai_family = AF_INET;
+  Hints.ai_socktype = SOCK_STREAM;
+  Hints.ai_flags = AI_PASSIVE;
 
-  {
-    // lose the "Address already in use" error message
-    int Yes = 1;
-    if (setsockopt(SockFD, SOL_SOCKET, SO_REUSEADDR, &Yes, sizeof(int)) == -1) {
-      errs() << "Error calling setsockopt.\n";
-      exit(1);
-    }
-  }
-
-  if (bind(SockFD, (struct sockaddr *)&ServerAddr, sizeof(ServerAddr)) < 0) {
-    errs() << "Error on binding.\n";
+  addrinfo *AI;
+  if (int EC = getaddrinfo(nullptr, PortStr.c_str(), &Hints, &AI)) {
+    errs() << "Error setting up bind address: " << gai_strerror(EC) << "\n";
     exit(1);
   }
 
-  listen(SockFD, 1);
-  return accept(SockFD, (struct sockaddr *)&ClientAddr, &ClientAddrLen);
+  // Create a socket from first addrinfo structure returned by getaddrinfo.
+  int SockFD;
+  if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0) {
+    errs() << "Error creating socket: " << std::strerror(errno) << "\n";
+    exit(1);
+  }
+
+  // Avoid "Address already in use" errors.
+  const int Yes = 1;
+  if (setsockopt(SockFD, SOL_SOCKET, SO_REUSEADDR, &Yes, sizeof(int)) == -1) {
+    errs() << "Error calling setsockopt: " << std::strerror(errno) << "\n";
+    exit(1);
+  }
+
+  // Bind the socket to the desired port.
+  if (bind(SockFD, AI->ai_addr, AI->ai_addrlen) < 0) {
+    errs() << "Error on binding: " << std::strerror(errno) << "\n";
+    exit(1);
+  }
+
+  // Listen for incomming connections.
+  static constexpr int ConnectionQueueLen = 1;
+  listen(SockFD, ConnectionQueueLen);
+
+  outs() << "Listening at " << Host << ":" << PortStr << "\n";
+
+#if defined(_AIX)
+  assert(Hi_32(AI->ai_addrlen) == 0 && "Field is a size_t on 64-bit AIX");
+  socklen_t AddrLen = Lo_32(AI->ai_addrlen);
+  return accept(SockFD, AI->ai_addr, &AddrLen);
+#else
+  return accept(SockFD, AI->ai_addr, &AI->ai_addrlen);
 #endif
+
+#endif // LLVM_ON_UNIX
 }
 
 int main(int argc, char *argv[]) {
@@ -103,9 +129,11 @@
 
       int Port = 0;
       if (PortStr.getAsInteger(10, Port))
-        printErrorAndExit("port" + PortStr + " is not a valid integer");
+        printErrorAndExit("port number '" + PortStr +
+                          "' is not a valid integer");
 
-      InFD = OutFD = openListener(Host.str(), Port);
+      InFD = OutFD = openListener(Host.str(), PortStr.str());
+      outs() << "Connection established. Running OrcRPCTPCServer...\n";
     } else
       printErrorAndExit("invalid specifier type \"" + SpecifierType + "\"");
   }
@@ -113,7 +141,7 @@
   ExitOnErr.setBanner(std::string(argv[0]) + ":");
 
   using JITLinkExecutorEndpoint =
-      shared::MultiThreadedRPCEndpoint<shared::FDRawByteChannel>;
+      shared::SingleThreadedRPCEndpoint<shared::FDRawByteChannel>;
 
   shared::registerStringError<shared::FDRawByteChannel>();
 
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp
index fc70934..7bd6bde 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp
@@ -159,7 +159,7 @@
       FileInfo.SectionInfos[Sec.getName()] = {SecSize, SecAddr};
     else
       FileInfo.SectionInfos[Sec.getName()] = {
-          StringRef(FirstSym->getBlock().getContent().data(), SecSize),
+          ArrayRef<char>(FirstSym->getBlock().getContent().data(), SecSize),
           SecAddr};
   }
 
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index da4a164..8bd384e 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -15,9 +15,14 @@
 #include "llvm-jitlink.h"
 
 #include "llvm/BinaryFormat/Magic.h"
+#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
+#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
+#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
+#include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h"
 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
-#include "llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h"
-#include "llvm/ExecutionEngine/Orc/TPCEHFrameRegistrar.h"
+#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
@@ -33,11 +38,13 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/Process.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/Timer.h"
 
+#include <cstring>
 #include <list>
 #include <string>
 
@@ -54,107 +61,138 @@
 using namespace llvm::jitlink;
 using namespace llvm::orc;
 
+static cl::OptionCategory JITLinkCategory("JITLink Options");
+
 static cl::list<std::string> InputFiles(cl::Positional, cl::OneOrMore,
-                                        cl::desc("input files"));
+                                        cl::desc("input files"),
+                                        cl::cat(JITLinkCategory));
 
 static cl::opt<bool> NoExec("noexec", cl::desc("Do not execute loaded code"),
-                            cl::init(false));
+                            cl::init(false), cl::cat(JITLinkCategory));
 
 static cl::list<std::string>
     CheckFiles("check", cl::desc("File containing verifier checks"),
-               cl::ZeroOrMore);
+               cl::ZeroOrMore, cl::cat(JITLinkCategory));
 
 static cl::opt<std::string>
     CheckName("check-name", cl::desc("Name of checks to match against"),
-              cl::init("jitlink-check"));
+              cl::init("jitlink-check"), cl::cat(JITLinkCategory));
 
 static cl::opt<std::string>
     EntryPointName("entry", cl::desc("Symbol to call as main entry point"),
-                   cl::init(""));
+                   cl::init(""), cl::cat(JITLinkCategory));
 
 static cl::list<std::string> JITLinkDylibs(
-    "jld", cl::desc("Specifies the JITDylib to be used for any subsequent "
-                    "input file arguments"));
+    "jld",
+    cl::desc("Specifies the JITDylib to be used for any subsequent "
+             "input file arguments"),
+    cl::cat(JITLinkCategory));
 
 static cl::list<std::string>
     Dylibs("dlopen", cl::desc("Dynamic libraries to load before linking"),
-           cl::ZeroOrMore);
+           cl::ZeroOrMore, cl::cat(JITLinkCategory));
 
 static cl::list<std::string> InputArgv("args", cl::Positional,
                                        cl::desc("<program arguments>..."),
-                                       cl::ZeroOrMore, cl::PositionalEatsArgs);
+                                       cl::ZeroOrMore, cl::PositionalEatsArgs,
+                                       cl::cat(JITLinkCategory));
 
 static cl::opt<bool>
     NoProcessSymbols("no-process-syms",
                      cl::desc("Do not resolve to llvm-jitlink process symbols"),
-                     cl::init(false));
+                     cl::init(false), cl::cat(JITLinkCategory));
 
 static cl::list<std::string> AbsoluteDefs(
     "define-abs",
     cl::desc("Inject absolute symbol definitions (syntax: <name>=<addr>)"),
-    cl::ZeroOrMore);
+    cl::ZeroOrMore, cl::cat(JITLinkCategory));
 
 static cl::list<std::string> TestHarnesses("harness", cl::Positional,
                                            cl::desc("Test harness files"),
                                            cl::ZeroOrMore,
-                                           cl::PositionalEatsArgs);
+                                           cl::PositionalEatsArgs,
+                                           cl::cat(JITLinkCategory));
 
 static cl::opt<bool> ShowInitialExecutionSessionState(
     "show-init-es",
     cl::desc("Print ExecutionSession state before resolving entry point"),
-    cl::init(false));
+    cl::init(false), cl::cat(JITLinkCategory));
 
 static cl::opt<bool> ShowAddrs(
     "show-addrs",
     cl::desc("Print registered symbol, section, got and stub addresses"),
-    cl::init(false));
+    cl::init(false), cl::cat(JITLinkCategory));
 
 static cl::opt<bool> ShowLinkGraph(
     "show-graph",
     cl::desc("Print the link graph after fixups have been applied"),
-    cl::init(false));
+    cl::init(false), cl::cat(JITLinkCategory));
 
 static cl::opt<bool> ShowSizes(
     "show-sizes",
     cl::desc("Show sizes pre- and post-dead stripping, and allocations"),
-    cl::init(false));
+    cl::init(false), cl::cat(JITLinkCategory));
 
 static cl::opt<bool> ShowTimes("show-times",
                                cl::desc("Show times for llvm-jitlink phases"),
-                               cl::init(false));
+                               cl::init(false), cl::cat(JITLinkCategory));
 
 static cl::opt<std::string> SlabAllocateSizeString(
     "slab-allocate",
     cl::desc("Allocate from a slab of the given size "
              "(allowable suffixes: Kb, Mb, Gb. default = "
              "Kb)"),
-    cl::init(""));
+    cl::init(""), cl::cat(JITLinkCategory));
 
 static cl::opt<uint64_t> SlabAddress(
     "slab-address",
     cl::desc("Set slab target address (requires -slab-allocate and -noexec)"),
-    cl::init(~0ULL));
+    cl::init(~0ULL), cl::cat(JITLinkCategory));
 
 static cl::opt<bool> ShowRelocatedSectionContents(
     "show-relocated-section-contents",
     cl::desc("show section contents after fixups have been applied"),
-    cl::init(false));
+    cl::init(false), cl::cat(JITLinkCategory));
 
 static cl::opt<bool> PhonyExternals(
     "phony-externals",
     cl::desc("resolve all otherwise unresolved externals to null"),
-    cl::init(false));
+    cl::init(false), cl::cat(JITLinkCategory));
 
 static cl::opt<std::string> OutOfProcessExecutor(
     "oop-executor", cl::desc("Launch an out-of-process executor to run code"),
-    cl::ValueOptional);
+    cl::ValueOptional, cl::cat(JITLinkCategory));
 
 static cl::opt<std::string> OutOfProcessExecutorConnect(
     "oop-executor-connect",
-    cl::desc("Connect to an out-of-process executor via TCP"));
+    cl::desc("Connect to an out-of-process executor via TCP"),
+    cl::cat(JITLinkCategory));
+
+// TODO: Default to false if compiler-rt is not built.
+static cl::opt<bool> UseOrcRuntime("use-orc-runtime",
+                                   cl::desc("Do not required/load ORC runtime"),
+                                   cl::init(true), cl::cat(JITLinkCategory));
+
+static cl::opt<std::string>
+    OrcRuntimePath("orc-runtime-path", cl::desc("Add orc runtime to session"),
+                   cl::init(""), cl::cat(JITLinkCategory));
 
 ExitOnError ExitOnErr;
 
+LLVM_ATTRIBUTE_USED void linkComponents() {
+  errs() << (void *)&llvm_orc_registerEHFrameSectionWrapper
+         << (void *)&llvm_orc_deregisterEHFrameSectionWrapper
+         << (void *)&llvm_orc_registerJITLoaderGDBWrapper;
+}
+
+static bool UseTestResultOverride = false;
+static int64_t TestResultOverride = 0;
+
+extern "C" void llvm_jitlink_setTestResultOverride(int64_t Value) {
+  TestResultOverride = Value;
+  UseTestResultOverride = true;
+}
+
 namespace llvm {
 
 static raw_ostream &
@@ -290,8 +328,9 @@
       JITTargetAddress SymStart = Sym->getAddress();
       JITTargetAddress SymSize = Sym->getSize();
       JITTargetAddress SymEnd = SymStart + SymSize;
-      const uint8_t *SymData =
-          IsZeroFill ? nullptr : Sym->getSymbolContent().bytes_begin();
+      const uint8_t *SymData = IsZeroFill ? nullptr
+                                          : reinterpret_cast<const uint8_t *>(
+                                                Sym->getSymbolContent().data());
 
       // Pad any space before the symbol starts.
       while (NextAddr != SymStart) {
@@ -466,12 +505,12 @@
 
   uint64_t Units = 1024;
 
-  if (SizeString.endswith_lower("kb"))
+  if (SizeString.endswith_insensitive("kb"))
     SizeString = SizeString.drop_back(2).rtrim();
-  else if (SizeString.endswith_lower("mb")) {
+  else if (SizeString.endswith_insensitive("mb")) {
     Units = 1024 * 1024;
     SizeString = SizeString.drop_back(2).rtrim();
-  } else if (SizeString.endswith_lower("gb")) {
+  } else if (SizeString.endswith_insensitive("gb")) {
     Units = 1024 * 1024 * 1024;
     SizeString = SizeString.drop_back(2).rtrim();
   }
@@ -575,8 +614,33 @@
   return JD.define(std::move(MU), std::move(RT));
 }
 
-Expected<std::unique_ptr<TargetProcessControl>>
-LLVMJITLinkRemoteTargetProcessControl::LaunchExecutor() {
+static Error loadProcessSymbols(Session &S) {
+  auto FilterMainEntryPoint =
+      [EPName = S.ES.intern(EntryPointName)](SymbolStringPtr Name) {
+        return Name != EPName;
+      };
+  S.MainJD->addGenerator(
+      ExitOnErr(orc::EPCDynamicLibrarySearchGenerator::GetForTargetProcess(
+          S.ES, std::move(FilterMainEntryPoint))));
+
+  return Error::success();
+}
+
+static Error loadDylibs(Session &S) {
+  LLVM_DEBUG(dbgs() << "Loading dylibs...\n");
+  for (const auto &Dylib : Dylibs) {
+    LLVM_DEBUG(dbgs() << "  " << Dylib << "\n");
+    auto G = orc::EPCDynamicLibrarySearchGenerator::Load(S.ES, Dylib.c_str());
+    if (!G)
+      return G.takeError();
+    S.MainJD->addGenerator(std::move(*G));
+  }
+
+  return Error::success();
+}
+
+Expected<std::unique_ptr<ExecutorProcessControl>>
+LLVMJITLinkRemoteExecutorProcessControl::LaunchExecutor() {
 #ifndef LLVM_ON_UNIX
   // FIXME: Add support for Windows.
   return make_error<StringError>("-" + OutOfProcessExecutor.ArgStr +
@@ -648,18 +712,64 @@
   };
 
   Error Err = Error::success();
-  std::unique_ptr<LLVMJITLinkRemoteTargetProcessControl> RTPC(
-      new LLVMJITLinkRemoteTargetProcessControl(
+  std::unique_ptr<LLVMJITLinkRemoteExecutorProcessControl> REPC(
+      new LLVMJITLinkRemoteExecutorProcessControl(
           std::move(SSP), std::move(Channel), std::move(Endpoint),
           std::move(ReportError), Err));
   if (Err)
     return std::move(Err);
-  return std::move(RTPC);
+  return std::move(REPC);
 #endif
 }
 
-Expected<std::unique_ptr<TargetProcessControl>>
-LLVMJITLinkRemoteTargetProcessControl::ConnectToExecutor() {
+#ifdef LLVM_ON_UNIX
+static Error createTCPSocketError(Twine Details) {
+  return make_error<StringError>(
+      formatv("Failed to connect TCP socket '{0}': {1}",
+              OutOfProcessExecutorConnect, Details),
+      inconvertibleErrorCode());
+}
+
+static Expected<int> connectTCPSocket(std::string Host, std::string PortStr) {
+  addrinfo *AI;
+  addrinfo Hints{};
+  Hints.ai_family = AF_INET;
+  Hints.ai_socktype = SOCK_STREAM;
+  Hints.ai_flags = AI_NUMERICSERV;
+
+  if (int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI))
+    return createTCPSocketError("Address resolution failed (" +
+                                StringRef(gai_strerror(EC)) + ")");
+
+  // Cycle through the returned addrinfo structures and connect to the first
+  // reachable endpoint.
+  int SockFD;
+  addrinfo *Server;
+  for (Server = AI; Server != nullptr; Server = Server->ai_next) {
+    // socket might fail, e.g. if the address family is not supported. Skip to
+    // the next addrinfo structure in such a case.
+    if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0)
+      continue;
+
+    // If connect returns null, we exit the loop with a working socket.
+    if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0)
+      break;
+
+    close(SockFD);
+  }
+  freeaddrinfo(AI);
+
+  // If we reached the end of the loop without connecting to a valid endpoint,
+  // dump the last error that was logged in socket() or connect().
+  if (Server == nullptr)
+    return createTCPSocketError(std::strerror(errno));
+
+  return SockFD;
+}
+#endif
+
+Expected<std::unique_ptr<ExecutorProcessControl>>
+LLVMJITLinkRemoteExecutorProcessControl::ConnectToExecutor() {
 #ifndef LLVM_ON_UNIX
   // FIXME: Add TCP support for Windows.
   return make_error<StringError>("-" + OutOfProcessExecutorConnect.ArgStr +
@@ -669,42 +779,27 @@
 
   shared::registerStringError<LLVMJITLinkChannel>();
 
-  StringRef HostNameStr, PortStr;
-  std::tie(HostNameStr, PortStr) =
-      StringRef(OutOfProcessExecutorConnect).split(':');
-
-  if (HostNameStr.empty())
-    return make_error<StringError>("host name for -" +
-                                       OutOfProcessExecutorConnect.ArgStr +
-                                       " can not be empty",
-                                   inconvertibleErrorCode());
+  StringRef Host, PortStr;
+  std::tie(Host, PortStr) = StringRef(OutOfProcessExecutorConnect).split(':');
+  if (Host.empty())
+    return createTCPSocketError("Host name for -" +
+                                OutOfProcessExecutorConnect.ArgStr +
+                                " can not be empty");
   if (PortStr.empty())
-    return make_error<StringError>(
-        "port for -" + OutOfProcessExecutorConnect.ArgStr + " can not be empty",
-        inconvertibleErrorCode());
-
-  std::string HostName = HostNameStr.str();
+    return createTCPSocketError("Port number in -" +
+                                OutOfProcessExecutorConnect.ArgStr +
+                                " can not be empty");
   int Port = 0;
   if (PortStr.getAsInteger(10, Port))
-    return make_error<StringError>("port number " + PortStr +
-                                       " is not a valid integer",
-                                   inconvertibleErrorCode());
+    return createTCPSocketError("Port number '" + PortStr +
+                                "' is not a valid integer");
 
-  int SockFD = socket(PF_INET, SOCK_STREAM, 0);
-  hostent *Server = gethostbyname(HostName.c_str());
-  sockaddr_in ServAddr;
-  memset(&ServAddr, 0, sizeof(ServAddr));
-  ServAddr.sin_family = PF_INET;
-  memmove(&Server->h_addr, &ServAddr.sin_addr.s_addr, Server->h_length);
-  ServAddr.sin_port = htons(Port);
-  if (connect(SockFD, reinterpret_cast<sockaddr *>(&ServAddr),
-              sizeof(ServAddr)) < 0)
-    return make_error<StringError>("Failed to connect to " + HostName + ":" +
-                                       Twine(Port),
-                                   inconvertibleErrorCode());
+  Expected<int> SockFD = connectTCPSocket(Host.str(), PortStr.str());
+  if (!SockFD)
+    return SockFD.takeError();
 
   auto SSP = std::make_shared<SymbolStringPool>();
-  auto Channel = std::make_unique<shared::FDRawByteChannel>(SockFD, SockFD);
+  auto Channel = std::make_unique<shared::FDRawByteChannel>(*SockFD, *SockFD);
   auto Endpoint = std::make_unique<LLVMJITLinkRPCEndpoint>(*Channel, true);
 
   auto ReportError = [](Error Err) {
@@ -712,17 +807,17 @@
   };
 
   Error Err = Error::success();
-  std::unique_ptr<LLVMJITLinkRemoteTargetProcessControl> RTPC(
-      new LLVMJITLinkRemoteTargetProcessControl(
+  std::unique_ptr<LLVMJITLinkRemoteExecutorProcessControl> REPC(
+      new LLVMJITLinkRemoteExecutorProcessControl(
           std::move(SSP), std::move(Channel), std::move(Endpoint),
           std::move(ReportError), Err));
   if (Err)
     return std::move(Err);
-  return std::move(RTPC);
+  return std::move(REPC);
 #endif
 }
 
-Error LLVMJITLinkRemoteTargetProcessControl::disconnect() {
+Error LLVMJITLinkRemoteExecutorProcessControl::disconnect() {
   std::promise<MSVCPError> P;
   auto F = P.get_future();
   auto Err = closeConnection([&](Error Err) -> Error {
@@ -752,27 +847,33 @@
   if (!PageSize)
     return PageSize.takeError();
 
-  /// If -oop-executor is passed then launch the executor.
-  std::unique_ptr<TargetProcessControl> TPC;
+  std::unique_ptr<ExecutorProcessControl> EPC;
   if (OutOfProcessExecutor.getNumOccurrences()) {
-    if (auto RTPC = LLVMJITLinkRemoteTargetProcessControl::LaunchExecutor())
-      TPC = std::move(*RTPC);
+    /// If -oop-executor is passed then launch the executor.
+    if (auto REPC = LLVMJITLinkRemoteExecutorProcessControl::LaunchExecutor())
+      EPC = std::move(*REPC);
     else
-      return RTPC.takeError();
+      return REPC.takeError();
   } else if (OutOfProcessExecutorConnect.getNumOccurrences()) {
-    if (auto RTPC = LLVMJITLinkRemoteTargetProcessControl::ConnectToExecutor())
-      TPC = std::move(*RTPC);
+    /// If -oop-executor-connect is passed then connect to the executor.
+    if (auto REPC =
+            LLVMJITLinkRemoteExecutorProcessControl::ConnectToExecutor())
+      EPC = std::move(*REPC);
     else
-      return RTPC.takeError();
-  } else
-    TPC = std::make_unique<SelfTargetProcessControl>(
+      return REPC.takeError();
+  } else {
+    /// Otherwise use SelfExecutorProcessControl to target the current process.
+    EPC = std::make_unique<SelfExecutorProcessControl>(
         std::make_shared<SymbolStringPool>(), std::move(TT), *PageSize,
         createMemoryManager());
+  }
 
   Error Err = Error::success();
-  std::unique_ptr<Session> S(new Session(std::move(TPC), Err));
-  if (Err)
-    return std::move(Err);
+  std::unique_ptr<Session> S(new Session(std::move(EPC), Err));
+
+  // FIXME: Errors destroy the session, leaving the SymbolStringPtrs dangling,
+  // so just exit here. We could fix this by having errors keep the pool alive.
+  ExitOnErr(std::move(Err));
   return std::move(S);
 }
 
@@ -781,19 +882,18 @@
     ES.reportError(std::move(Err));
 }
 
-// FIXME: Move to createJITDylib if/when we start using Platform support in
-// llvm-jitlink.
-Session::Session(std::unique_ptr<TargetProcessControl> TPC, Error &Err)
-    : TPC(std::move(TPC)), ObjLayer(*this, this->TPC->getMemMgr()) {
+Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err)
+    : ES(std::move(EPC)),
+      ObjLayer(*this, ES.getExecutorProcessControl().getMemMgr()) {
 
   /// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig to the
   /// Session.
   class JITLinkSessionPlugin : public ObjectLinkingLayer::Plugin {
   public:
     JITLinkSessionPlugin(Session &S) : S(S) {}
-    void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
+    void modifyPassConfig(MaterializationResponsibility &MR, LinkGraph &G,
                           PassConfiguration &PassConfig) override {
-      S.modifyPassConfig(TT, PassConfig);
+      S.modifyPassConfig(G.getTargetTriple(), PassConfig);
     }
 
     Error notifyFailed(MaterializationResponsibility &MR) override {
@@ -818,9 +918,26 @@
     return;
   }
 
-  if (!NoExec && !this->TPC->getTargetTriple().isOSWindows())
+  if (!NoProcessSymbols)
+    ExitOnErr(loadProcessSymbols(*this));
+  ExitOnErr(loadDylibs(*this));
+
+  // Set up the platform.
+  auto &TT = ES.getExecutorProcessControl().getTargetTriple();
+  if (TT.isOSBinFormatMachO() && UseOrcRuntime) {
+    if (auto P = MachOPlatform::Create(ES, ObjLayer, *MainJD,
+                                       OrcRuntimePath.c_str()))
+      ES.setPlatform(std::move(*P));
+    else {
+      Err = P.takeError();
+      return;
+    }
+  } else if (!NoExec && !TT.isOSWindows() && !TT.isOSBinFormatMachO()) {
     ObjLayer.addPlugin(std::make_unique<EHFrameRegistrationPlugin>(
-        ES, ExitOnErr(TPCEHFrameRegistrar::Create(*this->TPC))));
+        ES, ExitOnErr(EPCEHFrameRegistrar::Create(this->ES))));
+    ObjLayer.addPlugin(std::make_unique<DebugObjectManagerPlugin>(
+        ES, ExitOnErr(createJITLoaderGDBRegistrar(this->ES))));
+  }
 
   ObjLayer.addPlugin(std::make_unique<JITLinkSessionPlugin>(*this));
 
@@ -866,10 +983,11 @@
                                PassConfiguration &PassConfig) {
   if (!CheckFiles.empty())
     PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) {
-      if (TPC->getTargetTriple().getObjectFormat() == Triple::ELF)
+      auto &EPC = ES.getExecutorProcessControl();
+      if (EPC.getTargetTriple().getObjectFormat() == Triple::ELF)
         return registerELFGraphInfo(*this, G);
 
-      if (TPC->getTargetTriple().getObjectFormat() == Triple::MachO)
+      if (EPC.getTargetTriple().getObjectFormat() == Triple::MachO)
         return registerMachOGraphInfo(*this, G);
 
       return make_error<StringError>("Unsupported object format for GOT/stub "
@@ -975,28 +1093,62 @@
 static Triple getFirstFileTriple() {
   static Triple FirstTT = []() {
     assert(!InputFiles.empty() && "InputFiles can not be empty");
-    auto ObjBuffer =
-        ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFiles.front())));
-    auto Obj = ExitOnErr(
-        object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()));
-    return Obj->makeTriple();
+    for (auto InputFile : InputFiles) {
+      auto ObjBuffer =
+          ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(InputFile)));
+      switch (identify_magic(ObjBuffer->getBuffer())) {
+      case file_magic::elf_relocatable:
+      case file_magic::macho_object:
+      case file_magic::coff_object: {
+        auto Obj = ExitOnErr(
+            object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()));
+        return Obj->makeTriple();
+      }
+      default:
+        break;
+      }
+    }
+    return Triple();
   }();
 
   return FirstTT;
 }
 
-static Error sanitizeArguments(const Triple &TT, const char *ArgV0) {
-  // Set the entry point name if not specified.
-  if (EntryPointName.empty()) {
-    if (TT.getObjectFormat() == Triple::MachO)
-      EntryPointName = "_main";
-    else
-      EntryPointName = "main";
+static bool isOrcRuntimeSupported(const Triple &TT) {
+  switch (TT.getObjectFormat()) {
+  case Triple::MachO:
+    switch (TT.getArch()) {
+    case Triple::x86_64:
+      return true;
+    default:
+      return false;
+    }
+  default:
+    return false;
   }
+}
+
+static Error sanitizeArguments(const Triple &TT, const char *ArgV0) {
+
+  // If we're in noexec mode and the user didn't explicitly specify
+  // -use-orc-runtime then don't use it.
+  if (NoExec && UseOrcRuntime.getNumOccurrences() == 0)
+    UseOrcRuntime = false;
 
   // -noexec and --args should not be used together.
   if (NoExec && !InputArgv.empty())
-    outs() << "Warning: --args passed to -noexec run will be ignored.\n";
+    errs() << "Warning: --args passed to -noexec run will be ignored.\n";
+
+  // Turn off UseOrcRuntime on platforms where it's not supported.
+  if (UseOrcRuntime && !isOrcRuntimeSupported(TT)) {
+    errs() << "Warning: Orc runtime not available for target platform. "
+              "Use -use-orc-runtime=false to suppress this warning.\n";
+    UseOrcRuntime = false;
+  }
+
+  // Set the entry point name if not specified.
+  if (EntryPointName.empty())
+    EntryPointName = TT.getObjectFormat() == Triple::MachO ? "_main" : "main";
 
   // If -slab-address is passed, require -slab-allocate and -noexec
   if (SlabAddress != ~0ULL) {
@@ -1021,35 +1173,31 @@
     SmallString<256> OOPExecutorPath(sys::fs::getMainExecutable(
         ArgV0, reinterpret_cast<void *>(&sanitizeArguments)));
     sys::path::remove_filename(OOPExecutorPath);
-    if (OOPExecutorPath.back() != '/')
-      OOPExecutorPath += '/';
-    OOPExecutorPath += "llvm-jitlink-executor";
+    sys::path::append(OOPExecutorPath, "llvm-jitlink-executor");
     OutOfProcessExecutor = OOPExecutorPath.str().str();
   }
 
-  return Error::success();
-}
-
-static Error loadProcessSymbols(Session &S) {
-  auto FilterMainEntryPoint =
-      [EPName = S.ES.intern(EntryPointName)](SymbolStringPtr Name) {
-        return Name != EPName;
-      };
-  S.MainJD->addGenerator(
-      ExitOnErr(orc::TPCDynamicLibrarySearchGenerator::GetForTargetProcess(
-          *S.TPC, std::move(FilterMainEntryPoint))));
-
-  return Error::success();
-}
-
-static Error loadDylibs(Session &S) {
-  for (const auto &Dylib : Dylibs) {
-    auto G = orc::TPCDynamicLibrarySearchGenerator::Load(*S.TPC, Dylib.c_str());
-    if (!G)
-      return G.takeError();
-    S.MainJD->addGenerator(std::move(*G));
+  // If we're loading the Orc runtime then determine the path for it.
+  if (UseOrcRuntime) {
+    if (OrcRuntimePath.empty()) {
+      SmallString<256> DefaultOrcRuntimePath(sys::fs::getMainExecutable(
+          ArgV0, reinterpret_cast<void *>(&sanitizeArguments)));
+      sys::path::remove_filename(
+          DefaultOrcRuntimePath); // remove 'llvm-jitlink'
+      while (!DefaultOrcRuntimePath.empty() &&
+             DefaultOrcRuntimePath.back() == '/')
+        DefaultOrcRuntimePath.pop_back();
+      if (DefaultOrcRuntimePath.endswith("bin"))
+        sys::path::remove_filename(DefaultOrcRuntimePath); // remove 'bin'
+      sys::path::append(DefaultOrcRuntimePath,
+                        ("lib/clang/" + Twine(LLVM_VERSION_MAJOR) + "." +
+                         Twine(LLVM_VERSION_MINOR) + "." +
+                         Twine(LLVM_VERSION_PATCH) +
+                         "/lib/darwin/libclang_rt.orc_osx.a")
+                            .str());
+      OrcRuntimePath = DefaultOrcRuntimePath.str().str();
+    }
   }
-
   return Error::success();
 }
 
@@ -1120,7 +1268,8 @@
     if (Magic == file_magic::archive ||
         Magic == file_magic::macho_universal_binary)
       JD.addGenerator(ExitOnErr(StaticLibraryDefinitionGenerator::Load(
-          S.ObjLayer, InputFile.c_str(), S.TPC->getTargetTriple())));
+          S.ObjLayer, InputFile.c_str(),
+          S.ES.getExecutorProcessControl().getTargetTriple())));
     else
       ExitOnErr(S.ObjLayer.add(JD, std::move(ObjBuffer)));
   }
@@ -1153,7 +1302,7 @@
       return Err;
 
     // Register the absolute symbol with the session symbol infos.
-    S.SymbolInfos[Name] = { StringRef(), Addr };
+    S.SymbolInfos[Name] = {ArrayRef<char>(), Addr};
   }
 
   LLVM_DEBUG({
@@ -1167,8 +1316,14 @@
 }
 
 static Error runChecks(Session &S) {
+  const auto &TT = S.ES.getExecutorProcessControl().getTargetTriple();
 
-  auto TripleName = S.TPC->getTargetTriple().str();
+  if (CheckFiles.empty())
+    return Error::success();
+
+  LLVM_DEBUG(dbgs() << "Running checks...\n");
+
+  auto TripleName = TT.str();
   std::string ErrorStr;
   const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, ErrorStr);
   if (!TheTarget)
@@ -1198,7 +1353,7 @@
                                           TripleName,
                                       inconvertibleErrorCode()));
 
-  MCContext Ctx(MAI.get(), MRI.get(), nullptr);
+  MCContext Ctx(Triple(TripleName), MAI.get(), MRI.get(), STI.get());
 
   std::unique_ptr<MCDisassembler> Disassembler(
       TheTarget->createMCDisassembler(*STI, Ctx));
@@ -1234,9 +1389,8 @@
 
   RuntimeDyldChecker Checker(
       IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo, GetGOTInfo,
-      S.TPC->getTargetTriple().isLittleEndian() ? support::little
-                                                : support::big,
-      Disassembler.get(), InstPrinter.get(), dbgs());
+      TT.isLittleEndian() ? support::little : support::big, Disassembler.get(),
+      InstPrinter.get(), dbgs());
 
   std::string CheckLineStart = "# " + CheckName + ":";
   for (auto &CheckFile : CheckFiles) {
@@ -1251,9 +1405,15 @@
 }
 
 static void dumpSessionStats(Session &S) {
+  if (!ShowSizes)
+    return;
+  if (UseOrcRuntime)
+    outs() << "Note: Session stats include runtime and entry point lookup, but "
+              "not JITDylib initialization/deinitialization.\n";
   if (ShowSizes)
-    outs() << "Total size of all blocks before pruning: " << S.SizeBeforePruning
-           << "\nTotal size of all blocks after fixups: " << S.SizeAfterFixups
+    outs() << "  Total size of all blocks before pruning: "
+           << S.SizeBeforePruning
+           << "\n  Total size of all blocks after fixups: " << S.SizeAfterFixups
            << "\n";
 }
 
@@ -1261,6 +1421,37 @@
   return S.ES.lookup(S.JDSearchOrder, EntryPointName);
 }
 
+static Expected<JITEvaluatedSymbol> getOrcRuntimeEntryPoint(Session &S) {
+  std::string RuntimeEntryPoint = "__orc_rt_run_program_wrapper";
+  const auto &TT = S.ES.getExecutorProcessControl().getTargetTriple();
+  if (TT.getObjectFormat() == Triple::MachO)
+    RuntimeEntryPoint = '_' + RuntimeEntryPoint;
+  return S.ES.lookup(S.JDSearchOrder, RuntimeEntryPoint);
+}
+
+static Expected<int> runWithRuntime(Session &S,
+                                    JITTargetAddress EntryPointAddress) {
+  StringRef DemangledEntryPoint = EntryPointName;
+  const auto &TT = S.ES.getExecutorProcessControl().getTargetTriple();
+  if (TT.getObjectFormat() == Triple::MachO &&
+      DemangledEntryPoint.front() == '_')
+    DemangledEntryPoint = DemangledEntryPoint.drop_front();
+  using SPSRunProgramSig =
+      int64_t(SPSString, SPSString, SPSSequence<SPSString>);
+  int64_t Result;
+  if (auto Err = S.ES.callSPSWrapper<SPSRunProgramSig>(
+          EntryPointAddress, Result, S.MainJD->getName(), DemangledEntryPoint,
+          static_cast<std::vector<std::string> &>(InputArgv)))
+    return std::move(Err);
+  return Result;
+}
+
+static Expected<int> runWithoutRuntime(Session &S,
+                                       JITTargetAddress EntryPointAddress) {
+  return S.ES.getExecutorProcessControl().runAsMain(EntryPointAddress,
+                                                    InputArgv);
+}
+
 namespace {
 struct JITLinkTimers {
   TimerGroup JITLinkTG{"llvm-jitlink timers", "timers for llvm-jitlink phases"};
@@ -1277,6 +1468,7 @@
   InitializeAllTargetMCs();
   InitializeAllDisassemblers();
 
+  cl::HideUnrelatedOptions({&JITLinkCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv, "llvm jitlink tool");
   ExitOnErr.setBanner(std::string(argv[0]) + ": ");
 
@@ -1293,21 +1485,23 @@
     ExitOnErr(loadObjects(*S));
   }
 
-  if (!NoProcessSymbols)
-    ExitOnErr(loadProcessSymbols(*S));
-  ExitOnErr(loadDylibs(*S));
-
   if (PhonyExternals)
     addPhonyExternalsGenerator(*S);
 
-
   if (ShowInitialExecutionSessionState)
     S->ES.dump(outs());
 
   JITEvaluatedSymbol EntryPoint = 0;
   {
     TimeRegion TR(Timers ? &Timers->LinkTimer : nullptr);
+    // Find the entry-point function unconditionally, since we want to force
+    // it to be materialized to collect stats.
     EntryPoint = ExitOnErr(getMainEntryPoint(*S));
+
+    // If we're running with the ORC runtime then replace the entry-point
+    // with the __orc_rt_run_program symbol.
+    if (UseOrcRuntime)
+      EntryPoint = ExitOnErr(getOrcRuntimeEntryPoint(*S));
   }
 
   if (ShowAddrs)
@@ -1322,12 +1516,20 @@
 
   int Result = 0;
   {
+    LLVM_DEBUG(dbgs() << "Running \"" << EntryPointName << "\"...\n");
     TimeRegion TR(Timers ? &Timers->RunTimer : nullptr);
-    Result = ExitOnErr(S->TPC->runAsMain(EntryPoint.getAddress(), InputArgv));
+    if (UseOrcRuntime)
+      Result = ExitOnErr(runWithRuntime(*S, EntryPoint.getAddress()));
+    else
+      Result = ExitOnErr(runWithoutRuntime(*S, EntryPoint.getAddress()));
   }
 
-  ExitOnErr(S->ES.endSession());
-  ExitOnErr(S->TPC->disconnect());
+  // Destroy the session.
+  S.reset();
+
+  // If the executing code set a test result override then use that.
+  if (UseTestResultOverride)
+    Result = TestResultOverride;
 
   return Result;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.h b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.h
index 13b5592..acb64a9 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.h
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.h
@@ -17,11 +17,11 @@
 #include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
-#include "llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h"
+#include "llvm/ExecutionEngine/Orc/OrcRPCExecutorProcessControl.h"
 #include "llvm/ExecutionEngine/Orc/Shared/FDRawByteChannel.h"
 #include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h"
-#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
 #include "llvm/ExecutionEngine/RuntimeDyldChecker.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Regex.h"
@@ -51,29 +51,27 @@
 using LLVMJITLinkChannel = orc::shared::FDRawByteChannel;
 using LLVMJITLinkRPCEndpoint =
     orc::shared::MultiThreadedRPCEndpoint<LLVMJITLinkChannel>;
-using LLVMJITLinkRemoteMemoryManager =
-    orc::OrcRPCTPCJITLinkMemoryManager<LLVMJITLinkRPCEndpoint>;
 using LLVMJITLinkRemoteMemoryAccess =
-    orc::OrcRPCTPCMemoryAccess<LLVMJITLinkRPCEndpoint>;
+    orc::OrcRPCEPCMemoryAccess<LLVMJITLinkRPCEndpoint>;
 
-class LLVMJITLinkRemoteTargetProcessControl
-    : public orc::OrcRPCTargetProcessControlBase<LLVMJITLinkRPCEndpoint> {
+class LLVMJITLinkRemoteExecutorProcessControl
+    : public orc::OrcRPCExecutorProcessControlBase<LLVMJITLinkRPCEndpoint> {
 public:
-  using BaseT = orc::OrcRPCTargetProcessControlBase<LLVMJITLinkRPCEndpoint>;
-  static Expected<std::unique_ptr<TargetProcessControl>> LaunchExecutor();
+  using BaseT = orc::OrcRPCExecutorProcessControlBase<LLVMJITLinkRPCEndpoint>;
+  static Expected<std::unique_ptr<ExecutorProcessControl>> LaunchExecutor();
 
-  static Expected<std::unique_ptr<TargetProcessControl>> ConnectToExecutor();
+  static Expected<std::unique_ptr<ExecutorProcessControl>> ConnectToExecutor();
 
   Error disconnect() override;
 
 private:
   using LLVMJITLinkRemoteMemoryAccess =
-      orc::OrcRPCTPCMemoryAccess<LLVMJITLinkRemoteTargetProcessControl>;
+      orc::OrcRPCEPCMemoryAccess<LLVMJITLinkRemoteExecutorProcessControl>;
 
-  using LLVMJITLinkRemoteMemoryManager =
-      orc::OrcRPCTPCJITLinkMemoryManager<LLVMJITLinkRemoteTargetProcessControl>;
+  using LLVMJITLinkRemoteMemoryManager = orc::OrcRPCEPCJITLinkMemoryManager<
+      LLVMJITLinkRemoteExecutorProcessControl>;
 
-  LLVMJITLinkRemoteTargetProcessControl(
+  LLVMJITLinkRemoteExecutorProcessControl(
       std::shared_ptr<orc::SymbolStringPool> SSP,
       std::unique_ptr<LLVMJITLinkChannel> Channel,
       std::unique_ptr<LLVMJITLinkRPCEndpoint> Endpoint,
@@ -91,7 +89,7 @@
       }
     });
 
-    if (auto Err2 = initializeORCRPCTPCBase()) {
+    if (auto Err2 = initializeORCRPCEPCBase()) {
       Err = joinErrors(std::move(Err2), disconnect());
       return;
     }
@@ -104,16 +102,15 @@
 
   std::unique_ptr<LLVMJITLinkChannel> Channel;
   std::unique_ptr<LLVMJITLinkRPCEndpoint> Endpoint;
-  std::unique_ptr<TargetProcessControl::MemoryAccess> OwnedMemAccess;
+  std::unique_ptr<ExecutorProcessControl::MemoryAccess> OwnedMemAccess;
   std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr;
   std::atomic<bool> Finished{false};
   std::thread ListenerThread;
 };
 
 struct Session {
-  std::unique_ptr<orc::TargetProcessControl> TPC;
   orc::ExecutionSession ES;
-  orc::JITDylib *MainJD;
+  orc::JITDylib *MainJD = nullptr;
   LLVMJITLinkObjectLinkingLayer ObjLayer;
   std::vector<orc::JITDylib *> JDSearchOrder;
 
@@ -158,7 +155,7 @@
   DenseMap<StringRef, StringRef> CanonicalWeakDefs;
 
 private:
-  Session(std::unique_ptr<orc::TargetProcessControl> TPC, Error &Err);
+  Session(std::unique_ptr<orc::ExecutorProcessControl> EPC, Error &Err);
 };
 
 /// Record symbols, GOT entries, stubs, and sections for ELF file.
diff --git a/src/llvm-project/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp b/src/llvm-project/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
index 1ff6328..ef4aec5 100644
--- a/src/llvm-project/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
+++ b/src/llvm-project/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
@@ -21,8 +21,9 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LineIterator.h"
+#include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Support/WithColor.h"
-#include "llvm/TextAPI/MachO/Architecture.h"
+#include "llvm/TextAPI/Architecture.h"
 #include <map>
 
 using namespace llvm;
@@ -89,6 +90,11 @@
     VersionOption("V", cl::desc("Print the version number and exit"),
                   cl::cat(LibtoolCategory));
 
+static cl::opt<bool> NoWarningForNoSymbols(
+    "no_warning_for_no_symbols",
+    cl::desc("Do not warn about files that have no symbols"),
+    cl::cat(LibtoolCategory), cl::init(false));
+
 static const std::array<std::string, 3> StandardSearchDirs{
     "/lib",
     "/usr/lib",
@@ -142,7 +148,7 @@
   std::tie(FileName, DirName) = StringRef(FileList).rsplit(",");
 
   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
-      MemoryBuffer::getFileOrSTDIN(FileName, /*FileSize=*/-1,
+      MemoryBuffer::getFileOrSTDIN(FileName, /*IsText=*/false,
                                    /*RequiresNullTerminator=*/false);
   if (std::error_code EC = FileOrErr.getError())
     return createFileError(FileName, errorCodeToError(EC));
@@ -251,6 +257,9 @@
     return Error::success();
   }
 
+  if (!NoWarningForNoSymbols && O->symbols().empty())
+    WithColor::warning() << Member.MemberName + " has no symbols\n";
+
   uint64_t FileCPUID = getCPUID(FileCPUType, FileCPUSubtype);
   Members[FileCPUID].push_back(std::move(Member));
   return Error::success();
@@ -562,7 +571,7 @@
 
 int main(int Argc, char **Argv) {
   InitLLVM X(Argc, Argv);
-  cl::HideUnrelatedOptions({&LibtoolCategory, &ColorCategory});
+  cl::HideUnrelatedOptions({&LibtoolCategory, &getColorCategory()});
   Expected<Config> ConfigOrErr = parseCommandLine(Argc, Argv);
   if (!ConfigOrErr) {
     WithColor::defaultErrorHandler(ConfigOrErr.takeError());
diff --git a/src/llvm-project/llvm/tools/llvm-link/llvm-link.cpp b/src/llvm-project/llvm/tools/llvm-link/llvm-link.cpp
index eed49c4..9abe8ef 100644
--- a/src/llvm-project/llvm/tools/llvm-link/llvm-link.cpp
+++ b/src/llvm-project/llvm/tools/llvm-link/llvm-link.cpp
@@ -41,21 +41,25 @@
 #include <utility>
 using namespace llvm;
 
-static cl::list<std::string>
-InputFilenames(cl::Positional, cl::OneOrMore,
-               cl::desc("<input bitcode files>"));
+static cl::OptionCategory LinkCategory("Link Options");
+
+static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
+                                            cl::desc("<input bitcode files>"),
+                                            cl::cat(LinkCategory));
 
 static cl::list<std::string> OverridingInputs(
     "override", cl::ZeroOrMore, cl::value_desc("filename"),
     cl::desc(
-        "input bitcode file which can override previously defined symbol(s)"));
+        "input bitcode file which can override previously defined symbol(s)"),
+    cl::cat(LinkCategory));
 
 // Option to simulate function importing for testing. This enables using
 // llvm-link to simulate ThinLTO backend processes.
 static cl::list<std::string> Imports(
     "import", cl::ZeroOrMore, cl::value_desc("function:filename"),
     cl::desc("Pair of function name and filename, where function should be "
-             "imported from bitcode in filename"));
+             "imported from bitcode in filename"),
+    cl::cat(LinkCategory));
 
 // Option to support testing of function importing. The module summary
 // must be specified in the case were we request imports via the -import
@@ -64,51 +68,61 @@
 // consistent promotion and renaming of locals.
 static cl::opt<std::string>
     SummaryIndex("summary-index", cl::desc("Module summary index filename"),
-                 cl::init(""), cl::value_desc("filename"));
+                 cl::init(""), cl::value_desc("filename"),
+                 cl::cat(LinkCategory));
 
 static cl::opt<std::string>
-OutputFilename("o", cl::desc("Override output filename"), cl::init("-"),
-               cl::value_desc("filename"));
+    OutputFilename("o", cl::desc("Override output filename"), cl::init("-"),
+                   cl::value_desc("filename"), cl::cat(LinkCategory));
 
-static cl::opt<bool>
-Internalize("internalize", cl::desc("Internalize linked symbols"));
+static cl::opt<bool> Internalize("internalize",
+                                 cl::desc("Internalize linked symbols"),
+                                 cl::cat(LinkCategory));
 
 static cl::opt<bool>
     DisableDITypeMap("disable-debug-info-type-map",
-                     cl::desc("Don't use a uniquing type map for debug info"));
+                     cl::desc("Don't use a uniquing type map for debug info"),
+                     cl::cat(LinkCategory));
 
-static cl::opt<bool>
-OnlyNeeded("only-needed", cl::desc("Link only needed symbols"));
+static cl::opt<bool> OnlyNeeded("only-needed",
+                                cl::desc("Link only needed symbols"),
+                                cl::cat(LinkCategory));
 
-static cl::opt<bool>
-Force("f", cl::desc("Enable binary output on terminals"));
+static cl::opt<bool> Force("f", cl::desc("Enable binary output on terminals"),
+                           cl::cat(LinkCategory));
 
-static cl::opt<bool>
-    DisableLazyLoad("disable-lazy-loading",
-                    cl::desc("Disable lazy module loading"));
+static cl::opt<bool> DisableLazyLoad("disable-lazy-loading",
+                                     cl::desc("Disable lazy module loading"),
+                                     cl::cat(LinkCategory));
 
-static cl::opt<bool>
-    OutputAssembly("S", cl::desc("Write output as LLVM assembly"), cl::Hidden);
+static cl::opt<bool> OutputAssembly("S",
+                                    cl::desc("Write output as LLVM assembly"),
+                                    cl::Hidden, cl::cat(LinkCategory));
 
-static cl::opt<bool>
-Verbose("v", cl::desc("Print information about actions taken"));
+static cl::opt<bool> Verbose("v",
+                             cl::desc("Print information about actions taken"),
+                             cl::cat(LinkCategory));
 
-static cl::opt<bool>
-DumpAsm("d", cl::desc("Print assembly as linked"), cl::Hidden);
+static cl::opt<bool> DumpAsm("d", cl::desc("Print assembly as linked"),
+                             cl::Hidden, cl::cat(LinkCategory));
 
-static cl::opt<bool>
-SuppressWarnings("suppress-warnings", cl::desc("Suppress all linking warnings"),
-                 cl::init(false));
+static cl::opt<bool> SuppressWarnings("suppress-warnings",
+                                      cl::desc("Suppress all linking warnings"),
+                                      cl::init(false), cl::cat(LinkCategory));
 
 static cl::opt<bool> PreserveBitcodeUseListOrder(
     "preserve-bc-uselistorder",
     cl::desc("Preserve use-list order when writing LLVM bitcode."),
-    cl::init(true), cl::Hidden);
+    cl::init(true), cl::Hidden, cl::cat(LinkCategory));
 
 static cl::opt<bool> PreserveAssemblyUseListOrder(
     "preserve-ll-uselistorder",
     cl::desc("Preserve use-list order when writing LLVM assembly."),
-    cl::init(false), cl::Hidden);
+    cl::init(false), cl::Hidden, cl::cat(LinkCategory));
+
+static cl::opt<bool> NoVerify("disable-verify",
+                              cl::desc("Do not run the verifier"), cl::Hidden,
+                              cl::cat(LinkCategory));
 
 static ExitOnError ExitOnErr;
 
@@ -158,9 +172,8 @@
     Expected<StringRef> Ename = C.getName();
     if (Error E = Ename.takeError()) {
       errs() << Argv0 << ": ";
-      WithColor::error()
-          << " failed to read name of archive member"
-          << ArchiveName << "'\n";
+      WithColor::error() << " failed to read name of archive member"
+                         << ArchiveName << "'\n";
       return nullptr;
     }
     std::string ChildName = Ename.get().str();
@@ -177,10 +190,10 @@
       return nullptr;
     };
 
-    if (!isBitcode(reinterpret_cast<const unsigned char *>
-                   (MemBuf.get().getBufferStart()),
-                   reinterpret_cast<const unsigned char *>
-                   (MemBuf.get().getBufferEnd()))) {
+    if (!isBitcode(reinterpret_cast<const unsigned char *>(
+                       MemBuf.get().getBufferStart()),
+                   reinterpret_cast<const unsigned char *>(
+                       MemBuf.get().getBufferEnd()))) {
       errs() << Argv0 << ": ";
       WithColor::error() << "  member of archive is not a bitcode file: '"
                          << ChildName << "'\n";
@@ -246,8 +259,10 @@
 Module &ModuleLazyLoaderCache::operator()(const char *argv0,
                                           const std::string &Identifier) {
   auto &Module = ModuleMap[Identifier];
-  if (!Module)
+  if (!Module) {
     Module = createLazyModule(argv0, Identifier);
+    assert(Module && "Failed to create lazy module!");
+  }
   return *Module;
 }
 } // anonymous namespace
@@ -276,7 +291,7 @@
     return true;
   }
 };
-}
+} // namespace
 
 /// Import any functions requested via the -import option.
 static bool importFunctions(const char *argv0, Module &DestModule) {
@@ -309,7 +324,7 @@
     // Load the specified source module.
     auto &SrcModule = ModuleLoaderCache(argv0, FileName);
 
-    if (verifyModule(SrcModule, &errs())) {
+    if (!NoVerify && verifyModule(SrcModule, &errs())) {
       errs() << argv0 << ": " << FileName;
       WithColor::error() << "input module is broken!\n";
       return false;
@@ -347,8 +362,7 @@
 }
 
 static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L,
-                      const cl::list<std::string> &Files,
-                      unsigned Flags) {
+                      const cl::list<std::string> &Files, unsigned Flags) {
   // Filter out flags that don't apply to the first file we load.
   unsigned ApplicableFlags = Flags & Linker::Flags::OverrideFromSrc;
   // Similar to some flags, internalization doesn't apply to the first file.
@@ -370,7 +384,7 @@
     // Note that when ODR merging types cannot verify input files in here When
     // doing that debug metadata in the src module might already be pointing to
     // the destination.
-    if (DisableDITypeMap && verifyModule(*M, &errs())) {
+    if (DisableDITypeMap && !NoVerify && verifyModule(*M, &errs())) {
       errs() << argv0 << ": " << File << ": ";
       WithColor::error() << "input module is broken!\n";
       return false;
@@ -431,8 +445,9 @@
   ExitOnErr.setBanner(std::string(argv[0]) + ": ");
 
   LLVMContext Context;
-  Context.setDiagnosticHandler(
-    std::make_unique<LLVMLinkDiagnosticHandler>(), true);
+  Context.setDiagnosticHandler(std::make_unique<LLVMLinkDiagnosticHandler>(),
+                               true);
+  cl::HideUnrelatedOptions({&LinkCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");
 
   if (!DisableDITypeMap)
@@ -463,13 +478,14 @@
 
   std::error_code EC;
   ToolOutputFile Out(OutputFilename, EC,
-                     OutputAssembly ? sys::fs::OF_Text : sys::fs::OF_None);
+                     OutputAssembly ? sys::fs::OF_TextWithCRLF
+                                    : sys::fs::OF_None);
   if (EC) {
     WithColor::error() << EC.message() << '\n';
     return 1;
   }
 
-  if (verifyModule(*Composite, &errs())) {
+  if (!NoVerify && verifyModule(*Composite, &errs())) {
     errs() << argv[0] << ": ";
     WithColor::error() << "linked module is broken!\n";
     return 1;
diff --git a/src/llvm-project/llvm/tools/llvm-lipo/llvm-lipo.cpp b/src/llvm-project/llvm/tools/llvm-lipo/llvm-lipo.cpp
index 7fbe489..d099ea1 100644
--- a/src/llvm-project/llvm/tools/llvm-lipo/llvm-lipo.cpp
+++ b/src/llvm-project/llvm/tools/llvm-lipo/llvm-lipo.cpp
@@ -28,7 +28,7 @@
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/WithColor.h"
-#include "llvm/TextAPI/MachO/Architecture.h"
+#include "llvm/TextAPI/Architecture.h"
 
 using namespace llvm;
 using namespace llvm::object;
@@ -159,14 +159,14 @@
                 " option");
 
   if (InputArgs.size() == 0) {
-    // PrintHelp does not accept Twine.
-    T.PrintHelp(errs(), "llvm-lipo input[s] option[s]", "llvm-lipo");
+    // printHelp does not accept Twine.
+    T.printHelp(errs(), "llvm-lipo input[s] option[s]", "llvm-lipo");
     exit(EXIT_FAILURE);
   }
 
   if (InputArgs.hasArg(LIPO_help)) {
-    // PrintHelp does not accept Twine.
-    T.PrintHelp(outs(), "llvm-lipo input[s] option[s]", "llvm-lipo");
+    // printHelp does not accept Twine.
+    T.printHelp(outs(), "llvm-lipo input[s] option[s]", "llvm-lipo");
     exit(EXIT_SUCCESS);
   }
 
diff --git a/src/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp b/src/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp
index 1745b74..45bfa84 100644
--- a/src/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp
+++ b/src/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp
@@ -64,31 +64,38 @@
 
 static codegen::RegisterCodeGenFlags CGF;
 
+static cl::OptionCategory LTOCategory("LTO Options");
+
 static cl::opt<char>
-    OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
-                           "(default = '-O2')"),
-             cl::Prefix, cl::ZeroOrMore, cl::init('2'));
+    OptLevel("O",
+             cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
+                      "(default = '-O2')"),
+             cl::Prefix, cl::ZeroOrMore, cl::init('2'), cl::cat(LTOCategory));
 
 static cl::opt<bool>
     IndexStats("thinlto-index-stats",
                cl::desc("Print statistic for the index in every input files"),
-               cl::init(false));
+               cl::init(false), cl::cat(LTOCategory));
 
 static cl::opt<bool> DisableVerify(
     "disable-verify", cl::init(false),
-    cl::desc("Do not run the verifier during the optimization pipeline"));
+    cl::desc("Do not run the verifier during the optimization pipeline"),
+    cl::cat(LTOCategory));
 
 static cl::opt<bool> EnableFreestanding(
     "lto-freestanding", cl::init(false),
-    cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));
+    cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"),
+    cl::cat(LTOCategory));
 
 static cl::opt<bool> UseDiagnosticHandler(
     "use-diagnostic-handler", cl::init(false),
-    cl::desc("Use a diagnostic handler to test the handler interface"));
+    cl::desc("Use a diagnostic handler to test the handler interface"),
+    cl::cat(LTOCategory));
 
 static cl::opt<bool>
     ThinLTO("thinlto", cl::init(false),
-            cl::desc("Only write combined global index for ThinLTO backends"));
+            cl::desc("Only write combined global index for ThinLTO backends"),
+            cl::cat(LTOCategory));
 
 enum ThinLTOModes {
   THINLINK,
@@ -114,113 +121,144 @@
                    "Emit imports files for distributed backends."),
         clEnumValN(THINPROMOTE, "promote",
                    "Perform pre-import promotion (requires -thinlto-index)."),
-        clEnumValN(THINIMPORT, "import", "Perform both promotion and "
-                                         "cross-module importing (requires "
-                                         "-thinlto-index)."),
+        clEnumValN(THINIMPORT, "import",
+                   "Perform both promotion and "
+                   "cross-module importing (requires "
+                   "-thinlto-index)."),
         clEnumValN(THININTERNALIZE, "internalize",
                    "Perform internalization driven by -exported-symbol "
                    "(requires -thinlto-index)."),
         clEnumValN(THINOPT, "optimize", "Perform ThinLTO optimizations."),
         clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to match llc)"),
-        clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end")));
+        clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end")),
+    cl::cat(LTOCategory));
 
 static cl::opt<std::string>
     ThinLTOIndex("thinlto-index",
                  cl::desc("Provide the index produced by a ThinLink, required "
-                          "to perform the promotion and/or importing."));
+                          "to perform the promotion and/or importing."),
+                 cl::cat(LTOCategory));
 
 static cl::opt<std::string> ThinLTOPrefixReplace(
     "thinlto-prefix-replace",
     cl::desc("Control where files for distributed backends are "
              "created. Expects 'oldprefix;newprefix' and if path "
              "prefix of output file is oldprefix it will be "
-             "replaced with newprefix."));
+             "replaced with newprefix."),
+    cl::cat(LTOCategory));
 
 static cl::opt<std::string> ThinLTOModuleId(
     "thinlto-module-id",
     cl::desc("For the module ID for the file to process, useful to "
-             "match what is in the index."));
+             "match what is in the index."),
+    cl::cat(LTOCategory));
 
-static cl::opt<std::string>
-    ThinLTOCacheDir("thinlto-cache-dir", cl::desc("Enable ThinLTO caching."));
+static cl::opt<std::string> ThinLTOCacheDir("thinlto-cache-dir",
+                                            cl::desc("Enable ThinLTO caching."),
+                                            cl::cat(LTOCategory));
 
-static cl::opt<int>
-    ThinLTOCachePruningInterval("thinlto-cache-pruning-interval",
-    cl::init(1200), cl::desc("Set ThinLTO cache pruning interval."));
+static cl::opt<int> ThinLTOCachePruningInterval(
+    "thinlto-cache-pruning-interval", cl::init(1200),
+    cl::desc("Set ThinLTO cache pruning interval."), cl::cat(LTOCategory));
 
 static cl::opt<uint64_t> ThinLTOCacheMaxSizeBytes(
     "thinlto-cache-max-size-bytes",
-    cl::desc("Set ThinLTO cache pruning directory maximum size in bytes."));
+    cl::desc("Set ThinLTO cache pruning directory maximum size in bytes."),
+    cl::cat(LTOCategory));
 
-static cl::opt<int>
-    ThinLTOCacheMaxSizeFiles("thinlto-cache-max-size-files", cl::init(1000000),
-    cl::desc("Set ThinLTO cache pruning directory maximum number of files."));
+static cl::opt<int> ThinLTOCacheMaxSizeFiles(
+    "thinlto-cache-max-size-files", cl::init(1000000),
+    cl::desc("Set ThinLTO cache pruning directory maximum number of files."),
+    cl::cat(LTOCategory));
 
-static cl::opt<unsigned>
-    ThinLTOCacheEntryExpiration("thinlto-cache-entry-expiration", cl::init(604800) /* 1w */,
-    cl::desc("Set ThinLTO cache entry expiration time."));
+static cl::opt<unsigned> ThinLTOCacheEntryExpiration(
+    "thinlto-cache-entry-expiration", cl::init(604800) /* 1w */,
+    cl::desc("Set ThinLTO cache entry expiration time."), cl::cat(LTOCategory));
 
 static cl::opt<std::string> ThinLTOSaveTempsPrefix(
     "thinlto-save-temps",
     cl::desc("Save ThinLTO temp files using filenames created by adding "
-             "suffixes to the given file path prefix."));
+             "suffixes to the given file path prefix."),
+    cl::cat(LTOCategory));
 
 static cl::opt<std::string> ThinLTOGeneratedObjectsDir(
     "thinlto-save-objects",
     cl::desc("Save ThinLTO generated object files using filenames created in "
-             "the given directory."));
+             "the given directory."),
+    cl::cat(LTOCategory));
 
 static cl::opt<bool> SaveLinkedModuleFile(
     "save-linked-module", cl::init(false),
-    cl::desc("Write linked LTO module to file before optimize"));
+    cl::desc("Write linked LTO module to file before optimize"),
+    cl::cat(LTOCategory));
 
 static cl::opt<bool>
     SaveModuleFile("save-merged-module", cl::init(false),
-                   cl::desc("Write merged LTO module to file before CodeGen"));
+                   cl::desc("Write merged LTO module to file before CodeGen"),
+                   cl::cat(LTOCategory));
 
 static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
-                                            cl::desc("<input bitcode files>"));
+                                            cl::desc("<input bitcode files>"),
+                                            cl::cat(LTOCategory));
 
 static cl::opt<std::string> OutputFilename("o", cl::init(""),
                                            cl::desc("Override output filename"),
-                                           cl::value_desc("filename"));
+                                           cl::value_desc("filename"),
+                                           cl::cat(LTOCategory));
 
 static cl::list<std::string> ExportedSymbols(
     "exported-symbol",
     cl::desc("List of symbols to export from the resulting object file"),
-    cl::ZeroOrMore);
+    cl::ZeroOrMore, cl::cat(LTOCategory));
 
 static cl::list<std::string>
     DSOSymbols("dso-symbol",
                cl::desc("Symbol to put in the symtab in the resulting dso"),
-               cl::ZeroOrMore);
+               cl::ZeroOrMore, cl::cat(LTOCategory));
 
 static cl::opt<bool> ListSymbolsOnly(
     "list-symbols-only", cl::init(false),
-    cl::desc("Instead of running LTO, list the symbols in each IR file"));
+    cl::desc("Instead of running LTO, list the symbols in each IR file"),
+    cl::cat(LTOCategory));
 
 static cl::opt<bool> ListDependentLibrariesOnly(
     "list-dependent-libraries-only", cl::init(false),
-    cl::desc("Instead of running LTO, list the dependent libraries in each IR file"));
+    cl::desc(
+        "Instead of running LTO, list the dependent libraries in each IR file"),
+    cl::cat(LTOCategory));
 
-static cl::opt<bool> SetMergedModule(
-    "set-merged-module", cl::init(false),
-    cl::desc("Use the first input module as the merged module"));
+static cl::opt<bool>
+    SetMergedModule("set-merged-module", cl::init(false),
+                    cl::desc("Use the first input module as the merged module"),
+                    cl::cat(LTOCategory));
 
 static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
-                                     cl::desc("Number of backend threads"));
+                                     cl::desc("Number of backend threads"),
+                                     cl::cat(LTOCategory));
 
 static cl::opt<bool> RestoreGlobalsLinkage(
     "restore-linkage", cl::init(false),
-    cl::desc("Restore original linkage of globals prior to CodeGen"));
+    cl::desc("Restore original linkage of globals prior to CodeGen"),
+    cl::cat(LTOCategory));
 
 static cl::opt<bool> CheckHasObjC(
     "check-for-objc", cl::init(false),
-    cl::desc("Only check if the module has objective-C defined in it"));
+    cl::desc("Only check if the module has objective-C defined in it"),
+    cl::cat(LTOCategory));
 
 static cl::opt<bool> PrintMachOCPUOnly(
     "print-macho-cpu-only", cl::init(false),
-    cl::desc("Instead of running LTO, print the mach-o cpu in each IR file"));
+    cl::desc("Instead of running LTO, print the mach-o cpu in each IR file"),
+    cl::cat(LTOCategory));
+
+static cl::opt<bool> UseNewPM(
+    "use-new-pm", cl::desc("Run LTO passes using the new pass manager"),
+    cl::init(LLVM_ENABLE_NEW_PASS_MANAGER), cl::Hidden, cl::cat(LTOCategory));
+
+static cl::opt<bool>
+    DebugPassManager("debug-pass-manager", cl::init(false), cl::Hidden,
+                     cl::desc("Print pass management debugging information"),
+                     cl::cat(LTOCategory));
 
 namespace {
 
@@ -552,6 +590,8 @@
     ThinGenerator.setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles);
     ThinGenerator.setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes);
     ThinGenerator.setFreestanding(EnableFreestanding);
+    ThinGenerator.setUseNewPM(UseNewPM);
+    ThinGenerator.setDebugPassManager(DebugPassManager);
 
     // Add all the exported symbols to the table of symbols to preserve.
     for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
@@ -884,6 +924,7 @@
 
 int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
+  cl::HideUnrelatedOptions({&LTOCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
 
   if (OptLevel < '0' || OptLevel > '3')
@@ -1014,6 +1055,8 @@
   CodeGen.setOptLevel(OptLevel - '0');
   CodeGen.setAttrs(codegen::getMAttrs());
 
+  CodeGen.setUseNewPM(UseNewPM);
+
   if (auto FT = codegen::getExplicitFileType())
     CodeGen.setFileType(FT.getValue());
 
@@ -1041,25 +1084,24 @@
         error("writing merged module failed.");
     }
 
-    std::list<ToolOutputFile> OSs;
-    std::vector<raw_pwrite_stream *> OSPtrs;
-    for (unsigned I = 0; I != Parallelism; ++I) {
+    auto AddStream =
+        [&](size_t Task) -> std::unique_ptr<lto::NativeObjectStream> {
       std::string PartFilename = OutputFilename;
       if (Parallelism != 1)
-        PartFilename += "." + utostr(I);
+        PartFilename += "." + utostr(Task);
+
       std::error_code EC;
-      OSs.emplace_back(PartFilename, EC, sys::fs::OF_None);
+      auto S =
+          std::make_unique<raw_fd_ostream>(PartFilename, EC, sys::fs::OF_None);
       if (EC)
         error("error opening the file '" + PartFilename + "': " + EC.message());
-      OSPtrs.push_back(&OSs.back().os());
-    }
+      return std::make_unique<lto::NativeObjectStream>(std::move(S));
+    };
 
-    if (!CodeGen.compileOptimized(OSPtrs))
+    if (!CodeGen.compileOptimized(AddStream, Parallelism))
       // Diagnostic messages should have been printed by the handler.
       error("error compiling the code");
 
-    for (ToolOutputFile &OS : OSs)
-      OS.keep();
   } else {
     if (Parallelism != 1)
       error("-j must be specified together with -o");
diff --git a/src/llvm-project/llvm/tools/llvm-lto2/llvm-lto2.cpp b/src/llvm-project/llvm/tools/llvm-lto2/llvm-lto2.cpp
index ca4278f..c0bff1e 100644
--- a/src/llvm-project/llvm/tools/llvm-lto2/llvm-lto2.cpp
+++ b/src/llvm-project/llvm/tools/llvm-lto2/llvm-lto2.cpp
@@ -325,12 +325,12 @@
     std::vector<SymbolResolution> Res;
     for (const InputFile::Symbol &Sym : Input->symbols()) {
       auto I = CommandLineResolutions.find({F, std::string(Sym.getName())});
-      // If it isn't found, look for "$", which would have been added
+      // If it isn't found, look for ".", which would have been added
       // (followed by a hash) when the symbol was promoted during module
       // splitting if it was defined in one part and used in the other.
-      // Try looking up the symbol name before the "$".
+      // Try looking up the symbol name before the suffix.
       if (I == CommandLineResolutions.end()) {
-        auto SplitName = Sym.getName().rsplit("$");
+        auto SplitName = Sym.getName().rsplit(".");
         I = CommandLineResolutions.find({F, std::string(SplitName.first)});
       }
       if (I == CommandLineResolutions.end()) {
@@ -418,7 +418,8 @@
       outs() << '\n';
     }
 
-    std::vector<StringRef> ComdatTable = Input->getComdatTable();
+    ArrayRef<std::pair<StringRef, Comdat::SelectionKind>> ComdatTable =
+        Input->getComdatTable();
     for (const InputFile::Symbol &Sym : Input->symbols()) {
       switch (Sym.getVisibility()) {
       case GlobalValue::HiddenVisibility:
@@ -447,8 +448,27 @@
                << Sym.getCommonAlignment() << '\n';
 
       int Comdat = Sym.getComdatIndex();
-      if (Comdat != -1)
-        outs() << "         comdat " << ComdatTable[Comdat] << '\n';
+      if (Comdat != -1) {
+        outs() << "         comdat ";
+        switch (ComdatTable[Comdat].second) {
+        case Comdat::Any:
+          outs() << "any";
+          break;
+        case Comdat::ExactMatch:
+          outs() << "exactmatch";
+          break;
+        case Comdat::Largest:
+          outs() << "largest";
+          break;
+        case Comdat::NoDeduplicate:
+          outs() << "nodeduplicate";
+          break;
+        case Comdat::SameSize:
+          outs() << "samesize";
+          break;
+        }
+        outs() << ' ' << ComdatTable[Comdat].first << '\n';
+      }
 
       if (TT.isOSBinFormatCOFF() && Sym.isWeak() && Sym.isIndirect())
         outs() << "         fallback " << Sym.getCOFFWeakExternalFallback() << '\n';
diff --git a/src/llvm-project/llvm/tools/llvm-mc-assemble-fuzzer/llvm-mc-assemble-fuzzer.cpp b/src/llvm-project/llvm/tools/llvm-mc-assemble-fuzzer/llvm-mc-assemble-fuzzer.cpp
index 513ddc3..e32eb11 100644
--- a/src/llvm-project/llvm/tools/llvm-mc-assemble-fuzzer/llvm-mc-assemble-fuzzer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mc-assemble-fuzzer/llvm-mc-assemble-fuzzer.cpp
@@ -37,6 +37,8 @@
 
 using namespace llvm;
 
+static mc::RegisterMCTargetOptionsFlags MOF;
+
 static cl::opt<std::string>
     TripleName("triple", cl::desc("Target triple to assemble for, "
                                   "see -version for available targets"));
@@ -170,12 +172,13 @@
     abort();
   }
 
+  std::unique_ptr<MCSubtargetInfo> STI(
+      TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
 
-  MCObjectFileInfo MOFI;
-  MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr);
-
-  static const bool UsePIC = false;
-  MOFI.InitMCObjectFileInfo(TheTriple, UsePIC, Ctx);
+  MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
+  std::unique_ptr<MCObjectFileInfo> MOFI(
+      TheTarget->createMCObjectFileInfo(Ctx, /*PIC=*/false));
+  Ctx.setObjectFileInfo(MOFI.get());
 
   const unsigned OutputAsmVariant = 0;
   std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
@@ -191,8 +194,6 @@
   }
 
   const char *ProgName = "llvm-mc-fuzzer";
-  std::unique_ptr<MCSubtargetInfo> STI(
-      TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
   std::unique_ptr<MCCodeEmitter> CE = nullptr;
   std::unique_ptr<MCAsmBackend> MAB = nullptr;
 
diff --git a/src/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp b/src/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp
index f3a6618..24c601b 100644
--- a/src/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp
@@ -43,23 +43,33 @@
 
 static mc::RegisterMCTargetOptionsFlags MOF;
 
-static cl::opt<std::string>
-InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
+static cl::OptionCategory MCCategory("MC Options");
+
+static cl::opt<std::string> InputFilename(cl::Positional,
+                                          cl::desc("<input file>"),
+                                          cl::init("-"), cl::cat(MCCategory));
+
+static cl::list<std::string>
+    DisassemblerOptions("M", cl::desc("Disassembler options"),
+                        cl::cat(MCCategory));
 
 static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
                                            cl::value_desc("filename"),
-                                           cl::init("-"));
+                                           cl::init("-"), cl::cat(MCCategory));
 
 static cl::opt<std::string> SplitDwarfFile("split-dwarf-file",
                                            cl::desc("DWO output filename"),
-                                           cl::value_desc("filename"));
+                                           cl::value_desc("filename"),
+                                           cl::cat(MCCategory));
 
-static cl::opt<bool>
-ShowEncoding("show-encoding", cl::desc("Show instruction encodings"));
+static cl::opt<bool> ShowEncoding("show-encoding",
+                                  cl::desc("Show instruction encodings"),
+                                  cl::cat(MCCategory));
 
 static cl::opt<bool> RelaxELFRel(
     "relax-relocations", cl::init(true),
-    cl::desc("Emit R_X86_64_GOTPCRELX instead of R_X86_64_GOTPCREL"));
+    cl::desc("Emit R_X86_64_GOTPCRELX instead of R_X86_64_GOTPCREL"),
+    cl::cat(MCCategory));
 
 static cl::opt<DebugCompressionType> CompressDebugSections(
     "compress-debug-sections", cl::ValueOptional,
@@ -69,29 +79,37 @@
                clEnumValN(DebugCompressionType::Z, "zlib",
                           "Use zlib compression"),
                clEnumValN(DebugCompressionType::GNU, "zlib-gnu",
-                          "Use zlib-gnu compression (deprecated)")));
+                          "Use zlib-gnu compression (deprecated)")),
+    cl::cat(MCCategory));
 
 static cl::opt<bool>
-ShowInst("show-inst", cl::desc("Show internal instruction representation"));
+    ShowInst("show-inst", cl::desc("Show internal instruction representation"),
+             cl::cat(MCCategory));
 
 static cl::opt<bool>
-ShowInstOperands("show-inst-operands",
-                 cl::desc("Show instructions operands as parsed"));
+    ShowInstOperands("show-inst-operands",
+                     cl::desc("Show instructions operands as parsed"),
+                     cl::cat(MCCategory));
 
 static cl::opt<unsigned>
-OutputAsmVariant("output-asm-variant",
-                 cl::desc("Syntax variant to use for output printing"));
+    OutputAsmVariant("output-asm-variant",
+                     cl::desc("Syntax variant to use for output printing"),
+                     cl::cat(MCCategory));
 
 static cl::opt<bool>
-PrintImmHex("print-imm-hex", cl::init(false),
-            cl::desc("Prefer hex format for immediate values"));
+    PrintImmHex("print-imm-hex", cl::init(false),
+                cl::desc("Prefer hex format for immediate values"),
+                cl::cat(MCCategory));
 
 static cl::list<std::string>
-DefineSymbol("defsym", cl::desc("Defines a symbol to be an integer constant"));
+    DefineSymbol("defsym",
+                 cl::desc("Defines a symbol to be an integer constant"),
+                 cl::cat(MCCategory));
 
 static cl::opt<bool>
     PreserveComments("preserve-comments",
-                     cl::desc("Preserve Comments in outputted assembly"));
+                     cl::desc("Preserve Comments in outputted assembly"),
+                     cl::cat(MCCategory));
 
 enum OutputFileType {
   OFT_Null,
@@ -99,82 +117,101 @@
   OFT_ObjectFile
 };
 static cl::opt<OutputFileType>
-FileType("filetype", cl::init(OFT_AssemblyFile),
-  cl::desc("Choose an output file type:"),
-  cl::values(
-       clEnumValN(OFT_AssemblyFile, "asm",
-                  "Emit an assembly ('.s') file"),
-       clEnumValN(OFT_Null, "null",
-                  "Don't emit anything (for timing purposes)"),
-       clEnumValN(OFT_ObjectFile, "obj",
-                  "Emit a native object ('.o') file")));
+    FileType("filetype", cl::init(OFT_AssemblyFile),
+             cl::desc("Choose an output file type:"),
+             cl::values(clEnumValN(OFT_AssemblyFile, "asm",
+                                   "Emit an assembly ('.s') file"),
+                        clEnumValN(OFT_Null, "null",
+                                   "Don't emit anything (for timing purposes)"),
+                        clEnumValN(OFT_ObjectFile, "obj",
+                                   "Emit a native object ('.o') file")),
+             cl::cat(MCCategory));
+
+static cl::list<std::string> IncludeDirs("I",
+                                         cl::desc("Directory of include files"),
+                                         cl::value_desc("directory"),
+                                         cl::Prefix, cl::cat(MCCategory));
+
+static cl::opt<std::string>
+    ArchName("arch",
+             cl::desc("Target arch to assemble for, "
+                      "see -version for available targets"),
+             cl::cat(MCCategory));
+
+static cl::opt<std::string>
+    TripleName("triple",
+               cl::desc("Target triple to assemble for, "
+                        "see -version for available targets"),
+               cl::cat(MCCategory));
+
+static cl::opt<std::string>
+    MCPU("mcpu",
+         cl::desc("Target a specific cpu type (-mcpu=help for details)"),
+         cl::value_desc("cpu-name"), cl::init(""), cl::cat(MCCategory));
 
 static cl::list<std::string>
-IncludeDirs("I", cl::desc("Directory of include files"),
-            cl::value_desc("directory"), cl::Prefix);
-
-static cl::opt<std::string>
-ArchName("arch", cl::desc("Target arch to assemble for, "
-                          "see -version for available targets"));
-
-static cl::opt<std::string>
-TripleName("triple", cl::desc("Target triple to assemble for, "
-                              "see -version for available targets"));
-
-static cl::opt<std::string>
-MCPU("mcpu",
-     cl::desc("Target a specific cpu type (-mcpu=help for details)"),
-     cl::value_desc("cpu-name"),
-     cl::init(""));
-
-static cl::list<std::string>
-MAttrs("mattr",
-  cl::CommaSeparated,
-  cl::desc("Target specific attributes (-mattr=help for details)"),
-  cl::value_desc("a1,+a2,-a3,..."));
+    MAttrs("mattr", cl::CommaSeparated,
+           cl::desc("Target specific attributes (-mattr=help for details)"),
+           cl::value_desc("a1,+a2,-a3,..."), cl::cat(MCCategory));
 
 static cl::opt<bool> PIC("position-independent",
-                         cl::desc("Position independent"), cl::init(false));
+                         cl::desc("Position independent"), cl::init(false),
+                         cl::cat(MCCategory));
 
 static cl::opt<bool>
     LargeCodeModel("large-code-model",
                    cl::desc("Create cfi directives that assume the code might "
-                            "be more than 2gb away"));
+                            "be more than 2gb away"),
+                   cl::cat(MCCategory));
 
 static cl::opt<bool>
-NoInitialTextSection("n", cl::desc("Don't assume assembly file starts "
-                                   "in the text section"));
+    NoInitialTextSection("n",
+                         cl::desc("Don't assume assembly file starts "
+                                  "in the text section"),
+                         cl::cat(MCCategory));
 
 static cl::opt<bool>
-GenDwarfForAssembly("g", cl::desc("Generate dwarf debugging info for assembly "
-                                  "source files"));
+    GenDwarfForAssembly("g",
+                        cl::desc("Generate dwarf debugging info for assembly "
+                                 "source files"),
+                        cl::cat(MCCategory));
 
 static cl::opt<std::string>
-DebugCompilationDir("fdebug-compilation-dir",
-                    cl::desc("Specifies the debug info's compilation dir"));
+    DebugCompilationDir("fdebug-compilation-dir",
+                        cl::desc("Specifies the debug info's compilation dir"),
+                        cl::cat(MCCategory));
 
-static cl::list<std::string>
-DebugPrefixMap("fdebug-prefix-map",
-               cl::desc("Map file source paths in debug info"),
-               cl::value_desc("= separated key-value pairs"));
+static cl::list<std::string> DebugPrefixMap(
+    "fdebug-prefix-map", cl::desc("Map file source paths in debug info"),
+    cl::value_desc("= separated key-value pairs"), cl::cat(MCCategory));
 
-static cl::opt<std::string>
-MainFileName("main-file-name",
-             cl::desc("Specifies the name we should consider the input file"));
+static cl::opt<std::string> MainFileName(
+    "main-file-name",
+    cl::desc("Specifies the name we should consider the input file"),
+    cl::cat(MCCategory));
 
 static cl::opt<bool> SaveTempLabels("save-temp-labels",
-                                    cl::desc("Don't discard temporary labels"));
+                                    cl::desc("Don't discard temporary labels"),
+                                    cl::cat(MCCategory));
 
 static cl::opt<bool> LexMasmIntegers(
     "masm-integers",
-    cl::desc("Enable binary and hex masm integers (0b110 and 0ABCh)"));
+    cl::desc("Enable binary and hex masm integers (0b110 and 0ABCh)"),
+    cl::cat(MCCategory));
 
 static cl::opt<bool> LexMasmHexFloats(
     "masm-hexfloats",
-    cl::desc("Enable MASM-style hex float initializers (3F800000r)"));
+    cl::desc("Enable MASM-style hex float initializers (3F800000r)"),
+    cl::cat(MCCategory));
+
+static cl::opt<bool> LexMotorolaIntegers(
+    "motorola-integers",
+    cl::desc("Enable binary and hex Motorola integers (%110 and $ABC)"),
+    cl::cat(MCCategory));
 
 static cl::opt<bool> NoExecStack("no-exec-stack",
-                                 cl::desc("File doesn't need an exec stack"));
+                                 cl::desc("File doesn't need an exec stack"),
+                                 cl::cat(MCCategory));
 
 enum ActionType {
   AC_AsLex,
@@ -183,17 +220,16 @@
   AC_MDisassemble,
 };
 
-static cl::opt<ActionType>
-Action(cl::desc("Action to perform:"),
-       cl::init(AC_Assemble),
-       cl::values(clEnumValN(AC_AsLex, "as-lex",
-                             "Lex tokens from a .s file"),
-                  clEnumValN(AC_Assemble, "assemble",
-                             "Assemble a .s file (default)"),
-                  clEnumValN(AC_Disassemble, "disassemble",
-                             "Disassemble strings of hex bytes"),
-                  clEnumValN(AC_MDisassemble, "mdis",
-                             "Marked up disassembly of strings of hex bytes")));
+static cl::opt<ActionType> Action(
+    cl::desc("Action to perform:"), cl::init(AC_Assemble),
+    cl::values(clEnumValN(AC_AsLex, "as-lex", "Lex tokens from a .s file"),
+               clEnumValN(AC_Assemble, "assemble",
+                          "Assemble a .s file (default)"),
+               clEnumValN(AC_Disassemble, "disassemble",
+                          "Disassemble strings of hex bytes"),
+               clEnumValN(AC_MDisassemble, "mdis",
+                          "Marked up disassembly of strings of hex bytes")),
+    cl::cat(MCCategory));
 
 static const Target *GetTarget(const char *ProgName) {
   // Figure out the target triple.
@@ -305,6 +341,7 @@
   Parser->setTargetParser(*TAP);
   Parser->getLexer().setLexMasmIntegers(LexMasmIntegers);
   Parser->getLexer().setLexMasmHexFloats(LexMasmHexFloats);
+  Parser->getLexer().setLexMotorolaIntegers(LexMotorolaIntegers);
 
   int Res = Parser->Run(NoInitialTextSection);
 
@@ -323,6 +360,7 @@
   // Register the target printer for --version.
   cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
 
+  cl::HideUnrelatedOptions({&MCCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");
   const MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
   setDwarfDebugFlags(argc, argv);
@@ -338,7 +376,7 @@
   Triple TheTriple(TripleName);
 
   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr =
-      MemoryBuffer::getFileOrSTDIN(InputFilename);
+      MemoryBuffer::getFileOrSTDIN(InputFilename, /*IsText=*/true);
   if (std::error_code EC = BufferPtr.getError()) {
     WithColor::error(errs(), ProgName)
         << InputFilename << ": " << EC.message() << '\n';
@@ -374,11 +412,26 @@
   }
   MAI->setPreserveAsmComments(PreserveComments);
 
+  // Package up features to be passed to target/subtarget
+  std::string FeaturesStr;
+  if (MAttrs.size()) {
+    SubtargetFeatures Features;
+    for (unsigned i = 0; i != MAttrs.size(); ++i)
+      Features.AddFeature(MAttrs[i]);
+    FeaturesStr = Features.getString();
+  }
+
+  std::unique_ptr<MCSubtargetInfo> STI(
+      TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
+  assert(STI && "Unable to create subtarget info!");
+
   // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
   // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
-  MCObjectFileInfo MOFI;
-  MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr, &MCOptions);
-  MOFI.InitMCObjectFileInfo(TheTriple, PIC, Ctx, LargeCodeModel);
+  MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr,
+                &MCOptions);
+  std::unique_ptr<MCObjectFileInfo> MOFI(
+      TheTarget->createMCObjectFileInfo(Ctx, PIC, LargeCodeModel));
+  Ctx.setObjectFileInfo(MOFI.get());
 
   if (SaveTempLabels)
     Ctx.setAllowTemporaryLabels(false);
@@ -438,17 +491,9 @@
   if (GenDwarfForAssembly)
     Ctx.setGenDwarfRootFile(InputFilename, Buffer->getBuffer());
 
-  // Package up features to be passed to target/subtarget
-  std::string FeaturesStr;
-  if (MAttrs.size()) {
-    SubtargetFeatures Features;
-    for (unsigned i = 0; i != MAttrs.size(); ++i)
-      Features.AddFeature(MAttrs[i]);
-    FeaturesStr = Features.getString();
-  }
-
-  sys::fs::OpenFlags Flags = (FileType == OFT_AssemblyFile) ? sys::fs::OF_Text
-                                                            : sys::fs::OF_None;
+  sys::fs::OpenFlags Flags = (FileType == OFT_AssemblyFile)
+                                 ? sys::fs::OF_TextWithCRLF
+                                 : sys::fs::OF_None;
   std::unique_ptr<ToolOutputFile> Out = GetOutputStream(OutputFilename, Flags);
   if (!Out)
     return 1;
@@ -471,10 +516,6 @@
   std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
   assert(MCII && "Unable to create instruction info!");
 
-  std::unique_ptr<MCSubtargetInfo> STI(
-      TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
-  assert(STI && "Unable to create subtarget info!");
-
   MCInstPrinter *IP = nullptr;
   if (FileType == OFT_AssemblyFile) {
     IP = TheTarget->createMCInstPrinter(Triple(TripleName), OutputAsmVariant,
@@ -488,6 +529,12 @@
       return 1;
     }
 
+    for (StringRef Opt : DisassemblerOptions)
+      if (!IP->applyTargetSpecificCLOption(Opt)) {
+        WithColor::error() << "invalid disassembler option '" << Opt << "'\n";
+        return 1;
+      }
+
     // Set the display preference for hex vs. decimal immediates.
     IP->setPrintImmHex(PrintImmHex);
 
diff --git a/src/llvm-project/llvm/tools/llvm-mca/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-mca/CMakeLists.txt
index 9df1923..7cfabe7 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-mca/CMakeLists.txt
@@ -1,5 +1,7 @@
 include_directories(include)
 
+add_subdirectory(lib)
+
 set(LLVM_LINK_COMPONENTS
   AllTargetsAsmParsers
   AllTargetsDescs
@@ -30,3 +32,9 @@
   )
 
 set(LLVM_MCA_SOURCE_DIR ${CURRENT_SOURCE_DIR})
+
+target_link_libraries(llvm-mca PRIVATE
+  ${LLVM_MCA_CUSTOMBEHAVIOUR_TARGETS}
+  )
+
+add_definitions(${LLVM_MCA_MACROS_TO_DEFINE})
diff --git a/src/llvm-project/llvm/tools/llvm-mca/CodeRegion.h b/src/llvm-project/llvm/tools/llvm-mca/CodeRegion.h
index d2b05fa..0b25907 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/CodeRegion.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/CodeRegion.h
@@ -53,7 +53,7 @@
   // An optional descriptor for this region.
   llvm::StringRef Description;
   // Instructions that form this region.
-  llvm::SmallVector<llvm::MCInst, 8> Instructions;
+  llvm::SmallVector<llvm::MCInst, 16> Instructions;
   // Source location range.
   llvm::SMLoc RangeStart;
   llvm::SMLoc RangeEnd;
diff --git a/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp b/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
index 831b76a..6ad2a65 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
@@ -106,11 +106,21 @@
   Regions.beginRegion(Comment, Loc);
 }
 
-Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions() {
+Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions(
+    const std::unique_ptr<MCInstPrinter> &IP) {
   MCTargetOptions Opts;
   Opts.PreserveAsmComments = false;
   MCStreamerWrapper Str(Ctx, Regions);
 
+  // Need to initialize an MCTargetStreamer otherwise
+  // certain asm directives will cause a segfault.
+  // Using nulls() so that anything emitted by the MCTagetStreamer
+  // doesn't show up in the llvm-mca output.
+  raw_ostream &OSRef = nulls();
+  formatted_raw_ostream FOSRef(OSRef);
+  TheTarget.createAsmTargetStreamer(Str, FOSRef, IP.get(),
+                                    /*IsVerboseAsm=*/true);
+
   // Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM
   // comments.
   std::unique_ptr<MCAsmParser> Parser(
diff --git a/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h b/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h
index 9a10aa2..1c11784 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h
@@ -39,7 +39,8 @@
 public:
   CodeRegionGenerator(SourceMgr &SM) : Regions(SM) {}
   virtual ~CodeRegionGenerator();
-  virtual Expected<const CodeRegions &> parseCodeRegions() = 0;
+  virtual Expected<const CodeRegions &>
+  parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0;
 };
 
 /// This class is responsible for parsing input ASM and generating
@@ -60,7 +61,8 @@
         AssemblerDialect(0) {}
 
   unsigned getAssemblerDialect() const { return AssemblerDialect; }
-  Expected<const CodeRegions &> parseCodeRegions() override;
+  Expected<const CodeRegions &>
+  parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) override;
 };
 
 } // namespace mca
diff --git a/src/llvm-project/llvm/tools/llvm-mca/PipelinePrinter.cpp b/src/llvm-project/llvm/tools/llvm-mca/PipelinePrinter.cpp
index e7dfbfd..955b825 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/PipelinePrinter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/PipelinePrinter.cpp
@@ -12,14 +12,119 @@
 //===----------------------------------------------------------------------===//
 
 #include "PipelinePrinter.h"
+#include "CodeRegion.h"
+#include "Views/InstructionView.h"
 #include "Views/View.h"
 
 namespace llvm {
 namespace mca {
 
-void PipelinePrinter::printReport(llvm::raw_ostream &OS) const {
-  for (const auto &V : Views)
-    V->printView(OutputKind, OS);
+void PipelinePrinter::printRegionHeader(llvm::raw_ostream &OS) const {
+  StringRef RegionName;
+  if (!Region.getDescription().empty())
+    RegionName = Region.getDescription();
+
+  OS << "\n[" << RegionIdx << "] Code Region";
+  if (!RegionName.empty())
+    OS << " - " << RegionName;
+  OS << "\n\n";
 }
-} // namespace mca.
+
+json::Object PipelinePrinter::getJSONReportRegion() const {
+  json::Object JO;
+
+  StringRef RegionName = "";
+  if (!Region.getDescription().empty())
+    RegionName = Region.getDescription();
+
+  JO.try_emplace("Name", RegionName);
+  for (const auto &V : Views)
+    if (V->isSerializable())
+      JO.try_emplace(V->getNameAsString().str(), V->toJSON());
+
+  return JO;
+}
+
+json::Object PipelinePrinter::getJSONSimulationParameters() const {
+  json::Object SimParameters({{"-mcpu", STI.getCPU()},
+                              {"-mtriple", STI.getTargetTriple().getTriple()},
+                              {"-march", STI.getTargetTriple().getArchName()}});
+
+  const MCSchedModel &SM = STI.getSchedModel();
+  if (!SM.isOutOfOrder())
+    return SimParameters;
+
+  if (PO.RegisterFileSize)
+    SimParameters.try_emplace("-register-file-size", PO.RegisterFileSize);
+
+  if (!PO.AssumeNoAlias)
+    SimParameters.try_emplace("-noalias", PO.AssumeNoAlias);
+
+  if (PO.DecodersThroughput)
+    SimParameters.try_emplace("-decoder-throughput", PO.DecodersThroughput);
+
+  if (PO.MicroOpQueueSize)
+    SimParameters.try_emplace("-micro-op-queue-size", PO.MicroOpQueueSize);
+
+  if (PO.DispatchWidth)
+    SimParameters.try_emplace("-dispatch", PO.DispatchWidth);
+
+  if (PO.LoadQueueSize)
+    SimParameters.try_emplace("-lqueue", PO.LoadQueueSize);
+
+  if (PO.StoreQueueSize)
+    SimParameters.try_emplace("-squeue", PO.StoreQueueSize);
+
+  return SimParameters;
+}
+
+json::Object PipelinePrinter::getJSONTargetInfo() const {
+  json::Array Resources;
+  const MCSchedModel &SM = STI.getSchedModel();
+  StringRef MCPU = STI.getCPU();
+
+  for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) {
+    const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
+    unsigned NumUnits = ProcResource.NumUnits;
+    if (ProcResource.SubUnitsIdxBegin || !NumUnits)
+      continue;
+
+    for (unsigned J = 0; J < NumUnits; ++J) {
+      std::string ResourceName = ProcResource.Name;
+      if (NumUnits > 1) {
+        ResourceName += ".";
+        ResourceName += J;
+      }
+
+      Resources.push_back(ResourceName);
+    }
+  }
+
+  return json::Object({{"CPUName", MCPU}, {"Resources", std::move(Resources)}});
+}
+
+void PipelinePrinter::printReport(json::Object &JO) const {
+  if (!RegionIdx) {
+    JO.try_emplace("TargetInfo", getJSONTargetInfo());
+    JO.try_emplace("SimulationParameters", getJSONSimulationParameters());
+    // Construct an array of regions.
+    JO.try_emplace("CodeRegions", json::Array());
+  }
+
+  json::Array *Regions = JO.getArray("CodeRegions");
+  assert(Regions && "This array must exist!");
+  Regions->push_back(getJSONReportRegion());
+}
+
+void PipelinePrinter::printReport(llvm::raw_ostream &OS) const {
+  // Don't print the header of this region if it is the default region, and if
+  // it doesn't have an end location.
+  if (Region.startLoc().isValid() || Region.endLoc().isValid())
+    printRegionHeader(OS);
+
+  for (const auto &V : Views)
+    V->printView(OS);
+}
+
+} // namespace mca
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-mca/PipelinePrinter.h b/src/llvm-project/llvm/tools/llvm-mca/PipelinePrinter.h
index ae18140..1365f75 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/PipelinePrinter.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/PipelinePrinter.h
@@ -18,6 +18,8 @@
 
 #include "Views/View.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MCA/Context.h"
 #include "llvm/MCA/Pipeline.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -26,6 +28,8 @@
 namespace llvm {
 namespace mca {
 
+class CodeRegion;
+
 /// A printer class that knows how to collects statistics on the
 /// code analyzed by the llvm-mca tool.
 ///
@@ -35,12 +39,21 @@
 /// resource pressure.
 class PipelinePrinter {
   Pipeline &P;
+  const CodeRegion &Region;
+  unsigned RegionIdx;
+  const MCSubtargetInfo &STI;
+  const PipelineOptions &PO;
   llvm::SmallVector<std::unique_ptr<View>, 8> Views;
-  View::OutputKind OutputKind;
+
+  void printRegionHeader(llvm::raw_ostream &OS) const;
+  json::Object getJSONReportRegion() const;
+  json::Object getJSONTargetInfo() const;
+  json::Object getJSONSimulationParameters() const;
 
 public:
-  PipelinePrinter(Pipeline &pipeline, View::OutputKind OutputKind)
-      : P(pipeline), OutputKind(OutputKind) {}
+  PipelinePrinter(Pipeline &Pipe, const CodeRegion &R, unsigned Idx,
+                  const MCSubtargetInfo &STI, const PipelineOptions &PO)
+      : P(Pipe), Region(R), RegionIdx(Idx), STI(STI), PO(PO), Views() {}
 
   void addView(std::unique_ptr<View> V) {
     P.addEventListener(V.get());
@@ -48,6 +61,7 @@
   }
 
   void printReport(llvm::raw_ostream &OS) const;
+  void printReport(json::Object &JO) const;
 };
 } // namespace mca
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp b/src/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp
index 38a8e2e..5b110d6 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp
@@ -66,8 +66,6 @@
 void PressureTracker::handleInstructionIssuedEvent(
     const HWInstructionIssuedEvent &Event) {
   unsigned IID = Event.IR.getSourceIndex();
-  using ResourceRef = HWInstructionIssuedEvent::ResourceRef;
-  using ResourceUse = std::pair<ResourceRef, ResourceCycles>;
   for (const ResourceUse &Use : Event.UsedResources) {
     const ResourceRef &RR = Use.first;
     unsigned Index = ProcResID2ResourceUsersIndex[RR.first];
@@ -200,8 +198,8 @@
   }
 }
 
-void DependencyGraph::propagateThroughEdges(
-    SmallVectorImpl<unsigned> &RootSet, unsigned Iterations) {
+void DependencyGraph::propagateThroughEdges(SmallVectorImpl<unsigned> &RootSet,
+                                            unsigned Iterations) {
   SmallVector<unsigned, 8> ToVisit;
 
   // A critical sequence is computed as the longest path from a node of the
@@ -223,14 +221,14 @@
   // The `unvisited nodes` set initially contains all the nodes from the
   // RootSet.  A node N is added to the `unvisited nodes` if all its
   // predecessors have been visited already.
-  // 
+  //
   // For simplicity, every node tracks the number of unvisited incoming edges in
   // field `NumVisitedPredecessors`.  When the value of that field drops to
   // zero, then the corresponding node is added to a `ToVisit` set.
   //
   // At the end of every iteration of the outer loop, set `ToVisit` becomes our
   // new `unvisited nodes` set.
-  // 
+  //
   // The algorithm terminates when the set of unvisited nodes (i.e. our RootSet)
   // is empty. This algorithm works under the assumption that the graph is
   // acyclic.
@@ -269,8 +267,9 @@
   // that node is the last instruction of our critical sequence.
   // Field N.Depth would tell us the total length of the sequence.
   //
-  // To obtain the sequence of critical edges, we simply follow the chain of critical
-  // predecessors starting from node N (field DGNode::CriticalPredecessor).
+  // To obtain the sequence of critical edges, we simply follow the chain of
+  // critical predecessors starting from node N (field
+  // DGNode::CriticalPredecessor).
   const auto It = std::max_element(
       Nodes.begin(), Nodes.end(),
       [](const DGNode &Lhs, const DGNode &Rhs) { return Lhs.Cost < Rhs.Cost; });
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h b/src/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h
index 427937d..cd5af0a 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h
@@ -33,9 +33,9 @@
 /// In particular, this occurs when there is a delta between the number of uOps
 /// dispatched and the number of uOps issued to the underlying pipelines.
 ///
-/// The bottleneck analysis view is also responsible for identifying and printing
-/// the most "critical" sequence of dependent instructions according to the
-/// simulated run.
+/// The bottleneck analysis view is also responsible for identifying and
+/// printing the most "critical" sequence of dependent instructions according to
+/// the simulated run.
 ///
 /// Below is the critical sequence computed for the dot-product example on
 /// btver2:
@@ -62,13 +62,14 @@
 /// and edges of the graph represent data dependencies or processor resource
 /// interferences.
 ///
-/// Edges are dynamically 'discovered' by observing instruction state transitions
-/// and backend pressure increase events. Edges are internally ranked based on
-/// their "criticality". A dependency is considered to be critical if it takes a
-/// long time to execute, and if it contributes to backend pressure increases.
-/// Criticality is internally measured in terms of cycles; it is computed for
-/// every edge in the graph as a function of the edge latency and the number of
-/// backend pressure increase cycles contributed by that edge.
+/// Edges are dynamically 'discovered' by observing instruction state
+/// transitions and backend pressure increase events. Edges are internally
+/// ranked based on their "criticality". A dependency is considered to be
+/// critical if it takes a long time to execute, and if it contributes to
+/// backend pressure increases. Criticality is internally measured in terms of
+/// cycles; it is computed for every edge in the graph as a function of the edge
+/// latency and the number of backend pressure increase cycles contributed by
+/// that edge.
 ///
 /// At the end of simulation, costs are propagated to nodes through the edges of
 /// the graph, and the most expensive path connecting the root-set (a
@@ -217,8 +218,8 @@
 // Loop carried dependencies are carefully expanded by the bottleneck analysis
 // to guarantee that the graph stays acyclic. To this end, extra nodes are
 // pre-allocated at construction time to describe instructions from "past and
-// future" iterations. The graph is kept acyclic mainly because it simplifies the
-// complexity of the algorithm that computes the critical sequence.
+// future" iterations. The graph is kept acyclic mainly because it simplifies
+// the complexity of the algorithm that computes the critical sequence.
 class DependencyGraph {
   struct DGNode {
     unsigned NumPredecessors;
@@ -239,7 +240,8 @@
 
   void pruneEdges(unsigned Iterations);
   void initializeRootSet(SmallVectorImpl<unsigned> &RootSet) const;
-  void propagateThroughEdges(SmallVectorImpl<unsigned> &RootSet, unsigned Iterations);
+  void propagateThroughEdges(SmallVectorImpl<unsigned> &RootSet,
+                             unsigned Iterations);
 
 #ifndef NDEBUG
   void dumpDependencyEdge(raw_ostream &OS, const DependencyEdge &DE,
@@ -333,7 +335,7 @@
 
   void printView(raw_ostream &OS) const override;
   StringRef getNameAsString() const override { return "BottleneckAnalysis"; }
-  json::Value toJSON() const override { return "not implemented"; }
+  bool isSerializable() const override { return false; }
 
 #ifndef NDEBUG
   void dump(raw_ostream &OS, MCInstPrinter &MCIP) const { DG.dump(OS, MCIP); }
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/DispatchStatistics.cpp b/src/llvm-project/llvm/tools/llvm-mca/Views/DispatchStatistics.cpp
index a1c0cf2..3dc17c8 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/DispatchStatistics.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/DispatchStatistics.cpp
@@ -1,5 +1,4 @@
-//===--------------------- DispatchStatistics.cpp ---------------------*- C++
-//-*-===//
+//===--------------------- DispatchStatistics.cpp ---------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -77,10 +76,23 @@
   printStalls(SS, HWStalls[HWStallEvent::StoreQueueFull], NumCycles);
   SS << "\nGROUP   - Static restrictions on the dispatch group: ";
   printStalls(SS, HWStalls[HWStallEvent::DispatchGroupStall], NumCycles);
+  SS << "\nUSH     - Uncategorised Structural Hazard:           ";
+  printStalls(SS, HWStalls[HWStallEvent::CustomBehaviourStall], NumCycles);
   SS << '\n';
   SS.flush();
   OS << Buffer;
 }
 
+json::Value DispatchStatistics::toJSON() const {
+  json::Object JO({{"RAT", HWStalls[HWStallEvent::RegisterFileStall]},
+                   {"RCU", HWStalls[HWStallEvent::RetireControlUnitStall]},
+                   {"SCHEDQ", HWStalls[HWStallEvent::SchedulerQueueFull]},
+                   {"LQ", HWStalls[HWStallEvent::LoadQueueFull]},
+                   {"SQ", HWStalls[HWStallEvent::StoreQueueFull]},
+                   {"GROUP", HWStalls[HWStallEvent::DispatchGroupStall]},
+                   {"USH", HWStalls[HWStallEvent::CustomBehaviourStall]}});
+  return JO;
+}
+
 } // namespace mca
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/DispatchStatistics.h b/src/llvm-project/llvm/tools/llvm-mca/Views/DispatchStatistics.h
index 8d999fb..81b582f 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/DispatchStatistics.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/DispatchStatistics.h
@@ -79,6 +79,7 @@
     printDispatchHistogram(OS);
   }
   StringRef getNameAsString() const override { return "DispatchStatistics"; }
+  json::Value toJSON() const override;
 };
 } // namespace mca
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp b/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp
index 2248f63..3f6abf4 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp
@@ -93,7 +93,7 @@
     MutableArrayRef<InstructionInfoViewData> IIVD) const {
   const llvm::MCSubtargetInfo &STI = getSubTargetInfo();
   const MCSchedModel &SM = STI.getSchedModel();
-  for (const auto &I : zip(getSource(), IIVD)) {
+  for (const auto I : zip(getSource(), IIVD)) {
     const MCInst &Inst = std::get<0>(I);
     InstructionInfoViewData &IIVDEntry = std::get<1>(I);
     const MCInstrDesc &MCDesc = MCII.get(Inst.getOpcode());
@@ -147,7 +147,7 @@
     JO.try_emplace("Instruction", (unsigned)I.index());
     InstInfo.push_back(std::move(JO));
   }
-  return json::Value(std::move(InstInfo));
+  return json::Object({{"InstructionList", json::Value(std::move(InstInfo))}});
 }
 } // namespace mca.
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionView.cpp b/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionView.cpp
index 7f7a5b7..3b174a0 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionView.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionView.cpp
@@ -1,4 +1,4 @@
-//===----------------------- View.cpp ---------------------------*- C++ -*-===//
+//===----------------------- InstructionView.cpp ----------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -11,15 +11,18 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#include <sstream>
 #include "Views/InstructionView.h"
 #include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 
 namespace llvm {
 namespace mca {
 
-StringRef InstructionView::printInstructionString(const llvm::MCInst &MCI) const {
+InstructionView::~InstructionView() = default;
+
+StringRef
+InstructionView::printInstructionString(const llvm::MCInst &MCI) const {
   InstructionString = "";
   MCIP.printInst(&MCI, 0, "", STI, InstrStream);
   InstrStream.flush();
@@ -28,33 +31,13 @@
 }
 
 json::Value InstructionView::toJSON() const {
-  json::Object JO;
   json::Array SourceInfo;
   for (const auto &MCI : getSource()) {
     StringRef Instruction = printInstructionString(MCI);
     SourceInfo.push_back(Instruction.str());
   }
-  JO.try_emplace("Instructions", std::move(SourceInfo));
-
-  json::Array Resources;
-  const MCSchedModel &SM = STI.getSchedModel();
-  for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) {
-    const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
-    unsigned NumUnits = ProcResource.NumUnits;
-    // Skip groups and invalid resources with zero units.
-    if (ProcResource.SubUnitsIdxBegin || !NumUnits)
-      continue;
-    for (unsigned J = 0; J < NumUnits; ++J) {
-      std::stringstream ResNameStream;
-      ResNameStream << ProcResource.Name;
-      if (NumUnits > 1)
-        ResNameStream << "." << J;
-      Resources.push_back(ResNameStream.str());
-    }
-  }
-  JO.try_emplace("Resources", json::Object({{"CPUName", MCPU}, {"Resources", std::move(Resources)}}));
-
-  return JO;
+  return SourceInfo;
 }
+
 } // namespace mca
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionView.h b/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionView.h
index 2a260b9..1843b05 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionView.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionView.h
@@ -1,4 +1,4 @@
-//===----------------------- InstrucionView.h -----------------------------*- C++ -*-===//
+//===----------------------- InstructionView.h ------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -16,9 +16,8 @@
 #define LLVM_TOOLS_LLVM_MCA_INSTRUCTIONVIEW_H
 
 #include "Views/View.h"
-#include "llvm/MC/MCInstPrinter.h"
-#include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/JSON.h"
+#include "llvm/Support/raw_ostream.h"
 
 namespace llvm {
 namespace mca {
@@ -28,7 +27,6 @@
   const llvm::MCSubtargetInfo &STI;
   llvm::MCInstPrinter &MCIP;
   llvm::ArrayRef<llvm::MCInst> Source;
-  StringRef MCPU;
 
   mutable std::string InstructionString;
   mutable raw_string_ostream InstrStream;
@@ -36,17 +34,13 @@
 public:
   void printView(llvm::raw_ostream &) const override {}
   InstructionView(const llvm::MCSubtargetInfo &STI,
-                  llvm::MCInstPrinter &Printer,
-                  llvm::ArrayRef<llvm::MCInst> S,
-                  StringRef MCPU = StringRef())
-      : STI(STI), MCIP(Printer), Source(S), MCPU(MCPU),
-        InstrStream(InstructionString) {}
+                  llvm::MCInstPrinter &Printer, llvm::ArrayRef<llvm::MCInst> S)
+      : STI(STI), MCIP(Printer), Source(S), InstrStream(InstructionString) {}
 
-  virtual ~InstructionView() = default;
+  virtual ~InstructionView();
 
-  StringRef getNameAsString() const override {
-    return "Instructions and CPU resources";
-  }
+  StringRef getNameAsString() const override { return "Instructions"; }
+
   // Return a reference to a string representing a given machine instruction.
   // The result should be used or copied before the next call to
   // printInstructionString() as it will overwrite the previous result.
@@ -55,12 +49,10 @@
 
   llvm::MCInstPrinter &getInstPrinter() const { return MCIP; }
   llvm::ArrayRef<llvm::MCInst> getSource() const { return Source; }
+
   json::Value toJSON() const override;
-  virtual void printViewJSON(llvm::raw_ostream &OS) override {
-    json::Value JV = toJSON();
-    OS << formatv("{0:2}", JV) << "\n";
-  }
 };
+
 } // namespace mca
 } // namespace llvm
 
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp b/src/llvm-project/llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp
index 58736ee..4ef8053 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp
@@ -60,18 +60,21 @@
   if (!Inst.isOptimizableMove())
     return;
 
-  assert(Inst.getDefs().size() == 1 && "Expected a single definition!");
-  assert(Inst.getUses().size() == 1 && "Expected a single register use!");
-  const WriteState &WS = Inst.getDefs()[0];
-  const ReadState &RS = Inst.getUses()[0];
+  if (Inst.getDefs().size() != Inst.getUses().size())
+    return;
 
-  MoveEliminationInfo &Info =
-      MoveElimInfo[Inst.getDefs()[0].getRegisterFileID()];
-  Info.TotalMoveEliminationCandidates++;
-  if (WS.isEliminated())
-    Info.CurrentMovesEliminated++;
-  if (WS.isWriteZero() && RS.isReadZero())
-    Info.TotalMovesThatPropagateZero++;
+  for (size_t I = 0, E = Inst.getDefs().size(); I < E; ++I) {
+    const WriteState &WS = Inst.getDefs()[I];
+    const ReadState &RS = Inst.getUses()[E - (I + 1)];
+
+    MoveEliminationInfo &Info =
+        MoveElimInfo[Inst.getDefs()[0].getRegisterFileID()];
+    Info.TotalMoveEliminationCandidates++;
+    if (WS.isEliminated())
+      Info.CurrentMovesEliminated++;
+    if (WS.isWriteZero() && RS.isReadZero())
+      Info.TotalMovesThatPropagateZero++;
+  }
 }
 
 void RegisterFileStatistics::onEvent(const HWInstructionEvent &Event) {
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/RegisterFileStatistics.h b/src/llvm-project/llvm/tools/llvm-mca/Views/RegisterFileStatistics.h
index cf384db..ec5c5f4 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/RegisterFileStatistics.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/RegisterFileStatistics.h
@@ -76,6 +76,7 @@
   StringRef getNameAsString() const override {
     return "RegisterFileStatistics";
   }
+  bool isSerializable() const override { return false; }
 };
 } // namespace mca
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.cpp b/src/llvm-project/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.cpp
index 61c115b..1c40428 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.cpp
@@ -71,7 +71,8 @@
   }
 
   unsigned AvgUsage = (double)SumOfUsedEntries / NumCycles;
-  double MaxUsagePercentage = ((double)MaxUsedEntries / TotalROBEntries) * 100.0;
+  double MaxUsagePercentage =
+      ((double)MaxUsedEntries / TotalROBEntries) * 100.0;
   double NormalizedMaxPercentage = floor((MaxUsagePercentage * 10) + 0.5) / 10;
   double AvgUsagePercentage = ((double)AvgUsage / TotalROBEntries) * 100.0;
   double NormalizedAvgPercentage = floor((AvgUsagePercentage * 10) + 0.5) / 10;
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h b/src/llvm-project/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h
index 662a223..86b46e9 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h
@@ -55,6 +55,7 @@
   StringRef getNameAsString() const override {
     return "RetireControlUnitStatistics";
   }
+  bool isSerializable() const override { return false; }
 };
 
 } // namespace mca
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/SchedulerStatistics.h b/src/llvm-project/llvm/tools/llvm-mca/Views/SchedulerStatistics.h
index 734046c..66f4b00 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/SchedulerStatistics.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/SchedulerStatistics.h
@@ -89,6 +89,7 @@
 
   void printView(llvm::raw_ostream &OS) const override;
   StringRef getNameAsString() const override { return "SchedulerStatistics"; }
+  bool isSerializable() const override { return false; }
 };
 } // namespace mca
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/SummaryView.cpp b/src/llvm-project/llvm/tools/llvm-mca/Views/SummaryView.cpp
index c0fe3b5..bf258b4 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/SummaryView.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/SummaryView.cpp
@@ -1,4 +1,4 @@
-//===--------------------- SummaryView.cpp -------------------*- C++ -*-===//
+//===--------------------- SummaryView.cpp ----------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -24,9 +24,8 @@
 
 SummaryView::SummaryView(const MCSchedModel &Model, ArrayRef<MCInst> S,
                          unsigned Width)
-    : SM(Model), Source(S), DispatchWidth(Width?Width: Model.IssueWidth),
-      LastInstructionIdx(0),
-      TotalCycles(0), NumMicroOps(0),
+    : SM(Model), Source(S), DispatchWidth(Width ? Width : Model.IssueWidth),
+      LastInstructionIdx(0), TotalCycles(0), NumMicroOps(0),
       ProcResourceUsage(Model.getNumProcResourceKinds(), 0),
       ProcResourceMasks(Model.getNumProcResourceKinds()),
       ResIdx2ProcResID(Model.getNumProcResourceKinds(), 0) {
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/SummaryView.h b/src/llvm-project/llvm/tools/llvm-mca/Views/SummaryView.h
index 2622e86..e2c7cfd 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/SummaryView.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/SummaryView.h
@@ -1,4 +1,4 @@
-//===--------------------- SummaryView.h ---------------------*- C++ -*-===//
+//===--------------------- SummaryView.h ------------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/TimelineView.cpp b/src/llvm-project/llvm/tools/llvm-mca/Views/TimelineView.cpp
index c8b481b..4ecc301 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/TimelineView.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/TimelineView.cpp
@@ -21,8 +21,8 @@
                            llvm::ArrayRef<llvm::MCInst> S, unsigned Iterations,
                            unsigned Cycles)
     : InstructionView(sti, Printer, S), CurrentCycle(0),
-      MaxCycle(Cycles == 0 ? 80 : Cycles), LastCycle(0), WaitTime(S.size()),
-      UsedBuffer(S.size()) {
+      MaxCycle(Cycles == 0 ? std::numeric_limits<unsigned>::max() : Cycles),
+      LastCycle(0), WaitTime(S.size()), UsedBuffer(S.size()) {
   unsigned NumInstructions = getSource().size();
   assert(Iterations && "Invalid number of iterations specified!");
   NumInstructions *= Iterations;
@@ -77,8 +77,10 @@
            "Instruction cannot be ready if it hasn't been dispatched yet!");
     WTEntry.CyclesSpentInSQWhileReady +=
         TVEntry.CycleIssued - TVEntry.CycleReady;
-    WTEntry.CyclesSpentAfterWBAndBeforeRetire +=
-        (CurrentCycle - 1) - TVEntry.CycleExecuted;
+    if (CurrentCycle > TVEntry.CycleExecuted) {
+      WTEntry.CyclesSpentAfterWBAndBeforeRetire +=
+          (CurrentCycle - 1) - TVEntry.CycleExecuted;
+    }
     break;
   }
   case HWInstructionEvent::Ready:
@@ -143,10 +145,11 @@
 
   double AverageTime1, AverageTime2, AverageTime3;
   AverageTime1 =
-      (double)Entry.CyclesSpentInSchedulerQueue / CumulativeExecutions;
-  AverageTime2 = (double)Entry.CyclesSpentInSQWhileReady / CumulativeExecutions;
-  AverageTime3 =
-      (double)Entry.CyclesSpentAfterWBAndBeforeRetire / CumulativeExecutions;
+      (double)(Entry.CyclesSpentInSchedulerQueue * 10) / CumulativeExecutions;
+  AverageTime2 =
+      (double)(Entry.CyclesSpentInSQWhileReady * 10) / CumulativeExecutions;
+  AverageTime3 = (double)(Entry.CyclesSpentAfterWBAndBeforeRetire * 10) /
+                 CumulativeExecutions;
 
   OS << Executions;
   OS.PadToColumn(13);
@@ -155,18 +158,18 @@
   if (!PrintingTotals)
     tryChangeColor(OS, Entry.CyclesSpentInSchedulerQueue, CumulativeExecutions,
                    BufferSize);
-  OS << format("%.1f", floor((AverageTime1 * 10) + 0.5) / 10);
+  OS << format("%.1f", floor(AverageTime1 + 0.5) / 10);
   OS.PadToColumn(20);
   if (!PrintingTotals)
     tryChangeColor(OS, Entry.CyclesSpentInSQWhileReady, CumulativeExecutions,
                    BufferSize);
-  OS << format("%.1f", floor((AverageTime2 * 10) + 0.5) / 10);
+  OS << format("%.1f", floor(AverageTime2 + 0.5) / 10);
   OS.PadToColumn(27);
   if (!PrintingTotals)
     tryChangeColor(OS, Entry.CyclesSpentAfterWBAndBeforeRetire,
                    CumulativeExecutions,
                    getSubTargetInfo().getSchedModel().MicroOpBufferSize);
-  OS << format("%.1f", floor((AverageTime3 * 10) + 0.5) / 10);
+  OS << format("%.1f", floor(AverageTime3 + 0.5) / 10);
 
   if (OS.has_colors())
     OS.resetColor();
@@ -243,7 +246,8 @@
 
   for (unsigned I = Entry.CycleExecuted + 1, E = Entry.CycleRetired; I < E; ++I)
     OS << TimelineView::DisplayChar::RetireLag;
-  OS << TimelineView::DisplayChar::Retired;
+  if (Entry.CycleExecuted < Entry.CycleRetired)
+    OS << TimelineView::DisplayChar::Retired;
 
   // Skip other columns.
   for (unsigned I = Entry.CycleRetired + 1, E = LastCycle; I <= E; ++I)
@@ -285,7 +289,14 @@
   for (unsigned Iteration = 0; Iteration < Iterations; ++Iteration) {
     for (const MCInst &Inst : Source) {
       const TimelineViewEntry &Entry = Timeline[IID];
-      if (Entry.CycleRetired == 0)
+      // When an instruction is retired after timeline-max-cycles,
+      // its CycleRetired is left at 0. However, it's possible for
+      // a 0 latency instruction to be retired during cycle 0 and we
+      // don't want to early exit in that case. The CycleExecuted
+      // attribute is set correctly whether or not it is greater
+      // than timeline-max-cycles so we can use that to ensure
+      // we don't early exit because of a 0 latency instruction.
+      if (Entry.CycleRetired == 0 && Entry.CycleExecuted != 0)
         return;
 
       unsigned SourceIndex = IID % Source.size();
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/TimelineView.h b/src/llvm-project/llvm/tools/llvm-mca/Views/TimelineView.h
index 81f2b03..81be824 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/TimelineView.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/TimelineView.h
@@ -125,7 +125,7 @@
   unsigned LastCycle;
 
   struct TimelineViewEntry {
-    int CycleDispatched;  // A negative value is an "invalid cycle".
+    int CycleDispatched; // A negative value is an "invalid cycle".
     unsigned CycleReady;
     unsigned CycleIssued;
     unsigned CycleExecuted;
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/View.h b/src/llvm-project/llvm/tools/llvm-mca/Views/View.h
index 85464bf..c604733 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/View.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/View.h
@@ -17,32 +17,22 @@
 
 #include "llvm/MC/MCInstPrinter.h"
 #include "llvm/MCA/HWEventListener.h"
-#include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/JSON.h"
+#include "llvm/Support/raw_ostream.h"
 
 namespace llvm {
 namespace mca {
 
 class View : public HWEventListener {
 public:
-  enum OutputKind { OK_READABLE, OK_JSON };
-
-  void printView(OutputKind OutputKind, llvm::raw_ostream &OS) {
-    if (OutputKind == OK_JSON)
-      printViewJSON(OS);
-    else
-      printView(OS);
-  }
+  virtual ~View() = default;
 
   virtual void printView(llvm::raw_ostream &OS) const = 0;
-  virtual void printViewJSON(llvm::raw_ostream &OS) {
-    json::Object JO;
-    JO.try_emplace(getNameAsString().str(), toJSON());
-    OS << formatv("{0:2}", json::Value(std::move(JO))) << "\n";
-  }
-  virtual ~View() = default;
   virtual StringRef getNameAsString() const = 0;
+
   virtual json::Value toJSON() const { return "not implemented"; }
+  virtual bool isSerializable() const { return true; }
+
   void anchor() override;
 };
 } // namespace mca
diff --git a/src/llvm-project/llvm/tools/llvm-mca/lib/AMDGPU/AMDGPUCustomBehaviour.cpp b/src/llvm-project/llvm/tools/llvm-mca/lib/AMDGPU/AMDGPUCustomBehaviour.cpp
new file mode 100644
index 0000000..a655f3f
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-mca/lib/AMDGPU/AMDGPUCustomBehaviour.cpp
@@ -0,0 +1,33 @@
+//===------------------ AMDGPUCustomBehaviour.cpp ---------------*-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
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements methods from the AMDGPUCustomBehaviour class.
+///
+//===----------------------------------------------------------------------===//
+
+#include "AMDGPUCustomBehaviour.h"
+#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
+#include "SIInstrInfo.h"
+#include "llvm/Support/WithColor.h"
+
+namespace llvm {
+namespace mca {
+
+AMDGPUCustomBehaviour::AMDGPUCustomBehaviour(const MCSubtargetInfo &STI,
+                                             const SourceMgr &SrcMgr,
+                                             const MCInstrInfo &MCII)
+    : CustomBehaviour(STI, SrcMgr, MCII) {}
+
+unsigned AMDGPUCustomBehaviour::checkCustomHazard(ArrayRef<InstRef> IssuedInst,
+                                                  const InstRef &IR) {
+  return 0;
+}
+
+} // namespace mca
+} // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-mca/lib/AMDGPU/AMDGPUCustomBehaviour.h b/src/llvm-project/llvm/tools/llvm-mca/lib/AMDGPU/AMDGPUCustomBehaviour.h
new file mode 100644
index 0000000..0dd21c7
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-mca/lib/AMDGPU/AMDGPUCustomBehaviour.h
@@ -0,0 +1,57 @@
+//===------------------- AMDGPUCustomBehaviour.h ----------------*-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
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines the AMDGPUCustomBehaviour class which inherits from
+/// CustomBehaviour.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_LIB_AMDGPU_AMDGPUCUSTOMBEHAVIOUR_H
+#define LLVM_TOOLS_LLVM_MCA_LIB_AMDGPU_AMDGPUCUSTOMBEHAVIOUR_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/MCA/CustomBehaviour.h"
+#include "llvm/Support/TargetParser.h"
+
+namespace llvm {
+namespace mca {
+
+class AMDGPUInstrPostProcess : public InstrPostProcess {
+public:
+  AMDGPUInstrPostProcess(const MCSubtargetInfo &STI, const MCInstrInfo &MCII)
+      : InstrPostProcess(STI, MCII) {}
+
+  ~AMDGPUInstrPostProcess() {}
+
+  void postProcessInstruction(std::unique_ptr<Instruction> &Inst,
+                              const MCInst &MCI) override {}
+};
+
+class AMDGPUCustomBehaviour : public CustomBehaviour {
+public:
+  AMDGPUCustomBehaviour(const MCSubtargetInfo &STI, const SourceMgr &SrcMgr,
+                        const MCInstrInfo &MCII);
+
+  ~AMDGPUCustomBehaviour() {}
+
+  /// This method is used to determine if an instruction
+  /// should be allowed to be dispatched. The return value is
+  /// how many cycles until the instruction can be dispatched.
+  /// This method is called after MCA has already checked for
+  /// register and hardware dependencies so this method should only
+  /// implement custom behaviour and dependencies that are not picked up
+  /// by MCA naturally.
+  unsigned checkCustomHazard(ArrayRef<InstRef> IssuedInst,
+                             const InstRef &IR) override;
+};
+
+} // namespace mca
+} // namespace llvm
+
+#endif /* LLVM_TOOLS_LLVM_MCA_LIB_AMDGPU_AMDGPUCUSTOMBEHAVIOUR_H */
diff --git a/src/llvm-project/llvm/tools/llvm-mca/lib/AMDGPU/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-mca/lib/AMDGPU/CMakeLists.txt
new file mode 100644
index 0000000..cd6e171
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-mca/lib/AMDGPU/CMakeLists.txt
@@ -0,0 +1,18 @@
+include_directories(
+  ${LLVM_MAIN_SRC_DIR}/lib/Target/AMDGPU
+  ${LLVM_BINARY_DIR}/lib/Target/AMDGPU
+  )
+
+set(LLVM_LINK_COMPONENTS
+  AMDGPU
+  Core
+  MCA
+  Support
+  )
+
+add_llvm_library(LLVMMCACustomBehaviourAMDGPU
+  AMDGPUCustomBehaviour.cpp
+
+  DEPENDS
+  AMDGPUCommonTableGen
+  )
diff --git a/src/llvm-project/llvm/tools/llvm-mca/lib/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-mca/lib/CMakeLists.txt
new file mode 100644
index 0000000..57057dc
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-mca/lib/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(TARGETS_TO_APPEND "")
+set(MACROS_TO_APPEND "")
+
+if (LLVM_TARGETS_TO_BUILD MATCHES "AMDGPU")
+  add_subdirectory(AMDGPU)
+  list(APPEND TARGETS_TO_APPEND LLVMMCACustomBehaviourAMDGPU)
+  list(APPEND MACROS_TO_APPEND -DHAS_AMDGPU)
+endif()
+
+set(LLVM_MCA_CUSTOMBEHAVIOUR_TARGETS ${TARGETS_TO_APPEND} PARENT_SCOPE)
+set(LLVM_MCA_MACROS_TO_DEFINE ${MACROS_TO_APPEND} PARENT_SCOPE)
diff --git a/src/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp b/src/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp
index 13a2c63..a473cd8 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp
@@ -32,6 +32,9 @@
 #include "Views/SchedulerStatistics.h"
 #include "Views/SummaryView.h"
 #include "Views/TimelineView.h"
+#ifdef HAS_AMDGPU
+#include "lib/AMDGPU/AMDGPUCustomBehaviour.h"
+#endif
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCCodeEmitter.h"
@@ -42,6 +45,7 @@
 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
 #include "llvm/MCA/CodeEmitter.h"
 #include "llvm/MCA/Context.h"
+#include "llvm/MCA/CustomBehaviour.h"
 #include "llvm/MCA/InstrBuilder.h"
 #include "llvm/MCA/Pipeline.h"
 #include "llvm/MCA/Stages/EntryStage.h"
@@ -91,15 +95,13 @@
          cl::desc("Target a specific cpu type (-mcpu=help for details)"),
          cl::value_desc("cpu-name"), cl::cat(ToolOptions), cl::init("native"));
 
-static cl::opt<std::string>
-    MATTR("mattr",
-          cl::desc("Additional target features."),
-          cl::cat(ToolOptions));
+static cl::opt<std::string> MATTR("mattr",
+                                  cl::desc("Additional target features."),
+                                  cl::cat(ToolOptions));
 
-static cl::opt<bool>
-    PrintJson("json",
-          cl::desc("Print the output in json format"),
-          cl::cat(ToolOptions), cl::init(false));
+static cl::opt<bool> PrintJson("json",
+                               cl::desc("Print the output in json format"),
+                               cl::cat(ToolOptions), cl::init(false));
 
 static cl::opt<int>
     OutputAsmVariant("output-asm-variant",
@@ -172,11 +174,11 @@
     cl::desc("Maximum number of iterations to print in timeline view"),
     cl::cat(ViewOptions), cl::init(0));
 
-static cl::opt<unsigned> TimelineMaxCycles(
-    "timeline-max-cycles",
-    cl::desc(
-        "Maximum number of cycles in the timeline view. Defaults to 80 cycles"),
-    cl::cat(ViewOptions), cl::init(80));
+static cl::opt<unsigned>
+    TimelineMaxCycles("timeline-max-cycles",
+                      cl::desc("Maximum number of cycles in the timeline view, "
+                               "or 0 for unlimited. Defaults to 80 cycles"),
+                      cl::cat(ViewOptions), cl::init(80));
 
 static cl::opt<bool>
     AssumeNoAlias("noalias",
@@ -220,6 +222,12 @@
     cl::desc("Print encoding information in the instruction info view"),
     cl::cat(ViewOptions), cl::init(false));
 
+static cl::opt<bool> DisableCustomBehaviour(
+    "disable-cb",
+    cl::desc(
+        "Disable custom behaviour (use the default class which does nothing)."),
+    cl::cat(ViewOptions), cl::init(false));
+
 namespace {
 
 const Target *getTarget(const char *ProgName) {
@@ -236,6 +244,9 @@
     return nullptr;
   }
 
+  // Update TripleName with the updated triple from the target lookup.
+  TripleName = TheTriple.str();
+
   // Return the found target.
   return TheTarget;
 }
@@ -244,8 +255,8 @@
   if (OutputFilename == "")
     OutputFilename = "-";
   std::error_code EC;
-  auto Out =
-      std::make_unique<ToolOutputFile>(OutputFilename, EC, sys::fs::OF_Text);
+  auto Out = std::make_unique<ToolOutputFile>(OutputFilename, EC,
+                                              sys::fs::OF_TextWithCRLF);
   if (!EC)
     return std::move(Out);
   return EC;
@@ -257,14 +268,15 @@
     O = Default.getValue();
 }
 
-static void processViewOptions() {
+static void processViewOptions(bool IsOutOfOrder) {
   if (!EnableAllViews.getNumOccurrences() &&
       !EnableAllStats.getNumOccurrences())
     return;
 
   if (EnableAllViews.getNumOccurrences()) {
     processOptionImpl(PrintSummaryView, EnableAllViews);
-    processOptionImpl(EnableBottleneckAnalysis, EnableAllViews);
+    if (IsOutOfOrder)
+      processOptionImpl(EnableBottleneckAnalysis, EnableAllViews);
     processOptionImpl(PrintResourcePressureView, EnableAllViews);
     processOptionImpl(PrintTimelineView, EnableAllViews);
     processOptionImpl(PrintInstructionInfoView, EnableAllViews);
@@ -277,7 +289,41 @@
   processOptionImpl(PrintRegisterFileStats, Default);
   processOptionImpl(PrintDispatchStats, Default);
   processOptionImpl(PrintSchedulerStats, Default);
-  processOptionImpl(PrintRetireStats, Default);
+  if (IsOutOfOrder)
+    processOptionImpl(PrintRetireStats, Default);
+}
+
+std::unique_ptr<mca::InstrPostProcess>
+createInstrPostProcess(const Triple &TheTriple, const MCSubtargetInfo &STI,
+                       const MCInstrInfo &MCII) {
+  // Might be a good idea to have a separate flag so that InstrPostProcess
+  // can be used with or without CustomBehaviour
+  if (DisableCustomBehaviour)
+    return std::make_unique<mca::InstrPostProcess>(STI, MCII);
+#ifdef HAS_AMDGPU
+  if (TheTriple.isAMDGPU())
+    return std::make_unique<mca::AMDGPUInstrPostProcess>(STI, MCII);
+#endif
+  return std::make_unique<mca::InstrPostProcess>(STI, MCII);
+}
+
+std::unique_ptr<mca::CustomBehaviour>
+createCustomBehaviour(const Triple &TheTriple, const MCSubtargetInfo &STI,
+                      const mca::SourceMgr &SrcMgr, const MCInstrInfo &MCII) {
+  // Build the appropriate CustomBehaviour object for the current target.
+  // The CustomBehaviour class should never depend on the source code,
+  // but it can depend on the list of mca::Instruction and any classes
+  // that can be built using just the target info. If you need extra
+  // information from the source code or the list of MCInst, consider
+  // adding that information to the mca::Instruction class and setting
+  // it during InstrBuilder::createInstruction().
+  if (DisableCustomBehaviour)
+    return std::make_unique<mca::CustomBehaviour>(STI, SrcMgr, MCII);
+#ifdef HAS_AMDGPU
+  if (TheTriple.isAMDGPU())
+    return std::make_unique<mca::AMDGPUCustomBehaviour>(STI, SrcMgr, MCII);
+#endif
+  return std::make_unique<mca::CustomBehaviour>(STI, SrcMgr, MCII);
 }
 
 // Returns true on success.
@@ -327,9 +373,6 @@
     return 1;
   }
 
-  // Apply overrides to llvm-mca specific options.
-  processViewOptions();
-
   if (MCPU == "native")
     MCPU = std::string(llvm::sys::getHostCPUName());
 
@@ -339,10 +382,10 @@
   if (!STI->isCPUStringValid(MCPU))
     return 1;
 
-  if (!PrintInstructionTables && !STI->getSchedModel().isOutOfOrder()) {
-    WithColor::error() << "please specify an out-of-order cpu. '" << MCPU
-                       << "' is an in-order cpu.\n";
-    return 1;
+  bool IsOutOfOrder = STI->getSchedModel().isOutOfOrder();
+  if (!PrintInstructionTables && !IsOutOfOrder) {
+    WithColor::warning() << "support for in-order CPU '" << MCPU
+                         << "' is experimental.\n";
   }
 
   if (!STI->getSchedModel().hasInstrSchedModel()) {
@@ -358,6 +401,9 @@
     return 1;
   }
 
+  // Apply overrides to llvm-mca specific options.
+  processViewOptions(IsOutOfOrder);
+
   std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
   assert(MRI && "Unable to create target register info!");
 
@@ -366,15 +412,15 @@
       TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
   assert(MAI && "Unable to create target asm info!");
 
-  MCObjectFileInfo MOFI;
   SourceMgr SrcMgr;
 
   // Tell SrcMgr about this buffer, which is what the parser will pick up.
   SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc());
 
-  MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr);
-
-  MOFI.InitMCObjectFileInfo(TheTriple, /* PIC= */ false, Ctx);
+  MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
+  std::unique_ptr<MCObjectFileInfo> MOFI(
+      TheTarget->createMCObjectFileInfo(Ctx, /*PIC=*/false));
+  Ctx.setObjectFileInfo(MOFI.get());
 
   std::unique_ptr<buffer_ostream> BOS;
 
@@ -384,9 +430,28 @@
   std::unique_ptr<MCInstrAnalysis> MCIA(
       TheTarget->createMCInstrAnalysis(MCII.get()));
 
+  // Need to initialize an MCInstPrinter as it is
+  // required for initializing the MCTargetStreamer
+  // which needs to happen within the CRG.parseCodeRegions() call below.
+  // Without an MCTargetStreamer, certain assembly directives can trigger a
+  // segfault. (For example, the .cv_fpo_proc directive on x86 will segfault if
+  // we don't initialize the MCTargetStreamer.)
+  unsigned IPtempOutputAsmVariant =
+      OutputAsmVariant == -1 ? 0 : OutputAsmVariant;
+  std::unique_ptr<MCInstPrinter> IPtemp(TheTarget->createMCInstPrinter(
+      Triple(TripleName), IPtempOutputAsmVariant, *MAI, *MCII, *MRI));
+  if (!IPtemp) {
+    WithColor::error()
+        << "unable to create instruction printer for target triple '"
+        << TheTriple.normalize() << "' with assembly variant "
+        << IPtempOutputAsmVariant << ".\n";
+    return 1;
+  }
+
   // Parse the input and create CodeRegions that llvm-mca can analyze.
   mca::AsmCodeRegionGenerator CRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI, *MCII);
-  Expected<const mca::CodeRegions &> RegionsOrErr = CRG.parseCodeRegions();
+  Expected<const mca::CodeRegions &> RegionsOrErr =
+      CRG.parseCodeRegions(std::move(IPtemp));
   if (!RegionsOrErr) {
     if (auto Err =
             handleErrors(RegionsOrErr.takeError(), [](const StringError &E) {
@@ -456,24 +521,19 @@
       *STI, *MRI, mc::InitMCTargetOptionsFromFlags()));
   assert(MAB && "Unable to create asm backend!");
 
+  json::Object JSONOutput;
   for (const std::unique_ptr<mca::CodeRegion> &Region : Regions) {
     // Skip empty code regions.
     if (Region->empty())
       continue;
 
-    // Don't print the header of this region if it is the default region, and
-    // it doesn't have an end location.
-    if (Region->startLoc().isValid() || Region->endLoc().isValid()) {
-      TOF->os() << "\n[" << RegionIdx++ << "] Code Region";
-      StringRef Desc = Region->getDescription();
-      if (!Desc.empty())
-        TOF->os() << " - " << Desc;
-      TOF->os() << "\n\n";
-    }
+    IB.clear();
 
     // Lower the MCInst sequence into an mca::Instruction sequence.
     ArrayRef<MCInst> Insts = Region->getInstructions();
     mca::CodeEmitter CE(*STI, *MAB, *MCE, Insts);
+    std::unique_ptr<mca::InstrPostProcess> IPP =
+        createInstrPostProcess(TheTriple, *STI, *MCII);
     std::vector<std::unique_ptr<mca::Instruction>> LoweredSequence;
     for (const MCInst &MCI : Insts) {
       Expected<std::unique_ptr<mca::Instruction>> Inst =
@@ -496,6 +556,8 @@
         return 1;
       }
 
+      IPP->postProcessInstruction(Inst.get(), MCI);
+
       LoweredSequence.emplace_back(std::move(Inst.get()));
     }
 
@@ -506,7 +568,12 @@
       auto P = std::make_unique<mca::Pipeline>();
       P->appendStage(std::make_unique<mca::EntryStage>(S));
       P->appendStage(std::make_unique<mca::InstructionTables>(SM));
-      mca::PipelinePrinter Printer(*P, mca::View::OK_READABLE);
+
+      mca::PipelinePrinter Printer(*P, *Region, RegionIdx, *STI, PO);
+      if (PrintJson) {
+        Printer.addView(
+            std::make_unique<mca::InstructionView>(*STI, *IP, Insts));
+      }
 
       // Create the views for this pipeline, execute, and emit a report.
       if (PrintInstructionInfoView) {
@@ -519,26 +586,47 @@
       if (!runPipeline(*P))
         return 1;
 
-      Printer.printReport(TOF->os());
+      if (PrintJson) {
+        Printer.printReport(JSONOutput);
+      } else {
+        Printer.printReport(TOF->os());
+      }
+
+      ++RegionIdx;
       continue;
     }
 
+    // Create the CustomBehaviour object for enforcing Target Specific
+    // behaviours and dependencies that aren't expressed well enough
+    // in the tablegen. CB cannot depend on the list of MCInst or
+    // the source code (but it can depend on the list of
+    // mca::Instruction or any objects that can be reconstructed
+    // from the target information).
+    std::unique_ptr<mca::CustomBehaviour> CB =
+        createCustomBehaviour(TheTriple, *STI, S, *MCII);
+
     // Create a basic pipeline simulating an out-of-order backend.
-    auto P = MCA.createDefaultPipeline(PO, S);
-    mca::PipelinePrinter Printer(*P, PrintJson ? mca::View::OK_JSON
-                                               : mca::View::OK_READABLE);
+    auto P = MCA.createDefaultPipeline(PO, S, *CB);
+
+    mca::PipelinePrinter Printer(*P, *Region, RegionIdx, *STI, PO);
 
     // When we output JSON, we add a view that contains the instructions
     // and CPU resource information.
-    if (PrintJson)
-      Printer.addView(
-          std::make_unique<mca::InstructionView>(*STI, *IP, Insts, MCPU));
+    if (PrintJson) {
+      auto IV = std::make_unique<mca::InstructionView>(*STI, *IP, Insts);
+      Printer.addView(std::move(IV));
+    }
 
     if (PrintSummaryView)
       Printer.addView(
           std::make_unique<mca::SummaryView>(SM, Insts, DispatchWidth));
 
     if (EnableBottleneckAnalysis) {
+      if (!IsOutOfOrder) {
+        WithColor::warning()
+            << "bottleneck analysis is not supported for in-order CPU '" << MCPU
+            << "'.\n";
+      }
       Printer.addView(std::make_unique<mca::BottleneckAnalysis>(
           *STI, *IP, Insts, S.getNumIterations()));
     }
@@ -574,12 +662,18 @@
     if (!runPipeline(*P))
       return 1;
 
-    Printer.printReport(TOF->os());
+    if (PrintJson) {
+      Printer.printReport(JSONOutput);
+    } else {
+      Printer.printReport(TOF->os());
+    }
 
-    // Clear the InstrBuilder internal state in preparation for another round.
-    IB.clear();
+    ++RegionIdx;
   }
 
+  if (PrintJson)
+    TOF->os() << formatv("{0:2}", json::Value(std::move(JSONOutput))) << "\n";
+
   TOF->keep();
   return 0;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-ml/Disassembler.cpp b/src/llvm-project/llvm/tools/llvm-ml/Disassembler.cpp
index 8eeddb7..793128c 100644
--- a/src/llvm-project/llvm/tools/llvm-ml/Disassembler.cpp
+++ b/src/llvm-project/llvm/tools/llvm-ml/Disassembler.cpp
@@ -123,31 +123,31 @@
   return false;
 }
 
-int Disassembler::disassemble(const Target &T, const std::string &Triple,
+int Disassembler::disassemble(const Target &T, const std::string &TripleName,
                               MCSubtargetInfo &STI, MCStreamer &Streamer,
                               MemoryBuffer &Buffer, SourceMgr &SM,
                               raw_ostream &Out) {
-  std::unique_ptr<const MCRegisterInfo> MRI(T.createMCRegInfo(Triple));
+  std::unique_ptr<const MCRegisterInfo> MRI(T.createMCRegInfo(TripleName));
   if (!MRI) {
-    errs() << "error: no register info for target " << Triple << "\n";
+    errs() << "error: no register info for target " << TripleName << "\n";
     return -1;
   }
 
   MCTargetOptions MCOptions;
   std::unique_ptr<const MCAsmInfo> MAI(
-      T.createMCAsmInfo(*MRI, Triple, MCOptions));
+      T.createMCAsmInfo(*MRI, TripleName, MCOptions));
   if (!MAI) {
-    errs() << "error: no assembly info for target " << Triple << "\n";
+    errs() << "error: no assembly info for target " << TripleName << "\n";
     return -1;
   }
 
   // Set up the MCContext for creating symbols and MCExpr's.
-  MCContext Ctx(MAI.get(), MRI.get(), nullptr);
+  MCContext Ctx(Triple(TripleName), MAI.get(), MRI.get(), &STI);
 
   std::unique_ptr<const MCDisassembler> DisAsm(
       T.createMCDisassembler(STI, Ctx));
   if (!DisAsm) {
-    errs() << "error: no disassembler for target " << Triple << "\n";
+    errs() << "error: no disassembler for target " << TripleName << "\n";
     return -1;
   }
 
diff --git a/src/llvm-project/llvm/tools/llvm-ml/Opts.td b/src/llvm-project/llvm/tools/llvm-ml/Opts.td
index 4c2757b..631c856 100644
--- a/src/llvm-project/llvm/tools/llvm-ml/Opts.td
+++ b/src/llvm-project/llvm/tools/llvm-ml/Opts.td
@@ -27,29 +27,12 @@
 class UnsupportedSeparate<string name> : Separate<["/", "-"], name>,
                                          Group<unsupported_Group>;
 
-def help : MLFlag<"?">,
-           HelpText<"Display available options">;
-def help_long : MLFlag<"help">, Alias<help>;
-def assemble_only : MLFlag<"c">, HelpText<"Assemble only; do not link">;
-def define : MLJoinedOrSeparate<"D">, MetaVarName<"<macro>=<value>">,
-             HelpText<"Define <macro> to <value> (or blank if <value> "
-                      "omitted)">;
-def output_file : MLJoinedOrSeparate<"Fo">, HelpText<"Names the output file">;
-def include_path : MLJoinedOrSeparate<"I">,
-                   HelpText<"Sets path for include files">;
-def safeseh : MLFlag<"safeseh">,
-              HelpText<"Mark resulting object files as either containing no "
-                       "exception handlers or containing exception handlers "
-                       "that are all declared with .SAFESEH. Only available in "
-                       "32-bit.">;
-def assembly_file : MLJoinedOrSeparate<"Ta">,
-                    HelpText<"Assemble source file with name not ending with "
-                             "the .asm extension">;
-
 def bitness : LLVMJoined<"m">, Values<"32,64">,
               HelpText<"Target platform (x86 or x86-64)">;
 def as_lex : LLVMFlag<"as-lex">,
              HelpText<"Lex tokens from a .asm file without assembling">;
+def fatal_warnings : LLVMFlag<"fatal-warnings">,
+                     HelpText<"Treat warnings as errors">;
 def filetype : LLVMJoined<"filetype=">, Values<"obj,s,null">,
                HelpText<"Emit a file with the given type">;
 def output_att_asm : LLVMFlag<"output-att-asm">,
@@ -68,6 +51,36 @@
                         HelpText<"Preserve comments in output assembly">;
 def save_temp_labels : LLVMFlag<"save-temp-labels">,
                        HelpText<"Don't discard temporary labels">;
+def timestamp : LLVMJoined<"timestamp=">,
+                HelpText<"Specify the assembly timestamp (used for @Date and "
+                         "@Time built-ins)">;
+def utc : LLVMFlag<"utc">,
+          HelpText<"Render @Date and @Time built-ins in GMT/UTC">;
+def gmtime : LLVMFlag<"gmtime">, Alias<utc>;
+
+def help : MLFlag<"?">,
+           HelpText<"Display available options">;
+def help_long : MLFlag<"help">, Alias<help>;
+def assemble_only : MLFlag<"c">, HelpText<"Assemble only; do not link">;
+def define : MLJoinedOrSeparate<"D">, MetaVarName<"<macro>=<value>">,
+             HelpText<"Define <macro> to <value> (or blank if <value> "
+                      "omitted)">;
+def output_file : MLJoinedOrSeparate<"Fo">, HelpText<"Names the output file">;
+def include_path : MLJoinedOrSeparate<"I">,
+                   HelpText<"Sets path for include files">;
+def safeseh : MLFlag<"safeseh">,
+              HelpText<"Mark resulting object files as either containing no "
+                       "exception handlers or containing exception handlers "
+                       "that are all declared with .SAFESEH. Only available in "
+                       "32-bit.">;
+def assembly_file : MLJoinedOrSeparate<"Ta">,
+                    HelpText<"Assemble source file with name not ending with "
+                             "the .asm extension">;
+def error_on_warning : MLFlag<"WX">, Alias<fatal_warnings>;
+def parse_only : MLFlag<"Zs">, HelpText<"Run a syntax-check only">,
+                 Alias<filetype>, AliasArgs<["null"]>;
+def ignore_include_envvar : MLFlag<"X">,
+                            HelpText<"Ignore the INCLUDE environment variable">;
 
 def tiny_model_support : UnsupportedFlag<"AT">, HelpText<"">;
 def alternate_linker : UnsupportedJoined<"Bl">, HelpText<"">;
@@ -100,11 +113,8 @@
 def listing_false_conditionals : UnsupportedFlag<"Sx">, HelpText<"">;
 def extra_warnings : UnsupportedFlag<"w">, HelpText<"">;
 def warning_level : UnsupportedJoined<"W">, HelpText<"">;
-def error_on_warning : UnsupportedFlag<"WX">, HelpText<"">;
-def ignore_include_envvar : UnsupportedFlag<"X">, HelpText<"">;
 def line_number_info : UnsupportedFlag<"Zd">, HelpText<"">;
 def export_all_symbols : UnsupportedFlag<"Zf">, HelpText<"">;
 def codeview_info : UnsupportedFlag<"Zi">, HelpText<"">;
 def enable_m510_option : UnsupportedFlag<"Zm">, HelpText<"">;
 def structure_packing : UnsupportedJoined<"Zp">, HelpText<"">;
-def parse_only : UnsupportedFlag<"Zs">, HelpText<"">;
diff --git a/src/llvm-project/llvm/tools/llvm-ml/llvm-ml.cpp b/src/llvm-project/llvm/tools/llvm-ml/llvm-ml.cpp
index 1733dcd..0e6b055 100644
--- a/src/llvm-project/llvm/tools/llvm-ml/llvm-ml.cpp
+++ b/src/llvm-project/llvm/tools/llvm-ml/llvm-ml.cpp
@@ -36,11 +36,13 @@
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/ToolOutputFile.h"
 #include "llvm/Support/WithColor.h"
+#include <ctime>
 
 using namespace llvm;
 using namespace llvm::opt;
@@ -96,7 +98,7 @@
 
 static std::unique_ptr<ToolOutputFile> GetOutputStream(StringRef Path) {
   std::error_code EC;
-  auto Out = std::make_unique<ToolOutputFile>(Path, EC, sys::fs::F_None);
+  auto Out = std::make_unique<ToolOutputFile>(Path, EC, sys::fs::OF_None);
   if (EC) {
     WithColor::error() << EC.message() << '\n';
     return nullptr;
@@ -129,8 +131,31 @@
                          MCAsmInfo &MAI, MCSubtargetInfo &STI,
                          MCInstrInfo &MCII, MCTargetOptions &MCOptions,
                          const opt::ArgList &InputArgs) {
+  struct tm TM;
+  time_t Timestamp;
+  if (InputArgs.hasArg(OPT_timestamp)) {
+    StringRef TimestampStr = InputArgs.getLastArgValue(OPT_timestamp);
+    int64_t IntTimestamp;
+    if (TimestampStr.getAsInteger(10, IntTimestamp)) {
+      WithColor::error(errs(), ProgName)
+          << "invalid timestamp '" << TimestampStr
+          << "'; must be expressed in seconds since the UNIX epoch.\n";
+      return 1;
+    }
+    Timestamp = IntTimestamp;
+  } else {
+    Timestamp = time(nullptr);
+  }
+  if (InputArgs.hasArg(OPT_utc)) {
+    // Not thread-safe.
+    TM = *gmtime(&Timestamp);
+  } else {
+    // Not thread-safe.
+    TM = *localtime(&Timestamp);
+  }
+
   std::unique_ptr<MCAsmParser> Parser(
-      createMCMasmParser(SrcMgr, Ctx, Str, MAI, 0));
+      createMCMasmParser(SrcMgr, Ctx, Str, MAI, TM, 0));
   std::unique_ptr<MCTargetAsmParser> TAP(
       TheTarget->createMCAsmParser(STI, *Parser, MCII, MCOptions));
 
@@ -219,7 +244,7 @@
 
   if (InputArgs.hasArg(OPT_help)) {
     std::string Usage = llvm::formatv("{0} [ /options ] file", ProgName).str();
-    T.PrintHelp(outs(), Usage.c_str(), "LLVM MASM Assembler",
+    T.printHelp(outs(), Usage.c_str(), "LLVM MASM Assembler",
                 /*ShowHidden=*/false);
     return 0;
   } else if (InputFilename.empty()) {
@@ -231,6 +256,7 @@
 
   MCTargetOptions MCOptions;
   MCOptions.AssemblyLanguage = "masm";
+  MCOptions.MCFatalWarnings = InputArgs.hasArg(OPT_fatal_warnings);
 
   Triple TheTriple = GetTriple(ProgName, InputArgs);
   std::string Error;
@@ -262,8 +288,21 @@
   SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc());
 
   // Record the location of the include directories so that the lexer can find
-  // it later.
-  SrcMgr.setIncludeDirs(InputArgs.getAllArgValues(OPT_include_path));
+  // included files later.
+  std::vector<std::string> IncludeDirs =
+      InputArgs.getAllArgValues(OPT_include_path);
+  if (!InputArgs.hasArg(OPT_ignore_include_envvar)) {
+    if (llvm::Optional<std::string> IncludeEnvVar =
+            llvm::sys::Process::GetEnv("INCLUDE")) {
+      SmallVector<StringRef, 8> Dirs;
+      StringRef(*IncludeEnvVar)
+          .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+      IncludeDirs.reserve(IncludeDirs.size() + Dirs.size());
+      for (StringRef Dir : Dirs)
+        IncludeDirs.push_back(Dir.str());
+    }
+  }
+  SrcMgr.setIncludeDirs(IncludeDirs);
 
   std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
   assert(MRI && "Unable to create target register info!");
@@ -274,12 +313,16 @@
 
   MAI->setPreserveAsmComments(InputArgs.hasArg(OPT_preserve_comments));
 
+  std::unique_ptr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(
+      TripleName, /*CPU=*/"", /*Features=*/""));
+  assert(STI && "Unable to create subtarget info!");
+
   // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
   // MCObjectFileInfo needs a MCContext reference in order to initialize itself.
-  MCObjectFileInfo MOFI;
-  MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr);
-  MOFI.InitMCObjectFileInfo(TheTriple, /*PIC=*/false, Ctx,
-                            /*LargeCodeModel=*/true);
+  MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
+  std::unique_ptr<MCObjectFileInfo> MOFI(TheTarget->createMCObjectFileInfo(
+      Ctx, /*PIC=*/false, /*LargeCodeModel=*/true));
+  Ctx.setObjectFileInfo(MOFI.get());
 
   if (InputArgs.hasArg(OPT_save_temp_labels))
     Ctx.setAllowTemporaryLabels(false);
@@ -311,10 +354,6 @@
   std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
   assert(MCII && "Unable to create instruction info!");
 
-  std::unique_ptr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(
-      TripleName, /*CPU=*/"", /*Features=*/""));
-  assert(STI && "Unable to create subtarget info!");
-
   MCInstPrinter *IP = nullptr;
   if (FileType == "s") {
     const bool OutputATTAsm = InputArgs.hasArg(OPT_output_att_asm);
diff --git a/src/llvm-project/llvm/tools/llvm-modextract/llvm-modextract.cpp b/src/llvm-project/llvm/tools/llvm-modextract/llvm-modextract.cpp
index 7c40996..9a44cbf 100644
--- a/src/llvm-project/llvm/tools/llvm-modextract/llvm-modextract.cpp
+++ b/src/llvm-project/llvm/tools/llvm-modextract/llvm-modextract.cpp
@@ -21,21 +21,29 @@
 
 using namespace llvm;
 
+static cl::OptionCategory ModextractCategory("Modextract Options");
+
 static cl::opt<bool>
-    BinaryExtract("b", cl::desc("Whether to perform binary extraction"));
+    BinaryExtract("b", cl::desc("Whether to perform binary extraction"),
+                  cl::cat(ModextractCategory));
 
 static cl::opt<std::string> OutputFilename("o", cl::Required,
                                            cl::desc("Output filename"),
-                                           cl::value_desc("filename"));
+                                           cl::value_desc("filename"),
+                                           cl::cat(ModextractCategory));
 
-static cl::opt<std::string>
-    InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
+static cl::opt<std::string> InputFilename(cl::Positional,
+                                          cl::desc("<input bitcode>"),
+                                          cl::init("-"),
+                                          cl::cat(ModextractCategory));
 
 static cl::opt<unsigned> ModuleIndex("n", cl::Required,
                                      cl::desc("Index of module to extract"),
-                                     cl::value_desc("index"));
+                                     cl::value_desc("index"),
+                                     cl::cat(ModextractCategory));
 
 int main(int argc, char **argv) {
+  cl::HideUnrelatedOptions({&ModextractCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv, "Module extractor");
 
   ExitOnError ExitOnErr("llvm-modextract: error: ");
diff --git a/src/llvm-project/llvm/tools/llvm-mt/llvm-mt.cpp b/src/llvm-project/llvm/tools/llvm-mt/llvm-mt.cpp
index 997e5ac..6f26765 100644
--- a/src/llvm-project/llvm/tools/llvm-mt/llvm-mt.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mt/llvm-mt.cpp
@@ -109,7 +109,7 @@
   }
 
   if (InputArgs.hasArg(OPT_help)) {
-    T.PrintHelp(outs(), "llvm-mt [options] file...", "Manifest Tool", false);
+    T.printHelp(outs(), "llvm-mt [options] file...", "Manifest Tool", false);
     return 0;
   }
 
diff --git a/src/llvm-project/llvm/tools/llvm-nm/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-nm/CMakeLists.txt
index 42699bf..4ad5370 100644
--- a/src/llvm-project/llvm/tools/llvm-nm/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-nm/CMakeLists.txt
@@ -6,14 +6,20 @@
   Core
   Demangle
   Object
+  Option
   Support
   TextAPI
   )
 
+set(LLVM_TARGET_DEFINITIONS Opts.td)
+tablegen(LLVM Opts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(NmOptsTableGen)
+
 add_llvm_tool(llvm-nm
   llvm-nm.cpp
 
   DEPENDS
+  NmOptsTableGen
   intrinsics_gen
   )
 
diff --git a/src/llvm-project/llvm/tools/llvm-nm/Opts.td b/src/llvm-project/llvm/tools/llvm-nm/Opts.td
new file mode 100644
index 0000000..3a79089
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-nm/Opts.td
@@ -0,0 +1,76 @@
+include "llvm/Option/OptParser.td"
+
+class F<string letter, string help> : Flag<["-"], letter>, HelpText<help>;
+class FF<string name, string help> : Flag<["--"], name>, HelpText<help>;
+
+multiclass BB<string name, string help1, string help2> {
+  def NAME: Flag<["--"], name>, HelpText<help1>;
+  def no_ # NAME: Flag<["--"], "no-" # name>, HelpText<help2>;
+}
+
+multiclass Eq<string name, string help> {
+  def NAME #_EQ : Joined<["--"], name #"=">, HelpText<help>;
+  def : Separate<["--"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
+}
+
+def debug_syms : FF<"debug-syms", "Show all symbols, even debugger only">;
+def defined_only : FF<"defined-only", "Show only defined symbols">;
+defm demangle : BB<"demangle", "Demangle C++ symbol names", "Don't demangle symbol names">;
+def dynamic : FF<"dynamic", "Display dynamic symbols instead of normal symbols">;
+def extern_only : FF<"extern-only", "Show only external symbols">;
+defm format : Eq<"format", "Specify output format: bsd (default), posix, sysv, darwin, just-symbols">, MetaVarName<"<format>">;
+def help : FF<"help", "Display this help">;
+def no_llvm_bc : FF<"no-llvm-bc", "Disable LLVM bitcode reader">;
+def no_sort : FF<"no-sort", "Show symbols in order encountered">;
+def no_weak : FF<"no-weak", "Show only non-weak symbols">;
+def numeric_sort : FF<"numeric-sort", "Sort symbols by address">;
+def print_armap : FF<"print-armap", "Print the archive map">;
+def print_file_name : FF<"print-file-name", "Precede each symbol with the object file it came from">;
+def print_size : FF<"print-size", "Show symbol size as well as address">;
+def quiet : FF<"quiet", "Suppress 'no symbols' diagnostic">;
+defm radix : Eq<"radix", "Radix (o/d/x) for printing symbol Values">, MetaVarName<"<radix>">;
+def reverse_sort : FF<"reverse-sort", "Sort in reverse order">;
+def size_sort : FF<"size-sort", "Sort symbols by size">;
+def special_syms : FF<"special-syms", "Do not filter special symbols from the output">;
+def undefined_only : FF<"undefined-only", "Show only undefined symbols">;
+def version : FF<"version", "Display the version">;
+def without_aliases : FF<"without-aliases", "Exclude aliases from output">, Flags<[HelpHidden]>;
+
+// Mach-O specific options.
+def grp_mach_o : OptionGroup<"kind">, HelpText<"llvm-nm Mach-O Specific Options">;
+
+def add_dyldinfo : FF<"add-dyldinfo", "Add symbols from the dyldinfo not already in the symbol table">, Group<grp_mach_o>;
+def add_inlinedinfo : FF<"add-inlinedinfo", "Add symbols from the inlined libraries, TBD only">, Group<grp_mach_o>;
+def arch_EQ : Joined<["--"], "arch=">, HelpText<"architecture(s) from a Mach-O file to dump">, Group<grp_mach_o>;
+def : Separate<["--", "-"], "arch">, Alias<arch_EQ>;
+def dyldinfo_only : FF<"dyldinfo-only", "Show only symbols from the dyldinfo">, Group<grp_mach_o>;
+def no_dyldinfo : FF<"no-dyldinfo", "Don't add any symbols from the dyldinfo">, Group<grp_mach_o>;
+def s : F<"s", "Dump only symbols from this segment and section name">, Group<grp_mach_o>;
+def x : F<"x", "Print symbol entry in hex">, Group<grp_mach_o>;
+
+def : FF<"just-symbol-name", "Alias for --format=just-symbols">, Alias<format_EQ>, AliasArgs<["just-symbols"]>, Flags<[HelpHidden]>;
+def : FF<"portability", "Alias for --format=posix">, Alias<format_EQ>, AliasArgs<["posix"]>;
+
+def : F<"a", "Alias for --debug-syms">, Alias<debug_syms>;
+def : F<"A", "Alias for --print-file-name">, Alias<print_file_name>;
+def : F<"B", "Alias for --format=bsd">, Alias<format_EQ>, AliasArgs<["bsd"]>;
+def : F<"C", "Alias for --demangle">, Alias<demangle>;
+def : F<"D", "Alias for --dynamic">, Alias<dynamic>;
+def : JoinedOrSeparate<["-"], "f">, HelpText<"Alias for --format">, Alias<format_EQ>, MetaVarName<"<format>">;
+def : F<"h", "Alias for --help">, Alias<help>;
+def : F<"g", "Alias for --extern-only">, Alias<extern_only>;
+def : F<"j", "Alias for --format=just-symbols">, Alias<format_EQ>, AliasArgs<["just-symbols"]>;
+def : F<"m", "Alias for --format=darwin">, Alias<format_EQ>, AliasArgs<["darwin"]>;
+def : F<"M", "Deprecated alias for --print-armap">, Alias<print_armap>, Flags<[HelpHidden]>;
+def : F<"n", "Alias for --numeric-sort">, Alias<numeric_sort>;
+def : F<"o", "Alias for --print-file-name">, Alias<print_file_name>;
+def : F<"p", "Alias for --no-sort">, Alias<no_sort>;
+def : F<"P", "Alias for --format=posix">, Alias<format_EQ>, AliasArgs<["posix"]>;
+def : F<"r", "Alias for --reverse-sort">, Alias<reverse_sort>;
+def : F<"S", "Alias for --print-size">, Alias<print_size>;
+def : JoinedOrSeparate<["-"], "t">, HelpText<"Alias for --radix">, Alias<radix_EQ>, MetaVarName<"<radix>">;
+def : F<"u", "Alias for --undefined-only">, Alias<undefined_only>;
+def : F<"U", "Deprecated alias for --defined-only">, Alias<defined_only>, Flags<[HelpHidden]>;
+def : F<"v", "Alias for --numeric-sort">, Alias<numeric_sort>;
+def : F<"V", "Alias for --version">, Alias<version>;
+def : F<"W", "Deprecated alias for --no-weak">, Alias<no_weak>, Flags<[HelpHidden]>;
diff --git a/src/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp b/src/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp
index c678108..ffb427a 100644
--- a/src/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/src/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -31,6 +31,9 @@
 #include "llvm/Object/TapiFile.h"
 #include "llvm/Object/TapiUniversal.h"
 #include "llvm/Object/Wasm.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
@@ -47,192 +50,86 @@
 using namespace object;
 
 namespace {
-enum OutputFormatTy { bsd, sysv, posix, darwin };
+using namespace llvm::opt; // for HelpHidden in Opts.inc
+enum ID {
+  OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  OPT_##ID,
+#include "Opts.inc"
+#undef OPTION
+};
 
-cl::OptionCategory NMCat("llvm-nm Options");
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#include "Opts.inc"
+#undef PREFIX
 
-cl::opt<OutputFormatTy> OutputFormat(
-    "format", cl::desc("Specify output format"),
-    cl::values(clEnumVal(bsd, "BSD format"), clEnumVal(sysv, "System V format"),
-               clEnumVal(posix, "POSIX.2 format"),
-               clEnumVal(darwin, "Darwin -m format")),
-    cl::init(bsd), cl::cat(NMCat));
-cl::alias OutputFormat2("f", cl::desc("Alias for --format"),
-                        cl::aliasopt(OutputFormat));
+static const opt::OptTable::Info InfoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  {                                                                            \
+      PREFIX,      NAME,      HELPTEXT,                                        \
+      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
+      PARAM,       FLAGS,     OPT_##GROUP,                                     \
+      OPT_##ALIAS, ALIASARGS, VALUES},
+#include "Opts.inc"
+#undef OPTION
+};
 
-cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
-                                     cl::ZeroOrMore);
+class NmOptTable : public opt::OptTable {
+public:
+  NmOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+};
 
-cl::opt<bool> UndefinedOnly("undefined-only",
-                            cl::desc("Show only undefined symbols"),
-                            cl::cat(NMCat));
-cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"),
-                         cl::aliasopt(UndefinedOnly), cl::Grouping);
+enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
+} // namespace
 
-cl::opt<bool> DynamicSyms("dynamic",
-                          cl::desc("Display the dynamic symbols instead "
-                                   "of normal symbols."),
-                          cl::cat(NMCat));
-cl::alias DynamicSyms2("D", cl::desc("Alias for --dynamic"),
-                       cl::aliasopt(DynamicSyms), cl::Grouping);
+static bool ArchiveMap;
+static bool DebugSyms;
+static bool DefinedOnly;
+static bool Demangle;
+static bool DynamicSyms;
+static bool ExternalOnly;
+static OutputFormatTy OutputFormat;
+static bool NoLLVMBitcode;
+static bool NoSort;
+static bool NoWeakSymbols;
+static bool NumericSort;
+static bool PrintFileName;
+static bool PrintSize;
+static bool Quiet;
+static bool ReverseSort;
+static bool SpecialSyms;
+static bool SizeSort;
+static bool UndefinedOnly;
+static bool WithoutAliases;
 
-cl::opt<bool> DefinedOnly("defined-only", cl::desc("Show only defined symbols"),
-                          cl::cat(NMCat));
-cl::alias DefinedOnly2("U", cl::desc("Alias for --defined-only"),
-                       cl::aliasopt(DefinedOnly), cl::Grouping);
-
-cl::opt<bool> ExternalOnly("extern-only",
-                           cl::desc("Show only external symbols"),
-                           cl::ZeroOrMore, cl::cat(NMCat));
-cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"),
-                        cl::aliasopt(ExternalOnly), cl::Grouping,
-                        cl::ZeroOrMore);
-
-cl::opt<bool> NoWeakSymbols("no-weak", cl::desc("Show only non-weak symbols"),
-                            cl::cat(NMCat));
-cl::alias NoWeakSymbols2("W", cl::desc("Alias for --no-weak"),
-                         cl::aliasopt(NoWeakSymbols), cl::Grouping);
-
-cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd"), cl::Grouping,
-                        cl::cat(NMCat));
-cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix"),
-                          cl::Grouping, cl::cat(NMCat));
-cl::alias Portability("portability", cl::desc("Alias for --format=posix"),
-                      cl::aliasopt(POSIXFormat), cl::NotHidden);
-cl::opt<bool> DarwinFormat("m", cl::desc("Alias for --format=darwin"),
-                           cl::Grouping, cl::cat(NMCat));
-
-static cl::list<std::string>
-    ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
-              cl::ZeroOrMore, cl::cat(NMCat));
-bool ArchAll = false;
-
-cl::opt<bool> PrintFileName(
-    "print-file-name",
-    cl::desc("Precede each symbol with the object file it came from"),
-    cl::cat(NMCat));
-
-cl::alias PrintFileNameA("A", cl::desc("Alias for --print-file-name"),
-                         cl::aliasopt(PrintFileName), cl::Grouping);
-cl::alias PrintFileNameo("o", cl::desc("Alias for --print-file-name"),
-                         cl::aliasopt(PrintFileName), cl::Grouping);
-
-cl::opt<bool> DebugSyms("debug-syms",
-                        cl::desc("Show all symbols, even debugger only"),
-                        cl::cat(NMCat));
-cl::alias DebugSymsa("a", cl::desc("Alias for --debug-syms"),
-                     cl::aliasopt(DebugSyms), cl::Grouping);
-
-cl::opt<bool> NumericSort("numeric-sort", cl::desc("Sort symbols by address"),
-                          cl::cat(NMCat));
-cl::alias NumericSortn("n", cl::desc("Alias for --numeric-sort"),
-                       cl::aliasopt(NumericSort), cl::Grouping);
-cl::alias NumericSortv("v", cl::desc("Alias for --numeric-sort"),
-                       cl::aliasopt(NumericSort), cl::Grouping);
-
-cl::opt<bool> NoSort("no-sort", cl::desc("Show symbols in order encountered"),
-                     cl::cat(NMCat));
-cl::alias NoSortp("p", cl::desc("Alias for --no-sort"), cl::aliasopt(NoSort),
-                  cl::Grouping);
-
-cl::opt<bool> Demangle("demangle", cl::ZeroOrMore,
-                       cl::desc("Demangle C++ symbol names"), cl::cat(NMCat));
-cl::alias DemangleC("C", cl::desc("Alias for --demangle"),
-                    cl::aliasopt(Demangle), cl::Grouping);
-cl::opt<bool> NoDemangle("no-demangle", cl::init(false), cl::ZeroOrMore,
-                         cl::desc("Don't demangle symbol names"),
-                         cl::cat(NMCat));
-
-cl::opt<bool> ReverseSort("reverse-sort", cl::desc("Sort in reverse order"),
-                          cl::cat(NMCat));
-cl::alias ReverseSortr("r", cl::desc("Alias for --reverse-sort"),
-                       cl::aliasopt(ReverseSort), cl::Grouping);
-
-cl::opt<bool> PrintSize("print-size",
-                        cl::desc("Show symbol size as well as address"),
-                        cl::cat(NMCat));
-cl::alias PrintSizeS("S", cl::desc("Alias for --print-size"),
-                     cl::aliasopt(PrintSize), cl::Grouping);
-bool MachOPrintSizeWarning = false;
-
-cl::opt<bool> SizeSort("size-sort", cl::desc("Sort symbols by size"),
-                       cl::cat(NMCat));
-
-cl::opt<bool> WithoutAliases("without-aliases", cl::Hidden,
-                             cl::desc("Exclude aliases from output"),
-                             cl::cat(NMCat));
-
-cl::opt<bool> ArchiveMap("print-armap", cl::desc("Print the archive map"),
-                         cl::cat(NMCat));
-cl::alias ArchiveMaps("M", cl::desc("Alias for --print-armap"),
-                      cl::aliasopt(ArchiveMap), cl::Grouping);
-
+namespace {
 enum Radix { d, o, x };
-cl::opt<Radix>
-    AddressRadix("radix", cl::desc("Radix (o/d/x) for printing symbol Values"),
-                 cl::values(clEnumVal(d, "decimal"), clEnumVal(o, "octal"),
-                            clEnumVal(x, "hexadecimal")),
-                 cl::init(x), cl::cat(NMCat));
-cl::alias RadixAlias("t", cl::desc("Alias for --radix"),
-                     cl::aliasopt(AddressRadix));
+} // namespace
+static Radix AddressRadix;
 
-cl::opt<bool> JustSymbolName("just-symbol-name",
-                             cl::desc("Print just the symbol's name"),
-                             cl::cat(NMCat));
-cl::alias JustSymbolNames("j", cl::desc("Alias for --just-symbol-name"),
-                          cl::aliasopt(JustSymbolName), cl::Grouping);
+// Mach-O specific options.
+static bool ArchAll = false;
+static std::vector<StringRef> ArchFlags;
+static bool AddDyldInfo;
+static bool AddInlinedInfo;
+static bool DyldInfoOnly;
+static bool FormatMachOasHex;
+static bool NoDyldInfo;
+static std::vector<StringRef> SegSect;
+static bool MachOPrintSizeWarning = false;
 
-cl::opt<bool>
-    SpecialSyms("special-syms",
-                cl::desc("Do not filter special symbols from the output"),
-                cl::cat(NMCat));
+// Miscellaneous states.
+static bool PrintAddress = true;
+static bool MultipleFiles = false;
+static bool HadError = false;
 
-cl::list<std::string> SegSect("s", cl::multi_val(2), cl::ZeroOrMore,
-                              cl::value_desc("segment section"), cl::Hidden,
-                              cl::desc("Dump only symbols from this segment "
-                                       "and section name, Mach-O only"),
-                              cl::cat(NMCat));
-
-cl::opt<bool> FormatMachOasHex("x",
-                               cl::desc("Print symbol entry in hex, "
-                                        "Mach-O only"),
-                               cl::Grouping, cl::cat(NMCat));
-cl::opt<bool> AddDyldInfo("add-dyldinfo",
-                          cl::desc("Add symbols from the dyldinfo not already "
-                                   "in the symbol table, Mach-O only"),
-                          cl::cat(NMCat));
-cl::opt<bool> NoDyldInfo("no-dyldinfo",
-                         cl::desc("Don't add any symbols from the dyldinfo, "
-                                  "Mach-O only"),
-                         cl::cat(NMCat));
-cl::opt<bool> DyldInfoOnly("dyldinfo-only",
-                           cl::desc("Show only symbols from the dyldinfo, "
-                                    "Mach-O only"),
-                           cl::cat(NMCat));
-
-cl::opt<bool> NoLLVMBitcode("no-llvm-bc",
-                            cl::desc("Disable LLVM bitcode reader"),
-                            cl::cat(NMCat));
-
-cl::opt<bool> AddInlinedInfo("add-inlinedinfo",
-                             cl::desc("Add symbols from the inlined libraries, "
-                                      "TBD(Mach-O) only"),
-                             cl::cat(NMCat));
-
-cl::extrahelp HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
-
-bool PrintAddress = true;
-
-bool MultipleFiles = false;
-
-bool HadError = false;
-
-std::string ToolName;
-} // anonymous namespace
+static StringRef ToolName;
 
 static void error(Twine Message, Twine Path = Twine()) {
   HadError = true;
-  WithColor::error(errs(), ToolName) << Path << ": " << Message << ".\n";
+  WithColor::error(errs(), ToolName) << Path << ": " << Message << "\n";
 }
 
 static bool error(std::error_code EC, Twine Path = Twine()) {
@@ -262,13 +159,13 @@
     errs() << "(" << NameOrErr.get() << ")";
 
   if (!ArchitectureName.empty())
-    errs() << " (for architecture " << ArchitectureName << ") ";
+    errs() << " (for architecture " << ArchitectureName << ")";
 
   std::string Buf;
   raw_string_ostream OS(Buf);
   logAllUnhandledErrors(std::move(E), OS);
   OS.flush();
-  errs() << " " << Buf << "\n";
+  errs() << ": " << Buf << "\n";
 }
 
 // This version of error() prints the file name and which architecture slice it
@@ -281,13 +178,13 @@
   WithColor::error(errs(), ToolName) << FileName;
 
   if (!ArchitectureName.empty())
-    errs() << " (for architecture " << ArchitectureName << ") ";
+    errs() << " (for architecture " << ArchitectureName << ")";
 
   std::string Buf;
   raw_string_ostream OS(Buf);
   logAllUnhandledErrors(std::move(E), OS);
   OS.flush();
-  errs() << " " << Buf << "\n";
+  errs() << ": " << Buf << "\n";
 }
 
 namespace {
@@ -737,16 +634,6 @@
   }
 }
 
-static bool isSpecialSym(SymbolicFile &Obj, StringRef Name) {
-  auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj);
-  if (!ELFObj)
-    return false;
-  uint16_t EMachine = ELFObj->getEMachine();
-  if (EMachine != ELF::EM_ARM && EMachine != ELF::EM_AARCH64)
-    return false;
-  return !Name.empty() && Name[0] == '$';
-}
-
 static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName,
                                    StringRef ArchiveName,
                                    StringRef ArchitectureName) {
@@ -769,10 +656,10 @@
   }
 
   if (!PrintFileName) {
-    if (OutputFormat == posix && MultipleFiles && printName) {
+    if ((OutputFormat == bsd || OutputFormat == posix ||
+         OutputFormat == just_symbols) &&
+        MultipleFiles && printName) {
       outs() << '\n' << CurrentFilename << ":\n";
-    } else if (OutputFormat == bsd && MultipleFiles && printName) {
-      outs() << "\n" << CurrentFilename << ":\n";
     } else if (OutputFormat == sysv) {
       outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n";
       if (isSymbolList64Bit(Obj))
@@ -835,13 +722,14 @@
     bool Undefined = SymFlags & SymbolRef::SF_Undefined;
     bool Global = SymFlags & SymbolRef::SF_Global;
     bool Weak = SymFlags & SymbolRef::SF_Weak;
+    bool FormatSpecific = SymFlags & SymbolRef::SF_FormatSpecific;
     if ((!Undefined && UndefinedOnly) || (Undefined && DefinedOnly) ||
         (!Global && ExternalOnly) || (Weak && NoWeakSymbols) ||
-        (!SpecialSyms && isSpecialSym(Obj, Name)))
+        (FormatSpecific && !(SpecialSyms || DebugSyms)))
       continue;
     if (PrintFileName)
       writeFileName(outs(), ArchiveName, ArchitectureName);
-    if ((JustSymbolName ||
+    if ((OutputFormat == just_symbols ||
          (UndefinedOnly && MachO && OutputFormat != darwin)) &&
         OutputFormat != posix) {
       outs() << Name << "\n";
@@ -1142,13 +1030,16 @@
     }
   }
 
-  if ((Symflags & object::SymbolRef::SF_Weak) && !isa<MachOObjectFile>(Obj)) {
-    char Ret = isObject(Obj, I) ? 'v' : 'w';
-    return (!(Symflags & object::SymbolRef::SF_Undefined)) ? toupper(Ret) : Ret;
+  if (Symflags & object::SymbolRef::SF_Undefined) {
+    if (isa<MachOObjectFile>(Obj) || !(Symflags & object::SymbolRef::SF_Weak))
+      return 'U';
+    return isObject(Obj, I) ? 'v' : 'w';
   }
-
-  if (Symflags & object::SymbolRef::SF_Undefined)
-    return 'U';
+  if (isa<ELFObjectFileBase>(&Obj))
+    if (ELFSymbolRef(*I).getELFType() == ELF::STT_GNU_IFUNC)
+      return 'i';
+  if (!isa<MachOObjectFile>(Obj) && (Symflags & object::SymbolRef::SF_Weak))
+    return isObject(Obj, I) ? 'V' : 'W';
 
   if (Symflags & object::SymbolRef::SF_Common)
     return 'C';
@@ -1169,8 +1060,6 @@
   else if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj))
     Ret = getSymbolNMTypeChar(*Tapi, I);
   else if (ELFObjectFileBase *ELF = dyn_cast<ELFObjectFileBase>(&Obj)) {
-    if (ELFSymbolRef(*I).getELFType() == ELF::STT_GNU_IFUNC)
-      return 'i';
     Ret = getSymbolNMTypeChar(*ELF, I);
     if (ELFSymbolRef(*I).getBinding() == ELF::STB_GNU_UNIQUE)
       return Ret;
@@ -1806,7 +1695,14 @@
         error(SymFlagsOrErr.takeError(), Obj.getFileName());
         return;
       }
-      if (!DebugSyms && (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific))
+
+      // Don't drop format specifc symbols for ARM and AArch64 ELF targets, they
+      // are used to repesent mapping symbols and needed to honor the
+      // --special-syms option.
+      auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj);
+      if ((!ELFObj || (ELFObj->getEMachine() != ELF::EM_ARM &&
+                       ELFObj->getEMachine() != ELF::EM_AARCH64)) &&
+          !DebugSyms && (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific))
         continue;
       if (WithoutAliases && (*SymFlagsOrErr & SymbolRef::SF_Indirect))
         continue;
@@ -1860,7 +1756,7 @@
 
   CurrentFilename = Obj.getFileName();
 
-  if (Symbols.empty() && SymbolList.empty()) {
+  if (Symbols.empty() && SymbolList.empty() && !Quiet) {
     writeFileName(errs(), ArchiveName, ArchitectureName);
     errs() << "no symbols\n";
   }
@@ -2228,8 +2124,80 @@
 
 int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
-  cl::HideUnrelatedOptions(NMCat);
-  cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n");
+  BumpPtrAllocator A;
+  StringSaver Saver(A);
+  NmOptTable Tbl;
+  ToolName = argv[0];
+  opt::InputArgList Args =
+      Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
+        error(Msg);
+        exit(1);
+      });
+  if (Args.hasArg(OPT_help)) {
+    Tbl.printHelp(
+        outs(),
+        (Twine(ToolName) + " [options] <input object files>").str().c_str(),
+        "LLVM symbol table dumper");
+    // TODO Replace this with OptTable API once it adds extrahelp support.
+    outs() << "\nPass @FILE as argument to read options from FILE.\n";
+    return 0;
+  }
+  if (Args.hasArg(OPT_version)) {
+    // This needs to contain the word "GNU", libtool looks for that string.
+    outs() << "llvm-nm, compatible with GNU nm" << '\n';
+    cl::PrintVersionMessage();
+    return 0;
+  }
+
+  DebugSyms = Args.hasArg(OPT_debug_syms);
+  DefinedOnly = Args.hasArg(OPT_defined_only);
+  Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false);
+  DynamicSyms = Args.hasArg(OPT_dynamic);
+  ExternalOnly = Args.hasArg(OPT_extern_only);
+  StringRef V = Args.getLastArgValue(OPT_format_EQ, "bsd");
+  if (V == "bsd")
+    OutputFormat = bsd;
+  else if (V == "posix")
+    OutputFormat = posix;
+  else if (V == "sysv")
+    OutputFormat = sysv;
+  else if (V == "darwin")
+    OutputFormat = darwin;
+  else if (V == "just-symbols")
+    OutputFormat = just_symbols;
+  else
+    error("--format value should be one of: bsd, posix, sysv, darwin, "
+          "just-symbols");
+  NoLLVMBitcode = Args.hasArg(OPT_no_llvm_bc);
+  NoSort = Args.hasArg(OPT_no_sort);
+  NoWeakSymbols = Args.hasArg(OPT_no_weak);
+  NumericSort = Args.hasArg(OPT_numeric_sort);
+  ArchiveMap = Args.hasArg(OPT_print_armap);
+  PrintFileName = Args.hasArg(OPT_print_file_name);
+  PrintSize = Args.hasArg(OPT_print_size);
+  ReverseSort = Args.hasArg(OPT_reverse_sort);
+  Quiet = Args.hasArg(OPT_quiet);
+  V = Args.getLastArgValue(OPT_radix_EQ, "x");
+  if (V == "o")
+    AddressRadix = Radix::o;
+  else if (V == "d")
+    AddressRadix = Radix::d;
+  else if (V == "x")
+    AddressRadix = Radix::x;
+  else
+    error("--radix value should be one of: 'o' (octal), 'd' (decimal), 'x' "
+          "(hexadecimal)");
+  SizeSort = Args.hasArg(OPT_size_sort);
+  SpecialSyms = Args.hasArg(OPT_special_syms);
+  UndefinedOnly = Args.hasArg(OPT_undefined_only);
+  WithoutAliases = Args.hasArg(OPT_without_aliases);
+
+  // Mach-O specific options.
+  FormatMachOasHex = Args.hasArg(OPT_x);
+  AddDyldInfo = Args.hasArg(OPT_add_dyldinfo);
+  AddInlinedInfo = Args.hasArg(OPT_add_inlinedinfo);
+  DyldInfoOnly = Args.hasArg(OPT_dyldinfo_only);
+  NoDyldInfo = Args.hasArg(OPT_no_dyldinfo);
 
   // llvm-nm only reads binary files.
   if (error(sys::ChangeStdinToBinary()))
@@ -2240,14 +2208,6 @@
   llvm::InitializeAllTargetMCs();
   llvm::InitializeAllAsmParsers();
 
-  ToolName = argv[0];
-  if (BSDFormat)
-    OutputFormat = bsd;
-  if (POSIXFormat)
-    OutputFormat = posix;
-  if (DarwinFormat)
-    OutputFormat = darwin;
-
   // The relative order of these is important. If you pass --size-sort it should
   // only print out the size. However, if you pass -S --size-sort, it should
   // print out both the size and address.
@@ -2255,29 +2215,44 @@
     PrintAddress = false;
   if (OutputFormat == sysv || SizeSort)
     PrintSize = true;
-  if (InputFilenames.empty())
-    InputFilenames.push_back("a.out");
-  if (InputFilenames.size() > 1)
-    MultipleFiles = true;
 
-  // If both --demangle and --no-demangle are specified then pick the last one.
-  if (NoDemangle.getPosition() > Demangle.getPosition())
-    Demangle = !NoDemangle;
-
-  for (unsigned i = 0; i < ArchFlags.size(); ++i) {
-    if (ArchFlags[i] == "all") {
-      ArchAll = true;
-    } else {
-      if (!MachOObjectFile::isValidArch(ArchFlags[i]))
-        error("Unknown architecture named '" + ArchFlags[i] + "'",
+  for (const auto *A : Args.filtered(OPT_arch_EQ)) {
+    SmallVector<StringRef, 2> Values;
+    llvm::SplitString(A->getValue(), Values, ",");
+    for (StringRef V : Values) {
+      if (V == "all")
+        ArchAll = true;
+      else if (MachOObjectFile::isValidArch(V))
+        ArchFlags.push_back(V);
+      else
+        error("Unknown architecture named '" + V + "'",
               "for the --arch option");
     }
   }
 
+  // Mach-O takes -s to accept two arguments. We emulate this by iterating over
+  // both OPT_s and OPT_INPUT.
+  std::vector<std::string> InputFilenames;
+  int SegSectArgs = 0;
+  for (opt::Arg *A : Args.filtered(OPT_s, OPT_INPUT)) {
+    if (SegSectArgs > 0) {
+      --SegSectArgs;
+      SegSect.push_back(A->getValue());
+    } else if (A->getOption().matches(OPT_s)) {
+      SegSectArgs = 2;
+    } else {
+      InputFilenames.push_back(A->getValue());
+    }
+  }
   if (!SegSect.empty() && SegSect.size() != 2)
     error("bad number of arguments (must be two arguments)",
           "for the -s option");
 
+  if (InputFilenames.empty())
+    InputFilenames.push_back("a.out");
+  if (InputFilenames.size() > 1)
+    MultipleFiles = true;
+
   if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly))
     error("--no-dyldinfo can't be used with --add-dyldinfo or --dyldinfo-only");
 
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/Buffer.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/Buffer.cpp
deleted file mode 100644
index 06b2a20..0000000
--- a/src/llvm-project/llvm/tools/llvm-objcopy/Buffer.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-//===- Buffer.cpp ---------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#include "Buffer.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Process.h"
-#include <memory>
-
-namespace llvm {
-namespace objcopy {
-
-Buffer::~Buffer() {}
-
-static Error createEmptyFile(StringRef FileName) {
-  // Create an empty tempfile and atomically swap it in place with the desired
-  // output file.
-  Expected<sys::fs::TempFile> Temp =
-      sys::fs::TempFile::create(FileName + ".temp-empty-%%%%%%%");
-  return Temp ? Temp->keep(FileName) : Temp.takeError();
-}
-
-Error FileBuffer::allocate(size_t Size) {
-  // When a 0-sized file is requested, skip allocation but defer file
-  // creation/truncation until commit() to avoid side effects if something
-  // happens between allocate() and commit().
-  if (Size == 0) {
-    EmptyFile = true;
-    return Error::success();
-  }
-
-  Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
-      FileOutputBuffer::create(getName(), Size, FileOutputBuffer::F_executable);
-  // FileOutputBuffer::create() returns an Error that is just a wrapper around
-  // std::error_code. Wrap it in FileError to include the actual filename.
-  if (!BufferOrErr)
-    return createFileError(getName(), BufferOrErr.takeError());
-  Buf = std::move(*BufferOrErr);
-  return Error::success();
-}
-
-Error FileBuffer::commit() {
-  if (EmptyFile)
-    return createEmptyFile(getName());
-
-  assert(Buf && "allocate() not called before commit()!");
-  Error Err = Buf->commit();
-  // FileOutputBuffer::commit() returns an Error that is just a wrapper around
-  // std::error_code. Wrap it in FileError to include the actual filename.
-  return Err ? createFileError(getName(), std::move(Err)) : std::move(Err);
-}
-
-uint8_t *FileBuffer::getBufferStart() {
-  return reinterpret_cast<uint8_t *>(Buf->getBufferStart());
-}
-
-Error MemBuffer::allocate(size_t Size) {
-  Buf = WritableMemoryBuffer::getNewMemBuffer(Size, getName());
-  return Error::success();
-}
-
-Error MemBuffer::commit() { return Error::success(); }
-
-uint8_t *MemBuffer::getBufferStart() {
-  return reinterpret_cast<uint8_t *>(Buf->getBufferStart());
-}
-
-std::unique_ptr<WritableMemoryBuffer> MemBuffer::releaseMemoryBuffer() {
-  return std::move(Buf);
-}
-
-} // end namespace objcopy
-} // end namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/Buffer.h b/src/llvm-project/llvm/tools/llvm-objcopy/Buffer.h
deleted file mode 100644
index 487d558..0000000
--- a/src/llvm-project/llvm/tools/llvm-objcopy/Buffer.h
+++ /dev/null
@@ -1,68 +0,0 @@
-//===- Buffer.h -------------------------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_OBJCOPY_BUFFER_H
-#define LLVM_TOOLS_OBJCOPY_BUFFER_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include <memory>
-
-namespace llvm {
-namespace objcopy {
-
-// The class Buffer abstracts out the common interface of FileOutputBuffer and
-// WritableMemoryBuffer so that the hierarchy of Writers depends on this
-// abstract interface and doesn't depend on a particular implementation.
-// TODO: refactor the buffer classes in LLVM to enable us to use them here
-// directly.
-class Buffer {
-  StringRef Name;
-
-public:
-  virtual ~Buffer();
-  virtual Error allocate(size_t Size) = 0;
-  virtual uint8_t *getBufferStart() = 0;
-  virtual Error commit() = 0;
-
-  explicit Buffer(StringRef Name) : Name(Name) {}
-  StringRef getName() const { return Name; }
-};
-
-class FileBuffer : public Buffer {
-  std::unique_ptr<FileOutputBuffer> Buf;
-  // Indicates that allocate(0) was called, and commit() should create or
-  // truncate a file instead of using a FileOutputBuffer.
-  bool EmptyFile = false;
-
-public:
-  Error allocate(size_t Size) override;
-  uint8_t *getBufferStart() override;
-  Error commit() override;
-
-  explicit FileBuffer(StringRef FileName) : Buffer(FileName) {}
-};
-
-class MemBuffer : public Buffer {
-  std::unique_ptr<WritableMemoryBuffer> Buf;
-
-public:
-  Error allocate(size_t Size) override;
-  uint8_t *getBufferStart() override;
-  Error commit() override;
-
-  explicit MemBuffer(StringRef Name) : Buffer(Name) {}
-
-  std::unique_ptr<WritableMemoryBuffer> releaseMemoryBuffer();
-};
-
-} // end namespace objcopy
-} // end namespace llvm
-
-#endif // LLVM_TOOLS_OBJCOPY_BUFFER_H
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-objcopy/CMakeLists.txt
index 1f733c3..d14d213 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/CMakeLists.txt
@@ -22,14 +22,12 @@
 add_public_tablegen_target(StripOptsTableGen)
 
 add_llvm_tool(llvm-objcopy
-  Buffer.cpp
-  CopyConfig.cpp
+  ConfigManager.cpp
   llvm-objcopy.cpp
   COFF/COFFObjcopy.cpp
   COFF/Object.cpp
   COFF/Reader.cpp
   COFF/Writer.cpp
-  ELF/ELFConfig.cpp
   ELF/ELFObjcopy.cpp
   ELF/Object.cpp
   MachO/MachOObjcopy.cpp
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/COFF/COFFConfig.h b/src/llvm-project/llvm/tools/llvm-objcopy/COFF/COFFConfig.h
new file mode 100644
index 0000000..3897ff4
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/COFF/COFFConfig.h
@@ -0,0 +1,21 @@
+//===- COFFConfig.h ---------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_OBJCOPY_COFF_COFFCONFIG_H
+#define LLVM_TOOLS_LLVM_OBJCOPY_COFF_COFFCONFIG_H
+
+namespace llvm {
+namespace objcopy {
+
+// Coff specific configuration for copying/stripping a single file.
+struct COFFConfig {};
+
+} // namespace objcopy
+} // namespace llvm
+
+#endif // LLVM_TOOLS_LLVM_OBJCOPY_COFF_COFFCONFIG_H
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
index b5de8a4..e50ac2e 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
@@ -7,8 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "COFFObjcopy.h"
-#include "Buffer.h"
-#include "CopyConfig.h"
+#include "COFFConfig.h"
+#include "CommonConfig.h"
 #include "Object.h"
 #include "Reader.h"
 #include "Writer.h"
@@ -131,7 +131,7 @@
   Sec.Header.Characteristics = NewCharacteristics;
 }
 
-static Error handleArgs(const CopyConfig &Config, Object &Obj) {
+static Error handleArgs(const CommonConfig &Config, Object &Obj) {
   // Perform the actual section removals.
   Obj.removeSections([&Config](const Section &Sec) {
     // Contrary to --only-keep-debug, --only-section fully removes sections that
@@ -249,30 +249,11 @@
     if (Error E = addGnuDebugLink(Obj, Config.AddGnuDebugLink))
       return E;
 
-  if (Config.AllowBrokenLinks || !Config.BuildIdLinkDir.empty() ||
-      Config.BuildIdLinkInput || Config.BuildIdLinkOutput ||
-      !Config.SplitDWO.empty() || !Config.SymbolsPrefix.empty() ||
-      !Config.AllocSectionsPrefix.empty() || !Config.DumpSection.empty() ||
-      !Config.KeepSection.empty() || Config.NewSymbolVisibility ||
-      !Config.SymbolsToGlobalize.empty() || !Config.SymbolsToKeep.empty() ||
-      !Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() ||
-      !Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() ||
-      !Config.SetSectionAlignment.empty() || Config.ExtractDWO ||
-      Config.LocalizeHidden || Config.PreserveDates || Config.StripDWO ||
-      Config.StripNonAlloc || Config.StripSections ||
-      Config.StripSwiftSymbols || Config.Weaken ||
-      Config.DecompressDebugSections ||
-      Config.DiscardMode == DiscardType::Locals ||
-      !Config.SymbolsToAdd.empty() || Config.EntryExpr) {
-    return createStringError(llvm::errc::invalid_argument,
-                             "option not supported by llvm-objcopy for COFF");
-  }
-
   return Error::success();
 }
 
-Error executeObjcopyOnBinary(const CopyConfig &Config, COFFObjectFile &In,
-                             Buffer &Out) {
+Error executeObjcopyOnBinary(const CommonConfig &Config, const COFFConfig &,
+                             COFFObjectFile &In, raw_ostream &Out) {
   COFFReader Reader(In);
   Expected<std::unique_ptr<Object>> ObjOrErr = Reader.create();
   if (!ObjOrErr)
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.h b/src/llvm-project/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.h
index 858759e..2c7ccd3 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.h
@@ -11,18 +11,20 @@
 
 namespace llvm {
 class Error;
+class raw_ostream;
 
 namespace object {
 class COFFObjectFile;
 } // end namespace object
 
 namespace objcopy {
-struct CopyConfig;
-class Buffer;
+struct CommonConfig;
+struct COFFConfig;
 
 namespace coff {
-Error executeObjcopyOnBinary(const CopyConfig &Config,
-                             object::COFFObjectFile &In, Buffer &Out);
+
+Error executeObjcopyOnBinary(const CommonConfig &Config, const COFFConfig &,
+                             object::COFFObjectFile &In, raw_ostream &Out);
 
 } // end namespace coff
 } // end namespace objcopy
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/COFF/Reader.h b/src/llvm-project/llvm/tools/llvm-objcopy/COFF/Reader.h
index ec15369..48c050b 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/COFF/Reader.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/COFF/Reader.h
@@ -9,7 +9,6 @@
 #ifndef LLVM_TOOLS_OBJCOPY_COFF_READER_H
 #define LLVM_TOOLS_OBJCOPY_COFF_READER_H
 
-#include "Buffer.h"
 #include "llvm/BinaryFormat/COFF.h"
 #include "llvm/Object/COFF.h"
 #include "llvm/Support/Error.h"
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/COFF/Writer.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/COFF/Writer.cpp
index 6b56089..e7be64f 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/COFF/Writer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/COFF/Writer.cpp
@@ -12,6 +12,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/COFF.h"
 #include "llvm/Object/COFF.h"
+#include "llvm/Support/Errc.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <cstddef>
 #include <cstdint>
@@ -240,7 +241,7 @@
 }
 
 void COFFWriter::writeHeaders(bool IsBigObj) {
-  uint8_t *Ptr = Buf.getBufferStart();
+  uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart());
   if (Obj.IsPE) {
     memcpy(Ptr, &Obj.DosHeader, sizeof(Obj.DosHeader));
     Ptr += sizeof(Obj.DosHeader);
@@ -302,7 +303,8 @@
 
 void COFFWriter::writeSections() {
   for (const auto &S : Obj.getSections()) {
-    uint8_t *Ptr = Buf.getBufferStart() + S.Header.PointerToRawData;
+    uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) +
+                   S.Header.PointerToRawData;
     ArrayRef<uint8_t> Contents = S.getContents();
     std::copy(Contents.begin(), Contents.end(), Ptr);
 
@@ -331,7 +333,8 @@
 }
 
 template <class SymbolTy> void COFFWriter::writeSymbolStringTables() {
-  uint8_t *Ptr = Buf.getBufferStart() + Obj.CoffFileHeader.PointerToSymbolTable;
+  uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) +
+                 Obj.CoffFileHeader.PointerToSymbolTable;
   for (const auto &S : Obj.getSymbols()) {
     // Convert symbols back to the right size, from coff_symbol32.
     copySymbol<SymbolTy, coff_symbol32>(*reinterpret_cast<SymbolTy *>(Ptr),
@@ -366,8 +369,11 @@
   if (Error E = finalize(IsBigObj))
     return E;
 
-  if (Error E = Buf.allocate(FileSize))
-    return E;
+  Buf = WritableMemoryBuffer::getNewMemBuffer(FileSize);
+  if (!Buf)
+    return createStringError(llvm::errc::not_enough_memory,
+                             "failed to allocate memory buffer of " +
+                                 Twine::utohexstr(FileSize) + " bytes.");
 
   writeHeaders(IsBigObj);
   writeSections();
@@ -380,7 +386,10 @@
     if (Error E = patchDebugDirectory())
       return E;
 
-  return Buf.commit();
+  // TODO: Implement direct writing to the output stream (without intermediate
+  // memory buffer Buf).
+  Out.write(Buf->getBufferStart(), Buf->getBufferSize());
+  return Error::success();
 }
 
 Expected<uint32_t> COFFWriter::virtualAddressToFileAddress(uint32_t RVA) {
@@ -412,7 +421,8 @@
                                  "debug directory extends past end of section");
 
       size_t Offset = Dir->RelativeVirtualAddress - S.Header.VirtualAddress;
-      uint8_t *Ptr = Buf.getBufferStart() + S.Header.PointerToRawData + Offset;
+      uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) +
+                     S.Header.PointerToRawData + Offset;
       uint8_t *End = Ptr + Dir->Size;
       while (Ptr < End) {
         debug_directory *Debug = reinterpret_cast<debug_directory *>(Ptr);
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/COFF/Writer.h b/src/llvm-project/llvm/tools/llvm-objcopy/COFF/Writer.h
index 3c0bdcb..eed43b3 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/COFF/Writer.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/COFF/Writer.h
@@ -9,9 +9,9 @@
 #ifndef LLVM_TOOLS_OBJCOPY_COFF_WRITER_H
 #define LLVM_TOOLS_OBJCOPY_COFF_WRITER_H
 
-#include "Buffer.h"
 #include "llvm/MC/StringTableBuilder.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include <cstddef>
 #include <utility>
 
@@ -23,7 +23,8 @@
 
 class COFFWriter {
   Object &Obj;
-  Buffer &Buf;
+  std::unique_ptr<WritableMemoryBuffer> Buf;
+  raw_ostream &Out;
 
   size_t FileSize;
   size_t FileAlignment;
@@ -51,8 +52,8 @@
   virtual ~COFFWriter() {}
   Error write();
 
-  COFFWriter(Object &Obj, Buffer &Buf)
-      : Obj(Obj), Buf(Buf), StrTabBuilder(StringTableBuilder::WinCOFF) {}
+  COFFWriter(Object &Obj, raw_ostream &Out)
+      : Obj(Obj), Out(Out), StrTabBuilder(StringTableBuilder::WinCOFF) {}
 };
 
 } // end namespace coff
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/CopyConfig.h b/src/llvm-project/llvm/tools/llvm-objcopy/CommonConfig.h
similarity index 68%
rename from src/llvm-project/llvm/tools/llvm-objcopy/CopyConfig.h
rename to src/llvm-project/llvm/tools/llvm-objcopy/CommonConfig.h
index 07eac9d..131ce5c 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/CopyConfig.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/CommonConfig.h
@@ -1,4 +1,4 @@
-//===- CopyConfig.h -------------------------------------------------------===//
+//===- CommonConfig.h -------------------------------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,20 +6,17 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_LLVM_OBJCOPY_COPY_CONFIG_H
-#define LLVM_TOOLS_LLVM_OBJCOPY_COPY_CONFIG_H
+#ifndef LLVM_TOOLS_LLVM_OBJCOPY_COMMONCONFIG_H
+#define LLVM_TOOLS_LLVM_OBJCOPY_COMMONCONFIG_H
 
-#include "ELF/ELFConfig.h"
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/BitmaskEnum.h"
+#include "llvm/ADT/CachedHashString.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Object/ELFTypes.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Error.h"
 #include "llvm/Support/GlobPattern.h"
 #include "llvm/Support/Regex.h"
 // Necessary for llvm::DebugCompressionType::None
@@ -99,7 +96,7 @@
 
 class NameOrPattern {
   StringRef Name;
-  // Regex is shared between multiple CopyConfig instances.
+  // Regex is shared between multiple CommonConfig instances.
   std::shared_ptr<Regex> R;
   std::shared_ptr<GlobPattern> G;
   bool IsPositiveMatch = true;
@@ -117,6 +114,11 @@
          llvm::function_ref<Error(Error)> ErrorCallback);
 
   bool isPositiveMatch() const { return IsPositiveMatch; }
+  Optional<StringRef> getName() const {
+    if (!R && !G)
+      return Name;
+    return None;
+  }
   bool operator==(StringRef S) const {
     return R ? R->match(S) : G ? G->match(S) : Name == S;
   }
@@ -126,30 +128,66 @@
 // Matcher that checks symbol or section names against the command line flags
 // provided for that option.
 class NameMatcher {
-  std::vector<NameOrPattern> PosMatchers;
+  DenseSet<CachedHashStringRef> PosNames;
+  std::vector<NameOrPattern> PosPatterns;
   std::vector<NameOrPattern> NegMatchers;
 
 public:
   Error addMatcher(Expected<NameOrPattern> Matcher) {
     if (!Matcher)
       return Matcher.takeError();
-    if (Matcher->isPositiveMatch())
-      PosMatchers.push_back(std::move(*Matcher));
-    else
+    if (Matcher->isPositiveMatch()) {
+      if (Optional<StringRef> MaybeName = Matcher->getName())
+        PosNames.insert(CachedHashStringRef(*MaybeName));
+      else
+        PosPatterns.push_back(std::move(*Matcher));
+    } else {
       NegMatchers.push_back(std::move(*Matcher));
+    }
     return Error::success();
   }
   bool matches(StringRef S) const {
-    return is_contained(PosMatchers, S) && !is_contained(NegMatchers, S);
+    return (PosNames.contains(CachedHashStringRef(S)) ||
+            is_contained(PosPatterns, S)) &&
+           !is_contained(NegMatchers, S);
   }
-  bool empty() const { return PosMatchers.empty() && NegMatchers.empty(); }
+  bool empty() const {
+    return PosNames.empty() && PosPatterns.empty() && NegMatchers.empty();
+  }
+};
+
+enum class SymbolFlag {
+  Global,
+  Local,
+  Weak,
+  Default,
+  Hidden,
+  Protected,
+  File,
+  Section,
+  Object,
+  Function,
+  IndirectFunction,
+  Debug,
+  Constructor,
+  Warning,
+  Indirect,
+  Synthetic,
+  UniqueObject,
+};
+
+// Symbol info specified by --add-symbol option. Symbol flags not supported
+// by a concrete format should be ignored.
+struct NewSymbolInfo {
+  StringRef SymbolName;
+  StringRef SectionName;
+  uint64_t Value = 0;
+  std::vector<SymbolFlag> Flags;
+  std::vector<StringRef> BeforeSyms;
 };
 
 // Configuration for copying/stripping a single file.
-struct CopyConfig {
-  // Format-specific options to be initialized lazily when needed.
-  Optional<elf::ELFCopyConfig> ELF;
-
+struct CommonConfig {
   // Main input/output options
   StringRef InputFilename;
   FileFormat InputFormat = FileFormat::Unspecified;
@@ -163,20 +201,15 @@
   StringRef AddGnuDebugLink;
   // Cached gnu_debuglink's target CRC
   uint32_t GnuDebugLinkCRC32;
-  StringRef BuildIdLinkDir;
-  Optional<StringRef> BuildIdLinkInput;
-  Optional<StringRef> BuildIdLinkOutput;
   Optional<StringRef> ExtractPartition;
   StringRef SplitDWO;
   StringRef SymbolsPrefix;
   StringRef AllocSectionsPrefix;
   DiscardType DiscardMode = DiscardType::None;
-  Optional<StringRef> NewSymbolVisibility;
 
   // Repeated options
   std::vector<StringRef> AddSection;
   std::vector<StringRef> DumpSection;
-  std::vector<StringRef> SymbolsToAdd;
   std::vector<StringRef> RPathToAdd;
   std::vector<StringRef> RPathToPrepend;
   DenseMap<StringRef, StringRef> RPathsToUpdate;
@@ -212,12 +245,16 @@
   // --change-start is used.
   std::function<uint64_t(uint64_t)> EntryExpr;
 
+  // Symbol info specified by --add-symbol option.
+  std::vector<NewSymbolInfo> SymbolsToAdd;
+
   // Boolean options
   bool AllowBrokenLinks = false;
   bool DeterministicArchives = true;
   bool ExtractDWO = false;
   bool ExtractMainPartition = false;
   bool KeepFileSymbols = false;
+  bool KeepUndefined = false;
   bool LocalizeHidden = false;
   bool OnlyKeepDebug = false;
   bool PreserveDates = false;
@@ -235,55 +272,9 @@
   bool RemoveAllRpaths = false;
 
   DebugCompressionType CompressionType = DebugCompressionType::None;
-
-  // parseELFConfig performs ELF-specific command-line parsing. Fills `ELF` on
-  // success or returns an Error otherwise.
-  Error parseELFConfig() {
-    if (!ELF) {
-      Expected<elf::ELFCopyConfig> ELFConfig = elf::parseConfig(*this);
-      if (!ELFConfig)
-        return ELFConfig.takeError();
-      ELF = *ELFConfig;
-    }
-    return Error::success();
-  }
 };
 
-// Configuration for the overall invocation of this tool. When invoked as
-// objcopy, will always contain exactly one CopyConfig. When invoked as strip,
-// will contain one or more CopyConfigs.
-struct DriverConfig {
-  SmallVector<CopyConfig, 1> CopyConfigs;
-  BumpPtrAllocator Alloc;
-};
-
-// ParseObjcopyOptions returns the config and sets the input arguments. If a
-// help flag is set then ParseObjcopyOptions will print the help messege and
-// exit. ErrorCallback is used to handle recoverable errors. An Error returned
-// by the callback aborts the parsing and is then returned by this function.
-Expected<DriverConfig>
-parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
-                    llvm::function_ref<Error(Error)> ErrorCallback);
-
-// ParseInstallNameToolOptions returns the config and sets the input arguments.
-// If a help flag is set then ParseInstallNameToolOptions will print the help
-// messege and exit.
-Expected<DriverConfig>
-parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr);
-
-// ParseBitcodeStripOptions returns the config and sets the input arguments.
-// If a help flag is set then ParseBitcodeStripOptions will print the help
-// messege and exit.
-Expected<DriverConfig> parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr);
-
-// ParseStripOptions returns the config and sets the input arguments. If a
-// help flag is set then ParseStripOptions will print the help messege and
-// exit. ErrorCallback is used to handle recoverable errors. An Error returned
-// by the callback aborts the parsing and is then returned by this function.
-Expected<DriverConfig>
-parseStripOptions(ArrayRef<const char *> ArgsArr,
-                  llvm::function_ref<Error(Error)> ErrorCallback);
 } // namespace objcopy
 } // namespace llvm
 
-#endif
+#endif // LLVM_TOOLS_LLVM_OBJCOPY_COMMONCONFIG_H
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/CommonOpts.td b/src/llvm-project/llvm/tools/llvm-objcopy/CommonOpts.td
index 6481d1d..4222532 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/CommonOpts.td
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/CommonOpts.td
@@ -84,6 +84,9 @@
 def keep_file_symbols : Flag<["--"], "keep-file-symbols">,
                         HelpText<"Do not remove file symbols">;
 
+def keep_undefined : Flag<["--"], "keep-undefined">,
+                        HelpText<"Do not remove undefined symbols">;
+
 def only_keep_debug
     : Flag<["--"], "only-keep-debug">,
       HelpText<
@@ -99,7 +102,8 @@
 
 def discard_all
     : Flag<["--"], "discard-all">,
-      HelpText<"Remove all local symbols except file and section symbols">;
+      HelpText<"Remove all local symbols except file and section symbols. Also "
+               "remove all debug sections">;
 def x : Flag<["-"], "x">,
         Alias<discard_all>,
         HelpText<"Alias for --discard-all">;
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/CopyConfig.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/ConfigManager.cpp
similarity index 79%
rename from src/llvm-project/llvm/tools/llvm-objcopy/CopyConfig.cpp
rename to src/llvm-project/llvm/tools/llvm-objcopy/ConfigManager.cpp
index ba74759..9f7d06b 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/CopyConfig.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/ConfigManager.cpp
@@ -1,4 +1,4 @@
-//===- CopyConfig.cpp -----------------------------------------------------===//
+//===- ConfigManager.cpp --------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,8 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "CopyConfig.h"
-
+#include "ConfigManager.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
@@ -18,12 +17,13 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compression.h"
 #include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/StringSaver.h"
 #include <memory>
 
-namespace llvm {
-namespace objcopy {
+using namespace llvm;
+using namespace llvm::objcopy;
 
 namespace {
 enum ObjcopyID {
@@ -60,7 +60,9 @@
 
 class ObjcopyOptTable : public opt::OptTable {
 public:
-  ObjcopyOptTable() : OptTable(ObjcopyInfoTable) {}
+  ObjcopyOptTable() : OptTable(ObjcopyInfoTable) {
+    setGroupedShortOptions(true);
+  }
 };
 
 enum InstallNameToolID {
@@ -164,7 +166,7 @@
 
 class StripOptTable : public opt::OptTable {
 public:
-  StripOptTable() : OptTable(StripInfoTable) {}
+  StripOptTable() : OptTable(StripInfoTable) { setGroupedShortOptions(true); }
 };
 
 } // namespace
@@ -244,9 +246,10 @@
         "bad format for --set-section-alignment: missing section name");
   uint64_t NewAlign;
   if (Split.second.getAsInteger(0, NewAlign))
-    return createStringError(errc::invalid_argument,
-                             "invalid alignment for --set-section-alignment: '%s'",
-                             Split.second.str().c_str());
+    return createStringError(
+        errc::invalid_argument,
+        "invalid alignment for --set-section-alignment: '%s'",
+        Split.second.str().c_str());
   return std::make_pair(Split.first, NewAlign);
 }
 
@@ -272,10 +275,12 @@
   return SFU;
 }
 
+namespace {
 struct TargetInfo {
   FileFormat Format;
   MachineInfo Machine;
 };
+} // namespace
 
 // FIXME: consolidate with the bfd parsing used by lld.
 static const StringMap<MachineInfo> TargetMap{
@@ -337,10 +342,9 @@
   return {TargetInfo{Format, MI}};
 }
 
-static Error
-addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc,
-                   StringRef Filename, MatchStyle MS,
-                   llvm::function_ref<Error(Error)> ErrorCallback) {
+static Error addSymbolsFromFile(NameMatcher &Symbols, BumpPtrAllocator &Alloc,
+                                StringRef Filename, MatchStyle MS,
+                                function_ref<Error(Error)> ErrorCallback) {
   StringSaver Saver(Alloc);
   SmallVector<StringRef, 16> Lines;
   auto BufOrErr = MemoryBuffer::getFile(Filename);
@@ -363,7 +367,7 @@
 
 Expected<NameOrPattern>
 NameOrPattern::create(StringRef Pattern, MatchStyle MS,
-                      llvm::function_ref<Error(Error)> ErrorCallback) {
+                      function_ref<Error(Error)> ErrorCallback) {
   switch (MS) {
   case MatchStyle::Literal:
     return NameOrPattern(Pattern);
@@ -457,7 +461,7 @@
     HelpText = " [options] input";
     break;
   }
-  OptTable.PrintHelp(OS, (ToolName + HelpText).str().c_str(),
+  OptTable.printHelp(OS, (ToolName + HelpText).str().c_str(),
                      (ToolName + " tool").str().c_str());
   // TODO: Replace this with libOption call once it adds extrahelp support.
   // The CommandLine library has a cl::extrahelp class to support this,
@@ -465,19 +469,186 @@
   OS << "\nPass @FILE as argument to read options from FILE.\n";
 }
 
+static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue) {
+  // Parse value given with --add-symbol option and create the
+  // new symbol if possible. The value format for --add-symbol is:
+  //
+  // <name>=[<section>:]<value>[,<flags>]
+  //
+  // where:
+  // <name> - symbol name, can be empty string
+  // <section> - optional section name. If not given ABS symbol is created
+  // <value> - symbol value, can be decimal or hexadecimal number prefixed
+  //           with 0x.
+  // <flags> - optional flags affecting symbol type, binding or visibility.
+  NewSymbolInfo SI;
+  StringRef Value;
+  std::tie(SI.SymbolName, Value) = FlagValue.split('=');
+  if (Value.empty())
+    return createStringError(
+        errc::invalid_argument,
+        "bad format for --add-symbol, missing '=' after '%s'",
+        SI.SymbolName.str().c_str());
+
+  if (Value.contains(':')) {
+    std::tie(SI.SectionName, Value) = Value.split(':');
+    if (SI.SectionName.empty() || Value.empty())
+      return createStringError(
+          errc::invalid_argument,
+          "bad format for --add-symbol, missing section name or symbol value");
+  }
+
+  SmallVector<StringRef, 6> Flags;
+  Value.split(Flags, ',');
+  if (Flags[0].getAsInteger(0, SI.Value))
+    return createStringError(errc::invalid_argument, "bad symbol value: '%s'",
+                             Flags[0].str().c_str());
+
+  using Functor = std::function<void()>;
+  SmallVector<StringRef, 6> UnsupportedFlags;
+  for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I)
+    static_cast<Functor>(
+        StringSwitch<Functor>(Flags[I])
+            .CaseLower("global",
+                       [&] { SI.Flags.push_back(SymbolFlag::Global); })
+            .CaseLower("local", [&] { SI.Flags.push_back(SymbolFlag::Local); })
+            .CaseLower("weak", [&] { SI.Flags.push_back(SymbolFlag::Weak); })
+            .CaseLower("default",
+                       [&] { SI.Flags.push_back(SymbolFlag::Default); })
+            .CaseLower("hidden",
+                       [&] { SI.Flags.push_back(SymbolFlag::Hidden); })
+            .CaseLower("protected",
+                       [&] { SI.Flags.push_back(SymbolFlag::Protected); })
+            .CaseLower("file", [&] { SI.Flags.push_back(SymbolFlag::File); })
+            .CaseLower("section",
+                       [&] { SI.Flags.push_back(SymbolFlag::Section); })
+            .CaseLower("object",
+                       [&] { SI.Flags.push_back(SymbolFlag::Object); })
+            .CaseLower("function",
+                       [&] { SI.Flags.push_back(SymbolFlag::Function); })
+            .CaseLower(
+                "indirect-function",
+                [&] { SI.Flags.push_back(SymbolFlag::IndirectFunction); })
+            .CaseLower("debug", [&] { SI.Flags.push_back(SymbolFlag::Debug); })
+            .CaseLower("constructor",
+                       [&] { SI.Flags.push_back(SymbolFlag::Constructor); })
+            .CaseLower("warning",
+                       [&] { SI.Flags.push_back(SymbolFlag::Warning); })
+            .CaseLower("indirect",
+                       [&] { SI.Flags.push_back(SymbolFlag::Indirect); })
+            .CaseLower("synthetic",
+                       [&] { SI.Flags.push_back(SymbolFlag::Synthetic); })
+            .CaseLower("unique-object",
+                       [&] { SI.Flags.push_back(SymbolFlag::UniqueObject); })
+            .StartsWithLower("before=",
+                             [&] {
+                               StringRef SymNamePart =
+                                   Flags[I].split('=').second;
+
+                               if (!SymNamePart.empty())
+                                 SI.BeforeSyms.push_back(SymNamePart);
+                             })
+            .Default([&] { UnsupportedFlags.push_back(Flags[I]); }))();
+  if (!UnsupportedFlags.empty())
+    return createStringError(errc::invalid_argument,
+                             "unsupported flag%s for --add-symbol: '%s'",
+                             UnsupportedFlags.size() > 1 ? "s" : "",
+                             join(UnsupportedFlags, "', '").c_str());
+
+  return SI;
+}
+
+Expected<const ELFConfig &> ConfigManager::getELFConfig() const {
+  if (Common.StripSwiftSymbols || Common.KeepUndefined)
+    return createStringError(llvm::errc::invalid_argument,
+                             "option not supported by llvm-objcopy for ELF");
+
+  return ELF;
+}
+
+Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const {
+  if (Common.AllowBrokenLinks || !Common.SplitDWO.empty() ||
+      !Common.SymbolsPrefix.empty() || !Common.AllocSectionsPrefix.empty() ||
+      !Common.DumpSection.empty() || !Common.KeepSection.empty() ||
+      ELF.NewSymbolVisibility || !Common.SymbolsToGlobalize.empty() ||
+      !Common.SymbolsToKeep.empty() || !Common.SymbolsToLocalize.empty() ||
+      !Common.SymbolsToWeaken.empty() || !Common.SymbolsToKeepGlobal.empty() ||
+      !Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
+      Common.ExtractDWO || Common.LocalizeHidden || Common.PreserveDates ||
+      Common.StripDWO || Common.StripNonAlloc || Common.StripSections ||
+      Common.StripSwiftSymbols || Common.KeepUndefined || Common.Weaken ||
+      Common.DecompressDebugSections ||
+      Common.DiscardMode == DiscardType::Locals ||
+      !Common.SymbolsToAdd.empty() || Common.EntryExpr) {
+    return createStringError(llvm::errc::invalid_argument,
+                             "option not supported by llvm-objcopy for COFF");
+  }
+
+  return COFF;
+}
+
+Expected<const MachOConfig &> ConfigManager::getMachOConfig() const {
+  if (Common.AllowBrokenLinks || !Common.SplitDWO.empty() ||
+      !Common.SymbolsPrefix.empty() || !Common.AllocSectionsPrefix.empty() ||
+      !Common.KeepSection.empty() || ELF.NewSymbolVisibility ||
+      !Common.SymbolsToGlobalize.empty() || !Common.SymbolsToKeep.empty() ||
+      !Common.SymbolsToLocalize.empty() || !Common.SymbolsToWeaken.empty() ||
+      !Common.SymbolsToKeepGlobal.empty() || !Common.SectionsToRename.empty() ||
+      !Common.UnneededSymbolsToRemove.empty() ||
+      !Common.SetSectionAlignment.empty() || !Common.SetSectionFlags.empty() ||
+      Common.ExtractDWO || Common.LocalizeHidden || Common.PreserveDates ||
+      Common.StripAllGNU || Common.StripDWO || Common.StripNonAlloc ||
+      Common.StripSections || Common.Weaken || Common.DecompressDebugSections ||
+      Common.StripUnneeded || Common.DiscardMode == DiscardType::Locals ||
+      !Common.SymbolsToAdd.empty() || Common.EntryExpr) {
+    return createStringError(llvm::errc::invalid_argument,
+                             "option not supported by llvm-objcopy for MachO");
+  }
+
+  return MachO;
+}
+
+Expected<const WasmConfig &> ConfigManager::getWasmConfig() const {
+  if (!Common.AddGnuDebugLink.empty() || Common.ExtractPartition ||
+      !Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
+      !Common.AllocSectionsPrefix.empty() ||
+      Common.DiscardMode != DiscardType::None || ELF.NewSymbolVisibility ||
+      !Common.SymbolsToAdd.empty() || !Common.RPathToAdd.empty() ||
+      !Common.SymbolsToGlobalize.empty() || !Common.SymbolsToLocalize.empty() ||
+      !Common.SymbolsToKeep.empty() || !Common.SymbolsToRemove.empty() ||
+      !Common.UnneededSymbolsToRemove.empty() ||
+      !Common.SymbolsToWeaken.empty() || !Common.SymbolsToKeepGlobal.empty() ||
+      !Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
+      !Common.SetSectionFlags.empty() || !Common.SymbolsToRename.empty()) {
+    return createStringError(
+        llvm::errc::invalid_argument,
+        "only flags for section dumping, removal, and addition are supported");
+  }
+
+  return Wasm;
+}
+
 // ParseObjcopyOptions returns the config and sets the input arguments. If a
 // help flag is set then ParseObjcopyOptions will print the help messege and
 // exit.
 Expected<DriverConfig>
-parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
-                    llvm::function_ref<Error(Error)> ErrorCallback) {
+objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
+                             function_ref<Error(Error)> ErrorCallback) {
   DriverConfig DC;
   ObjcopyOptTable T;
+
+  const char *const *DashDash =
+      std::find_if(RawArgsArr.begin(), RawArgsArr.end(),
+                   [](StringRef Str) { return Str == "--"; });
+  ArrayRef<const char *> ArgsArr = makeArrayRef(RawArgsArr.begin(), DashDash);
+  if (DashDash != RawArgsArr.end())
+    DashDash = std::next(DashDash);
+
   unsigned MissingArgumentIndex, MissingArgumentCount;
   llvm::opt::InputArgList InputArgs =
       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
 
-  if (InputArgs.size() == 0) {
+  if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) {
     printHelp(T, errs(), ToolType::Objcopy);
     exit(1);
   }
@@ -501,6 +672,7 @@
 
   for (auto Arg : InputArgs.filtered(OBJCOPY_INPUT))
     Positional.push_back(Arg->getValue());
+  std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
 
   if (Positional.empty())
     return createStringError(errc::invalid_argument, "no input file specified");
@@ -509,7 +681,9 @@
     return createStringError(errc::invalid_argument,
                              "too many positional arguments");
 
-  CopyConfig Config;
+  ConfigManager ConfigMgr;
+  CommonConfig &Config = ConfigMgr.Common;
+  ELFConfig &ELFConfig = ConfigMgr.ELF;
   Config.InputFilename = Positional[0];
   Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
   if (InputArgs.hasArg(OBJCOPY_target) &&
@@ -548,10 +722,24 @@
                            .Case("ihex", FileFormat::IHex)
                            .Default(FileFormat::Unspecified);
 
-  if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility))
-    Config.NewSymbolVisibility =
+  if (InputArgs.hasArg(OBJCOPY_new_symbol_visibility)) {
+    const uint8_t Invalid = 0xff;
+    StringRef VisibilityStr =
         InputArgs.getLastArgValue(OBJCOPY_new_symbol_visibility);
 
+    ELFConfig.NewSymbolVisibility = StringSwitch<uint8_t>(VisibilityStr)
+                                        .Case("default", ELF::STV_DEFAULT)
+                                        .Case("hidden", ELF::STV_HIDDEN)
+                                        .Case("internal", ELF::STV_INTERNAL)
+                                        .Case("protected", ELF::STV_PROTECTED)
+                                        .Default(Invalid);
+
+    if (ELFConfig.NewSymbolVisibility == Invalid)
+      return createStringError(errc::invalid_argument,
+                               "'%s' is not a valid symbol visibility",
+                               VisibilityStr.str().c_str());
+  }
+
   Config.OutputFormat = StringSwitch<FileFormat>(OutputFormat)
                             .Case("binary", FileFormat::Binary)
                             .Case("ihex", FileFormat::IHex)
@@ -607,13 +795,6 @@
     Config.GnuDebugLinkCRC32 =
         llvm::crc32(arrayRefFromStringRef(Debug->getBuffer()));
   }
-  Config.BuildIdLinkDir = InputArgs.getLastArgValue(OBJCOPY_build_id_link_dir);
-  if (InputArgs.hasArg(OBJCOPY_build_id_link_input))
-    Config.BuildIdLinkInput =
-        InputArgs.getLastArgValue(OBJCOPY_build_id_link_input);
-  if (InputArgs.hasArg(OBJCOPY_build_id_link_output))
-    Config.BuildIdLinkOutput =
-        InputArgs.getLastArgValue(OBJCOPY_build_id_link_output);
   Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo);
   Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols);
   Config.AllocSectionsPrefix =
@@ -706,8 +887,14 @@
           "bad format for --add-section: missing file name");
     Config.AddSection.push_back(ArgValue);
   }
-  for (auto Arg : InputArgs.filtered(OBJCOPY_dump_section))
-    Config.DumpSection.push_back(Arg->getValue());
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) {
+    StringRef Value(Arg->getValue());
+    if (Value.split('=').second.empty())
+      return createStringError(
+          errc::invalid_argument,
+          "bad format for --dump-section, expected section=file");
+    Config.DumpSection.push_back(Value);
+  }
   Config.StripAll = InputArgs.hasArg(OBJCOPY_strip_all);
   Config.StripAllGNU = InputArgs.hasArg(OBJCOPY_strip_all_gnu);
   Config.StripDebug = InputArgs.hasArg(OBJCOPY_strip_debug);
@@ -727,6 +914,7 @@
             : DiscardType::Locals;
   Config.OnlyKeepDebug = InputArgs.hasArg(OBJCOPY_only_keep_debug);
   Config.KeepFileSymbols = InputArgs.hasArg(OBJCOPY_keep_file_symbols);
+  Config.KeepUndefined = InputArgs.hasArg(OBJCOPY_keep_undefined);
   Config.DecompressDebugSections =
       InputArgs.hasArg(OBJCOPY_decompress_debug_sections);
   if (Config.DiscardMode == DiscardType::All) {
@@ -797,8 +985,13 @@
             addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(),
                                SymbolMatchStyle, ErrorCallback))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_add_symbol))
-    Config.SymbolsToAdd.push_back(Arg->getValue());
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) {
+    Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue());
+    if (!SymInfo)
+      return SymInfo.takeError();
+
+    Config.SymbolsToAdd.push_back(*SymInfo);
+  }
 
   Config.AllowBrokenLinks = InputArgs.hasArg(OBJCOPY_allow_broken_links);
 
@@ -852,7 +1045,7 @@
                              "cannot specify --extract-partition together with "
                              "--extract-main-partition");
 
-  DC.CopyConfigs.push_back(std::move(Config));
+  DC.CopyConfigs.push_back(std::move(ConfigMgr));
   return std::move(DC);
 }
 
@@ -860,9 +1053,10 @@
 // If a help flag is set then ParseInstallNameToolOptions will print the help
 // messege and exit.
 Expected<DriverConfig>
-parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
+objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
   DriverConfig DC;
-  CopyConfig Config;
+  ConfigManager ConfigMgr;
+  CommonConfig &Config = ConfigMgr.Common;
   InstallNameToolOptTable T;
   unsigned MissingArgumentIndex, MissingArgumentCount;
   llvm::opt::InputArgList InputArgs =
@@ -986,14 +1180,15 @@
   Config.InputFilename = Positional[0];
   Config.OutputFilename = Positional[0];
 
-  DC.CopyConfigs.push_back(std::move(Config));
+  DC.CopyConfigs.push_back(std::move(ConfigMgr));
   return std::move(DC);
 }
 
 Expected<DriverConfig>
-parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr) {
+objcopy::parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr) {
   DriverConfig DC;
-  CopyConfig Config;
+  ConfigManager ConfigMgr;
+  CommonConfig &Config = ConfigMgr.Common;
   BitcodeStripOptTable T;
   unsigned MissingArgumentIndex, MissingArgumentCount;
   opt::InputArgList InputArgs =
@@ -1030,7 +1225,7 @@
   Config.InputFilename = Positional[0];
   Config.OutputFilename = Positional[0];
 
-  DC.CopyConfigs.push_back(std::move(Config));
+  DC.CopyConfigs.push_back(std::move(ConfigMgr));
   return std::move(DC);
 }
 
@@ -1038,14 +1233,21 @@
 // help flag is set then ParseStripOptions will print the help messege and
 // exit.
 Expected<DriverConfig>
-parseStripOptions(ArrayRef<const char *> ArgsArr,
-                  llvm::function_ref<Error(Error)> ErrorCallback) {
+objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
+                           function_ref<Error(Error)> ErrorCallback) {
+  const char *const *DashDash =
+      std::find_if(RawArgsArr.begin(), RawArgsArr.end(),
+                   [](StringRef Str) { return Str == "--"; });
+  ArrayRef<const char *> ArgsArr = makeArrayRef(RawArgsArr.begin(), DashDash);
+  if (DashDash != RawArgsArr.end())
+    DashDash = std::next(DashDash);
+
   StripOptTable T;
   unsigned MissingArgumentIndex, MissingArgumentCount;
   llvm::opt::InputArgList InputArgs =
       T.ParseArgs(ArgsArr, MissingArgumentIndex, MissingArgumentCount);
 
-  if (InputArgs.size() == 0) {
+  if (InputArgs.size() == 0 && DashDash == RawArgsArr.end()) {
     printHelp(T, errs(), ToolType::Strip);
     exit(1);
   }
@@ -1067,6 +1269,7 @@
                              Arg->getAsString(InputArgs).c_str());
   for (auto Arg : InputArgs.filtered(STRIP_INPUT))
     Positional.push_back(Arg->getValue());
+  std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
 
   if (Positional.empty())
     return createStringError(errc::invalid_argument, "no input file specified");
@@ -1076,7 +1279,8 @@
         errc::invalid_argument,
         "multiple input files cannot be used in combination with -o");
 
-  CopyConfig Config;
+  ConfigManager ConfigMgr;
+  CommonConfig &Config = ConfigMgr.Common;
 
   if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard))
     return createStringError(errc::invalid_argument,
@@ -1104,6 +1308,7 @@
   Config.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols);
   Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug);
   Config.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols);
+  Config.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined);
 
   for (auto Arg : InputArgs.filtered(STRIP_keep_section))
     if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
@@ -1148,7 +1353,7 @@
     Config.InputFilename = Positional[0];
     Config.OutputFilename =
         InputArgs.getLastArgValue(STRIP_output, Positional[0]);
-    DC.CopyConfigs.push_back(std::move(Config));
+    DC.CopyConfigs.push_back(std::move(ConfigMgr));
   } else {
     StringMap<unsigned> InputFiles;
     for (StringRef Filename : Positional) {
@@ -1164,7 +1369,7 @@
       }
       Config.InputFilename = Filename;
       Config.OutputFilename = Filename;
-      DC.CopyConfigs.push_back(Config);
+      DC.CopyConfigs.push_back(ConfigMgr);
     }
   }
 
@@ -1175,6 +1380,3 @@
 
   return std::move(DC);
 }
-
-} // namespace objcopy
-} // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/ConfigManager.h b/src/llvm-project/llvm/tools/llvm-objcopy/ConfigManager.h
new file mode 100644
index 0000000..c0d0e8b
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/ConfigManager.h
@@ -0,0 +1,80 @@
+//===- ConfigManager.h ----------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_OBJCOPY_CONFIGMANAGER_H
+#define LLVM_TOOLS_LLVM_OBJCOPY_CONFIGMANAGER_H
+
+#include "COFF/COFFConfig.h"
+#include "CommonConfig.h"
+#include "ELF/ELFConfig.h"
+#include "MachO/MachOConfig.h"
+#include "MultiFormatConfig.h"
+#include "wasm/WasmConfig.h"
+#include "llvm/Support/Allocator.h"
+#include <vector>
+
+namespace llvm {
+namespace objcopy {
+
+// ConfigManager keeps all configurations and prepare
+// format-specific options.
+struct ConfigManager : public MultiFormatConfig {
+  virtual ~ConfigManager() {}
+
+  const CommonConfig &getCommonConfig() const override { return Common; }
+  Expected<const ELFConfig &> getELFConfig() const override;
+  Expected<const COFFConfig &> getCOFFConfig() const override;
+  Expected<const MachOConfig &> getMachOConfig() const override;
+  Expected<const WasmConfig &> getWasmConfig() const override;
+
+  // All configs.
+  CommonConfig Common;
+  ELFConfig ELF;
+  COFFConfig COFF;
+  MachOConfig MachO;
+  WasmConfig Wasm;
+};
+
+// Configuration for the overall invocation of this tool. When invoked as
+// objcopy, will always contain exactly one CopyConfig. When invoked as strip,
+// will contain one or more CopyConfigs.
+struct DriverConfig {
+  SmallVector<ConfigManager, 1> CopyConfigs;
+  BumpPtrAllocator Alloc;
+};
+
+// ParseObjcopyOptions returns the config and sets the input arguments. If a
+// help flag is set then ParseObjcopyOptions will print the help messege and
+// exit. ErrorCallback is used to handle recoverable errors. An Error returned
+// by the callback aborts the parsing and is then returned by this function.
+Expected<DriverConfig>
+parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
+                    llvm::function_ref<Error(Error)> ErrorCallback);
+
+// ParseInstallNameToolOptions returns the config and sets the input arguments.
+// If a help flag is set then ParseInstallNameToolOptions will print the help
+// messege and exit.
+Expected<DriverConfig>
+parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr);
+
+// ParseBitcodeStripOptions returns the config and sets the input arguments.
+// If a help flag is set then ParseBitcodeStripOptions will print the help
+// messege and exit.
+Expected<DriverConfig> parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr);
+
+// ParseStripOptions returns the config and sets the input arguments. If a
+// help flag is set then ParseStripOptions will print the help messege and
+// exit. ErrorCallback is used to handle recoverable errors. An Error returned
+// by the callback aborts the parsing and is then returned by this function.
+Expected<DriverConfig>
+parseStripOptions(ArrayRef<const char *> ArgsArr,
+                  llvm::function_ref<Error(Error)> ErrorCallback);
+} // namespace objcopy
+} // namespace llvm
+
+#endif // LLVM_TOOLS_LLVM_OBJCOPY_CONFIGMANAGER_H
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFConfig.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFConfig.cpp
deleted file mode 100644
index 4099376..0000000
--- a/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFConfig.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-//===- ELFConfig.cpp ------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#include "CopyConfig.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Error.h"
-
-namespace llvm {
-namespace objcopy {
-namespace elf {
-
-static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue,
-                                                  uint8_t DefaultVisibility) {
-  // Parse value given with --add-symbol option and create the
-  // new symbol if possible. The value format for --add-symbol is:
-  //
-  // <name>=[<section>:]<value>[,<flags>]
-  //
-  // where:
-  // <name> - symbol name, can be empty string
-  // <section> - optional section name. If not given ABS symbol is created
-  // <value> - symbol value, can be decimal or hexadecimal number prefixed
-  //           with 0x.
-  // <flags> - optional flags affecting symbol type, binding or visibility:
-  //           The following are currently supported:
-  //
-  //           global, local, weak, default, hidden, file, section, object,
-  //           indirect-function.
-  //
-  //           The following flags are ignored and provided for GNU
-  //           compatibility only:
-  //
-  //           warning, debug, constructor, indirect, synthetic,
-  //           unique-object, before=<symbol>.
-  NewSymbolInfo SI;
-  StringRef Value;
-  std::tie(SI.SymbolName, Value) = FlagValue.split('=');
-  if (Value.empty())
-    return createStringError(
-        errc::invalid_argument,
-        "bad format for --add-symbol, missing '=' after '%s'",
-        SI.SymbolName.str().c_str());
-
-  if (Value.contains(':')) {
-    std::tie(SI.SectionName, Value) = Value.split(':');
-    if (SI.SectionName.empty() || Value.empty())
-      return createStringError(
-          errc::invalid_argument,
-          "bad format for --add-symbol, missing section name or symbol value");
-  }
-
-  SmallVector<StringRef, 6> Flags;
-  Value.split(Flags, ',');
-  if (Flags[0].getAsInteger(0, SI.Value))
-    return createStringError(errc::invalid_argument, "bad symbol value: '%s'",
-                             Flags[0].str().c_str());
-
-  SI.Visibility = DefaultVisibility;
-
-  using Functor = std::function<void(void)>;
-  SmallVector<StringRef, 6> UnsupportedFlags;
-  for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I)
-    static_cast<Functor>(
-        StringSwitch<Functor>(Flags[I])
-            .CaseLower("global", [&SI] { SI.Bind = ELF::STB_GLOBAL; })
-            .CaseLower("local", [&SI] { SI.Bind = ELF::STB_LOCAL; })
-            .CaseLower("weak", [&SI] { SI.Bind = ELF::STB_WEAK; })
-            .CaseLower("default", [&SI] { SI.Visibility = ELF::STV_DEFAULT; })
-            .CaseLower("hidden", [&SI] { SI.Visibility = ELF::STV_HIDDEN; })
-            .CaseLower("protected",
-                       [&SI] { SI.Visibility = ELF::STV_PROTECTED; })
-            .CaseLower("file", [&SI] { SI.Type = ELF::STT_FILE; })
-            .CaseLower("section", [&SI] { SI.Type = ELF::STT_SECTION; })
-            .CaseLower("object", [&SI] { SI.Type = ELF::STT_OBJECT; })
-            .CaseLower("function", [&SI] { SI.Type = ELF::STT_FUNC; })
-            .CaseLower("indirect-function",
-                       [&SI] { SI.Type = ELF::STT_GNU_IFUNC; })
-            .CaseLower("debug", [] {})
-            .CaseLower("constructor", [] {})
-            .CaseLower("warning", [] {})
-            .CaseLower("indirect", [] {})
-            .CaseLower("synthetic", [] {})
-            .CaseLower("unique-object", [] {})
-            .StartsWithLower("before", [] {})
-            .Default([&] { UnsupportedFlags.push_back(Flags[I]); }))();
-  if (!UnsupportedFlags.empty())
-    return createStringError(errc::invalid_argument,
-                             "unsupported flag%s for --add-symbol: '%s'",
-                             UnsupportedFlags.size() > 1 ? "s" : "",
-                             join(UnsupportedFlags, "', '").c_str());
-  return SI;
-}
-
-Expected<ELFCopyConfig> parseConfig(const CopyConfig &Config) {
-  ELFCopyConfig ELFConfig;
-  if (Config.NewSymbolVisibility) {
-    const uint8_t Invalid = 0xff;
-    ELFConfig.NewSymbolVisibility =
-        StringSwitch<uint8_t>(*Config.NewSymbolVisibility)
-            .Case("default", ELF::STV_DEFAULT)
-            .Case("hidden", ELF::STV_HIDDEN)
-            .Case("internal", ELF::STV_INTERNAL)
-            .Case("protected", ELF::STV_PROTECTED)
-            .Default(Invalid);
-
-    if (ELFConfig.NewSymbolVisibility == Invalid)
-      return createStringError(errc::invalid_argument,
-                               "'%s' is not a valid symbol visibility",
-                               Config.NewSymbolVisibility->str().c_str());
-  }
-
-  for (StringRef Arg : Config.SymbolsToAdd) {
-    Expected<elf::NewSymbolInfo> NSI = parseNewSymbolInfo(
-        Arg,
-        ELFConfig.NewSymbolVisibility.getValueOr((uint8_t)ELF::STV_DEFAULT));
-    if (!NSI)
-      return NSI.takeError();
-    ELFConfig.SymbolsToAdd.push_back(*NSI);
-  }
-
-  return ELFConfig;
-}
-
-} // end namespace elf
-} // end namespace objcopy
-} // end namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFConfig.h b/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFConfig.h
index 977efbc..42d407d 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFConfig.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFConfig.h
@@ -6,39 +6,23 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_OBJCOPY_ELFCONFIG_H
-#define LLVM_TOOLS_OBJCOPY_ELFCONFIG_H
+#ifndef LLVM_TOOLS_LLVM_OBJCOPY_ELF_ELFCONFIG_H
+#define LLVM_TOOLS_LLVM_OBJCOPY_ELF_ELFCONFIG_H
 
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Object/ELFTypes.h"
-#include "llvm/Support/Error.h"
 #include <vector>
 
 namespace llvm {
 namespace objcopy {
-struct CopyConfig;
 
-namespace elf {
-
-struct NewSymbolInfo {
-  StringRef SymbolName;
-  StringRef SectionName;
-  uint64_t Value = 0;
-  uint8_t Type = ELF::STT_NOTYPE;
-  uint8_t Bind = ELF::STB_GLOBAL;
-  uint8_t Visibility = ELF::STV_DEFAULT;
+// ELF specific configuration for copying/stripping a single file.
+struct ELFConfig {
+  uint8_t NewSymbolVisibility = (uint8_t)ELF::STV_DEFAULT;
 };
 
-struct ELFCopyConfig {
-  Optional<uint8_t> NewSymbolVisibility;
-  std::vector<NewSymbolInfo> SymbolsToAdd;
-};
-
-Expected<ELFCopyConfig> parseConfig(const CopyConfig &Config);
-
-} // namespace elf
 } // namespace objcopy
 } // namespace llvm
 
-#endif
+#endif // LLVM_TOOLS_LLVM_OBJCOPY_ELF_ELFCONFIG_H
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
index c53a34b..986eeca 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
@@ -7,9 +7,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "ELFObjcopy.h"
-#include "Buffer.h"
-#include "CopyConfig.h"
+#include "CommonConfig.h"
+#include "ELFConfig.h"
 #include "Object.h"
+#include "llvm-objcopy.h"
 #include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/Optional.h"
@@ -44,12 +45,12 @@
 #include <system_error>
 #include <utility>
 
-namespace llvm {
-namespace objcopy {
-namespace elf {
+using namespace llvm;
+using namespace llvm::ELF;
+using namespace llvm::objcopy;
+using namespace llvm::objcopy::elf;
+using namespace llvm::object;
 
-using namespace object;
-using namespace ELF;
 using SectionPred = std::function<bool(const SectionBase &Sec)>;
 
 static bool isDebugSection(const SectionBase &Sec) {
@@ -70,7 +71,7 @@
   return !isDWOSection(Sec);
 }
 
-uint64_t getNewShfFlags(SectionFlag AllFlags) {
+static uint64_t getNewShfFlags(SectionFlag AllFlags) {
   uint64_t NewFlags = 0;
   if (AllFlags & SectionFlag::SecAlloc)
     NewFlags |= ELF::SHF_ALLOC;
@@ -132,77 +133,40 @@
     return MI.IsLittleEndian ? ELFT_ELF32LE : ELFT_ELF32BE;
 }
 
-static std::unique_ptr<Writer> createELFWriter(const CopyConfig &Config,
-                                               Object &Obj, Buffer &Buf,
+static std::unique_ptr<Writer> createELFWriter(const CommonConfig &Config,
+                                               Object &Obj, raw_ostream &Out,
                                                ElfType OutputElfType) {
   // Depending on the initial ELFT and OutputFormat we need a different Writer.
   switch (OutputElfType) {
   case ELFT_ELF32LE:
-    return std::make_unique<ELFWriter<ELF32LE>>(Obj, Buf, !Config.StripSections,
+    return std::make_unique<ELFWriter<ELF32LE>>(Obj, Out, !Config.StripSections,
                                                 Config.OnlyKeepDebug);
   case ELFT_ELF64LE:
-    return std::make_unique<ELFWriter<ELF64LE>>(Obj, Buf, !Config.StripSections,
+    return std::make_unique<ELFWriter<ELF64LE>>(Obj, Out, !Config.StripSections,
                                                 Config.OnlyKeepDebug);
   case ELFT_ELF32BE:
-    return std::make_unique<ELFWriter<ELF32BE>>(Obj, Buf, !Config.StripSections,
+    return std::make_unique<ELFWriter<ELF32BE>>(Obj, Out, !Config.StripSections,
                                                 Config.OnlyKeepDebug);
   case ELFT_ELF64BE:
-    return std::make_unique<ELFWriter<ELF64BE>>(Obj, Buf, !Config.StripSections,
+    return std::make_unique<ELFWriter<ELF64BE>>(Obj, Out, !Config.StripSections,
                                                 Config.OnlyKeepDebug);
   }
   llvm_unreachable("Invalid output format");
 }
 
-static std::unique_ptr<Writer> createWriter(const CopyConfig &Config,
-                                            Object &Obj, Buffer &Buf,
+static std::unique_ptr<Writer> createWriter(const CommonConfig &Config,
+                                            Object &Obj, raw_ostream &Out,
                                             ElfType OutputElfType) {
   switch (Config.OutputFormat) {
   case FileFormat::Binary:
-    return std::make_unique<BinaryWriter>(Obj, Buf);
+    return std::make_unique<BinaryWriter>(Obj, Out);
   case FileFormat::IHex:
-    return std::make_unique<IHexWriter>(Obj, Buf);
+    return std::make_unique<IHexWriter>(Obj, Out);
   default:
-    return createELFWriter(Config, Obj, Buf, OutputElfType);
+    return createELFWriter(Config, Obj, Out, OutputElfType);
   }
 }
 
-template <class ELFT>
-static Expected<ArrayRef<uint8_t>>
-findBuildID(const CopyConfig &Config, const object::ELFFile<ELFT> &In) {
-  auto PhdrsOrErr = In.program_headers();
-  if (auto Err = PhdrsOrErr.takeError())
-    return createFileError(Config.InputFilename, std::move(Err));
-
-  for (const auto &Phdr : *PhdrsOrErr) {
-    if (Phdr.p_type != PT_NOTE)
-      continue;
-    Error Err = Error::success();
-    for (auto Note : In.notes(Phdr, Err))
-      if (Note.getType() == NT_GNU_BUILD_ID && Note.getName() == ELF_NOTE_GNU)
-        return Note.getDesc();
-    if (Err)
-      return createFileError(Config.InputFilename, std::move(Err));
-  }
-
-  return createFileError(Config.InputFilename,
-                         createStringError(llvm::errc::invalid_argument,
-                                           "could not find build ID"));
-}
-
-static Expected<ArrayRef<uint8_t>>
-findBuildID(const CopyConfig &Config, const object::ELFObjectFileBase &In) {
-  if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(&In))
-    return findBuildID(Config, O->getELFFile());
-  else if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(&In))
-    return findBuildID(Config, O->getELFFile());
-  else if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(&In))
-    return findBuildID(Config, O->getELFFile());
-  else if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(&In))
-    return findBuildID(Config, O->getELFFile());
-
-  llvm_unreachable("Bad file format");
-}
-
 template <class... Ts>
 static Error makeStringError(std::error_code EC, const Twine &Msg,
                              Ts &&... Args) {
@@ -210,83 +174,6 @@
   return createStringError(EC, FullMsg.c_str(), std::forward<Ts>(Args)...);
 }
 
-#define MODEL_8 "%%%%%%%%"
-#define MODEL_16 MODEL_8 MODEL_8
-#define MODEL_32 (MODEL_16 MODEL_16)
-
-static Error linkToBuildIdDir(const CopyConfig &Config, StringRef ToLink,
-                              StringRef Suffix,
-                              ArrayRef<uint8_t> BuildIdBytes) {
-  SmallString<128> Path = Config.BuildIdLinkDir;
-  sys::path::append(Path, llvm::toHex(BuildIdBytes[0], /*LowerCase*/ true));
-  if (auto EC = sys::fs::create_directories(Path))
-    return createFileError(
-        Path.str(),
-        makeStringError(EC, "cannot create build ID link directory"));
-
-  sys::path::append(Path,
-                    llvm::toHex(BuildIdBytes.slice(1), /*LowerCase*/ true));
-  Path += Suffix;
-  SmallString<128> TmpPath;
-  // create_hard_link races so we need to link to a temporary path but
-  // we want to make sure that we choose a filename that does not exist.
-  // By using 32 model characters we get 128-bits of entropy. It is
-  // unlikely that this string has ever existed before much less exists
-  // on this disk or in the current working directory.
-  // Additionally we prepend the original Path for debugging but also
-  // because it ensures that we're linking within a directory on the same
-  // partition on the same device which is critical. It has the added
-  // win of yet further decreasing the odds of a conflict.
-  sys::fs::createUniquePath(Twine(Path) + "-" + MODEL_32 + ".tmp", TmpPath,
-                            /*MakeAbsolute*/ false);
-  if (auto EC = sys::fs::create_hard_link(ToLink, TmpPath)) {
-    Path.push_back('\0');
-    return makeStringError(EC, "cannot link '%s' to '%s'", ToLink.data(),
-                           Path.data());
-  }
-  // We then atomically rename the link into place which will just move the
-  // link. If rename fails something is more seriously wrong so just return
-  // an error.
-  if (auto EC = sys::fs::rename(TmpPath, Path)) {
-    Path.push_back('\0');
-    return makeStringError(EC, "cannot link '%s' to '%s'", ToLink.data(),
-                           Path.data());
-  }
-  // If `Path` was already a hard-link to the same underlying file then the
-  // temp file will be left so we need to remove it. Remove will not cause
-  // an error by default if the file is already gone so just blindly remove
-  // it rather than checking.
-  if (auto EC = sys::fs::remove(TmpPath)) {
-    TmpPath.push_back('\0');
-    return makeStringError(EC, "could not remove '%s'", TmpPath.data());
-  }
-  return Error::success();
-}
-
-static Error splitDWOToFile(const CopyConfig &Config, const Reader &Reader,
-                            StringRef File, ElfType OutputElfType) {
-  Expected<std::unique_ptr<Object>> DWOFile = Reader.create(false);
-  if (!DWOFile)
-    return DWOFile.takeError();
-
-  auto OnlyKeepDWOPred = [&DWOFile](const SectionBase &Sec) {
-    return onlyKeepDWOPred(**DWOFile, Sec);
-  };
-  if (Error E =
-          (*DWOFile)->removeSections(Config.AllowBrokenLinks, OnlyKeepDWOPred))
-    return E;
-  if (Config.OutputArch) {
-    (*DWOFile)->Machine = Config.OutputArch.getValue().EMachine;
-    (*DWOFile)->OSABI = Config.OutputArch.getValue().OSABI;
-  }
-  FileBuffer FB(File);
-  std::unique_ptr<Writer> Writer =
-      createWriter(Config, **DWOFile, FB, OutputElfType);
-  if (Error E = Writer->finalize())
-    return E;
-  return Writer->write();
-}
-
 static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
                                Object &Obj) {
   for (auto &Sec : Obj.sections()) {
@@ -357,7 +244,7 @@
          Sym.Type != STT_SECTION;
 }
 
-static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) {
+static Error updateAndRemoveSymbols(const CommonConfig &Config, Object &Obj) {
   // TODO: update or remove symbols only if there is an option that affects
   // them.
   if (!Obj.SymbolTable)
@@ -452,7 +339,7 @@
   return Obj.removeSymbols(RemoveSymbolsPred);
 }
 
-static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) {
+static Error replaceAndRemoveSections(const CommonConfig &Config, Object &Obj) {
   SectionPred RemovePred = [](const SectionBase &) { return false; };
 
   // Removes:
@@ -462,7 +349,7 @@
     };
   }
 
-  if (Config.StripDWO || !Config.SplitDWO.empty())
+  if (Config.StripDWO)
     RemovePred = [RemovePred](const SectionBase &Sec) {
       return isDWOSection(Sec) || RemovePred(Sec);
     };
@@ -613,6 +500,60 @@
   return Obj.removeSections(Config.AllowBrokenLinks, RemovePred);
 }
 
+// Add symbol to the Object symbol table with the specified properties.
+static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo,
+                      uint8_t DefaultVisibility) {
+  SectionBase *Sec = Obj.findSection(SymInfo.SectionName);
+  uint64_t Value = Sec ? Sec->Addr + SymInfo.Value : SymInfo.Value;
+
+  uint8_t Bind = ELF::STB_GLOBAL;
+  uint8_t Type = ELF::STT_NOTYPE;
+  uint8_t Visibility = DefaultVisibility;
+
+  for (SymbolFlag FlagValue : SymInfo.Flags)
+    switch (FlagValue) {
+    case SymbolFlag::Global:
+      Bind = ELF::STB_GLOBAL;
+      break;
+    case SymbolFlag::Local:
+      Bind = ELF::STB_LOCAL;
+      break;
+    case SymbolFlag::Weak:
+      Bind = ELF::STB_WEAK;
+      break;
+    case SymbolFlag::Default:
+      Visibility = ELF::STV_DEFAULT;
+      break;
+    case SymbolFlag::Hidden:
+      Visibility = ELF::STV_HIDDEN;
+      break;
+    case SymbolFlag::Protected:
+      Visibility = ELF::STV_PROTECTED;
+      break;
+    case SymbolFlag::File:
+      Type = ELF::STT_FILE;
+      break;
+    case SymbolFlag::Section:
+      Type = ELF::STT_SECTION;
+      break;
+    case SymbolFlag::Object:
+      Type = ELF::STT_OBJECT;
+      break;
+    case SymbolFlag::Function:
+      Type = ELF::STT_FUNC;
+      break;
+    case SymbolFlag::IndirectFunction:
+      Type = ELF::STT_GNU_IFUNC;
+      break;
+    default: /* Other flag values are ignored for ELF. */
+      break;
+    };
+
+  Obj.SymbolTable->addSymbol(
+      SymInfo.SymbolName, Bind, Type, Sec, Value, Visibility,
+      Sec ? (uint16_t)SYMBOL_SIMPLE_INDEX : (uint16_t)SHN_ABS, 0);
+}
+
 // This function handles the high level operations of GNU objcopy including
 // handling command line options. It's important to outline certain properties
 // we expect to hold of the command line operations. Any operation that "keeps"
@@ -620,21 +561,19 @@
 // any previous removals. Lastly whether or not something is removed shouldn't
 // depend a) on the order the options occur in or b) on some opaque priority
 // system. The only priority is that keeps/copies overrule removes.
-static Error handleArgs(const CopyConfig &Config, Object &Obj,
-                        const Reader &Reader, ElfType OutputElfType) {
-  if (Config.StripSwiftSymbols)
-    return createStringError(llvm::errc::invalid_argument,
-                             "option not supported by llvm-objcopy for ELF");
-  if (!Config.SplitDWO.empty())
-    if (Error E =
-            splitDWOToFile(Config, Reader, Config.SplitDWO, OutputElfType))
-      return E;
-
+static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
+                        Object &Obj) {
   if (Config.OutputArch) {
     Obj.Machine = Config.OutputArch.getValue().EMachine;
     Obj.OSABI = Config.OutputArch.getValue().OSABI;
   }
 
+  if (!Config.SplitDWO.empty() && Config.ExtractDWO) {
+    return Obj.removeSections(
+        Config.AllowBrokenLinks,
+        [&Obj](const SectionBase &Sec) { return onlyKeepDWOPred(Obj, Sec); });
+  }
+
   // Dump sections before add/remove for compatibility with GNU objcopy.
   for (StringRef Flag : Config.DumpSection) {
     StringRef SectionName;
@@ -748,17 +687,12 @@
 
   // If the symbol table was previously removed, we need to create a new one
   // before adding new symbols.
-  if (!Obj.SymbolTable && !Config.ELF->SymbolsToAdd.empty())
+  if (!Obj.SymbolTable && !Config.SymbolsToAdd.empty())
     if (Error E = Obj.addNewSymbolTable())
       return E;
 
-  for (const NewSymbolInfo &SI : Config.ELF->SymbolsToAdd) {
-    SectionBase *Sec = Obj.findSection(SI.SectionName);
-    uint64_t Value = Sec ? Sec->Addr + SI.Value : SI.Value;
-    Obj.SymbolTable->addSymbol(
-        SI.SymbolName, SI.Bind, SI.Type, Sec, Value, SI.Visibility,
-        Sec ? (uint16_t)SYMBOL_SIMPLE_INDEX : (uint16_t)SHN_ABS, 0);
-  }
+  for (const NewSymbolInfo &SI : Config.SymbolsToAdd)
+    addSymbol(Obj, SI, ELFConfig.NewSymbolVisibility);
 
   // --set-section-flags works with sections added by --add-section.
   if (!Config.SetSectionFlags.empty()) {
@@ -776,8 +710,8 @@
   return Error::success();
 }
 
-static Error writeOutput(const CopyConfig &Config, Object &Obj, Buffer &Out,
-                         ElfType OutputElfType) {
+static Error writeOutput(const CommonConfig &Config, Object &Obj,
+                         raw_ostream &Out, ElfType OutputElfType) {
   std::unique_ptr<Writer> Writer =
       createWriter(Config, Obj, Out, OutputElfType);
   if (Error E = Writer->finalize())
@@ -785,8 +719,9 @@
   return Writer->write();
 }
 
-Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
-                           Buffer &Out) {
+Error objcopy::elf::executeObjcopyOnIHex(const CommonConfig &Config,
+                                         const ELFConfig &ELFConfig,
+                                         MemoryBuffer &In, raw_ostream &Out) {
   IHexReader Reader(&In);
   Expected<std::unique_ptr<Object>> Obj = Reader.create(true);
   if (!Obj)
@@ -794,16 +729,16 @@
 
   const ElfType OutputElfType =
       getOutputElfType(Config.OutputArch.getValueOr(MachineInfo()));
-  if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType))
+  if (Error E = handleArgs(Config, ELFConfig, **Obj))
     return E;
   return writeOutput(Config, **Obj, Out, OutputElfType);
 }
 
-Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
-                                Buffer &Out) {
-  uint8_t NewSymbolVisibility =
-      Config.ELF->NewSymbolVisibility.getValueOr((uint8_t)ELF::STV_DEFAULT);
-  BinaryReader Reader(&In, NewSymbolVisibility);
+Error objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig &Config,
+                                              const ELFConfig &ELFConfig,
+                                              MemoryBuffer &In,
+                                              raw_ostream &Out) {
+  BinaryReader Reader(&In, ELFConfig.NewSymbolVisibility);
   Expected<std::unique_ptr<Object>> Obj = Reader.create(true);
   if (!Obj)
     return Obj.takeError();
@@ -812,13 +747,15 @@
   // (-B<arch>).
   const ElfType OutputElfType =
       getOutputElfType(Config.OutputArch.getValueOr(MachineInfo()));
-  if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType))
+  if (Error E = handleArgs(Config, ELFConfig, **Obj))
     return E;
   return writeOutput(Config, **Obj, Out, OutputElfType);
 }
 
-Error executeObjcopyOnBinary(const CopyConfig &Config,
-                             object::ELFObjectFileBase &In, Buffer &Out) {
+Error objcopy::elf::executeObjcopyOnBinary(const CommonConfig &Config,
+                                           const ELFConfig &ELFConfig,
+                                           object::ELFObjectFileBase &In,
+                                           raw_ostream &Out) {
   ELFReader Reader(&In, Config.ExtractPartition);
   Expected<std::unique_ptr<Object>> Obj =
       Reader.create(!Config.SymbolsToAdd.empty());
@@ -828,41 +765,12 @@
   const ElfType OutputElfType =
       Config.OutputArch ? getOutputElfType(Config.OutputArch.getValue())
                         : getOutputElfType(In);
-  ArrayRef<uint8_t> BuildIdBytes;
 
-  if (!Config.BuildIdLinkDir.empty()) {
-    auto BuildIdBytesOrErr = findBuildID(Config, In);
-    if (auto E = BuildIdBytesOrErr.takeError())
-      return E;
-    BuildIdBytes = *BuildIdBytesOrErr;
-
-    if (BuildIdBytes.size() < 2)
-      return createFileError(
-          Config.InputFilename,
-          createStringError(object_error::parse_failed,
-                            "build ID is smaller than two bytes"));
-  }
-
-  if (!Config.BuildIdLinkDir.empty() && Config.BuildIdLinkInput)
-    if (Error E =
-            linkToBuildIdDir(Config, Config.InputFilename,
-                             Config.BuildIdLinkInput.getValue(), BuildIdBytes))
-      return E;
-
-  if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType))
+  if (Error E = handleArgs(Config, ELFConfig, **Obj))
     return createFileError(Config.InputFilename, std::move(E));
 
   if (Error E = writeOutput(Config, **Obj, Out, OutputElfType))
     return createFileError(Config.InputFilename, std::move(E));
-  if (!Config.BuildIdLinkDir.empty() && Config.BuildIdLinkOutput)
-    if (Error E =
-            linkToBuildIdDir(Config, Config.OutputFilename,
-                             Config.BuildIdLinkOutput.getValue(), BuildIdBytes))
-      return createFileError(Config.OutputFilename, std::move(E));
 
   return Error::success();
 }
-
-} // end namespace elf
-} // end namespace objcopy
-} // end namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.h b/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.h
index e13e237..852661e 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.h
@@ -12,22 +12,26 @@
 namespace llvm {
 class Error;
 class MemoryBuffer;
+class raw_ostream;
 
 namespace object {
 class ELFObjectFileBase;
 } // end namespace object
 
 namespace objcopy {
-struct CopyConfig;
-class Buffer;
+struct CommonConfig;
+struct ELFConfig;
 
 namespace elf {
-Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
-                           Buffer &Out);
-Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
-                                Buffer &Out);
-Error executeObjcopyOnBinary(const CopyConfig &Config,
-                             object::ELFObjectFileBase &In, Buffer &Out);
+Error executeObjcopyOnIHex(const CommonConfig &Config,
+                           const ELFConfig &ELFConfig, MemoryBuffer &In,
+                           raw_ostream &Out);
+Error executeObjcopyOnRawBinary(const CommonConfig &Config,
+                                const ELFConfig &ELFConfig, MemoryBuffer &In,
+                                raw_ostream &Out);
+Error executeObjcopyOnBinary(const CommonConfig &Config,
+                             const ELFConfig &ELFConfig,
+                             object::ELFObjectFileBase &In, raw_ostream &Out);
 
 } // end namespace elf
 } // end namespace objcopy
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/ELF/Object.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/ELF/Object.cpp
index 0ff82f9..ba91d08 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/ELF/Object.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/ELF/Object.cpp
@@ -29,16 +29,14 @@
 #include <utility>
 #include <vector>
 
-namespace llvm {
-namespace objcopy {
-namespace elf {
-
-using namespace object;
-using namespace ELF;
+using namespace llvm;
+using namespace llvm::ELF;
+using namespace llvm::objcopy::elf;
+using namespace llvm::object;
 
 template <class ELFT> void ELFWriter<ELFT>::writePhdr(const Segment &Seg) {
-  uint8_t *B = Buf.getBufferStart() + Obj.ProgramHdrSegment.Offset +
-               Seg.Index * sizeof(Elf_Phdr);
+  uint8_t *B = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) +
+               Obj.ProgramHdrSegment.Offset + Seg.Index * sizeof(Elf_Phdr);
   Elf_Phdr &Phdr = *reinterpret_cast<Elf_Phdr *>(B);
   Phdr.p_type = Seg.Type;
   Phdr.p_flags = Seg.Flags;
@@ -67,7 +65,8 @@
 void SectionBase::onRemove() {}
 
 template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase &Sec) {
-  uint8_t *B = Buf.getBufferStart() + Sec.HeaderOffset;
+  uint8_t *B =
+      reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Sec.HeaderOffset;
   Elf_Shdr &Shdr = *reinterpret_cast<Elf_Shdr *>(B);
   Shdr.sh_name = Sec.NameIndex;
   Shdr.sh_type = Sec.Type;
@@ -191,7 +190,7 @@
 // Fills exactly Len bytes of buffer with hexadecimal characters
 // representing value 'X'
 template <class T, class Iterator>
-static Iterator utohexstr(T X, Iterator It, size_t Len) {
+static Iterator toHexStr(T X, Iterator It, size_t Len) {
   // Fill range with '0'
   std::fill(It, It + Len, '0');
 
@@ -220,13 +219,13 @@
   assert(Line.size());
   auto Iter = Line.begin();
   *Iter++ = ':';
-  Iter = utohexstr(Data.size(), Iter, 2);
-  Iter = utohexstr(Addr, Iter, 4);
-  Iter = utohexstr(Type, Iter, 2);
+  Iter = toHexStr(Data.size(), Iter, 2);
+  Iter = toHexStr(Addr, Iter, 4);
+  Iter = toHexStr(Type, Iter, 2);
   for (uint8_t X : Data)
-    Iter = utohexstr(X, Iter, 2);
+    Iter = toHexStr(X, Iter, 2);
   StringRef S(Line.data() + 1, std::distance(Line.begin() + 1, Iter));
-  Iter = utohexstr(getChecksum(S), Iter, 2);
+  Iter = toHexStr(getChecksum(S), Iter, 2);
   *Iter++ = '\r';
   *Iter++ = '\n';
   assert(Iter == Line.end());
@@ -474,7 +473,7 @@
     return createStringError(errc::invalid_argument,
                              "'" + Sec.Name + "': " + toString(std::move(Err)));
 
-  uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
+  uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
   std::copy(DecompressedContent.begin(), DecompressedContent.end(), Buf);
 
   return Error::success();
@@ -519,7 +518,7 @@
 
 template <class ELFT>
 Error ELFSectionWriter<ELFT>::visit(const CompressedSection &Sec) {
-  uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
+  uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
   if (Sec.CompressionType == DebugCompressionType::None) {
     std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), Buf);
     return Error::success();
@@ -624,7 +623,8 @@
 }
 
 Error SectionWriter::visit(const StringTableSection &Sec) {
-  Sec.StrTabBuilder.write(Out.getBufferStart() + Sec.Offset);
+  Sec.StrTabBuilder.write(reinterpret_cast<uint8_t *>(Out.getBufferStart()) +
+                          Sec.Offset);
   return Error::success();
 }
 
@@ -638,7 +638,7 @@
 
 template <class ELFT>
 Error ELFSectionWriter<ELFT>::visit(const SectionIndexSection &Sec) {
-  uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
+  uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
   llvm::copy(Sec.Indexes, reinterpret_cast<Elf_Word *>(Buf));
   return Error::success();
 }
@@ -979,7 +979,7 @@
 
 template <class ELFT>
 Error ELFSectionWriter<ELFT>::visit(const RelocationSection &Sec) {
-  uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
+  uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
   if (Sec.Type == SHT_REL)
     writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf));
   else
@@ -1069,6 +1069,12 @@
 void GroupSection::finalize() {
   this->Info = Sym ? Sym->Index : 0;
   this->Link = SymTab ? SymTab->Index : 0;
+  // Linker deduplication for GRP_COMDAT is based on Sym->Name. The local/global
+  // status is not part of the equation. If Sym is localized, the intention is
+  // likely to make the group fully localized. Drop GRP_COMDAT to suppress
+  // deduplication. See https://groups.google.com/g/generic-abi/c/2X6mR-s2zoc
+  if ((FlagWord & GRP_COMDAT) && Sym && Sym->Binding == STB_LOCAL)
+    this->FlagWord &= ~GRP_COMDAT;
 }
 
 Error GroupSection::removeSectionReferences(
@@ -1160,7 +1166,8 @@
 
 template <class ELFT>
 Error ELFSectionWriter<ELFT>::visit(const GnuDebugLinkSection &Sec) {
-  unsigned char *Buf = Out.getBufferStart() + Sec.Offset;
+  unsigned char *Buf =
+      reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
   Elf_Word *CRC =
       reinterpret_cast<Elf_Word *>(Buf + Sec.Size - sizeof(Elf_Word));
   *CRC = Sec.CRC32;
@@ -1180,7 +1187,7 @@
 Error ELFSectionWriter<ELFT>::visit(const GroupSection &Sec) {
   ELF::Elf32_Word *Buf =
       reinterpret_cast<ELF::Elf32_Word *>(Out.getBufferStart() + Sec.Offset);
-  *Buf++ = Sec.FlagWord;
+  support::endian::write32<ELFT::TargetEndianness>(Buf++, Sec.FlagWord);
   for (SectionBase *S : Sec.GroupMembers)
     support::endian::write32<ELFT::TargetEndianness>(Buf++, S->Index);
   return Error::success();
@@ -1202,6 +1209,10 @@
   // not the first.
   uint64_t SecSize = Sec.Size ? Sec.Size : 1;
 
+  // Ignore just added sections.
+  if (Sec.OriginalOffset == std::numeric_limits<uint64_t>::max())
+    return false;
+
   if (Sec.Type == SHT_NOBITS) {
     if (!(Sec.Flags & SHF_ALLOC))
       return false;
@@ -1290,8 +1301,9 @@
   DataSection.Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE;
 
   std::string SanitizedFilename = MemBuf->getBufferIdentifier().str();
-  std::replace_if(std::begin(SanitizedFilename), std::end(SanitizedFilename),
-                  [](char C) { return !isalnum(C); }, '_');
+  std::replace_if(
+      std::begin(SanitizedFilename), std::end(SanitizedFilename),
+      [](char C) { return !isAlnum(C); }, '_');
   Twine Prefix = Twine("_binary_") + SanitizedFilename;
 
   SymTab->addSymbol(Prefix + "_start", STB_GLOBAL, STT_NOTYPE, &DataSection,
@@ -1505,7 +1517,8 @@
       reinterpret_cast<const ELF::Elf32_Word *>(GroupSec->Contents.data());
   const ELF::Elf32_Word *End =
       Word + GroupSec->Contents.size() / sizeof(ELF::Elf32_Word);
-  GroupSec->setFlagWord(*Word++);
+  GroupSec->setFlagWord(
+      support::endian::read32<ELFT::TargetEndianness>(Word++));
   for (; Word != End; ++Word) {
     uint32_t Index = support::endian::read32<ELFT::TargetEndianness>(Word);
     Expected<SectionBase *> Sec = SecTable.getSection(
@@ -1778,7 +1791,7 @@
     Sec->OriginalIndex = Sec->Index;
     Sec->OriginalData =
         ArrayRef<uint8_t>(ElfFile.base() + Shdr.sh_offset,
-                          (Shdr.sh_type == SHT_NOBITS) ? 0 : Shdr.sh_size);
+                          (Shdr.sh_type == SHT_NOBITS) ? (size_t)0 : Shdr.sh_size);
   }
 
   return Error::success();
@@ -1971,7 +1984,7 @@
 }
 
 template <class ELFT> void ELFWriter<ELFT>::writeEhdr() {
-  Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(Buf.getBufferStart());
+  Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(Buf->getBufferStart());
   std::fill(Ehdr.e_ident, Ehdr.e_ident + 16, 0);
   Ehdr.e_ident[EI_MAG0] = 0x7f;
   Ehdr.e_ident[EI_MAG1] = 'E';
@@ -2036,7 +2049,7 @@
   // This reference serves to write the dummy section header at the begining
   // of the file. It is not used for anything else
   Elf_Shdr &Shdr =
-      *reinterpret_cast<Elf_Shdr *>(Buf.getBufferStart() + Obj.SHOff);
+      *reinterpret_cast<Elf_Shdr *>(Buf->getBufferStart() + Obj.SHOff);
   Shdr.sh_name = 0;
   Shdr.sh_type = SHT_NULL;
   Shdr.sh_flags = 0;
@@ -2076,7 +2089,7 @@
 template <class ELFT> void ELFWriter<ELFT>::writeSegmentData() {
   for (Segment &Seg : Obj.segments()) {
     size_t Size = std::min<size_t>(Seg.FileSize, Seg.getContents().size());
-    std::memcpy(Buf.getBufferStart() + Seg.Offset, Seg.getContents().data(),
+    std::memcpy(Buf->getBufferStart() + Seg.Offset, Seg.getContents().data(),
                 Size);
   }
 
@@ -2087,12 +2100,12 @@
       continue;
     uint64_t Offset =
         Sec.OriginalOffset - Parent->OriginalOffset + Parent->Offset;
-    std::memset(Buf.getBufferStart() + Offset, 0, Sec.Size);
+    std::memset(Buf->getBufferStart() + Offset, 0, Sec.Size);
   }
 }
 
 template <class ELFT>
-ELFWriter<ELFT>::ELFWriter(Object &Obj, Buffer &Buf, bool WSH,
+ELFWriter<ELFT>::ELFWriter(Object &Obj, raw_ostream &Buf, bool WSH,
                            bool OnlyKeepDebug)
     : Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs),
       OnlyKeepDebug(OnlyKeepDebug) {}
@@ -2311,18 +2324,19 @@
                                                uint64_t HdrEnd) {
   uint64_t MaxOffset = 0;
   for (Segment *Seg : Segments) {
-    // An empty segment contains no section (see sectionWithinSegment). If it
-    // has a parent segment, copy the parent segment's offset field. This works
-    // for empty PT_TLS. We don't handle empty segments without a parent for
-    // now.
-    if (Seg->ParentSegment != nullptr && Seg->MemSize == 0)
-      Seg->Offset = Seg->ParentSegment->Offset;
-
-    const SectionBase *FirstSec = Seg->firstSection();
-    if (Seg->Type == PT_PHDR || !FirstSec)
+    if (Seg->Type == PT_PHDR)
       continue;
 
-    uint64_t Offset = FirstSec->Offset;
+    // The segment offset is generally the offset of the first section.
+    //
+    // For a segment containing no section (see sectionWithinSegment), if it has
+    // a parent segment, copy the parent segment's offset field. This works for
+    // empty PT_TLS. If no parent segment, use 0: the segment is not useful for
+    // debugging anyway.
+    const SectionBase *FirstSec = Seg->firstSection();
+    uint64_t Offset =
+        FirstSec ? FirstSec->Offset
+                 : (Seg->ParentSegment ? Seg->ParentSegment->Offset : 0);
     uint64_t FileSize = 0;
     for (const SectionBase *Sec : Seg->Sections) {
       uint64_t Size = Sec->Type == SHT_NOBITS ? 0 : Sec->Size;
@@ -2409,7 +2423,11 @@
     return E;
   if (WriteSectionHeaders)
     writeShdrs();
-  return Buf.commit();
+
+  // TODO: Implement direct writing to the output stream (without intermediate
+  // memory buffer Buf).
+  Out.write(Buf->getBufferStart(), Buf->getBufferSize());
+  return Error::success();
 }
 
 static Error removeUnneededSections(Object &Obj) {
@@ -2450,8 +2468,10 @@
   bool NeedsLargeIndexes = false;
   if (Obj.sections().size() >= SHN_LORESERVE) {
     SectionTableRef Sections = Obj.sections();
+    // Sections doesn't include the null section header, so account for this
+    // when skipping the first N sections.
     NeedsLargeIndexes =
-        any_of(drop_begin(Sections, SHN_LORESERVE),
+        any_of(drop_begin(Sections, SHN_LORESERVE - 1),
                [](const SectionBase &Sec) { return Sec.HasSymbol; });
     // TODO: handle case where only one section needs the large index table but
     // only needs it because the large index table hasn't been removed yet.
@@ -2529,9 +2549,14 @@
     Sec.finalize();
   }
 
-  if (Error E = Buf.allocate(totalSize()))
-    return E;
-  SecWriter = std::make_unique<ELFSectionWriter<ELFT>>(Buf);
+  size_t TotalSize = totalSize();
+  Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
+  if (!Buf)
+    return createStringError(errc::not_enough_memory,
+                             "failed to allocate memory buffer of " +
+                                 Twine::utohexstr(TotalSize) + " bytes");
+
+  SecWriter = std::make_unique<ELFSectionWriter<ELFT>>(*Buf);
   return Error::success();
 }
 
@@ -2540,7 +2565,10 @@
     if (Error Err = Sec.accept(*SecWriter))
       return Err;
 
-  return Buf.commit();
+  // TODO: Implement direct writing to the output stream (without intermediate
+  // memory buffer Buf).
+  Out.write(Buf->getBufferStart(), Buf->getBufferSize());
+  return Error::success();
 }
 
 Error BinaryWriter::finalize() {
@@ -2553,7 +2581,7 @@
     if (Sec.ParentSegment != nullptr)
       Sec.Addr =
           Sec.Offset - Sec.ParentSegment->Offset + Sec.ParentSegment->PAddr;
-    if (Sec.Size > 0)
+    if (Sec.Type != SHT_NOBITS && Sec.Size > 0)
       MinAddr = std::min(MinAddr, Sec.Addr);
   }
 
@@ -2568,9 +2596,12 @@
       TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size);
     }
 
-  if (Error E = Buf.allocate(TotalSize))
-    return E;
-  SecWriter = std::make_unique<BinarySectionWriter>(Buf);
+  Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
+  if (!Buf)
+    return createStringError(errc::not_enough_memory,
+                             "failed to allocate memory buffer of " +
+                                 Twine::utohexstr(TotalSize) + " bytes");
+  SecWriter = std::make_unique<BinarySectionWriter>(*Buf);
   return Error::success();
 }
 
@@ -2608,7 +2639,7 @@
 }
 
 Error IHexWriter::write() {
-  IHexSectionWriter Writer(Buf);
+  IHexSectionWriter Writer(*Buf);
   // Write sections.
   for (const SectionBase *Sec : Sections)
     if (Error Err = Sec->accept(Writer))
@@ -2616,11 +2647,17 @@
 
   uint64_t Offset = Writer.getBufferOffset();
   // Write entry point address.
-  Offset += writeEntryPointRecord(Buf.getBufferStart() + Offset);
+  Offset += writeEntryPointRecord(
+      reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Offset);
   // Write EOF.
-  Offset += writeEndOfFileRecord(Buf.getBufferStart() + Offset);
+  Offset += writeEndOfFileRecord(
+      reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + Offset);
   assert(Offset == TotalSize);
-  return Buf.commit();
+
+  // TODO: Implement direct writing to the output stream (without intermediate
+  // memory buffer Buf).
+  Out.write(Buf->getBufferStart(), Buf->getBufferSize());
+  return Error::success();
 }
 
 Error IHexWriter::checkSection(const SectionBase &Sec) {
@@ -2634,37 +2671,27 @@
 }
 
 Error IHexWriter::finalize() {
-  bool UseSegments = false;
-  auto ShouldWrite = [](const SectionBase &Sec) {
-    return (Sec.Flags & ELF::SHF_ALLOC) && (Sec.Type != ELF::SHT_NOBITS);
-  };
-  auto IsInPtLoad = [](const SectionBase &Sec) {
-    return Sec.ParentSegment && Sec.ParentSegment->Type == ELF::PT_LOAD;
-  };
-
   // We can't write 64-bit addresses.
   if (addressOverflows32bit(Obj.Entry))
     return createStringError(errc::invalid_argument,
-                             "Entry point address 0x%llx overflows 32 bits.",
+                             "Entry point address 0x%llx overflows 32 bits",
                              Obj.Entry);
 
-  // If any section we're to write has segment then we
-  // switch to using physical addresses. Otherwise we
-  // use section virtual address.
   for (const SectionBase &Sec : Obj.sections())
-    if (ShouldWrite(Sec) && IsInPtLoad(Sec)) {
-      UseSegments = true;
-      break;
-    }
-
-  for (const SectionBase &Sec : Obj.sections())
-    if (ShouldWrite(Sec) && (!UseSegments || IsInPtLoad(Sec))) {
+    if ((Sec.Flags & ELF::SHF_ALLOC) && Sec.Type != ELF::SHT_NOBITS &&
+        Sec.Size > 0) {
       if (Error E = checkSection(Sec))
         return E;
       Sections.insert(&Sec);
     }
 
-  IHexSectionWriterBase LengthCalc(Buf);
+  std::unique_ptr<WritableMemoryBuffer> EmptyBuffer =
+      WritableMemoryBuffer::getNewMemBuffer(0);
+  if (!EmptyBuffer)
+    return createStringError(errc::not_enough_memory,
+                             "failed to allocate memory buffer of 0 bytes");
+
+  IHexSectionWriterBase LengthCalc(*EmptyBuffer);
   for (const SectionBase *Sec : Sections)
     if (Error Err = Sec->accept(LengthCalc))
       return Err;
@@ -2674,11 +2701,20 @@
   TotalSize = LengthCalc.getBufferOffset() +
               (Obj.Entry ? IHexRecord::getLineLength(4) : 0) +
               IHexRecord::getLineLength(0);
-  if (Error E = Buf.allocate(TotalSize))
-    return E;
+
+  Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
+  if (!Buf)
+    return createStringError(errc::not_enough_memory,
+                             "failed to allocate memory buffer of " +
+                                 Twine::utohexstr(TotalSize) + " bytes");
+
   return Error::success();
 }
 
+namespace llvm {
+namespace objcopy {
+namespace elf {
+
 template class ELFBuilder<ELF64LE>;
 template class ELFBuilder<ELF64BE>;
 template class ELFBuilder<ELF32LE>;
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/ELF/Object.h b/src/llvm-project/llvm/tools/llvm-objcopy/ELF/Object.h
index 0205c2d..6fd26af 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/ELF/Object.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/ELF/Object.h
@@ -9,8 +9,7 @@
 #ifndef LLVM_TOOLS_OBJCOPY_OBJECT_H
 #define LLVM_TOOLS_OBJCOPY_OBJECT_H
 
-#include "Buffer.h"
-#include "CopyConfig.h"
+#include "CommonConfig.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -19,6 +18,7 @@
 #include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include <cstddef>
 #include <cstdint>
 #include <functional>
@@ -106,7 +106,7 @@
 
 class SectionWriter : public SectionVisitor {
 protected:
-  Buffer &Out;
+  WritableMemoryBuffer &Out;
 
 public:
   virtual ~SectionWriter() = default;
@@ -123,7 +123,7 @@
   virtual Error visit(const CompressedSection &Sec) override = 0;
   virtual Error visit(const DecompressedSection &Sec) override = 0;
 
-  explicit SectionWriter(Buffer &Buf) : Out(Buf) {}
+  explicit SectionWriter(WritableMemoryBuffer &Buf) : Out(Buf) {}
 };
 
 template <class ELFT> class ELFSectionWriter : public SectionWriter {
@@ -143,7 +143,7 @@
   Error visit(const CompressedSection &Sec) override;
   Error visit(const DecompressedSection &Sec) override;
 
-  explicit ELFSectionWriter(Buffer &Buf) : SectionWriter(Buf) {}
+  explicit ELFSectionWriter(WritableMemoryBuffer &Buf) : SectionWriter(Buf) {}
 };
 
 template <class ELFT> class ELFSectionSizer : public MutableSectionVisitor {
@@ -187,7 +187,8 @@
   Error visit(const CompressedSection &Sec) override;
   Error visit(const DecompressedSection &Sec) override;
 
-  explicit BinarySectionWriter(Buffer &Buf) : SectionWriter(Buf) {}
+  explicit BinarySectionWriter(WritableMemoryBuffer &Buf)
+      : SectionWriter(Buf) {}
 };
 
 using IHexLineData = SmallVector<char, 64>;
@@ -283,7 +284,8 @@
   virtual void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data);
 
 public:
-  explicit IHexSectionWriterBase(Buffer &Buf) : BinarySectionWriter(Buf) {}
+  explicit IHexSectionWriterBase(WritableMemoryBuffer &Buf)
+      : BinarySectionWriter(Buf) {}
 
   uint64_t getBufferOffset() const { return Offset; }
   Error visit(const Section &Sec) final;
@@ -296,7 +298,7 @@
 // Real IHEX section writer
 class IHexSectionWriter : public IHexSectionWriterBase {
 public:
-  IHexSectionWriter(Buffer &Buf) : IHexSectionWriterBase(Buf) {}
+  IHexSectionWriter(WritableMemoryBuffer &Buf) : IHexSectionWriterBase(Buf) {}
 
   void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data) override;
   Error visit(const StringTableSection &Sec) override;
@@ -305,14 +307,15 @@
 class Writer {
 protected:
   Object &Obj;
-  Buffer &Buf;
+  std::unique_ptr<WritableMemoryBuffer> Buf;
+  raw_ostream &Out;
 
 public:
   virtual ~Writer();
   virtual Error finalize() = 0;
   virtual Error write() = 0;
 
-  Writer(Object &O, Buffer &B) : Obj(O), Buf(B) {}
+  Writer(Object &O, raw_ostream &Out) : Obj(O), Out(Out) {}
 };
 
 template <class ELFT> class ELFWriter : public Writer {
@@ -349,7 +352,7 @@
 
   Error finalize() override;
   Error write() override;
-  ELFWriter(Object &Obj, Buffer &Buf, bool WSH, bool OnlyKeepDebug);
+  ELFWriter(Object &Obj, raw_ostream &Out, bool WSH, bool OnlyKeepDebug);
 };
 
 class BinaryWriter : public Writer {
@@ -362,7 +365,7 @@
   ~BinaryWriter() {}
   Error finalize() override;
   Error write() override;
-  BinaryWriter(Object &Obj, Buffer &Buf) : Writer(Obj, Buf) {}
+  BinaryWriter(Object &Obj, raw_ostream &Out) : Writer(Obj, Out) {}
 };
 
 class IHexWriter : public Writer {
@@ -381,7 +384,7 @@
   ~IHexWriter() {}
   Error finalize() override;
   Error write() override;
-  IHexWriter(Object &Obj, Buffer &Buf) : Writer(Obj, Buf) {}
+  IHexWriter(Object &Obj, raw_ostream &Out) : Writer(Obj, Out) {}
 };
 
 class SectionBase {
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOConfig.h b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOConfig.h
new file mode 100644
index 0000000..7c5dbfd
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOConfig.h
@@ -0,0 +1,21 @@
+//===- MachOConfig.h --------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_OBJCOPY_MACHO_MACHOCONFIG_H
+#define LLVM_TOOLS_LLVM_OBJCOPY_MACHO_MACHOCONFIG_H
+
+namespace llvm {
+namespace objcopy {
+
+// Mach-O specific configuration for copying/stripping a single file.
+struct MachOConfig {};
+
+} // namespace objcopy
+} // namespace llvm
+
+#endif // LLVM_TOOLS_LLVM_OBJCOPY_MACHO_MACHOCONFIG_H
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
index 8e2bf36..6ed2180 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
@@ -11,9 +11,8 @@
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/ErrorHandling.h"
 
-namespace llvm {
-namespace objcopy {
-namespace macho {
+using namespace llvm;
+using namespace llvm::objcopy::macho;
 
 StringTableBuilder::Kind
 MachOLayoutBuilder::getStringTableBuilderKind(const Object &O, bool Is64Bit) {
@@ -252,7 +251,10 @@
   uint64_t StartOfFunctionStarts = StartOfExportTrie + O.Exports.Trie.size();
   uint64_t StartOfDataInCode =
       StartOfFunctionStarts + O.FunctionStarts.Data.size();
-  uint64_t StartOfSymbols = StartOfDataInCode + O.DataInCode.Data.size();
+  uint64_t StartOfLinkerOptimizationHint =
+      StartOfDataInCode + O.DataInCode.Data.size();
+  uint64_t StartOfSymbols =
+      StartOfLinkerOptimizationHint + O.LinkerOptimizationHint.Data.size();
   uint64_t StartOfIndirectSymbols =
       StartOfSymbols + NListSize * O.SymTable.Symbols.size();
   uint64_t StartOfSymbolStrings =
@@ -321,6 +323,11 @@
       MLC.linkedit_data_command_data.dataoff = StartOfDataInCode;
       MLC.linkedit_data_command_data.datasize = O.DataInCode.Data.size();
       break;
+    case MachO::LC_LINKER_OPTIMIZATION_HINT:
+      MLC.linkedit_data_command_data.dataoff = StartOfLinkerOptimizationHint;
+      MLC.linkedit_data_command_data.datasize =
+          O.LinkerOptimizationHint.Data.size();
+      break;
     case MachO::LC_FUNCTION_STARTS:
       MLC.linkedit_data_command_data.dataoff = StartOfFunctionStarts;
       MLC.linkedit_data_command_data.datasize = O.FunctionStarts.Data.size();
@@ -371,6 +378,8 @@
     case MachO::LC_LOAD_WEAK_DYLIB:
     case MachO::LC_UUID:
     case MachO::LC_SOURCE_VERSION:
+    case MachO::LC_THREAD:
+    case MachO::LC_UNIXTHREAD:
       // Nothing to update.
       break;
     default:
@@ -392,7 +401,3 @@
   Offset = layoutRelocations(Offset);
   return layoutTail(Offset);
 }
-
-} // end namespace macho
-} // end namespace objcopy
-} // end namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
index fef4a0a..8233069 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
@@ -7,22 +7,25 @@
 //===----------------------------------------------------------------------===//
 
 #include "MachOObjcopy.h"
-#include "../CopyConfig.h"
 #include "../llvm-objcopy.h"
+#include "CommonConfig.h"
 #include "MachOReader.h"
 #include "MachOWriter.h"
+#include "MultiFormatConfig.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/Object/ArchiveWriter.h"
 #include "llvm/Object/MachOUniversal.h"
 #include "llvm/Object/MachOUniversalWriter.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/SmallVectorMemoryBuffer.h"
 
-namespace llvm {
-namespace objcopy {
-namespace macho {
+using namespace llvm;
+using namespace llvm::objcopy;
+using namespace llvm::objcopy::macho;
+using namespace llvm::object;
 
-using namespace object;
 using SectionPred = std::function<bool(const std::unique_ptr<Section> &Sec)>;
 using LoadCommandPred = std::function<bool(const LoadCommand &LC)>;
 
@@ -46,7 +49,7 @@
       .rtrim('\0');
 }
 
-static Error removeSections(const CopyConfig &Config, Object &Obj) {
+static Error removeSections(const CommonConfig &Config, Object &Obj) {
   SectionPred RemovePred = [](const std::unique_ptr<Section> &) {
     return false;
   };
@@ -77,14 +80,14 @@
   return Obj.removeSections(RemovePred);
 }
 
-static void markSymbols(const CopyConfig &Config, Object &Obj) {
+static void markSymbols(const CommonConfig &, Object &Obj) {
   // Symbols referenced from the indirect symbol table must not be removed.
   for (IndirectSymbolEntry &ISE : Obj.IndirectSymTable.Symbols)
     if (ISE.Symbol)
       (*ISE.Symbol)->Referenced = true;
 }
 
-static void updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) {
+static void updateAndRemoveSymbols(const CommonConfig &Config, Object &Obj) {
   for (SymbolEntry &Sym : Obj.SymTable) {
     auto I = Config.SymbolsToRename.find(Sym.Name);
     if (I != Config.SymbolsToRename.end())
@@ -94,6 +97,10 @@
   auto RemovePred = [Config, &Obj](const std::unique_ptr<SymbolEntry> &N) {
     if (N->Referenced)
       return false;
+    if (Config.KeepUndefined && N->isUndefinedSymbol())
+      return false;
+    if (N->n_desc & MachO::REFERENCED_DYNAMICALLY)
+      return false;
     if (Config.StripAll)
       return true;
     if (Config.DiscardMode == DiscardType::All && !(N->n_type & MachO::N_EXT))
@@ -132,7 +139,7 @@
   return LC;
 }
 
-static Error processLoadCommands(const CopyConfig &Config, Object &Obj) {
+static Error processLoadCommands(const CommonConfig &Config, Object &Obj) {
   // Remove RPaths.
   DenseSet<StringRef> RPathsToRemove(Config.RPathsToRemove.begin(),
                                      Config.RPathsToRemove.end());
@@ -326,26 +333,7 @@
   return Error::success();
 }
 
-static Error handleArgs(const CopyConfig &Config, Object &Obj) {
-  if (Config.AllowBrokenLinks || !Config.BuildIdLinkDir.empty() ||
-      Config.BuildIdLinkInput || Config.BuildIdLinkOutput ||
-      !Config.SplitDWO.empty() || !Config.SymbolsPrefix.empty() ||
-      !Config.AllocSectionsPrefix.empty() || !Config.KeepSection.empty() ||
-      Config.NewSymbolVisibility || !Config.SymbolsToGlobalize.empty() ||
-      !Config.SymbolsToKeep.empty() || !Config.SymbolsToLocalize.empty() ||
-      !Config.SymbolsToWeaken.empty() || !Config.SymbolsToKeepGlobal.empty() ||
-      !Config.SectionsToRename.empty() ||
-      !Config.UnneededSymbolsToRemove.empty() ||
-      !Config.SetSectionAlignment.empty() || !Config.SetSectionFlags.empty() ||
-      Config.ExtractDWO || Config.LocalizeHidden || Config.PreserveDates ||
-      Config.StripAllGNU || Config.StripDWO || Config.StripNonAlloc ||
-      Config.StripSections || Config.Weaken || Config.DecompressDebugSections ||
-      Config.StripUnneeded || Config.DiscardMode == DiscardType::Locals ||
-      !Config.SymbolsToAdd.empty() || Config.EntryExpr) {
-    return createStringError(llvm::errc::invalid_argument,
-                             "option not supported by llvm-objcopy for MachO");
-  }
-
+static Error handleArgs(const CommonConfig &Config, Object &Obj) {
   // Dump sections before add/remove for compatibility with GNU objcopy.
   for (StringRef Flag : Config.DumpSection) {
     StringRef SectionName;
@@ -385,8 +373,10 @@
   return Error::success();
 }
 
-Error executeObjcopyOnBinary(const CopyConfig &Config,
-                             object::MachOObjectFile &In, Buffer &Out) {
+Error objcopy::macho::executeObjcopyOnBinary(const CommonConfig &Config,
+                                             const MachOConfig &,
+                                             object::MachOObjectFile &In,
+                                             raw_ostream &Out) {
   MachOReader Reader(In);
   Expected<std::unique_ptr<Object>> O = Reader.create();
   if (!O)
@@ -414,9 +404,9 @@
   return Writer.write();
 }
 
-Error executeObjcopyOnMachOUniversalBinary(CopyConfig &Config,
-                                           const MachOUniversalBinary &In,
-                                           Buffer &Out) {
+Error objcopy::macho::executeObjcopyOnMachOUniversalBinary(
+    const MultiFormatConfig &Config, const MachOUniversalBinary &In,
+    raw_ostream &Out) {
   SmallVector<OwningBinary<Binary>, 2> Binaries;
   SmallVector<Slice, 2> Slices;
   for (const auto &O : In.objects()) {
@@ -429,7 +419,7 @@
       Expected<std::unique_ptr<MemoryBuffer>> OutputBufferOrErr =
           writeArchiveToBuffer(*NewArchiveMembersOrErr,
                                (*ArOrErr)->hasSymbolTable(), (*ArOrErr)->kind(),
-                               Config.DeterministicArchives,
+                               Config.getCommonConfig().DeterministicArchives,
                                (*ArOrErr)->isThin());
       if (!OutputBufferOrErr)
         return OutputBufferOrErr.takeError();
@@ -453,36 +443,39 @@
     Expected<std::unique_ptr<MachOObjectFile>> ObjOrErr = O.getAsObjectFile();
     if (!ObjOrErr) {
       consumeError(ObjOrErr.takeError());
-      return createStringError(std::errc::invalid_argument,
-                               "slice for '%s' of the universal Mach-O binary "
-                               "'%s' is not a Mach-O object or an archive",
-                               O.getArchFlagName().c_str(),
-                               Config.InputFilename.str().c_str());
+      return createStringError(
+          std::errc::invalid_argument,
+          "slice for '%s' of the universal Mach-O binary "
+          "'%s' is not a Mach-O object or an archive",
+          O.getArchFlagName().c_str(),
+          Config.getCommonConfig().InputFilename.str().c_str());
     }
     std::string ArchFlagName = O.getArchFlagName();
-    MemBuffer MB(ArchFlagName);
-    if (Error E = executeObjcopyOnBinary(Config, **ObjOrErr, MB))
+
+    SmallVector<char, 0> Buffer;
+    raw_svector_ostream MemStream(Buffer);
+
+    Expected<const MachOConfig &> MachO = Config.getMachOConfig();
+    if (!MachO)
+      return MachO.takeError();
+
+    if (Error E = executeObjcopyOnBinary(Config.getCommonConfig(), *MachO,
+                                         **ObjOrErr, MemStream))
       return E;
-    std::unique_ptr<WritableMemoryBuffer> OutputBuffer =
-        MB.releaseMemoryBuffer();
-    Expected<std::unique_ptr<Binary>> BinaryOrErr =
-        object::createBinary(*OutputBuffer);
+
+    std::unique_ptr<MemoryBuffer> MB =
+        std::make_unique<SmallVectorMemoryBuffer>(std::move(Buffer),
+                                                  ArchFlagName);
+    Expected<std::unique_ptr<Binary>> BinaryOrErr = object::createBinary(*MB);
     if (!BinaryOrErr)
       return BinaryOrErr.takeError();
-    Binaries.emplace_back(std::move(*BinaryOrErr), std::move(OutputBuffer));
+    Binaries.emplace_back(std::move(*BinaryOrErr), std::move(MB));
     Slices.emplace_back(*cast<MachOObjectFile>(Binaries.back().getBinary()),
                         O.getAlign());
   }
-  Expected<std::unique_ptr<MemoryBuffer>> B =
-      writeUniversalBinaryToBuffer(Slices);
-  if (!B)
-    return B.takeError();
-  if (Error E = Out.allocate((*B)->getBufferSize()))
-    return E;
-  memcpy(Out.getBufferStart(), (*B)->getBufferStart(), (*B)->getBufferSize());
-  return Out.commit();
-}
 
-} // end namespace macho
-} // end namespace objcopy
-} // end namespace llvm
+  if (Error Err = writeUniversalBinaryToStream(Slices, Out))
+    return Err;
+
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.h b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.h
index c3f5391..e30940a 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.h
@@ -11,6 +11,7 @@
 
 namespace llvm {
 class Error;
+class raw_ostream;
 
 namespace object {
 class MachOObjectFile;
@@ -18,15 +19,17 @@
 } // end namespace object
 
 namespace objcopy {
-struct CopyConfig;
-class Buffer;
+struct CommonConfig;
+struct MachOConfig;
+class MultiFormatConfig;
 
 namespace macho {
-Error executeObjcopyOnBinary(const CopyConfig &Config,
-                             object::MachOObjectFile &In, Buffer &Out);
+Error executeObjcopyOnBinary(const CommonConfig &Config, const MachOConfig &,
+                             object::MachOObjectFile &In, raw_ostream &Out);
 
 Error executeObjcopyOnMachOUniversalBinary(
-    CopyConfig &Config, const object::MachOUniversalBinary &In, Buffer &Out);
+    const MultiFormatConfig &Config, const object::MachOUniversalBinary &In,
+    raw_ostream &Out);
 
 } // end namespace macho
 } // end namespace objcopy
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
index 548a85b..7d1c29b 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
@@ -13,9 +13,9 @@
 #include "llvm/Support/Errc.h"
 #include <memory>
 
-namespace llvm {
-namespace objcopy {
-namespace macho {
+using namespace llvm;
+using namespace llvm::objcopy;
+using namespace llvm::objcopy::macho;
 
 void MachOReader::readHeader(Object &O) const {
   O.Header.Magic = MachOObj.getHeader().magic;
@@ -28,7 +28,7 @@
 }
 
 template <typename SectionType>
-Section constructSectionCommon(SectionType Sec, uint32_t Index) {
+static Section constructSectionCommon(const SectionType &Sec, uint32_t Index) {
   StringRef SegName(Sec.segname, strnlen(Sec.segname, sizeof(Sec.segname)));
   StringRef SectName(Sec.sectname, strnlen(Sec.sectname, sizeof(Sec.sectname)));
   Section S(SegName, SectName);
@@ -46,39 +46,34 @@
   return S;
 }
 
-template <typename SectionType>
-Section constructSection(SectionType Sec, uint32_t Index);
-
-template <> Section constructSection(MachO::section Sec, uint32_t Index) {
+Section constructSection(const MachO::section &Sec, uint32_t Index) {
   return constructSectionCommon(Sec, Index);
 }
 
-template <> Section constructSection(MachO::section_64 Sec, uint32_t Index) {
+Section constructSection(const MachO::section_64 &Sec, uint32_t Index) {
   Section S = constructSectionCommon(Sec, Index);
   S.Reserved3 = Sec.reserved3;
   return S;
 }
 
 template <typename SectionType, typename SegmentType>
-Expected<std::vector<std::unique_ptr<Section>>>
-extractSections(const object::MachOObjectFile::LoadCommandInfo &LoadCmd,
-                const object::MachOObjectFile &MachOObj,
-                uint32_t &NextSectionIndex) {
-  auto End = LoadCmd.Ptr + LoadCmd.C.cmdsize;
-  const SectionType *Curr =
-      reinterpret_cast<const SectionType *>(LoadCmd.Ptr + sizeof(SegmentType));
+Expected<std::vector<std::unique_ptr<Section>>> static extractSections(
+    const object::MachOObjectFile::LoadCommandInfo &LoadCmd,
+    const object::MachOObjectFile &MachOObj, uint32_t &NextSectionIndex) {
   std::vector<std::unique_ptr<Section>> Sections;
-  for (; reinterpret_cast<const void *>(Curr) < End; Curr++) {
-    if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) {
-      SectionType Sec;
-      memcpy((void *)&Sec, Curr, sizeof(SectionType));
+  for (auto Curr = reinterpret_cast<const SectionType *>(LoadCmd.Ptr +
+                                                         sizeof(SegmentType)),
+            End = reinterpret_cast<const SectionType *>(LoadCmd.Ptr +
+                                                        LoadCmd.C.cmdsize);
+       Curr < End; ++Curr) {
+    SectionType Sec;
+    memcpy((void *)&Sec, Curr, sizeof(SectionType));
+
+    if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost)
       MachO::swapStruct(Sec);
-      Sections.push_back(
-          std::make_unique<Section>(constructSection(Sec, NextSectionIndex)));
-    } else {
-      Sections.push_back(
-          std::make_unique<Section>(constructSection(*Curr, NextSectionIndex)));
-    }
+
+    Sections.push_back(
+        std::make_unique<Section>(constructSection(Sec, NextSectionIndex)));
 
     Section &S = *Sections.back();
 
@@ -95,6 +90,7 @@
     S.Content =
         StringRef(reinterpret_cast<const char *>(Data->data()), Data->size());
 
+    const uint32_t CPUType = MachOObj.getHeader().cputype;
     S.Relocations.reserve(S.NReloc);
     for (auto RI = MachOObj.section_rel_begin(SecRef->getRawDataRefImpl()),
               RE = MachOObj.section_rel_end(SecRef->getRawDataRefImpl());
@@ -103,6 +99,10 @@
       R.Symbol = nullptr; // We'll fill this field later.
       R.Info = MachOObj.getRelocation(RI->getRawDataRefImpl());
       R.Scattered = MachOObj.isRelocationScattered(R.Info);
+      unsigned Type = MachOObj.getAnyRelocationType(R.Info);
+      // TODO Support CPU_TYPE_ARM.
+      R.IsAddend = !R.Scattered && (CPUType == MachO::CPU_TYPE_ARM64 &&
+                                    Type == MachO::ARM64_RELOC_ADDEND);
       R.Extern = !R.Scattered && MachOObj.getPlainRelocationExternal(R.Info);
       S.Relocations.push_back(R);
     }
@@ -151,6 +151,9 @@
     case MachO::LC_DATA_IN_CODE:
       O.DataInCodeCommandIndex = O.LoadCommands.size();
       break;
+    case MachO::LC_LINKER_OPTIMIZATION_HINT:
+      O.LinkerOptimizationHintCommandIndex = O.LoadCommands.size();
+      break;
     case MachO::LC_FUNCTION_STARTS:
       O.FunctionStartsCommandIndex = O.LoadCommands.size();
       break;
@@ -223,7 +226,7 @@
   for (LoadCommand &LC : O.LoadCommands)
     for (std::unique_ptr<Section> &Sec : LC.Sections)
       for (auto &Reloc : Sec->Relocations)
-        if (!Reloc.Scattered) {
+        if (!Reloc.Scattered && !Reloc.IsAddend) {
           const uint32_t SymbolNum =
               Reloc.getPlainRelocationSymbolNum(MachOObj.isLittleEndian());
           if (Reloc.Extern) {
@@ -276,6 +279,11 @@
   return readLinkData(O, O.DataInCodeCommandIndex, O.DataInCode);
 }
 
+void MachOReader::readLinkerOptimizationHint(Object &O) const {
+  return readLinkData(O, O.LinkerOptimizationHintCommandIndex,
+                      O.LinkerOptimizationHint);
+}
+
 void MachOReader::readFunctionStartsData(Object &O) const {
   return readLinkData(O, O.FunctionStartsCommandIndex, O.FunctionStarts);
 }
@@ -330,12 +338,9 @@
   readExportInfo(*Obj);
   readCodeSignature(*Obj);
   readDataInCodeData(*Obj);
+  readLinkerOptimizationHint(*Obj);
   readFunctionStartsData(*Obj);
   readIndirectSymbolTable(*Obj);
   readSwiftVersion(*Obj);
   return std::move(Obj);
 }
-
-} // end namespace macho
-} // end namespace objcopy
-} // end namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOReader.h b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOReader.h
index b446e02..ca3a021 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOReader.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOReader.h
@@ -39,6 +39,7 @@
   void readLinkData(Object &O, Optional<size_t> LCIndex, LinkData &LD) const;
   void readCodeSignature(Object &O) const;
   void readDataInCodeData(Object &O) const;
+  void readLinkerOptimizationHint(Object &O) const;
   void readFunctionStartsData(Object &O) const;
   void readIndirectSymbolTable(Object &O) const;
   void readSwiftVersion(Object &O) const;
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
index 56dd08d..295098e 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
@@ -16,9 +16,8 @@
 #include "llvm/Support/ErrorHandling.h"
 #include <memory>
 
-namespace llvm {
-namespace objcopy {
-namespace macho {
+using namespace llvm;
+using namespace llvm::objcopy::macho;
 
 size_t MachOWriter::headerSize() const {
   return Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
@@ -108,6 +107,16 @@
                      LinkEditDataCommand.datasize);
   }
 
+  if (O.LinkerOptimizationHintCommandIndex) {
+    const MachO::linkedit_data_command &LinkEditDataCommand =
+        O.LoadCommands[*O.LinkerOptimizationHintCommandIndex]
+            .MachOLoadCommand.linkedit_data_command_data;
+
+    if (LinkEditDataCommand.dataoff)
+      Ends.push_back(LinkEditDataCommand.dataoff +
+                     LinkEditDataCommand.datasize);
+  }
+
   if (O.FunctionStartsCommandIndex) {
     const MachO::linkedit_data_command &LinkEditDataCommand =
         O.LoadCommands[*O.FunctionStartsCommandIndex]
@@ -159,11 +168,12 @@
 
   auto HeaderSize =
       Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
-  memcpy(B.getBufferStart(), &Header, HeaderSize);
+  memcpy(Buf->getBufferStart(), &Header, HeaderSize);
 }
 
 void MachOWriter::writeLoadCommands() {
-  uint8_t *Begin = B.getBufferStart() + headerSize();
+  uint8_t *Begin =
+      reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + headerSize();
   for (const LoadCommand &LC : O.LoadCommands) {
     // Construct a load command.
     MachO::macho_load_command MLC = LC.MachOLoadCommand;
@@ -257,11 +267,11 @@
 
       assert(Sec->Offset && "Section offset can not be zero");
       assert((Sec->Size == Sec->Content.size()) && "Incorrect section size");
-      memcpy(B.getBufferStart() + Sec->Offset, Sec->Content.data(),
+      memcpy(Buf->getBufferStart() + Sec->Offset, Sec->Content.data(),
              Sec->Content.size());
       for (size_t Index = 0; Index < Sec->Relocations.size(); ++Index) {
         RelocationInfo RelocInfo = Sec->Relocations[Index];
-        if (!RelocInfo.Scattered) {
+        if (!RelocInfo.Scattered && !RelocInfo.IsAddend) {
           const uint32_t SymbolNum = RelocInfo.Extern
                                          ? (*RelocInfo.Symbol)->Index
                                          : (*RelocInfo.Sec)->Index;
@@ -270,7 +280,7 @@
         if (IsLittleEndian != sys::IsLittleEndianHost)
           MachO::swapStruct(
               reinterpret_cast<MachO::any_relocation_info &>(RelocInfo.Info));
-        memcpy(B.getBufferStart() + Sec->RelOff +
+        memcpy(Buf->getBufferStart() + Sec->RelOff +
                    Index * sizeof(MachO::any_relocation_info),
                &RelocInfo.Info, sizeof(RelocInfo.Info));
       }
@@ -300,7 +310,7 @@
       O.LoadCommands[*O.SymTabCommandIndex]
           .MachOLoadCommand.symtab_command_data;
 
-  uint8_t *StrTable = (uint8_t *)B.getBufferStart() + SymTabCommand.stroff;
+  uint8_t *StrTable = (uint8_t *)Buf->getBufferStart() + SymTabCommand.stroff;
   LayoutBuilder.getStringTableBuilder().write(StrTable);
 }
 
@@ -311,7 +321,7 @@
       O.LoadCommands[*O.SymTabCommandIndex]
           .MachOLoadCommand.symtab_command_data;
 
-  char *SymTable = (char *)B.getBufferStart() + SymTabCommand.symoff;
+  char *SymTable = (char *)Buf->getBufferStart() + SymTabCommand.symoff;
   for (auto Iter = O.SymTable.Symbols.begin(), End = O.SymTable.Symbols.end();
        Iter != End; Iter++) {
     SymbolEntry *Sym = Iter->get();
@@ -330,7 +340,7 @@
   const MachO::dyld_info_command &DyLdInfoCommand =
       O.LoadCommands[*O.DyLdInfoCommandIndex]
           .MachOLoadCommand.dyld_info_command_data;
-  char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.rebase_off;
+  char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.rebase_off;
   assert((DyLdInfoCommand.rebase_size == O.Rebases.Opcodes.size()) &&
          "Incorrect rebase opcodes size");
   memcpy(Out, O.Rebases.Opcodes.data(), O.Rebases.Opcodes.size());
@@ -342,7 +352,7 @@
   const MachO::dyld_info_command &DyLdInfoCommand =
       O.LoadCommands[*O.DyLdInfoCommandIndex]
           .MachOLoadCommand.dyld_info_command_data;
-  char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.bind_off;
+  char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.bind_off;
   assert((DyLdInfoCommand.bind_size == O.Binds.Opcodes.size()) &&
          "Incorrect bind opcodes size");
   memcpy(Out, O.Binds.Opcodes.data(), O.Binds.Opcodes.size());
@@ -354,7 +364,7 @@
   const MachO::dyld_info_command &DyLdInfoCommand =
       O.LoadCommands[*O.DyLdInfoCommandIndex]
           .MachOLoadCommand.dyld_info_command_data;
-  char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.weak_bind_off;
+  char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.weak_bind_off;
   assert((DyLdInfoCommand.weak_bind_size == O.WeakBinds.Opcodes.size()) &&
          "Incorrect weak bind opcodes size");
   memcpy(Out, O.WeakBinds.Opcodes.data(), O.WeakBinds.Opcodes.size());
@@ -366,7 +376,7 @@
   const MachO::dyld_info_command &DyLdInfoCommand =
       O.LoadCommands[*O.DyLdInfoCommandIndex]
           .MachOLoadCommand.dyld_info_command_data;
-  char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.lazy_bind_off;
+  char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.lazy_bind_off;
   assert((DyLdInfoCommand.lazy_bind_size == O.LazyBinds.Opcodes.size()) &&
          "Incorrect lazy bind opcodes size");
   memcpy(Out, O.LazyBinds.Opcodes.data(), O.LazyBinds.Opcodes.size());
@@ -378,7 +388,7 @@
   const MachO::dyld_info_command &DyLdInfoCommand =
       O.LoadCommands[*O.DyLdInfoCommandIndex]
           .MachOLoadCommand.dyld_info_command_data;
-  char *Out = (char *)B.getBufferStart() + DyLdInfoCommand.export_off;
+  char *Out = (char *)Buf->getBufferStart() + DyLdInfoCommand.export_off;
   assert((DyLdInfoCommand.export_size == O.Exports.Trie.size()) &&
          "Incorrect export trie size");
   memcpy(Out, O.Exports.Trie.data(), O.Exports.Trie.size());
@@ -393,7 +403,7 @@
           .MachOLoadCommand.dysymtab_command_data;
 
   uint32_t *Out =
-      (uint32_t *)(B.getBufferStart() + DySymTabCommand.indirectsymoff);
+      (uint32_t *)(Buf->getBufferStart() + DySymTabCommand.indirectsymoff);
   for (const IndirectSymbolEntry &Sym : O.IndirectSymTable.Symbols) {
     uint32_t Entry = (Sym.Symbol) ? (*Sym.Symbol)->Index : Sym.OriginalIndex;
     if (IsLittleEndian != sys::IsLittleEndianHost)
@@ -407,7 +417,7 @@
     return;
   const MachO::linkedit_data_command &LinkEditDataCommand =
       O.LoadCommands[*LCIndex].MachOLoadCommand.linkedit_data_command_data;
-  char *Out = (char *)B.getBufferStart() + LinkEditDataCommand.dataoff;
+  char *Out = (char *)Buf->getBufferStart() + LinkEditDataCommand.dataoff;
   assert((LinkEditDataCommand.datasize == LD.Data.size()) &&
          "Incorrect data size");
   memcpy(Out, LD.Data.data(), LD.Data.size());
@@ -421,6 +431,11 @@
   return writeLinkData(O.DataInCodeCommandIndex, O.DataInCode);
 }
 
+void MachOWriter::writeLinkerOptimizationHint() {
+  return writeLinkData(O.LinkerOptimizationHintCommandIndex,
+                       O.LinkerOptimizationHint);
+}
+
 void MachOWriter::writeFunctionStartsData() {
   return writeLinkData(O.FunctionStartsCommandIndex, O.FunctionStarts);
 }
@@ -490,6 +505,16 @@
                          &MachOWriter::writeDataInCodeData);
   }
 
+  if (O.LinkerOptimizationHintCommandIndex) {
+    const MachO::linkedit_data_command &LinkEditDataCommand =
+        O.LoadCommands[*O.LinkerOptimizationHintCommandIndex]
+            .MachOLoadCommand.linkedit_data_command_data;
+
+    if (LinkEditDataCommand.dataoff)
+      Queue.emplace_back(LinkEditDataCommand.dataoff,
+                         &MachOWriter::writeLinkerOptimizationHint);
+  }
+
   if (O.FunctionStartsCommandIndex) {
     const MachO::linkedit_data_command &LinkEditDataCommand =
         O.LoadCommands[*O.FunctionStartsCommandIndex]
@@ -511,16 +536,20 @@
 Error MachOWriter::finalize() { return LayoutBuilder.layout(); }
 
 Error MachOWriter::write() {
-  if (Error E = B.allocate(totalSize()))
-    return E;
-  memset(B.getBufferStart(), 0, totalSize());
+  size_t TotalSize = totalSize();
+  Buf = WritableMemoryBuffer::getNewMemBuffer(TotalSize);
+  if (!Buf)
+    return createStringError(errc::not_enough_memory,
+                             "failed to allocate memory buffer of " +
+                                 Twine::utohexstr(TotalSize) + " bytes");
+  memset(Buf->getBufferStart(), 0, totalSize());
   writeHeader();
   writeLoadCommands();
   writeSections();
   writeTail();
-  return B.commit();
-}
 
-} // end namespace macho
-} // end namespace objcopy
-} // end namespace llvm
+  // TODO: Implement direct writing to the output stream (without intermediate
+  // memory buffer Buf).
+  Out.write(Buf->getBufferStart(), Buf->getBufferSize());
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOWriter.h b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOWriter.h
index c2c6f5a..c8c06d6 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOWriter.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/MachOWriter.h
@@ -6,7 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "../Buffer.h"
 #include "MachOLayoutBuilder.h"
 #include "MachOObjcopy.h"
 #include "Object.h"
@@ -24,7 +23,8 @@
   bool Is64Bit;
   bool IsLittleEndian;
   uint64_t PageSize;
-  Buffer &B;
+  std::unique_ptr<WritableMemoryBuffer> Buf;
+  raw_ostream &Out;
   MachOLayoutBuilder LayoutBuilder;
 
   size_t headerSize() const;
@@ -48,14 +48,15 @@
   void writeLinkData(Optional<size_t> LCIndex, const LinkData &LD);
   void writeCodeSignatureData();
   void writeDataInCodeData();
+  void writeLinkerOptimizationHint();
   void writeFunctionStartsData();
   void writeTail();
 
 public:
   MachOWriter(Object &O, bool Is64Bit, bool IsLittleEndian, uint64_t PageSize,
-              Buffer &B)
+              raw_ostream &Out)
       : O(O), Is64Bit(Is64Bit), IsLittleEndian(IsLittleEndian),
-        PageSize(PageSize), B(B), LayoutBuilder(O, Is64Bit, PageSize) {}
+        PageSize(PageSize), Out(Out), LayoutBuilder(O, Is64Bit, PageSize) {}
 
   size_t totalSize() const;
   Error finalize();
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/Object.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/Object.cpp
index cdb9753..b4f98fa 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/Object.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/Object.cpp
@@ -10,9 +10,8 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include <unordered_set>
 
-namespace llvm {
-namespace objcopy {
-namespace macho {
+using namespace llvm;
+using namespace llvm::objcopy::macho;
 
 const SymbolEntry *SymbolTable::getSymbolByIndex(uint32_t Index) const {
   assert(Index < Symbols.size() && "invalid symbol index");
@@ -47,6 +46,9 @@
     case MachO::LC_DATA_IN_CODE:
       DataInCodeCommandIndex = Index;
       break;
+    case MachO::LC_LINKER_OPTIMIZATION_HINT:
+      LinkerOptimizationHintCommandIndex = Index;
+      break;
     case MachO::LC_FUNCTION_STARTS:
       FunctionStartsCommandIndex = Index;
       break;
@@ -190,7 +192,3 @@
     return None;
   }
 }
-
-} // end namespace macho
-} // end namespace objcopy
-} // end namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/Object.h b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/Object.h
index 0bb4b34..207502e 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/MachO/Object.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/MachO/Object.h
@@ -180,6 +180,9 @@
   Optional<const Section *> Sec;
   // True if Info is a scattered_relocation_info.
   bool Scattered;
+  // True if the type is an ADDEND. r_symbolnum holds the addend instead of a
+  // symbol index.
+  bool IsAddend;
   // True if the r_symbolnum points to a section number (i.e. r_extern=0).
   bool Extern;
   MachO::any_relocation_info Info;
@@ -310,6 +313,7 @@
   ExportInfo Exports;
   IndirectSymbolTable IndirectSymTable;
   LinkData DataInCode;
+  LinkData LinkerOptimizationHint;
   LinkData FunctionStarts;
   LinkData CodeSignature;
 
@@ -325,6 +329,8 @@
   Optional<size_t> DySymTabCommandIndex;
   /// The index LC_DATA_IN_CODE load comamnd if present.
   Optional<size_t> DataInCodeCommandIndex;
+  /// The index of LC_LINKER_OPTIMIZATIN_HINT load comamnd if present.
+  Optional<size_t> LinkerOptimizationHintCommandIndex;
   /// The index LC_FUNCTION_STARTS load comamnd if present.
   Optional<size_t> FunctionStartsCommandIndex;
 
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/MultiFormatConfig.h b/src/llvm-project/llvm/tools/llvm-objcopy/MultiFormatConfig.h
new file mode 100644
index 0000000..31d9883
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/MultiFormatConfig.h
@@ -0,0 +1,37 @@
+//===- MultiFormatConfig.h --------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_OBJCOPY_MULTIFORMATCONFIG_H
+#define LLVM_TOOLS_LLVM_OBJCOPY_MULTIFORMATCONFIG_H
+
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace objcopy {
+
+struct CommonConfig;
+struct ELFConfig;
+struct COFFConfig;
+struct MachOConfig;
+struct WasmConfig;
+
+class MultiFormatConfig {
+public:
+  virtual ~MultiFormatConfig() {}
+
+  virtual const CommonConfig &getCommonConfig() const = 0;
+  virtual Expected<const ELFConfig &> getELFConfig() const = 0;
+  virtual Expected<const COFFConfig &> getCOFFConfig() const = 0;
+  virtual Expected<const MachOConfig &> getMachOConfig() const = 0;
+  virtual Expected<const WasmConfig &> getWasmConfig() const = 0;
+};
+
+} // namespace objcopy
+} // namespace llvm
+
+#endif // LLVM_TOOLS_LLVM_OBJCOPY_MULTIFORMATCONFIG_H
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td
index 9e6b6f0..63abbe4 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -196,19 +196,6 @@
     : Eq<"prefix-alloc-sections", "Add <prefix> to the start of every allocated section name">,
       MetaVarName<"prefix">;
 
-defm build_id_link_dir
-    : Eq<"build-id-link-dir", "Set directory for --build-id-link-input and "
-                              "--build-id-link-output to <dir>">,
-      MetaVarName<"dir">;
-defm build_id_link_input
-    : Eq<"build-id-link-input", "Hard-link the input to <dir>/xx/xxx<suffix> "
-                                "name derived from hex build ID">,
-      MetaVarName<"suffix">;
-defm build_id_link_output
-    : Eq<"build-id-link-output", "Hard-link the output to <dir>/xx/xxx<suffix> "
-                                 "name derived from hex build ID">,
-      MetaVarName<"suffix">;
-
 defm set_start : Eq<"set-start", "Set the start address to <addr>. Overrides "
                     "any previous --change-start or --adjust-start values.">,
                  MetaVarName<"addr">;
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
index 7fd2acd..ad16648 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -6,17 +6,23 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Buffer.h"
+#include "llvm-objcopy.h"
+#include "COFF/COFFConfig.h"
 #include "COFF/COFFObjcopy.h"
-#include "CopyConfig.h"
+#include "CommonConfig.h"
+#include "ConfigManager.h"
+#include "ELF/ELFConfig.h"
 #include "ELF/ELFObjcopy.h"
+#include "MachO/MachOConfig.h"
 #include "MachO/MachOObjcopy.h"
+#include "wasm/WasmConfig.h"
 #include "wasm/WasmObjcopy.h"
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/ELF.h"
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/ArchiveWriter.h"
 #include "llvm/Object/Binary.h"
@@ -32,6 +38,7 @@
 #include "llvm/Option/Option.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Errc.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ErrorOr.h"
@@ -40,6 +47,7 @@
 #include "llvm/Support/Memory.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Process.h"
+#include "llvm/Support/SmallVectorMemoryBuffer.h"
 #include "llvm/Support/StringSaver.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
@@ -51,13 +59,14 @@
 #include <system_error>
 #include <utility>
 
-namespace llvm {
-namespace objcopy {
+using namespace llvm;
+using namespace llvm::objcopy;
+using namespace llvm::object;
 
 // The name this program was invoked as.
-StringRef ToolName;
+static StringRef ToolName;
 
-ErrorSuccess reportWarning(Error E) {
+static ErrorSuccess reportWarning(Error E) {
   assert(E);
   WithColor::warning(errs(), ToolName) << toString(std::move(E)) << '\n';
   return Error::success();
@@ -72,7 +81,7 @@
     // strip-10.exe -> strip
     // powerpc64-unknown-freebsd13-objcopy -> objcopy
     // llvm-install-name-tool -> install-name-tool
-    auto I = Stem.rfind_lower(Tool);
+    auto I = Stem.rfind_insensitive(Tool);
     return I != StringRef::npos &&
            (I + Tool.size() == Stem.size() || !isAlnum(Stem[I + Tool.size()]));
   };
@@ -87,13 +96,6 @@
     return parseObjcopyOptions(Args, reportWarning);
 }
 
-} // end namespace objcopy
-} // end namespace llvm
-
-using namespace llvm;
-using namespace llvm::object;
-using namespace llvm::objcopy;
-
 // For regular archives this function simply calls llvm::writeArchive,
 // For thin archives it writes the archive file itself as well as its members.
 static Error deepWriteArchive(StringRef ArcName,
@@ -108,20 +110,21 @@
     return Error::success();
 
   for (const NewArchiveMember &Member : NewMembers) {
-    // Internally, FileBuffer will use the buffer created by
-    // FileOutputBuffer::create, for regular files (that is the case for
-    // deepWriteArchive) FileOutputBuffer::create will return OnDiskBuffer.
+    // For regular files (as is the case for deepWriteArchive),
+    // FileOutputBuffer::create will return OnDiskBuffer.
     // OnDiskBuffer uses a temporary file and then renames it. So in reality
     // there is no inefficiency / duplicated in-memory buffers in this case. For
     // now in-memory buffers can not be completely avoided since
     // NewArchiveMember still requires them even though writeArchive does not
     // write them on disk.
-    FileBuffer FB(Member.MemberName);
-    if (Error E = FB.allocate(Member.Buf->getBufferSize()))
-      return E;
+    Expected<std::unique_ptr<FileOutputBuffer>> FB =
+        FileOutputBuffer::create(Member.MemberName, Member.Buf->getBufferSize(),
+                                 FileOutputBuffer::F_executable);
+    if (!FB)
+      return FB.takeError();
     std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(),
-              FB.getBufferStart());
-    if (Error E = FB.commit())
+              (*FB)->getBufferStart());
+    if (Error E = (*FB)->commit())
       return E;
   }
   return Error::success();
@@ -129,18 +132,22 @@
 
 /// The function executeObjcopyOnIHex does the dispatch based on the format
 /// of the output specified by the command line options.
-static Error executeObjcopyOnIHex(CopyConfig &Config, MemoryBuffer &In,
-                                  Buffer &Out) {
+static Error executeObjcopyOnIHex(ConfigManager &ConfigMgr, MemoryBuffer &In,
+                                  raw_ostream &Out) {
   // TODO: support output formats other than ELF.
-  if (Error E = Config.parseELFConfig())
-    return E;
-  return elf::executeObjcopyOnIHex(Config, In, Out);
+  Expected<const ELFConfig &> ELFConfig = ConfigMgr.getELFConfig();
+  if (!ELFConfig)
+    return ELFConfig.takeError();
+
+  return elf::executeObjcopyOnIHex(ConfigMgr.getCommonConfig(), *ELFConfig, In,
+                                   Out);
 }
 
 /// The function executeObjcopyOnRawBinary does the dispatch based on the format
 /// of the output specified by the command line options.
-static Error executeObjcopyOnRawBinary(CopyConfig &Config, MemoryBuffer &In,
-                                       Buffer &Out) {
+static Error executeObjcopyOnRawBinary(ConfigManager &ConfigMgr,
+                                       MemoryBuffer &In, raw_ostream &Out) {
+  const CommonConfig &Config = ConfigMgr.getCommonConfig();
   switch (Config.OutputFormat) {
   case FileFormat::ELF:
   // FIXME: Currently, we call elf::executeObjcopyOnRawBinary even if the
@@ -149,9 +156,11 @@
   case FileFormat::Binary:
   case FileFormat::IHex:
   case FileFormat::Unspecified:
-    if (Error E = Config.parseELFConfig())
-      return E;
-    return elf::executeObjcopyOnRawBinary(Config, In, Out);
+    Expected<const ELFConfig &> ELFConfig = ConfigMgr.getELFConfig();
+    if (!ELFConfig)
+      return ELFConfig.takeError();
+
+    return elf::executeObjcopyOnRawBinary(Config, *ELFConfig, In, Out);
   }
 
   llvm_unreachable("unsupported output format");
@@ -159,23 +168,41 @@
 
 /// The function executeObjcopyOnBinary does the dispatch based on the format
 /// of the input binary (ELF, MachO or COFF).
-static Error executeObjcopyOnBinary(CopyConfig &Config, object::Binary &In,
-                                    Buffer &Out) {
+static Error executeObjcopyOnBinary(const MultiFormatConfig &Config,
+                                    object::Binary &In, raw_ostream &Out) {
   if (auto *ELFBinary = dyn_cast<object::ELFObjectFileBase>(&In)) {
-    if (Error E = Config.parseELFConfig())
-      return E;
-    return elf::executeObjcopyOnBinary(Config, *ELFBinary, Out);
-  } else if (auto *COFFBinary = dyn_cast<object::COFFObjectFile>(&In))
-    return coff::executeObjcopyOnBinary(Config, *COFFBinary, Out);
-  else if (auto *MachOBinary = dyn_cast<object::MachOObjectFile>(&In))
-    return macho::executeObjcopyOnBinary(Config, *MachOBinary, Out);
-  else if (auto *MachOUniversalBinary =
-               dyn_cast<object::MachOUniversalBinary>(&In))
+    Expected<const ELFConfig &> ELFConfig = Config.getELFConfig();
+    if (!ELFConfig)
+      return ELFConfig.takeError();
+
+    return elf::executeObjcopyOnBinary(Config.getCommonConfig(), *ELFConfig,
+                                       *ELFBinary, Out);
+  } else if (auto *COFFBinary = dyn_cast<object::COFFObjectFile>(&In)) {
+    Expected<const COFFConfig &> COFFConfig = Config.getCOFFConfig();
+    if (!COFFConfig)
+      return COFFConfig.takeError();
+
+    return coff::executeObjcopyOnBinary(Config.getCommonConfig(), *COFFConfig,
+                                        *COFFBinary, Out);
+  } else if (auto *MachOBinary = dyn_cast<object::MachOObjectFile>(&In)) {
+    Expected<const MachOConfig &> MachOConfig = Config.getMachOConfig();
+    if (!MachOConfig)
+      return MachOConfig.takeError();
+
+    return macho::executeObjcopyOnBinary(Config.getCommonConfig(), *MachOConfig,
+                                         *MachOBinary, Out);
+  } else if (auto *MachOUniversalBinary =
+                 dyn_cast<object::MachOUniversalBinary>(&In)) {
     return macho::executeObjcopyOnMachOUniversalBinary(
         Config, *MachOUniversalBinary, Out);
-  else if (auto *WasmBinary = dyn_cast<object::WasmObjectFile>(&In))
-    return objcopy::wasm::executeObjcopyOnBinary(Config, *WasmBinary, Out);
-  else
+  } else if (auto *WasmBinary = dyn_cast<object::WasmObjectFile>(&In)) {
+    Expected<const WasmConfig &> WasmConfig = Config.getWasmConfig();
+    if (!WasmConfig)
+      return WasmConfig.takeError();
+
+    return objcopy::wasm::executeObjcopyOnBinary(Config.getCommonConfig(),
+                                                 *WasmConfig, *WasmBinary, Out);
+  } else
     return createStringError(object_error::invalid_file_type,
                              "unsupported object file format");
 }
@@ -184,7 +211,7 @@
 namespace objcopy {
 
 Expected<std::vector<NewArchiveMember>>
-createNewArchiveMembers(CopyConfig &Config, const Archive &Ar) {
+createNewArchiveMembers(const MultiFormatConfig &Config, const Archive &Ar) {
   std::vector<NewArchiveMember> NewArchiveMembers;
   Error Err = Error::success();
   for (const Archive::Child &Child : Ar.children(Err)) {
@@ -197,32 +224,38 @@
       return createFileError(Ar.getFileName() + "(" + *ChildNameOrErr + ")",
                              ChildOrErr.takeError());
 
-    MemBuffer MB(ChildNameOrErr.get());
-    if (Error E = executeObjcopyOnBinary(Config, *ChildOrErr->get(), MB))
+    SmallVector<char, 0> Buffer;
+    raw_svector_ostream MemStream(Buffer);
+
+    if (Error E = executeObjcopyOnBinary(Config, *ChildOrErr->get(), MemStream))
       return std::move(E);
 
-    Expected<NewArchiveMember> Member =
-        NewArchiveMember::getOldMember(Child, Config.DeterministicArchives);
+    Expected<NewArchiveMember> Member = NewArchiveMember::getOldMember(
+        Child, Config.getCommonConfig().DeterministicArchives);
     if (!Member)
       return createFileError(Ar.getFileName(), Member.takeError());
-    Member->Buf = MB.releaseMemoryBuffer();
+
+    Member->Buf = std::make_unique<SmallVectorMemoryBuffer>(
+        std::move(Buffer), ChildNameOrErr.get());
     Member->MemberName = Member->Buf->getBufferIdentifier();
     NewArchiveMembers.push_back(std::move(*Member));
   }
   if (Err)
-    return createFileError(Config.InputFilename, std::move(Err));
+    return createFileError(Config.getCommonConfig().InputFilename,
+                           std::move(Err));
   return std::move(NewArchiveMembers);
 }
 
 } // end namespace objcopy
 } // end namespace llvm
 
-static Error executeObjcopyOnArchive(CopyConfig &Config,
+static Error executeObjcopyOnArchive(const ConfigManager &ConfigMgr,
                                      const object::Archive &Ar) {
   Expected<std::vector<NewArchiveMember>> NewArchiveMembersOrErr =
-      createNewArchiveMembers(Config, Ar);
+      createNewArchiveMembers(ConfigMgr, Ar);
   if (!NewArchiveMembersOrErr)
     return NewArchiveMembersOrErr.takeError();
+  const CommonConfig &Config = ConfigMgr.getCommonConfig();
   return deepWriteArchive(Config.OutputFilename, *NewArchiveMembersOrErr,
                           Ar.hasSymbolTable(), Ar.kind(),
                           Config.DeterministicArchives, Ar.isThin());
@@ -230,8 +263,9 @@
 
 static Error restoreStatOnFile(StringRef Filename,
                                const sys::fs::file_status &Stat,
-                               bool PreserveDates) {
+                               const ConfigManager &ConfigMgr) {
   int FD;
+  const CommonConfig &Config = ConfigMgr.getCommonConfig();
 
   // Writing to stdout should not be treated as an error here, just
   // do not set access/modification times or permissions.
@@ -242,7 +276,7 @@
           sys::fs::openFileForWrite(Filename, FD, sys::fs::CD_OpenExisting))
     return createFileError(Filename, EC);
 
-  if (PreserveDates)
+  if (Config.PreserveDates)
     if (auto EC = sys::fs::setLastAccessAndModificationTime(
             FD, Stat.getLastAccessedTime(), Stat.getLastModificationTime()))
       return createFileError(Filename, EC);
@@ -250,17 +284,23 @@
   sys::fs::file_status OStat;
   if (std::error_code EC = sys::fs::status(FD, OStat))
     return createFileError(Filename, EC);
-  if (OStat.type() == sys::fs::file_type::regular_file)
+  if (OStat.type() == sys::fs::file_type::regular_file) {
+#ifndef _WIN32
+    // Keep ownership if llvm-objcopy is called under root.
+    if (Config.InputFilename == Config.OutputFilename && OStat.getUser() == 0)
+      sys::fs::changeFileOwnership(FD, Stat.getUser(), Stat.getGroup());
+#endif
+
+    sys::fs::perms Perm = Stat.permissions();
+    if (Config.InputFilename != Config.OutputFilename)
+      Perm = static_cast<sys::fs::perms>(Perm & ~sys::fs::getUmask() & ~06000);
 #ifdef _WIN32
-    if (auto EC = sys::fs::setPermissions(
-            Filename, static_cast<sys::fs::perms>(Stat.permissions() &
-                                                  ~sys::fs::getUmask())))
+    if (auto EC = sys::fs::setPermissions(Filename, Perm))
 #else
-    if (auto EC = sys::fs::setPermissions(
-            FD, static_cast<sys::fs::perms>(Stat.permissions() &
-                                            ~sys::fs::getUmask())))
+    if (auto EC = sys::fs::setPermissions(FD, Perm))
 #endif
       return createFileError(Filename, EC);
+  }
 
   if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD))
     return createFileError(Filename, EC);
@@ -271,7 +311,9 @@
 /// The function executeObjcopy does the higher level dispatch based on the type
 /// of input (raw binary, archive or single object file) and takes care of the
 /// format-agnostic modifications, i.e. preserving dates.
-static Error executeObjcopy(CopyConfig &Config) {
+static Error executeObjcopy(ConfigManager &ConfigMgr) {
+  CommonConfig &Config = ConfigMgr.Common;
+
   sys::fs::file_status Stat;
   if (Config.InputFilename != "-") {
     if (auto EC = sys::fs::status(Config.InputFilename, Stat))
@@ -280,61 +322,85 @@
     Stat.permissions(static_cast<sys::fs::perms>(0777));
   }
 
-  using ProcessRawFn = Error (*)(CopyConfig &, MemoryBuffer &, Buffer &);
-  ProcessRawFn ProcessRaw;
-  switch (Config.InputFormat) {
-  case FileFormat::Binary:
-    ProcessRaw = executeObjcopyOnRawBinary;
-    break;
-  case FileFormat::IHex:
-    ProcessRaw = executeObjcopyOnIHex;
-    break;
-  default:
-    ProcessRaw = nullptr;
-  }
+  std::function<Error(raw_ostream & OutFile)> ObjcopyFunc;
 
-  if (ProcessRaw) {
-    auto BufOrErr = MemoryBuffer::getFileOrSTDIN(Config.InputFilename);
+  OwningBinary<llvm::object::Binary> BinaryHolder;
+  std::unique_ptr<MemoryBuffer> MemoryBufferHolder;
+
+  if (Config.InputFormat == FileFormat::Binary ||
+      Config.InputFormat == FileFormat::IHex) {
+    ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
+        MemoryBuffer::getFileOrSTDIN(Config.InputFilename);
     if (!BufOrErr)
       return createFileError(Config.InputFilename, BufOrErr.getError());
-    FileBuffer FB(Config.OutputFilename);
-    if (Error E = ProcessRaw(Config, *BufOrErr->get(), FB))
-      return E;
+    MemoryBufferHolder = std::move(*BufOrErr);
+
+    if (Config.InputFormat == FileFormat::Binary)
+      ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
+        // Handle FileFormat::Binary.
+        return executeObjcopyOnRawBinary(ConfigMgr, *MemoryBufferHolder,
+                                         OutFile);
+      };
+    else
+      ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
+        // Handle FileFormat::IHex.
+        return executeObjcopyOnIHex(ConfigMgr, *MemoryBufferHolder, OutFile);
+      };
   } else {
     Expected<OwningBinary<llvm::object::Binary>> BinaryOrErr =
         createBinary(Config.InputFilename);
     if (!BinaryOrErr)
       return createFileError(Config.InputFilename, BinaryOrErr.takeError());
+    BinaryHolder = std::move(*BinaryOrErr);
 
-    if (Archive *Ar = dyn_cast<Archive>(BinaryOrErr.get().getBinary())) {
-      if (Error E = executeObjcopyOnArchive(Config, *Ar))
+    if (Archive *Ar = dyn_cast<Archive>(BinaryHolder.getBinary())) {
+      // Handle Archive.
+      if (Error E = executeObjcopyOnArchive(ConfigMgr, *Ar))
         return E;
     } else {
-      FileBuffer FB(Config.OutputFilename);
-      if (Error E = executeObjcopyOnBinary(Config,
-                                           *BinaryOrErr.get().getBinary(), FB))
+      // Handle llvm::object::Binary.
+      ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
+        return executeObjcopyOnBinary(ConfigMgr, *BinaryHolder.getBinary(),
+                                      OutFile);
+      };
+    }
+  }
+
+  if (ObjcopyFunc) {
+    if (Config.SplitDWO.empty()) {
+      // Apply transformations described by Config and store result into
+      // Config.OutputFilename using specified ObjcopyFunc function.
+      if (Error E = writeToOutput(Config.OutputFilename, ObjcopyFunc))
+        return E;
+    } else {
+      Config.ExtractDWO = true;
+      Config.StripDWO = false;
+      // Copy .dwo tables from the Config.InputFilename into Config.SplitDWO
+      // file using specified ObjcopyFunc function.
+      if (Error E = writeToOutput(Config.SplitDWO, ObjcopyFunc))
+        return E;
+      Config.ExtractDWO = false;
+      Config.StripDWO = true;
+      // Apply transformations described by Config, remove .dwo tables and
+      // store result into Config.OutputFilename using specified ObjcopyFunc
+      // function.
+      if (Error E = writeToOutput(Config.OutputFilename, ObjcopyFunc))
         return E;
     }
   }
 
-  if (Error E =
-          restoreStatOnFile(Config.OutputFilename, Stat, Config.PreserveDates))
+  if (Error E = restoreStatOnFile(Config.OutputFilename, Stat, ConfigMgr))
     return E;
 
   if (!Config.SplitDWO.empty()) {
     Stat.permissions(static_cast<sys::fs::perms>(0666));
-    if (Error E =
-            restoreStatOnFile(Config.SplitDWO, Stat, Config.PreserveDates))
+    if (Error E = restoreStatOnFile(Config.SplitDWO, Stat, ConfigMgr))
       return E;
   }
 
   return Error::success();
 }
 
-namespace {
-
-} // anonymous namespace
-
 int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
   ToolName = argv[0];
@@ -360,8 +426,8 @@
                           WithColor::error(errs(), ToolName));
     return 1;
   }
-  for (CopyConfig &CopyConfig : DriverConfig->CopyConfigs) {
-    if (Error E = executeObjcopy(CopyConfig)) {
+  for (ConfigManager &ConfigMgr : DriverConfig->CopyConfigs) {
+    if (Error E = executeObjcopy(ConfigMgr)) {
       logAllUnhandledErrors(std::move(E), WithColor::error(errs(), ToolName));
       return 1;
     }
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.h b/src/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.h
index 97a1667..182c95d 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.h
@@ -10,6 +10,7 @@
 #define LLVM_TOOLS_OBJCOPY_OBJCOPY_H
 
 #include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
 
 namespace llvm {
 
@@ -22,9 +23,10 @@
 } // end namespace object
 
 namespace objcopy {
-struct CopyConfig;
+class MultiFormatConfig;
 Expected<std::vector<NewArchiveMember>>
-createNewArchiveMembers(CopyConfig &Config, const object::Archive &Ar);
+createNewArchiveMembers(const MultiFormatConfig &Config,
+                        const object::Archive &Ar);
 
 } // end namespace objcopy
 } // end namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/wasm/WasmConfig.h b/src/llvm-project/llvm/tools/llvm-objcopy/wasm/WasmConfig.h
new file mode 100644
index 0000000..4e40926
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/wasm/WasmConfig.h
@@ -0,0 +1,21 @@
+//===- WasmConfig.h ---------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_OBJCOPY_WASM_WASMCONFIG_H
+#define LLVM_TOOLS_LLVM_OBJCOPY_WASM_WASMCONFIG_H
+
+namespace llvm {
+namespace objcopy {
+
+// Wasm specific configuration for copying/stripping a single file.
+struct WasmConfig {};
+
+} // namespace objcopy
+} // namespace llvm
+
+#endif // LLVM_TOOLS_LLVM_OBJCOPY_WASM_WASMCONFIG_H
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp
index eb0e563..397d097 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp
@@ -7,18 +7,35 @@
 //===----------------------------------------------------------------------===//
 
 #include "WasmObjcopy.h"
-#include "Buffer.h"
-#include "CopyConfig.h"
+#include "CommonConfig.h"
 #include "Object.h"
 #include "Reader.h"
 #include "Writer.h"
 #include "llvm/Support/Errc.h"
+#include "llvm/Support/FileOutputBuffer.h"
 
 namespace llvm {
 namespace objcopy {
 namespace wasm {
 
 using namespace object;
+using SectionPred = std::function<bool(const Section &Sec)>;
+
+static bool isDebugSection(const Section &Sec) {
+  return Sec.Name.startswith(".debug");
+}
+
+static bool isLinkerSection(const Section &Sec) {
+  return Sec.Name.startswith("reloc.") || Sec.Name == "linking";
+}
+
+static bool isNameSection(const Section &Sec) { return Sec.Name == "name"; }
+
+// Sections which are known to be "comments" or informational and do not affect
+// program semantics.
+static bool isCommentSection(const Section &Sec) {
+  return Sec.Name == "producers";
+}
 
 static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
                                Object &Obj) {
@@ -39,7 +56,60 @@
   return createStringError(errc::invalid_argument, "section '%s' not found",
                            SecName.str().c_str());
 }
-static Error handleArgs(const CopyConfig &Config, Object &Obj) {
+
+static void removeSections(const CommonConfig &Config, Object &Obj) {
+  SectionPred RemovePred = [](const Section &) { return false; };
+
+  // Explicitly-requested sections.
+  if (!Config.ToRemove.empty()) {
+    RemovePred = [&Config](const Section &Sec) {
+      return Config.ToRemove.matches(Sec.Name);
+    };
+  }
+
+  if (Config.StripDebug) {
+    RemovePred = [RemovePred](const Section &Sec) {
+      return RemovePred(Sec) || isDebugSection(Sec);
+    };
+  }
+
+  if (Config.StripAll) {
+    RemovePred = [RemovePred](const Section &Sec) {
+      return RemovePred(Sec) || isDebugSection(Sec) || isLinkerSection(Sec) ||
+             isNameSection(Sec) || isCommentSection(Sec);
+    };
+  }
+
+  if (Config.OnlyKeepDebug) {
+    RemovePred = [&Config](const Section &Sec) {
+      // Keep debug sections, unless explicitly requested to remove.
+      // Remove everything else, including known sections.
+      return Config.ToRemove.matches(Sec.Name) || !isDebugSection(Sec);
+    };
+  }
+
+  if (!Config.OnlySection.empty()) {
+    RemovePred = [&Config](const Section &Sec) {
+      // Explicitly keep these sections regardless of previous removes.
+      // Remove everything else, inluding known sections.
+      return !Config.OnlySection.matches(Sec.Name);
+    };
+  }
+
+  if (!Config.KeepSection.empty()) {
+    RemovePred = [&Config, RemovePred](const Section &Sec) {
+      // Explicitly keep these sections regardless of previous removes.
+      if (Config.KeepSection.matches(Sec.Name))
+        return false;
+      // Otherwise defer to RemovePred.
+      return RemovePred(Sec);
+    };
+  }
+
+  Obj.removeSections(RemovePred);
+}
+
+static Error handleArgs(const CommonConfig &Config, Object &Obj) {
   // Only support AddSection, DumpSection, RemoveSection for now.
   for (StringRef Flag : Config.DumpSection) {
     StringRef SecName;
@@ -49,11 +119,7 @@
       return createFileError(FileName, std::move(E));
   }
 
-  Obj.removeSections([&Config](const Section &Sec) {
-    if (Config.ToRemove.matches(Sec.Name))
-      return true;
-    return false;
-  });
+  removeSections(Config, Obj);
 
   for (StringRef Flag : Config.AddSection) {
     StringRef SecName, FileName;
@@ -72,28 +138,11 @@
     Obj.addSectionWithOwnedContents(Sec, std::move(Buf));
   }
 
-  if (!Config.AddGnuDebugLink.empty() || !Config.BuildIdLinkDir.empty() ||
-      Config.BuildIdLinkInput || Config.BuildIdLinkOutput ||
-      Config.ExtractPartition || !Config.SplitDWO.empty() ||
-      !Config.SymbolsPrefix.empty() || !Config.AllocSectionsPrefix.empty() ||
-      Config.DiscardMode != DiscardType::None || Config.NewSymbolVisibility ||
-      !Config.SymbolsToAdd.empty() || !Config.RPathToAdd.empty() ||
-      !Config.OnlySection.empty() || !Config.SymbolsToGlobalize.empty() ||
-      !Config.SymbolsToKeep.empty() || !Config.SymbolsToLocalize.empty() ||
-      !Config.SymbolsToRemove.empty() ||
-      !Config.UnneededSymbolsToRemove.empty() ||
-      !Config.SymbolsToWeaken.empty() || !Config.SymbolsToKeepGlobal.empty() ||
-      !Config.SectionsToRename.empty() || !Config.SetSectionAlignment.empty() ||
-      !Config.SetSectionFlags.empty() || !Config.SymbolsToRename.empty()) {
-    return createStringError(
-        llvm::errc::invalid_argument,
-        "only add-section, dump-section, and remove-section are supported");
-  }
   return Error::success();
 }
 
-Error executeObjcopyOnBinary(const CopyConfig &Config,
-                             object::WasmObjectFile &In, Buffer &Out) {
+Error executeObjcopyOnBinary(const CommonConfig &Config, const WasmConfig &,
+                             object::WasmObjectFile &In, raw_ostream &Out) {
   Reader TheReader(In);
   Expected<std::unique_ptr<Object>> ObjOrErr = TheReader.create();
   if (!ObjOrErr)
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.h b/src/llvm-project/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.h
index 3557d5c..28268e3 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.h
@@ -11,18 +11,19 @@
 
 namespace llvm {
 class Error;
+class raw_ostream;
 
 namespace object {
 class WasmObjectFile;
 } // end namespace object
 
 namespace objcopy {
-struct CopyConfig;
-class Buffer;
+struct CommonConfig;
+struct WasmConfig;
 
 namespace wasm {
-Error executeObjcopyOnBinary(const CopyConfig &Config,
-                             object::WasmObjectFile &In, Buffer &Out);
+Error executeObjcopyOnBinary(const CommonConfig &Config, const WasmConfig &,
+                             object::WasmObjectFile &In, raw_ostream &Out);
 
 } // end namespace wasm
 } // end namespace objcopy
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/wasm/Writer.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/wasm/Writer.cpp
index 50d2650..2fad9e6 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/wasm/Writer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/wasm/Writer.cpp
@@ -9,6 +9,7 @@
 #include "Writer.h"
 #include "llvm/BinaryFormat/Wasm.h"
 #include "llvm/Support/Endian.h"
+#include "llvm/Support/Errc.h"
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -54,23 +55,23 @@
 }
 
 Error Writer::write() {
-  size_t FileSize = finalize();
-  if (Error E = Buf.allocate(FileSize))
-    return E;
+  size_t TotalSize = finalize();
+  Out.reserveExtraSpace(TotalSize);
 
   // Write the header.
-  uint8_t *Ptr = Buf.getBufferStart();
-  Ptr = std::copy(Obj.Header.Magic.begin(), Obj.Header.Magic.end(), Ptr);
-  support::endian::write32le(Ptr, Obj.Header.Version);
-  Ptr += sizeof(Obj.Header.Version);
+  Out.write(Obj.Header.Magic.data(), Obj.Header.Magic.size());
+  uint32_t Version;
+  support::endian::write32le(&Version, Obj.Header.Version);
+  Out.write(reinterpret_cast<const char *>(&Version), sizeof(Version));
 
   // Write each section.
   for (size_t I = 0, S = SectionHeaders.size(); I < S; ++I) {
-    Ptr = std::copy(SectionHeaders[I].begin(), SectionHeaders[I].end(), Ptr);
-    ArrayRef<uint8_t> Contents = Obj.Sections[I].Contents;
-    Ptr = std::copy(Contents.begin(), Contents.end(), Ptr);
+    Out.write(SectionHeaders[I].data(), SectionHeaders[I].size());
+    Out.write(reinterpret_cast<const char *>(Obj.Sections[I].Contents.data()),
+              Obj.Sections[I].Contents.size());
   }
-  return Buf.commit();
+
+  return Error::success();
 }
 
 } // end namespace wasm
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/wasm/Writer.h b/src/llvm-project/llvm/tools/llvm-objcopy/wasm/Writer.h
index da48ee7..4404cd8 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/wasm/Writer.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/wasm/Writer.h
@@ -9,7 +9,6 @@
 #ifndef LLVM_TOOLS_LLVM_OBJCOPY_WASM_WRITER_H
 #define LLVM_TOOLS_LLVM_OBJCOPY_WASM_WRITER_H
 
-#include "Buffer.h"
 #include "Object.h"
 #include <cstdint>
 #include <vector>
@@ -20,13 +19,13 @@
 
 class Writer {
 public:
-  Writer(Object &Obj, Buffer &Buf) : Obj(Obj), Buf(Buf) {}
+  Writer(Object &Obj, raw_ostream &Out) : Obj(Obj), Out(Out) {}
   Error write();
 
 private:
   using SectionHeader = SmallVector<char, 8>;
   Object &Obj;
-  Buffer &Buf;
+  raw_ostream &Out;
   std::vector<SectionHeader> SectionHeaders;
 
   /// Generate a wasm section section header for S.
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-objdump/CMakeLists.txt
index 91c28dd..149bb3d 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-objdump/CMakeLists.txt
@@ -3,30 +3,44 @@
   AllTargetsDisassemblers
   AllTargetsInfos
   BinaryFormat
-  CodeGen
   DebugInfoDWARF
   DebugInfoPDB
   Demangle
   MC
   MCDisassembler
   Object
+  Option
   Support
   Symbolize
   )
 
+set(LLVM_TARGET_DEFINITIONS ObjdumpOpts.td)
+tablegen(LLVM ObjdumpOpts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(ObjdumpOptsTableGen)
+
+set(LLVM_TARGET_DEFINITIONS OtoolOpts.td)
+tablegen(LLVM OtoolOpts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(OtoolOptsTableGen)
+
 add_llvm_tool(llvm-objdump
   llvm-objdump.cpp
+  SourcePrinter.cpp
   COFFDump.cpp
   ELFDump.cpp
   MachODump.cpp
   WasmDump.cpp
   XCOFFDump.cpp
+  DEPENDS
+  ObjdumpOptsTableGen
+  OtoolOptsTableGen
   )
 
-if(HAVE_LIBXAR)
+if(LLVM_HAVE_LIBXAR)
   target_link_libraries(llvm-objdump PRIVATE ${XAR_LIB})
 endif()
 
+add_llvm_tool_symlink(llvm-otool llvm-objdump)
+
 if(LLVM_INSTALL_BINUTILS_SYMLINKS)
   add_llvm_tool_symlink(objdump llvm-objdump)
 endif()
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp
index b9d69d6..09a9001 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp
@@ -454,8 +454,7 @@
       continue;
 
     const coff_section *Pdata = Obj->getCOFFSection(Section);
-    for (const RelocationRef &Reloc : Section.relocations())
-      Rels.push_back(Reloc);
+    append_range(Rels, Section.relocations());
 
     // Sort relocations by address.
     llvm::sort(Rels, isRelocAddressLess);
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp
index 1c4d591..da74158 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp
@@ -74,7 +74,10 @@
     const typename ELFT::Rela *ERela = Obj->getRela(Rel);
     Addend = ERela->r_addend;
     Undef = ERela->getSymbol(false) == 0;
-  } else if ((*SecOrErr)->sh_type != ELF::SHT_REL) {
+  } else if ((*SecOrErr)->sh_type == ELF::SHT_REL) {
+    const typename ELFT::Rel *ERel = Obj->getRel(Rel);
+    Undef = ERel->getSymbol(false) == 0;
+  } else {
     return make_error<BinaryError>();
   }
 
@@ -177,7 +180,7 @@
     MaxLen = std::max(MaxLen, Elf.getDynamicTagAsString(Dyn.d_tag).size());
   std::string TagFmt = "  %-" + std::to_string(MaxLen) + "s ";
 
-  outs() << "Dynamic Section:\n";
+  outs() << "\nDynamic Section:\n";
   for (const typename ELFT::Dyn &Dyn : DynamicEntries) {
     if (Dyn.d_tag == ELF::DT_NULL)
       continue;
@@ -205,7 +208,7 @@
 
 template <class ELFT>
 static void printProgramHeaders(const ELFFile<ELFT> &Obj, StringRef FileName) {
-  outs() << "Program Header:\n";
+  outs() << "\nProgram Header:\n";
   auto ProgramHeaderOrError = Obj.program_headers();
   if (!ProgramHeaderOrError) {
     reportWarning("unable to read program headers: " +
@@ -272,13 +275,12 @@
            << ((Phdr.p_flags & ELF::PF_W) ? "w" : "-")
            << ((Phdr.p_flags & ELF::PF_X) ? "x" : "-") << "\n";
   }
-  outs() << "\n";
 }
 
 template <class ELFT>
 static void printSymbolVersionDependency(ArrayRef<uint8_t> Contents,
                                          StringRef StrTab) {
-  outs() << "Version References:\n";
+  outs() << "\nVersion References:\n";
 
   const uint8_t *Buf = Contents.data();
   while (Buf) {
@@ -304,7 +306,7 @@
 static void printSymbolVersionDefinition(const typename ELFT::Shdr &Shdr,
                                          ArrayRef<uint8_t> Contents,
                                          StringRef StrTab) {
-  outs() << "Version definitions:\n";
+  outs() << "\nVersion definitions:\n";
 
   const uint8_t *Buf = Contents.data();
   uint32_t VerdefIndex = 1;
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp
index 51212d5..7c1fdf0 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp
@@ -12,6 +12,7 @@
 
 #include "MachODump.h"
 
+#include "ObjdumpOptID.h"
 #include "llvm-objdump.h"
 #include "llvm-c/Disassembler.h"
 #include "llvm/ADT/STLExtras.h"
@@ -34,8 +35,8 @@
 #include "llvm/MC/MCTargetOptions.h"
 #include "llvm/Object/MachO.h"
 #include "llvm/Object/MachOUniversal.h"
+#include "llvm/Option/ArgList.h"
 #include "llvm/Support/Casting.h"
-#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Format.h"
@@ -52,7 +53,7 @@
 #include <cstring>
 #include <system_error>
 
-#ifdef HAVE_LIBXAR
+#ifdef LLVM_HAVE_LIBXAR
 extern "C" {
 #include <xar/xar.h>
 }
@@ -62,125 +63,63 @@
 using namespace llvm::object;
 using namespace llvm::objdump;
 
-cl::OptionCategory objdump::MachOCat("llvm-objdump MachO Specific Options");
-
-cl::opt<bool> objdump::FirstPrivateHeader(
-    "private-header",
-    cl::desc("Display only the first format specific file header"),
-    cl::cat(MachOCat));
-
-cl::opt<bool> objdump::ExportsTrie("exports-trie",
-                                   cl::desc("Display mach-o exported symbols"),
-                                   cl::cat(MachOCat));
-
-cl::opt<bool> objdump::Rebase("rebase",
-                              cl::desc("Display mach-o rebasing info"),
-                              cl::cat(MachOCat));
-
-cl::opt<bool> objdump::Bind("bind", cl::desc("Display mach-o binding info"),
-                            cl::cat(MachOCat));
-
-cl::opt<bool> objdump::LazyBind("lazy-bind",
-                                cl::desc("Display mach-o lazy binding info"),
-                                cl::cat(MachOCat));
-
-cl::opt<bool> objdump::WeakBind("weak-bind",
-                                cl::desc("Display mach-o weak binding info"),
-                                cl::cat(MachOCat));
-
-static cl::opt<bool>
-    UseDbg("g", cl::Grouping,
-           cl::desc("Print line information from debug info if available"),
-           cl::cat(MachOCat));
-
-static cl::opt<std::string> DSYMFile("dsym",
-                                     cl::desc("Use .dSYM file for debug info"),
-                                     cl::cat(MachOCat));
-
-static cl::opt<bool> FullLeadingAddr("full-leading-addr",
-                                     cl::desc("Print full leading address"),
-                                     cl::cat(MachOCat));
-
-static cl::opt<bool> NoLeadingHeaders("no-leading-headers",
-                                      cl::desc("Print no leading headers"),
-                                      cl::cat(MachOCat));
-
-cl::opt<bool> objdump::UniversalHeaders(
-    "universal-headers",
-    cl::desc("Print Mach-O universal headers (requires --macho)"),
-    cl::cat(MachOCat));
-
-static cl::opt<bool> ArchiveMemberOffsets(
-    "archive-member-offsets",
-    cl::desc("Print the offset to each archive member for Mach-O archives "
-             "(requires --macho and --archive-headers)"),
-    cl::cat(MachOCat));
-
-cl::opt<bool> objdump::IndirectSymbols(
-    "indirect-symbols",
-    cl::desc(
-        "Print indirect symbol table for Mach-O objects (requires --macho)"),
-    cl::cat(MachOCat));
-
-cl::opt<bool> objdump::DataInCode(
-    "data-in-code",
-    cl::desc(
-        "Print the data in code table for Mach-O objects (requires --macho)"),
-    cl::cat(MachOCat));
-
-cl::opt<bool>
-    objdump::LinkOptHints("link-opt-hints",
-                          cl::desc("Print the linker optimization hints for "
-                                   "Mach-O objects (requires --macho)"),
-                          cl::cat(MachOCat));
-
-cl::opt<bool>
-    objdump::InfoPlist("info-plist",
-                       cl::desc("Print the info plist section as strings for "
-                                "Mach-O objects (requires --macho)"),
-                       cl::cat(MachOCat));
-
-cl::opt<bool>
-    objdump::DylibsUsed("dylibs-used",
-                        cl::desc("Print the shared libraries used for linked "
-                                 "Mach-O files (requires --macho)"),
-                        cl::cat(MachOCat));
-
-cl::opt<bool> objdump::DylibId("dylib-id",
-                               cl::desc("Print the shared library's id for the "
-                                        "dylib Mach-O file (requires --macho)"),
-                               cl::cat(MachOCat));
-
-static cl::opt<bool>
-    NonVerbose("non-verbose",
-               cl::desc("Print the info for Mach-O objects in non-verbose or "
-                        "numeric form (requires --macho)"),
-               cl::cat(MachOCat));
-
-cl::opt<bool>
-    objdump::ObjcMetaData("objc-meta-data",
-                          cl::desc("Print the Objective-C runtime meta data "
-                                   "for Mach-O files (requires --macho)"),
-                          cl::cat(MachOCat));
-
-static cl::opt<std::string> DisSymName(
-    "dis-symname",
-    cl::desc("disassemble just this symbol's instructions (requires --macho)"),
-    cl::cat(MachOCat));
-
-static cl::opt<bool> NoSymbolicOperands(
-    "no-symbolic-operands",
-    cl::desc("do not symbolic operands when disassembling (requires --macho)"),
-    cl::cat(MachOCat));
-
-static cl::list<std::string>
-    ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
-              cl::ZeroOrMore, cl::cat(MachOCat));
+bool objdump::FirstPrivateHeader;
+bool objdump::ExportsTrie;
+bool objdump::Rebase;
+bool objdump::Rpaths;
+bool objdump::Bind;
+bool objdump::LazyBind;
+bool objdump::WeakBind;
+static bool UseDbg;
+static std::string DSYMFile;
+bool objdump::FullLeadingAddr;
+bool objdump::LeadingHeaders;
+bool objdump::UniversalHeaders;
+static bool ArchiveMemberOffsets;
+bool objdump::IndirectSymbols;
+bool objdump::DataInCode;
+bool objdump::FunctionStarts;
+bool objdump::LinkOptHints;
+bool objdump::InfoPlist;
+bool objdump::DylibsUsed;
+bool objdump::DylibId;
+bool objdump::Verbose;
+bool objdump::ObjcMetaData;
+std::string objdump::DisSymName;
+bool objdump::SymbolicOperands;
+static std::vector<std::string> ArchFlags;
 
 static bool ArchAll = false;
-
 static std::string ThumbTripleName;
 
+void objdump::parseMachOOptions(const llvm::opt::InputArgList &InputArgs) {
+  FirstPrivateHeader = InputArgs.hasArg(OBJDUMP_private_header);
+  ExportsTrie = InputArgs.hasArg(OBJDUMP_exports_trie);
+  Rebase = InputArgs.hasArg(OBJDUMP_rebase);
+  Rpaths = InputArgs.hasArg(OBJDUMP_rpaths);
+  Bind = InputArgs.hasArg(OBJDUMP_bind);
+  LazyBind = InputArgs.hasArg(OBJDUMP_lazy_bind);
+  WeakBind = InputArgs.hasArg(OBJDUMP_weak_bind);
+  UseDbg = InputArgs.hasArg(OBJDUMP_g);
+  DSYMFile = InputArgs.getLastArgValue(OBJDUMP_dsym_EQ).str();
+  FullLeadingAddr = InputArgs.hasArg(OBJDUMP_full_leading_addr);
+  LeadingHeaders = !InputArgs.hasArg(OBJDUMP_no_leading_headers);
+  UniversalHeaders = InputArgs.hasArg(OBJDUMP_universal_headers);
+  ArchiveMemberOffsets = InputArgs.hasArg(OBJDUMP_archive_member_offsets);
+  IndirectSymbols = InputArgs.hasArg(OBJDUMP_indirect_symbols);
+  DataInCode = InputArgs.hasArg(OBJDUMP_data_in_code);
+  FunctionStarts = InputArgs.hasArg(OBJDUMP_function_starts);
+  LinkOptHints = InputArgs.hasArg(OBJDUMP_link_opt_hints);
+  InfoPlist = InputArgs.hasArg(OBJDUMP_info_plist);
+  DylibsUsed = InputArgs.hasArg(OBJDUMP_dylibs_used);
+  DylibId = InputArgs.hasArg(OBJDUMP_dylib_id);
+  Verbose = !InputArgs.hasArg(OBJDUMP_non_verbose);
+  ObjcMetaData = InputArgs.hasArg(OBJDUMP_objc_meta_data);
+  DisSymName = InputArgs.getLastArgValue(OBJDUMP_dis_symname).str();
+  SymbolicOperands = !InputArgs.hasArg(OBJDUMP_no_symbolic_operands);
+  ArchFlags = InputArgs.getAllArgValues(OBJDUMP_arch_EQ);
+}
+
 static const Target *GetTarget(const MachOObjectFile *MachOObj,
                                const char **McpuDefault,
                                const Target **ThumbTarget) {
@@ -245,7 +184,7 @@
 typedef std::vector<DiceTableEntry> DiceTable;
 typedef DiceTable::iterator dice_table_iterator;
 
-#ifdef HAVE_LIBXAR
+#ifdef LLVM_HAVE_LIBXAR
 namespace {
 struct ScopedXarFile {
   xar_t xar;
@@ -272,7 +211,7 @@
   operator xar_iter_t() { return iter; }
 };
 } // namespace
-#endif // defined(HAVE_LIBXAR)
+#endif // defined(LLVM_HAVE_LIBXAR)
 
 // This is used to search for a data in code table entry for the PC being
 // disassembled.  The j parameter has the PC in j.first.  A single data in code
@@ -296,19 +235,19 @@
   default:
   case MachO::DICE_KIND_DATA:
     if (Length >= 4) {
-      if (!NoShowRawInsn)
+      if (ShowRawInsn)
         dumpBytes(makeArrayRef(bytes, 4), outs());
       Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
       outs() << "\t.long " << Value;
       Size = 4;
     } else if (Length >= 2) {
-      if (!NoShowRawInsn)
+      if (ShowRawInsn)
         dumpBytes(makeArrayRef(bytes, 2), outs());
       Value = bytes[1] << 8 | bytes[0];
       outs() << "\t.short " << Value;
       Size = 2;
     } else {
-      if (!NoShowRawInsn)
+      if (ShowRawInsn)
         dumpBytes(makeArrayRef(bytes, 2), outs());
       Value = bytes[0];
       outs() << "\t.byte " << Value;
@@ -320,14 +259,14 @@
       outs() << "\t@ data in code kind = " << Kind << "\n";
     break;
   case MachO::DICE_KIND_JUMP_TABLE8:
-    if (!NoShowRawInsn)
+    if (ShowRawInsn)
       dumpBytes(makeArrayRef(bytes, 1), outs());
     Value = bytes[0];
     outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
     Size = 1;
     break;
   case MachO::DICE_KIND_JUMP_TABLE16:
-    if (!NoShowRawInsn)
+    if (ShowRawInsn)
       dumpBytes(makeArrayRef(bytes, 2), outs());
     Value = bytes[1] << 8 | bytes[0];
     outs() << "\t.short " << format("%5u", Value & 0xffff)
@@ -336,7 +275,7 @@
     break;
   case MachO::DICE_KIND_JUMP_TABLE32:
   case MachO::DICE_KIND_ABS_JUMP_TABLE32:
-    if (!NoShowRawInsn)
+    if (ShowRawInsn)
       dumpBytes(makeArrayRef(bytes, 4), outs());
     Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
     outs() << "\t.long " << Value;
@@ -362,8 +301,7 @@
       Symbols.push_back(Symbol);
   }
 
-  for (const SectionRef &Section : MachOObj->sections())
-    Sections.push_back(Section);
+  append_range(Sections, MachOObj->sections());
 
   bool BaseSegmentAddressSet = false;
   for (const auto &Command : MachOObj->load_commands()) {
@@ -461,7 +399,7 @@
 
   if (isExtern) {
     symbol_iterator SI = O->symbol_begin();
-    advance(SI, Val);
+    std::advance(SI, Val);
     S = unwrapOrError(SI->getName(), FileName);
   } else {
     section_iterator SI = O->section_begin();
@@ -473,7 +411,7 @@
     uint32_t I = Val - 1;
     while (I != 0 && SI != O->section_end()) {
       --I;
-      advance(SI, 1);
+      std::advance(SI, 1);
     }
     if (SI == O->section_end()) {
       Fmt << Val << " (?,?)";
@@ -1104,6 +1042,43 @@
   }
 }
 
+static void PrintFunctionStarts(MachOObjectFile *O) {
+  uint64_t BaseSegmentAddress = 0;
+  for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) {
+    if (Command.C.cmd == MachO::LC_SEGMENT) {
+      MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
+      if (StringRef(SLC.segname) == "__TEXT") {
+        BaseSegmentAddress = SLC.vmaddr;
+        break;
+      }
+    } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
+      MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command);
+      if (StringRef(SLC.segname) == "__TEXT") {
+        BaseSegmentAddress = SLC.vmaddr;
+        break;
+      }
+    }
+  }
+
+  SmallVector<uint64_t, 8> FunctionStarts;
+  for (const MachOObjectFile::LoadCommandInfo &LC : O->load_commands()) {
+    if (LC.C.cmd == MachO::LC_FUNCTION_STARTS) {
+      MachO::linkedit_data_command FunctionStartsLC =
+          O->getLinkeditDataLoadCommand(LC);
+      O->ReadULEB128s(FunctionStartsLC.dataoff, FunctionStarts);
+      break;
+    }
+  }
+
+  for (uint64_t S : FunctionStarts) {
+    uint64_t Addr = BaseSegmentAddress + S;
+    if (O->is64Bit())
+      outs() << format("%016" PRIx64, Addr) << "\n";
+    else
+      outs() << format("%08" PRIx32, static_cast<uint32_t>(Addr)) << "\n";
+  }
+}
+
 static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {
   MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();
   uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry);
@@ -1260,6 +1235,16 @@
   }
 }
 
+static void printRpaths(MachOObjectFile *O) {
+  for (const auto &Command : O->load_commands()) {
+    if (Command.C.cmd == MachO::LC_RPATH) {
+      auto Rpath = O->getRpathCommand(Command);
+      const char *P = (const char *)(Command.Ptr) + Rpath.path;
+      outs() << P << "\n";
+    }
+  }
+}
+
 typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
 
 static void CreateSymbolAddressMap(MachOObjectFile *O,
@@ -1712,12 +1697,12 @@
                              StringRef DisSegName, StringRef DisSectName);
 static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
                                 uint32_t size, uint32_t addr);
-#ifdef HAVE_LIBXAR
+#ifdef LLVM_HAVE_LIBXAR
 static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
                                 uint32_t size, bool verbose,
                                 bool PrintXarHeader, bool PrintXarFileHeaders,
                                 std::string XarMemberName);
-#endif // defined(HAVE_LIBXAR)
+#endif // defined(LLVM_HAVE_LIBXAR)
 
 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
                                 bool verbose) {
@@ -1770,7 +1755,7 @@
         uint32_t sect_size = BytesStr.size();
         uint64_t sect_addr = Section.getAddress();
 
-        if (!NoLeadingHeaders)
+        if (LeadingHeaders)
           outs() << "Contents of (" << SegName << "," << SectName
                  << ") section\n";
 
@@ -1788,13 +1773,13 @@
             DumpProtocolSection(O, sect, sect_size, sect_addr);
             continue;
           }
-#ifdef HAVE_LIBXAR
+#ifdef LLVM_HAVE_LIBXAR
           if (SegName == "__LLVM" && SectName == "__bundle") {
-            DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands,
+            DumpBitcodeSection(O, sect, sect_size, verbose, SymbolicOperands,
                                ArchiveHeaders, "");
             continue;
           }
-#endif // defined(HAVE_LIBXAR)
+#endif // defined(LLVM_HAVE_LIBXAR)
           switch (section_type) {
           case MachO::S_REGULAR:
             DumpRawSectionContents(O, sect, sect_size, sect_addr);
@@ -1803,20 +1788,20 @@
             outs() << "zerofill section and has no contents in the file\n";
             break;
           case MachO::S_CSTRING_LITERALS:
-            DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr);
+            DumpCstringSection(O, sect, sect_size, sect_addr, LeadingAddr);
             break;
           case MachO::S_4BYTE_LITERALS:
-            DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
+            DumpLiteral4Section(O, sect, sect_size, sect_addr, LeadingAddr);
             break;
           case MachO::S_8BYTE_LITERALS:
-            DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
+            DumpLiteral8Section(O, sect, sect_size, sect_addr, LeadingAddr);
             break;
           case MachO::S_16BYTE_LITERALS:
-            DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
+            DumpLiteral16Section(O, sect, sect_size, sect_addr, LeadingAddr);
             break;
           case MachO::S_LITERAL_POINTERS:
             DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr,
-                                      !NoLeadingAddr);
+                                      LeadingAddr);
             break;
           case MachO::S_MOD_INIT_FUNC_POINTERS:
           case MachO::S_MOD_TERM_FUNC_POINTERS:
@@ -1853,7 +1838,7 @@
     DataRefImpl Ref = Section.getRawDataRefImpl();
     StringRef SegName = O->getSectionFinalSegmentName(Ref);
     if (SegName == "__TEXT" && SectName == "__info_plist") {
-      if (!NoLeadingHeaders)
+      if (LeadingHeaders)
         outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
       StringRef BytesStr =
           unwrapOrError(Section.getContents(), O->getFileName());
@@ -1911,9 +1896,9 @@
   // UniversalHeaders or ArchiveHeaders.
   if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase ||
       Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols ||
-      DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData ||
-      (!FilterSections.empty())) {
-    if (!NoLeadingHeaders) {
+      DataInCode || FunctionStarts || LinkOptHints || DylibsUsed || DylibId ||
+      Rpaths || ObjcMetaData || (!FilterSections.empty())) {
+    if (LeadingHeaders) {
       outs() << Name;
       if (!ArchiveMemberName.empty())
         outs() << '(' << ArchiveMemberName << ')';
@@ -1964,19 +1949,21 @@
       DisassembleMachO(FileName, MachOOF, "__TEXT", "__text");
   }
   if (IndirectSymbols)
-    PrintIndirectSymbols(MachOOF, !NonVerbose);
+    PrintIndirectSymbols(MachOOF, Verbose);
   if (DataInCode)
-    PrintDataInCodeTable(MachOOF, !NonVerbose);
+    PrintDataInCodeTable(MachOOF, Verbose);
+  if (FunctionStarts)
+    PrintFunctionStarts(MachOOF);
   if (LinkOptHints)
     PrintLinkOptHints(MachOOF);
   if (Relocations)
-    PrintRelocations(MachOOF, !NonVerbose);
+    PrintRelocations(MachOOF, Verbose);
   if (SectionHeaders)
     printSectionHeaders(MachOOF);
   if (SectionContents)
     printSectionContents(MachOOF);
   if (!FilterSections.empty())
-    DumpSectionContents(FileName, MachOOF, !NonVerbose);
+    DumpSectionContents(FileName, MachOOF, Verbose);
   if (InfoPlist)
     DumpInfoPlistSectionContents(FileName, MachOOF);
   if (DylibsUsed)
@@ -1994,11 +1981,13 @@
   if (FirstPrivateHeader)
     printMachOFileHeader(MachOOF);
   if (ObjcMetaData)
-    printObjcMetaData(MachOOF, !NonVerbose);
+    printObjcMetaData(MachOOF, Verbose);
   if (ExportsTrie)
     printExportsTrie(MachOOF);
   if (Rebase)
     printRebaseTable(MachOOF);
+  if (Rpaths)
+    printRpaths(MachOOF);
   if (Bind)
     printBindTable(MachOOF);
   if (LazyBind)
@@ -2333,7 +2322,7 @@
   if (Archive *A = dyn_cast<Archive>(&Bin)) {
     outs() << "Archive : " << Filename << "\n";
     if (ArchiveHeaders)
-      printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets);
+      printArchiveHeaders(Filename, A, Verbose, ArchiveMemberOffsets);
 
     Error Err = Error::success();
     unsigned I = -1;
@@ -2380,7 +2369,7 @@
   auto Filename = UB->getFileName();
 
   if (UniversalHeaders)
-    printMachOUniversalHeaders(UB, !NonVerbose);
+    printMachOUniversalHeaders(UB, Verbose);
 
   // If we have a list of architecture flags specified dump only those.
   if (!ArchAll && !ArchFlags.empty()) {
@@ -2414,7 +2403,7 @@
               outs() << " (architecture " << ArchitectureName << ")";
             outs() << "\n";
             if (ArchiveHeaders)
-              printArchiveHeaders(Filename, A.get(), !NonVerbose,
+              printArchiveHeaders(Filename, A.get(), Verbose,
                                   ArchiveMemberOffsets, ArchitectureName);
             Error Err = Error::success();
             unsigned I = -1;
@@ -2475,7 +2464,7 @@
           std::unique_ptr<Archive> &A = *AOrErr;
           outs() << "Archive : " << Filename << "\n";
           if (ArchiveHeaders)
-            printArchiveHeaders(Filename, A.get(), !NonVerbose,
+            printArchiveHeaders(Filename, A.get(), Verbose,
                                 ArchiveMemberOffsets);
           Error Err = Error::success();
           unsigned I = -1;
@@ -2528,8 +2517,8 @@
         outs() << " (architecture " << ArchitectureName << ")";
       outs() << "\n";
       if (ArchiveHeaders)
-        printArchiveHeaders(Filename, A.get(), !NonVerbose,
-                            ArchiveMemberOffsets, ArchitectureName);
+        printArchiveHeaders(Filename, A.get(), Verbose, ArchiveMemberOffsets,
+                            ArchitectureName);
       Error Err = Error::success();
       unsigned I = -1;
       for (auto &C : A->children(Err)) {
@@ -6115,8 +6104,7 @@
     CreateSymbolAddressMap(O, &AddrMap);
 
   std::vector<SectionRef> Sections;
-  for (const SectionRef &Section : O->sections())
-    Sections.push_back(Section);
+  append_range(Sections, O->sections());
 
   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
 
@@ -6197,8 +6185,7 @@
     CreateSymbolAddressMap(O, &AddrMap);
 
   std::vector<SectionRef> Sections;
-  for (const SectionRef &Section : O->sections())
-    Sections.push_back(Section);
+  append_range(Sections, O->sections());
 
   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
 
@@ -6292,8 +6279,7 @@
     CreateSymbolAddressMap(O, &AddrMap);
 
   std::vector<SectionRef> Sections;
-  for (const SectionRef &Section : O->sections())
-    Sections.push_back(Section);
+  append_range(Sections, O->sections());
 
   struct DisassembleInfo info(O, &AddrMap, &Sections, verbose);
 
@@ -6450,8 +6436,7 @@
   CreateSymbolAddressMap(O, &AddrMap);
 
   std::vector<SectionRef> Sections;
-  for (const SectionRef &Section : O->sections())
-    Sections.push_back(Section);
+  append_range(Sections, O->sections());
 
   struct DisassembleInfo info(O, &AddrMap, &Sections, true);
 
@@ -6475,7 +6460,7 @@
   }
 }
 
-#ifdef HAVE_LIBXAR
+#ifdef LLVM_HAVE_LIBXAR
 static inline void swapStruct(struct xar_header &xar) {
   sys::swapByteOrder(xar.magic);
   sys::swapByteOrder(xar.size);
@@ -6838,7 +6823,7 @@
     }
   }
 }
-#endif // defined(HAVE_LIBXAR)
+#endif // defined(LLVM_HAVE_LIBXAR)
 
 static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
   if (O->is64Bit())
@@ -7165,17 +7150,15 @@
   // Get the default information for printing a comment.
   StringRef CommentBegin = MAI.getCommentString();
   unsigned CommentColumn = MAI.getCommentColumn();
-  bool IsFirst = true;
+  ListSeparator LS("\n");
   while (!Comments.empty()) {
-    if (!IsFirst)
-      FormattedOS << '\n';
+    FormattedOS << LS;
     // Emit a line of comments.
     FormattedOS.PadToColumn(CommentColumn);
     size_t Position = Comments.find('\n');
     FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
     // Move after the newline character.
     Comments = Comments.substr(Position + 1);
-    IsFirst = false;
   }
   FormattedOS.flush();
 
@@ -7245,7 +7228,7 @@
   std::unique_ptr<const MCSubtargetInfo> STI(
       TheTarget->createMCSubtargetInfo(TripleName, MachOMCPU, FeaturesStr));
   CHECK_TARGET_INFO_CREATION(STI);
-  MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr);
+  MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get());
   std::unique_ptr<MCDisassembler> DisAsm(
       TheTarget->createMCDisassembler(*STI, Ctx));
   CHECK_TARGET_INFO_CREATION(DisAsm);
@@ -7295,7 +7278,8 @@
         ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MachOMCPU,
                                            FeaturesStr));
     CHECK_THUMB_TARGET_INFO_CREATION(ThumbSTI);
-    ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr));
+    ThumbCtx.reset(new MCContext(Triple(ThumbTripleName), ThumbAsmInfo.get(),
+                                 ThumbMRI.get(), ThumbSTI.get()));
     ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx));
     CHECK_THUMB_TARGET_INFO_CREATION(ThumbDisAsm);
     MCContext *PtrThumbCtx = ThumbCtx.get();
@@ -7334,7 +7318,7 @@
                         BaseSegmentAddress);
 
   // Sort the symbols by address, just in case they didn't come in that way.
-  llvm::sort(Symbols, SymbolSorter());
+  llvm::stable_sort(Symbols, SymbolSorter());
 
   // Build a data in code table that is sorted on by the address of each entry.
   uint64_t BaseAddress = 0;
@@ -7489,13 +7473,13 @@
       return;
     }
     // Set up the block of info used by the Symbolizer call backs.
-    SymbolizerInfo.verbose = !NoSymbolicOperands;
+    SymbolizerInfo.verbose = SymbolicOperands;
     SymbolizerInfo.O = MachOOF;
     SymbolizerInfo.S = Sections[SectIdx];
     SymbolizerInfo.AddrMap = &AddrMap;
     SymbolizerInfo.Sections = &Sections;
     // Same for the ThumbSymbolizer
-    ThumbSymbolizerInfo.verbose = !NoSymbolicOperands;
+    ThumbSymbolizerInfo.verbose = SymbolicOperands;
     ThumbSymbolizerInfo.O = MachOOF;
     ThumbSymbolizerInfo.S = Sections[SectIdx];
     ThumbSymbolizerInfo.AddrMap = &AddrMap;
@@ -7620,7 +7604,7 @@
           outs() << SymName << ":\n";
 
         uint64_t PC = SectAddress + Index;
-        if (!NoLeadingAddr) {
+        if (LeadingAddr) {
           if (FullLeadingAddr) {
             if (MachOOF->is64Bit())
               outs() << format("%016" PRIx64, PC);
@@ -7630,7 +7614,7 @@
             outs() << format("%8" PRIx64 ":", PC);
           }
         }
-        if (!NoShowRawInsn || Arch == Triple::arm)
+        if (ShowRawInsn || Arch == Triple::arm)
           outs() << "\t";
 
         if (DumpAndSkipDataInCode(PC, Bytes.data() + Index, Dices, Size))
@@ -7647,7 +7631,7 @@
           gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC,
                                            Annotations);
         if (gotInst) {
-          if (!NoShowRawInsn || Arch == Triple::arm) {
+          if (ShowRawInsn || Arch == Triple::arm) {
             dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs());
           }
           formatted_raw_ostream FormattedOS(outs());
@@ -7717,7 +7701,7 @@
         raw_svector_ostream Annotations(AnnotationsBytes);
         if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC,
                                    Annotations)) {
-          if (!NoLeadingAddr) {
+          if (LeadingAddr) {
             if (FullLeadingAddr) {
               if (MachOOF->is64Bit())
                 outs() << format("%016" PRIx64, PC);
@@ -7727,7 +7711,7 @@
               outs() << format("%8" PRIx64 ":", PC);
             }
           }
-          if (!NoShowRawInsn || Arch == Triple::arm) {
+          if (ShowRawInsn || Arch == Triple::arm) {
             outs() << "\t";
             dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs());
           }
@@ -8012,12 +7996,23 @@
   (void)Kind;
   assert(Kind == 3 && "kind for a compressed 2nd level index should be 3");
 
+  uint32_t NumCommonEncodings = CommonEncodings.size();
   uint16_t EntriesStart = readNext<uint16_t>(PageData, Pos);
   uint16_t NumEntries = readNext<uint16_t>(PageData, Pos);
 
-  uint16_t EncodingsStart = readNext<uint16_t>(PageData, Pos);
-  readNext<uint16_t>(PageData, Pos);
-  StringRef PageEncodings = PageData.substr(EncodingsStart, StringRef::npos);
+  uint16_t PageEncodingsStart = readNext<uint16_t>(PageData, Pos);
+  uint16_t NumPageEncodings = readNext<uint16_t>(PageData, Pos);
+  SmallVector<uint32_t, 64> PageEncodings;
+  if (NumPageEncodings) {
+    outs() << "      Page encodings: (count = " << NumPageEncodings << ")\n";
+    Pos = PageEncodingsStart;
+    for (unsigned i = 0; i < NumPageEncodings; ++i) {
+      uint32_t Encoding = readNext<uint32_t>(PageData, Pos);
+      PageEncodings.push_back(Encoding);
+      outs() << "        encoding[" << (i + NumCommonEncodings)
+             << "]: " << format("0x%08" PRIx32, Encoding) << '\n';
+    }
+  }
 
   Pos = EntriesStart;
   for (unsigned i = 0; i < NumEntries; ++i) {
@@ -8026,12 +8021,10 @@
     uint32_t EncodingIdx = Entry >> 24;
 
     uint32_t Encoding;
-    if (EncodingIdx < CommonEncodings.size())
+    if (EncodingIdx < NumCommonEncodings)
       Encoding = CommonEncodings[EncodingIdx];
     else
-      Encoding = read<uint32_t>(PageEncodings,
-                                sizeof(uint32_t) *
-                                    (EncodingIdx - CommonEncodings.size()));
+      Encoding = PageEncodings[EncodingIdx - NumCommonEncodings];
 
     outs() << "      [" << i << "]: "
            << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
@@ -10233,7 +10226,7 @@
 
 void objdump::printMachOFileHeader(const object::ObjectFile *Obj) {
   const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
-  PrintMachHeader(file, !NonVerbose);
+  PrintMachHeader(file, Verbose);
 }
 
 void objdump::printMachOLoadCommands(const object::ObjectFile *Obj) {
@@ -10251,7 +10244,7 @@
     filetype = H.filetype;
     cputype = H.cputype;
   }
-  PrintLoadCommands(file, filetype, cputype, !NonVerbose);
+  PrintLoadCommands(file, filetype, cputype, Verbose);
 }
 
 //===----------------------------------------------------------------------===//
@@ -10292,30 +10285,16 @@
                        Entry.address() + BaseSegmentAddress);
     outs() << Entry.name();
     if (WeakDef || ThreadLocal || Resolver || Abs) {
-      bool NeedsComma = false;
+      ListSeparator LS;
       outs() << " [";
-      if (WeakDef) {
-        outs() << "weak_def";
-        NeedsComma = true;
-      }
-      if (ThreadLocal) {
-        if (NeedsComma)
-          outs() << ", ";
-        outs() << "per-thread";
-        NeedsComma = true;
-      }
-      if (Abs) {
-        if (NeedsComma)
-          outs() << ", ";
-        outs() << "absolute";
-        NeedsComma = true;
-      }
-      if (Resolver) {
-        if (NeedsComma)
-          outs() << ", ";
-        outs() << format("resolver=0x%08llX", Entry.other());
-        NeedsComma = true;
-      }
+      if (WeakDef)
+        outs() << LS << "weak_def";
+      if (ThreadLocal)
+        outs() << LS << "per-thread";
+      if (Abs)
+        outs() << LS << "absolute";
+      if (Resolver)
+        outs() << LS << format("resolver=0x%08llX", Entry.other());
       outs() << "]";
     }
     if (ReExport) {
@@ -10486,7 +10465,7 @@
 }
 
 void objdump::printLazyBindTable(ObjectFile *o) {
-  outs() << "Lazy bind table:\n";
+  outs() << "\nLazy bind table:\n";
   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
     printMachOLazyBindTable(MachO);
   else
@@ -10496,7 +10475,7 @@
 }
 
 void objdump::printWeakBindTable(ObjectFile *o) {
-  outs() << "Weak bind table:\n";
+  outs() << "\nWeak bind table:\n";
   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
     printMachOWeakBindTable(MachO);
   else
@@ -10506,7 +10485,7 @@
 }
 
 void objdump::printExportsTrie(const ObjectFile *o) {
-  outs() << "Exports trie:\n";
+  outs() << "\nExports trie:\n";
   if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
     printMachOExportsTrie(MachO);
   else
@@ -10516,7 +10495,7 @@
 }
 
 void objdump::printRebaseTable(ObjectFile *o) {
-  outs() << "Rebase table:\n";
+  outs() << "\nRebase table:\n";
   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
     printMachORebaseTable(MachO);
   else
@@ -10526,7 +10505,7 @@
 }
 
 void objdump::printBindTable(ObjectFile *o) {
-  outs() << "Bind table:\n";
+  outs() << "\nBind table:\n";
   if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))
     printMachOBindTable(MachO);
   else
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/MachODump.h b/src/llvm-project/llvm/tools/llvm-objdump/MachODump.h
index adf6c34..7568062 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/MachODump.h
+++ b/src/llvm-project/llvm/tools/llvm-objdump/MachODump.h
@@ -24,24 +24,36 @@
 class RelocationRef;
 } // namespace object
 
+namespace opt {
+class InputArgList;
+} // namespace opt
+
 namespace objdump {
 
+void parseMachOOptions(const llvm::opt::InputArgList &InputArgs);
+
 // MachO specific options
-extern cl::OptionCategory MachOCat;
-extern cl::opt<bool> Bind;
-extern cl::opt<bool> DataInCode;
-extern cl::opt<bool> DylibsUsed;
-extern cl::opt<bool> DylibId;
-extern cl::opt<bool> ExportsTrie;
-extern cl::opt<bool> FirstPrivateHeader;
-extern cl::opt<bool> IndirectSymbols;
-extern cl::opt<bool> InfoPlist;
-extern cl::opt<bool> LazyBind;
-extern cl::opt<bool> LinkOptHints;
-extern cl::opt<bool> ObjcMetaData;
-extern cl::opt<bool> Rebase;
-extern cl::opt<bool> UniversalHeaders;
-extern cl::opt<bool> WeakBind;
+extern bool Bind;
+extern bool DataInCode;
+extern std::string DisSymName;
+extern bool DylibId;
+extern bool DylibsUsed;
+extern bool ExportsTrie;
+extern bool FirstPrivateHeader;
+extern bool FullLeadingAddr;
+extern bool FunctionStarts;
+extern bool IndirectSymbols;
+extern bool InfoPlist;
+extern bool LazyBind;
+extern bool LeadingHeaders;
+extern bool LinkOptHints;
+extern bool ObjcMetaData;
+extern bool Rebase;
+extern bool Rpaths;
+extern bool SymbolicOperands;
+extern bool UniversalHeaders;
+extern bool Verbose;
+extern bool WeakBind;
 
 Error getMachORelocationValueString(const object::MachOObjectFile *Obj,
                                     const object::RelocationRef &RelRef,
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOptID.h b/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOptID.h
new file mode 100644
index 0000000..65f6c60
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOptID.h
@@ -0,0 +1,13 @@
+#ifndef LLVM_TOOLS_LLVM_OBJDUMP_OBJDUMP_OPT_ID_H
+#define LLVM_TOOLS_LLVM_OBJDUMP_OBJDUMP_OPT_ID_H
+
+enum ObjdumpOptID {
+  OBJDUMP_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  OBJDUMP_##ID,
+#include "ObjdumpOpts.inc"
+#undef OPTION
+};
+
+#endif // LLVM_TOOLS_LLVM_OBJDUMP_OBJDUMP_OPT_ID_H
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td b/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td
new file mode 100644
index 0000000..1b19733
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td
@@ -0,0 +1,323 @@
+include "llvm/Option/OptParser.td"
+
+def help : Flag<["--"], "help">,
+  HelpText<"Display available options (--help-hidden for more)">;
+
+def help_hidden : Flag<["--"], "help-hidden">,
+  Flags<[HelpHidden]>,
+  HelpText<"Display all available options">;
+
+def version : Flag<["--"], "version">,
+  HelpText<"Display the version of this program">;
+def : Flag<["-"], "v">, Alias<version>, HelpText<"Alias for --version">;
+
+def adjust_vma_EQ : Joined<["--"], "adjust-vma=">,
+  MetaVarName<"offset">,
+  HelpText<"Increase the displayed address by the specified offset">;
+
+def all_headers : Flag<["--"], "all-headers">,
+  HelpText<"Display all available header information">;
+def : Flag<["-"], "x">, Alias<all_headers>, HelpText<"Alias for --all-headers">;
+
+def arch_name_EQ : Joined<["--"], "arch-name=">,
+  HelpText<"Target arch to disassemble for, "
+            "see --version for available targets">;
+def archive_headers : Flag<["--"], "archive-headers">,
+  HelpText<"Display archive header information">;
+
+def : Flag<["-"], "a">, Alias<archive_headers>,
+  HelpText<"Alias for --archive-headers">;
+
+def demangle : Flag<["--"], "demangle">, HelpText<"Demangle symbol names">;
+def : Flag<["-"], "C">, Alias<demangle>, HelpText<"Alias for --demangle">;
+
+def disassemble : Flag<["--"], "disassemble">,
+  HelpText<"Display assembler mnemonics for the machine instructions">;
+def : Flag<["-"], "d">, Alias<disassemble>, HelpText<"Alias for --disassemble">;
+
+def disassemble_all : Flag<["--"], "disassemble-all">,
+  HelpText<"Display assembler mnemonics for the machine instructions">;
+def : Flag<["-"], "D">, Alias<disassemble_all>,
+  HelpText<"Alias for --disassemble-all">;
+
+def symbol_description : Flag<["--"], "symbol-description">,
+  HelpText<"Add symbol description for disassembly. This "
+           "option is for XCOFF files only.">;
+
+def disassemble_symbols_EQ : Joined<["--"], "disassemble-symbols=">,
+  HelpText<"List of symbols to disassemble. "
+           "Accept demangled names when --demangle is "
+           "specified, otherwise accept mangled names">;
+
+def disassemble_zeroes : Flag<["--"], "disassemble-zeroes">,
+  HelpText<"Do not skip blocks of zeroes when disassembling">;
+def : Flag<["-"], "z">, Alias<disassemble_zeroes>,
+  HelpText<"Alias for --disassemble-zeroes">;
+
+def disassembler_options_EQ : Joined<["--"], "disassembler-options=">,
+  MetaVarName<"options">,
+  HelpText<"Pass target specific disassembler options">;
+def : JoinedOrSeparate<["-"], "M">, Alias<disassembler_options_EQ>,
+  HelpText<"Alias for --disassembler-options=">;
+
+def dynamic_reloc : Flag<["--"], "dynamic-reloc">,
+  HelpText<"Display the dynamic relocation entries in the file">;
+def : Flag<["-"], "R">, Alias<dynamic_reloc>,
+  HelpText<"Alias for --dynamic-reloc">;
+
+def dwarf_EQ : Joined<["--"], "dwarf=">,
+  HelpText<"Dump of dwarf debug sections">, Values<"frames">;
+
+def fault_map_section : Flag<["--"], "fault-map-section">,
+  HelpText<"Display contents of faultmap section">;
+
+def file_headers : Flag<["--"], "file-headers">,
+  HelpText<"Display the contents of the overall file header">;
+def : Flag<["-"], "f">, Alias<file_headers>,
+  HelpText<"Alias for --file-headers">;
+
+def full_contents : Flag<["--"], "full-contents">,
+  HelpText<"Display the content of each section">;
+def : Flag<["-"], "s">, Alias<full_contents>,
+  HelpText<"Alias for --full-contents">;
+
+def line_numbers : Flag<["--"], "line-numbers">,
+  HelpText<"Display source line numbers with "
+            "disassembly. Implies disassemble object">;
+def : Flag<["-"], "l">, Alias<line_numbers>,
+  HelpText<"Alias for --line-numbers">;
+
+def macho : Flag<["--"], "macho">,
+  HelpText<"Use MachO specific object file parser">;
+def : Flag<["-"], "m">, Alias<macho>, HelpText<"Alias for --macho">;
+
+def mcpu_EQ : Joined<["--"], "mcpu=">,
+  MetaVarName<"cpu-name">,
+  HelpText<"Target a specific cpu type (--mcpu=help for details)">;
+
+def mattr_EQ : Joined<["--"], "mattr=">,
+  MetaVarName<"a1,+a2,-a3,...">,
+  HelpText<"Target specific attributes (--mattr=help for details)">;
+
+def no_show_raw_insn : Flag<["--"], "no-show-raw-insn">,
+  HelpText<"When disassembling instructions, "
+           "do not print the instruction bytes.">;
+
+def no_leading_addr : Flag<["--"], "no-leading-addr">,
+  HelpText<"Print no leading address">;
+
+def raw_clang_ast : Flag<["--"], "raw-clang-ast">,
+  HelpText<"Dump the raw binary contents of the clang AST section">;
+
+def reloc : Flag<["--"], "reloc">,
+  HelpText<"Display the relocation entries in the file">;
+def : Flag<["-"], "r">, Alias<reloc>, HelpText<"Alias for --reloc">;
+
+def print_imm_hex : Flag<["--"], "print-imm-hex">,
+  HelpText<"Use hex format for immediate values">;
+
+def no_print_imm_hex : Flag<["--"], "no-print-imm-hex">,
+  HelpText<"Do not use hex format for immediate values (default)">;
+def : Flag<["--"], "print-imm-hex=false">, Alias<no_print_imm_hex>;
+
+def private_headers : Flag<["--"], "private-headers">,
+  HelpText<"Display format specific file headers">;
+def : Flag<["-"], "p">, Alias<private_headers>,
+  HelpText<"Alias for --private-headers">;
+
+def section_EQ : Joined<["--"], "section=">,
+  HelpText<"Operate on the specified sections only. "
+           "With --macho dump segment,section">;
+def : Separate<["--"], "section">, Alias<section_EQ>;
+def : JoinedOrSeparate<["-"], "j">, Alias<section_EQ>,
+  HelpText<"Alias for --section">;
+
+def section_headers : Flag<["--"], "section-headers">,
+  HelpText<"Display summaries of the headers for each section.">;
+def : Flag<["--"], "headers">, Alias<section_headers>,
+  HelpText<"Alias for --section-headers">;
+def : Flag<["-"], "h">, Alias<section_headers>,
+  HelpText<"Alias for --section-headers">;
+
+def show_lma : Flag<["--"], "show-lma">,
+  HelpText<"Display LMA column when dumping ELF section headers">;
+
+def source : Flag<["--"], "source">,
+  HelpText<"Display source inlined with disassembly. Implies disassemble object">;
+def : Flag<["-"], "S">, Alias<source>, HelpText<"Alias for --source">;
+
+def start_address_EQ : Joined<["--"], "start-address=">,
+  MetaVarName<"address">,
+  HelpText<"Disassemble beginning at address">;
+def stop_address_EQ : Joined<["--"], "stop-address=">,
+  MetaVarName<"address">,
+  HelpText<"Stop disassembly at address">;
+
+def syms : Flag<["--"], "syms">,
+  HelpText<"Display the symbol table">;
+def : Flag<["-"], "t">, Alias<syms>, HelpText<"Alias for --syms">;
+
+def symbolize_operands : Flag<["--"], "symbolize-operands">,
+  HelpText<"Symbolize instruction operands when disassembling">;
+
+def dynamic_syms : Flag<["--"], "dynamic-syms">,
+  HelpText<"Display the contents of the dynamic symbol table">;
+def : Flag<["-"], "T">, Alias<dynamic_syms>,
+  HelpText<"Alias for --dynamic-syms">;
+
+def triple_EQ : Joined<["--"], "triple=">,
+  HelpText<"Target triple to disassemble for, "
+            "see --version for available targets">;
+def : Separate<["--"], "triple">,
+  Alias<triple_EQ>;
+
+def unwind_info : Flag<["--"], "unwind-info">,
+  HelpText<"Display unwind information">;
+def : Flag<["-"], "u">, Alias<unwind_info>,
+  HelpText<"Alias for --unwind-info">;
+
+def wide : Flag<["--"], "wide">,
+  HelpText<"Ignored for compatibility with GNU objdump">;
+def : Flag<["-"], "w">, Alias<wide>;
+
+def prefix : Separate<["--"], "prefix">,
+  HelpText<"Add prefix to absolute paths">;
+
+def prefix_strip : Separate<["--"], "prefix-strip">,
+  HelpText<"Strip out initial directories from absolute "
+           "paths. No effect without --prefix">;
+
+def debug_vars_EQ : Joined<["--"], "debug-vars=">,
+  Values<"unicode,ascii">;
+def : Flag<["--"], "debug-vars">,
+  HelpText<"Print the locations (in registers or memory) of "
+           "source-level variables alongside disassembly">,
+  Alias<debug_vars_EQ>, AliasArgs<["unicode"]>;
+
+def debug_vars_indent_EQ : Joined<["--"], "debug-vars-indent=">,
+  HelpText<"Distance to indent the source-level variable display, "
+           "relative to the start of the disassembly">;
+
+def x86_asm_syntax_att : Flag<["--"], "x86-asm-syntax=att">,
+  HelpText<"Emit AT&T-style disassembly">;
+
+def x86_asm_syntax_intel : Flag<["--"], "x86-asm-syntax=intel">,
+  HelpText<"Emit Intel-style disassembly">;
+
+
+def grp_mach_o : OptionGroup<"kind">, HelpText<"llvm-objdump MachO Specific Options">;
+
+def private_header : Flag<["--"], "private-header">,
+  HelpText<"Display only the first format specific file header">,
+  Group<grp_mach_o>;
+
+def exports_trie : Flag<["--"], "exports-trie">,
+  HelpText<"Display mach-o exported symbols">,
+  Group<grp_mach_o>;
+
+def rebase : Flag<["--"], "rebase">,
+  HelpText<"Display mach-o rebasing info">,
+  Group<grp_mach_o>;
+
+def bind : Flag<["--"], "bind">,
+  HelpText<"Display mach-o binding info">,
+  Group<grp_mach_o>;
+
+def lazy_bind : Flag<["--"], "lazy-bind">,
+  HelpText<"Display mach-o lazy binding info">,
+  Group<grp_mach_o>;
+
+def weak_bind : Flag<["--"], "weak-bind">,
+  HelpText<"Display mach-o weak binding info">,
+  Group<grp_mach_o>;
+
+def g : Flag<["-"], "g">,
+  HelpText<"Print line information from debug info if available">,
+  Group<grp_mach_o>;
+
+def dsym_EQ : Joined<["--"], "dsym=">,
+  HelpText<"Use .dSYM file for debug info">,
+  Group<grp_mach_o>;
+def : Separate<["--"], "dsym">,
+  Alias<dsym_EQ>,
+  Group<grp_mach_o>;
+
+def full_leading_addr : Flag<["--"], "full-leading-addr">,
+  HelpText<"Print full leading address">,
+  Group<grp_mach_o>;
+
+def no_leading_headers : Flag<["--"], "no-leading-headers">,
+  HelpText<"Print no leading headers">,
+  Group<grp_mach_o>;
+
+def universal_headers : Flag<["--"], "universal-headers">,
+  HelpText<"Print Mach-O universal headers (requires --macho)">,
+  Group<grp_mach_o>;
+
+def archive_member_offsets : Flag<["--"], "archive-member-offsets">,
+  HelpText<"Print the offset to each archive member for Mach-O archives "
+           "(requires --macho and --archive-headers)">,
+  Group<grp_mach_o>;
+
+def indirect_symbols : Flag<["--"], "indirect-symbols">,
+  HelpText<"Print indirect symbol table for Mach-O objects (requires --macho)">,
+  Group<grp_mach_o>;
+
+def data_in_code : Flag<["--"], "data-in-code">,
+  HelpText<"Print the data in code table for Mach-O objects (requires --macho)">,
+  Group<grp_mach_o>;
+
+def function_starts : Flag<["--"], "function-starts">,
+  HelpText<"Print the function starts table for "
+           "Mach-O objects (requires --macho)">,
+  Group<grp_mach_o>;
+
+def link_opt_hints : Flag<["--"], "link-opt-hints">,
+  HelpText<"Print the linker optimization hints for "
+           "Mach-O objects (requires --macho)">,
+  Group<grp_mach_o>;
+
+def info_plist : Flag<["--"], "info-plist">,
+  HelpText<"Print the info plist section as strings for "
+           "Mach-O objects (requires --macho)">,
+  Group<grp_mach_o>;
+
+def dylibs_used : Flag<["--"], "dylibs-used">,
+  HelpText<"Print the shared libraries used for linked "
+           "Mach-O files (requires --macho)">,
+  Group<grp_mach_o>;
+
+def dylib_id : Flag<["--"], "dylib-id">,
+  HelpText<"Print the shared library's id for the "
+           "dylib Mach-O file (requires --macho)">,
+  Group<grp_mach_o>;
+
+def rpaths : Flag<["--"], "rpaths">,
+  HelpText<"Print the runtime search paths for the "
+           "Mach-O file (requires --macho)">,
+  Group<grp_mach_o>;
+
+def non_verbose : Flag<["--"], "non-verbose">,
+  HelpText<"Print the info for Mach-O objects in non-verbose or "
+           "numeric form (requires --macho)">,
+  Group<grp_mach_o>;
+
+def objc_meta_data : Flag<["--"], "objc-meta-data">,
+  HelpText<"Print the Objective-C runtime meta data "
+           "for Mach-O files (requires --macho)">,
+  Group<grp_mach_o>;
+
+def dis_symname : Separate<["--"], "dis-symname">,
+  HelpText<"disassemble just this symbol's instructions (requires --macho)">,
+  Group<grp_mach_o>;
+
+def no_symbolic_operands : Flag<["--"], "no-symbolic-operands">,
+  HelpText<"do not symbolic operands when disassembling (requires --macho)">,
+  Group<grp_mach_o>;
+
+def arch_EQ : Joined<["--"], "arch=">,
+  HelpText<"architecture(s) from a Mach-O file to dump">,
+  Group<grp_mach_o>;
+def : Separate<["--"], "arch">,
+  Alias<arch_EQ>,
+  Group<grp_mach_o>;
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/OtoolOpts.td b/src/llvm-project/llvm/tools/llvm-objdump/OtoolOpts.td
new file mode 100644
index 0000000..61ea701
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-objdump/OtoolOpts.td
@@ -0,0 +1,68 @@
+include "llvm/Option/OptParser.td"
+
+def help : Flag<["--"], "help">, HelpText<"print help">;
+def help_hidden : Flag<["--"], "help-hidden">,
+  HelpText<"print help for hidden flags">;
+
+def arch : Separate<["-"], "arch">,
+  HelpText<"select slice of universal Mach-O file">;
+def C : Flag<["-"], "C">, HelpText<"print linker optimization hints">;
+def d : Flag<["-"], "d">, HelpText<"print data section">;
+def D : Flag<["-"], "D">, HelpText<"print shared library id">;
+def f : Flag<["-"], "f">, HelpText<"print universal headers">;
+def G : Flag<["-"], "G">, HelpText<"print data-in-code table">;
+def h : Flag<["-"], "h">, HelpText<"print mach header">;
+def I : Flag<["-"], "I">, HelpText<"print indirect symbol table">;
+def j : Flag<["-"], "j">, HelpText<"print opcode bytes">;
+def l : Flag<["-"], "l">, HelpText<"print load commnads">;
+def L : Flag<["-"], "L">, HelpText<"print used shared libraries">;
+def mcpu_EQ : Joined<["-"], "mcpu=">, HelpText<"select cpu for disassembly">;
+def o : Flag<["-"], "o">, HelpText<"print Objective-C segment">;
+def p : Separate<["-"], "p">,
+  MetaVarName<"<function name>">,
+  HelpText<"start disassembly at <function name>">;
+def P : Flag<["-"], "P">, HelpText<"print __TEXT,__info_plist section as strings">;
+def : Flag<["-"], "q">, Flags<[HelpHidden]>,
+  HelpText<"use LLVM's disassembler (default)">;
+def r : Flag<["-"], "r">, HelpText<"print relocation entries">;
+def s : MultiArg<["-"], "s", 2>,
+  MetaVarName<"<segname> <sectname>">,
+  HelpText<"print contents of section">;
+def t : Flag<["-"], "t">, HelpText<"print text section">;
+def version : Flag<["--"], "version">, HelpText<"print version">;
+def v : Flag<["-"], "v">,
+  HelpText<"verbose output / disassemble when printing text sections">;
+def V : Flag<["-"], "V">,
+  HelpText<"symbolize disassembled operands (implies -v)">;
+def x : Flag<["-"], "x">, HelpText<"print all text sections">;
+def X : Flag<["-"], "X">, HelpText<"omit leading addresses or headers">;
+
+// Not (yet?) implemented:
+// def a : Flag<["-"], "a">, HelpText<"print archive header">;
+// -c print argument strings of a core file
+// -m don't use archive(member) syntax
+// -dyld_info
+// -dyld_opcodes
+// -chained_fixups
+// -addr_slide=arg
+// -function_offsets
+
+
+// Obsolete and unsupported:
+def grp_obsolete : OptionGroup<"kind">,
+  HelpText<"Obsolete and unsupported flags">;
+
+def : Flag<["-"], "B">, Flags<[HelpHidden]>, Group<grp_obsolete>,
+  HelpText<"force Thum disassembly (ARM 32-bit objects only)">;
+def : Flag<["-"], "H">, Flags<[HelpHidden]>, Group<grp_obsolete>,
+  HelpText<"print two-level hints table">;
+def : Flag<["-"], "M">, Flags<[HelpHidden]>, Group<grp_obsolete>,
+  HelpText<"print module table of shared library">;
+def : Flag<["-"], "R">, Flags<[HelpHidden]>, Group<grp_obsolete>,
+  HelpText<"print reference table of shared library">;
+def : Flag<["-"], "S">, Flags<[HelpHidden]>, Group<grp_obsolete>,
+  HelpText<"print table of contents of library">;
+def : Flag<["-"], "T">, Flags<[HelpHidden]>, Group<grp_obsolete>,
+  HelpText<"print table of contents of shared library">;
+def : Flag<["-"], "Q">, Flags<[HelpHidden]>, Group<grp_obsolete>,
+  HelpText<"llvm-otool cannot use otool-classic's disassembler">;
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp b/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp
new file mode 100644
index 0000000..8befac5
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp
@@ -0,0 +1,483 @@
+//===-- SourcePrinter.cpp -  source interleaving utilities ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the LiveVariablePrinter and SourcePrinter classes to
+// keep track of DWARF info as the current address is updated, and print out the
+// source file line and variable liveness as needed.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SourcePrinter.h"
+#include "llvm-objdump.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/FormatVariadic.h"
+
+#define DEBUG_TYPE "objdump"
+
+namespace llvm {
+namespace objdump {
+
+unsigned getInstStartColumn(const MCSubtargetInfo &STI) {
+  return !ShowRawInsn ? 16 : STI.getTargetTriple().isX86() ? 40 : 24;
+}
+
+bool LiveVariable::liveAtAddress(object::SectionedAddress Addr) {
+  if (LocExpr.Range == None)
+    return false;
+  return LocExpr.Range->SectionIndex == Addr.SectionIndex &&
+         LocExpr.Range->LowPC <= Addr.Address &&
+         LocExpr.Range->HighPC > Addr.Address;
+}
+
+void LiveVariable::print(raw_ostream &OS, const MCRegisterInfo &MRI) const {
+  DataExtractor Data({LocExpr.Expr.data(), LocExpr.Expr.size()},
+                     Unit->getContext().isLittleEndian(), 0);
+  DWARFExpression Expression(Data, Unit->getAddressByteSize());
+  Expression.printCompact(OS, MRI);
+}
+
+void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) {
+  uint64_t FuncLowPC, FuncHighPC, SectionIndex;
+  FuncDie.getLowAndHighPC(FuncLowPC, FuncHighPC, SectionIndex);
+  const char *VarName = VarDie.getName(DINameKind::ShortName);
+  DWARFUnit *U = VarDie.getDwarfUnit();
+
+  Expected<DWARFLocationExpressionsVector> Locs =
+      VarDie.getLocations(dwarf::DW_AT_location);
+  if (!Locs) {
+    // If the variable doesn't have any locations, just ignore it. We don't
+    // report an error or warning here as that could be noisy on optimised
+    // code.
+    consumeError(Locs.takeError());
+    return;
+  }
+
+  for (const DWARFLocationExpression &LocExpr : *Locs) {
+    if (LocExpr.Range) {
+      LiveVariables.emplace_back(LocExpr, VarName, U, FuncDie);
+    } else {
+      // If the LocExpr does not have an associated range, it is valid for
+      // the whole of the function.
+      // TODO: technically it is not valid for any range covered by another
+      // LocExpr, does that happen in reality?
+      DWARFLocationExpression WholeFuncExpr{
+          DWARFAddressRange(FuncLowPC, FuncHighPC, SectionIndex), LocExpr.Expr};
+      LiveVariables.emplace_back(WholeFuncExpr, VarName, U, FuncDie);
+    }
+  }
+}
+
+void LiveVariablePrinter::addFunction(DWARFDie D) {
+  for (const DWARFDie &Child : D.children()) {
+    if (Child.getTag() == dwarf::DW_TAG_variable ||
+        Child.getTag() == dwarf::DW_TAG_formal_parameter)
+      addVariable(D, Child);
+    else
+      addFunction(Child);
+  }
+}
+
+// Get the column number (in characters) at which the first live variable
+// line should be printed.
+unsigned LiveVariablePrinter::getIndentLevel() const {
+  return DbgIndent + getInstStartColumn(STI);
+}
+
+// Indent to the first live-range column to the right of the currently
+// printed line, and return the index of that column.
+// TODO: formatted_raw_ostream uses "column" to mean a number of characters
+// since the last \n, and we use it to mean the number of slots in which we
+// put live variable lines. Pick a less overloaded word.
+unsigned LiveVariablePrinter::moveToFirstVarColumn(formatted_raw_ostream &OS) {
+  // Logical column number: column zero is the first column we print in, each
+  // logical column is 2 physical columns wide.
+  unsigned FirstUnprintedLogicalColumn =
+      std::max((int)(OS.getColumn() - getIndentLevel() + 1) / 2, 0);
+  // Physical column number: the actual column number in characters, with
+  // zero being the left-most side of the screen.
+  unsigned FirstUnprintedPhysicalColumn =
+      getIndentLevel() + FirstUnprintedLogicalColumn * 2;
+
+  if (FirstUnprintedPhysicalColumn > OS.getColumn())
+    OS.PadToColumn(FirstUnprintedPhysicalColumn);
+
+  return FirstUnprintedLogicalColumn;
+}
+
+unsigned LiveVariablePrinter::findFreeColumn() {
+  for (unsigned ColIdx = 0; ColIdx < ActiveCols.size(); ++ColIdx)
+    if (!ActiveCols[ColIdx].isActive())
+      return ColIdx;
+
+  size_t OldSize = ActiveCols.size();
+  ActiveCols.grow(std::max<size_t>(OldSize * 2, 1));
+  return OldSize;
+}
+
+void LiveVariablePrinter::dump() const {
+  for (const LiveVariable &LV : LiveVariables) {
+    dbgs() << LV.VarName << " @ " << LV.LocExpr.Range << ": ";
+    LV.print(dbgs(), MRI);
+    dbgs() << "\n";
+  }
+}
+
+void LiveVariablePrinter::addCompileUnit(DWARFDie D) {
+  if (D.getTag() == dwarf::DW_TAG_subprogram)
+    addFunction(D);
+  else
+    for (const DWARFDie &Child : D.children())
+      addFunction(Child);
+}
+
+/// Update to match the state of the instruction between ThisAddr and
+/// NextAddr. In the common case, any live range active at ThisAddr is
+/// live-in to the instruction, and any live range active at NextAddr is
+/// live-out of the instruction. If IncludeDefinedVars is false, then live
+/// ranges starting at NextAddr will be ignored.
+void LiveVariablePrinter::update(object::SectionedAddress ThisAddr,
+                                 object::SectionedAddress NextAddr,
+                                 bool IncludeDefinedVars) {
+  // First, check variables which have already been assigned a column, so
+  // that we don't change their order.
+  SmallSet<unsigned, 8> CheckedVarIdxs;
+  for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) {
+    if (!ActiveCols[ColIdx].isActive())
+      continue;
+    CheckedVarIdxs.insert(ActiveCols[ColIdx].VarIdx);
+    LiveVariable &LV = LiveVariables[ActiveCols[ColIdx].VarIdx];
+    ActiveCols[ColIdx].LiveIn = LV.liveAtAddress(ThisAddr);
+    ActiveCols[ColIdx].LiveOut = LV.liveAtAddress(NextAddr);
+    LLVM_DEBUG(dbgs() << "pass 1, " << ThisAddr.Address << "-"
+                      << NextAddr.Address << ", " << LV.VarName << ", Col "
+                      << ColIdx << ": LiveIn=" << ActiveCols[ColIdx].LiveIn
+                      << ", LiveOut=" << ActiveCols[ColIdx].LiveOut << "\n");
+
+    if (!ActiveCols[ColIdx].LiveIn && !ActiveCols[ColIdx].LiveOut)
+      ActiveCols[ColIdx].VarIdx = Column::NullVarIdx;
+  }
+
+  // Next, look for variables which don't already have a column, but which
+  // are now live.
+  if (IncludeDefinedVars) {
+    for (unsigned VarIdx = 0, End = LiveVariables.size(); VarIdx < End;
+         ++VarIdx) {
+      if (CheckedVarIdxs.count(VarIdx))
+        continue;
+      LiveVariable &LV = LiveVariables[VarIdx];
+      bool LiveIn = LV.liveAtAddress(ThisAddr);
+      bool LiveOut = LV.liveAtAddress(NextAddr);
+      if (!LiveIn && !LiveOut)
+        continue;
+
+      unsigned ColIdx = findFreeColumn();
+      LLVM_DEBUG(dbgs() << "pass 2, " << ThisAddr.Address << "-"
+                        << NextAddr.Address << ", " << LV.VarName << ", Col "
+                        << ColIdx << ": LiveIn=" << LiveIn
+                        << ", LiveOut=" << LiveOut << "\n");
+      ActiveCols[ColIdx].VarIdx = VarIdx;
+      ActiveCols[ColIdx].LiveIn = LiveIn;
+      ActiveCols[ColIdx].LiveOut = LiveOut;
+      ActiveCols[ColIdx].MustDrawLabel = true;
+    }
+  }
+}
+
+enum class LineChar {
+  RangeStart,
+  RangeMid,
+  RangeEnd,
+  LabelVert,
+  LabelCornerNew,
+  LabelCornerActive,
+  LabelHoriz,
+};
+const char *LiveVariablePrinter::getLineChar(LineChar C) const {
+  bool IsASCII = DbgVariables == DVASCII;
+  switch (C) {
+  case LineChar::RangeStart:
+    return IsASCII ? "^" : (const char *)u8"\u2548";
+  case LineChar::RangeMid:
+    return IsASCII ? "|" : (const char *)u8"\u2503";
+  case LineChar::RangeEnd:
+    return IsASCII ? "v" : (const char *)u8"\u253b";
+  case LineChar::LabelVert:
+    return IsASCII ? "|" : (const char *)u8"\u2502";
+  case LineChar::LabelCornerNew:
+    return IsASCII ? "/" : (const char *)u8"\u250c";
+  case LineChar::LabelCornerActive:
+    return IsASCII ? "|" : (const char *)u8"\u2520";
+  case LineChar::LabelHoriz:
+    return IsASCII ? "-" : (const char *)u8"\u2500";
+  }
+  llvm_unreachable("Unhandled LineChar enum");
+}
+
+/// Print live ranges to the right of an existing line. This assumes the
+/// line is not an instruction, so doesn't start or end any live ranges, so
+/// we only need to print active ranges or empty columns. If AfterInst is
+/// true, this is being printed after the last instruction fed to update(),
+/// otherwise this is being printed before it.
+void LiveVariablePrinter::printAfterOtherLine(formatted_raw_ostream &OS,
+                                              bool AfterInst) {
+  if (ActiveCols.size()) {
+    unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS);
+    for (size_t ColIdx = FirstUnprintedColumn, End = ActiveCols.size();
+         ColIdx < End; ++ColIdx) {
+      if (ActiveCols[ColIdx].isActive()) {
+        if ((AfterInst && ActiveCols[ColIdx].LiveOut) ||
+            (!AfterInst && ActiveCols[ColIdx].LiveIn))
+          OS << getLineChar(LineChar::RangeMid);
+        else if (!AfterInst && ActiveCols[ColIdx].LiveOut)
+          OS << getLineChar(LineChar::LabelVert);
+        else
+          OS << " ";
+      }
+      OS << " ";
+    }
+  }
+  OS << "\n";
+}
+
+/// Print any live variable range info needed to the right of a
+/// non-instruction line of disassembly. This is where we print the variable
+/// names and expressions, with thin line-drawing characters connecting them
+/// to the live range which starts at the next instruction. If MustPrint is
+/// true, we have to print at least one line (with the continuation of any
+/// already-active live ranges) because something has already been printed
+/// earlier on this line.
+void LiveVariablePrinter::printBetweenInsts(formatted_raw_ostream &OS,
+                                            bool MustPrint) {
+  bool PrintedSomething = false;
+  for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) {
+    if (ActiveCols[ColIdx].isActive() && ActiveCols[ColIdx].MustDrawLabel) {
+      // First we need to print the live range markers for any active
+      // columns to the left of this one.
+      OS.PadToColumn(getIndentLevel());
+      for (unsigned ColIdx2 = 0; ColIdx2 < ColIdx; ++ColIdx2) {
+        if (ActiveCols[ColIdx2].isActive()) {
+          if (ActiveCols[ColIdx2].MustDrawLabel && !ActiveCols[ColIdx2].LiveIn)
+            OS << getLineChar(LineChar::LabelVert) << " ";
+          else
+            OS << getLineChar(LineChar::RangeMid) << " ";
+        } else
+          OS << "  ";
+      }
+
+      // Then print the variable name and location of the new live range,
+      // with box drawing characters joining it to the live range line.
+      OS << getLineChar(ActiveCols[ColIdx].LiveIn ? LineChar::LabelCornerActive
+                                                  : LineChar::LabelCornerNew)
+         << getLineChar(LineChar::LabelHoriz) << " ";
+      WithColor(OS, raw_ostream::GREEN)
+          << LiveVariables[ActiveCols[ColIdx].VarIdx].VarName;
+      OS << " = ";
+      {
+        WithColor ExprColor(OS, raw_ostream::CYAN);
+        LiveVariables[ActiveCols[ColIdx].VarIdx].print(OS, MRI);
+      }
+
+      // If there are any columns to the right of the expression we just
+      // printed, then continue their live range lines.
+      unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS);
+      for (unsigned ColIdx2 = FirstUnprintedColumn, End = ActiveCols.size();
+           ColIdx2 < End; ++ColIdx2) {
+        if (ActiveCols[ColIdx2].isActive() && ActiveCols[ColIdx2].LiveIn)
+          OS << getLineChar(LineChar::RangeMid) << " ";
+        else
+          OS << "  ";
+      }
+
+      OS << "\n";
+      PrintedSomething = true;
+    }
+  }
+
+  for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx)
+    if (ActiveCols[ColIdx].isActive())
+      ActiveCols[ColIdx].MustDrawLabel = false;
+
+  // If we must print something (because we printed a line/column number),
+  // but don't have any new variables to print, then print a line which
+  // just continues any existing live ranges.
+  if (MustPrint && !PrintedSomething)
+    printAfterOtherLine(OS, false);
+}
+
+/// Print the live variable ranges to the right of a disassembled instruction.
+void LiveVariablePrinter::printAfterInst(formatted_raw_ostream &OS) {
+  if (!ActiveCols.size())
+    return;
+  unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS);
+  for (unsigned ColIdx = FirstUnprintedColumn, End = ActiveCols.size();
+       ColIdx < End; ++ColIdx) {
+    if (!ActiveCols[ColIdx].isActive())
+      OS << "  ";
+    else if (ActiveCols[ColIdx].LiveIn && ActiveCols[ColIdx].LiveOut)
+      OS << getLineChar(LineChar::RangeMid) << " ";
+    else if (ActiveCols[ColIdx].LiveOut)
+      OS << getLineChar(LineChar::RangeStart) << " ";
+    else if (ActiveCols[ColIdx].LiveIn)
+      OS << getLineChar(LineChar::RangeEnd) << " ";
+    else
+      llvm_unreachable("var must be live in or out!");
+  }
+}
+
+bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) {
+  std::unique_ptr<MemoryBuffer> Buffer;
+  if (LineInfo.Source) {
+    Buffer = MemoryBuffer::getMemBuffer(*LineInfo.Source);
+  } else {
+    auto BufferOrError = MemoryBuffer::getFile(LineInfo.FileName);
+    if (!BufferOrError) {
+      if (MissingSources.insert(LineInfo.FileName).second)
+        reportWarning("failed to find source " + LineInfo.FileName,
+                      Obj->getFileName());
+      return false;
+    }
+    Buffer = std::move(*BufferOrError);
+  }
+  // Chomp the file to get lines
+  const char *BufferStart = Buffer->getBufferStart(),
+             *BufferEnd = Buffer->getBufferEnd();
+  std::vector<StringRef> &Lines = LineCache[LineInfo.FileName];
+  const char *Start = BufferStart;
+  for (const char *I = BufferStart; I != BufferEnd; ++I)
+    if (*I == '\n') {
+      Lines.emplace_back(Start, I - Start - (BufferStart < I && I[-1] == '\r'));
+      Start = I + 1;
+    }
+  if (Start < BufferEnd)
+    Lines.emplace_back(Start, BufferEnd - Start);
+  SourceCache[LineInfo.FileName] = std::move(Buffer);
+  return true;
+}
+
+void SourcePrinter::printSourceLine(formatted_raw_ostream &OS,
+                                    object::SectionedAddress Address,
+                                    StringRef ObjectFilename,
+                                    LiveVariablePrinter &LVP,
+                                    StringRef Delimiter) {
+  if (!Symbolizer)
+    return;
+
+  DILineInfo LineInfo = DILineInfo();
+  Expected<DILineInfo> ExpectedLineInfo =
+      Symbolizer->symbolizeCode(*Obj, Address);
+  std::string ErrorMessage;
+  if (ExpectedLineInfo) {
+    LineInfo = *ExpectedLineInfo;
+  } else if (!WarnedInvalidDebugInfo) {
+    WarnedInvalidDebugInfo = true;
+    // TODO Untested.
+    reportWarning("failed to parse debug information: " +
+                      toString(ExpectedLineInfo.takeError()),
+                  ObjectFilename);
+  }
+
+  if (!objdump::Prefix.empty() &&
+      sys::path::is_absolute_gnu(LineInfo.FileName)) {
+    // FileName has at least one character since is_absolute_gnu is false for
+    // an empty string.
+    assert(!LineInfo.FileName.empty());
+    if (PrefixStrip > 0) {
+      uint32_t Level = 0;
+      auto StrippedNameStart = LineInfo.FileName.begin();
+
+      // Path.h iterator skips extra separators. Therefore it cannot be used
+      // here to keep compatibility with GNU Objdump.
+      for (auto Pos = StrippedNameStart + 1, End = LineInfo.FileName.end();
+           Pos != End && Level < PrefixStrip; ++Pos) {
+        if (sys::path::is_separator(*Pos)) {
+          StrippedNameStart = Pos;
+          ++Level;
+        }
+      }
+
+      LineInfo.FileName =
+          std::string(StrippedNameStart, LineInfo.FileName.end());
+    }
+
+    SmallString<128> FilePath;
+    sys::path::append(FilePath, Prefix, LineInfo.FileName);
+
+    LineInfo.FileName = std::string(FilePath);
+  }
+
+  if (PrintLines)
+    printLines(OS, LineInfo, Delimiter, LVP);
+  if (PrintSource)
+    printSources(OS, LineInfo, ObjectFilename, Delimiter, LVP);
+  OldLineInfo = LineInfo;
+}
+
+void SourcePrinter::printLines(formatted_raw_ostream &OS,
+                               const DILineInfo &LineInfo, StringRef Delimiter,
+                               LiveVariablePrinter &LVP) {
+  bool PrintFunctionName = LineInfo.FunctionName != DILineInfo::BadString &&
+                           LineInfo.FunctionName != OldLineInfo.FunctionName;
+  if (PrintFunctionName) {
+    OS << Delimiter << LineInfo.FunctionName;
+    // If demangling is successful, FunctionName will end with "()". Print it
+    // only if demangling did not run or was unsuccessful.
+    if (!StringRef(LineInfo.FunctionName).endswith("()"))
+      OS << "()";
+    OS << ":\n";
+  }
+  if (LineInfo.FileName != DILineInfo::BadString && LineInfo.Line != 0 &&
+      (OldLineInfo.Line != LineInfo.Line ||
+       OldLineInfo.FileName != LineInfo.FileName || PrintFunctionName)) {
+    OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line;
+    LVP.printBetweenInsts(OS, true);
+  }
+}
+
+void SourcePrinter::printSources(formatted_raw_ostream &OS,
+                                 const DILineInfo &LineInfo,
+                                 StringRef ObjectFilename, StringRef Delimiter,
+                                 LiveVariablePrinter &LVP) {
+  if (LineInfo.FileName == DILineInfo::BadString || LineInfo.Line == 0 ||
+      (OldLineInfo.Line == LineInfo.Line &&
+       OldLineInfo.FileName == LineInfo.FileName))
+    return;
+
+  if (SourceCache.find(LineInfo.FileName) == SourceCache.end())
+    if (!cacheSource(LineInfo))
+      return;
+  auto LineBuffer = LineCache.find(LineInfo.FileName);
+  if (LineBuffer != LineCache.end()) {
+    if (LineInfo.Line > LineBuffer->second.size()) {
+      reportWarning(
+          formatv(
+              "debug info line number {0} exceeds the number of lines in {1}",
+              LineInfo.Line, LineInfo.FileName),
+          ObjectFilename);
+      return;
+    }
+    // Vector begins at 0, line numbers are non-zero
+    OS << Delimiter << LineBuffer->second[LineInfo.Line - 1];
+    LVP.printBetweenInsts(OS, true);
+  }
+}
+
+SourcePrinter::SourcePrinter(const object::ObjectFile *Obj,
+                             StringRef DefaultArch)
+    : Obj(Obj) {
+  symbolize::LLVMSymbolizer::Options SymbolizerOpts;
+  SymbolizerOpts.PrintFunctions =
+      DILineInfoSpecifier::FunctionNameKind::LinkageName;
+  SymbolizerOpts.Demangle = Demangle;
+  SymbolizerOpts.DefaultArch = std::string(DefaultArch);
+  Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts));
+}
+
+} // namespace objdump
+} // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.h b/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.h
new file mode 100644
index 0000000..21d5bdc
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.h
@@ -0,0 +1,166 @@
+//===-- SourcePrinter.h -  source interleaving utilities --------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_OBJDUMP_SOURCEPRINTER_H
+#define LLVM_TOOLS_LLVM_OBJDUMP_SOURCEPRINTER_H
+
+#include "llvm/ADT/IndexedMap.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/Symbolize/Symbolize.h"
+#include "llvm/Support/FormattedStream.h"
+#include <unordered_map>
+#include <vector>
+
+namespace llvm {
+namespace objdump {
+
+/// Stores a single expression representing the location of a source-level
+/// variable, along with the PC range for which that expression is valid.
+struct LiveVariable {
+  DWARFLocationExpression LocExpr;
+  const char *VarName;
+  DWARFUnit *Unit;
+  const DWARFDie FuncDie;
+
+  LiveVariable(const DWARFLocationExpression &LocExpr, const char *VarName,
+               DWARFUnit *Unit, const DWARFDie FuncDie)
+      : LocExpr(LocExpr), VarName(VarName), Unit(Unit), FuncDie(FuncDie) {}
+
+  bool liveAtAddress(object::SectionedAddress Addr);
+
+  void print(raw_ostream &OS, const MCRegisterInfo &MRI) const;
+};
+
+/// Helper class for printing source variable locations alongside disassembly.
+class LiveVariablePrinter {
+  // Information we want to track about one column in which we are printing a
+  // variable live range.
+  struct Column {
+    unsigned VarIdx = NullVarIdx;
+    bool LiveIn = false;
+    bool LiveOut = false;
+    bool MustDrawLabel = false;
+
+    bool isActive() const { return VarIdx != NullVarIdx; }
+
+    static constexpr unsigned NullVarIdx = std::numeric_limits<unsigned>::max();
+  };
+
+  // All live variables we know about in the object/image file.
+  std::vector<LiveVariable> LiveVariables;
+
+  // The columns we are currently drawing.
+  IndexedMap<Column> ActiveCols;
+
+  const MCRegisterInfo &MRI;
+  const MCSubtargetInfo &STI;
+
+  void addVariable(DWARFDie FuncDie, DWARFDie VarDie);
+
+  void addFunction(DWARFDie D);
+
+  // Get the column number (in characters) at which the first live variable
+  // line should be printed.
+  unsigned getIndentLevel() const;
+
+  // Indent to the first live-range column to the right of the currently
+  // printed line, and return the index of that column.
+  // TODO: formatted_raw_ostream uses "column" to mean a number of characters
+  // since the last \n, and we use it to mean the number of slots in which we
+  // put live variable lines. Pick a less overloaded word.
+  unsigned moveToFirstVarColumn(formatted_raw_ostream &OS);
+
+  unsigned findFreeColumn();
+
+public:
+  LiveVariablePrinter(const MCRegisterInfo &MRI, const MCSubtargetInfo &STI)
+      : LiveVariables(), ActiveCols(Column()), MRI(MRI), STI(STI) {}
+
+  void dump() const;
+
+  void addCompileUnit(DWARFDie D);
+
+  /// Update to match the state of the instruction between ThisAddr and
+  /// NextAddr. In the common case, any live range active at ThisAddr is
+  /// live-in to the instruction, and any live range active at NextAddr is
+  /// live-out of the instruction. If IncludeDefinedVars is false, then live
+  /// ranges starting at NextAddr will be ignored.
+  void update(object::SectionedAddress ThisAddr,
+              object::SectionedAddress NextAddr, bool IncludeDefinedVars);
+
+  enum class LineChar {
+    RangeStart,
+    RangeMid,
+    RangeEnd,
+    LabelVert,
+    LabelCornerNew,
+    LabelCornerActive,
+    LabelHoriz,
+  };
+  const char *getLineChar(LineChar C) const;
+
+  /// Print live ranges to the right of an existing line. This assumes the
+  /// line is not an instruction, so doesn't start or end any live ranges, so
+  /// we only need to print active ranges or empty columns. If AfterInst is
+  /// true, this is being printed after the last instruction fed to update(),
+  /// otherwise this is being printed before it.
+  void printAfterOtherLine(formatted_raw_ostream &OS, bool AfterInst);
+
+  /// Print any live variable range info needed to the right of a
+  /// non-instruction line of disassembly. This is where we print the variable
+  /// names and expressions, with thin line-drawing characters connecting them
+  /// to the live range which starts at the next instruction. If MustPrint is
+  /// true, we have to print at least one line (with the continuation of any
+  /// already-active live ranges) because something has already been printed
+  /// earlier on this line.
+  void printBetweenInsts(formatted_raw_ostream &OS, bool MustPrint);
+
+  /// Print the live variable ranges to the right of a disassembled instruction.
+  void printAfterInst(formatted_raw_ostream &OS);
+};
+
+class SourcePrinter {
+protected:
+  DILineInfo OldLineInfo;
+  const object::ObjectFile *Obj = nullptr;
+  std::unique_ptr<symbolize::LLVMSymbolizer> Symbolizer;
+  // File name to file contents of source.
+  std::unordered_map<std::string, std::unique_ptr<MemoryBuffer>> SourceCache;
+  // Mark the line endings of the cached source.
+  std::unordered_map<std::string, std::vector<StringRef>> LineCache;
+  // Keep track of missing sources.
+  StringSet<> MissingSources;
+  // Only emit 'invalid debug info' warning once.
+  bool WarnedInvalidDebugInfo = false;
+
+private:
+  bool cacheSource(const DILineInfo &LineInfoFile);
+
+  void printLines(formatted_raw_ostream &OS, const DILineInfo &LineInfo,
+                  StringRef Delimiter, LiveVariablePrinter &LVP);
+
+  void printSources(formatted_raw_ostream &OS, const DILineInfo &LineInfo,
+                    StringRef ObjectFilename, StringRef Delimiter,
+                    LiveVariablePrinter &LVP);
+
+public:
+  SourcePrinter() = default;
+  SourcePrinter(const object::ObjectFile *Obj, StringRef DefaultArch);
+  virtual ~SourcePrinter() = default;
+  virtual void printSourceLine(formatted_raw_ostream &OS,
+                               object::SectionedAddress Address,
+                               StringRef ObjectFilename,
+                               LiveVariablePrinter &LVP,
+                               StringRef Delimiter = "; ");
+};
+
+} // namespace objdump
+} // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp
index df37abb..c4cc5fe 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp
@@ -46,22 +46,30 @@
 Optional<XCOFF::StorageMappingClass>
 objdump::getXCOFFSymbolCsectSMC(const XCOFFObjectFile *Obj,
                                 const SymbolRef &Sym) {
-  XCOFFSymbolRef SymRef(Sym.getRawDataRefImpl(), Obj);
+  const XCOFFSymbolRef SymRef = Obj->toSymbolRef(Sym.getRawDataRefImpl());
 
-  if (SymRef.hasCsectAuxEnt())
-    return SymRef.getXCOFFCsectAuxEnt32()->StorageMappingClass;
+  if (!SymRef.isCsectSymbol())
+    return None;
 
-  return None;
+  auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
+  if (!CsectAuxEntOrErr)
+    return None;
+
+  return CsectAuxEntOrErr.get().getStorageMappingClass();
 }
 
 bool objdump::isLabel(const XCOFFObjectFile *Obj, const SymbolRef &Sym) {
 
-  XCOFFSymbolRef SymRef(Sym.getRawDataRefImpl(), Obj);
+  const XCOFFSymbolRef SymRef = Obj->toSymbolRef(Sym.getRawDataRefImpl());
 
-  if (SymRef.hasCsectAuxEnt())
-    return SymRef.getXCOFFCsectAuxEnt32()->isLabel();
+  if (!SymRef.isCsectSymbol())
+    return false;
 
-  return false;
+  auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
+  if (!CsectAuxEntOrErr)
+    return false;
+
+  return CsectAuxEntOrErr.get().isLabel();
 }
 
 std::string objdump::getXCOFFSymbolDescription(const SymbolInfoTy &SymbolInfo,
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 17128e9..48ae92f 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -19,18 +19,19 @@
 #include "COFFDump.h"
 #include "ELFDump.h"
 #include "MachODump.h"
+#include "ObjdumpOptID.h"
+#include "SourcePrinter.h"
 #include "WasmDump.h"
 #include "XCOFFDump.h"
 #include "llvm/ADT/IndexedMap.h"
 #include "llvm/ADT/Optional.h"
-#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetOperations.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/ADT/Twine.h"
-#include "llvm/CodeGen/FaultMaps.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
 #include "llvm/Demangle/Demangle.h"
@@ -50,12 +51,15 @@
 #include "llvm/Object/COFF.h"
 #include "llvm/Object/COFFImportFile.h"
 #include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/FaultMapParser.h"
 #include "llvm/Object/MachO.h"
 #include "llvm/Object/MachOUniversal.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Object/Wasm.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
 #include "llvm/Support/Casting.h"
-#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/FileSystem.h"
@@ -81,307 +85,143 @@
 using namespace llvm;
 using namespace llvm::object;
 using namespace llvm::objdump;
+using namespace llvm::opt;
+
+namespace {
+
+class CommonOptTable : public opt::OptTable {
+public:
+  CommonOptTable(ArrayRef<Info> OptionInfos, const char *Usage,
+                 const char *Description)
+      : OptTable(OptionInfos), Usage(Usage), Description(Description) {
+    setGroupedShortOptions(true);
+  }
+
+  void printHelp(StringRef Argv0, bool ShowHidden = false) const {
+    Argv0 = sys::path::filename(Argv0);
+    opt::OptTable::printHelp(outs(), (Argv0 + Usage).str().c_str(), Description,
+                             ShowHidden, ShowHidden);
+    // TODO Replace this with OptTable API once it adds extrahelp support.
+    outs() << "\nPass @FILE as argument to read options from FILE.\n";
+  }
+
+private:
+  const char *Usage;
+  const char *Description;
+};
+
+// ObjdumpOptID is in ObjdumpOptID.h
+
+#define PREFIX(NAME, VALUE) const char *const OBJDUMP_##NAME[] = VALUE;
+#include "ObjdumpOpts.inc"
+#undef PREFIX
+
+static constexpr opt::OptTable::Info ObjdumpInfoTable[] = {
+#define OBJDUMP_nullptr nullptr
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  {OBJDUMP_##PREFIX, NAME,         HELPTEXT,                                   \
+   METAVAR,          OBJDUMP_##ID, opt::Option::KIND##Class,                   \
+   PARAM,            FLAGS,        OBJDUMP_##GROUP,                            \
+   OBJDUMP_##ALIAS,  ALIASARGS,    VALUES},
+#include "ObjdumpOpts.inc"
+#undef OPTION
+#undef OBJDUMP_nullptr
+};
+
+class ObjdumpOptTable : public CommonOptTable {
+public:
+  ObjdumpOptTable()
+      : CommonOptTable(ObjdumpInfoTable, " [options] <input object files>",
+                       "llvm object file dumper") {}
+};
+
+enum OtoolOptID {
+  OTOOL_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  OTOOL_##ID,
+#include "OtoolOpts.inc"
+#undef OPTION
+};
+
+#define PREFIX(NAME, VALUE) const char *const OTOOL_##NAME[] = VALUE;
+#include "OtoolOpts.inc"
+#undef PREFIX
+
+static constexpr opt::OptTable::Info OtoolInfoTable[] = {
+#define OTOOL_nullptr nullptr
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  {OTOOL_##PREFIX, NAME,       HELPTEXT,                                       \
+   METAVAR,        OTOOL_##ID, opt::Option::KIND##Class,                       \
+   PARAM,          FLAGS,      OTOOL_##GROUP,                                  \
+   OTOOL_##ALIAS,  ALIASARGS,  VALUES},
+#include "OtoolOpts.inc"
+#undef OPTION
+#undef OTOOL_nullptr
+};
+
+class OtoolOptTable : public CommonOptTable {
+public:
+  OtoolOptTable()
+      : CommonOptTable(OtoolInfoTable, " [option...] [file...]",
+                       "Mach-O object file displaying tool") {}
+};
+
+} // namespace
 
 #define DEBUG_TYPE "objdump"
 
-static cl::OptionCategory ObjdumpCat("llvm-objdump Options");
+static uint64_t AdjustVMA;
+static bool AllHeaders;
+static std::string ArchName;
+bool objdump::ArchiveHeaders;
+bool objdump::Demangle;
+bool objdump::Disassemble;
+bool objdump::DisassembleAll;
+bool objdump::SymbolDescription;
+static std::vector<std::string> DisassembleSymbols;
+static bool DisassembleZeroes;
+static std::vector<std::string> DisassemblerOptions;
+DIDumpType objdump::DwarfDumpType;
+static bool DynamicRelocations;
+static bool FaultMapSection;
+static bool FileHeaders;
+bool objdump::SectionContents;
+static std::vector<std::string> InputFilenames;
+bool objdump::PrintLines;
+static bool MachOOpt;
+std::string objdump::MCPU;
+std::vector<std::string> objdump::MAttrs;
+bool objdump::ShowRawInsn;
+bool objdump::LeadingAddr;
+static bool RawClangAST;
+bool objdump::Relocations;
+bool objdump::PrintImmHex;
+bool objdump::PrivateHeaders;
+std::vector<std::string> objdump::FilterSections;
+bool objdump::SectionHeaders;
+static bool ShowLMA;
+bool objdump::PrintSource;
 
-static cl::opt<uint64_t> AdjustVMA(
-    "adjust-vma",
-    cl::desc("Increase the displayed address by the specified offset"),
-    cl::value_desc("offset"), cl::init(0), cl::cat(ObjdumpCat));
+static uint64_t StartAddress;
+static bool HasStartAddressFlag;
+static uint64_t StopAddress = UINT64_MAX;
+static bool HasStopAddressFlag;
 
-static cl::opt<bool>
-    AllHeaders("all-headers",
-               cl::desc("Display all available header information"),
-               cl::cat(ObjdumpCat));
-static cl::alias AllHeadersShort("x", cl::desc("Alias for --all-headers"),
-                                 cl::NotHidden, cl::Grouping,
-                                 cl::aliasopt(AllHeaders));
+bool objdump::SymbolTable;
+static bool SymbolizeOperands;
+static bool DynamicSymbolTable;
+std::string objdump::TripleName;
+bool objdump::UnwindInfo;
+static bool Wide;
+std::string objdump::Prefix;
+uint32_t objdump::PrefixStrip;
 
-static cl::opt<std::string>
-    ArchName("arch-name",
-             cl::desc("Target arch to disassemble for, "
-                      "see --version for available targets"),
-             cl::cat(ObjdumpCat));
+DebugVarsFormat objdump::DbgVariables = DVDisabled;
 
-cl::opt<bool>
-    objdump::ArchiveHeaders("archive-headers",
-                            cl::desc("Display archive header information"),
-                            cl::cat(ObjdumpCat));
-static cl::alias ArchiveHeadersShort("a",
-                                     cl::desc("Alias for --archive-headers"),
-                                     cl::NotHidden, cl::Grouping,
-                                     cl::aliasopt(ArchiveHeaders));
-
-cl::opt<bool> objdump::Demangle("demangle", cl::desc("Demangle symbols names"),
-                                cl::init(false), cl::cat(ObjdumpCat));
-static cl::alias DemangleShort("C", cl::desc("Alias for --demangle"),
-                               cl::NotHidden, cl::Grouping,
-                               cl::aliasopt(Demangle));
-
-cl::opt<bool> objdump::Disassemble(
-    "disassemble",
-    cl::desc("Display assembler mnemonics for the machine instructions"),
-    cl::cat(ObjdumpCat));
-static cl::alias DisassembleShort("d", cl::desc("Alias for --disassemble"),
-                                  cl::NotHidden, cl::Grouping,
-                                  cl::aliasopt(Disassemble));
-
-cl::opt<bool> objdump::DisassembleAll(
-    "disassemble-all",
-    cl::desc("Display assembler mnemonics for the machine instructions"),
-    cl::cat(ObjdumpCat));
-static cl::alias DisassembleAllShort("D",
-                                     cl::desc("Alias for --disassemble-all"),
-                                     cl::NotHidden, cl::Grouping,
-                                     cl::aliasopt(DisassembleAll));
-
-cl::opt<bool> objdump::SymbolDescription(
-    "symbol-description",
-    cl::desc("Add symbol description for disassembly. This "
-             "option is for XCOFF files only"),
-    cl::init(false), cl::cat(ObjdumpCat));
-
-static cl::list<std::string>
-    DisassembleSymbols("disassemble-symbols", cl::CommaSeparated,
-                       cl::desc("List of symbols to disassemble. "
-                                "Accept demangled names when --demangle is "
-                                "specified, otherwise accept mangled names"),
-                       cl::cat(ObjdumpCat));
-
-static cl::opt<bool> DisassembleZeroes(
-    "disassemble-zeroes",
-    cl::desc("Do not skip blocks of zeroes when disassembling"),
-    cl::cat(ObjdumpCat));
-static cl::alias
-    DisassembleZeroesShort("z", cl::desc("Alias for --disassemble-zeroes"),
-                           cl::NotHidden, cl::Grouping,
-                           cl::aliasopt(DisassembleZeroes));
-
-static cl::list<std::string>
-    DisassemblerOptions("disassembler-options",
-                        cl::desc("Pass target specific disassembler options"),
-                        cl::value_desc("options"), cl::CommaSeparated,
-                        cl::cat(ObjdumpCat));
-static cl::alias
-    DisassemblerOptionsShort("M", cl::desc("Alias for --disassembler-options"),
-                             cl::NotHidden, cl::Grouping, cl::Prefix,
-                             cl::CommaSeparated,
-                             cl::aliasopt(DisassemblerOptions));
-
-cl::opt<DIDumpType> objdump::DwarfDumpType(
-    "dwarf", cl::init(DIDT_Null), cl::desc("Dump of dwarf debug sections:"),
-    cl::values(clEnumValN(DIDT_DebugFrame, "frames", ".debug_frame")),
-    cl::cat(ObjdumpCat));
-
-static cl::opt<bool> DynamicRelocations(
-    "dynamic-reloc",
-    cl::desc("Display the dynamic relocation entries in the file"),
-    cl::cat(ObjdumpCat));
-static cl::alias DynamicRelocationShort("R",
-                                        cl::desc("Alias for --dynamic-reloc"),
-                                        cl::NotHidden, cl::Grouping,
-                                        cl::aliasopt(DynamicRelocations));
-
-static cl::opt<bool>
-    FaultMapSection("fault-map-section",
-                    cl::desc("Display contents of faultmap section"),
-                    cl::cat(ObjdumpCat));
-
-static cl::opt<bool>
-    FileHeaders("file-headers",
-                cl::desc("Display the contents of the overall file header"),
-                cl::cat(ObjdumpCat));
-static cl::alias FileHeadersShort("f", cl::desc("Alias for --file-headers"),
-                                  cl::NotHidden, cl::Grouping,
-                                  cl::aliasopt(FileHeaders));
-
-cl::opt<bool>
-    objdump::SectionContents("full-contents",
-                             cl::desc("Display the content of each section"),
-                             cl::cat(ObjdumpCat));
-static cl::alias SectionContentsShort("s",
-                                      cl::desc("Alias for --full-contents"),
-                                      cl::NotHidden, cl::Grouping,
-                                      cl::aliasopt(SectionContents));
-
-static cl::list<std::string> InputFilenames(cl::Positional,
-                                            cl::desc("<input object files>"),
-                                            cl::ZeroOrMore,
-                                            cl::cat(ObjdumpCat));
-
-static cl::opt<bool>
-    PrintLines("line-numbers",
-               cl::desc("Display source line numbers with "
-                        "disassembly. Implies disassemble object"),
-               cl::cat(ObjdumpCat));
-static cl::alias PrintLinesShort("l", cl::desc("Alias for --line-numbers"),
-                                 cl::NotHidden, cl::Grouping,
-                                 cl::aliasopt(PrintLines));
-
-static cl::opt<bool> MachOOpt("macho",
-                              cl::desc("Use MachO specific object file parser"),
-                              cl::cat(ObjdumpCat));
-static cl::alias MachOm("m", cl::desc("Alias for --macho"), cl::NotHidden,
-                        cl::Grouping, cl::aliasopt(MachOOpt));
-
-cl::opt<std::string> objdump::MCPU(
-    "mcpu", cl::desc("Target a specific cpu type (--mcpu=help for details)"),
-    cl::value_desc("cpu-name"), cl::init(""), cl::cat(ObjdumpCat));
-
-cl::list<std::string> objdump::MAttrs(
-    "mattr", cl::CommaSeparated,
-    cl::desc("Target specific attributes (--mattr=help for details)"),
-    cl::value_desc("a1,+a2,-a3,..."), cl::cat(ObjdumpCat));
-
-cl::opt<bool> objdump::NoShowRawInsn(
-    "no-show-raw-insn",
-    cl::desc(
-        "When disassembling instructions, do not print the instruction bytes."),
-    cl::cat(ObjdumpCat));
-
-cl::opt<bool> objdump::NoLeadingAddr("no-leading-addr",
-                                     cl::desc("Print no leading address"),
-                                     cl::cat(ObjdumpCat));
-
-static cl::opt<bool> RawClangAST(
-    "raw-clang-ast",
-    cl::desc("Dump the raw binary contents of the clang AST section"),
-    cl::cat(ObjdumpCat));
-
-cl::opt<bool>
-    objdump::Relocations("reloc",
-                         cl::desc("Display the relocation entries in the file"),
-                         cl::cat(ObjdumpCat));
-static cl::alias RelocationsShort("r", cl::desc("Alias for --reloc"),
-                                  cl::NotHidden, cl::Grouping,
-                                  cl::aliasopt(Relocations));
-
-cl::opt<bool>
-    objdump::PrintImmHex("print-imm-hex",
-                         cl::desc("Use hex format for immediate values"),
-                         cl::cat(ObjdumpCat));
-
-cl::opt<bool>
-    objdump::PrivateHeaders("private-headers",
-                            cl::desc("Display format specific file headers"),
-                            cl::cat(ObjdumpCat));
-static cl::alias PrivateHeadersShort("p",
-                                     cl::desc("Alias for --private-headers"),
-                                     cl::NotHidden, cl::Grouping,
-                                     cl::aliasopt(PrivateHeaders));
-
-cl::list<std::string>
-    objdump::FilterSections("section",
-                            cl::desc("Operate on the specified sections only. "
-                                     "With --macho dump segment,section"),
-                            cl::cat(ObjdumpCat));
-static cl::alias FilterSectionsj("j", cl::desc("Alias for --section"),
-                                 cl::NotHidden, cl::Grouping, cl::Prefix,
-                                 cl::aliasopt(FilterSections));
-
-cl::opt<bool> objdump::SectionHeaders(
-    "section-headers",
-    cl::desc("Display summaries of the headers for each section."),
-    cl::cat(ObjdumpCat));
-static cl::alias SectionHeadersShort("headers",
-                                     cl::desc("Alias for --section-headers"),
-                                     cl::NotHidden,
-                                     cl::aliasopt(SectionHeaders));
-static cl::alias SectionHeadersShorter("h",
-                                       cl::desc("Alias for --section-headers"),
-                                       cl::NotHidden, cl::Grouping,
-                                       cl::aliasopt(SectionHeaders));
-
-static cl::opt<bool>
-    ShowLMA("show-lma",
-            cl::desc("Display LMA column when dumping ELF section headers"),
-            cl::cat(ObjdumpCat));
-
-static cl::opt<bool> PrintSource(
-    "source",
-    cl::desc(
-        "Display source inlined with disassembly. Implies disassemble object"),
-    cl::cat(ObjdumpCat));
-static cl::alias PrintSourceShort("S", cl::desc("Alias for --source"),
-                                  cl::NotHidden, cl::Grouping,
-                                  cl::aliasopt(PrintSource));
-
-static cl::opt<uint64_t>
-    StartAddress("start-address", cl::desc("Disassemble beginning at address"),
-                 cl::value_desc("address"), cl::init(0), cl::cat(ObjdumpCat));
-static cl::opt<uint64_t> StopAddress("stop-address",
-                                     cl::desc("Stop disassembly at address"),
-                                     cl::value_desc("address"),
-                                     cl::init(UINT64_MAX), cl::cat(ObjdumpCat));
-
-cl::opt<bool> objdump::SymbolTable("syms", cl::desc("Display the symbol table"),
-                                   cl::cat(ObjdumpCat));
-static cl::alias SymbolTableShort("t", cl::desc("Alias for --syms"),
-                                  cl::NotHidden, cl::Grouping,
-                                  cl::aliasopt(SymbolTable));
-
-static cl::opt<bool> SymbolizeOperands(
-    "symbolize-operands",
-    cl::desc("Symbolize instruction operands when disassembling"),
-    cl::cat(ObjdumpCat));
-
-static cl::opt<bool> DynamicSymbolTable(
-    "dynamic-syms",
-    cl::desc("Display the contents of the dynamic symbol table"),
-    cl::cat(ObjdumpCat));
-static cl::alias DynamicSymbolTableShort("T",
-                                         cl::desc("Alias for --dynamic-syms"),
-                                         cl::NotHidden, cl::Grouping,
-                                         cl::aliasopt(DynamicSymbolTable));
-
-cl::opt<std::string>
-    objdump::TripleName("triple",
-                        cl::desc("Target triple to disassemble for, see "
-                                 "--version for available targets"),
-                        cl::cat(ObjdumpCat));
-
-cl::opt<bool> objdump::UnwindInfo("unwind-info",
-                                  cl::desc("Display unwind information"),
-                                  cl::cat(ObjdumpCat));
-static cl::alias UnwindInfoShort("u", cl::desc("Alias for --unwind-info"),
-                                 cl::NotHidden, cl::Grouping,
-                                 cl::aliasopt(UnwindInfo));
-
-static cl::opt<bool>
-    Wide("wide", cl::desc("Ignored for compatibility with GNU objdump"),
-         cl::cat(ObjdumpCat));
-static cl::alias WideShort("w", cl::Grouping, cl::aliasopt(Wide));
-
-cl::opt<std::string> objdump::Prefix("prefix",
-                                     cl::desc("Add prefix to absolute paths"),
-                                     cl::cat(ObjdumpCat));
-
-enum DebugVarsFormat {
-  DVDisabled,
-  DVUnicode,
-  DVASCII,
-};
-
-static cl::opt<DebugVarsFormat> DbgVariables(
-    "debug-vars", cl::init(DVDisabled),
-    cl::desc("Print the locations (in registers or memory) of "
-             "source-level variables alongside disassembly"),
-    cl::ValueOptional,
-    cl::values(clEnumValN(DVUnicode, "", "unicode"),
-               clEnumValN(DVUnicode, "unicode", "unicode"),
-               clEnumValN(DVASCII, "ascii", "unicode")),
-    cl::cat(ObjdumpCat));
-
-static cl::opt<int>
-    DbgIndent("debug-vars-indent", cl::init(40),
-              cl::desc("Distance to indent the source-level variable display, "
-                       "relative to the start of the disassembly"),
-              cl::cat(ObjdumpCat));
-
-static cl::extrahelp
-    HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
+int objdump::DbgIndent = 52;
 
 static StringSet<> DisasmSymbolSet;
 StringSet<> objdump::FoundSectionSet;
@@ -588,509 +428,7 @@
 /// Get the column at which we want to start printing the instruction
 /// disassembly, taking into account anything which appears to the left of it.
 unsigned getInstStartColumn(const MCSubtargetInfo &STI) {
-  return NoShowRawInsn ? 16 : STI.getTargetTriple().isX86() ? 40 : 24;
-}
-
-/// Stores a single expression representing the location of a source-level
-/// variable, along with the PC range for which that expression is valid.
-struct LiveVariable {
-  DWARFLocationExpression LocExpr;
-  const char *VarName;
-  DWARFUnit *Unit;
-  const DWARFDie FuncDie;
-
-  LiveVariable(const DWARFLocationExpression &LocExpr, const char *VarName,
-               DWARFUnit *Unit, const DWARFDie FuncDie)
-      : LocExpr(LocExpr), VarName(VarName), Unit(Unit), FuncDie(FuncDie) {}
-
-  bool liveAtAddress(object::SectionedAddress Addr) {
-    if (LocExpr.Range == None)
-      return false;
-    return LocExpr.Range->SectionIndex == Addr.SectionIndex &&
-           LocExpr.Range->LowPC <= Addr.Address &&
-           LocExpr.Range->HighPC > Addr.Address;
-  }
-
-  void print(raw_ostream &OS, const MCRegisterInfo &MRI) const {
-    DataExtractor Data({LocExpr.Expr.data(), LocExpr.Expr.size()},
-                       Unit->getContext().isLittleEndian(), 0);
-    DWARFExpression Expression(Data, Unit->getAddressByteSize());
-    Expression.printCompact(OS, MRI);
-  }
-};
-
-/// Helper class for printing source variable locations alongside disassembly.
-class LiveVariablePrinter {
-  // Information we want to track about one column in which we are printing a
-  // variable live range.
-  struct Column {
-    unsigned VarIdx = NullVarIdx;
-    bool LiveIn = false;
-    bool LiveOut = false;
-    bool MustDrawLabel  = false;
-
-    bool isActive() const { return VarIdx != NullVarIdx; }
-
-    static constexpr unsigned NullVarIdx = std::numeric_limits<unsigned>::max();
-  };
-
-  // All live variables we know about in the object/image file.
-  std::vector<LiveVariable> LiveVariables;
-
-  // The columns we are currently drawing.
-  IndexedMap<Column> ActiveCols;
-
-  const MCRegisterInfo &MRI;
-  const MCSubtargetInfo &STI;
-
-  void addVariable(DWARFDie FuncDie, DWARFDie VarDie) {
-    uint64_t FuncLowPC, FuncHighPC, SectionIndex;
-    FuncDie.getLowAndHighPC(FuncLowPC, FuncHighPC, SectionIndex);
-    const char *VarName = VarDie.getName(DINameKind::ShortName);
-    DWARFUnit *U = VarDie.getDwarfUnit();
-
-    Expected<DWARFLocationExpressionsVector> Locs =
-        VarDie.getLocations(dwarf::DW_AT_location);
-    if (!Locs) {
-      // If the variable doesn't have any locations, just ignore it. We don't
-      // report an error or warning here as that could be noisy on optimised
-      // code.
-      consumeError(Locs.takeError());
-      return;
-    }
-
-    for (const DWARFLocationExpression &LocExpr : *Locs) {
-      if (LocExpr.Range) {
-        LiveVariables.emplace_back(LocExpr, VarName, U, FuncDie);
-      } else {
-        // If the LocExpr does not have an associated range, it is valid for
-        // the whole of the function.
-        // TODO: technically it is not valid for any range covered by another
-        // LocExpr, does that happen in reality?
-        DWARFLocationExpression WholeFuncExpr{
-            DWARFAddressRange(FuncLowPC, FuncHighPC, SectionIndex),
-            LocExpr.Expr};
-        LiveVariables.emplace_back(WholeFuncExpr, VarName, U, FuncDie);
-      }
-    }
-  }
-
-  void addFunction(DWARFDie D) {
-    for (const DWARFDie &Child : D.children()) {
-      if (Child.getTag() == dwarf::DW_TAG_variable ||
-          Child.getTag() == dwarf::DW_TAG_formal_parameter)
-        addVariable(D, Child);
-      else
-        addFunction(Child);
-    }
-  }
-
-  // Get the column number (in characters) at which the first live variable
-  // line should be printed.
-  unsigned getIndentLevel() const {
-    return DbgIndent + getInstStartColumn(STI);
-  }
-
-  // Indent to the first live-range column to the right of the currently
-  // printed line, and return the index of that column.
-  // TODO: formatted_raw_ostream uses "column" to mean a number of characters
-  // since the last \n, and we use it to mean the number of slots in which we
-  // put live variable lines. Pick a less overloaded word.
-  unsigned moveToFirstVarColumn(formatted_raw_ostream &OS) {
-    // Logical column number: column zero is the first column we print in, each
-    // logical column is 2 physical columns wide.
-    unsigned FirstUnprintedLogicalColumn =
-        std::max((int)(OS.getColumn() - getIndentLevel() + 1) / 2, 0);
-    // Physical column number: the actual column number in characters, with
-    // zero being the left-most side of the screen.
-    unsigned FirstUnprintedPhysicalColumn =
-        getIndentLevel() + FirstUnprintedLogicalColumn * 2;
-
-    if (FirstUnprintedPhysicalColumn > OS.getColumn())
-      OS.PadToColumn(FirstUnprintedPhysicalColumn);
-
-    return FirstUnprintedLogicalColumn;
-  }
-
-  unsigned findFreeColumn() {
-    for (unsigned ColIdx = 0; ColIdx < ActiveCols.size(); ++ColIdx)
-      if (!ActiveCols[ColIdx].isActive())
-        return ColIdx;
-
-    size_t OldSize = ActiveCols.size();
-    ActiveCols.grow(std::max<size_t>(OldSize * 2, 1));
-    return OldSize;
-  }
-
-public:
-  LiveVariablePrinter(const MCRegisterInfo &MRI, const MCSubtargetInfo &STI)
-      : LiveVariables(), ActiveCols(Column()), MRI(MRI), STI(STI) {}
-
-  void dump() const {
-    for (const LiveVariable &LV : LiveVariables) {
-      dbgs() << LV.VarName << " @ " << LV.LocExpr.Range << ": ";
-      LV.print(dbgs(), MRI);
-      dbgs() << "\n";
-    }
-  }
-
-  void addCompileUnit(DWARFDie D) {
-    if (D.getTag() == dwarf::DW_TAG_subprogram)
-      addFunction(D);
-    else
-      for (const DWARFDie &Child : D.children())
-        addFunction(Child);
-  }
-
-  /// Update to match the state of the instruction between ThisAddr and
-  /// NextAddr. In the common case, any live range active at ThisAddr is
-  /// live-in to the instruction, and any live range active at NextAddr is
-  /// live-out of the instruction. If IncludeDefinedVars is false, then live
-  /// ranges starting at NextAddr will be ignored.
-  void update(object::SectionedAddress ThisAddr,
-              object::SectionedAddress NextAddr, bool IncludeDefinedVars) {
-    // First, check variables which have already been assigned a column, so
-    // that we don't change their order.
-    SmallSet<unsigned, 8> CheckedVarIdxs;
-    for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) {
-      if (!ActiveCols[ColIdx].isActive())
-        continue;
-      CheckedVarIdxs.insert(ActiveCols[ColIdx].VarIdx);
-      LiveVariable &LV = LiveVariables[ActiveCols[ColIdx].VarIdx];
-      ActiveCols[ColIdx].LiveIn = LV.liveAtAddress(ThisAddr);
-      ActiveCols[ColIdx].LiveOut = LV.liveAtAddress(NextAddr);
-      LLVM_DEBUG(dbgs() << "pass 1, " << ThisAddr.Address << "-"
-                        << NextAddr.Address << ", " << LV.VarName << ", Col "
-                        << ColIdx << ": LiveIn=" << ActiveCols[ColIdx].LiveIn
-                        << ", LiveOut=" << ActiveCols[ColIdx].LiveOut << "\n");
-
-      if (!ActiveCols[ColIdx].LiveIn && !ActiveCols[ColIdx].LiveOut)
-        ActiveCols[ColIdx].VarIdx = Column::NullVarIdx;
-    }
-
-    // Next, look for variables which don't already have a column, but which
-    // are now live.
-    if (IncludeDefinedVars) {
-      for (unsigned VarIdx = 0, End = LiveVariables.size(); VarIdx < End;
-           ++VarIdx) {
-        if (CheckedVarIdxs.count(VarIdx))
-          continue;
-        LiveVariable &LV = LiveVariables[VarIdx];
-        bool LiveIn = LV.liveAtAddress(ThisAddr);
-        bool LiveOut = LV.liveAtAddress(NextAddr);
-        if (!LiveIn && !LiveOut)
-          continue;
-
-        unsigned ColIdx = findFreeColumn();
-        LLVM_DEBUG(dbgs() << "pass 2, " << ThisAddr.Address << "-"
-                          << NextAddr.Address << ", " << LV.VarName << ", Col "
-                          << ColIdx << ": LiveIn=" << LiveIn
-                          << ", LiveOut=" << LiveOut << "\n");
-        ActiveCols[ColIdx].VarIdx = VarIdx;
-        ActiveCols[ColIdx].LiveIn = LiveIn;
-        ActiveCols[ColIdx].LiveOut = LiveOut;
-        ActiveCols[ColIdx].MustDrawLabel = true;
-      }
-    }
-  }
-
-  enum class LineChar {
-    RangeStart,
-    RangeMid,
-    RangeEnd,
-    LabelVert,
-    LabelCornerNew,
-    LabelCornerActive,
-    LabelHoriz,
-  };
-  const char *getLineChar(LineChar C) const {
-    bool IsASCII = DbgVariables == DVASCII;
-    switch (C) {
-    case LineChar::RangeStart:
-      return IsASCII ? "^" : (const char *)u8"\u2548";
-    case LineChar::RangeMid:
-      return IsASCII ? "|" : (const char *)u8"\u2503";
-    case LineChar::RangeEnd:
-      return IsASCII ? "v" : (const char *)u8"\u253b";
-    case LineChar::LabelVert:
-      return IsASCII ? "|" : (const char *)u8"\u2502";
-    case LineChar::LabelCornerNew:
-      return IsASCII ? "/" : (const char *)u8"\u250c";
-    case LineChar::LabelCornerActive:
-      return IsASCII ? "|" : (const char *)u8"\u2520";
-    case LineChar::LabelHoriz:
-      return IsASCII ? "-" : (const char *)u8"\u2500";
-    }
-    llvm_unreachable("Unhandled LineChar enum");
-  }
-
-  /// Print live ranges to the right of an existing line. This assumes the
-  /// line is not an instruction, so doesn't start or end any live ranges, so
-  /// we only need to print active ranges or empty columns. If AfterInst is
-  /// true, this is being printed after the last instruction fed to update(),
-  /// otherwise this is being printed before it.
-  void printAfterOtherLine(formatted_raw_ostream &OS, bool AfterInst) {
-    if (ActiveCols.size()) {
-      unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS);
-      for (size_t ColIdx = FirstUnprintedColumn, End = ActiveCols.size();
-           ColIdx < End; ++ColIdx) {
-        if (ActiveCols[ColIdx].isActive()) {
-          if ((AfterInst && ActiveCols[ColIdx].LiveOut) ||
-              (!AfterInst && ActiveCols[ColIdx].LiveIn))
-            OS << getLineChar(LineChar::RangeMid);
-          else if (!AfterInst && ActiveCols[ColIdx].LiveOut)
-            OS << getLineChar(LineChar::LabelVert);
-          else
-            OS << " ";
-        }
-        OS << " ";
-      }
-    }
-    OS << "\n";
-  }
-
-  /// Print any live variable range info needed to the right of a
-  /// non-instruction line of disassembly. This is where we print the variable
-  /// names and expressions, with thin line-drawing characters connecting them
-  /// to the live range which starts at the next instruction. If MustPrint is
-  /// true, we have to print at least one line (with the continuation of any
-  /// already-active live ranges) because something has already been printed
-  /// earlier on this line.
-  void printBetweenInsts(formatted_raw_ostream &OS, bool MustPrint) {
-    bool PrintedSomething = false;
-    for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx) {
-      if (ActiveCols[ColIdx].isActive() && ActiveCols[ColIdx].MustDrawLabel) {
-        // First we need to print the live range markers for any active
-        // columns to the left of this one.
-        OS.PadToColumn(getIndentLevel());
-        for (unsigned ColIdx2 = 0; ColIdx2 < ColIdx; ++ColIdx2) {
-          if (ActiveCols[ColIdx2].isActive()) {
-            if (ActiveCols[ColIdx2].MustDrawLabel &&
-                           !ActiveCols[ColIdx2].LiveIn)
-              OS << getLineChar(LineChar::LabelVert) << " ";
-            else
-              OS << getLineChar(LineChar::RangeMid) << " ";
-          } else
-            OS << "  ";
-        }
-
-        // Then print the variable name and location of the new live range,
-        // with box drawing characters joining it to the live range line.
-        OS << getLineChar(ActiveCols[ColIdx].LiveIn
-                              ? LineChar::LabelCornerActive
-                              : LineChar::LabelCornerNew)
-           << getLineChar(LineChar::LabelHoriz) << " ";
-        WithColor(OS, raw_ostream::GREEN)
-            << LiveVariables[ActiveCols[ColIdx].VarIdx].VarName;
-        OS << " = ";
-        {
-          WithColor ExprColor(OS, raw_ostream::CYAN);
-          LiveVariables[ActiveCols[ColIdx].VarIdx].print(OS, MRI);
-        }
-
-        // If there are any columns to the right of the expression we just
-        // printed, then continue their live range lines.
-        unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS);
-        for (unsigned ColIdx2 = FirstUnprintedColumn, End = ActiveCols.size();
-             ColIdx2 < End; ++ColIdx2) {
-          if (ActiveCols[ColIdx2].isActive() && ActiveCols[ColIdx2].LiveIn)
-            OS << getLineChar(LineChar::RangeMid) << " ";
-          else
-            OS << "  ";
-        }
-
-        OS << "\n";
-        PrintedSomething = true;
-      }
-    }
-
-    for (unsigned ColIdx = 0, End = ActiveCols.size(); ColIdx < End; ++ColIdx)
-      if (ActiveCols[ColIdx].isActive())
-        ActiveCols[ColIdx].MustDrawLabel = false;
-
-    // If we must print something (because we printed a line/column number),
-    // but don't have any new variables to print, then print a line which
-    // just continues any existing live ranges.
-    if (MustPrint && !PrintedSomething)
-      printAfterOtherLine(OS, false);
-  }
-
-  /// Print the live variable ranges to the right of a disassembled instruction.
-  void printAfterInst(formatted_raw_ostream &OS) {
-    if (!ActiveCols.size())
-      return;
-    unsigned FirstUnprintedColumn = moveToFirstVarColumn(OS);
-    for (unsigned ColIdx = FirstUnprintedColumn, End = ActiveCols.size();
-         ColIdx < End; ++ColIdx) {
-      if (!ActiveCols[ColIdx].isActive())
-        OS << "  ";
-      else if (ActiveCols[ColIdx].LiveIn && ActiveCols[ColIdx].LiveOut)
-        OS << getLineChar(LineChar::RangeMid) << " ";
-      else if (ActiveCols[ColIdx].LiveOut)
-        OS << getLineChar(LineChar::RangeStart) << " ";
-      else if (ActiveCols[ColIdx].LiveIn)
-        OS << getLineChar(LineChar::RangeEnd) << " ";
-      else
-        llvm_unreachable("var must be live in or out!");
-    }
-  }
-};
-
-class SourcePrinter {
-protected:
-  DILineInfo OldLineInfo;
-  const ObjectFile *Obj = nullptr;
-  std::unique_ptr<symbolize::LLVMSymbolizer> Symbolizer;
-  // File name to file contents of source.
-  std::unordered_map<std::string, std::unique_ptr<MemoryBuffer>> SourceCache;
-  // Mark the line endings of the cached source.
-  std::unordered_map<std::string, std::vector<StringRef>> LineCache;
-  // Keep track of missing sources.
-  StringSet<> MissingSources;
-  // Only emit 'invalid debug info' warning once.
-  bool WarnedInvalidDebugInfo = false;
-
-private:
-  bool cacheSource(const DILineInfo& LineInfoFile);
-
-  void printLines(formatted_raw_ostream &OS, const DILineInfo &LineInfo,
-                  StringRef Delimiter, LiveVariablePrinter &LVP);
-
-  void printSources(formatted_raw_ostream &OS, const DILineInfo &LineInfo,
-                    StringRef ObjectFilename, StringRef Delimiter,
-                    LiveVariablePrinter &LVP);
-
-public:
-  SourcePrinter() = default;
-  SourcePrinter(const ObjectFile *Obj, StringRef DefaultArch) : Obj(Obj) {
-    symbolize::LLVMSymbolizer::Options SymbolizerOpts;
-    SymbolizerOpts.PrintFunctions =
-        DILineInfoSpecifier::FunctionNameKind::LinkageName;
-    SymbolizerOpts.Demangle = Demangle;
-    SymbolizerOpts.DefaultArch = std::string(DefaultArch);
-    Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts));
-  }
-  virtual ~SourcePrinter() = default;
-  virtual void printSourceLine(formatted_raw_ostream &OS,
-                               object::SectionedAddress Address,
-                               StringRef ObjectFilename,
-                               LiveVariablePrinter &LVP,
-                               StringRef Delimiter = "; ");
-};
-
-bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) {
-  std::unique_ptr<MemoryBuffer> Buffer;
-  if (LineInfo.Source) {
-    Buffer = MemoryBuffer::getMemBuffer(*LineInfo.Source);
-  } else {
-    auto BufferOrError = MemoryBuffer::getFile(LineInfo.FileName);
-    if (!BufferOrError) {
-      if (MissingSources.insert(LineInfo.FileName).second)
-        reportWarning("failed to find source " + LineInfo.FileName,
-                      Obj->getFileName());
-      return false;
-    }
-    Buffer = std::move(*BufferOrError);
-  }
-  // Chomp the file to get lines
-  const char *BufferStart = Buffer->getBufferStart(),
-             *BufferEnd = Buffer->getBufferEnd();
-  std::vector<StringRef> &Lines = LineCache[LineInfo.FileName];
-  const char *Start = BufferStart;
-  for (const char *I = BufferStart; I != BufferEnd; ++I)
-    if (*I == '\n') {
-      Lines.emplace_back(Start, I - Start - (BufferStart < I && I[-1] == '\r'));
-      Start = I + 1;
-    }
-  if (Start < BufferEnd)
-    Lines.emplace_back(Start, BufferEnd - Start);
-  SourceCache[LineInfo.FileName] = std::move(Buffer);
-  return true;
-}
-
-void SourcePrinter::printSourceLine(formatted_raw_ostream &OS,
-                                    object::SectionedAddress Address,
-                                    StringRef ObjectFilename,
-                                    LiveVariablePrinter &LVP,
-                                    StringRef Delimiter) {
-  if (!Symbolizer)
-    return;
-
-  DILineInfo LineInfo = DILineInfo();
-  Expected<DILineInfo> ExpectedLineInfo =
-      Symbolizer->symbolizeCode(*Obj, Address);
-  std::string ErrorMessage;
-  if (ExpectedLineInfo) {
-    LineInfo = *ExpectedLineInfo;
-  } else if (!WarnedInvalidDebugInfo) {
-    WarnedInvalidDebugInfo = true;
-    // TODO Untested.
-    reportWarning("failed to parse debug information: " +
-                      toString(ExpectedLineInfo.takeError()),
-                  ObjectFilename);
-  }
-
-  if (!Prefix.empty() && sys::path::is_absolute_gnu(LineInfo.FileName)) {
-    SmallString<128> FilePath;
-    sys::path::append(FilePath, Prefix, LineInfo.FileName);
-
-    LineInfo.FileName = std::string(FilePath);
-  }
-
-  if (PrintLines)
-    printLines(OS, LineInfo, Delimiter, LVP);
-  if (PrintSource)
-    printSources(OS, LineInfo, ObjectFilename, Delimiter, LVP);
-  OldLineInfo = LineInfo;
-}
-
-void SourcePrinter::printLines(formatted_raw_ostream &OS,
-                               const DILineInfo &LineInfo, StringRef Delimiter,
-                               LiveVariablePrinter &LVP) {
-  bool PrintFunctionName = LineInfo.FunctionName != DILineInfo::BadString &&
-                           LineInfo.FunctionName != OldLineInfo.FunctionName;
-  if (PrintFunctionName) {
-    OS << Delimiter << LineInfo.FunctionName;
-    // If demangling is successful, FunctionName will end with "()". Print it
-    // only if demangling did not run or was unsuccessful.
-    if (!StringRef(LineInfo.FunctionName).endswith("()"))
-      OS << "()";
-    OS << ":\n";
-  }
-  if (LineInfo.FileName != DILineInfo::BadString && LineInfo.Line != 0 &&
-      (OldLineInfo.Line != LineInfo.Line ||
-       OldLineInfo.FileName != LineInfo.FileName || PrintFunctionName)) {
-    OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line;
-    LVP.printBetweenInsts(OS, true);
-  }
-}
-
-void SourcePrinter::printSources(formatted_raw_ostream &OS,
-                                 const DILineInfo &LineInfo,
-                                 StringRef ObjectFilename, StringRef Delimiter,
-                                 LiveVariablePrinter &LVP) {
-  if (LineInfo.FileName == DILineInfo::BadString || LineInfo.Line == 0 ||
-      (OldLineInfo.Line == LineInfo.Line &&
-       OldLineInfo.FileName == LineInfo.FileName))
-    return;
-
-  if (SourceCache.find(LineInfo.FileName) == SourceCache.end())
-    if (!cacheSource(LineInfo))
-      return;
-  auto LineBuffer = LineCache.find(LineInfo.FileName);
-  if (LineBuffer != LineCache.end()) {
-    if (LineInfo.Line > LineBuffer->second.size()) {
-      reportWarning(
-          formatv(
-              "debug info line number {0} exceeds the number of lines in {1}",
-              LineInfo.Line, LineInfo.FileName),
-          ObjectFilename);
-      return;
-    }
-    // Vector begins at 0, line numbers are non-zero
-    OS << Delimiter << LineBuffer->second[LineInfo.Line - 1];
-    LVP.printBetweenInsts(OS, true);
-  }
+  return !ShowRawInsn ? 16 : STI.getTargetTriple().isX86() ? 40 : 24;
 }
 
 static bool isAArch64Elf(const ObjectFile *Obj) {
@@ -1133,9 +471,9 @@
     LVP.printBetweenInsts(OS, false);
 
     size_t Start = OS.tell();
-    if (!NoLeadingAddr)
+    if (LeadingAddr)
       OS << format("%8" PRIx64 ":", Address.Address);
-    if (!NoShowRawInsn) {
+    if (ShowRawInsn) {
       OS << ' ';
       dumpBytes(Bytes, OS);
     }
@@ -1166,9 +504,9 @@
                  formatted_raw_ostream &OS) {
     uint32_t opcode =
       (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | Bytes[0];
-    if (!NoLeadingAddr)
+    if (LeadingAddr)
       OS << format("%8" PRIx64 ":", Address);
-    if (!NoShowRawInsn) {
+    if (ShowRawInsn) {
       OS << "\t";
       dumpBytes(Bytes.slice(0, 4), OS);
       OS << format("\t%08" PRIx32, opcode);
@@ -1303,9 +641,9 @@
                  LiveVariablePrinter &LVP) override {
     if (SP && (PrintSource || PrintLines))
       SP->printSourceLine(OS, Address, ObjectFilename, LVP);
-    if (!NoLeadingAddr)
+    if (LeadingAddr)
       OS << format("%8" PRId64 ":", Address.Address / 8);
-    if (!NoShowRawInsn) {
+    if (ShowRawInsn) {
       OS << "\t";
       dumpBytes(Bytes, OS);
     }
@@ -1398,6 +736,43 @@
     llvm_unreachable("Unsupported binary format");
 }
 
+static Optional<SectionRef> getWasmCodeSection(const WasmObjectFile *Obj) {
+  for (auto SecI : Obj->sections()) {
+    const WasmSection &Section = Obj->getWasmSection(SecI);
+    if (Section.Type == wasm::WASM_SEC_CODE)
+      return SecI;
+  }
+  return None;
+}
+
+static void
+addMissingWasmCodeSymbols(const WasmObjectFile *Obj,
+                          std::map<SectionRef, SectionSymbolsTy> &AllSymbols) {
+  Optional<SectionRef> Section = getWasmCodeSection(Obj);
+  if (!Section)
+    return;
+  SectionSymbolsTy &Symbols = AllSymbols[*Section];
+
+  std::set<uint64_t> SymbolAddresses;
+  for (const auto &Sym : Symbols)
+    SymbolAddresses.insert(Sym.Addr);
+
+  for (const wasm::WasmFunction &Function : Obj->functions()) {
+    uint64_t Address = Function.CodeSectionOffset;
+    // Only add fallback symbols for functions not already present in the symbol
+    // table.
+    if (SymbolAddresses.count(Address))
+      continue;
+    // This function has no symbol, so it should have no SymbolName.
+    assert(Function.SymbolName.empty());
+    // We use DebugName for the name, though it may be empty if there is no
+    // "name" custom section, or that section is missing a name for this
+    // function.
+    StringRef Name = Function.DebugName;
+    Symbols.emplace_back(Address, Name, ELF::STT_NOTYPE);
+  }
+}
+
 static void addPltEntries(const ObjectFile *Obj,
                           std::map<SectionRef, SectionSymbolsTy> &AllSymbols,
                           StringSaver &Saver) {
@@ -1473,8 +848,7 @@
     if (Relocated == Obj.section_end() || !checkSectionFilter(*Relocated).Keep)
       continue;
     std::vector<RelocationRef> &V = Ret[*Relocated];
-    for (const RelocationRef &R : Sec.relocations())
-      V.push_back(R);
+    append_range(V, Sec.relocations());
     // Sort relocations by address.
     llvm::stable_sort(V, isRelocAddressLess);
   }
@@ -1635,6 +1009,63 @@
   }
 }
 
+// Create an MCSymbolizer for the target and add it to the MCDisassembler.
+// This is currently only used on AMDGPU, and assumes the format of the
+// void * argument passed to AMDGPU's createMCSymbolizer.
+static void addSymbolizer(
+    MCContext &Ctx, const Target *Target, StringRef TripleName,
+    MCDisassembler *DisAsm, uint64_t SectionAddr, ArrayRef<uint8_t> Bytes,
+    SectionSymbolsTy &Symbols,
+    std::vector<std::unique_ptr<std::string>> &SynthesizedLabelNames) {
+
+  std::unique_ptr<MCRelocationInfo> RelInfo(
+      Target->createMCRelocationInfo(TripleName, Ctx));
+  if (!RelInfo)
+    return;
+  std::unique_ptr<MCSymbolizer> Symbolizer(Target->createMCSymbolizer(
+      TripleName, nullptr, nullptr, &Symbols, &Ctx, std::move(RelInfo)));
+  MCSymbolizer *SymbolizerPtr = &*Symbolizer;
+  DisAsm->setSymbolizer(std::move(Symbolizer));
+
+  if (!SymbolizeOperands)
+    return;
+
+  // Synthesize labels referenced by branch instructions by
+  // disassembling, discarding the output, and collecting the referenced
+  // addresses from the symbolizer.
+  for (size_t Index = 0; Index != Bytes.size();) {
+    MCInst Inst;
+    uint64_t Size;
+    DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), SectionAddr + Index,
+                           nulls());
+    if (Size == 0)
+      Size = 1;
+    Index += Size;
+  }
+  ArrayRef<uint64_t> LabelAddrsRef = SymbolizerPtr->getReferencedAddresses();
+  // Copy and sort to remove duplicates.
+  std::vector<uint64_t> LabelAddrs;
+  LabelAddrs.insert(LabelAddrs.end(), LabelAddrsRef.begin(),
+                    LabelAddrsRef.end());
+  llvm::sort(LabelAddrs);
+  LabelAddrs.resize(std::unique(LabelAddrs.begin(), LabelAddrs.end()) -
+                    LabelAddrs.begin());
+  // Add the labels.
+  for (unsigned LabelNum = 0; LabelNum != LabelAddrs.size(); ++LabelNum) {
+    auto Name = std::make_unique<std::string>();
+    *Name = (Twine("L") + Twine(LabelNum)).str();
+    SynthesizedLabelNames.push_back(std::move(Name));
+    Symbols.push_back(SymbolInfoTy(
+        LabelAddrs[LabelNum], *SynthesizedLabelNames.back(), ELF::STT_NOTYPE));
+  }
+  llvm::stable_sort(Symbols);
+  // Recreate the symbolizer with the new symbols list.
+  RelInfo.reset(Target->createMCRelocationInfo(TripleName, Ctx));
+  Symbolizer.reset(Target->createMCSymbolizer(
+      TripleName, nullptr, nullptr, &Symbols, &Ctx, std::move(RelInfo)));
+  DisAsm->setSymbolizer(std::move(Symbolizer));
+}
+
 static StringRef getSegmentName(const MachOObjectFile *MachO,
                                 const SectionRef &Section) {
   if (MachO) {
@@ -1645,6 +1076,29 @@
   return "";
 }
 
+static void emitPostInstructionInfo(formatted_raw_ostream &FOS,
+                                    const MCAsmInfo &MAI,
+                                    const MCSubtargetInfo &STI,
+                                    StringRef Comments,
+                                    LiveVariablePrinter &LVP) {
+  do {
+    if (!Comments.empty()) {
+      // Emit a line of comments.
+      StringRef Comment;
+      std::tie(Comment, Comments) = Comments.split('\n');
+      // MAI.getCommentColumn() assumes that instructions are printed at the
+      // position of 8, while getInstStartColumn() returns the actual position.
+      unsigned CommentColumn =
+          MAI.getCommentColumn() - 8 + getInstStartColumn(STI);
+      FOS.PadToColumn(CommentColumn);
+      FOS << MAI.getCommentString() << ' ' << Comment;
+    }
+    LVP.printAfterInst(FOS);
+    FOS << '\n';
+  } while (!Comments.empty());
+  FOS.flush();
+}
+
 static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
                               MCContext &Ctx, MCDisassembler *PrimaryDisAsm,
                               MCDisassembler *SecondaryDisAsm,
@@ -1682,10 +1136,15 @@
     if (Obj->isELF() && getElfSymbolType(Obj, Symbol) == ELF::STT_SECTION)
       continue;
 
-    // Don't ask a Mach-O STAB symbol for its section unless you know that
-    // STAB symbol's section field refers to a valid section index. Otherwise
-    // the symbol may error trying to load a section that does not exist.
     if (MachO) {
+      // __mh_(execute|dylib|dylinker|bundle|preload|object)_header are special
+      // symbols that support MachO header introspection. They do not bind to
+      // code locations and are irrelevant for disassembly.
+      if (NameOrErr->startswith("__mh_") && NameOrErr->endswith("_header"))
+        continue;
+      // Don't ask a Mach-O STAB symbol for its section unless you know that
+      // STAB symbol's section field refers to a valid section index. Otherwise
+      // the symbol may error trying to load a section that does not exist.
       DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
       uint8_t NType = (MachO->is64Bit() ?
                        MachO->getSymbol64TableEntry(SymDRI).n_type:
@@ -1704,6 +1163,9 @@
   if (AllSymbols.empty() && Obj->isELF())
     addDynamicElfSymbols(Obj, AllSymbols);
 
+  if (Obj->isWasm())
+    addMissingWasmCodeSymbols(cast<WasmObjectFile>(Obj), AllSymbols);
+
   BumpPtrAllocator A;
   StringSaver Saver(A);
   addPltEntries(Obj, AllSymbols, Saver);
@@ -1797,16 +1259,14 @@
 
     llvm::sort(MappingSymbols);
 
+    ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(
+        unwrapOrError(Section.getContents(), Obj->getFileName()));
+
+    std::vector<std::unique_ptr<std::string>> SynthesizedLabelNames;
     if (Obj->isELF() && Obj->getArch() == Triple::amdgcn) {
       // AMDGPU disassembler uses symbolizer for printing labels
-      std::unique_ptr<MCRelocationInfo> RelInfo(
-        TheTarget->createMCRelocationInfo(TripleName, Ctx));
-      if (RelInfo) {
-        std::unique_ptr<MCSymbolizer> Symbolizer(
-          TheTarget->createMCSymbolizer(
-            TripleName, nullptr, nullptr, &Symbols, &Ctx, std::move(RelInfo)));
-        DisAsm->setSymbolizer(std::move(Symbolizer));
-      }
+      addSymbolizer(Ctx, TheTarget, TripleName, DisAsm, SectionAddr, Bytes,
+                    Symbols, SynthesizedLabelNames);
     }
 
     StringRef SegmentName = getSegmentName(MachO, Section);
@@ -1822,9 +1282,6 @@
     SmallString<40> Comments;
     raw_svector_ostream CommentStream(Comments);
 
-    ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(
-        unwrapOrError(Section.getContents(), Obj->getFileName()));
-
     uint64_t VMAAdjustment = 0;
     if (shouldAdjustVA(Section))
       VMAAdjustment = AdjustVMA;
@@ -1871,7 +1328,7 @@
       }
 
       outs() << '\n';
-      if (!NoLeadingAddr)
+      if (LeadingAddr)
         outs() << format(Is64Bits ? "%016" PRIx64 " " : "%08" PRIx64 " ",
                          SectionAddr + Start + VMAAdjustment);
       if (Obj->isXCOFF() && SymbolDescription) {
@@ -2002,18 +1459,22 @@
           LVP.update({Index, Section.getIndex()},
                      {Index + Size, Section.getIndex()}, Index + Size != End);
 
+          IP->setCommentStream(CommentStream);
+
           PIP.printInst(
               *IP, Disassembled ? &Inst : nullptr, Bytes.slice(Index, Size),
               {SectionAddr + Index + VMAAdjustment, Section.getIndex()}, FOS,
               "", *STI, &SP, Obj->getFileName(), &Rels, LVP);
-          FOS << CommentStream.str();
-          Comments.clear();
+
+          IP->setCommentStream(llvm::nulls());
 
           // If disassembly has failed, avoid analysing invalid/incomplete
           // instruction information. Otherwise, try to resolve the target
           // address (jump target or memory operand address) and print it on the
           // right of the instruction.
           if (Disassembled && MIA) {
+            // Branch targets are printed just after the instructions.
+            llvm::raw_ostream *TargetOS = &FOS;
             uint64_t Target;
             bool PrintTarget =
                 MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target);
@@ -2024,8 +1485,11 @@
                 Target = *MaybeTarget;
                 PrintTarget = true;
                 // Do not print real address when symbolizing.
-                if (!SymbolizeOperands)
-                  FOS << "  # " << Twine::utohexstr(Target);
+                if (!SymbolizeOperands) {
+                  // Memory operand addresses are printed as comments.
+                  TargetOS = &CommentStream;
+                  *TargetOS << "0x" << Twine::utohexstr(Target);
+                }
               }
             if (PrintTarget) {
               // In a relocatable object, the target's section must reside in
@@ -2084,28 +1548,34 @@
                 if (Demangle)
                   TargetName = demangle(TargetName);
 
-                FOS << " <";
+                *TargetOS << " <";
                 if (!Disp) {
                   // Always Print the binary symbol precisely corresponding to
                   // the target address.
-                  FOS << TargetName;
+                  *TargetOS << TargetName;
                 } else if (!LabelAvailable) {
                   // Always Print the binary symbol plus an offset if there's no
                   // local label corresponding to the target address.
-                  FOS << TargetName << "+0x" << Twine::utohexstr(Disp);
+                  *TargetOS << TargetName << "+0x" << Twine::utohexstr(Disp);
                 } else {
-                  FOS << AllLabels[Target];
+                  *TargetOS << AllLabels[Target];
                 }
-                FOS << ">";
+                *TargetOS << ">";
               } else if (LabelAvailable) {
-                FOS << " <" << AllLabels[Target] << ">";
+                *TargetOS << " <" << AllLabels[Target] << ">";
               }
+              // By convention, each record in the comment stream should be
+              // terminated.
+              if (TargetOS == &CommentStream)
+                *TargetOS << "\n";
             }
           }
         }
 
-        LVP.printAfterInst(FOS);
-        FOS << "\n";
+        assert(Ctx.getAsmInfo());
+        emitPostInstructionInfo(FOS, *Ctx.getAsmInfo(), *STI,
+                                CommentStream.str(), LVP);
+        Comments.clear();
 
         // Hexagon does this in pretty printer
         if (Obj->getArch() != Triple::hexagon) {
@@ -2187,10 +1657,11 @@
   if (!MII)
     reportError(Obj->getFileName(),
                 "no instruction info for target " + TripleName);
-  MCObjectFileInfo MOFI;
-  MCContext Ctx(AsmInfo.get(), MRI.get(), &MOFI);
+  MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get());
   // FIXME: for now initialize MCObjectFileInfo with default values
-  MOFI.InitMCObjectFileInfo(Triple(TripleName), false, Ctx);
+  std::unique_ptr<MCObjectFileInfo> MOFI(
+      TheTarget->createMCObjectFileInfo(Ctx, /*PIC=*/false));
+  Ctx.setObjectFileInfo(MOFI.get());
 
   std::unique_ptr<MCDisassembler> DisAsm(
       TheTarget->createMCDisassembler(*STI, Ctx));
@@ -2267,7 +1738,7 @@
 
   for (std::pair<SectionRef, std::vector<SectionRef>> &P : SecToRelSec) {
     StringRef SecName = unwrapOrError(P.first.getName(), Obj->getFileName());
-    outs() << "RELOCATION RECORDS FOR [" << SecName << "]:\n";
+    outs() << "\nRELOCATION RECORDS FOR [" << SecName << "]:\n";
     uint32_t OffsetPadding = (Obj->getBytesInAddress() > 4 ? 16 : 8);
     uint32_t TypePadding = 24;
     outs() << left_justify("OFFSET", OffsetPadding) << " "
@@ -2290,7 +1761,6 @@
                << "\n";
       }
     }
-    outs() << "\n";
   }
 }
 
@@ -2350,16 +1820,13 @@
   size_t NameWidth = getMaxSectionNameWidth(Obj);
   size_t AddressWidth = 2 * Obj->getBytesInAddress();
   bool HasLMAColumn = shouldDisplayLMA(Obj);
+  outs() << "\nSections:\n";
   if (HasLMAColumn)
-    outs() << "Sections:\n"
-              "Idx "
-           << left_justify("Name", NameWidth) << " Size     "
+    outs() << "Idx " << left_justify("Name", NameWidth) << " Size     "
            << left_justify("VMA", AddressWidth) << " "
            << left_justify("LMA", AddressWidth) << " Type\n";
   else
-    outs() << "Sections:\n"
-              "Idx "
-           << left_justify("Name", NameWidth) << " Size     "
+    outs() << "Idx " << left_justify("Name", NameWidth) << " Size     "
            << left_justify("VMA", AddressWidth) << " Type\n";
 
   uint64_t Idx;
@@ -2373,9 +1840,11 @@
 
     std::string Type = Section.isText() ? "TEXT" : "";
     if (Section.isData())
-      Type += Type.empty() ? "DATA" : " DATA";
+      Type += Type.empty() ? "DATA" : ", DATA";
     if (Section.isBSS())
-      Type += Type.empty() ? "BSS" : " BSS";
+      Type += Type.empty() ? "BSS" : ", BSS";
+    if (Section.isDebugSection())
+      Type += Type.empty() ? "DEBUG" : ", DEBUG";
 
     if (HasLMAColumn)
       outs() << format("%3" PRIu64 " %-*s %08" PRIx64 " ", Idx, NameWidth,
@@ -2388,7 +1857,6 @@
                        Name.str().c_str(), Size)
              << format_hex_no_prefix(VMA, AddressWidth) << " " << Type << "\n";
   }
-  outs() << "\n";
 }
 
 void objdump::printSectionContents(const ObjectFile *Obj) {
@@ -2444,7 +1912,7 @@
 void objdump::printSymbolTable(const ObjectFile *O, StringRef ArchiveName,
                                StringRef ArchitectureName, bool DumpDynamic) {
   if (O->isCOFF() && !DumpDynamic) {
-    outs() << "SYMBOL TABLE:\n";
+    outs() << "\nSYMBOL TABLE:\n";
     printCOFFSymbolTable(cast<const COFFObjectFile>(O));
     return;
   }
@@ -2452,13 +1920,13 @@
   const StringRef FileName = O->getFileName();
 
   if (!DumpDynamic) {
-    outs() << "SYMBOL TABLE:\n";
+    outs() << "\nSYMBOL TABLE:\n";
     for (auto I = O->symbol_begin(); I != O->symbol_end(); ++I)
       printSymbol(O, *I, FileName, ArchiveName, ArchitectureName, DumpDynamic);
     return;
   }
 
-  outs() << "DYNAMIC SYMBOL TABLE:\n";
+  outs() << "\nDYNAMIC SYMBOL TABLE:\n";
   if (!O->isELF()) {
     reportWarning(
         "this operation is not currently supported for this file format",
@@ -2730,7 +2198,7 @@
 
   StringRef Fmt = O->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64;
   outs() << "start address: "
-         << "0x" << format(Fmt.data(), Address) << "\n\n";
+         << "0x" << format(Fmt.data(), Address) << "\n";
 }
 
 static void printArchiveChild(StringRef Filename, const Archive::Child &C) {
@@ -2803,11 +2271,11 @@
         return;
     }
 
-  if (StartAddress.getNumOccurrences() == 0)
+  if (!HasStartAddressFlag)
     reportWarning("no section has address less than 0x" +
                       Twine::utohexstr(Stop) + " specified by --stop-address",
                   Obj->getFileName());
-  else if (StopAddress.getNumOccurrences() == 0)
+  else if (!HasStopAddressFlag)
     reportWarning("no section has address greater than or equal to 0x" +
                       Twine::utohexstr(Start) + " specified by --start-address",
                   Obj->getFileName());
@@ -2827,10 +2295,10 @@
       outs() << A->getFileName() << "(" << O->getFileName() << ")";
     else
       outs() << O->getFileName();
-    outs() << ":\tfile format " << O->getFileFormatName().lower() << "\n\n";
+    outs() << ":\tfile format " << O->getFileFormatName().lower() << "\n";
   }
 
-  if (StartAddress.getNumOccurrences() || StopAddress.getNumOccurrences())
+  if (HasStartAddressFlag || HasStopAddressFlag)
     checkForInvalidStartStopAddress(O, StartAddress, StopAddress);
 
   // Note: the order here matches GNU objdump for compatability.
@@ -2950,33 +2418,246 @@
     reportError(errorCodeToError(object_error::invalid_file_type), file);
 }
 
+template <typename T>
+static void parseIntArg(const llvm::opt::InputArgList &InputArgs, int ID,
+                        T &Value) {
+  if (const opt::Arg *A = InputArgs.getLastArg(ID)) {
+    StringRef V(A->getValue());
+    if (!llvm::to_integer(V, Value, 0)) {
+      reportCmdLineError(A->getSpelling() +
+                         ": expected a non-negative integer, but got '" + V +
+                         "'");
+    }
+  }
+}
+
+static std::vector<std::string>
+commaSeparatedValues(const llvm::opt::InputArgList &InputArgs, int ID) {
+  std::vector<std::string> Values;
+  for (StringRef Value : InputArgs.getAllArgValues(ID)) {
+    llvm::SmallVector<StringRef, 2> SplitValues;
+    llvm::SplitString(Value, SplitValues, ",");
+    for (StringRef SplitValue : SplitValues)
+      Values.push_back(SplitValue.str());
+  }
+  return Values;
+}
+
+static void parseOtoolOptions(const llvm::opt::InputArgList &InputArgs) {
+  MachOOpt = true;
+  FullLeadingAddr = true;
+  PrintImmHex = true;
+
+  ArchName = InputArgs.getLastArgValue(OTOOL_arch).str();
+  LinkOptHints = InputArgs.hasArg(OTOOL_C);
+  if (InputArgs.hasArg(OTOOL_d))
+    FilterSections.push_back("__DATA,__data");
+  DylibId = InputArgs.hasArg(OTOOL_D);
+  UniversalHeaders = InputArgs.hasArg(OTOOL_f);
+  DataInCode = InputArgs.hasArg(OTOOL_G);
+  FirstPrivateHeader = InputArgs.hasArg(OTOOL_h);
+  IndirectSymbols = InputArgs.hasArg(OTOOL_I);
+  ShowRawInsn = InputArgs.hasArg(OTOOL_j);
+  PrivateHeaders = InputArgs.hasArg(OTOOL_l);
+  DylibsUsed = InputArgs.hasArg(OTOOL_L);
+  MCPU = InputArgs.getLastArgValue(OTOOL_mcpu_EQ).str();
+  ObjcMetaData = InputArgs.hasArg(OTOOL_o);
+  DisSymName = InputArgs.getLastArgValue(OTOOL_p).str();
+  InfoPlist = InputArgs.hasArg(OTOOL_P);
+  Relocations = InputArgs.hasArg(OTOOL_r);
+  if (const Arg *A = InputArgs.getLastArg(OTOOL_s)) {
+    auto Filter = (A->getValue(0) + StringRef(",") + A->getValue(1)).str();
+    FilterSections.push_back(Filter);
+  }
+  if (InputArgs.hasArg(OTOOL_t))
+    FilterSections.push_back("__TEXT,__text");
+  Verbose = InputArgs.hasArg(OTOOL_v) || InputArgs.hasArg(OTOOL_V) ||
+            InputArgs.hasArg(OTOOL_o);
+  SymbolicOperands = InputArgs.hasArg(OTOOL_V);
+  if (InputArgs.hasArg(OTOOL_x))
+    FilterSections.push_back(",__text");
+  LeadingAddr = LeadingHeaders = !InputArgs.hasArg(OTOOL_X);
+
+  InputFilenames = InputArgs.getAllArgValues(OTOOL_INPUT);
+  if (InputFilenames.empty())
+    reportCmdLineError("no input file");
+
+  for (const Arg *A : InputArgs) {
+    const Option &O = A->getOption();
+    if (O.getGroup().isValid() && O.getGroup().getID() == OTOOL_grp_obsolete) {
+      reportCmdLineWarning(O.getPrefixedName() +
+                           " is obsolete and not implemented");
+    }
+  }
+}
+
+static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
+  parseIntArg(InputArgs, OBJDUMP_adjust_vma_EQ, AdjustVMA);
+  AllHeaders = InputArgs.hasArg(OBJDUMP_all_headers);
+  ArchName = InputArgs.getLastArgValue(OBJDUMP_arch_name_EQ).str();
+  ArchiveHeaders = InputArgs.hasArg(OBJDUMP_archive_headers);
+  Demangle = InputArgs.hasArg(OBJDUMP_demangle);
+  Disassemble = InputArgs.hasArg(OBJDUMP_disassemble);
+  DisassembleAll = InputArgs.hasArg(OBJDUMP_disassemble_all);
+  SymbolDescription = InputArgs.hasArg(OBJDUMP_symbol_description);
+  DisassembleSymbols =
+      commaSeparatedValues(InputArgs, OBJDUMP_disassemble_symbols_EQ);
+  DisassembleZeroes = InputArgs.hasArg(OBJDUMP_disassemble_zeroes);
+  if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_dwarf_EQ)) {
+    DwarfDumpType =
+        StringSwitch<DIDumpType>(A->getValue()).Case("frames", DIDT_DebugFrame);
+  }
+  DynamicRelocations = InputArgs.hasArg(OBJDUMP_dynamic_reloc);
+  FaultMapSection = InputArgs.hasArg(OBJDUMP_fault_map_section);
+  FileHeaders = InputArgs.hasArg(OBJDUMP_file_headers);
+  SectionContents = InputArgs.hasArg(OBJDUMP_full_contents);
+  PrintLines = InputArgs.hasArg(OBJDUMP_line_numbers);
+  InputFilenames = InputArgs.getAllArgValues(OBJDUMP_INPUT);
+  MachOOpt = InputArgs.hasArg(OBJDUMP_macho);
+  MCPU = InputArgs.getLastArgValue(OBJDUMP_mcpu_EQ).str();
+  MAttrs = commaSeparatedValues(InputArgs, OBJDUMP_mattr_EQ);
+  ShowRawInsn = !InputArgs.hasArg(OBJDUMP_no_show_raw_insn);
+  LeadingAddr = !InputArgs.hasArg(OBJDUMP_no_leading_addr);
+  RawClangAST = InputArgs.hasArg(OBJDUMP_raw_clang_ast);
+  Relocations = InputArgs.hasArg(OBJDUMP_reloc);
+  PrintImmHex =
+      InputArgs.hasFlag(OBJDUMP_print_imm_hex, OBJDUMP_no_print_imm_hex, false);
+  PrivateHeaders = InputArgs.hasArg(OBJDUMP_private_headers);
+  FilterSections = InputArgs.getAllArgValues(OBJDUMP_section_EQ);
+  SectionHeaders = InputArgs.hasArg(OBJDUMP_section_headers);
+  ShowLMA = InputArgs.hasArg(OBJDUMP_show_lma);
+  PrintSource = InputArgs.hasArg(OBJDUMP_source);
+  parseIntArg(InputArgs, OBJDUMP_start_address_EQ, StartAddress);
+  HasStartAddressFlag = InputArgs.hasArg(OBJDUMP_start_address_EQ);
+  parseIntArg(InputArgs, OBJDUMP_stop_address_EQ, StopAddress);
+  HasStopAddressFlag = InputArgs.hasArg(OBJDUMP_stop_address_EQ);
+  SymbolTable = InputArgs.hasArg(OBJDUMP_syms);
+  SymbolizeOperands = InputArgs.hasArg(OBJDUMP_symbolize_operands);
+  DynamicSymbolTable = InputArgs.hasArg(OBJDUMP_dynamic_syms);
+  TripleName = InputArgs.getLastArgValue(OBJDUMP_triple_EQ).str();
+  UnwindInfo = InputArgs.hasArg(OBJDUMP_unwind_info);
+  Wide = InputArgs.hasArg(OBJDUMP_wide);
+  Prefix = InputArgs.getLastArgValue(OBJDUMP_prefix).str();
+  parseIntArg(InputArgs, OBJDUMP_prefix_strip, PrefixStrip);
+  if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_debug_vars_EQ)) {
+    DbgVariables = StringSwitch<DebugVarsFormat>(A->getValue())
+                       .Case("ascii", DVASCII)
+                       .Case("unicode", DVUnicode);
+  }
+  parseIntArg(InputArgs, OBJDUMP_debug_vars_indent_EQ, DbgIndent);
+
+  parseMachOOptions(InputArgs);
+
+  // Parse -M (--disassembler-options) and deprecated
+  // --x86-asm-syntax={att,intel}.
+  //
+  // Note, for x86, the asm dialect (AssemblerDialect) is initialized when the
+  // MCAsmInfo is constructed. MCInstPrinter::applyTargetSpecificCLOption is
+  // called too late. For now we have to use the internal cl::opt option.
+  const char *AsmSyntax = nullptr;
+  for (const auto *A : InputArgs.filtered(OBJDUMP_disassembler_options_EQ,
+                                          OBJDUMP_x86_asm_syntax_att,
+                                          OBJDUMP_x86_asm_syntax_intel)) {
+    switch (A->getOption().getID()) {
+    case OBJDUMP_x86_asm_syntax_att:
+      AsmSyntax = "--x86-asm-syntax=att";
+      continue;
+    case OBJDUMP_x86_asm_syntax_intel:
+      AsmSyntax = "--x86-asm-syntax=intel";
+      continue;
+    }
+
+    SmallVector<StringRef, 2> Values;
+    llvm::SplitString(A->getValue(), Values, ",");
+    for (StringRef V : Values) {
+      if (V == "att")
+        AsmSyntax = "--x86-asm-syntax=att";
+      else if (V == "intel")
+        AsmSyntax = "--x86-asm-syntax=intel";
+      else
+        DisassemblerOptions.push_back(V.str());
+    }
+  }
+  if (AsmSyntax) {
+    const char *Argv[] = {"llvm-objdump", AsmSyntax};
+    llvm::cl::ParseCommandLineOptions(2, Argv);
+  }
+
+  // objdump defaults to a.out if no filenames specified.
+  if (InputFilenames.empty())
+    InputFilenames.push_back("a.out");
+}
+
 int main(int argc, char **argv) {
   using namespace llvm;
   InitLLVM X(argc, argv);
-  const cl::OptionCategory *OptionFilters[] = {&ObjdumpCat, &MachOCat};
-  cl::HideUnrelatedOptions(OptionFilters);
+
+  ToolName = argv[0];
+  std::unique_ptr<CommonOptTable> T;
+  OptSpecifier Unknown, HelpFlag, HelpHiddenFlag, VersionFlag;
+
+  StringRef Stem = sys::path::stem(ToolName);
+  auto Is = [=](StringRef Tool) {
+    // We need to recognize the following filenames:
+    //
+    // llvm-objdump -> objdump
+    // llvm-otool-10.exe -> otool
+    // powerpc64-unknown-freebsd13-objdump -> objdump
+    auto I = Stem.rfind_insensitive(Tool);
+    return I != StringRef::npos &&
+           (I + Tool.size() == Stem.size() || !isAlnum(Stem[I + Tool.size()]));
+  };
+  if (Is("otool")) {
+    T = std::make_unique<OtoolOptTable>();
+    Unknown = OTOOL_UNKNOWN;
+    HelpFlag = OTOOL_help;
+    HelpHiddenFlag = OTOOL_help_hidden;
+    VersionFlag = OTOOL_version;
+  } else {
+    T = std::make_unique<ObjdumpOptTable>();
+    Unknown = OBJDUMP_UNKNOWN;
+    HelpFlag = OBJDUMP_help;
+    HelpHiddenFlag = OBJDUMP_help_hidden;
+    VersionFlag = OBJDUMP_version;
+  }
+
+  BumpPtrAllocator A;
+  StringSaver Saver(A);
+  opt::InputArgList InputArgs =
+      T->parseArgs(argc, argv, Unknown, Saver,
+                   [&](StringRef Msg) { reportCmdLineError(Msg); });
+
+  if (InputArgs.size() == 0 || InputArgs.hasArg(HelpFlag)) {
+    T->printHelp(ToolName);
+    return 0;
+  }
+  if (InputArgs.hasArg(HelpHiddenFlag)) {
+    T->printHelp(ToolName, /*show_hidden=*/true);
+    return 0;
+  }
 
   // Initialize targets and assembly printers/parsers.
   InitializeAllTargetInfos();
   InitializeAllTargetMCs();
   InitializeAllDisassemblers();
 
-  // Register the target printer for --version.
-  cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
+  if (InputArgs.hasArg(VersionFlag)) {
+    cl::PrintVersionMessage();
+    if (!Is("otool")) {
+      outs() << '\n';
+      TargetRegistry::printRegisteredTargetsForVersion(outs());
+    }
+    return 0;
+  }
 
-  cl::ParseCommandLineOptions(argc, argv, "llvm object file dumper\n", nullptr,
-                              /*EnvVar=*/nullptr,
-                              /*LongOptionsUseDoubleDash=*/true);
+  if (Is("otool"))
+    parseOtoolOptions(InputArgs);
+  else
+    parseObjdumpOptions(InputArgs);
 
   if (StartAddress >= StopAddress)
     reportCmdLineError("start address should be less than stop address");
 
-  ToolName = argv[0];
-
-  // Defaults to a.out if no filenames specified.
-  if (InputFilenames.empty())
-    InputFilenames.push_back("a.out");
-
   // Removes trailing separators from prefix.
   while (!Prefix.empty() && sys::path::is_separator(Prefix.back()))
     Prefix.pop_back();
@@ -2995,10 +2676,10 @@
       !DynamicSymbolTable && !UnwindInfo && !FaultMapSection &&
       !(MachOOpt &&
         (Bind || DataInCode || DylibId || DylibsUsed || ExportsTrie ||
-         FirstPrivateHeader || IndirectSymbols || InfoPlist || LazyBind ||
-         LinkOptHints || ObjcMetaData || Rebase || UniversalHeaders ||
-         WeakBind || !FilterSections.empty()))) {
-    cl::PrintHelpMessage();
+         FirstPrivateHeader || FunctionStarts || IndirectSymbols || InfoPlist ||
+         LazyBind || LinkOptHints || ObjcMetaData || Rebase || Rpaths ||
+         UniversalHeaders || WeakBind || !FilterSections.empty()))) {
+    T->printHelp(ToolName);
     return 2;
   }
 
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h b/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h
index 99bf191..33fb3f2 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -1,3 +1,4 @@
+//===--- llvm-objdump.h -----------------------------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -12,7 +13,6 @@
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
 #include "llvm/Object/Archive.h"
-#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/DataTypes.h"
 
@@ -30,26 +30,37 @@
 
 namespace objdump {
 
-extern cl::opt<bool> ArchiveHeaders;
-extern cl::opt<bool> Demangle;
-extern cl::opt<bool> Disassemble;
-extern cl::opt<bool> DisassembleAll;
-extern cl::opt<DIDumpType> DwarfDumpType;
-extern cl::list<std::string> FilterSections;
-extern cl::list<std::string> MAttrs;
-extern cl::opt<std::string> MCPU;
-extern cl::opt<bool> NoShowRawInsn;
-extern cl::opt<bool> NoLeadingAddr;
-extern cl::opt<std::string> Prefix;
-extern cl::opt<bool> PrintImmHex;
-extern cl::opt<bool> PrivateHeaders;
-extern cl::opt<bool> Relocations;
-extern cl::opt<bool> SectionHeaders;
-extern cl::opt<bool> SectionContents;
-extern cl::opt<bool> SymbolDescription;
-extern cl::opt<bool> SymbolTable;
-extern cl::opt<std::string> TripleName;
-extern cl::opt<bool> UnwindInfo;
+enum DebugVarsFormat {
+  DVDisabled,
+  DVUnicode,
+  DVASCII,
+};
+
+extern bool ArchiveHeaders;
+extern int DbgIndent;
+extern DebugVarsFormat DbgVariables;
+extern bool Demangle;
+extern bool Disassemble;
+extern bool DisassembleAll;
+extern DIDumpType DwarfDumpType;
+extern std::vector<std::string> FilterSections;
+extern bool LeadingAddr;
+extern std::vector<std::string> MAttrs;
+extern std::string MCPU;
+extern std::string Prefix;
+extern uint32_t PrefixStrip;
+extern bool PrintImmHex;
+extern bool PrintLines;
+extern bool PrintSource;
+extern bool PrivateHeaders;
+extern bool Relocations;
+extern bool SectionHeaders;
+extern bool SectionContents;
+extern bool ShowRawInsn;
+extern bool SymbolDescription;
+extern bool SymbolTable;
+extern std::string TripleName;
+extern bool UnwindInfo;
 
 extern StringSet<> FoundSectionSet;
 
diff --git a/src/llvm-project/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp b/src/llvm-project/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp
index dbe396d..d737f63 100644
--- a/src/llvm-project/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp
@@ -136,7 +136,7 @@
   // Create pass pipeline
   //
 
-  PassBuilder PB(false, TM.get());
+  PassBuilder PB(TM.get());
 
   LoopAnalysisManager LAM;
   FunctionAnalysisManager FAM;
@@ -243,7 +243,7 @@
     exit(1);
   }
 
-  PassBuilder PB(false, TM.get());
+  PassBuilder PB(TM.get());
   ModulePassManager MPM;
   if (auto Err = PB.parsePassPipeline(MPM, PassPipeline)) {
     errs() << *argv[0] << ": " << toString(std::move(Err)) << "\n";
diff --git a/src/llvm-project/llvm/tools/llvm-opt-report/OptReport.cpp b/src/llvm-project/llvm/tools/llvm-opt-report/OptReport.cpp
index 8d7ecfb..c47212d 100644
--- a/src/llvm-project/llvm/tools/llvm-opt-report/OptReport.cpp
+++ b/src/llvm-project/llvm/tools/llvm-opt-report/OptReport.cpp
@@ -247,7 +247,7 @@
 
 static bool writeReport(LocationInfoTy &LocationInfo) {
   std::error_code EC;
-  llvm::raw_fd_ostream OS(OutputFileName, EC, llvm::sys::fs::OF_Text);
+  llvm::raw_fd_ostream OS(OutputFileName, EC, llvm::sys::fs::OF_TextWithCRLF);
   if (EC) {
     WithColor::error() << "Can't open file " << OutputFileName << ": "
                        << EC.message() << "\n";
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
index babdb56..ef299ea 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
@@ -350,13 +350,13 @@
   StringRef Name = Group.name();
   if (Name.startswith("Import:"))
     return false;
-  if (Name.endswith_lower(".dll"))
+  if (Name.endswith_insensitive(".dll"))
     return false;
-  if (Name.equals_lower("* linker *"))
+  if (Name.equals_insensitive("* linker *"))
     return false;
-  if (Name.startswith_lower("f:\\binaries\\Intermediate\\vctools"))
+  if (Name.startswith_insensitive("f:\\binaries\\Intermediate\\vctools"))
     return false;
-  if (Name.startswith_lower("f:\\dd\\vctools\\crt"))
+  if (Name.startswith_insensitive("f:\\dd\\vctools\\crt"))
     return false;
   return true;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/InputFile.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/InputFile.cpp
index b316882..40b3562 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/InputFile.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/InputFile.cpp
@@ -288,7 +288,8 @@
         formatv("File {0} is not a supported file type", Path),
         inconvertibleErrorCode());
 
-  auto Result = MemoryBuffer::getFile(Path, -1LL, false);
+  auto Result = MemoryBuffer::getFile(Path, /*IsText=*/false,
+                                      /*RequiresNullTerminator=*/false);
   if (!Result)
     return make_error<StringError>(
         formatv("File {0} could not be opened", Path), Result.getError());
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
index 787785c..3e8b1e8 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
@@ -261,6 +261,9 @@
     RETURN_CASE(CPUType, ARM_WMMX, "arm wmmx");
     RETURN_CASE(CPUType, ARM7, "arm 7");
     RETURN_CASE(CPUType, ARM64, "arm64");
+    RETURN_CASE(CPUType, ARM64EC, "arm64ec");
+    RETURN_CASE(CPUType, ARM64X, "arm64x");
+    RETURN_CASE(CPUType, HybridX86ARM64, "hybrid x86 arm64");
     RETURN_CASE(CPUType, Omni, "omni");
     RETURN_CASE(CPUType, Ia64, "intel itanium ia64");
     RETURN_CASE(CPUType, Ia64_2, "intel itanium ia64 2");
@@ -559,7 +562,7 @@
   P.format(" `{0}`", Constant.Name);
   AutoIndent Indent(P, 7);
   P.formatLine("type = {0}, value = {1}", typeIndex(Constant.Type),
-               Constant.Value.toString(10));
+               toString(Constant.Value, 10));
   return Error::success();
 }
 
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
index 8e46a97..08006e9 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
@@ -557,7 +557,7 @@
 Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
                                                EnumeratorRecord &Enum) {
   P.format(" [{0} = {1}]", Enum.Name,
-           Enum.Value.toString(10, Enum.Value.isSigned()));
+           toString(Enum.Value, 10, Enum.Value.isSigned()));
   return Error::success();
 }
 
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
index 19f4880..b152ebd 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
@@ -748,7 +748,7 @@
 static void yamlToPdb(StringRef Path) {
   BumpPtrAllocator Allocator;
   ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
-      MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
+      MemoryBuffer::getFileOrSTDIN(Path, /*IsText=*/false,
                                    /*RequiresNullTerminator=*/false);
 
   if (ErrorOrBuffer.getError()) {
@@ -868,7 +868,6 @@
   auto &File = loadPDB(Path, Session);
 
   auto O = std::make_unique<YAMLOutputStyle>(File);
-  O = std::make_unique<YAMLOutputStyle>(File);
 
   ExitOnErr(O->dump());
 }
@@ -1431,6 +1430,8 @@
   InitLLVM X(Argc, Argv);
   ExitOnErr.setBanner("llvm-pdbutil: ");
 
+  cl::HideUnrelatedOptions(
+      {&opts::TypeCategory, &opts::FilterCategory, &opts::OtherOptions});
   cl::ParseCommandLineOptions(Argc, Argv, "LLVM PDB Dumper\n");
 
   if (opts::BytesSubcommand) {
diff --git a/src/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp b/src/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 7e53c30..66d7012 100644
--- a/src/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -20,6 +20,7 @@
 #include "llvm/ProfileData/SampleProfReader.h"
 #include "llvm/ProfileData/SampleProfWriter.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Discriminator.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
@@ -54,6 +55,14 @@
     WithColor::note() << Hint << "\n";
 }
 
+static void warn(Error E, StringRef Whence = "") {
+  if (E.isA<InstrProfError>()) {
+    handleAllErrors(std::move(E), [&](const InstrProfError &IPE) {
+      warn(IPE.message(), std::string(Whence), std::string(""));
+    });
+  }
+}
+
 static void exitWithError(Twine Message, std::string Whence = "",
                           std::string Hint = "") {
   WithColor::error();
@@ -243,7 +252,8 @@
   auto Reader = std::move(ReaderOrErr.get());
   bool IsIRProfile = Reader->isIRLevelProfile();
   bool HasCSIRProfile = Reader->hasCSIRLevelProfile();
-  if (WC->Writer.setIsIRLevelProfile(IsIRProfile, HasCSIRProfile)) {
+  if (Error E = WC->Writer.setIsIRLevelProfile(IsIRProfile, HasCSIRProfile)) {
+    consumeError(std::move(E));
     WC->Errors.emplace_back(
         make_error<StringError>(
             "Merge IR generated profile with Clang generated profile.",
@@ -297,16 +307,19 @@
                               InstrProfWriter &Writer) {
   std::error_code EC;
   raw_fd_ostream Output(OutputFilename.data(), EC,
-                        OutputFormat == PF_Text ? sys::fs::OF_Text
+                        OutputFormat == PF_Text ? sys::fs::OF_TextWithCRLF
                                                 : sys::fs::OF_None);
   if (EC)
     exitWithErrorCode(EC, OutputFilename);
 
   if (OutputFormat == PF_Text) {
     if (Error E = Writer.writeText(Output))
-      exitWithError(std::move(E));
+      warn(std::move(E));
   } else {
-    Writer.write(Output);
+    if (Output.is_displayed())
+      exitWithError("cannot write a non-text format profile to the terminal");
+    if (Error E = Writer.write(Output))
+      warn(std::move(E));
   }
 }
 
@@ -315,12 +328,9 @@
                               StringRef OutputFilename,
                               ProfileFormat OutputFormat, bool OutputSparse,
                               unsigned NumThreads, FailureMode FailMode) {
-  if (OutputFilename.compare("-") == 0)
-    exitWithError("Cannot write indexed profdata format to stdout.");
-
   if (OutputFormat != PF_Binary && OutputFormat != PF_Compact_Binary &&
       OutputFormat != PF_Ext_Binary && OutputFormat != PF_Text)
-    exitWithError("Unknown format is specified.");
+    exitWithError("unknown format is specified");
 
   std::mutex ErrorLock;
   SmallSet<instrprof_error, 4> WriterErrorCodes;
@@ -383,7 +393,7 @@
   }
   if (NumErrors == Inputs.size() ||
       (NumErrors > 0 && FailMode == failIfAnyAreInvalid))
-    exitWithError("No profiles could be merged.");
+    exitWithError("no profile can be merged");
 
   writeInstrProfile(OutputFilename, OutputFormat, Contexts[0]->Writer);
 }
@@ -441,6 +451,25 @@
 const uint64_t ColdPercentileIdx = 15;
 const uint64_t HotPercentileIdx = 11;
 
+using sampleprof::FSDiscriminatorPass;
+
+// Internal options to set FSDiscriminatorPass. Used in merge and show
+// commands.
+static cl::opt<FSDiscriminatorPass> FSDiscriminatorPassOption(
+    "fs-discriminator-pass", cl::init(PassLast), cl::Hidden,
+    cl::desc("Zero out the discriminator bits for the FS discrimiantor "
+             "pass beyond this value. The enum values are defined in "
+             "Support/Discriminator.h"),
+    cl::values(clEnumVal(Base, "Use base discriminators only"),
+               clEnumVal(Pass1, "Use base and pass 1 discriminators"),
+               clEnumVal(Pass2, "Use base and pass 1-2 discriminators"),
+               clEnumVal(Pass3, "Use base and pass 1-3 discriminators"),
+               clEnumVal(PassLast, "Use all discriminator bits (default)")));
+
+static unsigned getDiscriminatorMask() {
+  return getN1Bits(getFSPassBitEnd(FSDiscriminatorPassOption.getValue()));
+}
+
 /// Adjust the instr profile in \p WC based on the sample profile in
 /// \p Reader.
 static void
@@ -522,18 +551,18 @@
     unsigned SupplMinSizeThreshold, float ZeroCounterThreshold,
     unsigned InstrProfColdThreshold) {
   if (OutputFilename.compare("-") == 0)
-    exitWithError("Cannot write indexed profdata format to stdout.");
+    exitWithError("cannot write indexed profdata format to stdout");
   if (Inputs.size() != 1)
-    exitWithError("Expect one input to be an instr profile.");
+    exitWithError("expect one input to be an instr profile");
   if (Inputs[0].Weight != 1)
-    exitWithError("Expect instr profile doesn't have weight.");
+    exitWithError("expect instr profile doesn't have weight");
 
   StringRef InstrFilename = Inputs[0].Filename;
 
   // Read sample profile.
   LLVMContext Context;
-  auto ReaderOrErr =
-      sampleprof::SampleProfileReader::create(SampleFilename.str(), Context);
+  auto ReaderOrErr = sampleprof::SampleProfileReader::create(
+      SampleFilename.str(), Context, FSDiscriminatorPassOption);
   if (std::error_code EC = ReaderOrErr.getError())
     exitWithErrorCode(EC, SampleFilename);
   auto Reader = std::move(ReaderOrErr.get());
@@ -564,12 +593,13 @@
   Result.addTotalSamples(Samples.getTotalSamples());
   Result.addHeadSamples(Samples.getHeadSamples());
   for (const auto &BodySample : Samples.getBodySamples()) {
-    Result.addBodySamples(BodySample.first.LineOffset,
-                          BodySample.first.Discriminator,
+    uint32_t MaskedDiscriminator =
+        BodySample.first.Discriminator & getDiscriminatorMask();
+    Result.addBodySamples(BodySample.first.LineOffset, MaskedDiscriminator,
                           BodySample.second.getSamples());
     for (const auto &Target : BodySample.second.getCallTargets()) {
       Result.addCalledTargetSamples(BodySample.first.LineOffset,
-                                    BodySample.first.Discriminator,
+                                    MaskedDiscriminator,
                                     Remapper(Target.first()), Target.second);
     }
   }
@@ -656,15 +686,19 @@
 mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper,
                    StringRef OutputFilename, ProfileFormat OutputFormat,
                    StringRef ProfileSymbolListFile, bool CompressAllSections,
-                   bool UseMD5, bool GenPartialProfile, FailureMode FailMode) {
+                   bool UseMD5, bool GenPartialProfile,
+                   bool SampleMergeColdContext, bool SampleTrimColdContext,
+                   bool SampleColdContextFrameDepth, FailureMode FailMode) {
   using namespace sampleprof;
   StringMap<FunctionSamples> ProfileMap;
   SmallVector<std::unique_ptr<sampleprof::SampleProfileReader>, 5> Readers;
   LLVMContext Context;
   sampleprof::ProfileSymbolList WriterList;
   Optional<bool> ProfileIsProbeBased;
+  Optional<bool> ProfileIsCS;
   for (const auto &Input : Inputs) {
-    auto ReaderOrErr = SampleProfileReader::create(Input.Filename, Context);
+    auto ReaderOrErr = SampleProfileReader::create(Input.Filename, Context,
+                                                   FSDiscriminatorPassOption);
     if (std::error_code EC = ReaderOrErr.getError()) {
       warnOrExitGivenError(FailMode, EC, Input.Filename);
       continue;
@@ -683,11 +717,14 @@
     }
 
     StringMap<FunctionSamples> &Profiles = Reader->getProfiles();
-    if (ProfileIsProbeBased &&
+    if (ProfileIsProbeBased.hasValue() &&
         ProfileIsProbeBased != FunctionSamples::ProfileIsProbeBased)
       exitWithError(
           "cannot merge probe-based profile with non-probe-based profile");
     ProfileIsProbeBased = FunctionSamples::ProfileIsProbeBased;
+    if (ProfileIsCS.hasValue() && ProfileIsCS != FunctionSamples::ProfileIsCS)
+      exitWithError("cannot merge CS profile with non-CS profile");
+    ProfileIsCS = FunctionSamples::ProfileIsCS;
     for (StringMap<FunctionSamples>::iterator I = Profiles.begin(),
                                               E = Profiles.end();
          I != E; ++I) {
@@ -696,7 +733,7 @@
           Remapper ? remapSamples(I->second, *Remapper, Result)
                    : FunctionSamples();
       FunctionSamples &Samples = Remapper ? Remapped : I->second;
-      StringRef FName = Samples.getNameWithContext(true);
+      StringRef FName = Samples.getNameWithContext();
       MergeResult(Result, ProfileMap[FName].merge(Samples, Input.Weight));
       if (Result != sampleprof_error::success) {
         std::error_code EC = make_error_code(Result);
@@ -709,6 +746,22 @@
     if (ReaderList)
       WriterList.merge(*ReaderList);
   }
+
+  if (ProfileIsCS && (SampleMergeColdContext || SampleTrimColdContext)) {
+    // Use threshold calculated from profile summary unless specified.
+    SampleProfileSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
+    auto Summary = Builder.computeSummaryForProfiles(ProfileMap);
+    uint64_t SampleProfColdThreshold =
+        ProfileSummaryBuilder::getColdCountThreshold(
+            (Summary->getDetailedSummary()));
+
+    // Trim and merge cold context profile using cold threshold above;
+    SampleContextTrimmer(ProfileMap)
+        .trimAndMergeColdContextProfiles(
+            SampleProfColdThreshold, SampleTrimColdContext,
+            SampleMergeColdContext, SampleColdContextFrameDepth);
+  }
+
   auto WriterOrErr =
       SampleProfileWriter::create(OutputFilename, FormatMap[OutputFormat]);
   if (std::error_code EC = WriterOrErr.getError())
@@ -720,7 +773,8 @@
   auto Buffer = getInputFileBuf(ProfileSymbolListFile);
   handleExtBinaryWriter(*Writer, OutputFormat, Buffer.get(), WriterList,
                         CompressAllSections, UseMD5, GenPartialProfile);
-  Writer->write(ProfileMap);
+  if (std::error_code EC = Writer->write(ProfileMap))
+    exitWithErrorCode(std::move(EC));
 }
 
 static WeightedFile parseWeightedFile(const StringRef &WeightedFilename) {
@@ -729,7 +783,7 @@
 
   uint64_t Weight;
   if (WeightStr.getAsInteger(10, Weight) || Weight < 1)
-    exitWithError("Input weight must be a positive integer.");
+    exitWithError("input weight must be a positive integer");
 
   return {std::string(FileName), Weight};
 }
@@ -808,8 +862,7 @@
   cl::alias RemappingFileA("r", cl::desc("Alias for --remapping-file"),
                            cl::aliasopt(RemappingFile));
   cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
-                                      cl::init("-"), cl::Required,
-                                      cl::desc("Output file"));
+                                      cl::init("-"), cl::desc("Output file"));
   cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
                             cl::aliasopt(OutputFilename));
   cl::opt<ProfileKinds> ProfileKind(
@@ -851,6 +904,18 @@
       "use-md5", cl::init(false), cl::Hidden,
       cl::desc("Choose to use MD5 to represent string in name table (only "
                "meaningful for -extbinary)"));
+  cl::opt<bool> SampleMergeColdContext(
+      "sample-merge-cold-context", cl::init(false), cl::Hidden,
+      cl::desc(
+          "Merge context sample profiles whose count is below cold threshold"));
+  cl::opt<bool> SampleTrimColdContext(
+      "sample-trim-cold-context", cl::init(false), cl::Hidden,
+      cl::desc(
+          "Trim context sample profiles whose count is below cold threshold"));
+  cl::opt<uint32_t> SampleColdContextFrameDepth(
+      "sample-frame-depth-for-cold-context", cl::init(1), cl::ZeroOrMore,
+      cl::desc("Keep the last K frames while merging cold profile. 1 means the "
+               "context-less base profile"));
   cl::opt<bool> GenPartialProfile(
       "gen-partial-profile", cl::init(false), cl::Hidden,
       cl::desc("Generate a partial profile (only meaningful for -extbinary)"));
@@ -866,16 +931,16 @@
                "sample profile, if the ratio of the number of zero counters "
                "divided by the the total number of counters is above the "
                "threshold, the profile of the function will be regarded as "
-               "being harmful for performance and will be dropped. "));
+               "being harmful for performance and will be dropped."));
   cl::opt<unsigned> SupplMinSizeThreshold(
       "suppl-min-size-threshold", cl::init(10), cl::Hidden,
       cl::desc("If the size of a function is smaller than the threshold, "
                "assume it can be inlined by PGO early inliner and it won't "
-               "be adjusted based on sample profile. "));
+               "be adjusted based on sample profile."));
   cl::opt<unsigned> InstrProfColdThreshold(
       "instr-prof-cold-threshold", cl::init(0), cl::Hidden,
       cl::desc("User specified cold threshold for instr profile which will "
-               "override the cold threshold got from profile summary. "));
+               "override the cold threshold got from profile summary."));
 
   cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
 
@@ -891,7 +956,7 @@
   parseInputFilenamesFile(Buffer.get(), WeightedInputs);
 
   if (WeightedInputs.empty())
-    exitWithError("No input files specified. See " +
+    exitWithError("no input files specified. See " +
                   sys::path::filename(argv[0]) + " -help");
 
   if (DumpInputFileList) {
@@ -921,7 +986,9 @@
   else
     mergeSampleProfile(WeightedInputs, Remapper.get(), OutputFilename,
                        OutputFormat, ProfileSymbolListFile, CompressAllSections,
-                       UseMD5, GenPartialProfile, FailureMode);
+                       UseMD5, GenPartialProfile, SampleMergeColdContext,
+                       SampleTrimColdContext, SampleColdContextFrameDepth,
+                       FailureMode);
 
   return 0;
 }
@@ -938,7 +1005,7 @@
   OverlapStats Overlap;
   Error E = Overlap.accumulateCounts(BaseFilename, TestFilename, IsCS);
   if (E)
-    exitWithError(std::move(E), "Error in getting profile count sums");
+    exitWithError(std::move(E), "error in getting profile count sums");
   if (Overlap.Base.CountSum < 1.0f) {
     OS << "Sum of edge counts for profile " << BaseFilename << " is 0.\n";
     exit(0);
@@ -1548,14 +1615,15 @@
   StringMap<const FunctionSamples *> BaseFuncProf;
   const auto &BaseProfiles = BaseReader->getProfiles();
   for (const auto &BaseFunc : BaseProfiles) {
-    BaseFuncProf.try_emplace(BaseFunc.second.getName(), &(BaseFunc.second));
+    BaseFuncProf.try_emplace(BaseFunc.second.getNameWithContext(),
+                             &(BaseFunc.second));
   }
   ProfOverlap.UnionCount = BaseFuncProf.size();
 
   const auto &TestProfiles = TestReader->getProfiles();
   for (const auto &TestFunc : TestProfiles) {
     SampleOverlapStats FuncOverlap;
-    FuncOverlap.TestName = TestFunc.second.getName();
+    FuncOverlap.TestName = TestFunc.second.getNameWithContext();
     assert(TestStats.count(FuncOverlap.TestName) &&
            "TestStats should have records for all functions in test profile "
            "except inlinees");
@@ -1582,7 +1650,7 @@
 
       // Two functions match with each other. Compute function-level overlap and
       // aggregate them into profile-level overlap.
-      FuncOverlap.BaseName = Match->second->getName();
+      FuncOverlap.BaseName = Match->second->getNameWithContext();
       assert(BaseStats.count(FuncOverlap.BaseName) &&
              "BaseStats should have records for all functions in base profile "
              "except inlinees");
@@ -1631,10 +1699,11 @@
 
   // Traverse through functions in base profile but not in test profile.
   for (const auto &F : BaseFuncProf) {
-    assert(BaseStats.count(F.second->getName()) &&
+    assert(BaseStats.count(F.second->getNameWithContext()) &&
            "BaseStats should have records for all functions in base profile "
            "except inlinees");
-    const FuncSampleStats &FuncStats = BaseStats[F.second->getName()];
+    const FuncSampleStats &FuncStats =
+        BaseStats[F.second->getNameWithContext()];
     ++ProfOverlap.BaseUniqueCount;
     ProfOverlap.BaseUniqueSample += FuncStats.SampleSum;
 
@@ -1665,7 +1734,7 @@
     FuncSampleStats FuncStats;
     getFuncSampleStats(I.second, FuncStats, BaseHotThreshold);
     ProfOverlap.BaseSample += FuncStats.SampleSum;
-    BaseStats.try_emplace(I.second.getName(), FuncStats);
+    BaseStats.try_emplace(I.second.getNameWithContext(), FuncStats);
   }
 
   const auto &TestProf = TestReader->getProfiles();
@@ -1674,7 +1743,7 @@
     FuncSampleStats FuncStats;
     getFuncSampleStats(I.second, FuncStats, TestHotThreshold);
     ProfOverlap.TestSample += FuncStats.SampleSum;
-    TestStats.try_emplace(I.second.getName(), FuncStats);
+    TestStats.try_emplace(I.second.getNameWithContext(), FuncStats);
   }
 
   ProfOverlap.BaseName = StringRef(BaseFilename);
@@ -1815,11 +1884,13 @@
   using namespace sampleprof;
 
   LLVMContext Context;
-  auto BaseReaderOrErr = SampleProfileReader::create(BaseFilename, Context);
+  auto BaseReaderOrErr = SampleProfileReader::create(BaseFilename, Context,
+                                                     FSDiscriminatorPassOption);
   if (std::error_code EC = BaseReaderOrErr.getError())
     exitWithErrorCode(EC, BaseFilename);
 
-  auto TestReaderOrErr = SampleProfileReader::create(TestFilename, Context);
+  auto TestReaderOrErr = SampleProfileReader::create(TestFilename, Context,
+                                                     FSDiscriminatorPassOption);
   if (std::error_code EC = TestReaderOrErr.getError())
     exitWithErrorCode(EC, TestFilename);
 
@@ -1833,6 +1904,8 @@
   if (BaseReader->profileIsProbeBased() != TestReader->profileIsProbeBased())
     exitWithError(
         "cannot compare probe-based profile with non-probe-based profile");
+  if (BaseReader->profileIsCS() != TestReader->profileIsCS())
+    exitWithError("cannot compare CS profile with non-CS profile");
 
   // Load BaseHotThreshold and TestHotThreshold as 99-percentile threshold in
   // profile summary.
@@ -1888,21 +1961,24 @@
   cl::opt<std::string> Output("output", cl::value_desc("output"), cl::init("-"),
                               cl::desc("Output file"));
   cl::alias OutputA("o", cl::desc("Alias for --output"), cl::aliasopt(Output));
-  cl::opt<bool> IsCS("cs", cl::init(false),
-                     cl::desc("For context sensitive counts"));
+  cl::opt<bool> IsCS(
+      "cs", cl::init(false),
+      cl::desc("For context sensitive PGO counts. Does not work with CSSPGO."));
   cl::opt<unsigned long long> ValueCutoff(
       "value-cutoff", cl::init(-1),
       cl::desc(
-          "Function level overlap information for every function in test "
+          "Function level overlap information for every function (with calling "
+          "context for csspgo) in test "
           "profile with max count value greater then the parameter value"));
   cl::opt<std::string> FuncNameFilter(
       "function",
-      cl::desc("Function level overlap information for matching functions"));
+      cl::desc("Function level overlap information for matching functions. For "
+               "CSSPGO this takes a a function name with calling context"));
   cl::opt<unsigned long long> SimilarityCutoff(
       "similarity-cutoff", cl::init(0),
-      cl::desc(
-          "For sample profiles, list function names for overlapped functions "
-          "with similarities below the cutoff (percentage times 10000)."));
+      cl::desc("For sample profiles, list function names (with calling context "
+               "for csspgo) for overlapped functions "
+               "with similarities below the cutoff (percentage times 10000)."));
   cl::opt<ProfileKinds> ProfileKind(
       cl::desc("Profile kind:"), cl::init(instr),
       cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
@@ -1910,7 +1986,7 @@
   cl::ParseCommandLineOptions(argc, argv, "LLVM profile data overlap tool\n");
 
   std::error_code EC;
-  raw_fd_ostream OS(Output.data(), EC, sys::fs::OF_Text);
+  raw_fd_ostream OS(Output.data(), EC, sys::fs::OF_TextWithCRLF);
   if (EC)
     exitWithErrorCode(EC, Output);
 
@@ -1926,7 +2002,8 @@
   return 0;
 }
 
-typedef struct ValueSitesStats {
+namespace {
+struct ValueSitesStats {
   ValueSitesStats()
       : TotalNumValueSites(0), TotalNumValueSitesWithValueProfile(0),
         TotalNumValues(0) {}
@@ -1934,7 +2011,8 @@
   uint64_t TotalNumValueSitesWithValueProfile;
   uint64_t TotalNumValues;
   std::vector<unsigned> ValueSitesHistogram;
-} ValueSitesStats;
+};
+} // namespace
 
 static void traverseAllValueSites(const InstrProfRecord &Func, uint32_t VK,
                                   ValueSitesStats &Stats, raw_fd_ostream &OS,
@@ -1991,7 +2069,7 @@
                             bool ShowAllFunctions, bool ShowCS,
                             uint64_t ValueCutoff, bool OnlyListBelow,
                             const std::string &ShowFunction, bool TextFormat,
-                            raw_fd_ostream &OS) {
+                            bool ShowBinaryIds, raw_fd_ostream &OS) {
   auto ReaderOrErr = InstrProfReader::create(Filename);
   std::vector<uint32_t> Cutoffs = std::move(DetailedSummaryCutoffs);
   if (ShowDetailedSummary && Cutoffs.empty()) {
@@ -2173,6 +2251,11 @@
     OS << "Total count: " << PS->getTotalCount() << "\n";
     PS->printDetailedSummary(OS);
   }
+
+  if (ShowBinaryIds)
+    if (Error E = Reader->printBinaryIds(OS))
+      exitWithError(std::move(E), Filename);
+
   return 0;
 }
 
@@ -2307,9 +2390,9 @@
         (ProfileTotalSample > 0)
             ? (Func.getTotalSamples() * 100.0) / ProfileTotalSample
             : 0;
-    PrintValues.emplace_back(
-        HotFuncInfo(Func.getName(), Func.getTotalSamples(), TotalSamplePercent,
-                    FuncPair.second.second, Func.getEntrySamples()));
+    PrintValues.emplace_back(HotFuncInfo(
+        Func.getNameWithContext(), Func.getTotalSamples(), TotalSamplePercent,
+        FuncPair.second.second, Func.getEntrySamples()));
   }
   dumpHotFunctionList(ColumnTitle, ColumnOffset, PrintValues, HotFuncCount,
                       Profiles.size(), HotFuncSample, ProfileTotalSample,
@@ -2326,12 +2409,12 @@
                              raw_fd_ostream &OS) {
   using namespace sampleprof;
   LLVMContext Context;
-  auto ReaderOrErr = SampleProfileReader::create(Filename, Context);
+  auto ReaderOrErr =
+      SampleProfileReader::create(Filename, Context, FSDiscriminatorPassOption);
   if (std::error_code EC = ReaderOrErr.getError())
     exitWithErrorCode(EC, Filename);
 
   auto Reader = std::move(ReaderOrErr.get());
-
   if (ShowSectionInfoOnly) {
     showSectionInfo(Reader.get(), OS);
     return 0;
@@ -2423,12 +2506,11 @@
       cl::desc("Show the information of each section in the sample profile. "
                "The flag is only usable when the sample profile is in "
                "extbinary format"));
+  cl::opt<bool> ShowBinaryIds("binary-ids", cl::init(false),
+                              cl::desc("Show binary ids in the profile. "));
 
   cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n");
 
-  if (OutputFilename.empty())
-    OutputFilename = "-";
-
   if (Filename == OutputFilename) {
     errs() << sys::path::filename(argv[0])
            << ": Input file name cannot be the same as the output file name!\n";
@@ -2436,7 +2518,7 @@
   }
 
   std::error_code EC;
-  raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_Text);
+  raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF);
   if (EC)
     exitWithErrorCode(EC, OutputFilename);
 
@@ -2444,11 +2526,11 @@
     WithColor::warning() << "-function argument ignored: showing all functions\n";
 
   if (ProfileKind == instr)
-    return showInstrProfile(Filename, ShowCounts, TopNFunctions,
-                            ShowIndirectCallTargets, ShowMemOPSizes,
-                            ShowDetailedSummary, DetailedSummaryCutoffs,
-                            ShowAllFunctions, ShowCS, ValueCutoff,
-                            OnlyListBelow, ShowFunction, TextFormat, OS);
+    return showInstrProfile(
+        Filename, ShowCounts, TopNFunctions, ShowIndirectCallTargets,
+        ShowMemOPSizes, ShowDetailedSummary, DetailedSummaryCutoffs,
+        ShowAllFunctions, ShowCS, ValueCutoff, OnlyListBelow, ShowFunction,
+        TextFormat, ShowBinaryIds, OS);
   else
     return showSampleProfile(Filename, ShowCounts, ShowAllFunctions,
                              ShowDetailedSummary, ShowFunction,
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-profgen/CMakeLists.txt
index e7705eb..949b45f 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-profgen/CMakeLists.txt
@@ -5,6 +5,7 @@
   AllTargetsInfos
   Core
   MC
+  IPO
   MCDisassembler
   Object
   ProfileData
@@ -15,6 +16,7 @@
 add_llvm_tool(llvm-profgen
   llvm-profgen.cpp
   PerfReader.cpp
+  CSPreInliner.cpp
   ProfiledBinary.cpp
   ProfileGenerator.cpp
   PseudoProbe.cpp
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/CSPreInliner.cpp b/src/llvm-project/llvm/tools/llvm-profgen/CSPreInliner.cpp
new file mode 100644
index 0000000..23bdba8
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-profgen/CSPreInliner.cpp
@@ -0,0 +1,224 @@
+//===-- CSPreInliner.cpp - Profile guided preinliner -------------- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "CSPreInliner.h"
+#include "llvm/ADT/SCCIterator.h"
+#include <cstdint>
+#include <queue>
+
+#define DEBUG_TYPE "cs-preinliner"
+
+using namespace llvm;
+using namespace sampleprof;
+
+// The switches specify inline thresholds used in SampleProfileLoader inlining.
+// TODO: the actual threshold to be tuned here because the size here is based
+// on machine code not LLVM IR.
+extern cl::opt<int> SampleHotCallSiteThreshold;
+extern cl::opt<int> SampleColdCallSiteThreshold;
+extern cl::opt<int> ProfileInlineGrowthLimit;
+extern cl::opt<int> ProfileInlineLimitMin;
+extern cl::opt<int> ProfileInlineLimitMax;
+
+static cl::opt<bool> SamplePreInlineReplay(
+    "csspgo-replay-preinline", cl::Hidden, cl::init(false),
+    cl::desc(
+        "Replay previous inlining and adjust context profile accordingly"));
+
+CSPreInliner::CSPreInliner(StringMap<FunctionSamples> &Profiles,
+                           uint64_t HotThreshold, uint64_t ColdThreshold)
+    : ContextTracker(Profiles), ProfileMap(Profiles),
+      HotCountThreshold(HotThreshold), ColdCountThreshold(ColdThreshold) {}
+
+std::vector<StringRef> CSPreInliner::buildTopDownOrder() {
+  std::vector<StringRef> Order;
+  ProfiledCallGraph ProfiledCG(ContextTracker);
+
+  // Now that we have a profiled call graph, construct top-down order
+  // by building up SCC and reversing SCC order.
+  scc_iterator<ProfiledCallGraph *> I = scc_begin(&ProfiledCG);
+  while (!I.isAtEnd()) {
+    for (ProfiledCallGraphNode *Node : *I) {
+      if (Node != ProfiledCG.getEntryNode())
+        Order.push_back(Node->Name);
+    }
+    ++I;
+  }
+  std::reverse(Order.begin(), Order.end());
+
+  return Order;
+}
+
+bool CSPreInliner::getInlineCandidates(ProfiledCandidateQueue &CQueue,
+                                       const FunctionSamples *CallerSamples) {
+  assert(CallerSamples && "Expect non-null caller samples");
+
+  // Ideally we want to consider everything a function calls, but as far as
+  // context profile is concerned, only those frames that are children of
+  // current one in the trie is relavent. So we walk the trie instead of call
+  // targets from function profile.
+  ContextTrieNode *CallerNode =
+      ContextTracker.getContextFor(CallerSamples->getContext());
+
+  bool HasNewCandidate = false;
+  for (auto &Child : CallerNode->getAllChildContext()) {
+    ContextTrieNode *CalleeNode = &Child.second;
+    FunctionSamples *CalleeSamples = CalleeNode->getFunctionSamples();
+    if (!CalleeSamples)
+      continue;
+
+    // Call site count is more reliable, so we look up the corresponding call
+    // target profile in caller's context profile to retrieve call site count.
+    uint64_t CalleeEntryCount = CalleeSamples->getEntrySamples();
+    uint64_t CallsiteCount = 0;
+    LineLocation Callsite = CalleeNode->getCallSiteLoc();
+    if (auto CallTargets = CallerSamples->findCallTargetMapAt(Callsite)) {
+      SampleRecord::CallTargetMap &TargetCounts = CallTargets.get();
+      auto It = TargetCounts.find(CalleeSamples->getName());
+      if (It != TargetCounts.end())
+        CallsiteCount = It->second;
+    }
+
+    // TODO: call site and callee entry count should be mostly consistent, add
+    // check for that.
+    HasNewCandidate = true;
+    CQueue.emplace(CalleeSamples, std::max(CallsiteCount, CalleeEntryCount));
+  }
+
+  return HasNewCandidate;
+}
+
+bool CSPreInliner::shouldInline(ProfiledInlineCandidate &Candidate) {
+  // If replay inline is requested, simply follow the inline decision of the
+  // profiled binary.
+  if (SamplePreInlineReplay)
+    return Candidate.CalleeSamples->getContext().hasAttribute(
+        ContextWasInlined);
+
+  // Adjust threshold based on call site hotness, only do this for callsite
+  // prioritized inliner because otherwise cost-benefit check is done earlier.
+  unsigned int SampleThreshold = SampleColdCallSiteThreshold;
+  if (Candidate.CallsiteCount > HotCountThreshold)
+    SampleThreshold = SampleHotCallSiteThreshold;
+
+  // TODO: for small cold functions, we may inlined them and we need to keep
+  // context profile accordingly.
+  if (Candidate.CallsiteCount < ColdCountThreshold)
+    SampleThreshold = SampleColdCallSiteThreshold;
+
+  return (Candidate.SizeCost < SampleThreshold);
+}
+
+void CSPreInliner::processFunction(const StringRef Name) {
+  LLVM_DEBUG(dbgs() << "Process " << Name
+                    << " for context-sensitive pre-inlining\n");
+
+  FunctionSamples *FSamples = ContextTracker.getBaseSamplesFor(Name);
+  if (!FSamples)
+    return;
+
+  // Use the number of lines/probes as proxy for function size for now.
+  // TODO: retrieve accurate size from dwarf or binary instead.
+  unsigned FuncSize = FSamples->getBodySamples().size();
+  unsigned FuncFinalSize = FuncSize;
+  unsigned SizeLimit = FuncSize * ProfileInlineGrowthLimit;
+  SizeLimit = std::min(SizeLimit, (unsigned)ProfileInlineLimitMax);
+  SizeLimit = std::max(SizeLimit, (unsigned)ProfileInlineLimitMin);
+
+  ProfiledCandidateQueue CQueue;
+  getInlineCandidates(CQueue, FSamples);
+
+  while (!CQueue.empty() && FuncFinalSize < SizeLimit) {
+    ProfiledInlineCandidate Candidate = CQueue.top();
+    CQueue.pop();
+    bool ShouldInline = false;
+    if ((ShouldInline = shouldInline(Candidate))) {
+      // We mark context as inlined as the corresponding context profile
+      // won't be merged into that function's base profile.
+      ContextTracker.markContextSamplesInlined(Candidate.CalleeSamples);
+      Candidate.CalleeSamples->getContext().setAttribute(
+          ContextShouldBeInlined);
+      FuncFinalSize += Candidate.SizeCost;
+      getInlineCandidates(CQueue, Candidate.CalleeSamples);
+    }
+    LLVM_DEBUG(dbgs() << (ShouldInline ? "  Inlined" : "  Outlined")
+                      << " context profile for: "
+                      << Candidate.CalleeSamples->getNameWithContext()
+                      << " (callee size: " << Candidate.SizeCost
+                      << ", call count:" << Candidate.CallsiteCount << ")\n");
+  }
+
+  LLVM_DEBUG({
+    if (!CQueue.empty())
+      dbgs() << "  Inline candidates ignored due to size limit (inliner "
+                "original size: "
+             << FuncSize << ", inliner final size: " << FuncFinalSize
+             << ", size limit: " << SizeLimit << ")\n";
+
+    while (!CQueue.empty()) {
+      ProfiledInlineCandidate Candidate = CQueue.top();
+      CQueue.pop();
+      bool WasInlined =
+          Candidate.CalleeSamples->getContext().hasAttribute(ContextWasInlined);
+      dbgs() << "    " << Candidate.CalleeSamples->getNameWithContext()
+             << " (candidate size:" << Candidate.SizeCost
+             << ", call count: " << Candidate.CallsiteCount << ", previously "
+             << (WasInlined ? "inlined)\n" : "not inlined)\n");
+    }
+  });
+}
+
+void CSPreInliner::run() {
+#ifndef NDEBUG
+  auto printProfileNames = [](StringMap<FunctionSamples> &Profiles,
+                              bool IsInput) {
+    dbgs() << (IsInput ? "Input" : "Output") << " context-sensitive profiles ("
+           << Profiles.size() << " total):\n";
+    for (auto &It : Profiles) {
+      const FunctionSamples &Samples = It.second;
+      dbgs() << "  [" << Samples.getNameWithContext() << "] "
+             << Samples.getTotalSamples() << ":" << Samples.getHeadSamples()
+             << "\n";
+    }
+  };
+#endif
+
+  LLVM_DEBUG(printProfileNames(ProfileMap, true));
+
+  // Execute global pre-inliner to estimate a global top-down inline
+  // decision and merge profiles accordingly. This helps with profile
+  // merge for ThinLTO otherwise we won't be able to merge profiles back
+  // to base profile across module/thin-backend boundaries.
+  // It also helps better compress context profile to control profile
+  // size, as we now only need context profile for functions going to
+  // be inlined.
+  for (StringRef FuncName : buildTopDownOrder()) {
+    processFunction(FuncName);
+  }
+
+  // Not inlined context profiles are merged into its base, so we can
+  // trim out such profiles from the output.
+  std::vector<StringRef> ProfilesToBeRemoved;
+  for (auto &It : ProfileMap) {
+    SampleContext Context = It.second.getContext();
+    if (!Context.isBaseContext() && !Context.hasState(InlinedContext)) {
+      assert(Context.hasState(MergedContext) &&
+             "Not inlined context profile should be merged already");
+      ProfilesToBeRemoved.push_back(It.first());
+    }
+  }
+
+  for (StringRef ContextName : ProfilesToBeRemoved) {
+    ProfileMap.erase(ContextName);
+  }
+
+  // Make sure ProfileMap's key is consistent with FunctionSamples' name.
+  SampleContextTrimmer(ProfileMap).canonicalizeContextProfiles();
+
+  LLVM_DEBUG(printProfileNames(ProfileMap, false));
+}
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/CSPreInliner.h b/src/llvm-project/llvm/tools/llvm-profgen/CSPreInliner.h
new file mode 100644
index 0000000..5c65d8f
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-profgen/CSPreInliner.h
@@ -0,0 +1,92 @@
+//===-- CSPreInliner.h - Profile guided preinliner ---------------- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_PROFGEN_PGOINLINEADVISOR_H
+#define LLVM_TOOLS_LLVM_PROFGEN_PGOINLINEADVISOR_H
+
+#include "llvm/ADT/PriorityQueue.h"
+#include "llvm/ProfileData/ProfileCommon.h"
+#include "llvm/ProfileData/SampleProf.h"
+#include "llvm/Transforms/IPO/ProfiledCallGraph.h"
+#include "llvm/Transforms/IPO/SampleContextTracker.h"
+
+using namespace llvm;
+using namespace sampleprof;
+
+namespace llvm {
+namespace sampleprof {
+
+// Inline candidate seen from profile
+struct ProfiledInlineCandidate {
+  ProfiledInlineCandidate(const FunctionSamples *Samples, uint64_t Count)
+      : CalleeSamples(Samples), CallsiteCount(Count),
+        SizeCost(Samples->getBodySamples().size()) {}
+  // Context-sensitive function profile for inline candidate
+  const FunctionSamples *CalleeSamples;
+  // Call site count for an inline candidate
+  // TODO: make sure entry count for context profile and call site
+  // target count for corresponding call are consistent.
+  uint64_t CallsiteCount;
+  // Size proxy for function under particular call context.
+  // TODO: use post-inline callee size from debug info.
+  uint64_t SizeCost;
+};
+
+// Inline candidate comparer using call site weight
+struct ProfiledCandidateComparer {
+  bool operator()(const ProfiledInlineCandidate &LHS,
+                  const ProfiledInlineCandidate &RHS) {
+    if (LHS.CallsiteCount != RHS.CallsiteCount)
+      return LHS.CallsiteCount < RHS.CallsiteCount;
+
+    if (LHS.SizeCost != RHS.SizeCost)
+      return LHS.SizeCost > RHS.SizeCost;
+
+    // Tie breaker using GUID so we have stable/deterministic inlining order
+    assert(LHS.CalleeSamples && RHS.CalleeSamples &&
+           "Expect non-null FunctionSamples");
+    return LHS.CalleeSamples->getGUID(LHS.CalleeSamples->getName()) <
+           RHS.CalleeSamples->getGUID(RHS.CalleeSamples->getName());
+  }
+};
+
+using ProfiledCandidateQueue =
+    PriorityQueue<ProfiledInlineCandidate, std::vector<ProfiledInlineCandidate>,
+                  ProfiledCandidateComparer>;
+
+// Pre-compilation inliner based on context-sensitive profile.
+// The PreInliner estimates inline decision using hotness from profile
+// and cost estimation from machine code size. It helps merges context
+// profile globally and achieves better post-inine profile quality, which
+// otherwise won't be possible for ThinLTO. It also reduce context profile
+// size by only keep context that is estimated to be inlined.
+class CSPreInliner {
+public:
+  CSPreInliner(StringMap<FunctionSamples> &Profiles, uint64_t HotThreshold,
+               uint64_t ColdThreshold);
+  void run();
+
+private:
+  bool getInlineCandidates(ProfiledCandidateQueue &CQueue,
+                           const FunctionSamples *FCallerContextSamples);
+  std::vector<StringRef> buildTopDownOrder();
+  void processFunction(StringRef Name);
+  bool shouldInline(ProfiledInlineCandidate &Candidate);
+  SampleContextTracker ContextTracker;
+  StringMap<FunctionSamples> &ProfileMap;
+
+  // Count thresholds to answer isHotCount and isColdCount queries.
+  // Mirrors the threshold in ProfileSummaryInfo.
+  uint64_t HotCountThreshold;
+  uint64_t ColdCountThreshold;
+};
+
+} // end namespace sampleprof
+} // end namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.cpp b/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.cpp
index 1f84200..f6b394e 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 #include "PerfReader.h"
 #include "ProfileGenerator.h"
+#include "llvm/Support/FileSystem.h"
 
 static cl::opt<bool> ShowMmapEvents("show-mmap-events", cl::ReallyHidden,
                                     cl::init(false), cl::ZeroOrMore,
@@ -92,7 +93,8 @@
 std::shared_ptr<StringBasedCtxKey> FrameStack::getContextKey() {
   std::shared_ptr<StringBasedCtxKey> KeyStr =
       std::make_shared<StringBasedCtxKey>();
-  KeyStr->Context = Binary->getExpandedContextStr(Stack);
+  KeyStr->Context =
+      Binary->getExpandedContextStr(Stack, KeyStr->WasLeafInlined);
   if (KeyStr->Context.empty())
     return nullptr;
   KeyStr->genHashCode();
@@ -141,9 +143,11 @@
   if (!Cur->isDummyRoot()) {
     if (!Stack.pushFrame(Cur)) {
       // Process truncated context
+      // Start a new traversal ignoring its bottom context
+      T EmptyStack(Binary);
+      collectSamplesFromFrame(Cur, EmptyStack);
       for (const auto &Item : Cur->Children) {
-        // Start a new traversal ignoring its bottom context
-        collectSamplesFromFrameTrie(Item.second.get());
+        collectSamplesFromFrameTrie(Item.second.get(), EmptyStack);
       }
       return;
     }
@@ -307,18 +311,46 @@
   auto I = BinaryTable.find(BinaryName);
   // Drop the event which doesn't belong to user-provided binaries
   // or if its image is loaded at the same address
-  if (I == BinaryTable.end() || Event.BaseAddress == I->second.getBaseAddress())
+  if (I == BinaryTable.end() || Event.Address == I->second.getBaseAddress())
     return;
 
   ProfiledBinary &Binary = I->second;
 
-  // A binary image could be uploaded and then reloaded at different
-  // place, so update the address map here
-  AddrToBinaryMap.erase(Binary.getBaseAddress());
-  AddrToBinaryMap[Event.BaseAddress] = &Binary;
+  if (Event.Offset == Binary.getTextSegmentOffset()) {
+    // A binary image could be unloaded and then reloaded at different
+    // place, so update the address map here.
+    // Only update for the first executable segment and assume all other
+    // segments are loaded at consecutive memory addresses, which is the case on
+    // X64.
+    AddrToBinaryMap.erase(Binary.getBaseAddress());
+    AddrToBinaryMap[Event.Address] = &Binary;
 
-  // Update binary load address.
-  Binary.setBaseAddress(Event.BaseAddress);
+    // Update binary load address.
+    Binary.setBaseAddress(Event.Address);
+  } else {
+    // Verify segments are loaded consecutively.
+    const auto &Offsets = Binary.getTextSegmentOffsets();
+    auto It = std::lower_bound(Offsets.begin(), Offsets.end(), Event.Offset);
+    if (It != Offsets.end() && *It == Event.Offset) {
+      // The event is for loading a separate executable segment.
+      auto I = std::distance(Offsets.begin(), It);
+      const auto &PreferredAddrs = Binary.getPreferredTextSegmentAddresses();
+      if (PreferredAddrs[I] - Binary.getPreferredBaseAddress() !=
+          Event.Address - Binary.getBaseAddress())
+        exitWithError("Executable segments not loaded consecutively");
+    } else {
+      if (It == Offsets.begin())
+        exitWithError("File offset not found");
+      else {
+        // Find the segment the event falls in. A large segment could be loaded
+        // via multiple mmap calls with consecutive memory addresses.
+        --It;
+        assert(*It < Event.Offset);
+        if (Event.Offset - *It != Event.Address - Binary.getBaseAddress())
+          exitWithError("Segment not loaded by consecutive mmaps");
+      }
+    }
+  }
 }
 
 ProfiledBinary *PerfReader::getBinary(uint64_t Address) {
@@ -440,27 +472,57 @@
 
     bool SrcIsInternal = Binary->addressIsCode(Src);
     bool DstIsInternal = Binary->addressIsCode(Dst);
+    bool IsExternal = !SrcIsInternal && !DstIsInternal;
+    bool IsIncoming = !SrcIsInternal && DstIsInternal;
+    bool IsOutgoing = SrcIsInternal && !DstIsInternal;
     bool IsArtificial = false;
+
     // Ignore branches outside the current binary.
-    if (!SrcIsInternal && !DstIsInternal)
+    if (IsExternal)
       continue;
-    if (!SrcIsInternal && DstIsInternal) {
-      // For transition from external code (such as dynamic libraries) to
-      // the current binary, keep track of the branch target which will be
-      // grouped with the Source of the last transition from the current
-      // binary.
-      PrevTrDst = Dst;
-      continue;
-    }
-    if (SrcIsInternal && !DstIsInternal) {
+
+    if (IsOutgoing) {
+      if (!PrevTrDst) {
+        // This is unpaired outgoing jump which is likely due to interrupt or
+        // incomplete LBR trace. Ignore current and subsequent entries since
+        // they are likely in different contexts.
+        break;
+      }
+
+      if (Binary->addressIsReturn(Src)) {
+        // In a callback case, a return from internal code, say A, to external
+        // runtime can happen. The external runtime can then call back to
+        // another internal routine, say B. Making an artificial branch that
+        // looks like a return from A to B can confuse the unwinder to treat
+        // the instruction before B as the call instruction.
+        break;
+      }
+
       // For transition to external code, group the Source with the next
       // availabe transition target.
-      if (!PrevTrDst)
-        continue;
       Dst = PrevTrDst;
       PrevTrDst = 0;
       IsArtificial = true;
+    } else {
+      if (PrevTrDst) {
+        // If we have seen an incoming transition from external code to internal
+        // code, but not a following outgoing transition, the incoming
+        // transition is likely due to interrupt which is usually unpaired.
+        // Ignore current and subsequent entries since they are likely in
+        // different contexts.
+        break;
+      }
+
+      if (IsIncoming) {
+        // For transition from external code (such as dynamic libraries) to
+        // the current binary, keep track of the branch target which will be
+        // grouped with the Source of the last transition from the current
+        // binary.
+        PrevTrDst = Dst;
+        continue;
+      }
     }
+
     // TODO: filter out buggy duplicate branches on Skylake
 
     LBRStack.emplace_back(LBREntry(Src, Dst, IsArtificial));
@@ -586,7 +648,7 @@
   enum EventIndex {
     WHOLE_LINE = 0,
     PID = 1,
-    BASE_ADDRESS = 2,
+    MMAPPED_ADDRESS = 2,
     MMAPPED_SIZE = 3,
     PAGE_OFFSET = 4,
     BINARY_PATH = 5
@@ -603,14 +665,14 @@
   }
   MMapEvent Event;
   Fields[PID].getAsInteger(10, Event.PID);
-  Fields[BASE_ADDRESS].getAsInteger(0, Event.BaseAddress);
+  Fields[MMAPPED_ADDRESS].getAsInteger(0, Event.Address);
   Fields[MMAPPED_SIZE].getAsInteger(0, Event.Size);
   Fields[PAGE_OFFSET].getAsInteger(0, Event.Offset);
   Event.BinaryPath = Fields[BINARY_PATH];
   updateBinaryAddress(Event);
   if (ShowMmapEvents) {
     outs() << "Mmap: Binary " << Event.BinaryPath << " loaded at "
-           << format("0x%" PRIx64 ":", Event.BaseAddress) << " \n";
+           << format("0x%" PRIx64 ":", Event.Address) << " \n";
   }
   TraceIt.advance();
 }
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.h b/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.h
index b802c21..05bf2d6 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.h
+++ b/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.h
@@ -75,8 +75,33 @@
   bool IsArtificial = false;
   LBREntry(uint64_t S, uint64_t T, bool I)
       : Source(S), Target(T), IsArtificial(I) {}
+
+#ifndef NDEBUG
+  void print() const {
+    dbgs() << "from " << format("%#010x", Source) << " to "
+           << format("%#010x", Target);
+    if (IsArtificial)
+      dbgs() << " Artificial";
+  }
+#endif
 };
 
+#ifndef NDEBUG
+static inline void printLBRStack(const SmallVectorImpl<LBREntry> &LBRStack) {
+  for (size_t I = 0; I < LBRStack.size(); I++) {
+    dbgs() << "[" << I << "] ";
+    LBRStack[I].print();
+    dbgs() << "\n";
+  }
+}
+
+static inline void printCallStack(const SmallVectorImpl<uint64_t> &CallStack) {
+  for (size_t I = 0; I < CallStack.size(); I++) {
+    dbgs() << "[" << I << "] " << format("%#010x", CallStack[I]) << "\n";
+  }
+}
+#endif
+
 // Hash interface for generic data of type T
 // Data should implement a \fn getHashCode and a \fn isEqual
 // Currently getHashCode is non-virtual to avoid the overhead of calling vtable,
@@ -185,6 +210,15 @@
     }
     HashCode = Hash;
   }
+
+#ifndef NDEBUG
+  void print() const {
+    dbgs() << "LBR stack\n";
+    printLBRStack(LBRStack);
+    dbgs() << "Call stack\n";
+    printCallStack(CallStack);
+  }
+#endif
 };
 
 // After parsing the sample, we record the samples by aggregating them
@@ -224,6 +258,7 @@
       BranchSamples.emplace_back(std::make_tuple(Source, Target, Count));
     }
     bool isDummyRoot() { return Address == 0; }
+    bool isLeafFrame() { return Children.empty(); }
   };
 
   ProfiledFrame DummyTrieRoot;
@@ -311,7 +346,8 @@
 // String based context id
 struct StringBasedCtxKey : public ContextKey {
   std::string Context;
-  StringBasedCtxKey() : ContextKey(CK_StringBased){};
+  bool WasLeafInlined;
+  StringBasedCtxKey() : ContextKey(CK_StringBased), WasLeafInlined(false){};
   static bool classof(const ContextKey *K) {
     return K->getKind() == CK_StringBased;
   }
@@ -405,8 +441,13 @@
     // Callsite merging may cause the loss of original probe IDs.
     // Cutting off the context from here since the inliner will
     // not know how to consume a context with unknown callsites.
-    if (!CallProbe)
+    if (!CallProbe) {
+      if (!Cur->isLeafFrame())
+        WithColor::warning()
+            << "Untracked frame at " << format("%" PRIx64, Cur->Address)
+            << " due to missing call probe\n";
       return false;
+    }
     Stack.push_back(CallProbe);
     return true;
   }
@@ -554,7 +595,7 @@
   // The parsed MMap event
   struct MMapEvent {
     uint64_t PID = 0;
-    uint64_t BaseAddress = 0;
+    uint64_t Address = 0;
     uint64_t Size = 0;
     uint64_t Offset = 0;
     StringRef BinaryPath;
@@ -607,7 +648,6 @@
   BinaryMap BinaryTable;
   AddressBinaryMap AddrToBinaryMap; // Used by address-based lookup.
 
-private:
   BinarySampleCounterMap BinarySampleCounters;
   // Samples with the repeating time generated by the perf reader
   AggregatedCounter AggregatedSamples;
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.cpp
index 4cfadff..861dd17 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "ProfileGenerator.h"
+#include "llvm/ProfileData/ProfileCommon.h"
 
 static cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
                                            cl::Required,
@@ -15,7 +16,7 @@
                          cl::aliasopt(OutputFilename));
 
 static cl::opt<SampleProfileFormat> OutputFormat(
-    "format", cl::desc("Format of output profile"), cl::init(SPF_Text),
+    "format", cl::desc("Format of output profile"), cl::init(SPF_Ext_Binary),
     cl::values(
         clEnumValN(SPF_Binary, "binary", "Binary encoding (default)"),
         clEnumValN(SPF_Compact_Binary, "compbinary", "Compact binary encoding"),
@@ -31,18 +32,28 @@
     cl::Hidden,
     cl::location(llvm::sampleprof::CSProfileGenerator::MaxCompressionSize));
 
-static cl::opt<uint64_t> CSProfColdThres(
-    "csprof-cold-thres", cl::init(100), cl::ZeroOrMore,
-    cl::desc("Specify the total samples threshold for a context profile to "
-             "be considered cold, any cold profiles will be merged into "
-             "context-less base profiles"));
+static cl::opt<bool> CSProfMergeColdContext(
+    "csprof-merge-cold-context", cl::init(true), cl::ZeroOrMore,
+    cl::desc("If the total count of context profile is smaller than "
+             "the threshold, it will be merged into context-less base "
+             "profile."));
 
-static cl::opt<bool> CSProfKeepCold(
-    "csprof-keep-cold", cl::init(false), cl::ZeroOrMore,
-    cl::desc("This works together with --csprof-cold-thres. If the total count "
-             "of the profile after all merge is done is still smaller than the "
-             "csprof-cold-thres, it will be trimmed unless csprof-keep-cold "
-             "flag is specified."));
+static cl::opt<bool> CSProfTrimColdContext(
+    "csprof-trim-cold-context", cl::init(true), cl::ZeroOrMore,
+    cl::desc("If the total count of the profile after all merge is done "
+             "is still smaller than threshold, it will be trimmed."));
+
+static cl::opt<uint32_t> CSProfColdContextFrameDepth(
+    "csprof-frame-depth-for-cold-context", cl::init(1), cl::ZeroOrMore,
+    cl::desc("Keep the last K frames while merging cold profile. 1 means the "
+             "context-less base profile"));
+
+static cl::opt<bool> EnableCSPreInliner(
+    "csspgo-preinliner", cl::Hidden, cl::init(false),
+    cl::desc("Run a global pre-inliner to merge context profile based on "
+             "estimated global top-down inline decisions"));
+
+extern cl::opt<int> ProfileSummaryCutoffCold;
 
 using namespace llvm;
 using namespace sampleprof;
@@ -80,7 +91,8 @@
 
 void ProfileGenerator::write(std::unique_ptr<SampleProfileWriter> Writer,
                              StringMap<FunctionSamples> &ProfileMap) {
-  Writer->write(ProfileMap);
+  if (std::error_code EC = Writer->write(ProfileMap))
+    exitWithError(std::move(EC));
 }
 
 void ProfileGenerator::write() {
@@ -167,19 +179,20 @@
     Boundaries[End].addEndCount(Count);
   }
 
-  uint64_t BeginAddress = 0;
+  uint64_t BeginAddress = UINT64_MAX;
   int Count = 0;
   for (auto Item : Boundaries) {
     uint64_t Address = Item.first;
     BoundaryPoint &Point = Item.second;
     if (Point.BeginCount) {
-      if (BeginAddress)
+      if (BeginAddress != UINT64_MAX)
         DisjointRanges[{BeginAddress, Address - 1}] = Count;
       Count += Point.BeginCount;
       BeginAddress = Address;
     }
     if (Point.EndCount) {
-      assert(BeginAddress && "First boundary point cannot be 'end' point");
+      assert((BeginAddress != UINT64_MAX) &&
+             "First boundary point cannot be 'end' point");
       DisjointRanges[{BeginAddress, Address}] = Count;
       Count -= Point.EndCount;
       BeginAddress = Address + 1;
@@ -188,16 +201,52 @@
 }
 
 FunctionSamples &
-CSProfileGenerator::getFunctionProfileForContext(StringRef ContextStr) {
+CSProfileGenerator::getFunctionProfileForContext(StringRef ContextStr,
+                                                 bool WasLeafInlined) {
   auto Ret = ProfileMap.try_emplace(ContextStr, FunctionSamples());
   if (Ret.second) {
-    SampleContext FContext(Ret.first->first(), RawContext);
+    // Make a copy of the underlying context string in string table
+    // before StringRef wrapper is used for context.
+    auto It = ContextStrings.insert(ContextStr.str());
+    SampleContext FContext(*It.first, RawContext);
+    if (WasLeafInlined)
+      FContext.setAttribute(ContextWasInlined);
     FunctionSamples &FProfile = Ret.first->second;
     FProfile.setContext(FContext);
+    FProfile.setName(FContext.getNameWithoutContext());
   }
   return Ret.first->second;
 }
 
+void CSProfileGenerator::generateProfile() {
+  FunctionSamples::ProfileIsCS = true;
+  for (const auto &BI : BinarySampleCounters) {
+    ProfiledBinary *Binary = BI.first;
+    for (const auto &CI : BI.second) {
+      const StringBasedCtxKey *CtxKey =
+          dyn_cast<StringBasedCtxKey>(CI.first.getPtr());
+      StringRef ContextId(CtxKey->Context);
+      // Get or create function profile for the range
+      FunctionSamples &FunctionProfile =
+          getFunctionProfileForContext(ContextId, CtxKey->WasLeafInlined);
+
+      // Fill in function body samples
+      populateFunctionBodySamples(FunctionProfile, CI.second.RangeCounter,
+                                  Binary);
+      // Fill in boundary sample counts as well as call site samples for calls
+      populateFunctionBoundarySamples(ContextId, FunctionProfile,
+                                      CI.second.BranchCounter, Binary);
+    }
+  }
+  // Fill in call site value sample for inlined calls and also use context to
+  // infer missing samples. Since we don't have call count for inlined
+  // functions, we estimate it from inlinee's profile using the entry of the
+  // body sample.
+  populateInferredFunctionSamples();
+
+  postProcessProfiles();
+}
+
 void CSProfileGenerator::updateBodySamplesforFunctionProfile(
     FunctionSamples &FunctionProfile, const FrameLocation &LeafLoc,
     uint64_t Count) {
@@ -351,60 +400,42 @@
   }
 }
 
-void CSProfileGenerator::mergeAndTrimColdProfile(
-    StringMap<FunctionSamples> &ProfileMap) {
-  // Nothing to merge if sample threshold is zero
-  if (!CSProfColdThres)
-    return;
+void CSProfileGenerator::postProcessProfiles() {
+  // Compute hot/cold threshold based on profile. This will be used for cold
+  // context profile merging/trimming.
+  computeSummaryAndThreshold();
 
-  // Filter the cold profiles from ProfileMap and move them into a tmp
-  // container
-  std::vector<std::pair<StringRef, const FunctionSamples *>> ToRemoveVec;
-  for (const auto &I : ProfileMap) {
-    const FunctionSamples &FunctionProfile = I.second;
-    if (FunctionProfile.getTotalSamples() >= CSProfColdThres)
-      continue;
-    ToRemoveVec.emplace_back(I.getKey(), &I.second);
-  }
+  // Run global pre-inliner to adjust/merge context profile based on estimated
+  // inline decisions.
+  if (EnableCSPreInliner)
+    CSPreInliner(ProfileMap, HotCountThreshold, ColdCountThreshold).run();
 
-  // Remove the code profile from ProfileMap and merge them into BaseProileMap
-  StringMap<FunctionSamples> BaseProfileMap;
-  for (const auto &I : ToRemoveVec) {
-    auto Ret = BaseProfileMap.try_emplace(
-        I.second->getContext().getNameWithoutContext(), FunctionSamples());
-    FunctionSamples &BaseProfile = Ret.first->second;
-    BaseProfile.merge(*I.second);
-    ProfileMap.erase(I.first);
-  }
+  // Trim and merge cold context profile using cold threshold above;
+  SampleContextTrimmer(ProfileMap)
+      .trimAndMergeColdContextProfiles(
+          ColdCountThreshold, CSProfTrimColdContext, CSProfMergeColdContext,
+          CSProfColdContextFrameDepth);
+}
 
-  // Merge the base profiles into ProfileMap;
-  for (const auto &I : BaseProfileMap) {
-    // Filter the cold base profile
-    if (!CSProfKeepCold && I.second.getTotalSamples() < CSProfColdThres &&
-        ProfileMap.find(I.getKey()) == ProfileMap.end())
-      continue;
-    // Merge the profile if the original profile exists, otherwise just insert
-    // as a new profile
-    FunctionSamples &OrigProfile = getFunctionProfileForContext(I.getKey());
-    OrigProfile.merge(I.second);
-  }
+void CSProfileGenerator::computeSummaryAndThreshold() {
+  // Update the default value of cold cutoff for llvm-profgen.
+  // Do it here because we don't want to change the global default,
+  // which would lead CS profile size too large.
+  if (!ProfileSummaryCutoffCold.getNumOccurrences())
+    ProfileSummaryCutoffCold = 999000;
+
+  SampleProfileSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
+  auto Summary = Builder.computeSummaryForProfiles(ProfileMap);
+  HotCountThreshold = ProfileSummaryBuilder::getHotCountThreshold(
+      (Summary->getDetailedSummary()));
+  ColdCountThreshold = ProfileSummaryBuilder::getColdCountThreshold(
+      (Summary->getDetailedSummary()));
 }
 
 void CSProfileGenerator::write(std::unique_ptr<SampleProfileWriter> Writer,
                                StringMap<FunctionSamples> &ProfileMap) {
-  mergeAndTrimColdProfile(ProfileMap);
-  // Add bracket for context key to support different profile binary format
-  StringMap<FunctionSamples> CxtWithBracketPMap;
-  for (const auto &Item : ProfileMap) {
-    std::string ContextWithBracket = "[" + Item.first().str() + "]";
-    auto Ret = CxtWithBracketPMap.try_emplace(ContextWithBracket, Item.second);
-    assert(Ret.second && "Must be a unique context");
-    SampleContext FContext(Ret.first->first(), RawContext);
-    FunctionSamples &FProfile = Ret.first->second;
-    FProfile.setName(FContext.getNameWithContext(true));
-    FProfile.setContext(FContext);
-  }
-  Writer->write(CxtWithBracketPMap);
+  if (std::error_code EC = Writer->write(ProfileMap))
+    exitWithError(std::move(EC));
 }
 
 // Helper function to extract context prefix string stack
@@ -422,6 +453,7 @@
 void PseudoProbeCSProfileGenerator::generateProfile() {
   // Enable pseudo probe functionalities in SampleProf
   FunctionSamples::ProfileIsProbeBased = true;
+  FunctionSamples::ProfileIsCS = true;
   for (const auto &BI : BinarySampleCounters) {
     ProfiledBinary *Binary = BI.first;
     for (const auto &CI : BI.second) {
@@ -438,6 +470,8 @@
                                         ContextStrStack, Binary);
     }
   }
+
+  postProcessProfiles();
 }
 
 void PseudoProbeCSProfileGenerator::extractProbesFromRange(
@@ -486,13 +520,17 @@
   // Extract the top frame probes by looking up each address among the range in
   // the Address2ProbeMap
   extractProbesFromRange(RangeCounter, ProbeCounter, Binary);
+  std::unordered_map<PseudoProbeInlineTree *, FunctionSamples *> FrameSamples;
   for (auto PI : ProbeCounter) {
     const PseudoProbe *Probe = PI.first;
     uint64_t Count = PI.second;
     FunctionSamples &FunctionProfile =
         getFunctionProfileForLeafProbe(ContextStrStack, Probe, Binary);
-
-    FunctionProfile.addBodySamples(Probe->Index, 0, Count);
+    // Record the current frame and FunctionProfile whenever samples are
+    // collected for non-danglie probes. This is for reporting all of the
+    // zero count probes of the frame later.
+    FrameSamples[Probe->getInlineTreeNode()] = &FunctionProfile;
+    FunctionProfile.addBodySamplesForProbe(Probe->Index, Count);
     FunctionProfile.addTotalSamples(Count);
     if (Probe->isEntry()) {
       FunctionProfile.addHeadSamples(Count);
@@ -503,7 +541,7 @@
         // context id to infer caller's context id to ensure they share the
         // same context prefix.
         StringRef CalleeContextId =
-            FunctionProfile.getContext().getNameWithContext(true);
+            FunctionProfile.getContext().getNameWithContext();
         StringRef CallerContextId;
         FrameLocation &&CallerLeafFrameLoc =
             getCallerContext(CalleeContextId, CallerContextId);
@@ -520,6 +558,16 @@
             FunctionProfile.getContext().getNameWithoutContext(), Count);
       }
     }
+
+    // Assign zero count for remaining probes without sample hits to
+    // differentiate from probes optimized away, of which the counts are unknown
+    // and will be inferred by the compiler.
+    for (auto &I : FrameSamples) {
+      auto *FunctionProfile = I.second;
+      for (auto *Probe : I.first->getProbes()) {
+          FunctionProfile->addBodySamplesForProbe(Probe->Index, 0);
+      }
+    }
   }
 }
 
@@ -549,7 +597,7 @@
 
 FunctionSamples &PseudoProbeCSProfileGenerator::getFunctionProfileForLeafProbe(
     SmallVectorImpl<std::string> &ContextStrStack,
-    const PseudoProbeFuncDesc *LeafFuncDesc) {
+    const PseudoProbeFuncDesc *LeafFuncDesc, bool WasLeafInlined) {
   assert(ContextStrStack.size() && "Profile context must have the leaf frame");
   // Compress the context string except for the leaf frame
   std::string LeafFrame = ContextStrStack.back();
@@ -570,7 +618,7 @@
   OContextStr << StringRef(LeafFrame).split(":").first.str();
 
   FunctionSamples &FunctionProile =
-      getFunctionProfileForContext(OContextStr.str());
+      getFunctionProfileForContext(OContextStr.str(), WasLeafInlined);
   FunctionProile.setFunctionHash(LeafFuncDesc->FuncHash);
   return FunctionProile;
 }
@@ -581,13 +629,11 @@
   // Explicitly copy the context for appending the leaf context
   SmallVector<std::string, 16> ContextStrStackCopy(ContextStrStack.begin(),
                                                    ContextStrStack.end());
-  Binary->getInlineContextForProbe(LeafProbe, ContextStrStackCopy);
-  // Note that the context from probe doesn't include leaf frame,
-  // hence we need to retrieve and append the leaf frame.
+  Binary->getInlineContextForProbe(LeafProbe, ContextStrStackCopy, true);
   const auto *FuncDesc = Binary->getFuncDescForGUID(LeafProbe->GUID);
-  ContextStrStackCopy.emplace_back(FuncDesc->FuncName + ":" +
-                                   Twine(LeafProbe->Index).str());
-  return getFunctionProfileForLeafProbe(ContextStrStackCopy, FuncDesc);
+  bool WasLeafInlined = LeafProbe->InlineTree->hasInlineSite();
+  return getFunctionProfileForLeafProbe(ContextStrStackCopy, FuncDesc,
+                                        WasLeafInlined);
 }
 
 } // end namespace sampleprof
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.h b/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.h
index ff014ed..66ccf49 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.h
+++ b/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.h
@@ -8,10 +8,13 @@
 
 #ifndef LLVM_TOOLS_LLVM_PROGEN_PROFILEGENERATOR_H
 #define LLVM_TOOLS_LLVM_PROGEN_PROFILEGENERATOR_H
+#include "CSPreInliner.h"
 #include "ErrorHandling.h"
 #include "PerfReader.h"
 #include "ProfiledBinary.h"
 #include "llvm/ProfileData/SampleProfWriter.h"
+#include <memory>
+#include <unordered_set>
 
 using namespace llvm;
 using namespace sampleprof;
@@ -65,31 +68,7 @@
       : BinarySampleCounters(Counters){};
 
 public:
-  void generateProfile() override {
-    for (const auto &BI : BinarySampleCounters) {
-      ProfiledBinary *Binary = BI.first;
-      for (const auto &CI : BI.second) {
-        const StringBasedCtxKey *CtxKey =
-            dyn_cast<StringBasedCtxKey>(CI.first.getPtr());
-        StringRef ContextId(CtxKey->Context);
-        // Get or create function profile for the range
-        FunctionSamples &FunctionProfile =
-            getFunctionProfileForContext(ContextId);
-
-        // Fill in function body samples
-        populateFunctionBodySamples(FunctionProfile, CI.second.RangeCounter,
-                                    Binary);
-        // Fill in boundary sample counts as well as call site samples for calls
-        populateFunctionBoundarySamples(ContextId, FunctionProfile,
-                                        CI.second.BranchCounter, Binary);
-      }
-    }
-    // Fill in call site value sample for inlined calls and also use context to
-    // infer missing samples. Since we don't have call count for inlined
-    // functions, we estimate it from inlinee's profile using the entry of the
-    // body sample.
-    populateInferredFunctionSamples();
-  }
+  void generateProfile() override;
 
   // Remove adjacent repeated context sequences up to a given sequence length,
   // -1 means no size limit. Note that repeated sequences are identified based
@@ -198,13 +177,22 @@
 
 protected:
   // Lookup or create FunctionSamples for the context
-  FunctionSamples &getFunctionProfileForContext(StringRef ContextId);
-  // Merge cold context profile whose total sample is below threshold
-  // into base profile.
-  void mergeAndTrimColdProfile(StringMap<FunctionSamples> &ProfileMap);
+  FunctionSamples &getFunctionProfileForContext(StringRef ContextId,
+                                                bool WasLeafInlined = false);
+  // Post processing for profiles before writing out, such as mermining
+  // and trimming cold profiles, running preinliner on profiles.
+  void postProcessProfiles();
+  void computeSummaryAndThreshold();
   void write(std::unique_ptr<SampleProfileWriter> Writer,
              StringMap<FunctionSamples> &ProfileMap) override;
 
+  // Thresholds from profile summary to answer isHotCount/isColdCount queries.
+  uint64_t HotCountThreshold;
+  uint64_t ColdCountThreshold;
+
+  // String table owning context strings created from profile generation.
+  std::unordered_set<std::string> ContextStrings;
+
 private:
   // Helper function for updating body sample for a leaf location in
   // FunctionProfile
@@ -253,7 +241,8 @@
   // Helper function to get FunctionSamples for the leaf inlined context
   FunctionSamples &
   getFunctionProfileForLeafProbe(SmallVectorImpl<std::string> &ContextStrStack,
-                                 const PseudoProbeFuncDesc *LeafFuncDesc);
+                                 const PseudoProbeFuncDesc *LeafFuncDesc,
+                                 bool WasLeafInlined);
   // Helper function to get FunctionSamples for the leaf probe
   FunctionSamples &
   getFunctionProfileForLeafProbe(SmallVectorImpl<std::string> &ContextStrStack,
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.cpp
index df6ef2a..3f0ee4a 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.cpp
@@ -30,6 +30,10 @@
                                   cl::init(false), cl::ZeroOrMore,
                                   cl::desc("Print source locations."));
 
+cl::opt<bool> ShowCanonicalFnName("show-canonical-fname", cl::ReallyHidden,
+                                  cl::init(false), cl::ZeroOrMore,
+                                  cl::desc("Print canonical function name."));
+
 cl::opt<bool> ShowPseudoProbe(
     "show-pseudo-probe", cl::ReallyHidden, cl::init(false), cl::ZeroOrMore,
     cl::desc("Print pseudo probe section and disassembled info."));
@@ -48,38 +52,6 @@
   return TheTarget;
 }
 
-template <class ELFT>
-static uint64_t getELFImageLMAForSec(const ELFFile<ELFT> &Obj,
-                                     const object::ELFSectionRef &Sec,
-                                     StringRef FileName) {
-  // Search for a PT_LOAD segment containing the requested section. Return this
-  // segment's p_addr as the image load address for the section.
-  const auto &PhdrRange = unwrapOrError(Obj.program_headers(), FileName);
-  for (const typename ELFT::Phdr &Phdr : PhdrRange)
-    if ((Phdr.p_type == ELF::PT_LOAD) && (Phdr.p_vaddr <= Sec.getAddress()) &&
-        (Phdr.p_vaddr + Phdr.p_memsz > Sec.getAddress()))
-      // Segments will always be loaded at a page boundary.
-      return Phdr.p_paddr & ~(Phdr.p_align - 1U);
-  return 0;
-}
-
-// Get the image load address for a specific section. Note that an image is
-// loaded by segments (a group of sections) and segments may not be consecutive
-// in memory.
-static uint64_t getELFImageLMAForSec(const object::ELFSectionRef &Sec) {
-  if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Sec.getObject()))
-    return getELFImageLMAForSec(ELFObj->getELFFile(), Sec,
-                                ELFObj->getFileName());
-  else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Sec.getObject()))
-    return getELFImageLMAForSec(ELFObj->getELFFile(), Sec,
-                                ELFObj->getFileName());
-  else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Sec.getObject()))
-    return getELFImageLMAForSec(ELFObj->getELFFile(), Sec,
-                                ELFObj->getFileName());
-  const auto *ELFObj = cast<ELF64BEObjectFile>(Sec.getObject());
-  return getELFImageLMAForSec(ELFObj->getELFFile(), Sec, ELFObj->getFileName());
-}
-
 void ProfiledBinary::load() {
   // Attempt to open the binary.
   OwningBinary<Binary> OBinary = unwrapOrError(createBinary(Path), Path);
@@ -95,8 +67,8 @@
     exitWithError("unsupported target", TheTriple.getTriple());
   LLVM_DEBUG(dbgs() << "Loading " << Path << "\n");
 
-  // Find the preferred base address for text sections.
-  setPreferredBaseAddress(Obj);
+  // Find the preferred load address for text sections.
+  setPreferredTextSegmentAddresses(Obj);
 
   // Decode pseudo probe related section
   decodePseudoProbe(Obj);
@@ -127,8 +99,9 @@
                     Context2.begin(), Context2.begin() + Context2.size() - 1);
 }
 
-std::string ProfiledBinary::getExpandedContextStr(
-    const SmallVectorImpl<uint64_t> &Stack) const {
+std::string
+ProfiledBinary::getExpandedContextStr(const SmallVectorImpl<uint64_t> &Stack,
+                                      bool &WasLeafInlined) const {
   std::string ContextStr;
   SmallVector<std::string, 16> ContextVec;
   // Process from frame root to leaf
@@ -139,6 +112,9 @@
     // processing
     if (ExpandedContext.empty())
       return std::string();
+    // Set WasLeafInlined to the size of inlined frame count for the last
+    // address which is leaf
+    WasLeafInlined = (ExpandedContext.size() > 1);
     for (const auto &Loc : ExpandedContext) {
       ContextVec.push_back(getCallSite(Loc));
     }
@@ -164,16 +140,32 @@
   return OContextStr.str();
 }
 
-void ProfiledBinary::setPreferredBaseAddress(const ELFObjectFileBase *Obj) {
-  for (section_iterator SI = Obj->section_begin(), SE = Obj->section_end();
-       SI != SE; ++SI) {
-    const SectionRef &Section = *SI;
-    if (Section.isText()) {
-      PreferredBaseAddress = getELFImageLMAForSec(Section);
-      return;
-    }
+template <class ELFT>
+void ProfiledBinary::setPreferredTextSegmentAddresses(const ELFFile<ELFT> &Obj, StringRef FileName) {
+  const auto &PhdrRange = unwrapOrError(Obj.program_headers(), FileName);
+  for (const typename ELFT::Phdr &Phdr : PhdrRange) {
+    if ((Phdr.p_type == ELF::PT_LOAD) && (Phdr.p_flags & ELF::PF_X)) {
+        // Segments will always be loaded at a page boundary.
+        PreferredTextSegmentAddresses.push_back(Phdr.p_vaddr & ~(Phdr.p_align - 1U));
+        TextSegmentOffsets.push_back(Phdr.p_offset & ~(Phdr.p_align - 1U));
+      }
   }
-  exitWithError("no text section found", Obj->getFileName());
+
+  if (PreferredTextSegmentAddresses.empty())
+    exitWithError("no executable segment found", FileName);
+}
+
+void ProfiledBinary::setPreferredTextSegmentAddresses(const ELFObjectFileBase *Obj) {
+  if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj))
+    setPreferredTextSegmentAddresses(ELFObj->getELFFile(), Obj->getFileName());
+  else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj))
+    setPreferredTextSegmentAddresses(ELFObj->getELFFile(), Obj->getFileName());
+  else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj))
+    setPreferredTextSegmentAddresses(ELFObj->getELFFile(), Obj->getFileName());
+  else if (const auto *ELFObj = cast<ELF64BEObjectFile>(Obj))
+    setPreferredTextSegmentAddresses(ELFObj->getELFFile(), Obj->getFileName());
+  else
+    llvm_unreachable("invalid ELF object format");
 }
 
 void ProfiledBinary::decodePseudoProbe(const ELFObjectFileBase *Obj) {
@@ -204,67 +196,95 @@
                                         SectionSymbolsTy &Symbols,
                                         const SectionRef &Section) {
   std::size_t SE = Symbols.size();
-  uint64_t SectionOffset = Section.getAddress() - PreferredBaseAddress;
+  uint64_t SectionOffset = Section.getAddress() - getPreferredBaseAddress();
   uint64_t SectSize = Section.getSize();
-  uint64_t StartOffset = Symbols[SI].Addr - PreferredBaseAddress;
+  uint64_t StartOffset = Symbols[SI].Addr - getPreferredBaseAddress();
   uint64_t EndOffset = (SI + 1 < SE)
-                           ? Symbols[SI + 1].Addr - PreferredBaseAddress
+                           ? Symbols[SI + 1].Addr - getPreferredBaseAddress()
                            : SectionOffset + SectSize;
   if (StartOffset >= EndOffset)
     return true;
 
-  std::string &&SymbolName = Symbols[SI].Name.str();
+  StringRef SymbolName =
+      ShowCanonicalFnName
+          ? FunctionSamples::getCanonicalFnName(Symbols[SI].Name)
+          : Symbols[SI].Name;
   if (ShowDisassemblyOnly)
     outs() << '<' << SymbolName << ">:\n";
 
+  auto WarnInvalidInsts = [](uint64_t Start, uint64_t End) {
+    WithColor::warning() << "Invalid instructions at "
+                         << format("%8" PRIx64, Start) << " - "
+                         << format("%8" PRIx64, End) << "\n";
+  };
+
   uint64_t Offset = StartOffset;
+  // Size of a consecutive invalid instruction range starting from Offset -1
+  // backwards.
+  uint64_t InvalidInstLength = 0;
   while (Offset < EndOffset) {
     MCInst Inst;
     uint64_t Size;
     // Disassemble an instruction.
-    if (!DisAsm->getInstruction(Inst, Size, Bytes.slice(Offset - SectionOffset),
-                                Offset + PreferredBaseAddress, nulls()))
-      return false;
+    bool Disassembled =
+        DisAsm->getInstruction(Inst, Size, Bytes.slice(Offset - SectionOffset),
+                               Offset + getPreferredBaseAddress(), nulls());
+    if (Size == 0)
+      Size = 1;
 
     if (ShowDisassemblyOnly) {
       if (ShowPseudoProbe) {
         ProbeDecoder.printProbeForAddress(outs(),
-                                          Offset + PreferredBaseAddress);
+                                          Offset + getPreferredBaseAddress());
       }
-      outs() << format("%8" PRIx64 ":", Offset);
+      outs() << format("%8" PRIx64 ":", Offset + getPreferredBaseAddress());
       size_t Start = outs().tell();
-      IPrinter->printInst(&Inst, Offset + Size, "", *STI.get(), outs());
+      if (Disassembled)
+        IPrinter->printInst(&Inst, Offset + Size, "", *STI.get(), outs());
+      else
+        outs() << "\t<unknown>";
       if (ShowSourceLocations) {
         unsigned Cur = outs().tell() - Start;
         if (Cur < 40)
           outs().indent(40 - Cur);
-        InstructionPointer Inst(this, Offset);
-        outs() << getReversedLocWithContext(symbolize(Inst));
+        InstructionPointer IP(this, Offset);
+        outs() << getReversedLocWithContext(symbolize(IP, ShowCanonicalFnName));
       }
       outs() << "\n";
     }
 
-    const MCInstrDesc &MCDesc = MII->get(Inst.getOpcode());
+    if (Disassembled) {
+      const MCInstrDesc &MCDesc = MII->get(Inst.getOpcode());
+      // Populate a vector of the symbolized callsite at this location
+      // We don't need symbolized info for probe-based profile, just use an
+      // empty stack as an entry to indicate a valid binary offset
+      FrameLocationStack SymbolizedCallStack;
+      if (!UsePseudoProbes) {
+        InstructionPointer IP(this, Offset);
+        SymbolizedCallStack = symbolize(IP, true);
+      }
+      Offset2LocStackMap[Offset] = SymbolizedCallStack;
+      // Populate address maps.
+      CodeAddrs.push_back(Offset);
+      if (MCDesc.isCall())
+        CallAddrs.insert(Offset);
+      else if (MCDesc.isReturn())
+        RetAddrs.insert(Offset);
 
-    // Populate a vector of the symbolized callsite at this location
-    // We don't need symbolized info for probe-based profile, just use an empty
-    // stack as an entry to indicate a valid binary offset
-    FrameLocationStack SymbolizedCallStack;
-    if (!UsePseudoProbes) {
-      InstructionPointer IP(this, Offset);
-      SymbolizedCallStack = symbolize(IP, true);
+      if (InvalidInstLength) {
+        WarnInvalidInsts(Offset - InvalidInstLength, Offset - 1);
+        InvalidInstLength = 0;
+      }
+    } else {
+      InvalidInstLength += Size;
     }
-    Offset2LocStackMap[Offset] = SymbolizedCallStack;
-    // Populate address maps.
-    CodeAddrs.push_back(Offset);
-    if (MCDesc.isCall())
-      CallAddrs.insert(Offset);
-    else if (MCDesc.isReturn())
-      RetAddrs.insert(Offset);
 
     Offset += Size;
   }
 
+  if (InvalidInstLength)
+    WarnInvalidInsts(Offset - InvalidInstLength, Offset - 1);
+
   if (ShowDisassemblyOnly)
     outs() << "\n";
 
@@ -296,9 +316,10 @@
   if (!MII)
     exitWithError("no instruction info for target " + TripleName, FileName);
 
-  MCObjectFileInfo MOFI;
-  MCContext Ctx(AsmInfo.get(), MRI.get(), &MOFI);
-  MOFI.InitMCObjectFileInfo(Triple(TripleName), false, Ctx);
+  MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get());
+  std::unique_ptr<MCObjectFileInfo> MOFI(
+      TheTarget->createMCObjectFileInfo(Ctx, /*PIC=*/false));
+  Ctx.setObjectFileInfo(MOFI.get());
   DisAsm.reset(TheTarget->createMCDisassembler(*STI, Ctx));
   if (!DisAsm)
     exitWithError("no disassembler for target " + TripleName, FileName);
@@ -341,7 +362,7 @@
     if (!Section.isText())
       continue;
 
-    uint64_t ImageLoadAddr = PreferredBaseAddress;
+    uint64_t ImageLoadAddr = getPreferredBaseAddress();
     uint64_t SectionOffset = Section.getAddress() - ImageLoadAddr;
     uint64_t SectSize = Section.getSize();
     if (!SectSize)
@@ -353,8 +374,9 @@
     if (ShowDisassemblyOnly) {
       StringRef SectionName = unwrapOrError(Section.getName(), FileName);
       outs() << "\nDisassembly of section " << SectionName;
-      outs() << " [" << format("0x%" PRIx64, SectionOffset) << ", "
-             << format("0x%" PRIx64, SectionOffset + SectSize) << "]:\n\n";
+      outs() << " [" << format("0x%" PRIx64, Section.getAddress()) << ", "
+             << format("0x%" PRIx64, Section.getAddress() + SectSize)
+             << "]:\n\n";
     }
 
     // Get the section data.
@@ -387,7 +409,7 @@
                                              bool UseCanonicalFnName) {
   assert(this == IP.Binary &&
          "Binary should only symbolize its own instruction");
-  auto Addr = object::SectionedAddress{IP.Offset + PreferredBaseAddress,
+  auto Addr = object::SectionedAddress{IP.Offset + getPreferredBaseAddress(),
                                        object::SectionedAddress::UndefSection};
   DIInliningInfo InlineStack =
       unwrapOrError(Symbolizer->symbolizeInlinedCode(Path, Addr), getName());
@@ -403,7 +425,8 @@
       FunctionName = FunctionSamples::getCanonicalFnName(FunctionName);
     LineLocation Line(CallerFrame.Line - CallerFrame.StartLine,
                       DILocation::getBaseDiscriminatorFromDiscriminator(
-                          CallerFrame.Discriminator));
+                          CallerFrame.Discriminator,
+                          /* IsFSDiscriminator */ false));
     FrameLocation Callsite(FunctionName.str(), Line);
     CallStack.push_back(Callsite);
   }
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.h b/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.h
index ccb1c9d..be1169e 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.h
+++ b/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.h
@@ -99,10 +99,13 @@
   std::string Path;
   // The target triple.
   Triple TheTriple;
-  // The runtime base address that the executable sections are loaded at.
-  mutable uint64_t BaseAddress = 0;
-  // The preferred base address that the executable sections are loaded at.
-  uint64_t PreferredBaseAddress = 0;
+  // The runtime base address that the first executable segment is loaded at.
+  uint64_t BaseAddress = 0;
+  // The preferred load address of each executable segment.
+  std::vector<uint64_t> PreferredTextSegmentAddresses;
+  // The file offset of each executable segment.
+  std::vector<uint64_t> TextSegmentOffsets;
+
   // Mutiple MC component info
   std::unique_ptr<const MCRegisterInfo> MRI;
   std::unique_ptr<const MCAsmInfo> AsmInfo;
@@ -136,7 +139,10 @@
 
   bool UsePseudoProbes = false;
 
-  void setPreferredBaseAddress(const ELFObjectFileBase *O);
+  void setPreferredTextSegmentAddresses(const ELFObjectFileBase *O);
+
+  template <class ELFT>
+  void setPreferredTextSegmentAddresses(const ELFFile<ELFT> &Obj, StringRef FileName);
 
   void decodePseudoProbe(const ELFObjectFileBase *Obj);
 
@@ -174,17 +180,27 @@
     setupSymbolizer();
     load();
   }
-  uint64_t virtualAddrToOffset(uint64_t VitualAddress) const {
-    return VitualAddress - BaseAddress;
+  uint64_t virtualAddrToOffset(uint64_t VirtualAddress) const {
+    return VirtualAddress - BaseAddress;
   }
   uint64_t offsetToVirtualAddr(uint64_t Offset) const {
     return Offset + BaseAddress;
   }
-  const StringRef getPath() const { return Path; }
-  const StringRef getName() const { return llvm::sys::path::filename(Path); }
+  StringRef getPath() const { return Path; }
+  StringRef getName() const { return llvm::sys::path::filename(Path); }
   uint64_t getBaseAddress() const { return BaseAddress; }
   void setBaseAddress(uint64_t Address) { BaseAddress = Address; }
-  uint64_t getPreferredBaseAddress() const { return PreferredBaseAddress; }
+  
+  // Return the preferred load address for the first executable segment.
+  uint64_t getPreferredBaseAddress() const { return PreferredTextSegmentAddresses[0]; }
+  // Return the file offset for the first executable segment.
+  uint64_t getTextSegmentOffset() const { return TextSegmentOffsets[0]; }
+  const std::vector<uint64_t> &getPreferredTextSegmentAddresses() const {
+    return PreferredTextSegmentAddresses;
+  }
+  const std::vector<uint64_t> &getTextSegmentOffsets() const {
+    return TextSegmentOffsets;
+  }
 
   bool addressIsCode(uint64_t Address) const {
     uint64_t Offset = virtualAddrToOffset(Address);
@@ -226,7 +242,7 @@
     return FuncStartAddrMap[Offset];
   }
 
-  Optional<const FrameLocation> getInlineLeafFrameLoc(uint64_t Offset) {
+  Optional<FrameLocation> getInlineLeafFrameLoc(uint64_t Offset) {
     const auto &Stack = getFrameLocationStack(Offset);
     if (Stack.empty())
       return {};
@@ -239,8 +255,8 @@
   // Get the context string of the current stack with inline context filled in.
   // It will search the disassembling info stored in Offset2LocStackMap. This is
   // used as the key of function sample map
-  std::string
-  getExpandedContextStr(const SmallVectorImpl<uint64_t> &Stack) const;
+  std::string getExpandedContextStr(const SmallVectorImpl<uint64_t> &Stack,
+                                    bool &WasLeafInlined) const;
 
   const PseudoProbe *getCallProbeForAddr(uint64_t Address) const {
     return ProbeDecoder.getCallProbeForAddr(Address);
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/PseudoProbe.cpp b/src/llvm-project/llvm/tools/llvm-profgen/PseudoProbe.cpp
index a537d90..02af3f0 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/PseudoProbe.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profgen/PseudoProbe.cpp
@@ -88,12 +88,7 @@
   }
   OS << "Index: " << Index << "  ";
   OS << "Type: " << PseudoProbeTypeStr[static_cast<uint8_t>(Type)] << "  ";
-  if (isDangling()) {
-    OS << "Dangling  ";
-  }
-  if (isTailCall()) {
-    OS << "TailCall  ";
-  }
+
   std::string InlineContextStr = getInlineContextStr(GUID2FuncMAP, ShowName);
   if (InlineContextStr.size()) {
     OS << "Inlined: @ ";
@@ -162,7 +157,7 @@
     uint64_t GUID = readUnencodedNumber<uint64_t>();
     uint64_t Hash = readUnencodedNumber<uint64_t>();
     uint32_t NameSize = readUnsignedNumber<uint32_t>();
-    StringRef Name = readString(NameSize);
+    StringRef Name = FunctionSamples::getCanonicalFnName(readString(NameSize));
 
     // Initialize PseudoProbeFuncDesc and populate it into GUID2FuncDescMap
     GUID2FuncDescMap.emplace(GUID, PseudoProbeFuncDesc(GUID, Hash, Name));
@@ -189,7 +184,7 @@
   //           TYPE (uint4)
   //             0 - block probe, 1 - indirect call, 2 - direct call
   //           ATTRIBUTE (uint3)
-  //             1 - tail call, 2 - dangling
+  //             1 - reserved
   //           ADDRESS_TYPE (uint1)
   //             0 - code address, 1 - address delta
   //           CODE_ADDRESS (uint64 or ULEB128)
@@ -198,7 +193,6 @@
   //         A list of NUM_INLINED_FUNCTIONS entries describing each of the
   //         inlined callees.  Each record contains:
   //           INLINE SITE
-  //             GUID of the inlinee (uint64)
   //             Index of the callsite probe (ULEB128)
   //           FUNCTION BODY
   //             A FUNCTION BODY entry describing the inlined function.
@@ -214,8 +208,11 @@
   uint32_t Index = 0;
   // A DFS-based decoding
   while (Data < End) {
-    // Read inline site for inlinees
-    if (Root != Cur) {
+    if (Root == Cur) {
+      // Use a sequential id for top level inliner.
+      Index = Root->getChildren().size();
+    } else {
+      // Read inline site for inlinees
       Index = readUnsignedNumber<uint32_t>();
     }
     // Switch/add to a new tree node(inlinee)
@@ -243,10 +240,10 @@
         Addr = readUnencodedNumber<int64_t>();
       }
       // Populate Address2ProbesMap
-      std::vector<PseudoProbe> &ProbeVec = Address2ProbesMap[Addr];
-      ProbeVec.emplace_back(Addr, Cur->GUID, Index, PseudoProbeType(Kind), Attr,
-                            Cur);
-      Cur->addProbes(&ProbeVec.back());
+      auto &Probes = Address2ProbesMap[Addr];
+      Probes.emplace_back(Addr, Cur->GUID, Index, PseudoProbeType(Kind), Attr,
+                          Cur);
+      Cur->addProbes(&Probes.back());
       LastAddr = Addr;
     }
 
@@ -298,7 +295,7 @@
   auto It = Address2ProbesMap.find(Address);
   if (It == Address2ProbesMap.end())
     return nullptr;
-  const std::vector<PseudoProbe> &Probes = It->second;
+  const auto &Probes = It->second;
 
   const PseudoProbe *CallProbe = nullptr;
   for (const auto &Probe : Probes) {
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/PseudoProbe.h b/src/llvm-project/llvm/tools/llvm-profgen/PseudoProbe.h
index 2077724..62d46d3 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/PseudoProbe.h
+++ b/src/llvm-project/llvm/tools/llvm-profgen/PseudoProbe.h
@@ -24,7 +24,7 @@
 namespace llvm {
 namespace sampleprof {
 
-enum PseudoProbeAttributes { TAILCALL = 1, DANGLING = 2 };
+enum PseudoProbeAttributes { RESERVED = 1 };
 
 // Use func GUID and index as the location info of the inline site
 using InlineSite = std::tuple<uint64_t, uint32_t>;
@@ -45,9 +45,10 @@
       return std::get<0>(Site) ^ std::get<1>(Site);
     }
   };
-  std::unordered_map<InlineSite, std::unique_ptr<PseudoProbeInlineTree>,
-                     InlineSiteHash>
-      Children;
+  using InlinedProbeTreeMap =
+      std::unordered_map<InlineSite, std::unique_ptr<PseudoProbeInlineTree>,
+                         InlineSiteHash>;
+  InlinedProbeTreeMap Children;
 
 public:
   // Inlinee function GUID
@@ -71,6 +72,8 @@
     return Ret.first->second.get();
   }
 
+  InlinedProbeTreeMap &getChildren() { return Children; }
+  std::vector<PseudoProbe *> &getProbes() { return ProbeVector; }
   void addProbes(PseudoProbe *Probe) { ProbeVector.push_back(Probe); }
   // Return false if it's a dummy inline site
   bool hasInlineSite() const { return std::get<0>(ISite) != 0; }
@@ -91,7 +94,7 @@
 // GUID to PseudoProbeFuncDesc map
 using GUIDProbeFunctionMap = std::unordered_map<uint64_t, PseudoProbeFuncDesc>;
 // Address to pseudo probes map.
-using AddressProbesMap = std::unordered_map<uint64_t, std::vector<PseudoProbe>>;
+using AddressProbesMap = std::unordered_map<uint64_t, std::list<PseudoProbe>>;
 
 /*
 A pseudo probe has the format like below:
@@ -99,7 +102,7 @@
   TYPE (uint4)
     0 - block probe, 1 - indirect call, 2 - direct call
   ATTRIBUTE (uint3)
-    1 - tail call, 2 - dangling
+    1 - reserved
   ADDRESS_TYPE (uint1)
     0 - code address, 1 - address delta
   CODE_ADDRESS (uint64 or ULEB128)
@@ -121,20 +124,13 @@
         InlineTree(Tree){};
 
   bool isEntry() const { return Index == PseudoProbeFirstId; }
-
-  bool isDangling() const {
-    return Attribute & static_cast<uint8_t>(PseudoProbeAttributes::DANGLING);
-  }
-
-  bool isTailCall() const {
-    return Attribute & static_cast<uint8_t>(PseudoProbeAttributes::TAILCALL);
-  }
-
   bool isBlock() const { return Type == PseudoProbeType::Block; }
   bool isIndirectCall() const { return Type == PseudoProbeType::IndirectCall; }
   bool isDirectCall() const { return Type == PseudoProbeType::DirectCall; }
   bool isCall() const { return isIndirectCall() || isDirectCall(); }
 
+  PseudoProbeInlineTree *getInlineTreeNode() const { return InlineTree; }
+
   // Get the inlined context by traversing current inline tree backwards,
   // each tree node has its InlineSite which is taken as the context.
   // \p ContextStack is populated in root to leaf order
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/llvm-profgen.cpp b/src/llvm-project/llvm/tools/llvm-profgen/llvm-profgen.cpp
index 081f1bb..8ea0156 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/llvm-profgen.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profgen/llvm-profgen.cpp
@@ -18,16 +18,20 @@
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/TargetSelect.h"
 
+static cl::OptionCategory ProfGenCategory("ProfGen Options");
+
 static cl::list<std::string> PerfTraceFilenames(
     "perfscript", cl::value_desc("perfscript"), cl::OneOrMore,
     llvm::cl::MiscFlags::CommaSeparated,
     cl::desc("Path of perf-script trace created by Linux perf tool with "
-             "`script` command(the raw perf.data should be profiled with -b)"));
+             "`script` command(the raw perf.data should be profiled with -b)"),
+    cl::cat(ProfGenCategory));
 
 static cl::list<std::string>
     BinaryFilenames("binary", cl::value_desc("binary"), cl::OneOrMore,
                     llvm::cl::MiscFlags::CommaSeparated,
-                    cl::desc("Path of profiled binary files"));
+                    cl::desc("Path of profiled binary files"),
+                    cl::cat(ProfGenCategory));
 
 extern cl::opt<bool> ShowDisassemblyOnly;
 
@@ -42,6 +46,7 @@
   InitializeAllTargetMCs();
   InitializeAllDisassemblers();
 
+  cl::HideUnrelatedOptions({&ProfGenCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv, "llvm SPGO profile generator\n");
 
   // Load binaries and parse perf events and samples
diff --git a/src/llvm-project/llvm/tools/llvm-rc/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-rc/CMakeLists.txt
index 4cadc17..71b7994 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-rc/CMakeLists.txt
@@ -1,12 +1,16 @@
 set(LLVM_LINK_COMPONENTS
+  Object
   Option
   Support
   )
 
 set(LLVM_TARGET_DEFINITIONS Opts.td)
-
 tablegen(LLVM Opts.inc -gen-opt-parser-defs)
-add_public_tablegen_target(RcTableGen)
+add_public_tablegen_target(RcOptsTableGen)
+
+set(LLVM_TARGET_DEFINITIONS WindresOpts.td)
+tablegen(LLVM WindresOpts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(WindresOptsTableGen)
 
 add_llvm_tool(llvm-rc
   llvm-rc.cpp
@@ -16,3 +20,9 @@
   ResourceScriptStmt.cpp
   ResourceScriptToken.cpp
   )
+
+add_llvm_tool_symlink(llvm-windres llvm-rc)
+
+if(LLVM_INSTALL_BINUTILS_SYMLINKS)
+  add_llvm_tool_symlink(windres llvm-rc)
+endif()
diff --git a/src/llvm-project/llvm/tools/llvm-rc/Opts.td b/src/llvm-project/llvm/tools/llvm-rc/Opts.td
index 613f0a0..6d9c0e2 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/Opts.td
+++ b/src/llvm-project/llvm/tools/llvm-rc/Opts.td
@@ -4,55 +4,62 @@
 // These options seem to be important for the tool
 // and should be implemented.
 
-def fileout : JoinedOrSeparate<[ "/", "-" ], "FO">,
-              HelpText<"Change the output file location.">;
+class S<string name, string help> :
+      Separate<["/", "-"], name>, HelpText<help>;
 
-def define : Separate<[ "/", "-" ], "D">,
-             HelpText<"Define a symbol for the C preprocessor.">;
-def undef : Separate<[ "/", "-" ], "U">,
-            HelpText<"Undefine a symbol for the C preprocessor.">;
+class JS<string name, string help> :
+      JoinedOrSeparate<["/", "-"], name>, HelpText<help>;
 
-def lang_id : JoinedOrSeparate<[ "/", "-" ], "L">,
-              HelpText<"Set the default language identifier.">;
-def lang_name : Separate<[ "/", "-" ], "LN">,
-                HelpText<"Set the default language name.">;
+class F<string name, string help> : Flag<["/", "-"], name>, HelpText<help>;
 
-def includepath : Separate<[ "/", "-" ], "I">, HelpText<"Add an include path.">;
-def noinclude : Flag<[ "/", "-" ], "X">, HelpText<"Ignore 'include' variable.">;
+class F_nodoc<string name> : Flag<["/", "-"], name>;
+class S_nodoc<string name> : Separate<["/", "-"], name>;
 
-def add_null : Flag<[ "/", "-" ], "N">,
-               HelpText<"Null-terminate all strings in the string table.">;
+def fileout : JS<"FO", "Change the output file location.">;
 
-def dupid_nowarn : Flag<[ "/", "-" ], "Y">,
-                   HelpText<"Suppress warnings on duplicate resource IDs.">;
+def define : JS<"D", "Define a symbol for the C preprocessor.">;
+def undef : JS<"U", "Undefine a symbol for the C preprocessor.">;
 
-def verbose : Flag<[ "/", "-" ], "V">, HelpText<"Be verbose.">;
-def help : Flag<[ "/", "-" ], "?">, HelpText<"Display this help and exit.">;
-def h : Flag<[ "/", "-" ], "H">,
-        Alias<help>,
-        HelpText<"Display this help and exit.">;
+def lang_id : JS<"L", "Set the default language identifier.">;
+def lang_name : S<"LN", "Set the default language name.">;
 
-def dry_run : Flag<[ "/", "-" ], "dry-run">,
-              HelpText<"Don't compile the input; only try to parse it.">;
+def includepath : JS<"I", "Add an include path.">;
+def noinclude : F<"X", "Ignore 'include' variable.">;
 
-def codepage : JoinedOrSeparate<[ "/", "-" ], "C">,
-               HelpText<"Set the codepage used for input strings.">;
+def add_null : F<"N", "Null-terminate all strings in the string table.">;
+
+def dupid_nowarn : F<"Y", "Suppress warnings on duplicate resource IDs.">;
+
+def verbose : F<"V", "Be verbose.">;
+def help : F<"?", "Display this help and exit.">;
+def h : F<"H", "Display this help and exit.">, Alias<help>;
+
+def codepage : JS<"C", "Set the codepage used for input strings.">;
+
+// llvm-rc specific options:
+
+def dry_run : F<"dry-run", "Don't compile the input; only try to parse it.">;
+
+def no_preprocess : F<"no-preprocess", "Don't try to preprocess the input file.">;
+
+// Print (but do not run) the commands to run for preprocessing
+def _HASH_HASH_HASH : F_nodoc<"###">;
 
 // Unused switches (at least for now). These will stay unimplemented
 // in an early stage of development and can be ignored. However, we need to
 // parse them in order to preserve the compatibility with the original tool.
 
-def nologo : Flag<[ "/", "-" ], "NOLOGO">;
-def r : Flag<[ "/", "-" ], "R">;
-def sl : Flag<[ "/", "-" ], "SL">;
+def nologo : F_nodoc<"NOLOGO">;
+def r : F_nodoc<"R">;
+def sl : F_nodoc<"SL">;
 
 // (Codepages support.)
-def w : Flag<[ "/", "-" ], "W">;
+def w : F_nodoc<"W">;
 
 // (Support of MUI and similar.)
-def fm : Separate<[ "/", "-" ], "FM">;
-def q : Separate<[ "/", "-" ], "Q">;
-def g : Flag<[ "/", "-" ], "G">;
-def gn : Flag<[ "/", "-" ], "GN">;
-def g1 : Flag<[ "/", "-" ], "G1">;
-def g2 : Flag<[ "/", "-" ], "G2">;
+def fm : S_nodoc<"FM">;
+def q : S_nodoc<"Q">;
+def g : F_nodoc<"G">;
+def gn : F_nodoc<"GN">;
+def g1 : F_nodoc<"G1">;
+def g2 : F_nodoc<"G2">;
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.cpp b/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.cpp
index 553bb75..60287a3 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.cpp
@@ -99,7 +99,7 @@
     return false;
 
   // Just take the contents of the string, checking if it's been marked long.
-  IsLongString = Str.startswith_lower("L");
+  IsLongString = Str.startswith_insensitive("L");
   if (IsLongString)
     Str = Str.drop_front();
 
@@ -1524,14 +1524,16 @@
   // properly though, so if using that to append paths below, this early
   // exception case could be removed.)
   if (sys::path::has_root_directory(File))
-    return errorOrToExpected(MemoryBuffer::getFile(File, -1, false));
+    return errorOrToExpected(MemoryBuffer::getFile(
+        File, /*IsText=*/false, /*RequiresNullTerminator=*/false));
 
   // 1. The current working directory.
   sys::fs::current_path(Cwd);
   Path.assign(Cwd.begin(), Cwd.end());
   sys::path::append(Path, File);
   if (sys::fs::exists(Path))
-    return errorOrToExpected(MemoryBuffer::getFile(Path, -1, false));
+    return errorOrToExpected(MemoryBuffer::getFile(
+        Path, /*IsText=*/false, /*RequiresNullTerminator=*/false));
 
   // 2. The directory of the input resource file, if it is different from the
   // current working directory.
@@ -1539,19 +1541,23 @@
   Path.assign(InputFileDir.begin(), InputFileDir.end());
   sys::path::append(Path, File);
   if (sys::fs::exists(Path))
-    return errorOrToExpected(MemoryBuffer::getFile(Path, -1, false));
+    return errorOrToExpected(MemoryBuffer::getFile(
+        Path, /*IsText=*/false, /*RequiresNullTerminator=*/false));
 
   // 3. All of the include directories specified on the command line.
   for (StringRef ForceInclude : Params.Include) {
     Path.assign(ForceInclude.begin(), ForceInclude.end());
     sys::path::append(Path, File);
     if (sys::fs::exists(Path))
-      return errorOrToExpected(MemoryBuffer::getFile(Path, -1, false));
+      return errorOrToExpected(MemoryBuffer::getFile(
+          Path, /*IsText=*/false, /*RequiresNullTerminator=*/false));
   }
 
-  if (auto Result =
-          llvm::sys::Process::FindInEnvPath("INCLUDE", File, Params.NoInclude))
-    return errorOrToExpected(MemoryBuffer::getFile(*Result, -1, false));
+  if (!Params.NoInclude) {
+    if (auto Result = llvm::sys::Process::FindInEnvPath("INCLUDE", File))
+      return errorOrToExpected(MemoryBuffer::getFile(
+          *Result, /*IsText=*/false, /*RequiresNullTerminator=*/false));
+  }
 
   return make_error<StringError>("error : file not found : " + Twine(File),
                                  inconvertibleErrorCode());
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.h b/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.h
index d545a7a..0f3d593 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.h
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.h
@@ -35,7 +35,7 @@
 
 struct WriterParams {
   std::vector<std::string> Include;   // Additional folders to search for files.
-  std::vector<std::string> NoInclude; // Folders to exclude from file search.
+  bool NoInclude;                     // Ignore the INCLUDE variable.
   StringRef InputFilePath;            // The full path of the input file.
   int CodePage = CpAcp;               // The codepage for interpreting characters.
 };
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptCppFilter.cpp b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptCppFilter.cpp
index e610be9..6657aa5 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptCppFilter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptCppFilter.cpp
@@ -91,7 +91,7 @@
 
   StringRef Ext = Line.rsplit('.').second;
 
-  if (Ext.equals_lower("h") || Ext.equals_lower("c")) {
+  if (Ext.equals_insensitive("h") || Ext.equals_insensitive("c")) {
     Outputting = false;
   } else {
     Outputting = true;
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.cpp b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.cpp
index 5141ac0..4045131 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.cpp
@@ -215,7 +215,7 @@
   }
 
   case Kind::Identifier: {
-    if (!read().value().equals_lower("not"))
+    if (!read().value().equals_insensitive("not"))
       return getExpectedError(ErrorMsg, true);
     ASSIGN_OR_RETURN(Result, parseIntExpr2());
     return IntWithNotMask(0, (*Result).getValue());
@@ -330,7 +330,7 @@
     bool FoundFlag = false;
 
     for (size_t FlagId = 0; FlagId < FlagDesc.size(); ++FlagId) {
-      if (!FlagResult->equals_lower(FlagDesc[FlagId]))
+      if (!FlagResult->equals_insensitive(FlagDesc[FlagId]))
         continue;
 
       Result |= FlagValues[FlagId];
@@ -351,23 +351,23 @@
     if (Token.kind() != Kind::Identifier)
       return Flags;
     const StringRef Ident = Token.value();
-    if (Ident.equals_lower("PRELOAD"))
+    if (Ident.equals_insensitive("PRELOAD"))
       Flags |= MfPreload;
-    else if (Ident.equals_lower("LOADONCALL"))
+    else if (Ident.equals_insensitive("LOADONCALL"))
       Flags &= ~MfPreload;
-    else if (Ident.equals_lower("FIXED"))
+    else if (Ident.equals_insensitive("FIXED"))
       Flags &= ~(MfMoveable | MfDiscardable);
-    else if (Ident.equals_lower("MOVEABLE"))
+    else if (Ident.equals_insensitive("MOVEABLE"))
       Flags |= MfMoveable;
-    else if (Ident.equals_lower("DISCARDABLE"))
+    else if (Ident.equals_insensitive("DISCARDABLE"))
       Flags |= MfDiscardable | MfMoveable | MfPure;
-    else if (Ident.equals_lower("PURE"))
+    else if (Ident.equals_insensitive("PURE"))
       Flags |= MfPure;
-    else if (Ident.equals_lower("IMPURE"))
+    else if (Ident.equals_insensitive("IMPURE"))
       Flags &= ~(MfPure | MfDiscardable);
-    else if (Ident.equals_lower("SHARED"))
+    else if (Ident.equals_insensitive("SHARED"))
       Flags |= MfPure;
-    else if (Ident.equals_lower("NONSHARED"))
+    else if (Ident.equals_insensitive("NONSHARED"))
       Flags &= ~(MfPure | MfDiscardable);
     else
       return Flags;
@@ -392,23 +392,23 @@
 Expected<std::unique_ptr<OptionalStmt>>
 RCParser::parseSingleOptionalStatement(OptStmtType StmtsType) {
   ASSIGN_OR_RETURN(TypeToken, readIdentifier());
-  if (TypeToken->equals_lower("CHARACTERISTICS"))
+  if (TypeToken->equals_insensitive("CHARACTERISTICS"))
     return parseCharacteristicsStmt();
-  if (TypeToken->equals_lower("LANGUAGE"))
+  if (TypeToken->equals_insensitive("LANGUAGE"))
     return parseLanguageStmt();
-  if (TypeToken->equals_lower("VERSION"))
+  if (TypeToken->equals_insensitive("VERSION"))
     return parseVersionStmt();
 
   if (StmtsType != OptStmtType::BasicStmt) {
-    if (TypeToken->equals_lower("CAPTION"))
+    if (TypeToken->equals_insensitive("CAPTION"))
       return parseCaptionStmt();
-    if (TypeToken->equals_lower("CLASS"))
+    if (TypeToken->equals_insensitive("CLASS"))
       return parseClassStmt();
-    if (TypeToken->equals_lower("EXSTYLE"))
+    if (TypeToken->equals_insensitive("EXSTYLE"))
       return parseExStyleStmt();
-    if (TypeToken->equals_lower("FONT"))
+    if (TypeToken->equals_insensitive("FONT"))
       return parseFontStmt(StmtsType);
-    if (TypeToken->equals_lower("STYLE"))
+    if (TypeToken->equals_insensitive("STYLE"))
       return parseStyleStmt();
   }
 
@@ -506,15 +506,14 @@
   RETURN_IF_ERROR(consumeType(Kind::BlockBegin));
   std::vector<IntOrString> Data;
 
-  // Consume comma before each consecutive token except the first one.
-  bool ConsumeComma = false;
   while (!consumeOptionalType(Kind::BlockEnd)) {
-    if (ConsumeComma)
-      RETURN_IF_ERROR(consumeType(Kind::Comma));
-    ConsumeComma = true;
-
     ASSIGN_OR_RETURN(Item, readIntOrString());
     Data.push_back(*Item);
+
+    // There can be zero or more commas after each token (but not before
+    // the first one).
+    while (consumeOptionalType(Kind::Comma)) {
+    }
   }
 
   return std::make_unique<UserDefinedResource>(Type, std::move(Data),
@@ -635,15 +634,15 @@
   while (!consumeOptionalType(Kind::BlockEnd)) {
     ASSIGN_OR_RETURN(ItemTypeResult, readIdentifier());
 
-    bool IsMenuItem = ItemTypeResult->equals_lower("MENUITEM");
-    bool IsPopup = ItemTypeResult->equals_lower("POPUP");
+    bool IsMenuItem = ItemTypeResult->equals_insensitive("MENUITEM");
+    bool IsPopup = ItemTypeResult->equals_insensitive("POPUP");
     if (!IsMenuItem && !IsPopup)
       return getExpectedError("MENUITEM, POPUP, END or '}'", true);
 
     if (IsMenuItem && isNextTokenKind(Kind::Identifier)) {
       // Now, expecting SEPARATOR.
       ASSIGN_OR_RETURN(SeparatorResult, readIdentifier());
-      if (SeparatorResult->equals_lower("SEPARATOR")) {
+      if (SeparatorResult->equals_insensitive("SEPARATOR")) {
         List.addDefinition(std::make_unique<MenuSeparator>());
         continue;
       }
@@ -731,12 +730,12 @@
   // Expect either BLOCK or VALUE, then a name or a key (a string).
   ASSIGN_OR_RETURN(TypeResult, readIdentifier());
 
-  if (TypeResult->equals_lower("BLOCK")) {
+  if (TypeResult->equals_insensitive("BLOCK")) {
     ASSIGN_OR_RETURN(NameResult, readString());
     return parseVersionInfoBlockContents(*NameResult);
   }
 
-  if (TypeResult->equals_lower("VALUE")) {
+  if (TypeResult->equals_insensitive("VALUE")) {
     ASSIGN_OR_RETURN(KeyResult, readString());
     // Read a non-empty list of strings and/or ints, each
     // possibly preceded by a comma. Unfortunately, the tool behavior depends
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.h b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.h
index 27fbea3..9f77d36 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.h
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.h
@@ -145,7 +145,7 @@
       : Data(Token), IsInt(Token.kind() == RCToken::Kind::Int) {}
 
   bool equalsLower(const char *Str) {
-    return !IsInt && Data.String.equals_lower(Str);
+    return !IsInt && Data.String.equals_insensitive(Str);
   }
 
   bool isInt() const { return IsInt; }
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptToken.cpp b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptToken.cpp
index 2e21f67..a8f40ab 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptToken.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptToken.cpp
@@ -288,7 +288,7 @@
   assert(!streamEof());
   const char CurChar = Data[Pos];
   return std::isalnum(CurChar) || CurChar == '_' || CurChar == '.' ||
-         CurChar == '/' || CurChar == '\\';
+         CurChar == '/' || CurChar == '\\' || CurChar == '-';
 }
 
 bool Tokenizer::canStartInt() const {
@@ -350,9 +350,9 @@
   assert(Token.kind() == Kind::Identifier);
   StringRef Name = Token.value();
 
-  if (Name.equals_lower("begin"))
+  if (Name.equals_insensitive("begin"))
     Token = RCToken(Kind::BlockBegin, Name);
-  else if (Name.equals_lower("end"))
+  else if (Name.equals_insensitive("end"))
     Token = RCToken(Kind::BlockEnd, Name);
 }
 
diff --git a/src/llvm-project/llvm/tools/llvm-rc/WindresOpts.td b/src/llvm-project/llvm/tools/llvm-rc/WindresOpts.td
new file mode 100644
index 0000000..3c75c85
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-rc/WindresOpts.td
@@ -0,0 +1,62 @@
+include "llvm/Option/OptParser.td"
+
+multiclass Long<string name, string help> {
+  def NAME: Separate<["--"], name>;
+  def NAME # _eq: Joined<["--"], name # "=">, Alias<!cast<Separate>(NAME)>,
+    HelpText<help>;
+}
+
+multiclass LongAlias<string name, Option orig> {
+  def NAME: Separate<["--"], name>, Alias<orig>;
+  def NAME # _eq: Joined<["--"], name # "=">, Alias<orig>;
+}
+
+multiclass LongShort<string short, string long, string help> {
+  def NAME: Separate<["--"], long>;
+  def NAME # _eq: Joined<["--"], long # "=">, Alias<!cast<Separate>(NAME)>,
+    HelpText<help>;
+  def NAME # _short: JoinedOrSeparate<["-"], short>, Alias<!cast<Separate>(NAME)>;
+}
+
+multiclass F<string short, string long, string help> {
+  def NAME: Flag<["-"], short>;
+  def NAME # _long: Flag<["--"], long>, Alias<!cast<Flag>(NAME)>,
+    HelpText<help>;
+}
+
+defm input : LongShort<"i", "input", "Input file">;
+
+defm output : LongShort<"o", "output", "Output file">;
+
+defm input_format : LongShort<"J", "input-format", "Input format">;
+
+defm output_format : LongShort<"O", "output-format", "Output format">;
+
+defm preprocessor : Long<"preprocessor", "Custom preprocessor command">;
+defm preprocessor_arg : Long<"preprocessor-arg", "Preprocessor command argument">;
+
+defm target : LongShort<"F", "target", "Target BFD format name">;
+
+defm include_dir : LongShort<"I", "include-dir", "Include directory">;
+defm include_alias : LongAlias<"include", include_dir>;
+
+defm define : LongShort<"D", "define", "Define to pass to the preprocessor">;
+
+defm undef : LongShort<"U", "undefine", "Undefine to pass to the preprocessor">;
+
+defm codepage : LongShort<"c", "codepage", "Default codepage to use">;
+
+defm language : LongShort<"l", "language", "Default language to use (0x0-0xffff)">;
+
+defm verbose : F<"v", "verbose", "Enable verbose output">;
+defm version : F<"V", "version", "Display version">;
+
+defm help : F<"h", "help", "Display this message and exit">;
+
+// Print (but do not run) the commands to run for preprocessing
+def _HASH_HASH_HASH : Flag<["-"], "###">;
+
+def no_preprocess : Flag<["--"], "no-preprocess">;
+
+// Unimplemented options for compatibility
+def use_temp_file: Flag<["--"], "use-temp-file">;
diff --git a/src/llvm-project/llvm/tools/llvm-rc/llvm-rc.cpp b/src/llvm-project/llvm/tools/llvm-rc/llvm-rc.cpp
index e9027a21..83925c2 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/llvm-rc.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rc/llvm-rc.cpp
@@ -17,17 +17,24 @@
 #include "ResourceScriptStmt.h"
 #include "ResourceScriptToken.h"
 
+#include "llvm/ADT/Triple.h"
+#include "llvm/Object/WindowsResource.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/Host.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Process.h"
+#include "llvm/Support/Program.h"
 #include "llvm/Support/Signals.h"
+#include "llvm/Support/StringSaver.h"
 #include "llvm/Support/raw_ostream.h"
 
 #include <algorithm>
@@ -70,47 +77,530 @@
   RcOptTable() : OptTable(InfoTable, /* IgnoreCase = */ true) {}
 };
 
+enum Windres_ID {
+  WINDRES_INVALID = 0, // This is not a correct option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  WINDRES_##ID,
+#include "WindresOpts.inc"
+#undef OPTION
+};
+
+#define PREFIX(NAME, VALUE) const char *const WINDRES_##NAME[] = VALUE;
+#include "WindresOpts.inc"
+#undef PREFIX
+
+static const opt::OptTable::Info WindresInfoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  {                                                                            \
+      WINDRES_##PREFIX, NAME,         HELPTEXT,                                \
+      METAVAR,          WINDRES_##ID, opt::Option::KIND##Class,                \
+      PARAM,            FLAGS,        WINDRES_##GROUP,                         \
+      WINDRES_##ALIAS,  ALIASARGS,    VALUES},
+#include "WindresOpts.inc"
+#undef OPTION
+};
+
+class WindresOptTable : public opt::OptTable {
+public:
+  WindresOptTable() : OptTable(WindresInfoTable, /* IgnoreCase = */ false) {}
+};
+
 static ExitOnError ExitOnErr;
+static FileRemover TempPreprocFile;
+static FileRemover TempResFile;
 
 LLVM_ATTRIBUTE_NORETURN static void fatalError(const Twine &Message) {
   errs() << Message << "\n";
   exit(1);
 }
 
-} // anonymous namespace
+std::string createTempFile(const Twine &Prefix, StringRef Suffix) {
+  std::error_code EC;
+  SmallString<128> FileName;
+  if ((EC = sys::fs::createTemporaryFile(Prefix, Suffix, FileName)))
+    fatalError("Unable to create temp file: " + EC.message());
+  return static_cast<std::string>(FileName);
+}
 
-int main(int Argc, const char **Argv) {
-  InitLLVM X(Argc, Argv);
-  ExitOnErr.setBanner("llvm-rc: ");
+ErrorOr<std::string> findClang(const char *Argv0) {
+  StringRef Parent = llvm::sys::path::parent_path(Argv0);
+  ErrorOr<std::string> Path = std::error_code();
+  if (!Parent.empty()) {
+    // First look for the tool with all potential names in the specific
+    // directory of Argv0, if known
+    for (const auto *Name : {"clang", "clang-cl"}) {
+      Path = sys::findProgramByName(Name, Parent);
+      if (Path)
+        return Path;
+    }
+  }
+  // If no parent directory known, or not found there, look everywhere in PATH
+  for (const auto *Name : {"clang", "clang-cl"}) {
+    Path = sys::findProgramByName(Name);
+    if (Path)
+      return Path;
+  }
+  return Path;
+}
 
-  RcOptTable T;
+bool isUsableArch(Triple::ArchType Arch) {
+  switch (Arch) {
+  case Triple::x86:
+  case Triple::x86_64:
+  case Triple::arm:
+  case Triple::thumb:
+  case Triple::aarch64:
+    // These work properly with the clang driver, setting the expected
+    // defines such as _WIN32 etc.
+    return true;
+  default:
+    // Other archs aren't set up for use with windows as target OS, (clang
+    // doesn't define e.g. _WIN32 etc), so with them we need to set a
+    // different default arch.
+    return false;
+  }
+}
+
+Triple::ArchType getDefaultFallbackArch() {
+  return Triple::x86_64;
+}
+
+std::string getClangClTriple() {
+  Triple T(sys::getDefaultTargetTriple());
+  if (!isUsableArch(T.getArch()))
+    T.setArch(getDefaultFallbackArch());
+  T.setOS(Triple::Win32);
+  T.setVendor(Triple::PC);
+  T.setEnvironment(Triple::MSVC);
+  T.setObjectFormat(Triple::COFF);
+  return T.str();
+}
+
+std::string getMingwTriple() {
+  Triple T(sys::getDefaultTargetTriple());
+  if (!isUsableArch(T.getArch()))
+    T.setArch(getDefaultFallbackArch());
+  if (T.isWindowsGNUEnvironment())
+    return T.str();
+  // Write out the literal form of the vendor/env here, instead of
+  // constructing them with enum values (which end up with them in
+  // normalized form). The literal form of the triple can matter for
+  // finding include files.
+  return (Twine(T.getArchName()) + "-w64-mingw32").str();
+}
+
+enum Format { Rc, Res, Coff, Unknown };
+
+struct RcOptions {
+  bool Preprocess = true;
+  bool PrintCmdAndExit = false;
+  std::string Triple;
+  std::vector<std::string> PreprocessCmd;
+  std::vector<std::string> PreprocessArgs;
+
+  std::string InputFile;
+  Format InputFormat = Rc;
+  std::string OutputFile;
+  Format OutputFormat = Res;
+
+  bool BeVerbose = false;
+  WriterParams Params;
+  bool AppendNull = false;
+  bool IsDryRun = false;
+  // Set the default language; choose en-US arbitrarily.
+  unsigned LangId = (/*PrimaryLangId*/ 0x09) | (/*SubLangId*/ 0x01 << 10);
+};
+
+bool preprocess(StringRef Src, StringRef Dst, const RcOptions &Opts,
+                const char *Argv0) {
+  std::string Clang;
+  if (Opts.PrintCmdAndExit) {
+    Clang = "clang";
+  } else {
+    ErrorOr<std::string> ClangOrErr = findClang(Argv0);
+    if (ClangOrErr) {
+      Clang = *ClangOrErr;
+    } else {
+      errs() << "llvm-rc: Unable to find clang, skipping preprocessing."
+             << "\n";
+      errs() << "Pass -no-cpp to disable preprocessing. This will be an error "
+                "in the future."
+             << "\n";
+      return false;
+    }
+  }
+
+  SmallVector<StringRef, 8> Args = {
+      Clang, "--driver-mode=gcc", "-target", Opts.Triple, "-E",
+      "-xc", "-DRC_INVOKED"};
+  if (!Opts.PreprocessCmd.empty()) {
+    Args.clear();
+    for (const auto &S : Opts.PreprocessCmd)
+      Args.push_back(S);
+  }
+  Args.push_back(Src);
+  Args.push_back("-o");
+  Args.push_back(Dst);
+  for (const auto &S : Opts.PreprocessArgs)
+    Args.push_back(S);
+  if (Opts.PrintCmdAndExit || Opts.BeVerbose) {
+    for (const auto &A : Args) {
+      outs() << " ";
+      sys::printArg(outs(), A, Opts.PrintCmdAndExit);
+    }
+    outs() << "\n";
+    if (Opts.PrintCmdAndExit)
+      exit(0);
+  }
+  // The llvm Support classes don't handle reading from stdout of a child
+  // process; otherwise we could avoid using a temp file.
+  int Res = sys::ExecuteAndWait(Clang, Args);
+  if (Res) {
+    fatalError("llvm-rc: Preprocessing failed.");
+  }
+  return true;
+}
+
+static std::pair<bool, std::string> isWindres(llvm::StringRef Argv0) {
+  StringRef ProgName = llvm::sys::path::stem(Argv0);
+  // x86_64-w64-mingw32-windres -> x86_64-w64-mingw32, windres
+  // llvm-rc -> "", llvm-rc
+  // aarch64-w64-mingw32-llvm-windres-10.exe -> aarch64-w64-mingw32, llvm-windres
+  ProgName = ProgName.rtrim("0123456789.-");
+  if (!ProgName.consume_back_insensitive("windres"))
+    return std::make_pair<bool, std::string>(false, "");
+  ProgName.consume_back_insensitive("llvm-");
+  ProgName.consume_back_insensitive("-");
+  return std::make_pair<bool, std::string>(true, ProgName.str());
+}
+
+Format parseFormat(StringRef S) {
+  Format F = StringSwitch<Format>(S.lower())
+                 .Case("rc", Rc)
+                 .Case("res", Res)
+                 .Case("coff", Coff)
+                 .Default(Unknown);
+  if (F == Unknown)
+    fatalError("Unable to parse '" + Twine(S) + "' as a format");
+  return F;
+}
+
+void deduceFormat(Format &Dest, StringRef File) {
+  Format F = StringSwitch<Format>(sys::path::extension(File.lower()))
+                 .Case(".rc", Rc)
+                 .Case(".res", Res)
+                 .Case(".o", Coff)
+                 .Case(".obj", Coff)
+                 .Default(Unknown);
+  if (F != Unknown)
+    Dest = F;
+}
+
+std::string unescape(StringRef S) {
+  std::string Out;
+  Out.reserve(S.size());
+  for (int I = 0, E = S.size(); I < E; I++) {
+    if (S[I] == '\\') {
+      if (I + 1 < E)
+        Out.push_back(S[++I]);
+      else
+        fatalError("Unterminated escape");
+      continue;
+    }
+    Out.push_back(S[I]);
+  }
+  return Out;
+}
+
+std::vector<std::string> unescapeSplit(StringRef S) {
+  std::vector<std::string> OutArgs;
+  std::string Out;
+  bool InQuote = false;
+  for (int I = 0, E = S.size(); I < E; I++) {
+    if (S[I] == '\\') {
+      if (I + 1 < E)
+        Out.push_back(S[++I]);
+      else
+        fatalError("Unterminated escape");
+      continue;
+    }
+    if (S[I] == '"') {
+      InQuote = !InQuote;
+      continue;
+    }
+    if (S[I] == ' ' && !InQuote) {
+      OutArgs.push_back(Out);
+      Out.clear();
+      continue;
+    }
+    Out.push_back(S[I]);
+  }
+  if (InQuote)
+    fatalError("Unterminated quote");
+  if (!Out.empty())
+    OutArgs.push_back(Out);
+  return OutArgs;
+}
+
+RcOptions parseWindresOptions(ArrayRef<const char *> ArgsArr,
+                              ArrayRef<const char *> InputArgsArray,
+                              std::string Prefix) {
+  WindresOptTable T;
+  RcOptions Opts;
   unsigned MAI, MAC;
-  const char **DashDash = std::find_if(
-      Argv + 1, Argv + Argc, [](StringRef Str) { return Str == "--"; });
-  ArrayRef<const char *> ArgsArr = makeArrayRef(Argv + 1, DashDash);
+  opt::InputArgList InputArgs = T.ParseArgs(ArgsArr, MAI, MAC);
 
+  // The tool prints nothing when invoked with no command-line arguments.
+  if (InputArgs.hasArg(WINDRES_help)) {
+    T.printHelp(outs(), "windres [options] file...",
+                "LLVM windres (GNU windres compatible)", false, true);
+    exit(0);
+  }
+
+  if (InputArgs.hasArg(WINDRES_version)) {
+    outs() << "llvm-windres, compatible with GNU windres\n";
+    cl::PrintVersionMessage();
+    exit(0);
+  }
+
+  std::vector<std::string> FileArgs = InputArgs.getAllArgValues(WINDRES_INPUT);
+  FileArgs.insert(FileArgs.end(), InputArgsArray.begin(), InputArgsArray.end());
+
+  if (InputArgs.hasArg(WINDRES_input)) {
+    Opts.InputFile = InputArgs.getLastArgValue(WINDRES_input).str();
+  } else if (!FileArgs.empty()) {
+    Opts.InputFile = FileArgs.front();
+    FileArgs.erase(FileArgs.begin());
+  } else {
+    // TODO: GNU windres takes input on stdin in this case.
+    fatalError("Missing input file");
+  }
+
+  if (InputArgs.hasArg(WINDRES_output)) {
+    Opts.OutputFile = InputArgs.getLastArgValue(WINDRES_output).str();
+  } else if (!FileArgs.empty()) {
+    Opts.OutputFile = FileArgs.front();
+    FileArgs.erase(FileArgs.begin());
+  } else {
+    // TODO: GNU windres writes output in rc form to stdout in this case.
+    fatalError("Missing output file");
+  }
+
+  if (InputArgs.hasArg(WINDRES_input_format)) {
+    Opts.InputFormat =
+        parseFormat(InputArgs.getLastArgValue(WINDRES_input_format));
+  } else {
+    deduceFormat(Opts.InputFormat, Opts.InputFile);
+  }
+  if (Opts.InputFormat == Coff)
+    fatalError("Unsupported input format");
+
+  if (InputArgs.hasArg(WINDRES_output_format)) {
+    Opts.OutputFormat =
+        parseFormat(InputArgs.getLastArgValue(WINDRES_output_format));
+  } else {
+    // The default in windres differs from the default in RcOptions
+    Opts.OutputFormat = Coff;
+    deduceFormat(Opts.OutputFormat, Opts.OutputFile);
+  }
+  if (Opts.OutputFormat == Rc)
+    fatalError("Unsupported output format");
+  if (Opts.InputFormat == Opts.OutputFormat) {
+    outs() << "Nothing to do.\n";
+    exit(0);
+  }
+
+  Opts.PrintCmdAndExit = InputArgs.hasArg(WINDRES__HASH_HASH_HASH);
+  Opts.Preprocess = !InputArgs.hasArg(WINDRES_no_preprocess);
+  Triple TT(Prefix);
+  if (InputArgs.hasArg(WINDRES_target)) {
+    StringRef Value = InputArgs.getLastArgValue(WINDRES_target);
+    if (Value == "pe-i386")
+      Opts.Triple = "i686-w64-mingw32";
+    else if (Value == "pe-x86-64")
+      Opts.Triple = "x86_64-w64-mingw32";
+    else
+      // Implicit extension; if the --target value isn't one of the known
+      // BFD targets, allow setting the full triple string via this instead.
+      Opts.Triple = Value.str();
+  } else if (TT.getArch() != Triple::UnknownArch)
+    Opts.Triple = Prefix;
+  else
+    Opts.Triple = getMingwTriple();
+
+  for (const auto *Arg :
+       InputArgs.filtered(WINDRES_include_dir, WINDRES_define, WINDRES_undef,
+                          WINDRES_preprocessor_arg)) {
+    // GNU windres passes the arguments almost as-is on to popen() (it only
+    // backslash escapes spaces in the arguments), where a shell would
+    // unescape backslash escapes for quotes and similar. This means that
+    // when calling GNU windres, callers need to double escape chars like
+    // quotes, e.g. as -DSTRING=\\\"1.2.3\\\".
+    //
+    // Exactly how the arguments are interpreted depends on the platform
+    // though - but the cases where this matters (where callers would have
+    // done this double escaping) probably is confined to cases like these
+    // quoted string defines, and those happen to work the same across unix
+    // and windows.
+    std::string Unescaped = unescape(Arg->getValue());
+    switch (Arg->getOption().getID()) {
+    case WINDRES_include_dir:
+      // Technically, these are handled the same way as e.g. defines, but
+      // the way we consistently unescape the unix way breaks windows paths
+      // with single backslashes. Alternatively, our unescape function would
+      // need to mimic the platform specific command line parsing/unescaping
+      // logic.
+      Opts.Params.Include.push_back(Arg->getValue());
+      Opts.PreprocessArgs.push_back("-I");
+      Opts.PreprocessArgs.push_back(Arg->getValue());
+      break;
+    case WINDRES_define:
+      Opts.PreprocessArgs.push_back("-D");
+      Opts.PreprocessArgs.push_back(Unescaped);
+      break;
+    case WINDRES_undef:
+      Opts.PreprocessArgs.push_back("-U");
+      Opts.PreprocessArgs.push_back(Unescaped);
+      break;
+    case WINDRES_preprocessor_arg:
+      Opts.PreprocessArgs.push_back(Unescaped);
+      break;
+    }
+  }
+  if (InputArgs.hasArg(WINDRES_preprocessor))
+    Opts.PreprocessCmd =
+        unescapeSplit(InputArgs.getLastArgValue(WINDRES_preprocessor));
+
+  Opts.Params.CodePage = CpWin1252; // Different default
+  if (InputArgs.hasArg(WINDRES_codepage)) {
+    if (InputArgs.getLastArgValue(WINDRES_codepage)
+            .getAsInteger(0, Opts.Params.CodePage))
+      fatalError("Invalid code page: " +
+                 InputArgs.getLastArgValue(WINDRES_codepage));
+  }
+  if (InputArgs.hasArg(WINDRES_language)) {
+    StringRef Val = InputArgs.getLastArgValue(WINDRES_language);
+    Val.consume_front_insensitive("0x");
+    if (Val.getAsInteger(16, Opts.LangId))
+      fatalError("Invalid language id: " +
+                 InputArgs.getLastArgValue(WINDRES_language));
+  }
+
+  Opts.BeVerbose = InputArgs.hasArg(WINDRES_verbose);
+
+  return Opts;
+}
+
+RcOptions parseRcOptions(ArrayRef<const char *> ArgsArr,
+                         ArrayRef<const char *> InputArgsArray) {
+  RcOptTable T;
+  RcOptions Opts;
+  unsigned MAI, MAC;
   opt::InputArgList InputArgs = T.ParseArgs(ArgsArr, MAI, MAC);
 
   // The tool prints nothing when invoked with no command-line arguments.
   if (InputArgs.hasArg(OPT_help)) {
-    T.PrintHelp(outs(), "rc [options] file...", "Resource Converter", false);
-    return 0;
+    T.printHelp(outs(), "rc [options] file...", "Resource Converter", false);
+    exit(0);
   }
 
-  const bool BeVerbose = InputArgs.hasArg(OPT_verbose);
-
   std::vector<std::string> InArgsInfo = InputArgs.getAllArgValues(OPT_INPUT);
-  if (DashDash != Argv + Argc)
-    InArgsInfo.insert(InArgsInfo.end(), DashDash + 1, Argv + Argc);
+  InArgsInfo.insert(InArgsInfo.end(), InputArgsArray.begin(),
+                    InputArgsArray.end());
   if (InArgsInfo.size() != 1) {
     fatalError("Exactly one input file should be provided.");
   }
 
+  Opts.PrintCmdAndExit = InputArgs.hasArg(OPT__HASH_HASH_HASH);
+  Opts.Triple = getClangClTriple();
+  for (const auto *Arg :
+       InputArgs.filtered(OPT_includepath, OPT_define, OPT_undef)) {
+    switch (Arg->getOption().getID()) {
+    case OPT_includepath:
+      Opts.PreprocessArgs.push_back("-I");
+      break;
+    case OPT_define:
+      Opts.PreprocessArgs.push_back("-D");
+      break;
+    case OPT_undef:
+      Opts.PreprocessArgs.push_back("-U");
+      break;
+    }
+    Opts.PreprocessArgs.push_back(Arg->getValue());
+  }
+
+  Opts.InputFile = InArgsInfo[0];
+  Opts.BeVerbose = InputArgs.hasArg(OPT_verbose);
+  Opts.Preprocess = !InputArgs.hasArg(OPT_no_preprocess);
+  Opts.Params.Include = InputArgs.getAllArgValues(OPT_includepath);
+  Opts.Params.NoInclude = InputArgs.hasArg(OPT_noinclude);
+  if (Opts.Params.NoInclude) {
+    // Clear the INLCUDE variable for the external preprocessor
+#ifdef _WIN32
+    ::_putenv("INCLUDE=");
+#else
+    ::unsetenv("INCLUDE");
+#endif
+  }
+  if (InputArgs.hasArg(OPT_codepage)) {
+    if (InputArgs.getLastArgValue(OPT_codepage)
+            .getAsInteger(10, Opts.Params.CodePage))
+      fatalError("Invalid code page: " +
+                 InputArgs.getLastArgValue(OPT_codepage));
+  }
+  Opts.IsDryRun = InputArgs.hasArg(OPT_dry_run);
+  auto OutArgsInfo = InputArgs.getAllArgValues(OPT_fileout);
+  if (OutArgsInfo.empty()) {
+    SmallString<128> OutputFile(Opts.InputFile);
+    llvm::sys::fs::make_absolute(OutputFile);
+    llvm::sys::path::replace_extension(OutputFile, "res");
+    OutArgsInfo.push_back(std::string(OutputFile.str()));
+  }
+  if (!Opts.IsDryRun) {
+    if (OutArgsInfo.size() != 1)
+      fatalError(
+          "No more than one output file should be provided (using /FO flag).");
+    Opts.OutputFile = OutArgsInfo[0];
+  }
+  Opts.AppendNull = InputArgs.hasArg(OPT_add_null);
+  if (InputArgs.hasArg(OPT_lang_id)) {
+    StringRef Val = InputArgs.getLastArgValue(OPT_lang_id);
+    Val.consume_front_insensitive("0x");
+    if (Val.getAsInteger(16, Opts.LangId))
+      fatalError("Invalid language id: " +
+                 InputArgs.getLastArgValue(OPT_lang_id));
+  }
+  return Opts;
+}
+
+RcOptions getOptions(const char *Argv0, ArrayRef<const char *> ArgsArr,
+                     ArrayRef<const char *> InputArgs) {
+  std::string Prefix;
+  bool IsWindres;
+  std::tie(IsWindres, Prefix) = isWindres(Argv0);
+  if (IsWindres)
+    return parseWindresOptions(ArgsArr, InputArgs, Prefix);
+  else
+    return parseRcOptions(ArgsArr, InputArgs);
+}
+
+void doRc(std::string Src, std::string Dest, RcOptions &Opts,
+          const char *Argv0) {
+  std::string PreprocessedFile = Src;
+  if (Opts.Preprocess) {
+    std::string OutFile = createTempFile("preproc", "rc");
+    TempPreprocFile.setFile(OutFile);
+    if (preprocess(Src, OutFile, Opts, Argv0))
+      PreprocessedFile = OutFile;
+  }
+
   // Read and tokenize the input file.
   ErrorOr<std::unique_ptr<MemoryBuffer>> File =
-      MemoryBuffer::getFile(InArgsInfo[0]);
+      MemoryBuffer::getFile(PreprocessedFile);
   if (!File) {
-    fatalError("Error opening file '" + Twine(InArgsInfo[0]) +
+    fatalError("Error opening file '" + Twine(PreprocessedFile) +
                "': " + File.getError().message());
   }
 
@@ -120,7 +610,7 @@
   std::string FilteredContents = filterCppOutput(Contents);
   std::vector<RCToken> Tokens = ExitOnErr(tokenizeRC(FilteredContents));
 
-  if (BeVerbose) {
+  if (Opts.BeVerbose) {
     const Twine TokenNames[] = {
 #define TOKEN(Name) #Name,
 #define SHORT_TOKEN(Name, Ch) #Name,
@@ -137,80 +627,129 @@
     }
   }
 
-  WriterParams Params;
-  SmallString<128> InputFile(InArgsInfo[0]);
+  WriterParams &Params = Opts.Params;
+  SmallString<128> InputFile(Src);
   llvm::sys::fs::make_absolute(InputFile);
   Params.InputFilePath = InputFile;
-  Params.Include = InputArgs.getAllArgValues(OPT_includepath);
-  Params.NoInclude = InputArgs.getAllArgValues(OPT_noinclude);
 
-  if (InputArgs.hasArg(OPT_codepage)) {
-    if (InputArgs.getLastArgValue(OPT_codepage)
-            .getAsInteger(10, Params.CodePage))
-      fatalError("Invalid code page: " +
-                 InputArgs.getLastArgValue(OPT_codepage));
-    switch (Params.CodePage) {
-    case CpAcp:
-    case CpWin1252:
-    case CpUtf8:
-      break;
-    default:
-      fatalError(
-          "Unsupported code page, only 0, 1252 and 65001 are supported!");
-    }
+  switch (Params.CodePage) {
+  case CpAcp:
+  case CpWin1252:
+  case CpUtf8:
+    break;
+  default:
+    fatalError("Unsupported code page, only 0, 1252 and 65001 are supported!");
   }
 
   std::unique_ptr<ResourceFileWriter> Visitor;
-  bool IsDryRun = InputArgs.hasArg(OPT_dry_run);
 
-  if (!IsDryRun) {
-    auto OutArgsInfo = InputArgs.getAllArgValues(OPT_fileout);
-    if (OutArgsInfo.empty()) {
-      SmallString<128> OutputFile = InputFile;
-      llvm::sys::path::replace_extension(OutputFile, "res");
-      OutArgsInfo.push_back(std::string(OutputFile.str()));
-    }
-
-    if (OutArgsInfo.size() != 1)
-      fatalError(
-          "No more than one output file should be provided (using /FO flag).");
-
+  if (!Opts.IsDryRun) {
     std::error_code EC;
     auto FOut = std::make_unique<raw_fd_ostream>(
-        OutArgsInfo[0], EC, sys::fs::FA_Read | sys::fs::FA_Write);
+        Dest, EC, sys::fs::FA_Read | sys::fs::FA_Write);
     if (EC)
-      fatalError("Error opening output file '" + OutArgsInfo[0] +
-                 "': " + EC.message());
+      fatalError("Error opening output file '" + Dest + "': " + EC.message());
     Visitor = std::make_unique<ResourceFileWriter>(Params, std::move(FOut));
-    Visitor->AppendNull = InputArgs.hasArg(OPT_add_null);
+    Visitor->AppendNull = Opts.AppendNull;
 
     ExitOnErr(NullResource().visit(Visitor.get()));
 
-    // Set the default language; choose en-US arbitrarily.
-    unsigned PrimaryLangId = 0x09, SubLangId = 0x01;
-    if (InputArgs.hasArg(OPT_lang_id)) {
-      unsigned LangId;
-      if (InputArgs.getLastArgValue(OPT_lang_id).getAsInteger(16, LangId))
-        fatalError("Invalid language id: " +
-                   InputArgs.getLastArgValue(OPT_lang_id));
-      PrimaryLangId = LangId & 0x3ff;
-      SubLangId = LangId >> 10;
-    }
+    unsigned PrimaryLangId = Opts.LangId & 0x3ff;
+    unsigned SubLangId = Opts.LangId >> 10;
     ExitOnErr(LanguageResource(PrimaryLangId, SubLangId).visit(Visitor.get()));
   }
 
   rc::RCParser Parser{std::move(Tokens)};
   while (!Parser.isEof()) {
     auto Resource = ExitOnErr(Parser.parseSingleResource());
-    if (BeVerbose)
+    if (Opts.BeVerbose)
       Resource->log(outs());
-    if (!IsDryRun)
+    if (!Opts.IsDryRun)
       ExitOnErr(Resource->visit(Visitor.get()));
   }
 
   // STRINGTABLE resources come at the very end.
-  if (!IsDryRun)
+  if (!Opts.IsDryRun)
     ExitOnErr(Visitor->dumpAllStringTables());
+}
+
+void doCvtres(std::string Src, std::string Dest, std::string TargetTriple) {
+  object::WindowsResourceParser Parser;
+
+  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
+      MemoryBuffer::getFile(Src);
+  if (!BufferOrErr)
+    fatalError("Error opening file '" + Twine(Src) +
+               "': " + BufferOrErr.getError().message());
+  std::unique_ptr<MemoryBuffer> &Buffer = BufferOrErr.get();
+  std::unique_ptr<object::WindowsResource> Binary =
+      ExitOnErr(object::WindowsResource::createWindowsResource(
+          Buffer->getMemBufferRef()));
+
+  std::vector<std::string> Duplicates;
+  ExitOnErr(Parser.parse(Binary.get(), Duplicates));
+  for (const auto &DupeDiag : Duplicates)
+    fatalError("Duplicate resources: " + DupeDiag);
+
+  Triple T(TargetTriple);
+  COFF::MachineTypes MachineType;
+  switch (T.getArch()) {
+  case Triple::x86:
+    MachineType = COFF::IMAGE_FILE_MACHINE_I386;
+    break;
+  case Triple::x86_64:
+    MachineType = COFF::IMAGE_FILE_MACHINE_AMD64;
+    break;
+  case Triple::arm:
+  case Triple::thumb:
+    MachineType = COFF::IMAGE_FILE_MACHINE_ARMNT;
+    break;
+  case Triple::aarch64:
+    MachineType = COFF::IMAGE_FILE_MACHINE_ARM64;
+    break;
+  default:
+    fatalError("Unsupported architecture in target '" + Twine(TargetTriple) +
+               "'");
+  }
+
+  std::unique_ptr<MemoryBuffer> OutputBuffer =
+      ExitOnErr(object::writeWindowsResourceCOFF(MachineType, Parser,
+                                                 /*DateTimeStamp*/ 0));
+  std::unique_ptr<FileOutputBuffer> FileBuffer =
+      ExitOnErr(FileOutputBuffer::create(Dest, OutputBuffer->getBufferSize()));
+  std::copy(OutputBuffer->getBufferStart(), OutputBuffer->getBufferEnd(),
+            FileBuffer->getBufferStart());
+  ExitOnErr(FileBuffer->commit());
+}
+
+} // anonymous namespace
+
+int main(int Argc, const char **Argv) {
+  InitLLVM X(Argc, Argv);
+  ExitOnErr.setBanner("llvm-rc: ");
+
+  const char **DashDash = std::find_if(
+      Argv + 1, Argv + Argc, [](StringRef Str) { return Str == "--"; });
+  ArrayRef<const char *> ArgsArr = makeArrayRef(Argv + 1, DashDash);
+  ArrayRef<const char *> FileArgsArr;
+  if (DashDash != Argv + Argc)
+    FileArgsArr = makeArrayRef(DashDash + 1, Argv + Argc);
+
+  RcOptions Opts = getOptions(Argv[0], ArgsArr, FileArgsArr);
+
+  std::string ResFile = Opts.OutputFile;
+  if (Opts.InputFormat == Rc) {
+    if (Opts.OutputFormat == Coff) {
+      ResFile = createTempFile("rc", "res");
+      TempResFile.setFile(ResFile);
+    }
+    doRc(Opts.InputFile, ResFile, Opts, Argv[0]);
+  } else {
+    ResFile = Opts.InputFile;
+  }
+  if (Opts.OutputFormat == Coff) {
+    doCvtres(ResFile, Opts.OutputFile, Opts.Triple);
+  }
 
   return 0;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
index 5995a09..99ee639 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -100,7 +100,7 @@
     OS << Name << " ";
 
   if (Offset)
-    OS << format("+0x%X (0x%" PRIX64 ")", Offset, Address);
+    OS << format("+0x%" PRIX64 " (0x%" PRIX64 ")", Offset, Address);
   else if (!Name.empty())
     OS << format("(0x%" PRIX64 ")", Address);
   else
@@ -184,31 +184,16 @@
   const uint16_t VFPMask = std::get<1>(RegisterMask);
 
   OS << '{';
-  bool Comma = false;
-  for (unsigned RI = 0, RE = 11; RI < RE; ++RI) {
-    if (GPRMask & (1 << RI)) {
-      if (Comma)
-        OS << ", ";
-      OS << GPRRegisterNames[RI];
-      Comma = true;
-    }
-  }
-  for (unsigned RI = 0, RE = 32; RI < RE; ++RI) {
-    if (VFPMask & (1 << RI)) {
-      if (Comma)
-        OS << ", ";
-      OS << "d" << unsigned(RI);
-      Comma = true;
-    }
-  }
-  for (unsigned RI = 11, RE = 16; RI < RE; ++RI) {
-    if (GPRMask & (1 << RI)) {
-      if (Comma)
-        OS << ", ";
-      OS << GPRRegisterNames[RI];
-      Comma = true;
-    }
-  }
+  ListSeparator LS;
+  for (unsigned RI = 0, RE = 11; RI < RE; ++RI)
+    if (GPRMask & (1 << RI))
+      OS << LS << GPRRegisterNames[RI];
+  for (unsigned RI = 0, RE = 32; RI < RE; ++RI)
+    if (VFPMask & (1 << RI))
+      OS << LS << "d" << unsigned(RI);
+  for (unsigned RI = 11, RE = 16; RI < RE; ++RI)
+    if (GPRMask & (1 << RI))
+      OS << LS << GPRRegisterNames[RI];
   OS << '}';
 }
 
@@ -253,6 +238,65 @@
   return inconvertibleErrorCode();
 }
 
+SymbolRef Decoder::getPreferredSymbol(const COFFObjectFile &COFF,
+                                      SymbolRef Sym) {
+  // The symbol resolved by getRelocatedSymbol can be any internal
+  // nondescriptive symbol; try to resolve a more descriptive one.
+  COFFSymbolRef CoffSym = COFF.getCOFFSymbol(Sym);
+  if (CoffSym.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL)
+    return Sym;
+  for (const auto &S : COFF.symbols()) {
+    COFFSymbolRef CS = COFF.getCOFFSymbol(S);
+    if (CS.getSectionNumber() == CoffSym.getSectionNumber() &&
+        CS.getValue() == CoffSym.getValue()) {
+      if (CS.isExternal())
+        return S;
+      if (CS.getStorageClass() != COFF::IMAGE_SYM_CLASS_LABEL) {
+        Sym = S;
+        CoffSym = CS;
+      }
+    }
+  }
+  return Sym;
+}
+
+ErrorOr<SymbolRef> Decoder::getSymbolForLocation(
+    const COFFObjectFile &COFF, const SectionRef &Section,
+    uint64_t OffsetInSection, uint64_t ImmediateOffset, uint64_t &SymbolAddress,
+    uint64_t &SymbolOffset, bool FunctionOnly) {
+  // Try to locate a relocation that points at the offset in the section
+  ErrorOr<SymbolRef> SymOrErr =
+      getRelocatedSymbol(COFF, Section, OffsetInSection);
+  if (SymOrErr) {
+    // We found a relocation symbol; the immediate offset needs to be added
+    // to the symbol address.
+    SymbolOffset = ImmediateOffset;
+
+    Expected<uint64_t> AddressOrErr = SymOrErr->getAddress();
+    if (!AddressOrErr) {
+      std::string Buf;
+      llvm::raw_string_ostream OS(Buf);
+      logAllUnhandledErrors(AddressOrErr.takeError(), OS);
+      OS.flush();
+      report_fatal_error(Buf);
+    }
+    // We apply SymbolOffset here directly. We return it separately to allow
+    // the caller to print it as an offset on the symbol name.
+    SymbolAddress = *AddressOrErr + SymbolOffset;
+  } else {
+    // No matching relocation found; operating on a linked image. Try to
+    // find a descriptive symbol if possible. The immediate offset contains
+    // the image relative address, and we shouldn't add any offset to the
+    // symbol.
+    SymbolAddress = COFF.getImageBase() + ImmediateOffset;
+    SymbolOffset = 0;
+    SymOrErr = getSymbol(COFF, SymbolAddress, FunctionOnly);
+  }
+  if (SymOrErr && FunctionOnly) // Resolve label symbols into function names
+    SymOrErr = getPreferredSymbol(COFF, *SymOrErr);
+  return SymOrErr;
+}
+
 bool Decoder::opcode_0xxxxxxx(const uint8_t *OC, unsigned &Offset,
                               unsigned Length, bool Prologue) {
   uint8_t Imm = OC[Offset] & 0x7f;
@@ -934,16 +978,16 @@
   }
 
   if (XData.X()) {
-    const uint64_t Address = COFF.getImageBase() + XData.ExceptionHandlerRVA();
     const uint32_t Parameter = XData.ExceptionHandlerParameter();
-    const size_t HandlerOffset = HeaderWords(XData)
-                               + (XData.E() ? 0 : XData.EpilogueCount())
-                               + XData.CodeWords();
+    const size_t HandlerOffset = HeaderWords(XData) +
+                                 (XData.E() ? 0 : XData.EpilogueCount()) +
+                                 XData.CodeWords();
 
-    ErrorOr<SymbolRef> Symbol = getRelocatedSymbol(
-        COFF, Section, Offset + HandlerOffset * sizeof(uint32_t));
-    if (!Symbol)
-      Symbol = getSymbol(COFF, Address, /*FunctionOnly=*/true);
+    uint64_t Address, SymbolOffset;
+    ErrorOr<SymbolRef> Symbol = getSymbolForLocation(
+        COFF, Section, Offset + HandlerOffset * sizeof(uint32_t),
+        XData.ExceptionHandlerRVA(), Address, SymbolOffset,
+        /*FunctionOnly=*/true);
     if (!Symbol) {
       ListScope EHS(SW, "ExceptionHandler");
       SW.printHex("Routine", Address);
@@ -961,7 +1005,7 @@
     }
 
     ListScope EHS(SW, "ExceptionHandler");
-    SW.printString("Routine", formatSymbol(*Name, Address));
+    SW.printString("Routine", formatSymbol(*Name, Address, SymbolOffset));
     SW.printHex("Parameter", Parameter);
   }
 
@@ -974,14 +1018,15 @@
   assert(RF.Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
          "packed entry cannot be treated as an unpacked entry");
 
-  ErrorOr<SymbolRef> Function = getRelocatedSymbol(COFF, Section, Offset);
-  if (!Function)
-    Function = getSymbol(COFF, COFF.getImageBase() + RF.BeginAddress,
-                         /*FunctionOnly=*/true);
+  uint64_t FunctionAddress, FunctionOffset;
+  ErrorOr<SymbolRef> Function = getSymbolForLocation(
+      COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
+      /*FunctionOnly=*/true);
 
-  ErrorOr<SymbolRef> XDataRecord = getRelocatedSymbol(COFF, Section, Offset + 4);
-  if (!XDataRecord)
-    XDataRecord = getSymbol(COFF, RF.ExceptionInformationRVA());
+  uint64_t XDataAddress, XDataOffset;
+  ErrorOr<SymbolRef> XDataRecord = getSymbolForLocation(
+      COFF, Section, Offset + 4, RF.ExceptionInformationRVA(), XDataAddress,
+      XDataOffset);
 
   if (!RF.BeginAddress && !Function)
     return false;
@@ -989,7 +1034,6 @@
     return false;
 
   StringRef FunctionName;
-  uint64_t FunctionAddress;
   if (Function) {
     Expected<StringRef> FunctionNameOrErr = Function->getName();
     if (!FunctionNameOrErr) {
@@ -1000,20 +1044,10 @@
       report_fatal_error(Buf);
     }
     FunctionName = *FunctionNameOrErr;
-    Expected<uint64_t> FunctionAddressOrErr = Function->getAddress();
-    if (!FunctionAddressOrErr) {
-      std::string Buf;
-      llvm::raw_string_ostream OS(Buf);
-      logAllUnhandledErrors(FunctionAddressOrErr.takeError(), OS);
-      OS.flush();
-      report_fatal_error(Buf);
-    }
-    FunctionAddress = *FunctionAddressOrErr;
-  } else {
-    FunctionAddress = COFF.getImageBase() + RF.BeginAddress;
   }
 
-  SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
+  SW.printString("Function",
+                 formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
 
   if (XDataRecord) {
     Expected<StringRef> Name = XDataRecord->getName();
@@ -1025,17 +1059,8 @@
       report_fatal_error(Buf);
     }
 
-    Expected<uint64_t> AddressOrErr = XDataRecord->getAddress();
-    if (!AddressOrErr) {
-      std::string Buf;
-      llvm::raw_string_ostream OS(Buf);
-      logAllUnhandledErrors(AddressOrErr.takeError(), OS);
-      OS.flush();
-      report_fatal_error(Buf);
-    }
-    uint64_t Address = *AddressOrErr;
-
-    SW.printString("ExceptionRecord", formatSymbol(*Name, Address));
+    SW.printString("ExceptionRecord",
+                   formatSymbol(*Name, XDataAddress, XDataOffset));
 
     Expected<section_iterator> SIOrErr = XDataRecord->getSection();
     if (!SIOrErr) {
@@ -1045,18 +1070,15 @@
     }
     section_iterator SI = *SIOrErr;
 
-    // FIXME: Do we need to add an offset from the relocation?
-    return dumpXDataRecord(COFF, *SI, FunctionAddress,
-                           RF.ExceptionInformationRVA());
+    return dumpXDataRecord(COFF, *SI, FunctionAddress, XDataAddress);
   } else {
-    uint64_t Address = COFF.getImageBase() + RF.ExceptionInformationRVA();
-    SW.printString("ExceptionRecord", formatSymbol("", Address));
+    SW.printString("ExceptionRecord", formatSymbol("", XDataAddress));
 
-    ErrorOr<SectionRef> Section = getSectionContaining(COFF, Address);
+    ErrorOr<SectionRef> Section = getSectionContaining(COFF, XDataAddress);
     if (!Section)
       return false;
 
-    return dumpXDataRecord(COFF, *Section, FunctionAddress, Address);
+    return dumpXDataRecord(COFF, *Section, FunctionAddress, XDataAddress);
   }
 }
 
@@ -1067,12 +1089,12 @@
           RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
          "unpacked entry cannot be treated as a packed entry");
 
-  ErrorOr<SymbolRef> Function = getRelocatedSymbol(COFF, Section, Offset);
-  if (!Function)
-    Function = getSymbol(COFF, RF.BeginAddress, /*FunctionOnly=*/true);
+  uint64_t FunctionAddress, FunctionOffset;
+  ErrorOr<SymbolRef> Function = getSymbolForLocation(
+      COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
+      /*FunctionOnly=*/true);
 
   StringRef FunctionName;
-  uint64_t FunctionAddress;
   if (Function) {
     Expected<StringRef> FunctionNameOrErr = Function->getName();
     if (!FunctionNameOrErr) {
@@ -1083,20 +1105,10 @@
       report_fatal_error(Buf);
     }
     FunctionName = *FunctionNameOrErr;
-    Expected<uint64_t> FunctionAddressOrErr = Function->getAddress();
-    if (!FunctionAddressOrErr) {
-      std::string Buf;
-      llvm::raw_string_ostream OS(Buf);
-      logAllUnhandledErrors(FunctionAddressOrErr.takeError(), OS);
-      OS.flush();
-      report_fatal_error(Buf);
-    }
-    FunctionAddress = *FunctionAddressOrErr;
-  } else {
-    FunctionAddress = COFF.getPE32Header()->ImageBase + RF.BeginAddress;
   }
 
-  SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
+  SW.printString("Function",
+                 formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
   if (!isAArch64)
     SW.printBoolean("Fragment",
                     RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
@@ -1119,12 +1131,12 @@
           RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
          "unpacked entry cannot be treated as a packed entry");
 
-  ErrorOr<SymbolRef> Function = getRelocatedSymbol(COFF, Section, Offset);
-  if (!Function)
-    Function = getSymbol(COFF, RF.BeginAddress, /*FunctionOnly=*/true);
+  uint64_t FunctionAddress, FunctionOffset;
+  ErrorOr<SymbolRef> Function = getSymbolForLocation(
+      COFF, Section, Offset, RF.BeginAddress, FunctionAddress, FunctionOffset,
+      /*FunctionOnly=*/true);
 
   StringRef FunctionName;
-  uint64_t FunctionAddress;
   if (Function) {
     Expected<StringRef> FunctionNameOrErr = Function->getName();
     if (!FunctionNameOrErr) {
@@ -1135,20 +1147,10 @@
       report_fatal_error(Buf);
     }
     FunctionName = *FunctionNameOrErr;
-    Expected<uint64_t> FunctionAddressOrErr = Function->getAddress();
-    if (!FunctionAddressOrErr) {
-      std::string Buf;
-      llvm::raw_string_ostream OS(Buf);
-      logAllUnhandledErrors(FunctionAddressOrErr.takeError(), OS);
-      OS.flush();
-      report_fatal_error(Buf);
-    }
-    FunctionAddress = *FunctionAddressOrErr;
-  } else {
-    FunctionAddress = COFF.getPE32PlusHeader()->ImageBase + RF.BeginAddress;
   }
 
-  SW.printString("Function", formatSymbol(FunctionName, FunctionAddress));
+  SW.printString("Function",
+                 formatSymbol(FunctionName, FunctionAddress, FunctionOffset));
   SW.printBoolean("Fragment",
                   RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment);
   SW.printNumber("FunctionLength", RF.FunctionLength());
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.h b/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
index 3263841..efe1685 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
+++ b/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
@@ -146,6 +146,16 @@
   getRelocatedSymbol(const object::COFFObjectFile &COFF,
                      const object::SectionRef &Section, uint64_t Offset);
 
+  ErrorOr<object::SymbolRef>
+  getSymbolForLocation(const object::COFFObjectFile &COFF,
+                       const object::SectionRef &Section,
+                       uint64_t OffsetInSection, uint64_t ImmediateOffset,
+                       uint64_t &SymbolAddress, uint64_t &SymbolOffset,
+                       bool FunctionOnly = false);
+
+  object::SymbolRef getPreferredSymbol(const object::COFFObjectFile &COFF,
+                                       object::SymbolRef Sym);
+
   bool dumpXDataRecord(const object::COFFObjectFile &COFF,
                        const object::SectionRef &Section,
                        uint64_t FunctionAddress, uint64_t VA);
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-readobj/CMakeLists.txt
index 9e310f0..9d2d888 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-readobj/CMakeLists.txt
@@ -4,12 +4,17 @@
   Demangle
   Object
   BinaryFormat
+  Option
   Support
   DebugInfoCodeView
   DebugInfoMSF
   DebugInfoPDB
   )
 
+set(LLVM_TARGET_DEFINITIONS Opts.td)
+tablegen(LLVM Opts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(ReadobjOptsTableGen)
+
 add_llvm_tool(llvm-readobj
   ARMWinEHPrinter.cpp
   COFFDumper.cpp
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp
index 684967f..96124cc 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -71,6 +71,8 @@
   uint64_t GuardIatTableCount = 0;
   uint64_t GuardLJmpTableVA = 0;
   uint64_t GuardLJmpTableCount = 0;
+  uint64_t GuardEHContTableVA = 0;
+  uint64_t GuardEHContTableCount = 0;
 };
 
 class COFFDumper : public ObjDumper {
@@ -593,8 +595,7 @@
   for (const SectionRef &S : Obj->sections()) {
     const coff_section *Section = Obj->getCOFFSection(S);
 
-    for (const RelocationRef &Reloc : S.relocations())
-      RelocMap[Section].push_back(Reloc);
+    append_range(RelocMap[Section], S.relocations());
 
     // Sort relocations by address.
     llvm::sort(RelocMap[Section], [](RelocationRef L, RelocationRef R) {
@@ -794,19 +795,19 @@
     printRVATable(Tables.SEHTableVA, Tables.SEHTableCount, 4);
   }
 
+  auto PrintGuardFlags = [](raw_ostream &OS, const uint8_t *Entry) {
+    uint8_t Flags = *reinterpret_cast<const uint8_t *>(Entry + 4);
+    if (Flags)
+      OS << " flags " << utohexstr(Flags);
+  };
+
   if (Tables.GuardFidTableVA) {
     ListScope LS(W, "GuardFidTable");
-    if (Tables.GuardFlags & uint32_t(coff_guard_flags::FidTableHasFlags)) {
-      auto PrintGuardFlags = [](raw_ostream &OS, const uint8_t *Entry) {
-        uint8_t Flags = *reinterpret_cast<const uint8_t *>(Entry + 4);
-        if (Flags)
-          OS << " flags " << utohexstr(Flags);
-      };
+    if (Tables.GuardFlags & uint32_t(coff_guard_flags::FidTableHasFlags))
       printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, 5,
                     PrintGuardFlags);
-    } else {
+    else
       printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, 4);
-    }
   }
 
   if (Tables.GuardIatTableVA) {
@@ -818,6 +819,12 @@
     ListScope LS(W, "GuardLJmpTable");
     printRVATable(Tables.GuardLJmpTableVA, Tables.GuardLJmpTableCount, 4);
   }
+
+  if (Tables.GuardEHContTableVA) {
+    ListScope LS(W, "GuardEHContTable");
+    printRVATable(Tables.GuardEHContTableVA, Tables.GuardEHContTableCount, 5,
+                  PrintGuardFlags);
+  }
 }
 
 template <typename T>
@@ -876,8 +883,8 @@
   Tables.GuardFidTableCount = Conf->GuardCFFunctionCount;
   Tables.GuardFlags = Conf->GuardFlags;
 
-  // Print the rest. (2017)
-  if (Conf->Size < sizeof(T))
+  // Print everything before Reserved3. (2017)
+  if (Conf->Size < offsetof(T, Reserved3))
     return;
   W.printHex("GuardAddressTakenIatEntryTable",
              Conf->GuardAddressTakenIatEntryTable);
@@ -903,6 +910,17 @@
 
   Tables.GuardLJmpTableVA = Conf->GuardLongJumpTargetTable;
   Tables.GuardLJmpTableCount = Conf->GuardLongJumpTargetCount;
+
+  // Print the rest. (2019)
+  if (Conf->Size < sizeof(T))
+    return;
+  W.printHex("EnclaveConfigurationPointer", Conf->EnclaveConfigurationPointer);
+  W.printHex("VolatileMetadataPointer", Conf->VolatileMetadataPointer);
+  W.printHex("GuardEHContinuationTable", Conf->GuardEHContinuationTable);
+  W.printNumber("GuardEHContinuationCount", Conf->GuardEHContinuationCount);
+
+  Tables.GuardEHContTableVA = Conf->GuardEHContinuationTable;
+  Tables.GuardEHContTableCount = Conf->GuardEHContinuationCount;
 }
 
 void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) {
@@ -1856,7 +1874,7 @@
         OS << ": (ID " << Entry.Identifier.ID << ")";
       }
     }
-    Name = StringRef(IDStr);
+    Name = IDStr;
     ListScope ResourceType(W, Level.str() + Name.str());
     if (Entry.Offset.isSubDir()) {
       W.printHex("Table Offset", Entry.Offset.value());
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp
index 0f508f8..f221acb 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -298,6 +298,13 @@
 
   std::vector<GroupSection> getGroups();
 
+  // Returns the function symbol index for the given address. Matches the
+  // symbol's section with FunctionSec when specified.
+  // Returns None if no function symbol can be found for the address or in case
+  // it is not defined in the specified section.
+  SmallVector<uint32_t>
+  getSymbolIndexesForFunctionAddress(uint64_t SymValue,
+                                     Optional<const Elf_Shdr *> FunctionSec);
   bool printFunctionStackSize(uint64_t SymValue,
                               Optional<const Elf_Shdr *> FunctionSec,
                               const Elf_Shdr &StackSizeSec, DataExtractor Data,
@@ -306,11 +313,18 @@
                       unsigned Ndx, const Elf_Shdr *SymTab,
                       const Elf_Shdr *FunctionSec, const Elf_Shdr &StackSizeSec,
                       const RelocationResolver &Resolver, DataExtractor Data);
-  virtual void printStackSizeEntry(uint64_t Size, StringRef FuncName) = 0;
+  virtual void printStackSizeEntry(uint64_t Size,
+                                   ArrayRef<std::string> FuncNames) = 0;
 
   void printRelocatableStackSizes(std::function<void()> PrintHeader);
   void printNonRelocatableStackSizes(std::function<void()> PrintHeader);
 
+  /// Retrieves sections with corresponding relocation sections based on
+  /// IsMatch.
+  void getSectionAndRelocations(
+      std::function<bool(const Elf_Shdr &)> IsMatch,
+      llvm::MapVector<const Elf_Shdr *, const Elf_Shdr *> &SecToRelocMap);
+
   const object::ELFObjectFile<ELFT> &ObjF;
   const ELFFile<ELFT> &Obj;
   StringRef FileName;
@@ -349,10 +363,10 @@
   const Elf_GnuHash *GnuHashTable = nullptr;
   const Elf_Shdr *DotSymtabSec = nullptr;
   const Elf_Shdr *DotDynsymSec = nullptr;
-  const Elf_Shdr *DotCGProfileSec = nullptr;
   const Elf_Shdr *DotAddrsigSec = nullptr;
   DenseMap<const Elf_Shdr *, ArrayRef<Elf_Word>> ShndxTables;
   Optional<uint64_t> SONameOffset;
+  Optional<DenseMap<uint64_t, std::vector<uint32_t>>> AddressToIndexMap;
 
   const Elf_Shdr *SymbolVersionSection = nullptr;   // .gnu.version
   const Elf_Shdr *SymbolVersionNeedSection = nullptr; // .gnu.version_r
@@ -550,6 +564,7 @@
   void printVersionDependencySection(const Elf_Shdr *Sec) override;
   void printHashHistograms() override;
   void printCGProfile() override;
+  void printBBAddrMaps() override;
   void printAddrsig() override;
   void printNotes() override;
   void printELFLinkerOptions() override;
@@ -631,7 +646,8 @@
   void printGNUVersionSectionProlog(const typename ELFT::Shdr &Sec,
                                     const Twine &Label, unsigned EntriesNum);
 
-  void printStackSizeEntry(uint64_t Size, StringRef FuncName) override;
+  void printStackSizeEntry(uint64_t Size,
+                           ArrayRef<std::string> FuncNames) override;
 
   void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
   void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
@@ -660,6 +676,7 @@
   void printVersionDependencySection(const Elf_Shdr *Sec) override;
   void printHashHistograms() override;
   void printCGProfile() override;
+  void printBBAddrMaps() override;
   void printAddrsig() override;
   void printNotes() override;
   void printELFLinkerOptions() override;
@@ -678,7 +695,8 @@
                    bool /*NonVisibilityBitsUsed*/) const override;
   void printProgramHeaders() override;
   void printSectionMapping() override {}
-  void printStackSizeEntry(uint64_t Size, StringRef FuncName) override;
+  void printStackSizeEntry(uint64_t Size,
+                           ArrayRef<std::string> FuncNames) override;
 
   void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
   void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
@@ -1138,7 +1156,7 @@
   ENUM_ENT(EM_METAG,         "Imagination Technologies Meta processor architecture"),
   ENUM_ENT(EM_MCST_ELBRUS,   "MCST Elbrus general purpose hardware architecture"),
   ENUM_ENT(EM_ECOG16,        "Cyan Technology eCOG16 family"),
-  ENUM_ENT(EM_CR16,          "Xilinx MicroBlaze"),
+  ENUM_ENT(EM_CR16,          "National Semiconductor CompactRISC 16-bit processor"),
   ENUM_ENT(EM_ETPU,          "Freescale Extended Time Processing Unit"),
   ENUM_ENT(EM_SLE9X,         "Infineon Technologies SLE9X core"),
   ENUM_ENT(EM_L10M,          "EM_L10M"),
@@ -1148,6 +1166,7 @@
   ENUM_ENT(EM_STM8,          "STMicroeletronics STM8 8-bit microcontroller"),
   ENUM_ENT(EM_TILE64,        "Tilera TILE64 multicore architecture family"),
   ENUM_ENT(EM_TILEPRO,       "Tilera TILEPro multicore architecture family"),
+  ENUM_ENT(EM_MICROBLAZE,    "Xilinx MicroBlaze 32-bit RISC soft processor core"),
   ENUM_ENT(EM_CUDA,          "NVIDIA CUDA architecture"),
   ENUM_ENT(EM_TILEGX,        "Tilera TILE-Gx multicore architecture family"),
   ENUM_ENT(EM_CLOUDSHIELD,   "EM_CLOUDSHIELD"),
@@ -1201,6 +1220,7 @@
   ENUM_ENT(SHF_GROUP,            "G"),
   ENUM_ENT(SHF_TLS,              "T"),
   ENUM_ENT(SHF_COMPRESSED,       "C"),
+  ENUM_ENT(SHF_GNU_RETAIN,       "R"),
   ENUM_ENT(SHF_EXCLUDE,          "E"),
 };
 
@@ -1427,7 +1447,7 @@
   ENUM_ENT(EF_MIPS_ARCH_64R6, "mips64r6")
 };
 
-static const EnumEntry<unsigned> ElfHeaderAMDGPUFlags[] = {
+static const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion3[] = {
   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_NONE),
   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R600),
   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R630),
@@ -1465,16 +1485,78 @@
   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX906),
   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX908),
   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX909),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90A),
   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90C),
   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1010),
   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1011),
   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1012),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1013),
   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1030),
   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1031),
   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1032),
   LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1033),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_XNACK),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_SRAM_ECC)
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1034),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1035),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_V3),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_SRAMECC_V3)
+};
+
+static const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion4[] = {
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_NONE),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R600),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R630),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RS880),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV670),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV710),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV730),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV770),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CEDAR),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CYPRESS),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_JUNIPER),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_REDWOOD),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_SUMO),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_BARTS),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAICOS),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAYMAN),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_TURKS),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX600),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX601),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX602),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX700),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX701),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX702),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX703),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX704),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX705),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX801),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX802),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX803),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX805),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX810),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX900),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX902),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX904),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX906),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX908),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX909),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90A),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90C),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1010),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1011),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1012),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1013),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1030),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1031),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1032),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1033),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1034),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1035),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_ANY_V4),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_OFF_V4),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_ON_V4),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_SRAMECC_ANY_V4),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_SRAMECC_OFF_V4),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_SRAMECC_ON_V4)
 };
 
 static const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = {
@@ -1485,6 +1567,29 @@
   ENUM_ENT(EF_RISCV_RVE, "RVE")
 };
 
+static const EnumEntry<unsigned> ElfHeaderAVRFlags[] = {
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR1),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR2),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR25),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR3),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR31),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR35),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR4),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR5),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR51),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVR6),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_AVRTINY),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA1),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA2),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA3),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA4),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA5),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA6),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_AVR_ARCH_XMEGA7),
+  ENUM_ENT(EF_AVR_LINKRELAX_PREPARED, "relaxable"),
+};
+
+
 static const EnumEntry<unsigned> ElfSymOtherFlags[] = {
   LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL),
   LLVM_READOBJ_ENUM_ENT(ELF, STV_HIDDEN),
@@ -1743,10 +1848,6 @@
       if (!SymbolVersionNeedSection)
         SymbolVersionNeedSection = &Sec;
       break;
-    case ELF::SHT_LLVM_CALL_GRAPH_PROFILE:
-      if (!DotCGProfileSec)
-        DotCGProfileSec = &Sec;
-      break;
     case ELF::SHT_LLVM_ADDRSIG:
       if (!DotAddrsigSec)
         DotAddrsigSec = &Sec;
@@ -3170,6 +3271,9 @@
                    unsigned(ELF::EF_MIPS_MACH));
   else if (e.e_machine == EM_RISCV)
     ElfFlags = printFlags(e.e_flags, makeArrayRef(ElfHeaderRISCVFlags));
+  else if (e.e_machine == EM_AVR)
+    ElfFlags = printFlags(e.e_flags, makeArrayRef(ElfHeaderAVRFlags),
+                          unsigned(ELF::EF_AVR_ARCH_MASK));
   Str = "0x" + to_hexString(e.e_flags);
   if (!ElfFlags.empty())
     Str = Str + ", " + ElfFlags;
@@ -3483,15 +3587,14 @@
   OS << "  L (link order), O (extra OS processing required), G (group), T "
         "(TLS),\n";
   OS << "  C (compressed), x (unknown), o (OS specific), E (exclude),\n";
+  OS << "  R (retain)";
 
   if (EMachine == EM_X86_64)
-    OS << "  l (large), ";
+    OS << ", l (large)";
   else if (EMachine == EM_ARM)
-    OS << "  y (purecode), ";
-  else
-    OS << "  ";
+    OS << ", y (purecode)";
 
-  OS << "p (processor specific)\n";
+  OS << ", p (processor specific)\n";
 }
 
 template <class ELFT> void GNUELFDumper<ELFT>::printSectionHeaders() {
@@ -3934,21 +4037,17 @@
 
     uint64_t Flags = S.sh_flags;
     uint64_t UnknownFlags = 0;
-    bool NeedsComma = false;
+    ListSeparator LS;
     while (Flags) {
       // Take the least significant bit as a flag.
       uint64_t Flag = Flags & -Flags;
       Flags -= Flag;
 
       auto It = FlagToName.find(Flag);
-      if (It != FlagToName.end()) {
-        if (NeedsComma)
-          OS << ", ";
-        NeedsComma = true;
-        OS << It->second;
-      } else {
+      if (It != FlagToName.end())
+        OS << LS << It->second;
+      else
         UnknownFlags |= Flag;
-      }
     }
 
     auto PrintUnknownFlags = [&](uint64_t Mask, StringRef Name) {
@@ -3956,12 +4055,9 @@
       if (!FlagsToPrint)
         return;
 
-      if (NeedsComma)
-        OS << ", ";
-      OS << Name << " ("
+      OS << LS << Name << " ("
          << to_string(format_hex_no_prefix(FlagsToPrint, AddrSize)) << ")";
       UnknownFlags &= ~Mask;
-      NeedsComma = true;
     };
 
     PrintUnknownFlags(SHF_MASKOS, "OS");
@@ -4623,6 +4719,10 @@
   OS << "GNUStyle::printCGProfile not implemented\n";
 }
 
+template <class ELFT> void GNUELFDumper<ELFT>::printBBAddrMaps() {
+  OS << "GNUStyle::printBBAddrMaps not implemented\n";
+}
+
 static Expected<std::vector<uint64_t>> toULEB128Array(ArrayRef<uint8_t> Data) {
   std::vector<uint64_t> Ret;
   const uint8_t *Cur = Data.begin();
@@ -4736,47 +4836,6 @@
     if (PrData)
       OS << format("<unknown flags: 0x%x>", PrData);
     return OS.str();
-  case GNU_PROPERTY_X86_ISA_1_NEEDED:
-  case GNU_PROPERTY_X86_ISA_1_USED:
-    OS << "x86 ISA "
-       << (Type == GNU_PROPERTY_X86_ISA_1_NEEDED ? "needed: " : "used: ");
-    if (DataSize != 4) {
-      OS << format("<corrupt length: 0x%x>", DataSize);
-      return OS.str();
-    }
-    PrData = support::endian::read32<ELFT::TargetEndianness>(Data.data());
-    if (PrData == 0) {
-      OS << "<None>";
-      return OS.str();
-    }
-    DumpBit(GNU_PROPERTY_X86_ISA_1_CMOV, "CMOV");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_SSE, "SSE");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_SSE2, "SSE2");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_SSE3, "SSE3");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_SSSE3, "SSSE3");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_SSE4_1, "SSE4_1");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_SSE4_2, "SSE4_2");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX, "AVX");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX2, "AVX2");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_FMA, "FMA");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512F, "AVX512F");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512CD, "AVX512CD");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512ER, "AVX512ER");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512PF, "AVX512PF");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512VL, "AVX512VL");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512DQ, "AVX512DQ");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512BW, "AVX512BW");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_4FMAPS, "AVX512_4FMAPS");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_4VNNIW, "AVX512_4VNNIW");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_BITALG, "AVX512_BITALG");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_IFMA, "AVX512_IFMA");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_VBMI, "AVX512_VBMI");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_VBMI2, "AVX512_VBMI2");
-    DumpBit(GNU_PROPERTY_X86_ISA_1_AVX512_VNNI, "AVX512_VNNI");
-    if (PrData)
-      OS << format("<unknown flags: 0x%x>", PrData);
-    return OS.str();
-    break;
   case GNU_PROPERTY_X86_FEATURE_2_NEEDED:
   case GNU_PROPERTY_X86_FEATURE_2_USED:
     OS << "x86 feature "
@@ -4803,6 +4862,26 @@
     if (PrData)
       OS << format("<unknown flags: 0x%x>", PrData);
     return OS.str();
+  case GNU_PROPERTY_X86_ISA_1_NEEDED:
+  case GNU_PROPERTY_X86_ISA_1_USED:
+    OS << "x86 ISA "
+       << (Type == GNU_PROPERTY_X86_ISA_1_NEEDED ? "needed: " : "used: ");
+    if (DataSize != 4) {
+      OS << format("<corrupt length: 0x%x>", DataSize);
+      return OS.str();
+    }
+    PrData = support::endian::read32<ELFT::TargetEndianness>(Data.data());
+    if (PrData == 0) {
+      OS << "<None>";
+      return OS.str();
+    }
+    DumpBit(GNU_PROPERTY_X86_ISA_1_BASELINE, "x86-64-baseline");
+    DumpBit(GNU_PROPERTY_X86_ISA_1_V2, "x86-64-v2");
+    DumpBit(GNU_PROPERTY_X86_ISA_1_V3, "x86-64-v3");
+    DumpBit(GNU_PROPERTY_X86_ISA_1_V4, "x86-64-v4");
+    if (PrData)
+      OS << format("<unknown flags: 0x%x>", PrData);
+    return OS.str();
   }
 }
 
@@ -4877,11 +4956,12 @@
 }
 
 template <typename ELFT>
-static void printGNUNote(raw_ostream &OS, uint32_t NoteType,
+static bool printGNUNote(raw_ostream &OS, uint32_t NoteType,
                          ArrayRef<uint8_t> Desc) {
+  // Return true if we were able to pretty-print the note, false otherwise.
   switch (NoteType) {
   default:
-    return;
+    return false;
   case ELF::NT_GNU_ABI_TAG: {
     const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc);
     if (!AbiTag.IsValid)
@@ -4904,6 +4984,54 @@
     break;
   }
   OS << '\n';
+  return true;
+}
+
+static const EnumEntry<unsigned> FreeBSDFeatureCtlFlags[] = {
+    {"ASLR_DISABLE", NT_FREEBSD_FCTL_ASLR_DISABLE},
+    {"PROTMAX_DISABLE", NT_FREEBSD_FCTL_PROTMAX_DISABLE},
+    {"STKGAP_DISABLE", NT_FREEBSD_FCTL_STKGAP_DISABLE},
+    {"WXNEEDED", NT_FREEBSD_FCTL_WXNEEDED},
+    {"LA48", NT_FREEBSD_FCTL_LA48},
+    {"ASG_DISABLE", NT_FREEBSD_FCTL_ASG_DISABLE},
+};
+
+struct FreeBSDNote {
+  std::string Type;
+  std::string Value;
+};
+
+template <typename ELFT>
+static Optional<FreeBSDNote>
+getFreeBSDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc, bool IsCore) {
+  if (IsCore)
+    return None; // No pretty-printing yet.
+  switch (NoteType) {
+  case ELF::NT_FREEBSD_ABI_TAG:
+    if (Desc.size() != 4)
+      return None;
+    return FreeBSDNote{
+        "ABI tag",
+        utostr(support::endian::read32<ELFT::TargetEndianness>(Desc.data()))};
+  case ELF::NT_FREEBSD_ARCH_TAG:
+    return FreeBSDNote{"Arch tag", toStringRef(Desc).str()};
+  case ELF::NT_FREEBSD_FEATURE_CTL: {
+    if (Desc.size() != 4)
+      return None;
+    unsigned Value =
+        support::endian::read32<ELFT::TargetEndianness>(Desc.data());
+    std::string FlagsStr;
+    raw_string_ostream OS(FlagsStr);
+    printFlags(Value, makeArrayRef(FreeBSDFeatureCtlFlags), OS);
+    if (OS.str().empty())
+      OS << "0x" << utohexstr(Value);
+    else
+      OS << "(0x" << utohexstr(Value) << ")";
+    return FreeBSDNote{"Feature flags", OS.str()};
+  }
+  default:
+    return None;
+  }
 }
 
 struct AMDNote {
@@ -4916,15 +5044,98 @@
   switch (NoteType) {
   default:
     return {"", ""};
-  case ELF::NT_AMD_AMDGPU_HSA_METADATA:
+  case ELF::NT_AMD_HSA_CODE_OBJECT_VERSION: {
+    struct CodeObjectVersion {
+      uint32_t MajorVersion;
+      uint32_t MinorVersion;
+    };
+    if (Desc.size() != sizeof(CodeObjectVersion))
+      return {"AMD HSA Code Object Version",
+              "Invalid AMD HSA Code Object Version"};
+    std::string VersionString;
+    raw_string_ostream StrOS(VersionString);
+    auto Version = reinterpret_cast<const CodeObjectVersion *>(Desc.data());
+    StrOS << "[Major: " << Version->MajorVersion
+          << ", Minor: " << Version->MinorVersion << "]";
+    return {"AMD HSA Code Object Version", VersionString};
+  }
+  case ELF::NT_AMD_HSA_HSAIL: {
+    struct HSAILProperties {
+      uint32_t HSAILMajorVersion;
+      uint32_t HSAILMinorVersion;
+      uint8_t Profile;
+      uint8_t MachineModel;
+      uint8_t DefaultFloatRound;
+    };
+    if (Desc.size() != sizeof(HSAILProperties))
+      return {"AMD HSA HSAIL Properties", "Invalid AMD HSA HSAIL Properties"};
+    auto Properties = reinterpret_cast<const HSAILProperties *>(Desc.data());
+    std::string HSAILPropetiesString;
+    raw_string_ostream StrOS(HSAILPropetiesString);
+    StrOS << "[HSAIL Major: " << Properties->HSAILMajorVersion
+          << ", HSAIL Minor: " << Properties->HSAILMinorVersion
+          << ", Profile: " << uint32_t(Properties->Profile)
+          << ", Machine Model: " << uint32_t(Properties->MachineModel)
+          << ", Default Float Round: "
+          << uint32_t(Properties->DefaultFloatRound) << "]";
+    return {"AMD HSA HSAIL Properties", HSAILPropetiesString};
+  }
+  case ELF::NT_AMD_HSA_ISA_VERSION: {
+    struct IsaVersion {
+      uint16_t VendorNameSize;
+      uint16_t ArchitectureNameSize;
+      uint32_t Major;
+      uint32_t Minor;
+      uint32_t Stepping;
+    };
+    if (Desc.size() < sizeof(IsaVersion))
+      return {"AMD HSA ISA Version", "Invalid AMD HSA ISA Version"};
+    auto Isa = reinterpret_cast<const IsaVersion *>(Desc.data());
+    if (Desc.size() < sizeof(IsaVersion) +
+                          Isa->VendorNameSize + Isa->ArchitectureNameSize ||
+        Isa->VendorNameSize == 0 || Isa->ArchitectureNameSize == 0)
+      return {"AMD HSA ISA Version", "Invalid AMD HSA ISA Version"};
+    std::string IsaString;
+    raw_string_ostream StrOS(IsaString);
+    StrOS << "[Vendor: "
+          << StringRef((const char*)Desc.data() + sizeof(IsaVersion), Isa->VendorNameSize - 1)
+          << ", Architecture: "
+          << StringRef((const char*)Desc.data() + sizeof(IsaVersion) + Isa->VendorNameSize,
+                       Isa->ArchitectureNameSize - 1)
+          << ", Major: " << Isa->Major << ", Minor: " << Isa->Minor
+          << ", Stepping: " << Isa->Stepping << "]";
+    return {"AMD HSA ISA Version", IsaString};
+  }
+  case ELF::NT_AMD_HSA_METADATA: {
+    if (Desc.size() == 0)
+      return {"AMD HSA Metadata", ""};
     return {
-        "HSA Metadata",
-        std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size())};
-  case ELF::NT_AMD_AMDGPU_ISA:
+        "AMD HSA Metadata",
+        std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size() - 1)};
+  }
+  case ELF::NT_AMD_HSA_ISA_NAME: {
+    if (Desc.size() == 0)
+      return {"AMD HSA ISA Name", ""};
     return {
-        "ISA Version",
+        "AMD HSA ISA Name",
         std::string(reinterpret_cast<const char *>(Desc.data()), Desc.size())};
   }
+  case ELF::NT_AMD_PAL_METADATA: {
+    struct PALMetadata {
+      uint32_t Key;
+      uint32_t Value;
+    };
+    if (Desc.size() % sizeof(PALMetadata) != 0)
+      return {"AMD PAL Metadata", "Invalid AMD PAL Metadata"};
+    auto Isa = reinterpret_cast<const PALMetadata *>(Desc.data());
+    std::string MetadataString;
+    raw_string_ostream StrOS(MetadataString);
+    for (size_t I = 0, E = Desc.size() / sizeof(PALMetadata); I < E; ++I) {
+      StrOS << "[" << Isa[I].Key << ": " << Isa[I].Value << "]";
+    }
+    return {"AMD PAL Metadata", MetadataString};
+  }
+  }
 }
 
 struct AMDGPUNote {
@@ -4942,16 +5153,22 @@
         StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());
     msgpack::Document MsgPackDoc;
     if (!MsgPackDoc.readFromBlob(MsgPackString, /*Multi=*/false))
-      return {"AMDGPU Metadata", "Invalid AMDGPU Metadata"};
+      return {"", ""};
 
     AMDGPU::HSAMD::V3::MetadataVerifier Verifier(true);
-    std::string HSAMetadataString;
+    std::string MetadataString;
     if (!Verifier.verify(MsgPackDoc.getRoot()))
-      HSAMetadataString = "Invalid AMDGPU Metadata\n";
+      MetadataString = "Invalid AMDGPU Metadata\n";
 
-    raw_string_ostream StrOS(HSAMetadataString);
+    raw_string_ostream StrOS(MetadataString);
+    if (MsgPackDoc.getRoot().isScalar()) {
+      // TODO: passing a scalar root to toYAML() asserts:
+      // (PolymorphicTraits<T>::getKind(Val) != NodeKind::Scalar &&
+      //    "plain scalar documents are not supported")
+      // To avoid this crash we print the raw data instead.
+      return {"", ""};
+    }
     MsgPackDoc.toYAML(StrOS);
-
     return {"AMDGPU Metadata", StrOS.str()};
   }
   }
@@ -5049,7 +5266,7 @@
     {ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"},
 };
 
-static const NoteType FreeBSDNoteTypes[] = {
+static const NoteType FreeBSDCoreNoteTypes[] = {
     {ELF::NT_FREEBSD_THRMISC, "NT_THRMISC (thrmisc structure)"},
     {ELF::NT_FREEBSD_PROCSTAT_PROC, "NT_PROCSTAT_PROC (proc data)"},
     {ELF::NT_FREEBSD_PROCSTAT_FILES, "NT_PROCSTAT_FILES (files data)"},
@@ -5063,12 +5280,22 @@
     {ELF::NT_FREEBSD_PROCSTAT_AUXV, "NT_PROCSTAT_AUXV (auxv data)"},
 };
 
+static const NoteType FreeBSDNoteTypes[] = {
+    {ELF::NT_FREEBSD_ABI_TAG, "NT_FREEBSD_ABI_TAG (ABI version tag)"},
+    {ELF::NT_FREEBSD_NOINIT_TAG, "NT_FREEBSD_NOINIT_TAG (no .init tag)"},
+    {ELF::NT_FREEBSD_ARCH_TAG, "NT_FREEBSD_ARCH_TAG (architecture tag)"},
+    {ELF::NT_FREEBSD_FEATURE_CTL,
+     "NT_FREEBSD_FEATURE_CTL (FreeBSD feature control)"},
+};
+
 static const NoteType AMDNoteTypes[] = {
-    {ELF::NT_AMD_AMDGPU_HSA_METADATA,
-     "NT_AMD_AMDGPU_HSA_METADATA (HSA Metadata)"},
-    {ELF::NT_AMD_AMDGPU_ISA, "NT_AMD_AMDGPU_ISA (ISA Version)"},
-    {ELF::NT_AMD_AMDGPU_PAL_METADATA,
-     "NT_AMD_AMDGPU_PAL_METADATA (PAL Metadata)"},
+    {ELF::NT_AMD_HSA_CODE_OBJECT_VERSION,
+     "NT_AMD_HSA_CODE_OBJECT_VERSION (AMD HSA Code Object Version)"},
+    {ELF::NT_AMD_HSA_HSAIL, "NT_AMD_HSA_HSAIL (AMD HSA HSAIL Properties)"},
+    {ELF::NT_AMD_HSA_ISA_VERSION, "NT_AMD_HSA_ISA_VERSION (AMD HSA ISA Version)"},
+    {ELF::NT_AMD_HSA_METADATA, "NT_AMD_HSA_METADATA (AMD HSA Metadata)"},
+    {ELF::NT_AMD_HSA_ISA_NAME, "NT_AMD_HSA_ISA_NAME (AMD HSA ISA Name)"},
+    {ELF::NT_AMD_PAL_METADATA, "NT_AMD_PAL_METADATA (AMD PAL Metadata)"},
 };
 
 static const NoteType AMDGPUNoteTypes[] = {
@@ -5141,8 +5368,7 @@
 };
 
 template <class ELFT>
-const StringRef getNoteTypeName(const typename ELFT::Note &Note,
-                                unsigned ELFType) {
+StringRef getNoteTypeName(const typename ELFT::Note &Note, unsigned ELFType) {
   uint32_t Type = Note.getType();
   auto FindNote = [&](ArrayRef<NoteType> V) -> StringRef {
     for (const NoteType &N : V)
@@ -5154,8 +5380,17 @@
   StringRef Name = Note.getName();
   if (Name == "GNU")
     return FindNote(GNUNoteTypes);
-  if (Name == "FreeBSD")
-    return FindNote(FreeBSDNoteTypes);
+  if (Name == "FreeBSD") {
+    if (ELFType == ELF::ET_CORE) {
+      // FreeBSD also places the generic core notes in the FreeBSD namespace.
+      StringRef Result = FindNote(FreeBSDCoreNoteTypes);
+      if (!Result.empty())
+        return Result;
+      return FindNote(CoreNoteTypes);
+    } else {
+      return FindNote(FreeBSDNoteTypes);
+    }
+  }
   if (Name == "AMD")
     return FindNote(AMDNoteTypes);
   if (Name == "AMDGPU")
@@ -5172,12 +5407,13 @@
     llvm::function_ref<void(Optional<StringRef>, typename ELFT::Off,
                             typename ELFT::Addr)>
         StartNotesFn,
-    llvm::function_ref<Error(const typename ELFT::Note &)> ProcessNoteFn,
+    llvm::function_ref<Error(const typename ELFT::Note &, bool)> ProcessNoteFn,
     llvm::function_ref<void()> FinishNotesFn) {
   const ELFFile<ELFT> &Obj = Dumper.getElfObject().getELFFile();
+  bool IsCoreFile = Obj.getHeader().e_type == ELF::ET_CORE;
 
   ArrayRef<typename ELFT::Shdr> Sections = cantFail(Obj.sections());
-  if (Obj.getHeader().e_type != ELF::ET_CORE && !Sections.empty()) {
+  if (!IsCoreFile && !Sections.empty()) {
     for (const typename ELFT::Shdr &S : Sections) {
       if (S.sh_type != SHT_NOTE)
         continue;
@@ -5186,7 +5422,7 @@
       Error Err = Error::success();
       size_t I = 0;
       for (const typename ELFT::Note Note : Obj.notes(S, Err)) {
-        if (Error E = ProcessNoteFn(Note))
+        if (Error E = ProcessNoteFn(Note, IsCoreFile))
           Dumper.reportUniqueWarning(
               "unable to read note with index " + Twine(I) + " from the " +
               describe(Obj, S) + ": " + toString(std::move(E)));
@@ -5217,7 +5453,7 @@
     Error Err = Error::success();
     size_t Index = 0;
     for (const typename ELFT::Note Note : Obj.notes(P, Err)) {
-      if (Error E = ProcessNoteFn(Note))
+      if (Error E = ProcessNoteFn(Note, IsCoreFile))
         Dumper.reportUniqueWarning("unable to read note with index " +
                                    Twine(Index) +
                                    " from the PT_NOTE segment with index " +
@@ -5233,9 +5469,17 @@
 }
 
 template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
+  bool IsFirstHeader = true;
   auto PrintHeader = [&](Optional<StringRef> SecName,
                          const typename ELFT::Off Offset,
                          const typename ELFT::Addr Size) {
+    // Print a newline between notes sections to match GNU readelf.
+    if (!IsFirstHeader) {
+      OS << '\n';
+    } else {
+      IsFirstHeader = false;
+    }
+
     OS << "Displaying notes found ";
 
     if (SecName)
@@ -5247,7 +5491,7 @@
     OS << "  Owner                Data size \tDescription\n";
   };
 
-  auto ProcessNote = [&](const Elf_Note &Note) -> Error {
+  auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error {
     StringRef Name = Note.getName();
     ArrayRef<uint8_t> Descriptor = Note.getDesc();
     Elf_Word Type = Note.getType();
@@ -5264,28 +5508,42 @@
       OS << "Unknown note type: (" << format_hex(Type, 10) << ")\n";
 
     // Print the description, or fallback to printing raw bytes for unknown
-    // owners.
+    // owners/if we fail to pretty-print the contents.
     if (Name == "GNU") {
-      printGNUNote<ELFT>(OS, Type, Descriptor);
+      if (printGNUNote<ELFT>(OS, Type, Descriptor))
+        return Error::success();
+    } else if (Name == "FreeBSD") {
+      if (Optional<FreeBSDNote> N =
+              getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) {
+        OS << "    " << N->Type << ": " << N->Value << '\n';
+        return Error::success();
+      }
     } else if (Name == "AMD") {
       const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);
-      if (!N.Type.empty())
+      if (!N.Type.empty()) {
         OS << "    " << N.Type << ":\n        " << N.Value << '\n';
+        return Error::success();
+      }
     } else if (Name == "AMDGPU") {
       const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);
-      if (!N.Type.empty())
+      if (!N.Type.empty()) {
         OS << "    " << N.Type << ":\n        " << N.Value << '\n';
+        return Error::success();
+      }
     } else if (Name == "CORE") {
       if (Type == ELF::NT_FILE) {
         DataExtractor DescExtractor(Descriptor,
                                     ELFT::TargetEndianness == support::little,
                                     sizeof(Elf_Addr));
-        if (Expected<CoreNote> NoteOrErr = readCoreNote(DescExtractor))
+        if (Expected<CoreNote> NoteOrErr = readCoreNote(DescExtractor)) {
           printCoreNote<ELFT>(OS, *NoteOrErr);
-        else
+          return Error::success();
+        } else {
           return NoteOrErr.takeError();
+        }
       }
-    } else if (!Descriptor.empty()) {
+    }
+    if (!Descriptor.empty()) {
       OS << "   description data:";
       for (uint8_t B : Descriptor)
         OS << " " << format("%02x", B);
@@ -5461,64 +5719,81 @@
 }
 
 template <class ELFT>
-bool ELFDumper<ELFT>::printFunctionStackSize(
-    uint64_t SymValue, Optional<const Elf_Shdr *> FunctionSec,
-    const Elf_Shdr &StackSizeSec, DataExtractor Data, uint64_t *Offset) {
-  uint32_t FuncSymIndex = 0;
-  if (this->DotSymtabSec) {
-    if (Expected<Elf_Sym_Range> SymsOrError = Obj.symbols(this->DotSymtabSec)) {
-      uint32_t Index = (uint32_t)-1;
-      for (const Elf_Sym &Sym : *SymsOrError) {
-        ++Index;
+SmallVector<uint32_t> ELFDumper<ELFT>::getSymbolIndexesForFunctionAddress(
+    uint64_t SymValue, Optional<const Elf_Shdr *> FunctionSec) {
+  SmallVector<uint32_t> SymbolIndexes;
+  if (!this->AddressToIndexMap.hasValue()) {
+    // Populate the address to index map upon the first invocation of this
+    // function.
+    this->AddressToIndexMap.emplace();
+    if (this->DotSymtabSec) {
+      if (Expected<Elf_Sym_Range> SymsOrError =
+              Obj.symbols(this->DotSymtabSec)) {
+        uint32_t Index = (uint32_t)-1;
+        for (const Elf_Sym &Sym : *SymsOrError) {
+          ++Index;
 
-        if (Sym.st_shndx == ELF::SHN_UNDEF || Sym.getType() != ELF::STT_FUNC)
-          continue;
-
-        if (Expected<uint64_t> SymAddrOrErr =
-                ObjF.toSymbolRef(this->DotSymtabSec, Index).getAddress()) {
-          if (SymValue != *SymAddrOrErr)
+          if (Sym.st_shndx == ELF::SHN_UNDEF || Sym.getType() != ELF::STT_FUNC)
             continue;
-        } else {
-          std::string Name = this->getStaticSymbolName(Index);
-          reportUniqueWarning("unable to get address of symbol '" + Name +
-                              "': " + toString(SymAddrOrErr.takeError()));
-          break;
-        }
 
-        // Check if the symbol is in the right section. FunctionSec == None
-        // means "any section".
-        if (FunctionSec) {
-          if (Expected<const Elf_Shdr *> SecOrErr =
-                  Obj.getSection(Sym, this->DotSymtabSec,
-                                 this->getShndxTable(this->DotSymtabSec))) {
-            if (*FunctionSec != *SecOrErr)
-              continue;
-          } else {
+          Expected<uint64_t> SymAddrOrErr =
+              ObjF.toSymbolRef(this->DotSymtabSec, Index).getAddress();
+          if (!SymAddrOrErr) {
             std::string Name = this->getStaticSymbolName(Index);
-            // Note: it is impossible to trigger this error currently, it is
-            // untested.
-            reportUniqueWarning("unable to get section of symbol '" + Name +
-                                "': " + toString(SecOrErr.takeError()));
-            break;
+            reportUniqueWarning("unable to get address of symbol '" + Name +
+                                "': " + toString(SymAddrOrErr.takeError()));
+            return SymbolIndexes;
           }
-        }
 
-        FuncSymIndex = Index;
-        break;
+          (*this->AddressToIndexMap)[*SymAddrOrErr].push_back(Index);
+        }
+      } else {
+        reportUniqueWarning("unable to read the symbol table: " +
+                            toString(SymsOrError.takeError()));
       }
-    } else {
-      reportUniqueWarning("unable to read the symbol table: " +
-                          toString(SymsOrError.takeError()));
     }
   }
 
-  std::string FuncName = "?";
-  if (!FuncSymIndex)
+  auto Symbols = this->AddressToIndexMap->find(SymValue);
+  if (Symbols == this->AddressToIndexMap->end())
+    return SymbolIndexes;
+
+  for (uint32_t Index : Symbols->second) {
+    // Check if the symbol is in the right section. FunctionSec == None
+    // means "any section".
+    if (FunctionSec) {
+      const Elf_Sym &Sym = *cantFail(Obj.getSymbol(this->DotSymtabSec, Index));
+      if (Expected<const Elf_Shdr *> SecOrErr =
+              Obj.getSection(Sym, this->DotSymtabSec,
+                             this->getShndxTable(this->DotSymtabSec))) {
+        if (*FunctionSec != *SecOrErr)
+          continue;
+      } else {
+        std::string Name = this->getStaticSymbolName(Index);
+        // Note: it is impossible to trigger this error currently, it is
+        // untested.
+        reportUniqueWarning("unable to get section of symbol '" + Name +
+                            "': " + toString(SecOrErr.takeError()));
+        return SymbolIndexes;
+      }
+    }
+
+    SymbolIndexes.push_back(Index);
+  }
+
+  return SymbolIndexes;
+}
+
+template <class ELFT>
+bool ELFDumper<ELFT>::printFunctionStackSize(
+    uint64_t SymValue, Optional<const Elf_Shdr *> FunctionSec,
+    const Elf_Shdr &StackSizeSec, DataExtractor Data, uint64_t *Offset) {
+  SmallVector<uint32_t> FuncSymIndexes =
+      this->getSymbolIndexesForFunctionAddress(SymValue, FunctionSec);
+  if (FuncSymIndexes.empty())
     reportUniqueWarning(
         "could not identify function symbol for stack size entry in " +
         describe(StackSizeSec));
-  else
-    FuncName = this->getStaticSymbolName(FuncSymIndex);
 
   // Extract the size. The expectation is that Offset is pointing to the right
   // place, i.e. past the function address.
@@ -5530,17 +5805,27 @@
                         toString(std::move(Err)));
     return false;
   }
-  printStackSizeEntry(StackSize, FuncName);
+
+  if (FuncSymIndexes.empty()) {
+    printStackSizeEntry(StackSize, {"?"});
+  } else {
+    SmallVector<std::string> FuncSymNames;
+    for (uint32_t Index : FuncSymIndexes)
+      FuncSymNames.push_back(this->getStaticSymbolName(Index));
+    printStackSizeEntry(StackSize, FuncSymNames);
+  }
+
   return true;
 }
 
 template <class ELFT>
 void GNUELFDumper<ELFT>::printStackSizeEntry(uint64_t Size,
-                                             StringRef FuncName) {
+                                             ArrayRef<std::string> FuncNames) {
   OS.PadToColumn(2);
   OS << format_decimal(Size, 11);
   OS.PadToColumn(18);
-  OS << FuncName << "\n";
+
+  OS << join(FuncNames.begin(), FuncNames.end(), ", ") << "\n";
 }
 
 template <class ELFT>
@@ -5628,28 +5913,15 @@
 }
 
 template <class ELFT>
-void ELFDumper<ELFT>::printRelocatableStackSizes(
-    std::function<void()> PrintHeader) {
-  // Build a map between stack size sections and their corresponding relocation
-  // sections.
-  llvm::MapVector<const Elf_Shdr *, const Elf_Shdr *> StackSizeRelocMap;
+void ELFDumper<ELFT>::getSectionAndRelocations(
+    std::function<bool(const Elf_Shdr &)> IsMatch,
+    llvm::MapVector<const Elf_Shdr *, const Elf_Shdr *> &SecToRelocMap) {
   for (const Elf_Shdr &Sec : cantFail(Obj.sections())) {
-    StringRef SectionName;
-    if (Expected<StringRef> NameOrErr = Obj.getSectionName(Sec))
-      SectionName = *NameOrErr;
-    else
-      consumeError(NameOrErr.takeError());
-
-    // A stack size section that we haven't encountered yet is mapped to the
-    // null section until we find its corresponding relocation section.
-    if (SectionName == ".stack_sizes")
-      if (StackSizeRelocMap
-              .insert(std::make_pair(&Sec, (const Elf_Shdr *)nullptr))
+    if (IsMatch(Sec))
+      if (SecToRelocMap.insert(std::make_pair(&Sec, (const Elf_Shdr *)nullptr))
               .second)
         continue;
 
-    // Check relocation sections if they are relocating contents of a
-    // stack sizes section.
     if (Sec.sh_type != ELF::SHT_RELA && Sec.sh_type != ELF::SHT_REL)
       continue;
 
@@ -5660,14 +5932,28 @@
                           toString(RelSecOrErr.takeError()));
       continue;
     }
-
     const Elf_Shdr *ContentsSec = *RelSecOrErr;
-    if (this->getPrintableSectionName(**RelSecOrErr) != ".stack_sizes")
-      continue;
-
-    // Insert a mapping from the stack sizes section to its relocation section.
-    StackSizeRelocMap[ContentsSec] = &Sec;
+    if (IsMatch(*ContentsSec))
+      SecToRelocMap[ContentsSec] = &Sec;
   }
+}
+
+template <class ELFT>
+void ELFDumper<ELFT>::printRelocatableStackSizes(
+    std::function<void()> PrintHeader) {
+  // Build a map between stack size sections and their corresponding relocation
+  // sections.
+  llvm::MapVector<const Elf_Shdr *, const Elf_Shdr *> StackSizeRelocMap;
+  auto IsMatch = [&](const Elf_Shdr &Sec) -> bool {
+    StringRef SectionName;
+    if (Expected<StringRef> NameOrErr = Obj.getSectionName(Sec))
+      SectionName = *NameOrErr;
+    else
+      consumeError(NameOrErr.takeError());
+
+    return SectionName == ".stack_sizes";
+  };
+  getSectionAndRelocations(IsMatch, StackSizeRelocMap);
 
   for (const auto &StackSizeMapEntry : StackSizeRelocMap) {
     PrintHeader();
@@ -5728,7 +6014,7 @@
     OS.PadToColumn(9);
     OS << "Size";
     OS.PadToColumn(18);
-    OS << "Function\n";
+    OS << "Functions\n";
     HeaderHasBeenPrinted = true;
   };
 
@@ -5977,11 +6263,32 @@
       W.printFlags("Flags", E.e_flags, makeArrayRef(ElfHeaderMipsFlags),
                    unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI),
                    unsigned(ELF::EF_MIPS_MACH));
-    else if (E.e_machine == EM_AMDGPU)
-      W.printFlags("Flags", E.e_flags, makeArrayRef(ElfHeaderAMDGPUFlags),
-                   unsigned(ELF::EF_AMDGPU_MACH));
-    else if (E.e_machine == EM_RISCV)
+    else if (E.e_machine == EM_AMDGPU) {
+      switch (E.e_ident[ELF::EI_ABIVERSION]) {
+      default:
+        W.printHex("Flags", E.e_flags);
+        break;
+      case 0:
+        // ELFOSABI_AMDGPU_PAL, ELFOSABI_AMDGPU_MESA3D support *_V3 flags.
+        LLVM_FALLTHROUGH;
+      case ELF::ELFABIVERSION_AMDGPU_HSA_V3:
+        W.printFlags("Flags", E.e_flags,
+                     makeArrayRef(ElfHeaderAMDGPUFlagsABIVersion3),
+                     unsigned(ELF::EF_AMDGPU_MACH));
+        break;
+      case ELF::ELFABIVERSION_AMDGPU_HSA_V4:
+        W.printFlags("Flags", E.e_flags,
+                     makeArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),
+                     unsigned(ELF::EF_AMDGPU_MACH),
+                     unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),
+                     unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4));
+        break;
+      }
+    } else if (E.e_machine == EM_RISCV)
       W.printFlags("Flags", E.e_flags, makeArrayRef(ElfHeaderRISCVFlags));
+    else if (E.e_machine == EM_AVR)
+      W.printFlags("Flags", E.e_flags, makeArrayRef(ElfHeaderAVRFlags),
+                   unsigned(ELF::EF_AVR_ARCH_MASK));
     else
       W.printFlags("Flags", E.e_flags);
     W.printNumber("HeaderSize", E.e_ehsize);
@@ -6407,28 +6714,142 @@
   W.startLine() << "Hash Histogram not implemented!\n";
 }
 
-template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() {
-  ListScope L(W, "CGProfile");
-  if (!this->DotCGProfileSec)
-    return;
-
-  Expected<ArrayRef<Elf_CGProfile>> CGProfileOrErr =
-      this->Obj.template getSectionContentsAsArray<Elf_CGProfile>(
-          *this->DotCGProfileSec);
-  if (!CGProfileOrErr) {
-    this->reportUniqueWarning(
-        "unable to dump the SHT_LLVM_CALL_GRAPH_PROFILE section: " +
-        toString(CGProfileOrErr.takeError()));
-    return;
+// Returns true if rel/rela section exists, and populates SymbolIndices.
+// Otherwise returns false.
+template <class ELFT>
+static bool getSymbolIndices(const typename ELFT::Shdr *CGRelSection,
+                             const ELFFile<ELFT> &Obj,
+                             const LLVMELFDumper<ELFT> *Dumper,
+                             SmallVector<uint32_t, 128> &SymbolIndices) {
+  if (!CGRelSection) {
+    Dumper->reportUniqueWarning(
+        "relocation section for a call graph section doesn't exist");
+    return false;
   }
 
-  for (const Elf_CGProfile &CGPE : *CGProfileOrErr) {
-    DictScope D(W, "CGProfileEntry");
-    W.printNumber("From", this->getStaticSymbolName(CGPE.cgp_from),
-                  CGPE.cgp_from);
-    W.printNumber("To", this->getStaticSymbolName(CGPE.cgp_to),
-                  CGPE.cgp_to);
-    W.printNumber("Weight", CGPE.cgp_weight);
+  if (CGRelSection->sh_type == SHT_REL) {
+    typename ELFT::RelRange CGProfileRel;
+    Expected<typename ELFT::RelRange> CGProfileRelOrError =
+        Obj.rels(*CGRelSection);
+    if (!CGProfileRelOrError) {
+      Dumper->reportUniqueWarning("unable to load relocations for "
+                                  "SHT_LLVM_CALL_GRAPH_PROFILE section: " +
+                                  toString(CGProfileRelOrError.takeError()));
+      return false;
+    }
+
+    CGProfileRel = *CGProfileRelOrError;
+    for (const typename ELFT::Rel &Rel : CGProfileRel)
+      SymbolIndices.push_back(Rel.getSymbol(Obj.isMips64EL()));
+  } else {
+    // MC unconditionally produces SHT_REL, but GNU strip/objcopy may convert
+    // the format to SHT_RELA
+    // (https://sourceware.org/bugzilla/show_bug.cgi?id=28035)
+    typename ELFT::RelaRange CGProfileRela;
+    Expected<typename ELFT::RelaRange> CGProfileRelaOrError =
+        Obj.relas(*CGRelSection);
+    if (!CGProfileRelaOrError) {
+      Dumper->reportUniqueWarning("unable to load relocations for "
+                                  "SHT_LLVM_CALL_GRAPH_PROFILE section: " +
+                                  toString(CGProfileRelaOrError.takeError()));
+      return false;
+    }
+
+    CGProfileRela = *CGProfileRelaOrError;
+    for (const typename ELFT::Rela &Rela : CGProfileRela)
+      SymbolIndices.push_back(Rela.getSymbol(Obj.isMips64EL()));
+  }
+
+  return true;
+}
+
+template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() {
+  llvm::MapVector<const Elf_Shdr *, const Elf_Shdr *> SecToRelocMap;
+
+  auto IsMatch = [](const Elf_Shdr &Sec) -> bool {
+    return Sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE;
+  };
+  this->getSectionAndRelocations(IsMatch, SecToRelocMap);
+
+  for (const auto &CGMapEntry : SecToRelocMap) {
+    const Elf_Shdr *CGSection = CGMapEntry.first;
+    const Elf_Shdr *CGRelSection = CGMapEntry.second;
+
+    Expected<ArrayRef<Elf_CGProfile>> CGProfileOrErr =
+        this->Obj.template getSectionContentsAsArray<Elf_CGProfile>(*CGSection);
+    if (!CGProfileOrErr) {
+      this->reportUniqueWarning(
+          "unable to load the SHT_LLVM_CALL_GRAPH_PROFILE section: " +
+          toString(CGProfileOrErr.takeError()));
+      return;
+    }
+
+    SmallVector<uint32_t, 128> SymbolIndices;
+    bool UseReloc =
+        getSymbolIndices<ELFT>(CGRelSection, this->Obj, this, SymbolIndices);
+    if (UseReloc && SymbolIndices.size() != CGProfileOrErr->size() * 2) {
+      this->reportUniqueWarning(
+          "number of from/to pairs does not match number of frequencies");
+      UseReloc = false;
+    }
+
+    ListScope L(W, "CGProfile");
+    for (uint32_t I = 0, Size = CGProfileOrErr->size(); I != Size; ++I) {
+      const Elf_CGProfile &CGPE = (*CGProfileOrErr)[I];
+      DictScope D(W, "CGProfileEntry");
+      if (UseReloc) {
+        uint32_t From = SymbolIndices[I * 2];
+        uint32_t To = SymbolIndices[I * 2 + 1];
+        W.printNumber("From", this->getStaticSymbolName(From), From);
+        W.printNumber("To", this->getStaticSymbolName(To), To);
+      }
+      W.printNumber("Weight", CGPE.cgp_weight);
+    }
+  }
+}
+
+template <class ELFT> void LLVMELFDumper<ELFT>::printBBAddrMaps() {
+  bool IsRelocatable = this->Obj.getHeader().e_type == ELF::ET_REL;
+  for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {
+    if (Sec.sh_type != SHT_LLVM_BB_ADDR_MAP)
+      continue;
+    Optional<const Elf_Shdr *> FunctionSec = None;
+    if (IsRelocatable)
+      FunctionSec =
+          unwrapOrError(this->FileName, this->Obj.getSection(Sec.sh_link));
+    ListScope L(W, "BBAddrMap");
+    Expected<std::vector<Elf_BBAddrMap>> BBAddrMapOrErr =
+        this->Obj.decodeBBAddrMap(Sec);
+    if (!BBAddrMapOrErr) {
+      this->reportUniqueWarning("unable to dump " + this->describe(Sec) + ": " +
+                                toString(BBAddrMapOrErr.takeError()));
+      continue;
+    }
+    for (const Elf_BBAddrMap &AM : *BBAddrMapOrErr) {
+      DictScope D(W, "Function");
+      W.printHex("At", AM.Addr);
+      SmallVector<uint32_t> FuncSymIndex =
+          this->getSymbolIndexesForFunctionAddress(AM.Addr, FunctionSec);
+      std::string FuncName = "<?>";
+      if (FuncSymIndex.empty())
+        this->reportUniqueWarning(
+            "could not identify function symbol for address (0x" +
+            Twine::utohexstr(AM.Addr) + ") in " + this->describe(Sec));
+      else
+        FuncName = this->getStaticSymbolName(FuncSymIndex.front());
+      W.printString("Name", FuncName);
+
+      ListScope L(W, "BB entries");
+      for (const typename Elf_BBAddrMap::BBEntry &BBE : AM.BBEntries) {
+        DictScope L(W);
+        W.printHex("Offset", BBE.Offset);
+        W.printHex("Size", BBE.Size);
+        W.printBoolean("HasReturn", BBE.HasReturn);
+        W.printBoolean("HasTailCall", BBE.HasTailCall);
+        W.printBoolean("IsEHPad", BBE.IsEHPad);
+        W.printBoolean("CanFallThrough", BBE.CanFallThrough);
+      }
+    }
   }
 }
 
@@ -6449,15 +6870,17 @@
 }
 
 template <typename ELFT>
-static void printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
+static bool printGNUNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
                                   ScopedPrinter &W) {
+  // Return true if we were able to pretty-print the note, false otherwise.
   switch (NoteType) {
   default:
-    return;
+    return false;
   case ELF::NT_GNU_ABI_TAG: {
     const GNUAbiTag &AbiTag = getGNUAbiTag<ELFT>(Desc);
     if (!AbiTag.IsValid) {
       W.printString("ABI", "<corrupt GNU_ABI_TAG>");
+      return false;
     } else {
       W.printString("OS", AbiTag.OSName);
       W.printString("ABI", AbiTag.ABI);
@@ -6477,6 +6900,7 @@
       W.printString(Property);
     break;
   }
+  return true;
 }
 
 static void printCoreNoteLLVMStyle(const CoreNote &Note, ScopedPrinter &W) {
@@ -6505,7 +6929,7 @@
 
   auto EndNotes = [&] { NoteScope.reset(); };
 
-  auto ProcessNote = [&](const Elf_Note &Note) -> Error {
+  auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error {
     DictScope D2(W, "Note");
     StringRef Name = Note.getName();
     ArrayRef<uint8_t> Descriptor = Note.getDesc();
@@ -6524,28 +6948,42 @@
                     "Unknown (" + to_string(format_hex(Type, 10)) + ")");
 
     // Print the description, or fallback to printing raw bytes for unknown
-    // owners.
+    // owners/if we fail to pretty-print the contents.
     if (Name == "GNU") {
-      printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W);
+      if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W))
+        return Error::success();
+    } else if (Name == "FreeBSD") {
+      if (Optional<FreeBSDNote> N =
+              getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) {
+        W.printString(N->Type, N->Value);
+        return Error::success();
+      }
     } else if (Name == "AMD") {
       const AMDNote N = getAMDNote<ELFT>(Type, Descriptor);
-      if (!N.Type.empty())
+      if (!N.Type.empty()) {
         W.printString(N.Type, N.Value);
+        return Error::success();
+      }
     } else if (Name == "AMDGPU") {
       const AMDGPUNote N = getAMDGPUNote<ELFT>(Type, Descriptor);
-      if (!N.Type.empty())
+      if (!N.Type.empty()) {
         W.printString(N.Type, N.Value);
+        return Error::success();
+      }
     } else if (Name == "CORE") {
       if (Type == ELF::NT_FILE) {
         DataExtractor DescExtractor(Descriptor,
                                     ELFT::TargetEndianness == support::little,
                                     sizeof(Elf_Addr));
-        if (Expected<CoreNote> Note = readCoreNote(DescExtractor))
-          printCoreNoteLLVMStyle(*Note, W);
-        else
-          return Note.takeError();
+        if (Expected<CoreNote> N = readCoreNote(DescExtractor)) {
+          printCoreNoteLLVMStyle(*N, W);
+          return Error::success();
+        } else {
+          return N.takeError();
+        }
       }
-    } else if (!Descriptor.empty()) {
+    }
+    if (!Descriptor.empty()) {
       W.printBinaryBlock("Description data", Descriptor);
     }
     return Error::success();
@@ -6614,9 +7052,10 @@
 }
 
 template <class ELFT>
-void LLVMELFDumper<ELFT>::printStackSizeEntry(uint64_t Size, StringRef FuncName) {
+void LLVMELFDumper<ELFT>::printStackSizeEntry(uint64_t Size,
+                                              ArrayRef<std::string> FuncNames) {
   DictScope D(W, "Entry");
-  W.printString("Function", FuncName);
+  W.printList("Functions", FuncNames);
   W.printHex("Size", Size);
 }
 
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/MachODumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/MachODumper.cpp
index c13b1f3..433ca93 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/MachODumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/MachODumper.cpp
@@ -256,11 +256,14 @@
 };
 
 static const EnumEntry<unsigned> MachOSymbolFlags[] = {
+  { "ThumbDef",               0x8 },
   { "ReferencedDynamically", 0x10 },
   { "NoDeadStrip",           0x20 },
   { "WeakRef",               0x40 },
   { "WeakDef",               0x80 },
+  { "SymbolResolver",       0x100 },
   { "AltEntry",             0x200 },
+  { "ColdFunc",             0x400 },
 };
 
 static const EnumEntry<unsigned> MachOSymbolTypes[] = {
@@ -651,9 +654,9 @@
                 makeArrayRef(MachOSymbolTypes));
   }
   W.printHex("Section", SectionName, MOSymbol.SectionIndex);
-  W.printEnum("RefType", static_cast<uint16_t>(MOSymbol.Flags & 0xF),
+  W.printEnum("RefType", static_cast<uint16_t>(MOSymbol.Flags & 0x7),
               makeArrayRef(MachOSymbolRefTypes));
-  W.printFlags("Flags", static_cast<uint16_t>(MOSymbol.Flags & ~0xF),
+  W.printFlags("Flags", static_cast<uint16_t>(MOSymbol.Flags & ~0x7),
                makeArrayRef(MachOSymbolFlags));
   W.printHex("Value", MOSymbol.Value);
 }
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.cpp
index fc91d81..87c2293 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.cpp
@@ -52,6 +52,25 @@
     W << (isPrint(Start[i]) ? static_cast<char>(Start[i]) : '.');
 }
 
+void ObjDumper::printAsStringList(StringRef StringContent) {
+  const uint8_t *StrContent = StringContent.bytes_begin();
+  const uint8_t *CurrentWord = StrContent;
+  const uint8_t *StrEnd = StringContent.bytes_end();
+
+  while (CurrentWord <= StrEnd) {
+    size_t WordSize = strnlen(reinterpret_cast<const char *>(CurrentWord),
+                              StrEnd - CurrentWord);
+    if (!WordSize) {
+      CurrentWord++;
+      continue;
+    }
+    W.startLine() << format("[%6tx] ", CurrentWord - StrContent);
+    printAsPrintable(W.startLine(), CurrentWord, WordSize);
+    W.startLine() << '\n';
+    CurrentWord += WordSize + 1;
+  }
+}
+
 static std::vector<object::SectionRef>
 getSectionRefsByNameOrIndex(const object::ObjectFile &Obj,
                             ArrayRef<std::string> Sections) {
@@ -109,23 +128,7 @@
 
     StringRef SectionContent =
         unwrapOrError(Obj.getFileName(), Section.getContents());
-
-    const uint8_t *SecContent = SectionContent.bytes_begin();
-    const uint8_t *CurrentWord = SecContent;
-    const uint8_t *SecEnd = SectionContent.bytes_end();
-
-    while (CurrentWord <= SecEnd) {
-      size_t WordSize = strnlen(reinterpret_cast<const char *>(CurrentWord),
-                                SecEnd - CurrentWord);
-      if (!WordSize) {
-        CurrentWord++;
-        continue;
-      }
-      W.startLine() << format("[%6tx] ", CurrentWord - SecContent);
-      printAsPrintable(W.startLine(), CurrentWord, WordSize);
-      W.startLine() << '\n';
-      CurrentWord += WordSize + 1;
-    }
+    printAsStringList(SectionContent);
   }
 }
 
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h b/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h
index d4e166b..7e1c0ca 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h
@@ -72,6 +72,7 @@
   virtual void printGroupSections() {}
   virtual void printHashHistograms() {}
   virtual void printCGProfile() {}
+  virtual void printBBAddrMaps() {}
   virtual void printAddrsig() {}
   virtual void printNotes() {}
   virtual void printELFLinkerOptions() {}
@@ -104,8 +105,13 @@
   virtual void printMachOIndirectSymbols() { }
   virtual void printMachOLinkerOptions() { }
 
+  // Currently only implemented for XCOFF.
+  virtual void printStringTable() { }
+
   virtual void printStackMap() const = 0;
 
+  void printAsStringList(StringRef StringContent);
+
   void printSectionsAsString(const object::ObjectFile &Obj,
                              ArrayRef<std::string> Sections);
   void printSectionsAsHex(const object::ObjectFile &Obj,
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/Opts.td b/src/llvm-project/llvm/tools/llvm-readobj/Opts.td
new file mode 100644
index 0000000..493b937
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-readobj/Opts.td
@@ -0,0 +1,128 @@
+include "llvm/Option/OptParser.td"
+
+class F<string letter, string help> : Flag<["-"], letter>, HelpText<help>;
+class FF<string name, string help> : Flag<["--"], name>, HelpText<help>;
+
+multiclass BB<string name, string help1, string help2> {
+  def NAME: Flag<["--"], name>, HelpText<help1>;
+  def no_ # NAME: Flag<["--"], "no-" # name>, HelpText<help2>;
+}
+
+multiclass Eq<string name, string help> {
+  def NAME #_EQ : Joined<["--"], name #"=">, HelpText<help>;
+  def : Separate<["--"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
+}
+
+def addrsig : FF<"addrsig", "Display address-significance table">;
+def all : FF<"all", "Equivalent to setting: --file-header, --program-headers, --section-headers, "
+             "--symbols, --relocations, --dynamic-table, --notes, --version-info, --unwind, "
+             "--section-groups and --histogram">;
+def arch_specific : FF<"arch-specific", "Display architecture-specific information">;
+def bb_addr_map : FF<"bb-addr-map", "Display the BB address map section">;
+def cg_profile : FF<"cg-profile", "Display call graph profile section">;
+defm demangle : BB<"demangle", "Demangle symbol names", "Do not demangle symbol names (default)">;
+def dependent_libraries : FF<"dependent-libraries", "Display the dependent libraries section">;
+def dyn_relocations : FF<"dyn-relocations", "Display the dynamic relocation entries in the file">;
+def dyn_syms : FF<"dyn-syms", "Display the dynamic symbol table">;
+def expand_relocs : FF<"expand-relocs", "Expand each shown relocation to multiple lines">;
+def file_header : FF<"file-header", "Display file header">;
+def headers : FF<"headers", "Equivalent to setting: --file-header, --program-headers, --section-headers">;
+defm hex_dump : Eq<"hex-dump", "Display the specified section(s) as hexadecimal bytes">, MetaVarName<"<name or index>">;
+def relocs : FF<"relocs", "Display the relocation entries in the file">;
+def section_data : FF<"section-data", "Display section data for each section shown">;
+def section_details : FF<"section-details", "Display the section details">;
+def section_headers : FF<"section-headers", "Display section headers">;
+def section_mapping : FF<"section-mapping", "Display the section to segment mapping">;
+def section_mapping_EQ_false : FF<"section-mapping=false", "Don't display the section to segment mapping">, Flags<[HelpHidden]>;
+def section_relocations : FF<"section-relocations", "Display relocations for each section shown">;
+def section_symbols : FF<"section-symbols", "Display symbols for each section shown">;
+def stack_sizes : FF<"stack-sizes", "Display contents of all stack sizes sections">;
+def stackmap : FF<"stackmap", "Display contents of stackmap section">;
+defm string_dump : Eq<"string-dump", "Display the specified section(s) as a list of strings">, MetaVarName<"<name or index>">;
+def string_table : FF<"string-table", "Display the string table (only for XCOFF now)">;
+def symbols : FF<"symbols", "Display the symbol table. Also display the dynamic symbol table when using GNU output style for ELF">;
+def unwind : FF<"unwind", "Display unwind information">;
+
+// ELF specific options.
+def grp_elf : OptionGroup<"kind">, HelpText<"OPTIONS (ELF specific)">;
+def dynamic_table : FF<"dynamic-table", "Display the dynamic section table">, Group<grp_elf>;
+def elf_linker_options : FF<"elf-linker-options", "Display the .linker-options section">, Group<grp_elf>;
+defm elf_output_style : Eq<"elf-output-style", "Specify ELF dump style">, Group<grp_elf>;
+def histogram : FF<"histogram", "Display bucket list histogram for hash sections">, Group<grp_elf>;
+def section_groups : FF<"section-groups", "Display section groups">, Group<grp_elf>;
+def gnu_hash_table : FF<"gnu-hash-table", "Display .gnu.hash section">, Group<grp_elf>;
+def hash_symbols : FF<"hash-symbols", "Display the dynamic symbols derived from the hash section">, Group<grp_elf>;
+def hash_table : FF<"hash-table", "Display .hash section">, Group<grp_elf>;
+def needed_libs : FF<"needed-libs", "Display the needed libraries">, Group<grp_elf>;
+def notes : FF<"notes", "Display notes">, Group<grp_elf>;
+def program_headers : FF<"program-headers", "Display program headers">, Group<grp_elf>;
+def raw_relr : FF<"raw-relr", "Do not decode relocations in SHT_RELR section, display raw contents">, Group<grp_elf>;
+def version_info : FF<"version-info", "Display version sections">, Group<grp_elf>;
+
+// Mach-O specific options.
+def grp_mach_o : OptionGroup<"kind">, HelpText<"OPTIONS (Mach-O specific)">;
+def macho_data_in_code : FF<"macho-data-in-code", "Display Data in Code command">, Group<grp_mach_o>;
+def macho_dysymtab : FF<"macho-dysymtab", "Display Dysymtab command">, Group<grp_mach_o>;
+def macho_indirect_symbols : FF<"macho-indirect-symbols", "Display indirect symbols">, Group<grp_mach_o>;
+def macho_linker_options : FF<"macho-linker-options", "Display linker options">, Group<grp_mach_o>;
+def macho_segment : FF<"macho-segment", "Display Segment command">, Group<grp_mach_o>;
+def macho_version_min : FF<"macho-version-min", "Display version min command">, Group<grp_mach_o>;
+
+// PE/COFF specific options.
+def grp_coff : OptionGroup<"kind">, HelpText<"OPTIONS (PE/COFF specific)">;
+def codeview : FF<"codeview", "Display CodeView debug information">, Group<grp_coff>;
+def codeview_ghash : FF<"codeview-ghash", "Enable global hashing for CodeView type stream de-duplication">, Group<grp_coff>;
+def codeview_merged_types : FF<"codeview-merged-types", "Display the merged CodeView type stream">, Group<grp_coff>;
+def codeview_subsection_bytes : FF<"codeview-subsection-bytes", "Dump raw contents of codeview debug sections and records">, Group<grp_coff>;
+def coff_basereloc : FF<"coff-basereloc", "Display .reloc section">, Group<grp_coff>;
+def coff_debug_directory : FF<"coff-debug-directory", "Display debug directory">, Group<grp_coff>;
+def coff_directives : FF<"coff-directives", "Display .drectve section">, Group<grp_coff>;
+def coff_exports : FF<"coff-exports", "Display export table">, Group<grp_coff>;
+def coff_imports : FF<"coff-imports", "Display import table">, Group<grp_coff>;
+def coff_load_config : FF<"coff-load-config", "Display load config">, Group<grp_coff>;
+def coff_resources : FF<"coff-resources", "Display .rsrc section">, Group<grp_coff>;
+def coff_tls_directory : FF<"coff-tls-directory", "Display TLS directory">, Group<grp_coff>;
+
+def help : FF<"help", "Display this help">;
+def version : FF<"version", "Display the version">;
+
+// Ignored for GNU readelf compatibility.
+def : F<"W", "Ignored for GNU readelf compatibility">;
+def : FF<"wide", "Ignored for GNU readelf compatibility">;
+
+// Traditional llvm-readobj Aliases.
+def : Flag<["--"], "dt">, Alias<dyn_syms>, HelpText<"Alias for --dyn-syms">;
+def : Flag<["--"], "sd">, Alias<section_data>, HelpText<"Alias for --section-data">;
+def : Flag<["--"], "st">, Alias<section_symbols>, HelpText<"Alias for --section-symbols">;
+def : Flag<["--"], "sr">, Alias<section_relocations>, HelpText<"Alias for --section-relocations">;
+
+// Aliases.
+def : FF<"dyn-symbols", "Alias for --dyn-syms">, Alias<dyn_syms>;
+def : FF<"dynamic", "Alias for --dynamic-table">, Alias<dynamic_table>;
+def : FF<"elf-cg-profile", "Alias for --cg-profile">, Alias<cg_profile>, Flags<[HelpHidden]>;
+def : FF<"elf-hash-histogram", "Alias for --histogram">, Alias<histogram>, Flags<[HelpHidden]>;
+def : FF<"elf-section-groups", "Alias for --section-groups">, Alias<section_groups>, Flags<[HelpHidden]>;
+def : FF<"file-headers", "Alias for --file-header">, Alias<file_header>, Flags<[HelpHidden]>;
+def : FF<"relocations", "Alias for --relocs">, Alias<relocs>;
+def : FF<"sections", "Alias for --section-headers">, Alias<section_headers>;
+def : FF<"segments", "Alias for --program-headers">, Alias<program_headers>, Group<grp_elf>;
+def : FF<"syms", "Alias for --symbols">, Alias<symbols>;
+
+def : F<"A", "Alias for --arch-specific">, Alias<arch_specific>;
+def : F<"a", "Alias for --all">, Alias<all>;
+def : F<"C", "Alias for --demangle">, Alias<demangle>;
+def : F<"d", "Alias for --dynamic-table">, Alias<dynamic_table>, Group<grp_elf>;
+def : F<"e", "Alias for --headers">, Alias<headers>;
+def : F<"g", "Alias for --section-groups">, Alias<section_groups>, Group<grp_elf>;
+def : F<"h", "Alias for --file-header">, Alias<file_header>;
+def : F<"I", "Alias for --histogram">, Alias<histogram>, Group<grp_elf>;
+def : F<"l", "Alias for --program-headers">, Alias<program_headers>;
+def : F<"n", "Alias for --notes">, Alias<notes>;
+def : JoinedOrSeparate<["-"], "p">, Alias<string_dump_EQ>, HelpText<"Alias for --string-dump">, MetaVarName<"<name or index>">;
+def : F<"r", "Alias for --relocs">, Alias<relocs>;
+def : F<"S", "Alias for --section-headers">, Alias<section_headers>;
+def : F<"s", "Alias for --symbols">, Alias<symbols>;
+def : F<"t", "Alias for --section-details">, Alias<section_details>;
+def : F<"u", "Alias for --unwind">, Alias<unwind>;
+def : F<"V", "Alias for --version-info">, Alias<version_info>, Group<grp_elf>;
+def : JoinedOrSeparate<["-"], "x">, Alias<hex_dump_EQ>, HelpText<"Alias for --hex-dump">, MetaVarName<"<name or index>">;
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/WasmDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/WasmDumper.cpp
index fb7134d..f7dcaa3 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/WasmDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/WasmDumper.cpp
@@ -23,8 +23,8 @@
 static const EnumEntry<unsigned> WasmSymbolTypes[] = {
 #define ENUM_ENTRY(X)                                                          \
   { #X, wasm::WASM_SYMBOL_TYPE_##X }
-    ENUM_ENTRY(FUNCTION), ENUM_ENTRY(DATA),  ENUM_ENTRY(GLOBAL),
-    ENUM_ENTRY(SECTION),  ENUM_ENTRY(EVENT), ENUM_ENTRY(TABLE),
+    ENUM_ENTRY(FUNCTION), ENUM_ENTRY(DATA), ENUM_ENTRY(GLOBAL),
+    ENUM_ENTRY(SECTION),  ENUM_ENTRY(TAG),  ENUM_ENTRY(TABLE),
 #undef ENUM_ENTRY
 };
 
@@ -33,7 +33,7 @@
   { #X, wasm::WASM_SEC_##X }
     ENUM_ENTRY(CUSTOM),   ENUM_ENTRY(TYPE),      ENUM_ENTRY(IMPORT),
     ENUM_ENTRY(FUNCTION), ENUM_ENTRY(TABLE),     ENUM_ENTRY(MEMORY),
-    ENUM_ENTRY(GLOBAL),   ENUM_ENTRY(EVENT),     ENUM_ENTRY(EXPORT),
+    ENUM_ENTRY(GLOBAL),   ENUM_ENTRY(TAG),       ENUM_ENTRY(EXPORT),
     ENUM_ENTRY(START),    ENUM_ENTRY(ELEM),      ENUM_ENTRY(CODE),
     ENUM_ENTRY(DATA),     ENUM_ENTRY(DATACOUNT),
 #undef ENUM_ENTRY
@@ -192,7 +192,7 @@
       ListScope Group(W, "Memories");
       for (const wasm::WasmLimits &Memory : Obj->memories()) {
         DictScope Group(W, "Memory");
-        W.printNumber("InitialPages", Memory.Initial);
+        W.printNumber("MinPages", Memory.Minimum);
         if (Memory.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) {
           W.printNumber("MaxPages", WasmSec.Offset);
         }
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp
index 8f0f18c..94ef96e 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp
@@ -34,13 +34,14 @@
   void printUnwindInfo() override;
   void printStackMap() const override;
   void printNeededLibraries() override;
+  void printStringTable() override;
 
 private:
   template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
   template <typename T> void printGenericSectionHeader(T &Sec) const;
   template <typename T> void printOverflowSectionHeader(T &Sec) const;
   void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);
-  void printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr);
+  void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef);
   void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr);
   void printSymbol(const SymbolRef &);
   void printRelocations(ArrayRef<XCOFFSectionHeader32> Sections);
@@ -164,10 +165,17 @@
 #undef ECase
 };
 
+static const EnumEntry<XCOFF::SymbolAuxType> SymAuxType[] = {
+#define ECase(X)                                                               \
+  { #X, XCOFF::X }
+    ECase(AUX_EXCEPT), ECase(AUX_FCN), ECase(AUX_SYM), ECase(AUX_FILE),
+    ECase(AUX_CSECT),  ECase(AUX_SECT)
+#undef ECase
+};
+
 void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {
-  if (Obj.is64Bit())
-    report_fatal_error(
-        "Printing for File Auxiliary Entry in 64-bit is unimplemented.");
+  assert((!Obj.is64Bit() || AuxEntPtr->AuxType == XCOFF::AUX_FILE) &&
+         "Mismatched auxiliary type!");
   StringRef FileName =
       unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr));
   DictScope SymDs(W, "File Auxiliary Entry");
@@ -176,19 +184,22 @@
   W.printString("Name", FileName);
   W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),
               makeArrayRef(FileStringType));
+  if (Obj.is64Bit()) {
+    W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
+                makeArrayRef(SymAuxType));
+  }
 }
 
 static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] =
     {
 #define ECase(X)                                                               \
   { #X, XCOFF::X }
-        ECase(XMC_PR),   ECase(XMC_RO),     ECase(XMC_DB),
-        ECase(XMC_GL),   ECase(XMC_XO),     ECase(XMC_SV),
-        ECase(XMC_SV64), ECase(XMC_SV3264), ECase(XMC_TI),
-        ECase(XMC_TB),   ECase(XMC_RW),     ECase(XMC_TC0),
-        ECase(XMC_TC),   ECase(XMC_TD),     ECase(XMC_DS),
-        ECase(XMC_UA),   ECase(XMC_BS),     ECase(XMC_UC),
-        ECase(XMC_TL),   ECase(XMC_TE)
+        ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB),   ECase(XMC_GL),
+        ECase(XMC_XO), ECase(XMC_SV), ECase(XMC_SV64), ECase(XMC_SV3264),
+        ECase(XMC_TI), ECase(XMC_TB), ECase(XMC_RW),   ECase(XMC_TC0),
+        ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS),   ECase(XMC_UA),
+        ECase(XMC_BS), ECase(XMC_UC), ECase(XMC_TL),   ECase(XMC_UL),
+        ECase(XMC_TE)
 #undef ECase
 };
 
@@ -199,27 +210,32 @@
 #undef ECase
 };
 
-void XCOFFDumper::printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr) {
-  assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
+void XCOFFDumper::printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef) {
+  assert((!Obj.is64Bit() || AuxEntRef.getAuxType64() == XCOFF::AUX_CSECT) &&
+         "Mismatched auxiliary type!");
 
   DictScope SymDs(W, "CSECT Auxiliary Entry");
-  W.printNumber("Index",
-                Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
-  if (AuxEntPtr->isLabel())
-    W.printNumber("ContainingCsectSymbolIndex", AuxEntPtr->SectionOrLength);
-  else
-    W.printNumber("SectionLen", AuxEntPtr->SectionOrLength);
-  W.printHex("ParameterHashIndex", AuxEntPtr->ParameterHashIndex);
-  W.printHex("TypeChkSectNum", AuxEntPtr->TypeChkSectNum);
+  W.printNumber("Index", Obj.getSymbolIndex(AuxEntRef.getEntryAddress()));
+  W.printNumber(AuxEntRef.isLabel() ? "ContainingCsectSymbolIndex"
+                                    : "SectionLen",
+                AuxEntRef.getSectionOrLength());
+  W.printHex("ParameterHashIndex", AuxEntRef.getParameterHashIndex());
+  W.printHex("TypeChkSectNum", AuxEntRef.getTypeChkSectNum());
   // Print out symbol alignment and type.
-  W.printNumber("SymbolAlignmentLog2", AuxEntPtr->getAlignmentLog2());
-  W.printEnum("SymbolType", AuxEntPtr->getSymbolType(),
+  W.printNumber("SymbolAlignmentLog2", AuxEntRef.getAlignmentLog2());
+  W.printEnum("SymbolType", AuxEntRef.getSymbolType(),
               makeArrayRef(CsectSymbolTypeClass));
   W.printEnum("StorageMappingClass",
-              static_cast<uint8_t>(AuxEntPtr->StorageMappingClass),
+              static_cast<uint8_t>(AuxEntRef.getStorageMappingClass()),
               makeArrayRef(CsectStorageMappingClass));
-  W.printHex("StabInfoIndex", AuxEntPtr->StabInfoIndex);
-  W.printHex("StabSectNum", AuxEntPtr->StabSectNum);
+
+  if (Obj.is64Bit()) {
+    W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_CSECT),
+                makeArrayRef(SymAuxType));
+  } else {
+    W.printHex("StabInfoIndex", AuxEntRef.getStabInfoIndex32());
+    W.printHex("StabSectNum", AuxEntRef.getStabSectNum32());
+  }
 }
 
 void XCOFFDumper::printSectAuxEntForStat(
@@ -301,53 +317,62 @@
 };
 
 void XCOFFDumper::printSymbol(const SymbolRef &S) {
-  if (Obj.is64Bit())
-    report_fatal_error("64-bit support is unimplemented.");
-
   DataRefImpl SymbolDRI = S.getRawDataRefImpl();
-  const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI);
+  XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI);
 
-  XCOFFSymbolRef XCOFFSymRef(SymbolDRI, &Obj);
-  uint8_t NumberOfAuxEntries = XCOFFSymRef.getNumberOfAuxEntries();
+  uint8_t NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();
 
   DictScope SymDs(W, "Symbol");
 
   StringRef SymbolName =
-      unwrapOrError(Obj.getFileName(), Obj.getSymbolName(SymbolDRI));
+      unwrapOrError(Obj.getFileName(), SymbolEntRef.getName());
 
-  W.printNumber("Index",
-                Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(SymbolEntPtr)));
+  W.printNumber("Index", Obj.getSymbolIndex(SymbolEntRef.getEntryAddress()));
   W.printString("Name", SymbolName);
-  W.printHex(GetSymbolValueName(SymbolEntPtr->StorageClass),
-             SymbolEntPtr->Value);
+  W.printHex(GetSymbolValueName(SymbolEntRef.getStorageClass()),
+             SymbolEntRef.getValue());
 
   StringRef SectionName =
-      unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntPtr));
+      unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntRef));
 
   W.printString("Section", SectionName);
-  if (XCOFFSymRef.getStorageClass() == XCOFF::C_FILE) {
-    W.printEnum("Source Language ID",
-                SymbolEntPtr->CFileLanguageIdAndTypeId.LanguageId,
+  if (SymbolEntRef.getStorageClass() == XCOFF::C_FILE) {
+    W.printEnum("Source Language ID", SymbolEntRef.getLanguageIdForCFile(),
                 makeArrayRef(CFileLangIdClass));
-    W.printEnum("CPU Version ID",
-                SymbolEntPtr->CFileLanguageIdAndTypeId.CpuTypeId,
+    W.printEnum("CPU Version ID", SymbolEntRef.getCPUTypeIddForCFile(),
                 makeArrayRef(CFileCpuIdClass));
   } else
-    W.printHex("Type", SymbolEntPtr->SymbolType);
+    W.printHex("Type", SymbolEntRef.getSymbolType());
 
-  W.printEnum("StorageClass", static_cast<uint8_t>(SymbolEntPtr->StorageClass),
+  W.printEnum("StorageClass",
+              static_cast<uint8_t>(SymbolEntRef.getStorageClass()),
               makeArrayRef(SymStorageClass));
-  W.printNumber("NumberOfAuxEntries", SymbolEntPtr->NumberOfAuxEntries);
+  W.printNumber("NumberOfAuxEntries", NumberOfAuxEntries);
 
   if (NumberOfAuxEntries == 0)
     return;
 
-  switch (XCOFFSymRef.getStorageClass()) {
+  switch (SymbolEntRef.getStorageClass()) {
   case XCOFF::C_FILE:
     // If the symbol is C_FILE and has auxiliary entries...
-    for (int i = 1; i <= NumberOfAuxEntries; i++) {
+    for (int I = 1; I <= NumberOfAuxEntries; I++) {
+      uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
+          SymbolEntRef.getEntryAddress(), I);
+
+      if (Obj.is64Bit() &&
+          *Obj.getSymbolAuxType(AuxAddress) != XCOFF::SymbolAuxType::AUX_FILE) {
+        W.startLine() << "!Unexpected raw auxiliary entry data:\n";
+        W.startLine() << format_bytes(
+                             ArrayRef<uint8_t>(
+                                 reinterpret_cast<const uint8_t *>(AuxAddress),
+                                 XCOFF::SymbolTableEntrySize),
+                             0, XCOFF::SymbolTableEntrySize)
+                      << "\n";
+        continue;
+      }
+
       const XCOFFFileAuxEnt *FileAuxEntPtr =
-          reinterpret_cast<const XCOFFFileAuxEnt *>(SymbolEntPtr + i);
+          reinterpret_cast<const XCOFFFileAuxEnt *>(AuxAddress);
 #ifndef NDEBUG
       Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(FileAuxEntPtr));
 #endif
@@ -356,34 +381,52 @@
     break;
   case XCOFF::C_EXT:
   case XCOFF::C_WEAKEXT:
-  case XCOFF::C_HIDEXT:
+  case XCOFF::C_HIDEXT: {
     // If the symbol is for a function, and it has more than 1 auxiliary entry,
     // then one of them must be function auxiliary entry which we do not
     // support yet.
-    if (XCOFFSymRef.isFunction() && NumberOfAuxEntries >= 2)
+    if (SymbolEntRef.isFunction() && NumberOfAuxEntries >= 2)
       report_fatal_error("Function auxiliary entry printing is unimplemented.");
 
     // If there is more than 1 auxiliary entry, instead of printing out
-    // error information, print out the raw Auxiliary entry from 1st till
-    // the last - 1. The last one must be a CSECT Auxiliary Entry.
-    for (int i = 1; i < NumberOfAuxEntries; i++) {
+    // error information, print out the raw Auxiliary entry.
+    // For 32-bit object, print from first to the last - 1. The last one must be
+    // a CSECT Auxiliary Entry.
+    // For 64-bit object, print from first to last and skips if SymbolAuxType is
+    // AUX_CSECT.
+    for (int I = 1; I <= NumberOfAuxEntries; I++) {
+      if (I == NumberOfAuxEntries && !Obj.is64Bit())
+        break;
+
+      uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
+          SymbolEntRef.getEntryAddress(), I);
+      if (Obj.is64Bit() &&
+          *Obj.getSymbolAuxType(AuxAddress) == XCOFF::SymbolAuxType::AUX_CSECT)
+        continue;
+
       W.startLine() << "!Unexpected raw auxiliary entry data:\n";
       W.startLine() << format_bytes(
-          ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
+          ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(AuxAddress),
                             XCOFF::SymbolTableEntrySize));
     }
 
-    // The symbol's last auxiliary entry is a CSECT Auxiliary Entry.
-    printCsectAuxEnt32(XCOFFSymRef.getXCOFFCsectAuxEnt32());
+    auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef();
+    if (!ErrOrCsectAuxRef)
+      reportUniqueWarning(ErrOrCsectAuxRef.takeError());
+    else
+      printCsectAuxEnt(*ErrOrCsectAuxRef);
+
     break;
+  }
   case XCOFF::C_STAT:
     if (NumberOfAuxEntries > 1)
       report_fatal_error(
           "C_STAT symbol should not have more than 1 auxiliary entry.");
 
     const XCOFFSectAuxEntForStat *StatAuxEntPtr;
-    StatAuxEntPtr =
-        reinterpret_cast<const XCOFFSectAuxEntForStat *>(SymbolEntPtr + 1);
+    StatAuxEntPtr = reinterpret_cast<const XCOFFSectAuxEntForStat *>(
+        XCOFFObjectFile::getAdvancedSymbolEntryAddress(
+            SymbolEntRef.getEntryAddress(), 1));
 #ifndef NDEBUG
     Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(StatAuxEntPtr));
 #endif
@@ -399,7 +442,9 @@
     for (int i = 1; i <= NumberOfAuxEntries; i++) {
       W.startLine() << "!Unexpected raw auxiliary entry data:\n";
       W.startLine() << format_bytes(
-          ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
+          ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(
+                                XCOFFObjectFile::getAdvancedSymbolEntryAddress(
+                                    SymbolEntRef.getEntryAddress(), i)),
                             XCOFF::SymbolTableEntrySize));
     }
     break;
@@ -412,6 +457,12 @@
     printSymbol(S);
 }
 
+void XCOFFDumper::printStringTable() {
+  DictScope DS(W, "StringTable");
+  StringRef StrTable = Obj.getStringTable();
+  printAsStringList(StrTable);
+}
+
 void XCOFFDumper::printDynamicSymbols() {
   llvm_unreachable("Unimplemented functionality for XCOFFDumper");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp b/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp
index 41cd441..0b49f03 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -31,6 +31,9 @@
 #include "llvm/Object/Wasm.h"
 #include "llvm/Object/WindowsResource.h"
 #include "llvm/Object/XCOFFObjectFile.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/DataTypes.h"
@@ -47,339 +50,107 @@
 using namespace llvm;
 using namespace llvm::object;
 
+namespace {
+using namespace llvm::opt; // for HelpHidden in Opts.inc
+enum ID {
+  OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  OPT_##ID,
+#include "Opts.inc"
+#undef OPTION
+};
+
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#include "Opts.inc"
+#undef PREFIX
+
+static const opt::OptTable::Info InfoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  {                                                                            \
+      PREFIX,      NAME,      HELPTEXT,                                        \
+      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
+      PARAM,       FLAGS,     OPT_##GROUP,                                     \
+      OPT_##ALIAS, ALIASARGS, VALUES},
+#include "Opts.inc"
+#undef OPTION
+};
+
+class ReadobjOptTable : public opt::OptTable {
+public:
+  ReadobjOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+};
+
+enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
+} // namespace
+
 namespace opts {
-  cl::list<std::string> InputFilenames(cl::Positional,
-    cl::desc("<input object files>"),
-    cl::ZeroOrMore);
+static bool Addrsig;
+static bool All;
+static bool ArchSpecificInfo;
+static bool BBAddrMap;
+bool ExpandRelocs;
+static bool CGProfile;
+bool Demangle;
+static bool DependentLibraries;
+static bool DynRelocs;
+static bool DynamicSymbols;
+static bool FileHeaders;
+static bool Headers;
+static std::vector<std::string> HexDump;
+static bool PrintStackMap;
+static bool PrintStackSizes;
+static bool Relocations;
+bool SectionData;
+static bool SectionDetails;
+static bool SectionHeaders;
+bool SectionRelocations;
+bool SectionSymbols;
+static std::vector<std::string> StringDump;
+static bool StringTable;
+static bool Symbols;
+static bool UnwindInfo;
+static cl::boolOrDefault SectionMapping;
 
-  // --all, -a
-  cl::opt<bool>
-      All("all",
-          cl::desc("Equivalent to setting: --file-headers, --program-headers, "
-                   "--section-headers, --symbols, --relocations, "
-                   "--dynamic-table, --notes, --version-info, --unwind, "
-                   "--section-groups and --elf-hash-histogram."));
-  cl::alias AllShort("a", cl::desc("Alias for --all"), cl::aliasopt(All));
+// ELF specific options.
+static bool DynamicTable;
+static bool ELFLinkerOptions;
+static bool GnuHashTable;
+static bool HashSymbols;
+static bool HashTable;
+static bool HashHistogram;
+static bool NeededLibraries;
+static bool Notes;
+static bool ProgramHeaders;
+bool RawRelr;
+static bool SectionGroups;
+static bool VersionInfo;
 
-  // --dependent-libraries
-  cl::opt<bool>
-      DependentLibraries("dependent-libraries",
-                         cl::desc("Display the dependent libraries section"));
+// Mach-O specific options.
+static bool MachODataInCode;
+static bool MachODysymtab;
+static bool MachOIndirectSymbols;
+static bool MachOLinkerOptions;
+static bool MachOSegment;
+static bool MachOVersionMin;
 
-  // --headers, -e
-  cl::opt<bool>
-      Headers("headers",
-          cl::desc("Equivalent to setting: --file-headers, --program-headers, "
-                   "--section-headers"));
-  cl::alias HeadersShort("e", cl::desc("Alias for --headers"),
-     cl::aliasopt(Headers));
+// PE/COFF specific options.
+static bool CodeView;
+static bool CodeViewEnableGHash;
+static bool CodeViewMergedTypes;
+bool CodeViewSubsectionBytes;
+static bool COFFBaseRelocs;
+static bool COFFDebugDirectory;
+static bool COFFDirectives;
+static bool COFFExports;
+static bool COFFImports;
+static bool COFFLoadConfig;
+static bool COFFResources;
+static bool COFFTLSDirectory;
 
-  // --wide, -W
-  cl::opt<bool>
-      WideOutput("wide", cl::desc("Ignored for compatibility with GNU readelf"),
-                 cl::Hidden);
-  cl::alias WideOutputShort("W",
-    cl::desc("Alias for --wide"),
-    cl::aliasopt(WideOutput));
-
-  // --file-headers, --file-header, -h
-  cl::opt<bool> FileHeaders("file-headers",
-    cl::desc("Display file headers "));
-  cl::alias FileHeadersShort("h", cl::desc("Alias for --file-headers"),
-                             cl::aliasopt(FileHeaders), cl::NotHidden);
-  cl::alias FileHeadersSingular("file-header",
-                                cl::desc("Alias for --file-headers"),
-                                cl::aliasopt(FileHeaders));
-
-  // --section-headers, --sections, -S
-  // Also -s in llvm-readobj mode.
-  cl::opt<bool> SectionHeaders("section-headers",
-                               cl::desc("Display all section headers."));
-  cl::alias SectionsShortUpper("S", cl::desc("Alias for --section-headers"),
-                               cl::aliasopt(SectionHeaders), cl::NotHidden);
-  cl::alias SectionHeadersAlias("sections",
-                                cl::desc("Alias for --section-headers"),
-                                cl::aliasopt(SectionHeaders), cl::NotHidden);
-
-  // --section-relocations
-  // Also --sr in llvm-readobj mode.
-  cl::opt<bool> SectionRelocations("section-relocations",
-    cl::desc("Display relocations for each section shown."));
-
-  // --section-symbols
-  // Also --st in llvm-readobj mode.
-  cl::opt<bool> SectionSymbols("section-symbols",
-    cl::desc("Display symbols for each section shown."));
-
-  // --section-data
-  // Also --sd in llvm-readobj mode.
-  cl::opt<bool> SectionData("section-data",
-    cl::desc("Display section data for each section shown."));
-
-  // --section-mapping
-  cl::opt<cl::boolOrDefault>
-      SectionMapping("section-mapping",
-                     cl::desc("Display the section to segment mapping."));
-
-  // --relocations, --relocs, -r
-  cl::opt<bool> Relocations("relocations",
-    cl::desc("Display the relocation entries in the file"));
-  cl::alias RelocationsShort("r", cl::desc("Alias for --relocations"),
-                             cl::aliasopt(Relocations), cl::NotHidden);
-  cl::alias RelocationsGNU("relocs", cl::desc("Alias for --relocations"),
-                           cl::aliasopt(Relocations));
-
-  // --notes, -n
-  cl::opt<bool> Notes("notes", cl::desc("Display the ELF notes in the file"));
-  cl::alias NotesShort("n", cl::desc("Alias for --notes"), cl::aliasopt(Notes));
-
-  // --dyn-relocations
-  cl::opt<bool> DynRelocs("dyn-relocations",
-    cl::desc("Display the dynamic relocation entries in the file"));
-
-  // --section-details
-  // Also -t in llvm-readelf mode.
-  cl::opt<bool> SectionDetails("section-details",
-                               cl::desc("Display the section details"));
-
-  // --symbols
-  // Also -s in llvm-readelf mode, or -t in llvm-readobj mode.
-  cl::opt<bool>
-      Symbols("symbols",
-              cl::desc("Display the symbol table. Also display the dynamic "
-                       "symbol table when using GNU output style for ELF"));
-  cl::alias SymbolsGNU("syms", cl::desc("Alias for --symbols"),
-                       cl::aliasopt(Symbols));
-
-  // --dyn-symbols, --dyn-syms
-  // Also --dt in llvm-readobj mode.
-  cl::opt<bool> DynamicSymbols("dyn-symbols",
-    cl::desc("Display the dynamic symbol table"));
-  cl::alias DynSymsGNU("dyn-syms", cl::desc("Alias for --dyn-symbols"),
-                       cl::aliasopt(DynamicSymbols));
-
-  // --hash-symbols
-  cl::opt<bool> HashSymbols(
-      "hash-symbols",
-      cl::desc("Display the dynamic symbols derived from the hash section"));
-
-  // --unwind, -u
-  cl::opt<bool> UnwindInfo("unwind",
-    cl::desc("Display unwind information"));
-  cl::alias UnwindInfoShort("u",
-    cl::desc("Alias for --unwind"),
-    cl::aliasopt(UnwindInfo));
-
-  // --dynamic-table, --dynamic, -d
-  cl::opt<bool> DynamicTable("dynamic-table",
-    cl::desc("Display the ELF .dynamic section table"));
-  cl::alias DynamicTableShort("d", cl::desc("Alias for --dynamic-table"),
-                              cl::aliasopt(DynamicTable), cl::NotHidden);
-  cl::alias DynamicTableAlias("dynamic", cl::desc("Alias for --dynamic-table"),
-                              cl::aliasopt(DynamicTable));
-
-  // --needed-libs
-  cl::opt<bool> NeededLibraries("needed-libs",
-    cl::desc("Display the needed libraries"));
-
-  // --program-headers, --segments, -l
-  cl::opt<bool> ProgramHeaders("program-headers",
-    cl::desc("Display ELF program headers"));
-  cl::alias ProgramHeadersShort("l", cl::desc("Alias for --program-headers"),
-                                cl::aliasopt(ProgramHeaders), cl::NotHidden);
-  cl::alias SegmentsAlias("segments", cl::desc("Alias for --program-headers"),
-                          cl::aliasopt(ProgramHeaders));
-
-  // --string-dump, -p
-  cl::list<std::string> StringDump(
-      "string-dump", cl::value_desc("number|name"),
-      cl::desc("Display the specified section(s) as a list of strings"),
-      cl::ZeroOrMore);
-  cl::alias StringDumpShort("p", cl::desc("Alias for --string-dump"),
-                            cl::aliasopt(StringDump), cl::Prefix);
-
-  // --hex-dump, -x
-  cl::list<std::string>
-      HexDump("hex-dump", cl::value_desc("number|name"),
-              cl::desc("Display the specified section(s) as hexadecimal bytes"),
-              cl::ZeroOrMore);
-  cl::alias HexDumpShort("x", cl::desc("Alias for --hex-dump"),
-                         cl::aliasopt(HexDump), cl::Prefix);
-
-  // --demangle, -C
-  cl::opt<bool> Demangle("demangle",
-                         cl::desc("Demangle symbol names in output"));
-  cl::alias DemangleShort("C", cl::desc("Alias for --demangle"),
-                          cl::aliasopt(Demangle), cl::NotHidden);
-
-  // --hash-table
-  cl::opt<bool> HashTable("hash-table",
-    cl::desc("Display ELF hash table"));
-
-  // --gnu-hash-table
-  cl::opt<bool> GnuHashTable("gnu-hash-table",
-    cl::desc("Display ELF .gnu.hash section"));
-
-  // --expand-relocs
-  cl::opt<bool> ExpandRelocs("expand-relocs",
-    cl::desc("Expand each shown relocation to multiple lines"));
-
-  // --raw-relr
-  cl::opt<bool> RawRelr("raw-relr",
-    cl::desc("Do not decode relocations in SHT_RELR section, display raw contents"));
-
-  // --codeview
-  cl::opt<bool> CodeView("codeview",
-                         cl::desc("Display CodeView debug information"));
-
-  // --codeview-merged-types
-  cl::opt<bool>
-      CodeViewMergedTypes("codeview-merged-types",
-                          cl::desc("Display the merged CodeView type stream"));
-
-  // --codeview-ghash
-  cl::opt<bool> CodeViewEnableGHash(
-      "codeview-ghash",
-      cl::desc(
-          "Enable global hashing for CodeView type stream de-duplication"));
-
-  // --codeview-subsection-bytes
-  cl::opt<bool> CodeViewSubsectionBytes(
-      "codeview-subsection-bytes",
-      cl::desc("Dump raw contents of codeview debug sections and records"));
-
-  // --arch-specific
-  cl::opt<bool> ArchSpecificInfo("arch-specific",
-                              cl::desc("Displays architecture-specific information, if there is any."));
-  cl::alias ArchSpecifcInfoShort("A", cl::desc("Alias for --arch-specific"),
-                                 cl::aliasopt(ArchSpecificInfo), cl::NotHidden);
-
-  // --coff-imports
-  cl::opt<bool>
-  COFFImports("coff-imports", cl::desc("Display the PE/COFF import table"));
-
-  // --coff-exports
-  cl::opt<bool>
-  COFFExports("coff-exports", cl::desc("Display the PE/COFF export table"));
-
-  // --coff-directives
-  cl::opt<bool>
-  COFFDirectives("coff-directives",
-                 cl::desc("Display the PE/COFF .drectve section"));
-
-  // --coff-basereloc
-  cl::opt<bool>
-  COFFBaseRelocs("coff-basereloc",
-                 cl::desc("Display the PE/COFF .reloc section"));
-
-  // --coff-debug-directory
-  cl::opt<bool>
-  COFFDebugDirectory("coff-debug-directory",
-                     cl::desc("Display the PE/COFF debug directory"));
-
-  // --coff-tls-directory
-  cl::opt<bool> COFFTLSDirectory("coff-tls-directory",
-                                 cl::desc("Display the PE/COFF TLS directory"));
-
-  // --coff-resources
-  cl::opt<bool> COFFResources("coff-resources",
-                              cl::desc("Display the PE/COFF .rsrc section"));
-
-  // --coff-load-config
-  cl::opt<bool>
-  COFFLoadConfig("coff-load-config",
-                 cl::desc("Display the PE/COFF load config"));
-
-  // --elf-linker-options
-  cl::opt<bool>
-  ELFLinkerOptions("elf-linker-options",
-                   cl::desc("Display the ELF .linker-options section"));
-
-  // --macho-data-in-code
-  cl::opt<bool>
-  MachODataInCode("macho-data-in-code",
-                  cl::desc("Display MachO Data in Code command"));
-
-  // --macho-indirect-symbols
-  cl::opt<bool>
-  MachOIndirectSymbols("macho-indirect-symbols",
-                  cl::desc("Display MachO indirect symbols"));
-
-  // --macho-linker-options
-  cl::opt<bool>
-  MachOLinkerOptions("macho-linker-options",
-                  cl::desc("Display MachO linker options"));
-
-  // --macho-segment
-  cl::opt<bool>
-  MachOSegment("macho-segment",
-                  cl::desc("Display MachO Segment command"));
-
-  // --macho-version-min
-  cl::opt<bool>
-  MachOVersionMin("macho-version-min",
-                  cl::desc("Display MachO version min command"));
-
-  // --macho-dysymtab
-  cl::opt<bool>
-  MachODysymtab("macho-dysymtab",
-                  cl::desc("Display MachO Dysymtab command"));
-
-  // --stackmap
-  cl::opt<bool>
-  PrintStackMap("stackmap",
-                cl::desc("Display contents of stackmap section"));
-
-  // --stack-sizes
-  cl::opt<bool>
-      PrintStackSizes("stack-sizes",
-                      cl::desc("Display contents of all stack sizes sections"));
-
-  // --version-info, -V
-  cl::opt<bool>
-      VersionInfo("version-info",
-                  cl::desc("Display ELF version sections (if present)"));
-  cl::alias VersionInfoShort("V", cl::desc("Alias for -version-info"),
-                             cl::aliasopt(VersionInfo));
-
-  // --elf-section-groups, --section-groups, -g
-  cl::opt<bool> SectionGroups("elf-section-groups",
-                              cl::desc("Display ELF section group contents"));
-  cl::alias SectionGroupsAlias("section-groups",
-                               cl::desc("Alias for -elf-sections-groups"),
-                               cl::aliasopt(SectionGroups));
-  cl::alias SectionGroupsShort("g", cl::desc("Alias for -elf-sections-groups"),
-                               cl::aliasopt(SectionGroups));
-
-  // --elf-hash-histogram, --histogram, -I
-  cl::opt<bool> HashHistogram(
-      "elf-hash-histogram",
-      cl::desc("Display bucket list histogram for hash sections"));
-  cl::alias HashHistogramShort("I", cl::desc("Alias for -elf-hash-histogram"),
-                               cl::aliasopt(HashHistogram));
-  cl::alias HistogramAlias("histogram",
-                           cl::desc("Alias for --elf-hash-histogram"),
-                           cl::aliasopt(HashHistogram));
-
-  // --cg-profile
-  cl::opt<bool> CGProfile("cg-profile",
-                          cl::desc("Display callgraph profile section"));
-  cl::alias ELFCGProfile("elf-cg-profile", cl::desc("Alias for --cg-profile"),
-                         cl::aliasopt(CGProfile));
-
-  // -addrsig
-  cl::opt<bool> Addrsig("addrsig",
-                        cl::desc("Display address-significance table"));
-
-  // -elf-output-style
-  cl::opt<OutputStyleTy>
-      Output("elf-output-style", cl::desc("Specify ELF dump style"),
-             cl::values(clEnumVal(LLVM, "LLVM default style"),
-                        clEnumVal(GNU, "GNU readelf style")),
-             cl::init(LLVM));
-
-  cl::extrahelp
-      HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
+OutputStyleTy Output = OutputStyleTy::LLVM;
+static std::vector<std::string> InputFilenames;
 } // namespace opts
 
 static StringRef ToolName;
@@ -419,6 +190,87 @@
 
 } // namespace llvm
 
+static void parseOptions(const opt::InputArgList &Args) {
+  opts::Addrsig = Args.hasArg(OPT_addrsig);
+  opts::All = Args.hasArg(OPT_all);
+  opts::ArchSpecificInfo = Args.hasArg(OPT_arch_specific);
+  opts::BBAddrMap = Args.hasArg(OPT_bb_addr_map);
+  opts::CGProfile = Args.hasArg(OPT_cg_profile);
+  opts::Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false);
+  opts::DependentLibraries = Args.hasArg(OPT_dependent_libraries);
+  opts::DynRelocs = Args.hasArg(OPT_dyn_relocations);
+  opts::DynamicSymbols = Args.hasArg(OPT_dyn_syms);
+  opts::ExpandRelocs = Args.hasArg(OPT_expand_relocs);
+  opts::FileHeaders = Args.hasArg(OPT_file_header);
+  opts::Headers = Args.hasArg(OPT_headers);
+  opts::HexDump = Args.getAllArgValues(OPT_hex_dump_EQ);
+  opts::Relocations = Args.hasArg(OPT_relocs);
+  opts::SectionData = Args.hasArg(OPT_section_data);
+  opts::SectionDetails = Args.hasArg(OPT_section_details);
+  opts::SectionHeaders = Args.hasArg(OPT_section_headers);
+  opts::SectionRelocations = Args.hasArg(OPT_section_relocations);
+  opts::SectionSymbols = Args.hasArg(OPT_section_symbols);
+  if (Args.hasArg(OPT_section_mapping))
+    opts::SectionMapping = cl::BOU_TRUE;
+  else if (Args.hasArg(OPT_section_mapping_EQ_false))
+    opts::SectionMapping = cl::BOU_FALSE;
+  else
+    opts::SectionMapping = cl::BOU_UNSET;
+  opts::PrintStackSizes = Args.hasArg(OPT_stack_sizes);
+  opts::PrintStackMap = Args.hasArg(OPT_stackmap);
+  opts::StringDump = Args.getAllArgValues(OPT_string_dump_EQ);
+  opts::StringTable = Args.hasArg(OPT_string_table);
+  opts::Symbols = Args.hasArg(OPT_symbols);
+  opts::UnwindInfo = Args.hasArg(OPT_unwind);
+
+  // ELF specific options.
+  opts::DynamicTable = Args.hasArg(OPT_dynamic_table);
+  opts::ELFLinkerOptions = Args.hasArg(OPT_elf_linker_options);
+  if (Arg *A = Args.getLastArg(OPT_elf_output_style_EQ)) {
+    StringRef V(A->getValue());
+    if (V == "LLVM")
+      opts::Output = opts::OutputStyleTy::LLVM;
+    else if (V == "GNU")
+      opts::Output = opts::OutputStyleTy::GNU;
+    else
+      error("--elf-output-style value should be either 'LLVM' or 'GNU'");
+  }
+  opts::GnuHashTable = Args.hasArg(OPT_gnu_hash_table);
+  opts::HashSymbols = Args.hasArg(OPT_hash_symbols);
+  opts::HashTable = Args.hasArg(OPT_hash_table);
+  opts::HashHistogram = Args.hasArg(OPT_histogram);
+  opts::NeededLibraries = Args.hasArg(OPT_needed_libs);
+  opts::Notes = Args.hasArg(OPT_notes);
+  opts::ProgramHeaders = Args.hasArg(OPT_program_headers);
+  opts::RawRelr = Args.hasArg(OPT_raw_relr);
+  opts::SectionGroups = Args.hasArg(OPT_section_groups);
+  opts::VersionInfo = Args.hasArg(OPT_version_info);
+
+  // Mach-O specific options.
+  opts::MachODataInCode = Args.hasArg(OPT_macho_data_in_code);
+  opts::MachODysymtab = Args.hasArg(OPT_macho_dysymtab);
+  opts::MachOIndirectSymbols = Args.hasArg(OPT_macho_indirect_symbols);
+  opts::MachOLinkerOptions = Args.hasArg(OPT_macho_linker_options);
+  opts::MachOSegment = Args.hasArg(OPT_macho_segment);
+  opts::MachOVersionMin = Args.hasArg(OPT_macho_version_min);
+
+  // PE/COFF specific options.
+  opts::CodeView = Args.hasArg(OPT_codeview);
+  opts::CodeViewEnableGHash = Args.hasArg(OPT_codeview_ghash);
+  opts::CodeViewMergedTypes = Args.hasArg(OPT_codeview_merged_types);
+  opts::CodeViewSubsectionBytes = Args.hasArg(OPT_codeview_subsection_bytes);
+  opts::COFFBaseRelocs = Args.hasArg(OPT_coff_basereloc);
+  opts::COFFDebugDirectory = Args.hasArg(OPT_coff_debug_directory);
+  opts::COFFDirectives = Args.hasArg(OPT_coff_directives);
+  opts::COFFExports = Args.hasArg(OPT_coff_exports);
+  opts::COFFImports = Args.hasArg(OPT_coff_imports);
+  opts::COFFLoadConfig = Args.hasArg(OPT_coff_load_config);
+  opts::COFFResources = Args.hasArg(OPT_coff_resources);
+  opts::COFFTLSDirectory = Args.hasArg(OPT_coff_tls_directory);
+
+  opts::InputFilenames = Args.getAllArgValues(OPT_INPUT);
+}
+
 namespace {
 struct ReadObjTypeTableBuilder {
   ReadObjTypeTableBuilder()
@@ -529,6 +381,8 @@
     Dumper->printGnuHashTable();
   if (opts::VersionInfo)
     Dumper->printVersionInfo();
+  if (opts::StringTable)
+    Dumper->printStringTable();
   if (Obj.isELF()) {
     if (opts::DependentLibraries)
       Dumper->printDependentLibs();
@@ -542,6 +396,8 @@
       Dumper->printHashHistograms();
     if (opts::CGProfile)
       Dumper->printCGProfile();
+    if (opts::BBAddrMap)
+      Dumper->printBBAddrMaps();
     if (opts::Addrsig)
       Dumper->printAddrsig();
     if (opts::Notes)
@@ -646,93 +502,73 @@
 
 /// Opens \a File and dumps it.
 static void dumpInput(StringRef File, ScopedPrinter &Writer) {
-  // Attempt to open the binary.
-  Expected<OwningBinary<Binary>> BinaryOrErr =
-      createBinary(File, /*Context=*/nullptr, /*InitContent=*/false);
+  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
+      MemoryBuffer::getFileOrSTDIN(File, /*IsText=*/false,
+                                   /*RequiresNullTerminator=*/false);
+  if (std::error_code EC = FileOrErr.getError())
+    return reportError(errorCodeToError(EC), File);
+
+  std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
+  file_magic Type = identify_magic(Buffer->getBuffer());
+  if (Type == file_magic::bitcode) {
+    reportWarning(createStringError(errc::invalid_argument,
+                                    "bitcode files are not supported"),
+                  File);
+    return;
+  }
+
+  Expected<std::unique_ptr<Binary>> BinaryOrErr = createBinary(
+      Buffer->getMemBufferRef(), /*Context=*/nullptr, /*InitContent=*/false);
   if (!BinaryOrErr)
     reportError(BinaryOrErr.takeError(), File);
-  Binary &Binary = *BinaryOrErr.get().getBinary();
 
-  if (Archive *Arc = dyn_cast<Archive>(&Binary))
+  std::unique_ptr<Binary> Bin = std::move(*BinaryOrErr);
+  if (Archive *Arc = dyn_cast<Archive>(Bin.get()))
     dumpArchive(Arc, Writer);
   else if (MachOUniversalBinary *UBinary =
-               dyn_cast<MachOUniversalBinary>(&Binary))
+               dyn_cast<MachOUniversalBinary>(Bin.get()))
     dumpMachOUniversalBinary(UBinary, Writer);
-  else if (ObjectFile *Obj = dyn_cast<ObjectFile>(&Binary))
+  else if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin.get()))
     dumpObject(*Obj, Writer);
-  else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(&Binary))
+  else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(Bin.get()))
     dumpCOFFImportFile(Import, Writer);
-  else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(&Binary))
+  else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(Bin.get()))
     dumpWindowsResourceFile(WinRes, Writer);
   else
     llvm_unreachable("unrecognized file type");
 
-  CVTypes.Binaries.push_back(std::move(*BinaryOrErr));
+  CVTypes.Binaries.push_back(
+      OwningBinary<Binary>(std::move(Bin), std::move(Buffer)));
 }
 
-/// Registers aliases that should only be allowed by readobj.
-static void registerReadobjAliases() {
-  // -s has meant --sections for a very long time in llvm-readobj despite
-  // meaning --symbols in readelf.
-  static cl::alias SectionsShort("s", cl::desc("Alias for --section-headers"),
-                                 cl::aliasopt(opts::SectionHeaders),
-                                 cl::NotHidden);
-
-  // llvm-readelf reserves it for --section-details.
-  static cl::alias SymbolsShort("t", cl::desc("Alias for --symbols"),
-                                cl::aliasopt(opts::Symbols), cl::NotHidden);
-
-  // The following two-letter aliases are only provided for readobj, as readelf
-  // allows single-letter args to be grouped together.
-  static cl::alias SectionRelocationsShort(
-      "sr", cl::desc("Alias for --section-relocations"),
-      cl::aliasopt(opts::SectionRelocations));
-  static cl::alias SectionDataShort("sd", cl::desc("Alias for --section-data"),
-                                    cl::aliasopt(opts::SectionData));
-  static cl::alias SectionSymbolsShort("st",
-                                       cl::desc("Alias for --section-symbols"),
-                                       cl::aliasopt(opts::SectionSymbols));
-  static cl::alias DynamicSymbolsShort("dt",
-                                       cl::desc("Alias for --dyn-symbols"),
-                                       cl::aliasopt(opts::DynamicSymbols));
-}
-
-/// Registers aliases that should only be allowed by readelf.
-static void registerReadelfAliases() {
-  // -s is here because for readobj it means --sections.
-  static cl::alias SymbolsShort("s", cl::desc("Alias for --symbols"),
-                                cl::aliasopt(opts::Symbols), cl::NotHidden,
-                                cl::Grouping);
-
-  // -t is here because for readobj it is an alias for --symbols.
-  static cl::alias SectionDetailsShort(
-      "t", cl::desc("Alias for --section-details"),
-      cl::aliasopt(opts::SectionDetails), cl::NotHidden);
-
-  // Allow all single letter flags to be grouped together.
-  for (auto &OptEntry : cl::getRegisteredOptions()) {
-    StringRef ArgName = OptEntry.getKey();
-    cl::Option *Option = OptEntry.getValue();
-    if (ArgName.size() == 1)
-      apply(Option, cl::Grouping);
-  }
-}
-
-int main(int argc, const char *argv[]) {
+int main(int argc, char *argv[]) {
   InitLLVM X(argc, argv);
+  BumpPtrAllocator A;
+  StringSaver Saver(A);
+  ReadobjOptTable Tbl;
   ToolName = argv[0];
-
-  // Register the target printer for --version.
-  cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
-
-  if (sys::path::stem(argv[0]).contains("readelf")) {
-    opts::Output = opts::GNU;
-    registerReadelfAliases();
-  } else {
-    registerReadobjAliases();
+  opt::InputArgList Args =
+      Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
+        error(Msg);
+        exit(1);
+      });
+  if (Args.hasArg(OPT_help)) {
+    Tbl.printHelp(
+        outs(),
+        (Twine(ToolName) + " [options] <input object files>").str().c_str(),
+        "LLVM Object Reader");
+    // TODO Replace this with OptTable API once it adds extrahelp support.
+    outs() << "\nPass @FILE as argument to read options from FILE.\n";
+    return 0;
+  }
+  if (Args.hasArg(OPT_version)) {
+    cl::PrintVersionMessage();
+    return 0;
   }
 
-  cl::ParseCommandLineOptions(argc, argv, "LLVM Object Reader\n");
+  if (sys::path::stem(argv[0]).contains("readelf"))
+    opts::Output = opts::GNU;
+  parseOptions(Args);
 
   // Default to print error if no filename is specified.
   if (opts::InputFilenames.empty()) {
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.h b/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.h
index d9813f5..43d19b4 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.h
+++ b/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.h
@@ -32,15 +32,15 @@
 } // namespace llvm
 
 namespace opts {
-  extern llvm::cl::opt<bool> SectionRelocations;
-  extern llvm::cl::opt<bool> SectionSymbols;
-  extern llvm::cl::opt<bool> SectionData;
-  extern llvm::cl::opt<bool> ExpandRelocs;
-  extern llvm::cl::opt<bool> RawRelr;
-  extern llvm::cl::opt<bool> CodeViewSubsectionBytes;
-  extern llvm::cl::opt<bool> Demangle;
-  enum OutputStyleTy { LLVM, GNU };
-  extern llvm::cl::opt<OutputStyleTy> Output;
+extern bool SectionRelocations;
+extern bool SectionSymbols;
+extern bool SectionData;
+extern bool ExpandRelocs;
+extern bool RawRelr;
+extern bool CodeViewSubsectionBytes;
+extern bool Demangle;
+enum OutputStyleTy { LLVM, GNU };
+extern OutputStyleTy Output;
 } // namespace opts
 
 #define LLVM_READOBJ_ENUM_ENT(ns, enum) \
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-reduce/CMakeLists.txt
index b6db920..44818ed 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-reduce/CMakeLists.txt
@@ -11,6 +11,7 @@
   )
 
 add_llvm_tool(llvm-reduce
+  DeltaManager.cpp
   TestRunner.cpp
   deltas/Delta.cpp
   deltas/ReduceAliases.cpp
@@ -19,10 +20,12 @@
   deltas/ReduceBasicBlocks.cpp
   deltas/ReduceFunctionBodies.cpp
   deltas/ReduceFunctions.cpp
+  deltas/ReduceGlobalValues.cpp
   deltas/ReduceGlobalVarInitializers.cpp
   deltas/ReduceGlobalVars.cpp
   deltas/ReduceInstructions.cpp
   deltas/ReduceMetadata.cpp
+  deltas/ReduceModuleInlineAsm.cpp
   deltas/ReduceOperandBundles.cpp
   deltas/ReduceSpecialGlobals.cpp
   llvm-reduce.cpp
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.cpp b/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.cpp
new file mode 100644
index 0000000..19e9913
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.cpp
@@ -0,0 +1,92 @@
+//===- DeltaManager.cpp - Runs Delta Passes to reduce Input ---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file calls each specialized Delta pass in order to reduce the input IR
+// file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DeltaManager.h"
+#include "TestRunner.h"
+#include "deltas/Delta.h"
+#include "deltas/ReduceAliases.h"
+#include "deltas/ReduceArguments.h"
+#include "deltas/ReduceAttributes.h"
+#include "deltas/ReduceBasicBlocks.h"
+#include "deltas/ReduceFunctionBodies.h"
+#include "deltas/ReduceFunctions.h"
+#include "deltas/ReduceGlobalValues.h"
+#include "deltas/ReduceGlobalVarInitializers.h"
+#include "deltas/ReduceGlobalVars.h"
+#include "deltas/ReduceInstructions.h"
+#include "deltas/ReduceMetadata.h"
+#include "deltas/ReduceModuleInlineAsm.h"
+#include "deltas/ReduceOperandBundles.h"
+#include "deltas/ReduceSpecialGlobals.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+
+static cl::opt<std::string>
+    DeltaPasses("delta-passes",
+                cl::desc("Delta passes to run, separated by commas. By "
+                         "default, run all delta passes."));
+
+#define DELTA_PASSES                                                           \
+  DELTA_PASS("special-globals", reduceSpecialGlobalsDeltaPass)                 \
+  DELTA_PASS("aliases", reduceAliasesDeltaPass)                                \
+  DELTA_PASS("function-bodies", reduceFunctionBodiesDeltaPass)                 \
+  DELTA_PASS("functions", reduceFunctionsDeltaPass)                            \
+  DELTA_PASS("basic-blocks", reduceBasicBlocksDeltaPass)                       \
+  DELTA_PASS("global-values", reduceGlobalValuesDeltaPass)                     \
+  DELTA_PASS("global-initializers", reduceGlobalsInitializersDeltaPass)        \
+  DELTA_PASS("global-variables", reduceGlobalsDeltaPass)                       \
+  DELTA_PASS("metadata", reduceMetadataDeltaPass)                              \
+  DELTA_PASS("arguments", reduceArgumentsDeltaPass)                            \
+  DELTA_PASS("instructions", reduceInstructionsDeltaPass)                      \
+  DELTA_PASS("operand-bundles", reduceOperandBundesDeltaPass)                  \
+  DELTA_PASS("attributes", reduceAttributesDeltaPass)                          \
+  DELTA_PASS("module-inline-asm", reduceModuleInlineAsmDeltaPass)
+
+static void runAllDeltaPasses(TestRunner &Tester) {
+#define DELTA_PASS(NAME, FUNC) FUNC(Tester);
+  DELTA_PASSES
+#undef DELTA_PASS
+}
+
+static void runDeltaPassName(TestRunner &Tester, StringRef PassName) {
+#define DELTA_PASS(NAME, FUNC)                                                 \
+  if (PassName == NAME) {                                                      \
+    FUNC(Tester);                                                              \
+    return;                                                                    \
+  }
+  DELTA_PASSES
+#undef DELTA_PASS
+  errs() << "unknown pass \"" << PassName << "\"";
+  exit(1);
+}
+
+void llvm::printDeltaPasses(raw_ostream &OS) {
+  OS << "Delta passes (pass to `--delta-passes=` as a comma separated list):\n";
+#define DELTA_PASS(NAME, FUNC) OS << "  " << NAME << "\n";
+  DELTA_PASSES
+#undef DELTA_PASS
+}
+
+void llvm::runDeltaPasses(TestRunner &Tester) {
+  if (DeltaPasses.empty()) {
+    runAllDeltaPasses(Tester);
+  } else {
+    StringRef Passes = DeltaPasses;
+    while (!Passes.empty()) {
+      auto Split = Passes.split(",");
+      runDeltaPassName(Tester, Split.first);
+      Passes = Split.second;
+    }
+  }
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.h b/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.h
index 18a6b0d..8fb69be 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.h
@@ -11,38 +11,15 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "TestRunner.h"
-#include "deltas/Delta.h"
-#include "deltas/ReduceAliases.h"
-#include "deltas/ReduceArguments.h"
-#include "deltas/ReduceAttributes.h"
-#include "deltas/ReduceBasicBlocks.h"
-#include "deltas/ReduceFunctionBodies.h"
-#include "deltas/ReduceFunctions.h"
-#include "deltas/ReduceGlobalVarInitializers.h"
-#include "deltas/ReduceGlobalVars.h"
-#include "deltas/ReduceInstructions.h"
-#include "deltas/ReduceMetadata.h"
-#include "deltas/ReduceOperandBundles.h"
-#include "deltas/ReduceSpecialGlobals.h"
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAMANAGER_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAMANAGER_H
 
 namespace llvm {
+class raw_ostream;
+class TestRunner;
 
-// TODO: Add CLI option to run only specified Passes (for unit tests)
-inline void runDeltaPasses(TestRunner &Tester) {
-  reduceSpecialGlobalsDeltaPass(Tester);
-  reduceAliasesDeltaPass(Tester);
-  reduceFunctionBodiesDeltaPass(Tester);
-  reduceFunctionsDeltaPass(Tester);
-  reduceBasicBlocksDeltaPass(Tester);
-  reduceGlobalsInitializersDeltaPass(Tester);
-  reduceGlobalsDeltaPass(Tester);
-  reduceMetadataDeltaPass(Tester);
-  reduceArgumentsDeltaPass(Tester);
-  reduceInstructionsDeltaPass(Tester);
-  reduceOperandBundesDeltaPass(Tester);
-  reduceAttributesDeltaPass(Tester);
-  // TODO: Implement the remaining Delta Passes
-}
-
+void printDeltaPasses(raw_ostream &OS);
+void runDeltaPasses(TestRunner &Tester);
 } // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.h b/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.h
index 2270d6b..b7fb44e 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.h
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_LLVMREDUCE_TESTRUNNER_H
-#define LLVM_TOOLS_LLVMREDUCE_TESTRUNNER_H
+#ifndef LLVM_TOOLS_LLVM_REDUCE_TESTRUNNER_H
+#define LLVM_TOOLS_LLVM_REDUCE_TESTRUNNER_H
 
 #include "llvm/ADT/SmallString.h"
 #include "llvm/IR/Module.h"
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.cpp
index 9b0969e..1059764 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.cpp
@@ -15,6 +15,7 @@
 #include "Delta.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/IR/Verifier.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ToolOutputFile.h"
 #include "llvm/Transforms/Utils/Cloning.h"
 #include <fstream>
@@ -22,9 +23,13 @@
 
 using namespace llvm;
 
+static cl::opt<bool> AbortOnInvalidReduction(
+    "abort-on-invalid-reduction",
+    cl::desc("Abort if any reduction results in invalid IR"));
+
 void writeOutput(llvm::Module *M, llvm::StringRef Message);
 
-bool IsReduced(Module &M, TestRunner &Test, SmallString<128> &CurrentFilepath) {
+bool isReduced(Module &M, TestRunner &Test, SmallString<128> &CurrentFilepath) {
   // Write Module to tmp file
   int FD;
   std::error_code EC =
@@ -66,12 +71,12 @@
   bool SplitOne = false;
 
   for (auto &C : Chunks) {
-    if (C.end - C.begin == 0)
+    if (C.End - C.Begin == 0)
       NewChunks.push_back(C);
     else {
-      int Half = (C.begin + C.end) / 2;
-      NewChunks.push_back({C.begin, Half});
-      NewChunks.push_back({Half + 1, C.end});
+      int Half = (C.Begin + C.End) / 2;
+      NewChunks.push_back({C.Begin, Half});
+      NewChunks.push_back({Half + 1, C.End});
       SplitOne = true;
     }
   }
@@ -102,7 +107,7 @@
 
   if (Module *Program = Test.getProgram()) {
     SmallString<128> CurrentFilepath;
-    if (!IsReduced(*Program, Test, CurrentFilepath)) {
+    if (!isReduced(*Program, Test, CurrentFilepath)) {
       errs() << "\nInput isn't interesting! Verify interesting-ness test\n";
       exit(1);
     }
@@ -141,6 +146,10 @@
 
       // Some reductions may result in invalid IR. Skip such reductions.
       if (verifyModule(*Clone.get(), &errs())) {
+        if (AbortOnInvalidReduction) {
+          errs() << "Invalid reduction\n";
+          exit(1);
+        }
         errs() << " **** WARNING | reduction resulted in invalid module, "
                   "skipping\n";
         continue;
@@ -152,7 +161,7 @@
         C.print();
 
       SmallString<128> CurrentFilepath;
-      if (!IsReduced(*Clone, Test, CurrentFilepath)) {
+      if (!isReduced(*Clone, Test, CurrentFilepath)) {
         // Program became non-reduced, so this chunk appears to be interesting.
         errs() << "\n";
         continue;
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.h
index 7da3c79..69bd4d2 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.h
@@ -12,8 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_LLVMREDUCE_LLVMREDUCE_DELTA_H
-#define LLVM_TOOLS_LLVMREDUCE_LLVMREDUCE_DELTA_H
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_DELTA_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_DELTA_H
 
 #include "TestRunner.h"
 #include "llvm/ADT/ScopeExit.h"
@@ -24,27 +24,27 @@
 namespace llvm {
 
 struct Chunk {
-  int begin;
-  int end;
+  int Begin;
+  int End;
 
   /// Helper function to verify if a given Target-index is inside the Chunk
-  bool contains(int Index) const { return Index >= begin && Index <= end; }
+  bool contains(int Index) const { return Index >= Begin && Index <= End; }
 
   void print() const {
-    errs() << "[" << begin;
-    if (end - begin != 0)
-      errs() << "," << end;
+    errs() << "[" << Begin;
+    if (End - Begin != 0)
+      errs() << "," << End;
     errs() << "]";
   }
 
   /// Operator when populating CurrentChunks in Generic Delta Pass
   friend bool operator!=(const Chunk &C1, const Chunk &C2) {
-    return C1.begin != C2.begin || C1.end != C2.end;
+    return C1.Begin != C2.Begin || C1.End != C2.End;
   }
 
   /// Operator used for sets
   friend bool operator<(const Chunk &C1, const Chunk &C2) {
-    return std::tie(C1.begin, C1.end) < std::tie(C2.begin, C2.end);
+    return std::tie(C1.Begin, C1.End) < std::tie(C2.Begin, C2.End);
   }
 };
 
@@ -60,8 +60,7 @@
   ArrayRef<Chunk> ChunksToKeep;
 
 public:
-  explicit Oracle(ArrayRef<Chunk> ChunksToKeep_)
-      : ChunksToKeep(ChunksToKeep_) {}
+  explicit Oracle(ArrayRef<Chunk> ChunksToKeep) : ChunksToKeep(ChunksToKeep) {}
 
   /// Should be called for each feature on which we are operating.
   /// Name is self-explanatory - if returns true, then it should be preserved.
@@ -74,7 +73,7 @@
     auto _ = make_scope_exit([&]() { ++Index; }); // Next time - next feature.
 
     // Is this the last feature in the chunk?
-    if (ChunksToKeep.front().end == Index)
+    if (ChunksToKeep.front().End == Index)
       ChunksToKeep = ChunksToKeep.drop_front(); // Onto next chunk.
 
     return ShouldKeep;
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAliases.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAliases.h
index 0c2886e..0660efe 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAliases.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAliases.h
@@ -11,8 +11,13 @@
 //
 //===----------------------------------------------------------------------===//
 
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEALIASES_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEALIASES_H
+
 #include "Delta.h"
 
 namespace llvm {
 void reduceAliasesDeltaPass(TestRunner &Test);
 } // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp
index c3c7dee..a88bba4 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp
@@ -7,13 +7,14 @@
 //===----------------------------------------------------------------------===//
 //
 // This file implements a function which calls the Generic Delta pass in order
-// to reduce uninteresting Arguments from defined functions.
+// to reduce uninteresting Arguments from declared and defined functions.
 //
 //===----------------------------------------------------------------------===//
 
 #include "ReduceArguments.h"
 #include "Delta.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Intrinsics.h"
 #include <set>
 #include <vector>
 
@@ -38,6 +39,14 @@
     }
 }
 
+/// Returns whether or not this function should be considered a candidate for
+/// argument removal. Currently, functions with no arguments and intrinsics are
+/// not considered. Intrinsics aren't considered because their signatures are
+/// fixed.
+static bool shouldRemoveArguments(const Function &F) {
+  return !F.arg_empty() && !F.isIntrinsic();
+}
+
 /// Removes out-of-chunk arguments from functions, and modifies their calls
 /// accordingly. It also removes allocations of out-of-chunk arguments.
 static void extractArgumentsFromModule(std::vector<Chunk> ChunksToKeep,
@@ -48,7 +57,7 @@
   std::vector<Function *> Funcs;
   // Get inside-chunk arguments, as well as their parent function
   for (auto &F : *Program)
-    if (!F.arg_empty()) {
+    if (shouldRemoveArguments(F)) {
       Funcs.push_back(&F);
       for (auto &A : F.args())
         if (O.shouldKeep())
@@ -100,15 +109,15 @@
   }
 }
 
-/// Counts the amount of arguments in non-declaration functions and prints their
-/// respective name, index, and parent function name
+/// Counts the amount of arguments in functions and prints their respective
+/// name, index, and parent function name
 static int countArguments(Module *Program) {
   // TODO: Silence index with --quiet flag
   outs() << "----------------------------\n";
   outs() << "Param Index Reference:\n";
   int ArgsCount = 0;
   for (auto &F : *Program)
-    if (!F.arg_empty()) {
+    if (shouldRemoveArguments(F)) {
       outs() << "  " << F.getName() << "\n";
       for (auto &A : F.args())
         outs() << "\t" << ++ArgsCount << ": " << A.getName() << "\n";
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.h
index d9682b4..228409d 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.h
@@ -11,6 +11,9 @@
 //
 //===----------------------------------------------------------------------===//
 
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEARGUMENTS_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEARGUMENTS_H
+
 #include "Delta.h"
 #include "llvm/IR/Argument.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
@@ -19,3 +22,5 @@
 namespace llvm {
 void reduceArgumentsDeltaPass(TestRunner &Test);
 } // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp
index cbaf5d5..223866b 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp
@@ -1,4 +1,4 @@
-//===- ReduceAttributes.cpp - Specialized Delta Pass -------------------===//
+//===- ReduceAttributes.cpp - Specialized Delta Pass ----------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -84,7 +84,8 @@
                           AttrPtrVecVecTy &AttributeSetsToPreserve) {
     assert(AttributeSetsToPreserve.empty() && "Should not be sharing vectors.");
     AttributeSetsToPreserve.reserve(AL.getNumAttrSets());
-    for (unsigned SetIdx : seq(AL.index_begin(), AL.index_end())) {
+    for (unsigned SetIdx = AL.index_begin(), SetEndIdx = AL.index_end();
+         SetIdx != SetEndIdx; ++SetIdx) {
       AttrPtrIdxVecVecTy AttributesToPreserve;
       AttributesToPreserve.first = SetIdx;
       visitAttributeSet(AL.getAttributes(AttributesToPreserve.first),
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.h
index f8deb04..375e764 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.h
@@ -11,10 +11,12 @@
 //
 //===----------------------------------------------------------------------===//
 
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEATTRIBUTES_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEATTRIBUTES_H
+
 namespace llvm {
-
 class TestRunner;
-
 void reduceAttributesDeltaPass(TestRunner &Test);
-
 } // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp
index 8c0832d..5a1905d 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp
@@ -26,9 +26,9 @@
 /// Replaces BB Terminator with one that only contains Chunk BBs
 static void replaceBranchTerminator(BasicBlock &BB,
                                     std::set<BasicBlock *> BBsToKeep) {
-  auto Term = BB.getTerminator();
+  auto *Term = BB.getTerminator();
   std::vector<BasicBlock *> ChunkSucessors;
-  for (auto Succ : successors(&BB))
+  for (auto *Succ : successors(&BB))
     if (BBsToKeep.count(Succ))
       ChunkSucessors.push_back(Succ);
 
@@ -38,7 +38,7 @@
 
   bool IsBranch = isa<BranchInst>(Term) || isa<InvokeInst>(Term);
   Value *Address = nullptr;
-  if (auto IndBI = dyn_cast<IndirectBrInst>(Term))
+  if (auto *IndBI = dyn_cast<IndirectBrInst>(Term))
     Address = IndBI->getAddress();
 
   Term->replaceAllUsesWith(UndefValue::get(Term->getType()));
@@ -56,9 +56,9 @@
     BranchInst::Create(ChunkSucessors[0], &BB);
 
   if (Address) {
-    auto NewIndBI =
+    auto *NewIndBI =
         IndirectBrInst::Create(Address, ChunkSucessors.size(), &BB);
-    for (auto Dest : ChunkSucessors)
+    for (auto *Dest : ChunkSucessors)
       NewIndBI->addDestination(Dest);
   }
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.h
index cf76a0a..4938552 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.h
@@ -10,6 +10,8 @@
 // to reduce uninteresting Arguments from defined functions.
 //
 //===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEBASICBLOCKS_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEBASICBLOCKS_H
 
 #include "Delta.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
@@ -18,3 +20,5 @@
 namespace llvm {
 void reduceBasicBlocksDeltaPass(TestRunner &Test);
 } // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.h
index 8c06c2e..bfe701b 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.h
@@ -11,8 +11,13 @@
 //
 //===----------------------------------------------------------------------===//
 
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEFUNCTIONBODIES_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEFUNCTIONBODIES_H
+
 #include "Delta.h"
 
 namespace llvm {
 void reduceFunctionBodiesDeltaPass(TestRunner &Test);
 } // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.h
index 7c2cd3f..f5bc83b 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.h
@@ -11,6 +11,8 @@
 // Module.
 //
 //===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEFUNCTIONS_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEFUNCTIONS_H
 
 #include "Delta.h"
 #include "llvm/Transforms/Utils/Cloning.h"
@@ -18,3 +20,5 @@
 namespace llvm {
 void reduceFunctionsDeltaPass(TestRunner &Test);
 } // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.cpp
new file mode 100644
index 0000000..4d918aa
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.cpp
@@ -0,0 +1,54 @@
+//===- ReduceGlobalValues.cpp - Specialized Delta Pass --------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a function which calls the Generic Delta pass to reduce
+// global value attributes/specifiers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReduceGlobalValues.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/GlobalValue.h"
+
+using namespace llvm;
+
+static bool isValidDSOLocalReductionGV(GlobalValue &GV) {
+  return GV.isDSOLocal() && !GV.isImplicitDSOLocal();
+}
+
+/// Sets dso_local to false for all global values.
+static void extractGVsFromModule(std::vector<Chunk> ChunksToKeep,
+                                 Module *Program) {
+  Oracle O(ChunksToKeep);
+
+  // remove dso_local from global values
+  for (auto &GV : Program->global_values())
+    if (isValidDSOLocalReductionGV(GV) && !O.shouldKeep()) {
+      GV.setDSOLocal(false);
+    }
+}
+
+/// Counts the amount of global values with dso_local and displays their
+/// respective name & index
+static int countGVs(Module *Program) {
+  // TODO: Silence index with --quiet flag
+  outs() << "----------------------------\n";
+  outs() << "GlobalValue Index Reference:\n";
+  int GVCount = 0;
+  for (auto &GV : Program->global_values())
+    if (isValidDSOLocalReductionGV(GV))
+      outs() << "\t" << ++GVCount << ": " << GV.getName() << "\n";
+  outs() << "----------------------------\n";
+  return GVCount;
+}
+
+void llvm::reduceGlobalValuesDeltaPass(TestRunner &Test) {
+  outs() << "*** Reducing GlobalValues...\n";
+  int GVCount = countGVs(Test.getProgram());
+  runDeltaPass(Test, GVCount, extractGVsFromModule);
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.h
new file mode 100644
index 0000000..ea32a6c
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.h
@@ -0,0 +1,23 @@
+//===- ReduceGlobalValues.h - Specialized Delta Pass ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a function which calls the Generic Delta pass to reduce
+// global value attributes/specifiers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEGLOBALVALUES_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEGLOBALVALUES_H
+
+#include "Delta.h"
+
+namespace llvm {
+void reduceGlobalValuesDeltaPass(TestRunner &Test);
+} // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.h
index 39288ad..0f5f22a 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.h
@@ -1,5 +1,4 @@
-//===- reduceGlobalsInitializersDeltaPass.h - Specialized Delta Pass
-//-------===//
+//===- reduceGlobalsInitializersDeltaPass.h - Specialized Delta Pass ------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -12,6 +11,9 @@
 //
 //===----------------------------------------------------------------------===//
 
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEGLOBALVARINITIALIZERS_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEGLOBALVARINITIALIZERS_H
+
 #include "Delta.h"
 #include "llvm/IR/Value.h"
 #include "llvm/Transforms/Utils/Cloning.h"
@@ -19,3 +21,5 @@
 namespace llvm {
 void reduceGlobalsInitializersDeltaPass(TestRunner &Test);
 } // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.cpp
index 4b184e5..525eff9 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.cpp
@@ -33,7 +33,7 @@
   std::vector<WeakVH> InstToRemove;
   for (auto &GV : Program->globals())
     if (!GVsToKeep.count(&GV)) {
-      for (auto U : GV.users())
+      for (auto *U : GV.users())
         if (auto *Inst = dyn_cast<Instruction>(U))
           InstToRemove.push_back(Inst);
 
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.h
index c8ba7ea..fe7813c 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.h
@@ -11,6 +11,9 @@
 //
 //===----------------------------------------------------------------------===//
 
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEGLOBALVARS_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEGLOBALVARS_H
+
 #include "Delta.h"
 #include "llvm/IR/Value.h"
 #include "llvm/Transforms/Utils/Cloning.h"
@@ -18,3 +21,5 @@
 namespace llvm {
 void reduceGlobalsDeltaPass(TestRunner &Test);
 } // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructions.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructions.h
index a9266ac..be568f1 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructions.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructions.h
@@ -11,6 +11,9 @@
 //
 //===----------------------------------------------------------------------===//
 
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEINSTRUCTIONS_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEINSTRUCTIONS_H
+
 #include "Delta.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/Cloning.h"
@@ -18,3 +21,5 @@
 namespace llvm {
 void reduceInstructionsDeltaPass(TestRunner &Test);
 } // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMetadata.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMetadata.h
index 275b44c..6efc3f5 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMetadata.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMetadata.h
@@ -1,4 +1,4 @@
-//===- ReduceMetadata.h - Specialized Delta Pass ------------------------===//
+//===- ReduceMetadata.h - Specialized Delta Pass --------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -11,8 +11,13 @@
 //
 //===----------------------------------------------------------------------===//
 
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEMETADATA_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEMETADATA_H
+
 #include "TestRunner.h"
 
 namespace llvm {
 void reduceMetadataDeltaPass(TestRunner &Test);
 } // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceModuleInlineAsm.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceModuleInlineAsm.cpp
new file mode 100644
index 0000000..b74bd0a
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceModuleInlineAsm.cpp
@@ -0,0 +1,32 @@
+//===- ReduceModuleInlineAsm.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a function which calls the Generic Delta pass to reduce
+// module inline asm.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReduceModuleInlineAsm.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/GlobalValue.h"
+
+using namespace llvm;
+
+static void clearModuleInlineAsm(std::vector<Chunk> ChunksToKeep,
+                                 Module *Program) {
+  Oracle O(ChunksToKeep);
+
+  // TODO: clear line by line rather than all at once
+  if (!O.shouldKeep())
+    Program->setModuleInlineAsm("");
+}
+
+void llvm::reduceModuleInlineAsmDeltaPass(TestRunner &Test) {
+  outs() << "*** Reducing Module Inline Asm...\n";
+  runDeltaPass(Test, 1, clearModuleInlineAsm);
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceModuleInlineAsm.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceModuleInlineAsm.h
new file mode 100644
index 0000000..6d31c8f
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceModuleInlineAsm.h
@@ -0,0 +1,18 @@
+//===- ReduceModuleInlineAsm.h --------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCE_MODULEINLINEASM_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCE_MODULEINLINEASM_H
+
+#include "Delta.h"
+
+namespace llvm {
+void reduceModuleInlineAsmDeltaPass(TestRunner &Test);
+} // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.h
index 382c5cb..d07e021 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.h
@@ -11,10 +11,12 @@
 //
 //===----------------------------------------------------------------------===//
 
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEOPERANDBUNDLES_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEOPERANDBUNDLES_H
+
 namespace llvm {
-
 class TestRunner;
-
 void reduceOperandBundesDeltaPass(TestRunner &Test);
-
 } // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.h
index 52ecaed..c0f3f9e 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.h
@@ -14,8 +14,13 @@
 //
 //===----------------------------------------------------------------------===//
 
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCESPECIALGLOBALS_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCESPECIALGLOBALS_H
+
 #include "Delta.h"
 
 namespace llvm {
 void reduceSpecialGlobalsDeltaPass(TestRunner &Test);
 } // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/llvm-reduce.cpp b/src/llvm-project/llvm/tools/llvm-reduce/llvm-reduce.cpp
index 376826b..43dd15f 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/llvm-reduce.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/llvm-reduce.cpp
@@ -15,6 +15,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "DeltaManager.h"
+#include "TestRunner.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Verifier.h"
@@ -35,6 +36,11 @@
 static cl::opt<bool> Version("v", cl::desc("Alias for -version"), cl::Hidden,
                              cl::cat(Options));
 
+static cl::opt<bool>
+    PrintDeltaPasses("print-delta-passes",
+                     cl::desc("Print list of delta passes, passable to "
+                              "--delta-passes as a comma separated list"));
+
 static cl::opt<std::string> InputFilename(cl::Positional, cl::Required,
                                           cl::desc("<input llvm ll/bc file>"),
                                           cl::cat(Options));
@@ -96,15 +102,25 @@
   errs() << Message << OutputFilename << "\n";
 }
 
-int main(int argc, char **argv) {
-  InitLLVM X(argc, argv);
+int main(int Argc, char **Argv) {
+  InitLLVM X(Argc, Argv);
 
-  cl::ParseCommandLineOptions(argc, argv, "LLVM automatic testcase reducer.\n");
+  cl::HideUnrelatedOptions({&Options, &getColorCategory()});
+  cl::ParseCommandLineOptions(Argc, Argv, "LLVM automatic testcase reducer.\n");
+
+  if (PrintDeltaPasses) {
+    printDeltaPasses(errs());
+    return 0;
+  }
 
   LLVMContext Context;
   std::unique_ptr<Module> OriginalProgram =
       parseInputFile(InputFilename, Context);
 
+  if (!OriginalProgram) {
+    return 1;
+  }
+
   // Initialize test environment
   TestRunner Tester(TestFilename, TestArguments);
   Tester.setProgram(std::move(OriginalProgram));
diff --git a/src/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp b/src/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
index 9199431..f02d898 100644
--- a/src/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -27,6 +27,7 @@
 #include "llvm/Object/SymbolSize.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/MSVCErrorWorkarounds.h"
 #include "llvm/Support/Memory.h"
@@ -43,9 +44,11 @@
 using namespace llvm;
 using namespace llvm::object;
 
-static cl::list<std::string>
-InputFileList(cl::Positional, cl::ZeroOrMore,
-              cl::desc("<input files>"));
+static cl::OptionCategory RTDyldCategory("RTDyld Options");
+
+static cl::list<std::string> InputFileList(cl::Positional, cl::ZeroOrMore,
+                                           cl::desc("<input files>"),
+                                           cl::cat(RTDyldCategory));
 
 enum ActionType {
   AC_Execute,
@@ -55,94 +58,93 @@
   AC_Verify
 };
 
-static cl::opt<ActionType>
-Action(cl::desc("Action to perform:"),
-       cl::init(AC_Execute),
-       cl::values(clEnumValN(AC_Execute, "execute",
-                             "Load, link, and execute the inputs."),
-                  clEnumValN(AC_PrintLineInfo, "printline",
-                             "Load, link, and print line information for each function."),
-                  clEnumValN(AC_PrintDebugLineInfo, "printdebugline",
-                             "Load, link, and print line information for each function using the debug object"),
-                  clEnumValN(AC_PrintObjectLineInfo, "printobjline",
-                             "Like -printlineinfo but does not load the object first"),
-                  clEnumValN(AC_Verify, "verify",
-                             "Load, link and verify the resulting memory image.")));
+static cl::opt<ActionType> Action(
+    cl::desc("Action to perform:"), cl::init(AC_Execute),
+    cl::values(
+        clEnumValN(AC_Execute, "execute",
+                   "Load, link, and execute the inputs."),
+        clEnumValN(AC_PrintLineInfo, "printline",
+                   "Load, link, and print line information for each function."),
+        clEnumValN(AC_PrintDebugLineInfo, "printdebugline",
+                   "Load, link, and print line information for each function "
+                   "using the debug object"),
+        clEnumValN(AC_PrintObjectLineInfo, "printobjline",
+                   "Like -printlineinfo but does not load the object first"),
+        clEnumValN(AC_Verify, "verify",
+                   "Load, link and verify the resulting memory image.")),
+    cl::cat(RTDyldCategory));
 
 static cl::opt<std::string>
-EntryPoint("entry",
-           cl::desc("Function to call as entry point."),
-           cl::init("_main"));
+    EntryPoint("entry", cl::desc("Function to call as entry point."),
+               cl::init("_main"), cl::cat(RTDyldCategory));
 
-static cl::list<std::string>
-Dylibs("dylib",
-       cl::desc("Add library."),
-       cl::ZeroOrMore);
+static cl::list<std::string> Dylibs("dylib", cl::desc("Add library."),
+                                    cl::ZeroOrMore, cl::cat(RTDyldCategory));
 
 static cl::list<std::string> InputArgv("args", cl::Positional,
                                        cl::desc("<program arguments>..."),
-                                       cl::ZeroOrMore, cl::PositionalEatsArgs);
+                                       cl::ZeroOrMore, cl::PositionalEatsArgs,
+                                       cl::cat(RTDyldCategory));
 
 static cl::opt<std::string>
-TripleName("triple", cl::desc("Target triple for disassembler"));
+    TripleName("triple", cl::desc("Target triple for disassembler"),
+               cl::cat(RTDyldCategory));
 
 static cl::opt<std::string>
-MCPU("mcpu",
-     cl::desc("Target a specific cpu type (-mcpu=help for details)"),
-     cl::value_desc("cpu-name"),
-     cl::init(""));
+    MCPU("mcpu",
+         cl::desc("Target a specific cpu type (-mcpu=help for details)"),
+         cl::value_desc("cpu-name"), cl::init(""), cl::cat(RTDyldCategory));
 
 static cl::list<std::string>
-CheckFiles("check",
-           cl::desc("File containing RuntimeDyld verifier checks."),
-           cl::ZeroOrMore);
+    CheckFiles("check",
+               cl::desc("File containing RuntimeDyld verifier checks."),
+               cl::ZeroOrMore, cl::cat(RTDyldCategory));
 
 static cl::opt<uint64_t>
     PreallocMemory("preallocate",
                    cl::desc("Allocate memory upfront rather than on-demand"),
-                   cl::init(0));
+                   cl::init(0), cl::cat(RTDyldCategory));
 
 static cl::opt<uint64_t> TargetAddrStart(
     "target-addr-start",
     cl::desc("For -verify only: start of phony target address "
              "range."),
     cl::init(4096), // Start at "page 1" - no allocating at "null".
-    cl::Hidden);
+    cl::Hidden, cl::cat(RTDyldCategory));
 
 static cl::opt<uint64_t> TargetAddrEnd(
     "target-addr-end",
     cl::desc("For -verify only: end of phony target address range."),
-    cl::init(~0ULL), cl::Hidden);
+    cl::init(~0ULL), cl::Hidden, cl::cat(RTDyldCategory));
 
 static cl::opt<uint64_t> TargetSectionSep(
     "target-section-sep",
     cl::desc("For -verify only: Separation between sections in "
              "phony target address space."),
-    cl::init(0), cl::Hidden);
+    cl::init(0), cl::Hidden, cl::cat(RTDyldCategory));
 
 static cl::list<std::string>
-SpecificSectionMappings("map-section",
-                        cl::desc("For -verify only: Map a section to a "
-                                 "specific address."),
-                        cl::ZeroOrMore,
-                        cl::Hidden);
+    SpecificSectionMappings("map-section",
+                            cl::desc("For -verify only: Map a section to a "
+                                     "specific address."),
+                            cl::ZeroOrMore, cl::Hidden,
+                            cl::cat(RTDyldCategory));
 
-static cl::list<std::string>
-DummySymbolMappings("dummy-extern",
-                    cl::desc("For -verify only: Inject a symbol into the extern "
-                             "symbol table."),
-                    cl::ZeroOrMore,
-                    cl::Hidden);
+static cl::list<std::string> DummySymbolMappings(
+    "dummy-extern",
+    cl::desc("For -verify only: Inject a symbol into the extern "
+             "symbol table."),
+    cl::ZeroOrMore, cl::Hidden, cl::cat(RTDyldCategory));
 
-static cl::opt<bool>
-PrintAllocationRequests("print-alloc-requests",
-                        cl::desc("Print allocation requests made to the memory "
-                                 "manager by RuntimeDyld"),
-                        cl::Hidden);
+static cl::opt<bool> PrintAllocationRequests(
+    "print-alloc-requests",
+    cl::desc("Print allocation requests made to the memory "
+             "manager by RuntimeDyld"),
+    cl::Hidden, cl::cat(RTDyldCategory));
 
 static cl::opt<bool> ShowTimes("show-times",
                                cl::desc("Show times for llvm-rtdyld phases"),
-                               cl::init(false));
+                               cl::init(false), cl::cat(RTDyldCategory));
 
 ExitOnError ExitOnErr;
 
@@ -756,7 +758,7 @@
   if (!MAI)
     ErrorAndExit("Unable to create target asm info!");
 
-  MCContext Ctx(MAI.get(), MRI.get(), nullptr);
+  MCContext Ctx(Triple(TripleName), MAI.get(), MRI.get(), STI.get());
 
   std::unique_ptr<MCDisassembler> Disassembler(
     TheTarget->createMCDisassembler(*STI, Ctx));
@@ -840,7 +842,7 @@
         char *CSymAddr = static_cast<char *>(SymAddr);
         StringRef SecContent = Dyld.getSectionContent(SectionID);
         uint64_t SymSize = SecContent.size() - (CSymAddr - SecContent.data());
-        SymInfo.setContent(StringRef(CSymAddr, SymSize));
+        SymInfo.setContent(ArrayRef<char>(CSymAddr, SymSize));
       }
     }
     return SymInfo;
@@ -867,7 +869,8 @@
       return SectionID.takeError();
     RuntimeDyldChecker::MemoryRegionInfo SecInfo;
     SecInfo.setTargetAddress(Dyld.getSectionLoadAddress(*SectionID));
-    SecInfo.setContent(Dyld.getSectionContent(*SectionID));
+    StringRef SecContent = Dyld.getSectionContent(*SectionID);
+    SecInfo.setContent(ArrayRef<char>(SecContent.data(), SecContent.size()));
     return SecInfo;
   };
 
@@ -886,8 +889,10 @@
     RuntimeDyldChecker::MemoryRegionInfo StubMemInfo;
     StubMemInfo.setTargetAddress(Dyld.getSectionLoadAddress(SI.SectionID) +
                                  SI.Offset);
+    StringRef SecContent =
+        Dyld.getSectionContent(SI.SectionID).substr(SI.Offset);
     StubMemInfo.setContent(
-        Dyld.getSectionContent(SI.SectionID).substr(SI.Offset));
+        ArrayRef<char>(SecContent.data(), SecContent.size()));
     return StubMemInfo;
   };
 
@@ -962,6 +967,7 @@
   llvm::InitializeAllTargetMCs();
   llvm::InitializeAllDisassemblers();
 
+  cl::HideUnrelatedOptions({&RTDyldCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv, "llvm MC-JIT tool\n");
 
   ExitOnErr.setBanner(std::string(argv[0]) + ": ");
diff --git a/src/llvm-project/llvm/tools/llvm-rust-demangle-fuzzer/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-rust-demangle-fuzzer/CMakeLists.txt
new file mode 100644
index 0000000..eeb37fc
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-rust-demangle-fuzzer/CMakeLists.txt
@@ -0,0 +1,10 @@
+set(LLVM_LINK_COMPONENTS
+  Demangle
+  FuzzMutate
+  Support
+)
+
+add_llvm_fuzzer(llvm-rust-demangle-fuzzer
+  llvm-rust-demangle-fuzzer.cpp
+  DUMMY_MAIN DummyDemanglerFuzzer.cpp
+  )
diff --git a/src/llvm-project/llvm/tools/llvm-rust-demangle-fuzzer/DummyDemanglerFuzzer.cpp b/src/llvm-project/llvm/tools/llvm-rust-demangle-fuzzer/DummyDemanglerFuzzer.cpp
new file mode 100644
index 0000000..201fdd7
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-rust-demangle-fuzzer/DummyDemanglerFuzzer.cpp
@@ -0,0 +1,18 @@
+//===-- DummyDemanglerFuzzer.cpp - Entry point to sanity check the fuzzer -===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of main so we can build and test without linking libFuzzer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/FuzzMutate/FuzzerCLI.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
+int main(int argc, char *argv[]) {
+  return llvm::runFuzzerOnInputs(argc, argv, LLVMFuzzerTestOneInput);
+}
diff --git a/src/llvm-project/llvm/tools/llvm-rust-demangle-fuzzer/llvm-rust-demangle-fuzzer.cpp b/src/llvm-project/llvm/tools/llvm-rust-demangle-fuzzer/llvm-rust-demangle-fuzzer.cpp
new file mode 100644
index 0000000..c2891e5
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-rust-demangle-fuzzer/llvm-rust-demangle-fuzzer.cpp
@@ -0,0 +1,21 @@
+//===--- llvm-demangle-fuzzer.cpp - Fuzzer for the Rust Demangler ---------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Demangle/Demangle.h"
+#include <cstdint>
+#include <cstdlib>
+#include <string>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+  std::string NullTerminatedString((const char *)Data, Size);
+  int Status = 0;
+  char *Demangled = llvm::rustDemangle(NullTerminatedString.c_str(), nullptr,
+                                       nullptr, &Status);
+  std::free(Demangled);
+  return 0;
+}
diff --git a/src/llvm-project/llvm/tools/llvm-shlib/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-shlib/CMakeLists.txt
index b0ee190..76b9a25 100644
--- a/src/llvm-project/llvm/tools/llvm-shlib/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-shlib/CMakeLists.txt
@@ -50,6 +50,13 @@
       # Solaris ld does not accept global: *; so there is no way to version *all* global symbols
       set(LIB_NAMES -Wl,--version-script,${LLVM_LIBRARY_DIR}/tools/llvm-shlib/simple_version_script.map ${LIB_NAMES})
     endif()
+    if (NOT MINGW)
+      # Optimize function calls for default visibility definitions to avoid PLT and
+      # reduce dynamic relocations.
+      # Note: for -fno-pic default, the address of a function may be different from
+      # inside and outside libLLVM.so.
+      target_link_options(LLVM PRIVATE LINKER:-Bsymbolic-functions)
+    endif()
   elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
     set(LIB_NAMES -Wl,-all_load ${LIB_NAMES})
   endif()
diff --git a/src/llvm-project/llvm/tools/llvm-sim/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-sim/CMakeLists.txt
new file mode 100644
index 0000000..7629905
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-sim/CMakeLists.txt
@@ -0,0 +1,9 @@
+set(LLVM_LINK_COMPONENTS
+  Core
+  Support
+  Analysis
+  IRReader)
+
+add_llvm_tool(llvm-sim
+  llvm-sim.cpp
+)
diff --git a/src/llvm-project/llvm/tools/llvm-sim/llvm-sim.cpp b/src/llvm-project/llvm/tools/llvm-sim/llvm-sim.cpp
new file mode 100644
index 0000000..26e370f
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-sim/llvm-sim.cpp
@@ -0,0 +1,149 @@
+//===-- llvm-sim.cpp - Find  similar sections of programs -------*- 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 program finds similar sections of a Module, and exports them as a JSON
+// file.
+//
+// To find similarities contained across multiple modules, please use llvm-link
+// first to merge the modules.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/IRSimilarityIdentifier.h"
+#include "llvm/IRReader/IRReader.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/ToolOutputFile.h"
+
+using namespace llvm;
+using namespace IRSimilarity;
+
+static cl::opt<std::string> OutputFilename("o", cl::desc("Output Filename"),
+                                           cl::init("-"),
+                                           cl::value_desc("filename"));
+
+static cl::opt<std::string> InputSourceFile(cl::Positional,
+                                            cl::desc("<Source file>"),
+                                            cl::init("-"),
+                                            cl::value_desc("filename"));
+
+/// Retrieve the unique number \p I was mapped to in parseBitcodeFile.
+///
+/// \param I - The Instruction to find the instruction number for.
+/// \param LLVMInstNum - The mapping of Instructions to their location in the
+/// module represented by an unsigned integer.
+/// \returns The instruction number for \p I if it exists.
+Optional<unsigned>
+getPositionInModule(const Instruction *I,
+                    const DenseMap<Instruction *, unsigned> &LLVMInstNum) {
+  assert(I && "Instruction is nullptr!");
+  DenseMap<Instruction *, unsigned>::const_iterator It = LLVMInstNum.find(I);
+  if (It == LLVMInstNum.end())
+    return None;
+  return It->second;
+}
+
+/// Exports the given SimilarityGroups to a JSON file at \p FilePath.
+///
+/// \param FilePath - The path to the output location.
+/// \param SimSections - The similarity groups to process.
+/// \param LLVMInstNum - The mapping of Instructions to their location in the
+/// module represented by an unsigned integer.
+/// \returns A nonzero error code if there was a failure creating the file.
+std::error_code
+exportToFile(const StringRef FilePath,
+             const SimilarityGroupList &SimSections,
+             const DenseMap<Instruction *, unsigned> &LLVMInstNum) {
+  std::error_code EC;
+  std::unique_ptr<ToolOutputFile> Out(
+      new ToolOutputFile(FilePath, EC, sys::fs::OF_None));
+  if (EC)
+    return EC;
+
+  json::OStream J(Out->os(), 1);
+  J.objectBegin();
+
+  unsigned SimOption = 1;
+  // Process each list of SimilarityGroups organized by the Module.
+  for (const SimilarityGroup &G : SimSections) {
+    std::string SimOptionStr = std::to_string(SimOption);
+    J.attributeBegin(SimOptionStr);
+    J.arrayBegin();
+    // For each file there is a list of the range where the similarity
+    // exists.
+    for (const IRSimilarityCandidate &C : G) {
+      Optional<unsigned> Start =
+          getPositionInModule((*C.front()).Inst, LLVMInstNum);
+      Optional<unsigned> End =
+          getPositionInModule((*C.back()).Inst, LLVMInstNum);
+
+      assert(Start.hasValue() &&
+             "Could not find instruction number for first instruction");
+      assert(End.hasValue() &&
+             "Could not find instruction number for last instruction");
+
+      J.object([&] {
+        J.attribute("start", Start.getValue());
+        J.attribute("end", End.getValue());
+      });
+    }
+    J.arrayEnd();
+    J.attributeEnd();
+    SimOption++;
+  }
+  J.objectEnd();
+
+  Out->keep();
+
+  return EC;
+}
+
+int main(int argc, const char *argv[]) {
+  InitLLVM X(argc, argv);
+
+  cl::ParseCommandLineOptions(argc, argv, "LLVM IR Similarity Visualizer\n");
+
+  LLVMContext CurrContext;
+  SMDiagnostic Err;
+  std::unique_ptr<Module> ModuleToAnalyze =
+      parseIRFile(InputSourceFile, Err, CurrContext);
+
+  if (!ModuleToAnalyze) {
+    Err.print(argv[0], errs());
+    return 1;
+  }
+
+  // Mapping from an Instruction pointer to its occurrence in a sequential
+  // list of all the Instructions in a Module.
+  DenseMap<Instruction *, unsigned> LLVMInstNum;
+
+  // We give each instruction a number, which gives us a start and end value
+  // for the beginning and end of each IRSimilarityCandidate.
+  unsigned InstructionNumber = 1;
+  for (Function &F : *ModuleToAnalyze)
+    for (BasicBlock &BB : F)
+      for (Instruction &I : BB.instructionsWithoutDebug())
+        LLVMInstNum[&I]= InstructionNumber++;
+
+  // The similarity identifier we will use to find the similar sections.
+  IRSimilarityIdentifier SimIdent;
+  SimilarityGroupList SimilaritySections =
+      SimIdent.findSimilarity(*ModuleToAnalyze);
+
+  std::error_code E =
+      exportToFile(OutputFilename, SimilaritySections, LLVMInstNum);
+  if (E) {
+    errs() << argv[0] << ": " << E.message() << '\n';
+    return 2;
+  }
+
+  return 0;
+}
diff --git a/src/llvm-project/llvm/tools/llvm-size/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-size/CMakeLists.txt
index 7ef4f17..0d1f660 100644
--- a/src/llvm-project/llvm/tools/llvm-size/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-size/CMakeLists.txt
@@ -1,10 +1,17 @@
 set(LLVM_LINK_COMPONENTS
   Object
+  Option
   Support
   )
 
+set(LLVM_TARGET_DEFINITIONS Opts.td)
+tablegen(LLVM Opts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(SizeOptsTableGen)
+
 add_llvm_tool(llvm-size
   llvm-size.cpp
+  DEPENDS
+  SizeOptsTableGen
   )
 
 if(LLVM_INSTALL_BINUTILS_SYMLINKS)
diff --git a/src/llvm-project/llvm/tools/llvm-size/Opts.td b/src/llvm-project/llvm/tools/llvm-size/Opts.td
new file mode 100644
index 0000000..edae43f
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-size/Opts.td
@@ -0,0 +1,32 @@
+include "llvm/Option/OptParser.td"
+
+class F<string letter, string help> : Flag<["-"], letter>, HelpText<help>;
+class FF<string name, string help> : Flag<["--"], name>, HelpText<help>;
+
+multiclass Eq<string name, string help> {
+  def NAME #_EQ : Joined<["--"], name #"=">,
+                  HelpText<help>;
+  def : Separate<["--"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
+}
+
+def common : FF<"common", "Print common symbols in the ELF file. When using Berkeley format, this is added to bss">;
+defm format : Eq<"format", "Specify output format">;
+def help : FF<"help", "Display this help">;
+defm radix : Eq<"radix", "Print size in radix">;
+def totals : FF<"totals", "Print totals of all objects - Berkeley format only">;
+def version : FF<"version", "Display the version">;
+
+// Mach-O specific options.
+def grp_mach_o : OptionGroup<"kind">, HelpText<"OPTIONS (Mach-O specific)">;
+def arch_EQ : Joined<["--"], "arch=">, HelpText<"architecture(s) from a Mach-O file to dump">, Group<grp_mach_o>;
+def : Separate<["--", "-"], "arch">, Alias<arch_EQ>;
+def l : F<"l", "When format is darwin, use long format to include addresses and offsets">, Group<grp_mach_o>;
+
+def : F<"A", "Alias for --format">, Alias<format_EQ>, AliasArgs<["sysv"]>;
+def : F<"B", "Alias for --format">, Alias<format_EQ>, AliasArgs<["berkeley"]>;
+def : F<"d", "Alias for --radix=10">, Alias<radix_EQ>, AliasArgs<["10"]>;
+def : F<"h", "Alias for --help">, Alias<help>;
+def : F<"m", "Alias for --format">, Alias<format_EQ>, AliasArgs<["darwin"]>;
+def : F<"o", "Alias for --radix=8">, Alias<radix_EQ>, AliasArgs<["8"]>;
+def : F<"t", "Alias for --totals">, Alias<totals>;
+def : F<"x", "Alias for --radix=16">, Alias<radix_EQ>, AliasArgs<["16"]>;
diff --git a/src/llvm-project/llvm/tools/llvm-size/llvm-size.cpp b/src/llvm-project/llvm/tools/llvm-size/llvm-size.cpp
index 4f98a4c..ec9a4cd 100644
--- a/src/llvm-project/llvm/tools/llvm-size/llvm-size.cpp
+++ b/src/llvm-project/llvm/tools/llvm-size/llvm-size.cpp
@@ -18,6 +18,9 @@
 #include "llvm/Object/MachO.h"
 #include "llvm/Object/MachOUniversal.h"
 #include "llvm/Object/ObjectFile.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
@@ -33,23 +36,56 @@
 using namespace llvm;
 using namespace object;
 
-cl::OptionCategory SizeCat("llvm-size Options");
+namespace {
+using namespace llvm::opt; // for HelpHidden in Opts.inc
+enum ID {
+  OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  OPT_##ID,
+#include "Opts.inc"
+#undef OPTION
+};
+
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#include "Opts.inc"
+#undef PREFIX
+
+const opt::OptTable::Info InfoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  {                                                                            \
+      PREFIX,      NAME,      HELPTEXT,                                        \
+      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
+      PARAM,       FLAGS,     OPT_##GROUP,                                     \
+      OPT_##ALIAS, ALIASARGS, VALUES},
+#include "Opts.inc"
+#undef OPTION
+};
+
+class SizeOptTable : public opt::OptTable {
+public:
+  SizeOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+};
 
 enum OutputFormatTy { berkeley, sysv, darwin };
-static cl::opt<OutputFormatTy>
-    OutputFormat("format", cl::desc("Specify output format"),
-                 cl::values(clEnumVal(sysv, "System V format"),
-                            clEnumVal(berkeley, "Berkeley format"),
-                            clEnumVal(darwin, "Darwin -m format")),
-                 cl::init(berkeley), cl::cat(SizeCat));
+enum RadixTy { octal = 8, decimal = 10, hexadecimal = 16 };
+} // namespace
 
-static cl::opt<OutputFormatTy>
-    OutputFormatShort(cl::desc("Specify output format"),
-                      cl::values(clEnumValN(sysv, "A", "System V format"),
-                                 clEnumValN(berkeley, "B", "Berkeley format"),
-                                 clEnumValN(darwin, "m", "Darwin -m format")),
-                      cl::init(berkeley), cl::cat(SizeCat));
+static bool ArchAll = false;
+static std::vector<StringRef> ArchFlags;
+static bool ELFCommons;
+static OutputFormatTy OutputFormat;
+static bool DarwinLongFormat;
+static RadixTy Radix;
+static bool TotalSizes;
 
+static std::vector<std::string> InputFilenames;
+
+static std::string ToolName;
+
+// States
+static bool HadError = false;
 static bool BerkeleyHeaderPrinted = false;
 static bool MoreThanOneFile = false;
 static uint64_t TotalObjectText = 0;
@@ -57,59 +93,13 @@
 static uint64_t TotalObjectBss = 0;
 static uint64_t TotalObjectTotal = 0;
 
-cl::opt<bool>
-    DarwinLongFormat("l",
-                     cl::desc("When format is darwin, use long format "
-                              "to include addresses and offsets."),
-                     cl::cat(SizeCat));
-
-cl::opt<bool>
-    ELFCommons("common",
-               cl::desc("Print common symbols in the ELF file.  When using "
-                        "Berkeley format, this is added to bss."),
-               cl::init(false), cl::cat(SizeCat));
-
-static cl::list<std::string>
-    ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
-              cl::ZeroOrMore, cl::cat(SizeCat));
-static bool ArchAll = false;
-
-enum RadixTy { octal = 8, decimal = 10, hexadecimal = 16 };
-static cl::opt<RadixTy> Radix(
-    "radix", cl::desc("Print size in radix"), cl::init(decimal),
-    cl::values(clEnumValN(octal, "8", "Print size in octal"),
-               clEnumValN(decimal, "10", "Print size in decimal"),
-               clEnumValN(hexadecimal, "16", "Print size in hexadecimal")),
-    cl::cat(SizeCat));
-
-static cl::opt<RadixTy> RadixShort(
-    cl::desc("Print size in radix:"),
-    cl::values(clEnumValN(octal, "o", "Print size in octal"),
-               clEnumValN(decimal, "d", "Print size in decimal"),
-               clEnumValN(hexadecimal, "x", "Print size in hexadecimal")),
-    cl::init(decimal), cl::cat(SizeCat));
-
-static cl::opt<bool>
-    TotalSizes("totals",
-               cl::desc("Print totals of all objects - Berkeley format only"),
-               cl::init(false), cl::cat(SizeCat));
-
-static cl::alias TotalSizesShort("t", cl::desc("Short for --totals"),
-                                 cl::aliasopt(TotalSizes));
-
-static cl::list<std::string>
-    InputFilenames(cl::Positional, cl::desc("<input files>"), cl::ZeroOrMore);
-
-static cl::extrahelp
-    HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
-
-static bool HadError = false;
-
-static std::string ToolName;
-
-static void error(const Twine &Message, StringRef File) {
+static void error(const Twine &Message, StringRef File = "") {
   HadError = true;
-  WithColor::error(errs(), ToolName) << "'" << File << "': " << Message << "\n";
+  if (File.empty())
+    WithColor::error(errs(), ToolName) << Message << '\n';
+  else
+    WithColor::error(errs(), ToolName)
+        << "'" << File << "': " << Message << '\n';
 }
 
 // This version of error() prints the archive name and member name, for example:
@@ -874,27 +864,66 @@
 
 int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
-  cl::HideUnrelatedOptions(SizeCat);
-  cl::ParseCommandLineOptions(argc, argv, "llvm object size dumper\n");
-
+  BumpPtrAllocator A;
+  StringSaver Saver(A);
+  SizeOptTable Tbl;
   ToolName = argv[0];
-  if (OutputFormatShort.getNumOccurrences())
-    OutputFormat = static_cast<OutputFormatTy>(OutputFormatShort);
-  if (RadixShort.getNumOccurrences())
-    Radix = RadixShort.getValue();
+  opt::InputArgList Args = Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver,
+                                         [&](StringRef Msg) { error(Msg); });
+  if (Args.hasArg(OPT_help)) {
+    Tbl.printHelp(
+        outs(),
+        (Twine(ToolName) + " [options] <input object files>").str().c_str(),
+        "LLVM object size dumper");
+    // TODO Replace this with OptTable API once it adds extrahelp support.
+    outs() << "\nPass @FILE as argument to read options from FILE.\n";
+    return 0;
+  }
+  if (Args.hasArg(OPT_version)) {
+    outs() << ToolName << '\n';
+    cl::PrintVersionMessage();
+    return 0;
+  }
 
-  for (StringRef Arch : ArchFlags) {
-    if (Arch == "all") {
-      ArchAll = true;
-    } else {
-      if (!MachOObjectFile::isValidArch(Arch)) {
+  ELFCommons = Args.hasArg(OPT_common);
+  DarwinLongFormat = Args.hasArg(OPT_l);
+  TotalSizes = Args.hasArg(OPT_totals);
+  StringRef V = Args.getLastArgValue(OPT_format_EQ, "berkeley");
+  if (V == "berkeley")
+    OutputFormat = berkeley;
+  else if (V == "darwin")
+    OutputFormat = darwin;
+  else if (V == "sysv")
+    OutputFormat = sysv;
+  else
+    error("--format value should be one of: 'berkeley', 'darwin', 'sysv'");
+  V = Args.getLastArgValue(OPT_radix_EQ, "10");
+  if (V == "8")
+    Radix = RadixTy::octal;
+  else if (V == "10")
+    Radix = RadixTy::decimal;
+  else if (V == "16")
+    Radix = RadixTy::hexadecimal;
+  else
+    error("--radix value should be one of: 8, 10, 16 ");
+
+  for (const auto *A : Args.filtered(OPT_arch_EQ)) {
+    SmallVector<StringRef, 2> Values;
+    llvm::SplitString(A->getValue(), Values, ",");
+    for (StringRef V : Values) {
+      if (V == "all")
+        ArchAll = true;
+      else if (MachOObjectFile::isValidArch(V))
+        ArchFlags.push_back(V);
+      else {
         outs() << ToolName << ": for the -arch option: Unknown architecture "
-               << "named '" << Arch << "'";
+               << "named '" << V << "'";
         return 1;
       }
     }
   }
 
+  InputFilenames = Args.getAllArgValues(OPT_INPUT);
   if (InputFilenames.empty())
     InputFilenames.push_back("a.out");
 
diff --git a/src/llvm-project/llvm/tools/llvm-split/llvm-split.cpp b/src/llvm-project/llvm/tools/llvm-split/llvm-split.cpp
index be020c4..6de28dc 100644
--- a/src/llvm-project/llvm/tools/llvm-split/llvm-split.cpp
+++ b/src/llvm-project/llvm/tools/llvm-split/llvm-split.cpp
@@ -24,24 +24,32 @@
 
 using namespace llvm;
 
-static cl::opt<std::string>
-InputFilename(cl::Positional, cl::desc("<input bitcode file>"),
-    cl::init("-"), cl::value_desc("filename"));
+static cl::OptionCategory SplitCategory("Split Options");
 
-static cl::opt<std::string>
-OutputFilename("o", cl::desc("Override output filename"),
-               cl::value_desc("filename"));
+static cl::opt<std::string> InputFilename(cl::Positional,
+                                          cl::desc("<input bitcode file>"),
+                                          cl::init("-"),
+                                          cl::value_desc("filename"),
+                                          cl::cat(SplitCategory));
+
+static cl::opt<std::string> OutputFilename("o",
+                                           cl::desc("Override output filename"),
+                                           cl::value_desc("filename"),
+                                           cl::cat(SplitCategory));
 
 static cl::opt<unsigned> NumOutputs("j", cl::Prefix, cl::init(2),
-                                    cl::desc("Number of output files"));
+                                    cl::desc("Number of output files"),
+                                    cl::cat(SplitCategory));
 
 static cl::opt<bool>
     PreserveLocals("preserve-locals", cl::Prefix, cl::init(false),
-                   cl::desc("Split without externalizing locals"));
+                   cl::desc("Split without externalizing locals"),
+                   cl::cat(SplitCategory));
 
 int main(int argc, char **argv) {
   LLVMContext Context;
   SMDiagnostic Err;
+  cl::HideUnrelatedOptions({&SplitCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv, "LLVM module splitter\n");
 
   std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context);
@@ -52,25 +60,28 @@
   }
 
   unsigned I = 0;
-  SplitModule(std::move(M), NumOutputs, [&](std::unique_ptr<Module> MPart) {
-    std::error_code EC;
-    std::unique_ptr<ToolOutputFile> Out(
-        new ToolOutputFile(OutputFilename + utostr(I++), EC, sys::fs::OF_None));
-    if (EC) {
-      errs() << EC.message() << '\n';
-      exit(1);
-    }
+  SplitModule(
+      *M, NumOutputs,
+      [&](std::unique_ptr<Module> MPart) {
+        std::error_code EC;
+        std::unique_ptr<ToolOutputFile> Out(new ToolOutputFile(
+            OutputFilename + utostr(I++), EC, sys::fs::OF_None));
+        if (EC) {
+          errs() << EC.message() << '\n';
+          exit(1);
+        }
 
-    if (verifyModule(*MPart, &errs())) {
-      errs() << "Broken module!\n";
-      exit(1);
-    }
+        if (verifyModule(*MPart, &errs())) {
+          errs() << "Broken module!\n";
+          exit(1);
+        }
 
-    WriteBitcodeToFile(*MPart, Out->os());
+        WriteBitcodeToFile(*MPart, Out->os());
 
-    // Declare success.
-    Out->keep();
-  }, PreserveLocals);
+        // Declare success.
+        Out->keep();
+      },
+      PreserveLocals);
 
   return 0;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp b/src/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp
index 538240d..ece3229 100644
--- a/src/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp
+++ b/src/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp
@@ -52,16 +52,20 @@
 
 namespace llvm {
 
-static cl::opt<unsigned> SeedCL("seed",
-  cl::desc("Seed used for randomness"), cl::init(0));
+static cl::OptionCategory StressCategory("Stress Options");
 
-static cl::opt<unsigned> SizeCL("size",
-  cl::desc("The estimated size of the generated function (# of instrs)"),
-  cl::init(100));
+static cl::opt<unsigned> SeedCL("seed", cl::desc("Seed used for randomness"),
+                                cl::init(0), cl::cat(StressCategory));
 
-static cl::opt<std::string>
-OutputFilename("o", cl::desc("Override output filename"),
-               cl::value_desc("filename"));
+static cl::opt<unsigned> SizeCL(
+    "size",
+    cl::desc("The estimated size of the generated function (# of instrs)"),
+    cl::init(100), cl::cat(StressCategory));
+
+static cl::opt<std::string> OutputFilename("o",
+                                           cl::desc("Override output filename"),
+                                           cl::value_desc("filename"),
+                                           cl::cat(StressCategory));
 
 static LLVMContext Context;
 
@@ -632,7 +636,7 @@
 
     // If the value type is a vector, and we allow vector select, then in 50%
     // of the cases generate a vector select.
-    if (isa<FixedVectorType>(Val0->getType()) && (getRandom() % 1)) {
+    if (isa<FixedVectorType>(Val0->getType()) && (getRandom() & 1)) {
       unsigned NumElem =
           cast<FixedVectorType>(Val0->getType())->getNumElements();
       CondTy = FixedVectorType::get(CondTy, NumElem);
@@ -718,7 +722,7 @@
       BoolInst.push_back(&Instr);
   }
 
-  std::shuffle(BoolInst.begin(), BoolInst.end(), R);
+  llvm::shuffle(BoolInst.begin(), BoolInst.end(), R);
 
   for (auto *Instr : BoolInst) {
     BasicBlock *Curr = Instr->getParent();
@@ -738,6 +742,7 @@
   using namespace llvm;
 
   InitLLVM X(argc, argv);
+  cl::HideUnrelatedOptions({&StressCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n");
 
   auto M = std::make_unique<Module>("/tmp/autogen.bc", Context);
diff --git a/src/llvm-project/llvm/tools/llvm-strings/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-strings/CMakeLists.txt
index 390f117..95dd69c 100644
--- a/src/llvm-project/llvm/tools/llvm-strings/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-strings/CMakeLists.txt
@@ -1,11 +1,18 @@
 set(LLVM_LINK_COMPONENTS
   Core
   Object
+  Option
   Support
   )
 
+set(LLVM_TARGET_DEFINITIONS Opts.td)
+tablegen(LLVM Opts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(StringsOptsTableGen)
+
 add_llvm_tool(llvm-strings
   llvm-strings.cpp
+  DEPENDS
+  StringsOptsTableGen
   )
 
 if(LLVM_INSTALL_BINUTILS_SYMLINKS)
diff --git a/src/llvm-project/llvm/tools/llvm-strings/Opts.td b/src/llvm-project/llvm/tools/llvm-strings/Opts.td
new file mode 100644
index 0000000..2ad77fa
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-strings/Opts.td
@@ -0,0 +1,23 @@
+include "llvm/Option/OptParser.td"
+
+class F<string letter, string help> : Flag<["-"], letter>, HelpText<help>;
+class FF<string name, string help> : Flag<["--"], name>, HelpText<help>;
+
+multiclass Eq<string name, string help> {
+  def NAME #_EQ : Joined<["--"], name #"=">,
+                  HelpText<help>;
+  def : Separate<["--"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
+}
+
+def all : FF<"all", "Silently ignored. Present for GNU strings compatibility">;
+defm bytes : Eq<"bytes", "Print sequences of the specified length">;
+def help : FF<"help", "Display this help">;
+def print_file_name : Flag<["--"], "print-file-name">, HelpText<"Print the name of the file before each string">;
+defm radix : Eq<"radix", "Print the offset within the file with the specified radix: o (octal), d (decimal), x (hexadecimal)">, MetaVarName<"<radix>">;
+def version : FF<"version", "Display the version">;
+
+def : F<"a", "Alias for --all">, Alias<all>;
+def : F<"f", "Alias for --print-file-name">, Alias<print_file_name>;
+def : F<"h", "Alias for --help">, Alias<help>;
+def : JoinedOrSeparate<["-"], "n">, Alias<bytes_EQ>, HelpText<"Alias for --bytes">;
+def : JoinedOrSeparate<["-"], "t">, Alias<radix_EQ>, HelpText<"Alias for --radix">, MetaVarName<"<radix>">;
diff --git a/src/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp b/src/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp
index 51313d7..0b06874 100644
--- a/src/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp
+++ b/src/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp
@@ -11,51 +11,81 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "Opts.inc"
 #include "llvm/Object/Binary.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Program.h"
+#include "llvm/Support/WithColor.h"
 #include <cctype>
 #include <string>
 
 using namespace llvm;
 using namespace llvm::object;
 
+namespace {
+enum ID {
+  OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  OPT_##ID,
+#include "Opts.inc"
+#undef OPTION
+};
+
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#include "Opts.inc"
+#undef PREFIX
+
+static const opt::OptTable::Info InfoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
+               HELPTEXT, METAVAR, VALUES)                                      \
+  {                                                                            \
+      PREFIX,      NAME,      HELPTEXT,                                        \
+      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
+      PARAM,       FLAGS,     OPT_##GROUP,                                     \
+      OPT_##ALIAS, ALIASARGS, VALUES},
+#include "Opts.inc"
+#undef OPTION
+};
+
+class StringsOptTable : public opt::OptTable {
+public:
+  StringsOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+};
+} // namespace
+
+const char ToolName[] = "llvm-strings";
+
 static cl::list<std::string> InputFileNames(cl::Positional,
                                             cl::desc("<input object files>"),
                                             cl::ZeroOrMore);
 
-static cl::opt<bool>
-    PrintFileName("print-file-name",
-                  cl::desc("Print the name of the file before each string"));
-static cl::alias PrintFileNameShort("f", cl::desc(""),
-                                    cl::aliasopt(PrintFileName));
-
-static cl::opt<int>
-    MinLength("bytes", cl::desc("Print sequences of the specified length"),
-              cl::init(4));
-static cl::alias MinLengthShort("n", cl::desc(""), cl::aliasopt(MinLength));
-
-static cl::opt<bool>
-    AllSections("all",
-                  cl::desc("Check all sections, not just the data section"));
-static cl::alias AllSectionsShort("a", cl::desc(""),
-                                    cl::aliasopt(AllSections));
+static int MinLength = 4;
+static bool PrintFileName;
 
 enum radix { none, octal, hexadecimal, decimal };
-static cl::opt<radix>
-    Radix("radix", cl::desc("print the offset within the file"),
-          cl::values(clEnumValN(octal, "o", "octal"),
-                     clEnumValN(hexadecimal, "x", "hexadecimal"),
-                     clEnumValN(decimal, "d", "decimal")),
-          cl::init(none));
-static cl::alias RadixShort("t", cl::desc(""), cl::aliasopt(Radix));
+static radix Radix;
 
-static cl::extrahelp
-    HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
+LLVM_ATTRIBUTE_NORETURN static void reportCmdLineError(const Twine &Message) {
+  WithColor::error(errs(), ToolName) << Message << "\n";
+  exit(1);
+}
+
+template <typename T>
+static void parseIntArg(const opt::InputArgList &Args, int ID, T &Value) {
+  if (const opt::Arg *A = Args.getLastArg(ID)) {
+    StringRef V(A->getValue());
+    if (!llvm::to_integer(V, Value, 0) || Value <= 0)
+      reportCmdLineError("expected a positive integer, but got '" + V + "'");
+  }
+}
 
 static void strings(raw_ostream &OS, StringRef FileName, StringRef Contents) {
   auto print = [&OS, FileName](unsigned Offset, StringRef L) {
@@ -96,13 +126,48 @@
 
 int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
+  BumpPtrAllocator A;
+  StringSaver Saver(A);
+  StringsOptTable Tbl;
+  opt::InputArgList Args =
+      Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver,
+                    [&](StringRef Msg) { reportCmdLineError(Msg); });
+  if (Args.hasArg(OPT_help)) {
+    Tbl.printHelp(
+        outs(),
+        (Twine(ToolName) + " [options] <input object files>").str().c_str(),
+        "llvm string dumper");
+    // TODO Replace this with OptTable API once it adds extrahelp support.
+    outs() << "\nPass @FILE as argument to read options from FILE.\n";
+    return 0;
+  }
+  if (Args.hasArg(OPT_version)) {
+    outs() << ToolName << '\n';
+    cl::PrintVersionMessage();
+    return 0;
+  }
 
-  cl::ParseCommandLineOptions(argc, argv, "llvm string dumper\n");
+  parseIntArg(Args, OPT_bytes_EQ, MinLength);
+  PrintFileName = Args.hasArg(OPT_print_file_name);
+  StringRef R = Args.getLastArgValue(OPT_radix_EQ);
+  if (R.empty())
+    Radix = none;
+  else if (R == "o")
+    Radix = octal;
+  else if (R == "d")
+    Radix = decimal;
+  else if (R == "x")
+    Radix = hexadecimal;
+  else
+    reportCmdLineError("--radix value should be one of: '' (no offset), 'o' "
+                       "(octal), 'd' (decimal), 'x' (hexadecimal)");
+
   if (MinLength == 0) {
     errs() << "invalid minimum string length 0\n";
     return EXIT_FAILURE;
   }
 
+  std::vector<std::string> InputFileNames = Args.getAllArgValues(OPT_INPUT);
   if (InputFileNames.empty())
     InputFileNames.push_back("-");
 
diff --git a/src/llvm-project/llvm/tools/llvm-symbolizer/Opts.td b/src/llvm-project/llvm/tools/llvm-symbolizer/Opts.td
index ac23639..6026e24 100644
--- a/src/llvm-project/llvm/tools/llvm-symbolizer/Opts.td
+++ b/src/llvm-project/llvm/tools/llvm-symbolizer/Opts.td
@@ -1,17 +1,20 @@
 include "llvm/Option/OptParser.td"
 
 multiclass B<string name, string help1, string help2> {
-  def NAME: Flag<["--", "-"], name>, HelpText<help1>;
-  def no_ # NAME: Flag<["--", "-"], "no-" # name>, HelpText<help2>;
+  def NAME: Flag<["--"], name>, HelpText<help1>;
+  def no_ # NAME: Flag<["--"], "no-" # name>, HelpText<help2>;
 }
 
 multiclass Eq<string name, string help> {
-  def NAME #_EQ : Joined<["--", "-"], name #"=">,
+  def NAME #_EQ : Joined<["--"], name #"=">,
                   HelpText<help>;
-  def : Separate<["--", "-"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
+  def : Separate<["--"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
 }
 
-class F<string name, string help>: Flag<["--", "-"], name>, HelpText<help>;
+class F<string name, string help>: Flag<["--"], name>, HelpText<help>;
+
+def grp_mach_o : OptionGroup<"kind">,
+                 HelpText<"llvm-symbolizer Mach-O Specific Options">;
 
 def addresses : F<"addresses", "Show address before line information">;
 defm adjust_vma
@@ -19,13 +22,19 @@
       MetaVarName<"<offset>">;
 def basenames : Flag<["--"], "basenames">, HelpText<"Strip directory names from paths">;
 defm debug_file_directory : Eq<"debug-file-directory", "Path to directory where to look for debug files">, MetaVarName<"<dir>">;
-defm default_arch : Eq<"default-arch", "Default architecture (for multi-arch objects)">;
+defm default_arch
+    : Eq<"default-arch", "Default architecture (for multi-arch objects)">,
+      Group<grp_mach_o>;
 defm demangle : B<"demangle", "Demangle function names", "Don't demangle function names">;
 def functions : F<"functions", "Print function name for a given address">;
 def functions_EQ : Joined<["--"], "functions=">, HelpText<"Print function name for a given address">, Values<"none,short,linkage">;
 def help : F<"help", "Display this help">;
 defm dwp : Eq<"dwp", "Path to DWP file to be use for any split CUs">, MetaVarName<"<file>">;
-defm dsym_hint : Eq<"dsym-hint", "Path to .dSYM bundles to search for debug info for the object files">, MetaVarName<"<dir>">;
+defm dsym_hint
+    : Eq<"dsym-hint",
+         "Path to .dSYM bundles to search for debug info for the object files">,
+      MetaVarName<"<dir>">,
+      Group<grp_mach_o>;
 defm fallback_debug_path : Eq<"fallback-debug-path", "Fallback path for debug binaries">, MetaVarName<"<dir>">;
 defm inlines : B<"inlines", "Print all inlined frames for a given address",
                  "Do not print inlined frames">;
@@ -33,9 +42,9 @@
     : Eq<"obj", "Path to object file to be symbolized (if not provided, "
                 "object file should be specified for each input line)">, MetaVarName<"<file>">;
 defm output_style
-    : Eq<"output-style", "Specify print style. Supported styles: LLVM, GNU">,
+    : Eq<"output-style", "Specify print style. Supported styles: LLVM, GNU, JSON">,
       MetaVarName<"style">,
-      Values<"LLVM,GNU">;
+      Values<"LLVM,GNU,JSON">;
 def pretty_print : F<"pretty-print", "Make the output more human friendly">;
 defm print_source_context_lines : Eq<"print-source-context-lines", "Print N lines of source file context">;
 def relative_address : F<"relative-address", "Interpret addresses as addresses relative to the image base">;
diff --git a/src/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/src/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
index 8734c2d..227ce12 100644
--- a/src/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -66,23 +66,35 @@
 
 class SymbolizerOptTable : public opt::OptTable {
 public:
-  SymbolizerOptTable() : OptTable(InfoTable, true) {}
+  SymbolizerOptTable() : OptTable(InfoTable) {
+    setGroupedShortOptions(true);
+  }
 };
 } // namespace
 
-static cl::list<std::string> ClInputAddresses(cl::Positional,
-                                              cl::desc("<input addresses>..."),
-                                              cl::ZeroOrMore);
+template <typename T>
+static void print(const Request &Request, Expected<T> &ResOrErr,
+                  DIPrinter &Printer) {
+  if (ResOrErr) {
+    // No error, print the result.
+    Printer.print(Request, *ResOrErr);
+    return;
+  }
 
-template<typename T>
-static bool error(Expected<T> &ResOrErr) {
-  if (ResOrErr)
-    return false;
-  logAllUnhandledErrors(ResOrErr.takeError(), errs(),
-                        "LLVMSymbolizer: error reading file: ");
-  return true;
+  // Handle the error.
+  bool PrintEmpty = true;
+  handleAllErrors(std::move(ResOrErr.takeError()),
+                  [&](const ErrorInfoBase &EI) {
+                    PrintEmpty = Printer.printError(
+                        Request, EI, "LLVMSymbolizer: error reading file: ");
+                  });
+
+  if (PrintEmpty)
+    Printer.print(Request, T());
 }
 
+enum class OutputStyle { LLVM, GNU, JSON };
+
 enum class Command {
   Code,
   Data,
@@ -136,7 +148,7 @@
 }
 
 static void symbolizeInput(const opt::InputArgList &Args, uint64_t AdjustVMA,
-                           bool IsAddr2Line, DIPrinter::OutputStyle OutputStyle,
+                           bool IsAddr2Line, OutputStyle Style,
                            StringRef InputString, LLVMSymbolizer &Symbolizer,
                            DIPrinter &Printer) {
   Command Cmd;
@@ -144,62 +156,49 @@
   uint64_t Offset = 0;
   if (!parseCommand(Args.getLastArgValue(OPT_obj_EQ), IsAddr2Line,
                     StringRef(InputString), Cmd, ModuleName, Offset)) {
-    outs() << InputString << "\n";
+    Printer.printInvalidCommand({ModuleName, None}, InputString);
     return;
   }
 
-  if (Args.hasArg(OPT_addresses)) {
-    outs() << "0x";
-    outs().write_hex(Offset);
-    StringRef Delimiter = Args.hasArg(OPT_pretty_print) ? ": " : "\n";
-    outs() << Delimiter;
-  }
-  Offset -= AdjustVMA;
+  uint64_t AdjustedOffset = Offset - AdjustVMA;
   if (Cmd == Command::Data) {
-    auto ResOrErr = Symbolizer.symbolizeData(
-        ModuleName, {Offset, object::SectionedAddress::UndefSection});
-    Printer << (error(ResOrErr) ? DIGlobal() : ResOrErr.get());
+    Expected<DIGlobal> ResOrErr = Symbolizer.symbolizeData(
+        ModuleName, {AdjustedOffset, object::SectionedAddress::UndefSection});
+    print({ModuleName, Offset}, ResOrErr, Printer);
   } else if (Cmd == Command::Frame) {
-    auto ResOrErr = Symbolizer.symbolizeFrame(
-        ModuleName, {Offset, object::SectionedAddress::UndefSection});
-    if (!error(ResOrErr)) {
-      for (DILocal Local : *ResOrErr)
-        Printer << Local;
-      if (ResOrErr->empty())
-        outs() << "??\n";
-    }
+    Expected<std::vector<DILocal>> ResOrErr = Symbolizer.symbolizeFrame(
+        ModuleName, {AdjustedOffset, object::SectionedAddress::UndefSection});
+    print({ModuleName, Offset}, ResOrErr, Printer);
   } else if (Args.hasFlag(OPT_inlines, OPT_no_inlines, !IsAddr2Line)) {
-    auto ResOrErr = Symbolizer.symbolizeInlinedCode(
-        ModuleName, {Offset, object::SectionedAddress::UndefSection});
-    Printer << (error(ResOrErr) ? DIInliningInfo() : ResOrErr.get());
-  } else if (OutputStyle == DIPrinter::OutputStyle::GNU) {
+    Expected<DIInliningInfo> ResOrErr = Symbolizer.symbolizeInlinedCode(
+        ModuleName, {AdjustedOffset, object::SectionedAddress::UndefSection});
+    print({ModuleName, Offset}, ResOrErr, Printer);
+  } else if (Style == OutputStyle::GNU) {
     // With PrintFunctions == FunctionNameKind::LinkageName (default)
     // and UseSymbolTable == true (also default), Symbolizer.symbolizeCode()
     // may override the name of an inlined function with the name of the topmost
     // caller function in the inlining chain. This contradicts the existing
     // behavior of addr2line. Symbolizer.symbolizeInlinedCode() overrides only
     // the topmost function, which suits our needs better.
-    auto ResOrErr = Symbolizer.symbolizeInlinedCode(
-        ModuleName, {Offset, object::SectionedAddress::UndefSection});
-    if (!ResOrErr || ResOrErr->getNumberOfFrames() == 0) {
-      error(ResOrErr);
-      Printer << DILineInfo();
-    } else {
-      Printer << ResOrErr->getFrame(0);
-    }
+    Expected<DIInliningInfo> ResOrErr = Symbolizer.symbolizeInlinedCode(
+        ModuleName, {AdjustedOffset, object::SectionedAddress::UndefSection});
+    Expected<DILineInfo> Res0OrErr =
+        !ResOrErr
+            ? Expected<DILineInfo>(ResOrErr.takeError())
+            : ((ResOrErr->getNumberOfFrames() == 0) ? DILineInfo()
+                                                    : ResOrErr->getFrame(0));
+    print({ModuleName, Offset}, Res0OrErr, Printer);
   } else {
-    auto ResOrErr = Symbolizer.symbolizeCode(
-        ModuleName, {Offset, object::SectionedAddress::UndefSection});
-    Printer << (error(ResOrErr) ? DILineInfo() : ResOrErr.get());
+    Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode(
+        ModuleName, {AdjustedOffset, object::SectionedAddress::UndefSection});
+    print({ModuleName, Offset}, ResOrErr, Printer);
   }
-  if (OutputStyle == DIPrinter::OutputStyle::LLVM)
-    outs() << "\n";
 }
 
 static void printHelp(StringRef ToolName, const SymbolizerOptTable &Tbl,
                       raw_ostream &OS) {
   const char HelpText[] = " [options] addresses...";
-  Tbl.PrintHelp(OS, (ToolName + HelpText).str().c_str(),
+  Tbl.printHelp(OS, (ToolName + HelpText).str().c_str(),
                 ToolName.str().c_str());
   // TODO Replace this with OptTable API once it adds extrahelp support.
   OS << "\nPass @FILE as argument to read options from FILE.\n";
@@ -209,7 +208,6 @@
                                       StringSaver &Saver,
                                       SymbolizerOptTable &Tbl) {
   StringRef ToolName = IsAddr2Line ? "llvm-addr2line" : "llvm-symbolizer";
-  Tbl.setGroupedShortOptions(true);
   // The environment variable specifies initial options which can be overridden
   // by commnad line options.
   Tbl.setInitialOptionsFromEnvironment(IsAddr2Line ? "LLVM_ADDR2LINE_OPTS"
@@ -273,7 +271,7 @@
 
   LLVMSymbolizer::Options Opts;
   uint64_t AdjustVMA;
-  unsigned SourceContextLines;
+  PrinterConfig Config;
   parseIntArg(Args, OPT_adjust_vma_EQ, AdjustVMA);
   if (const opt::Arg *A = Args.getLastArg(OPT_basenames, OPT_relativenames)) {
     Opts.PathStyle =
@@ -290,7 +288,8 @@
   Opts.FallbackDebugPath =
       Args.getLastArgValue(OPT_fallback_debug_path_EQ).str();
   Opts.PrintFunctions = decideHowToPrintFunctions(Args, IsAddr2Line);
-  parseIntArg(Args, OPT_print_source_context_lines_EQ, SourceContextLines);
+  parseIntArg(Args, OPT_print_source_context_lines_EQ,
+              Config.SourceContextLines);
   Opts.RelativeAddresses = Args.hasArg(OPT_relative_address);
   Opts.UntagAddresses =
       Args.hasFlag(OPT_untag_addresses, OPT_no_untag_addresses, !IsAddr2Line);
@@ -302,6 +301,10 @@
   }
 #endif
   Opts.UseSymbolTable = true;
+  Config.PrintAddress = Args.hasArg(OPT_addresses);
+  Config.PrintFunctions = Opts.PrintFunctions != FunctionNameKind::None;
+  Config.Pretty = Args.hasArg(OPT_pretty_print);
+  Config.Verbose = Args.hasArg(OPT_verbose);
 
   for (const opt::Arg *A : Args.filtered(OPT_dsym_hint_EQ)) {
     StringRef Hint(A->getValue());
@@ -313,18 +316,24 @@
     }
   }
 
-  auto OutputStyle =
-      IsAddr2Line ? DIPrinter::OutputStyle::GNU : DIPrinter::OutputStyle::LLVM;
+  auto Style = IsAddr2Line ? OutputStyle::GNU : OutputStyle::LLVM;
   if (const opt::Arg *A = Args.getLastArg(OPT_output_style_EQ)) {
-    OutputStyle = strcmp(A->getValue(), "GNU") == 0
-                      ? DIPrinter::OutputStyle::GNU
-                      : DIPrinter::OutputStyle::LLVM;
+    if (strcmp(A->getValue(), "GNU") == 0)
+      Style = OutputStyle::GNU;
+    else if (strcmp(A->getValue(), "JSON") == 0)
+      Style = OutputStyle::JSON;
+    else
+      Style = OutputStyle::LLVM;
   }
 
   LLVMSymbolizer Symbolizer(Opts);
-  DIPrinter Printer(outs(), Opts.PrintFunctions != FunctionNameKind::None,
-                    Args.hasArg(OPT_pretty_print), SourceContextLines,
-                    Args.hasArg(OPT_verbose), OutputStyle);
+  std::unique_ptr<DIPrinter> Printer;
+  if (Style == OutputStyle::GNU)
+    Printer = std::make_unique<GNUPrinter>(outs(), errs(), Config);
+  else if (Style == OutputStyle::JSON)
+    Printer = std::make_unique<JSONPrinter>(outs(), Config);
+  else
+    Printer = std::make_unique<LLVMPrinter>(outs(), errs(), Config);
 
   std::vector<std::string> InputAddresses = Args.getAllArgValues(OPT_INPUT);
   if (InputAddresses.empty()) {
@@ -336,14 +345,16 @@
       std::string StrippedInputString(InputString);
       llvm::erase_if(StrippedInputString,
                      [](char c) { return c == '\r' || c == '\n'; });
-      symbolizeInput(Args, AdjustVMA, IsAddr2Line, OutputStyle,
-                     StrippedInputString, Symbolizer, Printer);
+      symbolizeInput(Args, AdjustVMA, IsAddr2Line, Style, StrippedInputString,
+                     Symbolizer, *Printer);
       outs().flush();
     }
   } else {
+    Printer->listBegin();
     for (StringRef Address : InputAddresses)
-      symbolizeInput(Args, AdjustVMA, IsAddr2Line, OutputStyle, Address,
-                     Symbolizer, Printer);
+      symbolizeInput(Args, AdjustVMA, IsAddr2Line, Style, Address, Symbolizer,
+                     *Printer);
+    Printer->listEnd();
   }
 
   return 0;
diff --git a/src/llvm-project/llvm/tools/llvm-tapi-diff/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-tapi-diff/CMakeLists.txt
new file mode 100644
index 0000000..2870221
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-tapi-diff/CMakeLists.txt
@@ -0,0 +1,10 @@
+set(LLVM_LINK_COMPONENTS
+  Object
+  Support
+  TextAPI
+  )
+
+add_llvm_tool(llvm-tapi-diff
+  llvm-tapi-diff.cpp
+  DiffEngine.cpp
+  )
diff --git a/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp b/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp
new file mode 100644
index 0000000..ff60d52
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp
@@ -0,0 +1,556 @@
+//===-- DiffEngine.cpp - Structural file comparison -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the implementation of the llvm-tapi difference
+// engine, which structurally compares two tbd files.
+//
+//===----------------------------------------------------------------------===/
+#include "DiffEngine.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TextAPI/InterfaceFile.h"
+#include "llvm/TextAPI/Symbol.h"
+#include "llvm/TextAPI/Target.h"
+
+using namespace llvm;
+using namespace MachO;
+using namespace object;
+
+StringRef setOrderIndicator(InterfaceInputOrder Order) {
+  return ((Order == lhs) ? "< " : "> ");
+}
+
+// The following template specialization implementations
+// need to be explicitly placed into the llvm namespace
+// to work around a GCC 4.8 bug.
+namespace llvm {
+
+template <typename T, DiffAttrKind U>
+inline void DiffScalarVal<T, U>::print(raw_ostream &OS, std::string Indent) {
+  OS << Indent << "\t" << setOrderIndicator(Order) << Val << "\n";
+}
+
+template <>
+inline void
+DiffScalarVal<StringRef, AD_Diff_Scalar_Str>::print(raw_ostream &OS,
+                                                    std::string Indent) {
+  OS << Indent << "\t\t" << setOrderIndicator(Order) << Val << "\n";
+}
+
+template <>
+inline void
+DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>::print(raw_ostream &OS,
+                                                       std::string Indent) {
+  OS << Indent << "\t" << setOrderIndicator(Order) << std::to_string(Val)
+     << "\n";
+}
+
+template <>
+inline void
+DiffScalarVal<bool, AD_Diff_Scalar_Bool>::print(raw_ostream &OS,
+                                                std::string Indent) {
+  OS << Indent << "\t" << setOrderIndicator(Order)
+     << ((Val == true) ? "true" : "false") << "\n";
+}
+
+} // end namespace llvm
+
+StringLiteral SymScalar::getSymbolNamePrefix(MachO::SymbolKind Kind) {
+  switch (Kind) {
+  case MachO::SymbolKind::GlobalSymbol:
+    return StringLiteral("");
+  case MachO::SymbolKind::ObjectiveCClass:
+    return ObjC2MetaClassNamePrefix;
+  case MachO::SymbolKind ::ObjectiveCClassEHType:
+    return ObjC2EHTypePrefix;
+  case MachO::SymbolKind ::ObjectiveCInstanceVariable:
+    return ObjC2IVarPrefix;
+  }
+  llvm_unreachable("Unknown llvm::MachO::SymbolKind enum");
+}
+
+std::string SymScalar::stringifySymbolFlag(MachO::SymbolFlags Flag) {
+  switch (Flag) {
+  case MachO::SymbolFlags::None:
+    return "";
+  case MachO::SymbolFlags::ThreadLocalValue:
+    return "Thread-Local";
+  case MachO::SymbolFlags::WeakDefined:
+    return "Weak-Defined";
+  case MachO::SymbolFlags::WeakReferenced:
+    return "Weak-Referenced";
+  case MachO::SymbolFlags::Undefined:
+    return "Undefined";
+  case MachO::SymbolFlags::Rexported:
+    return "Reexported";
+  }
+  llvm_unreachable("Unknown llvm::MachO::SymbolFlags enum");
+}
+
+void SymScalar::print(raw_ostream &OS, std::string Indent, MachO::Target Targ) {
+  if (Val->getKind() == MachO::SymbolKind::ObjectiveCClass) {
+    if (Targ.Arch == MachO::AK_i386 &&
+        Targ.Platform == MachO::PlatformKind::macOS) {
+      OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ")
+         << ObjC1ClassNamePrefix << Val->getName()
+         << getFlagString(Val->getFlags()) << "\n";
+      return;
+    }
+    OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ")
+       << ObjC2ClassNamePrefix << Val->getName()
+       << getFlagString(Val->getFlags()) << "\n";
+  }
+  OS << Indent << "\t\t" << ((Order == lhs) ? "< " : "> ")
+     << getSymbolNamePrefix(Val->getKind()) << Val->getName()
+     << getFlagString(Val->getFlags()) << "\n";
+}
+
+bool checkSymbolEquality(llvm::MachO::InterfaceFile::const_symbol_range LHS,
+                         llvm::MachO::InterfaceFile::const_symbol_range RHS) {
+  return std::equal(LHS.begin(), LHS.end(), RHS.begin(),
+                    [&](auto LHS, auto RHS) { return *LHS == *RHS; });
+}
+
+template <typename TargetVecT, typename ValTypeT, typename V>
+void addDiffForTargSlice(V Val, Target Targ, DiffOutput &Diff,
+                         InterfaceInputOrder Order) {
+  auto TargetVector = llvm::find_if(
+      Diff.Values, [&](const std::unique_ptr<AttributeDiff> &RawTVec) {
+        if (TargetVecT *TVec = dyn_cast<TargetVecT>(RawTVec.get()))
+          return TVec->Targ == Targ;
+        return false;
+      });
+  if (TargetVector != Diff.Values.end()) {
+    ValTypeT NewVal(Order, Val);
+    cast<TargetVecT>(TargetVector->get())->TargValues.push_back(NewVal);
+  } else {
+    auto NewTargetVec = std::make_unique<TargetVecT>(Targ);
+    ValTypeT NewVal(Order, Val);
+    NewTargetVec->TargValues.push_back(NewVal);
+    Diff.Values.push_back(std::move(NewTargetVec));
+  }
+}
+
+DiffOutput getSingleAttrDiff(const std::vector<InterfaceFileRef> &IRefVec,
+                             std::string Name, InterfaceInputOrder Order) {
+  DiffOutput Diff(Name);
+  Diff.Kind = AD_Str_Vec;
+  for (const auto &IRef : IRefVec)
+    for (auto Targ : IRef.targets())
+      addDiffForTargSlice<DiffStrVec,
+                          DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>(
+          IRef.getInstallName(), Targ, Diff, Order);
+  return Diff;
+}
+
+DiffOutput
+getSingleAttrDiff(const std::vector<std::pair<Target, std::string>> &PairVec,
+                  std::string Name, InterfaceInputOrder Order) {
+  DiffOutput Diff(Name);
+  Diff.Kind = AD_Str_Vec;
+  for (const auto &Pair : PairVec)
+    addDiffForTargSlice<DiffStrVec,
+                        DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>(
+        StringRef(Pair.second), Pair.first, Diff, Order);
+  return Diff;
+}
+
+DiffOutput getSingleAttrDiff(InterfaceFile::const_symbol_range SymRange,
+                             std::string Name, InterfaceInputOrder Order) {
+  DiffOutput Diff(Name);
+  Diff.Kind = AD_Sym_Vec;
+  for (const auto *Sym : SymRange)
+    for (auto Targ : Sym->targets())
+      addDiffForTargSlice<DiffSymVec, SymScalar>(Sym, Targ, Diff, Order);
+  return Diff;
+}
+
+template <typename T>
+DiffOutput getSingleAttrDiff(T SingleAttr, std::string Attribute) {
+  DiffOutput Diff(Attribute);
+  Diff.Kind = SingleAttr.getKind();
+  Diff.Values.push_back(std::make_unique<T>(SingleAttr));
+  return Diff;
+}
+
+template <typename T, DiffAttrKind U>
+void diffAttribute(std::string Name, std::vector<DiffOutput> &Output,
+                   DiffScalarVal<T, U> Attr) {
+  Output.push_back(getSingleAttrDiff(Attr, Name));
+}
+
+template <typename T>
+void diffAttribute(std::string Name, std::vector<DiffOutput> &Output,
+                   const T &Val, InterfaceInputOrder Order) {
+  Output.push_back(getSingleAttrDiff(Val, Name, Order));
+}
+
+std::vector<DiffOutput> getSingleIF(InterfaceFile *Interface,
+                                    InterfaceInputOrder Order) {
+  std::vector<DiffOutput> Output;
+  diffAttribute("Install Name", Output,
+                DiffScalarVal<StringRef, AD_Diff_Scalar_Str>(
+                    Order, Interface->getInstallName()));
+  diffAttribute("Current Version", Output,
+                DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>(
+                    Order, Interface->getCurrentVersion()));
+  diffAttribute("Compatibility Version", Output,
+                DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>(
+                    Order, Interface->getCompatibilityVersion()));
+  diffAttribute("Swift ABI Version", Output,
+                DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>(
+                    Order, Interface->getSwiftABIVersion()));
+  diffAttribute("InstallAPI", Output,
+                DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+                    Order, Interface->isInstallAPI()));
+  diffAttribute("Two Level Namespace", Output,
+                DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+                    Order, Interface->isTwoLevelNamespace()));
+  diffAttribute("Application Extension Safe", Output,
+                DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+                    Order, Interface->isApplicationExtensionSafe()));
+  diffAttribute("Reexported Libraries", Output,
+                Interface->reexportedLibraries(), Order);
+  diffAttribute("Allowable Clients", Output, Interface->allowableClients(),
+                Order);
+  diffAttribute("Parent Umbrellas", Output, Interface->umbrellas(), Order);
+  diffAttribute("Symbols", Output, Interface->symbols(), Order);
+  for (auto Doc : Interface->documents()) {
+    DiffOutput Documents("Inlined Reexported Frameworks/Libraries");
+    Documents.Kind = AD_Inline_Doc;
+    Documents.Values.push_back(std::make_unique<InlineDoc>(
+        InlineDoc(Doc->getInstallName(), getSingleIF(Doc.get(), Order))));
+    Output.push_back(std::move(Documents));
+  }
+  return Output;
+}
+
+void findAndAddDiff(const std::vector<InterfaceFileRef> &CollectedIRefVec,
+                    const std::vector<InterfaceFileRef> &LookupIRefVec,
+                    DiffOutput &Result, InterfaceInputOrder Order) {
+  Result.Kind = AD_Str_Vec;
+  for (const auto &IRef : CollectedIRefVec)
+    for (auto Targ : IRef.targets()) {
+      auto FoundIRef = llvm::find_if(LookupIRefVec, [&](const auto LIRef) {
+        auto FoundTarg = llvm::find(LIRef.targets(), Targ);
+        return (FoundTarg != LIRef.targets().end() &&
+                IRef.getInstallName() == LIRef.getInstallName());
+      });
+      if (FoundIRef == LookupIRefVec.end())
+        addDiffForTargSlice<DiffStrVec,
+                            DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>(
+            IRef.getInstallName(), Targ, Result, Order);
+    }
+}
+
+void findAndAddDiff(
+    const std::vector<std::pair<Target, std::string>> &CollectedPairs,
+    const std::vector<std::pair<Target, std::string>> &LookupPairs,
+    DiffOutput &Result, InterfaceInputOrder Order) {
+  Result.Kind = AD_Str_Vec;
+  for (const auto &Pair : CollectedPairs) {
+    auto FoundPair = llvm::find(LookupPairs, Pair);
+    if (FoundPair == LookupPairs.end())
+      addDiffForTargSlice<DiffStrVec,
+                          DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>(
+          StringRef(Pair.second), Pair.first, Result, Order);
+  }
+}
+
+void findAndAddDiff(InterfaceFile::const_symbol_range CollectedSyms,
+                    InterfaceFile::const_symbol_range LookupSyms,
+                    DiffOutput &Result, InterfaceInputOrder Order) {
+  Result.Kind = AD_Sym_Vec;
+  for (const auto *Sym : CollectedSyms)
+    for (const auto Targ : Sym->targets()) {
+      auto FoundSym = llvm::find_if(LookupSyms, [&](const auto LSym) {
+        auto FoundTarg = llvm::find(LSym->targets(), Targ);
+        return (Sym->getName() == LSym->getName() &&
+                Sym->getKind() == LSym->getKind() &&
+                Sym->getFlags() == LSym->getFlags() &&
+                FoundTarg != LSym->targets().end());
+      });
+      if (FoundSym == LookupSyms.end())
+        addDiffForTargSlice<DiffSymVec, SymScalar>(Sym, Targ, Result, Order);
+    }
+}
+
+template <typename T>
+DiffOutput recordDifferences(T LHS, T RHS, std::string Attr) {
+  DiffOutput Diff(Attr);
+  if (LHS.getKind() == RHS.getKind()) {
+    Diff.Kind = LHS.getKind();
+    Diff.Values.push_back(std::make_unique<T>(LHS));
+    Diff.Values.push_back(std::make_unique<T>(RHS));
+  }
+  return Diff;
+}
+
+template <typename T>
+DiffOutput recordDifferences(const std::vector<T> &LHS,
+                             const std::vector<T> &RHS, std::string Attr) {
+  DiffOutput Diff(Attr);
+  Diff.Kind = AD_Str_Vec;
+  findAndAddDiff(LHS, RHS, Diff, lhs);
+  findAndAddDiff(RHS, LHS, Diff, rhs);
+  return Diff;
+}
+
+DiffOutput recordDifferences(llvm::MachO::InterfaceFile::const_symbol_range LHS,
+                             llvm::MachO::InterfaceFile::const_symbol_range RHS,
+                             std::string Attr) {
+  DiffOutput Diff(Attr);
+  Diff.Kind = AD_Sym_Vec;
+  findAndAddDiff(LHS, RHS, Diff, lhs);
+  findAndAddDiff(RHS, LHS, Diff, rhs);
+  return Diff;
+}
+
+std::vector<DiffOutput>
+DiffEngine::findDifferences(const InterfaceFile *IFLHS,
+                            const InterfaceFile *IFRHS) {
+  std::vector<DiffOutput> Output;
+  if (IFLHS->getInstallName() != IFRHS->getInstallName())
+    Output.push_back(recordDifferences(
+        DiffScalarVal<StringRef, AD_Diff_Scalar_Str>(lhs,
+                                                     IFLHS->getInstallName()),
+        DiffScalarVal<StringRef, AD_Diff_Scalar_Str>(rhs,
+                                                     IFRHS->getInstallName()),
+        "Install Name"));
+
+  if (IFLHS->getCurrentVersion() != IFRHS->getCurrentVersion())
+    Output.push_back(recordDifferences(
+        DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>(
+            lhs, IFLHS->getCurrentVersion()),
+        DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>(
+            rhs, IFRHS->getCurrentVersion()),
+        "Current Version"));
+  if (IFLHS->getCompatibilityVersion() != IFRHS->getCompatibilityVersion())
+    Output.push_back(recordDifferences(
+        DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>(
+            lhs, IFLHS->getCompatibilityVersion()),
+        DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>(
+            rhs, IFRHS->getCompatibilityVersion()),
+        "Compatibility Version"));
+  if (IFLHS->getSwiftABIVersion() != IFRHS->getSwiftABIVersion())
+    Output.push_back(
+        recordDifferences(DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>(
+                              lhs, IFLHS->getSwiftABIVersion()),
+                          DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>(
+                              rhs, IFRHS->getSwiftABIVersion()),
+                          "Swift ABI Version"));
+  if (IFLHS->isInstallAPI() != IFRHS->isInstallAPI())
+    Output.push_back(recordDifferences(
+        DiffScalarVal<bool, AD_Diff_Scalar_Bool>(lhs, IFLHS->isInstallAPI()),
+        DiffScalarVal<bool, AD_Diff_Scalar_Bool>(rhs, IFRHS->isInstallAPI()),
+        "InstallAPI"));
+
+  if (IFLHS->isTwoLevelNamespace() != IFRHS->isTwoLevelNamespace())
+    Output.push_back(recordDifferences(DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+                                           lhs, IFLHS->isTwoLevelNamespace()),
+                                       DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+                                           rhs, IFRHS->isTwoLevelNamespace()),
+                                       "Two Level Namespace"));
+
+  if (IFLHS->isApplicationExtensionSafe() !=
+      IFRHS->isApplicationExtensionSafe())
+    Output.push_back(
+        recordDifferences(DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+                              lhs, IFLHS->isApplicationExtensionSafe()),
+                          DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+                              rhs, IFRHS->isApplicationExtensionSafe()),
+                          "Application Extension Safe"));
+
+  if (IFLHS->reexportedLibraries() != IFRHS->reexportedLibraries())
+    Output.push_back(recordDifferences(IFLHS->reexportedLibraries(),
+                                       IFRHS->reexportedLibraries(),
+                                       "Reexported Libraries"));
+
+  if (IFLHS->allowableClients() != IFRHS->allowableClients())
+    Output.push_back(recordDifferences(IFLHS->allowableClients(),
+                                       IFRHS->allowableClients(),
+                                       "Allowable Clients"));
+
+  if (IFLHS->umbrellas() != IFRHS->umbrellas())
+    Output.push_back(recordDifferences(IFLHS->umbrellas(), IFRHS->umbrellas(),
+                                       "Parent Umbrellas"));
+
+  if (!checkSymbolEquality(IFLHS->symbols(), IFRHS->symbols()))
+    Output.push_back(
+        recordDifferences(IFLHS->symbols(), IFRHS->symbols(), "Symbols"));
+
+  if (IFLHS->documents() != IFRHS->documents()) {
+    DiffOutput Docs("Inlined Reexported Frameworks/Libraries");
+    Docs.Kind = AD_Inline_Doc;
+    std::vector<StringRef> DocsInserted;
+    // Iterate through inline frameworks/libraries from interface file and find
+    // match based on install name.
+    for (auto DocLHS : IFLHS->documents()) {
+      auto Pair = llvm::find_if(IFRHS->documents(), [&](const auto &DocRHS) {
+        return (DocLHS->getInstallName() == DocRHS->getInstallName());
+      });
+      // If a match found, recursively get differences between the pair.
+      if (Pair != IFRHS->documents().end()) {
+        InlineDoc PairDiff =
+            InlineDoc(DocLHS->getInstallName(),
+                      findDifferences(DocLHS.get(), Pair->get()));
+        if (!PairDiff.DocValues.empty())
+          Docs.Values.push_back(
+              std::make_unique<InlineDoc>(std::move(PairDiff)));
+      }
+      // If a match is not found, get attributes from single item.
+      else
+        Docs.Values.push_back(std::make_unique<InlineDoc>(InlineDoc(
+            DocLHS->getInstallName(), getSingleIF(DocLHS.get(), lhs))));
+      DocsInserted.push_back(DocLHS->getInstallName());
+    }
+    for (auto DocRHS : IFRHS->documents()) {
+      auto WasGathered =
+          llvm::find_if(DocsInserted, [&](const auto &GatheredDoc) {
+            return (GatheredDoc == DocRHS->getInstallName());
+          });
+      if (WasGathered == DocsInserted.end())
+        Docs.Values.push_back(std::make_unique<InlineDoc>(InlineDoc(
+            DocRHS->getInstallName(), getSingleIF(DocRHS.get(), rhs))));
+    }
+    if (!Docs.Values.empty())
+      Output.push_back(std::move(Docs));
+  }
+  return Output;
+}
+
+template <typename T>
+void printSingleVal(std::string Indent, const DiffOutput &Attr,
+                    raw_ostream &OS) {
+  if (Attr.Values.empty())
+    return;
+  OS << Indent << Attr.Name << "\n";
+  for (auto &RawItem : Attr.Values)
+    if (T *Item = dyn_cast<T>(RawItem.get()))
+      Item->print(OS, Indent);
+}
+
+template <typename T>
+T *castValues(const std::unique_ptr<AttributeDiff> &RawAttr) {
+  T *CastAttr = cast<T>(RawAttr.get());
+  return CastAttr;
+}
+
+template <typename T> void sortTargetValues(std::vector<T> &TargValues) {
+  llvm::stable_sort(TargValues, [](const auto &ValA, const auto &ValB) {
+    return ValA.getOrder() < ValB.getOrder();
+  });
+  llvm::stable_sort(TargValues, [](const auto &ValA, const auto &ValB) {
+    return ValA.getOrder() == ValB.getOrder() && ValA.getVal() < ValB.getVal();
+  });
+}
+
+template <typename T>
+void printVecVal(std::string Indent, const DiffOutput &Attr, raw_ostream &OS) {
+  if (Attr.Values.empty())
+    return;
+
+  OS << Indent << Attr.Name << "\n";
+
+  std::vector<T *> SortedAttrs;
+
+  llvm::transform(Attr.Values, std::back_inserter(SortedAttrs), castValues<T>);
+
+  llvm::sort(SortedAttrs, [&](const auto &ValA, const auto &ValB) {
+    return ValA->Targ < ValB->Targ;
+  });
+
+  for (auto *Vec : SortedAttrs) {
+    sortTargetValues<DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>(
+        Vec->TargValues);
+    OS << Indent << "\t" << getTargetTripleName(Vec->Targ) << "\n";
+    for (auto &Item : Vec->TargValues)
+      Item.print(OS, Indent);
+  }
+}
+
+template <>
+void printVecVal<DiffSymVec>(std::string Indent, const DiffOutput &Attr,
+                             raw_ostream &OS) {
+  if (Attr.Values.empty())
+    return;
+
+  OS << Indent << Attr.Name << "\n";
+
+  std::vector<DiffSymVec *> SortedAttrs;
+
+  llvm::transform(Attr.Values, std::back_inserter(SortedAttrs),
+                  castValues<DiffSymVec>);
+
+  llvm::sort(SortedAttrs, [&](const auto &ValA, const auto &ValB) {
+    return ValA->Targ < ValB->Targ;
+  });
+  for (auto *SymVec : SortedAttrs) {
+    sortTargetValues<SymScalar>(SymVec->TargValues);
+    OS << Indent << "\t" << getTargetTripleName(SymVec->Targ) << "\n";
+    for (auto &Item : SymVec->TargValues)
+      Item.print(OS, Indent, SymVec->Targ);
+  }
+}
+
+void DiffEngine::printDifferences(raw_ostream &OS,
+                                  const std::vector<DiffOutput> &Diffs,
+                                  int IndentCounter) {
+  std::string Indent = std::string(IndentCounter, '\t');
+  for (auto &Attr : Diffs) {
+    switch (Attr.Kind) {
+    case AD_Diff_Scalar_Str:
+      if (IndentCounter == 0)
+        printSingleVal<DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>(Indent,
+                                                                     Attr, OS);
+      break;
+    case AD_Diff_Scalar_PackedVersion:
+      printSingleVal<
+          DiffScalarVal<PackedVersion, AD_Diff_Scalar_PackedVersion>>(Indent,
+                                                                      Attr, OS);
+      break;
+    case AD_Diff_Scalar_Unsigned:
+      printSingleVal<DiffScalarVal<uint8_t, AD_Diff_Scalar_Unsigned>>(Indent,
+                                                                      Attr, OS);
+      break;
+    case AD_Diff_Scalar_Bool:
+      printSingleVal<DiffScalarVal<bool, AD_Diff_Scalar_Bool>>(Indent, Attr,
+                                                               OS);
+      break;
+    case AD_Str_Vec:
+      printVecVal<DiffStrVec>(Indent, Attr, OS);
+      break;
+    case AD_Sym_Vec:
+      printVecVal<DiffSymVec>(Indent, Attr, OS);
+      break;
+    case AD_Inline_Doc:
+      if (!Attr.Values.empty()) {
+        OS << Indent << Attr.Name << "\n";
+        for (auto &Item : Attr.Values)
+          if (InlineDoc *Doc = dyn_cast<InlineDoc>(Item.get()))
+            if (!Doc->DocValues.empty()) {
+              OS << Indent << "\t" << Doc->InstallName << "\n";
+              printDifferences(OS, std::move(Doc->DocValues), 2);
+            }
+      }
+      break;
+    }
+  }
+}
+
+bool DiffEngine::compareFiles(raw_ostream &OS) {
+  const auto *IFLHS = &(FileLHS->getInterfaceFile());
+  const auto *IFRHS = &(FileRHS->getInterfaceFile());
+  if (*IFLHS == *IFRHS)
+    return false;
+  OS << "< " << std::string(IFLHS->getPath().data()) << "\n> "
+     << std::string(IFRHS->getPath().data()) << "\n\n";
+  std::vector<DiffOutput> Diffs = findDifferences(IFLHS, IFRHS);
+  printDifferences(OS, Diffs, 0);
+  return true;
+}
diff --git a/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h b/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h
new file mode 100644
index 0000000..252fbd8
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h
@@ -0,0 +1,169 @@
+//===-- DiffEngine.h - File comparator --------------------------*- 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 header defines the interface to the llvm-tapi difference engine,
+// which structurally compares two tbd files.
+//
+//===----------------------------------------------------------------------===/
+#ifndef LLVM_TOOLS_LLVM_TAPI_DIFF_DIFFENGINE_H
+#define LLVM_TOOLS_LLVM_TAPI_DIFF_DIFFENGINE_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/Object/TapiUniversal.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TextAPI/Symbol.h"
+#include "llvm/TextAPI/Target.h"
+
+namespace llvm {
+
+/// InterfaceInputOrder determines from which file the diff attribute belongs
+/// to.
+enum InterfaceInputOrder { lhs, rhs };
+
+/// DiffAttrKind is the enum that holds the concrete bases for RTTI.
+enum DiffAttrKind {
+  AD_Diff_Scalar_PackedVersion,
+  AD_Diff_Scalar_Unsigned,
+  AD_Diff_Scalar_Bool,
+  AD_Diff_Scalar_Str,
+  AD_Str_Vec,
+  AD_Sym_Vec,
+  AD_Inline_Doc,
+};
+
+/// AttributeDiff is the abstract class for RTTI.
+class AttributeDiff {
+public:
+  AttributeDiff(DiffAttrKind Kind) : Kind(Kind){};
+  virtual ~AttributeDiff(){};
+  DiffAttrKind getKind() const { return Kind; }
+
+private:
+  DiffAttrKind Kind;
+};
+
+/// DiffOutput is the representation of a diff for a single attribute.
+struct DiffOutput {
+  /// The name of the attribute.
+  std::string Name;
+  /// The kind for RTTI
+  DiffAttrKind Kind;
+  /// Different values for the attribute
+  /// from each file where a diff is present.
+  std::vector<std::unique_ptr<AttributeDiff>> Values;
+  DiffOutput(std::string Name) : Name(Name){};
+};
+
+/// DiffScalarVal is a template class for the different types of scalar values.
+template <class T, DiffAttrKind U> class DiffScalarVal : public AttributeDiff {
+public:
+  DiffScalarVal(InterfaceInputOrder Order, T Val)
+      : AttributeDiff(U), Order(Order), Val(Val){};
+
+  static bool classof(const AttributeDiff *A) { return A->getKind() == U; }
+
+  void print(raw_ostream &, std::string);
+
+  T getVal() const { return Val; }
+  InterfaceInputOrder getOrder() const { return Order; }
+
+private:
+  /// The order is the file from which the diff is found.
+  InterfaceInputOrder Order;
+  T Val;
+};
+
+/// SymScalar is the diff symbol and the order.
+class SymScalar {
+public:
+  SymScalar(InterfaceInputOrder Order, const MachO::Symbol *Sym)
+      : Order(Order), Val(Sym){};
+
+  std::string getFlagString(MachO::SymbolFlags Flags) {
+    return Flags != MachO::SymbolFlags::None
+               ? " - " + stringifySymbolFlag(Flags)
+               : stringifySymbolFlag(Flags);
+  }
+
+  void print(raw_ostream &OS, std::string Indent, MachO::Target Targ);
+
+  const MachO::Symbol *getVal() const { return Val; }
+  InterfaceInputOrder getOrder() const { return Order; }
+
+private:
+  /// The order is the file from which the diff is found.
+  InterfaceInputOrder Order;
+  const MachO::Symbol *Val;
+  StringLiteral getSymbolNamePrefix(MachO::SymbolKind Kind);
+  std::string stringifySymbolFlag(MachO::SymbolFlags Flag);
+};
+
+class DiffStrVec : public AttributeDiff {
+public:
+  MachO::Target Targ;
+  /// Values is a vector of StringRef values associated with the target.
+  std::vector<DiffScalarVal<StringRef, AD_Diff_Scalar_Str>> TargValues;
+  DiffStrVec(MachO::Target Targ) : AttributeDiff(AD_Str_Vec), Targ(Targ){};
+
+  static bool classof(const AttributeDiff *A) {
+    return A->getKind() == AD_Str_Vec;
+  }
+};
+
+class DiffSymVec : public AttributeDiff {
+public:
+  MachO::Target Targ;
+  /// Values is a vector of symbol values associated with the target.
+  std::vector<SymScalar> TargValues;
+  DiffSymVec(MachO::Target Targ) : AttributeDiff(AD_Sym_Vec), Targ(Targ){};
+
+  static bool classof(const AttributeDiff *A) {
+    return A->getKind() == AD_Sym_Vec;
+  }
+};
+
+/// InlineDoc represents an inlined framework/library in a TBD File.
+class InlineDoc : public AttributeDiff {
+public:
+  /// Install name of the framework/library.
+  std::string InstallName;
+  /// Differences found from each file.
+  std::vector<DiffOutput> DocValues;
+  InlineDoc(StringRef InstName, std::vector<DiffOutput> Diff)
+      : AttributeDiff(AD_Inline_Doc), InstallName(InstName),
+        DocValues(std::move(Diff)){};
+
+  static bool classof(const AttributeDiff *A) {
+    return A->getKind() == AD_Inline_Doc;
+  }
+};
+
+/// DiffEngine contains the methods to compare the input files and print the
+/// output of the differences found in the files.
+class DiffEngine {
+public:
+  DiffEngine(object::TapiUniversal *InputFileNameLHS,
+             object::TapiUniversal *InputFileNameRHS)
+      : FileLHS(InputFileNameLHS), FileRHS(InputFileNameRHS){};
+  bool compareFiles(raw_ostream &);
+
+private:
+  object::TapiUniversal *FileLHS;
+  object::TapiUniversal *FileRHS;
+
+  /// Function that prints the differences found in the files.
+  void printDifferences(raw_ostream &, const std::vector<DiffOutput> &, int);
+  /// Function that does the comparison of the TBD files and returns the
+  /// differences.
+  std::vector<DiffOutput> findDifferences(const MachO::InterfaceFile *,
+                                          const MachO::InterfaceFile *);
+};
+
+} // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-tapi-diff/llvm-tapi-diff.cpp b/src/llvm-project/llvm/tools/llvm-tapi-diff/llvm-tapi-diff.cpp
new file mode 100644
index 0000000..40f1eec
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-tapi-diff/llvm-tapi-diff.cpp
@@ -0,0 +1,89 @@
+//===-- llvm-tapi-diff.cpp - tbd comparator command-line driver ---*-
+// 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 file defines the command-line driver for the llvm-tapi difference
+// engine.
+//
+//===----------------------------------------------------------------------===//
+#include "DiffEngine.h"
+#include "llvm/Object/TapiUniversal.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdlib>
+
+using namespace llvm;
+using namespace MachO;
+using namespace object;
+
+namespace {
+cl::OptionCategory NMCat("llvm-tapi-diff Options");
+cl::opt<std::string> InputFileNameLHS(cl::Positional, cl::desc("<first file>"),
+                                      cl::cat(NMCat));
+cl::opt<std::string> InputFileNameRHS(cl::Positional, cl::desc("<second file>"),
+                                      cl::cat(NMCat));
+
+std::string ToolName;
+} // anonymous namespace
+
+ExitOnError ExitOnErr;
+
+void setErrorBanner(ExitOnError &ExitOnErr, std::string InputFile) {
+  ExitOnErr.setBanner(ToolName + ": error: " + InputFile + ": ");
+}
+
+Expected<std::unique_ptr<Binary>> convertFileToBinary(std::string &Filename) {
+  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
+      MemoryBuffer::getFileOrSTDIN(Filename);
+  if (BufferOrErr.getError())
+    return errorCodeToError(BufferOrErr.getError());
+  return createBinary(BufferOrErr.get()->getMemBufferRef());
+}
+
+int main(int Argc, char **Argv) {
+  InitLLVM X(Argc, Argv);
+  cl::HideUnrelatedOptions(NMCat);
+  cl::ParseCommandLineOptions(
+      Argc, Argv,
+      "This tool will compare two tbd files and return the "
+      "differences in those files.");
+  if (InputFileNameLHS.empty() || InputFileNameRHS.empty()) {
+    cl::PrintHelpMessage();
+    return EXIT_FAILURE;
+  }
+
+  ToolName = Argv[0];
+
+  setErrorBanner(ExitOnErr, InputFileNameLHS);
+  auto BinLHS = ExitOnErr(convertFileToBinary(InputFileNameLHS));
+
+  TapiUniversal *FileLHS = dyn_cast<TapiUniversal>(BinLHS.get());
+  if (!FileLHS) {
+    ExitOnErr(
+        createStringError(std::errc::executable_format_error,
+                          "Error when parsing file, unsupported file format"));
+  }
+
+  setErrorBanner(ExitOnErr, InputFileNameRHS);
+  auto BinRHS = ExitOnErr(convertFileToBinary(InputFileNameRHS));
+
+  TapiUniversal *FileRHS = dyn_cast<TapiUniversal>(BinRHS.get());
+  if (!FileRHS) {
+    ExitOnErr(
+        createStringError(std::errc::executable_format_error,
+                          "Error when parsing file, unsupported file format"));
+  }
+
+  raw_ostream &OS = outs();
+
+  return DiffEngine(FileLHS, FileRHS).compareFiles(OS);
+}
diff --git a/src/llvm-project/llvm/tools/llvm-undname/llvm-undname.cpp b/src/llvm-project/llvm/tools/llvm-undname/llvm-undname.cpp
index f9f9e05..c6714cf 100644
--- a/src/llvm-project/llvm/tools/llvm-undname/llvm-undname.cpp
+++ b/src/llvm-project/llvm/tools/llvm-undname/llvm-undname.cpp
@@ -28,28 +28,32 @@
 
 using namespace llvm;
 
+cl::OptionCategory UndNameCategory("UndName Options");
+
 cl::opt<bool> DumpBackReferences("backrefs", cl::Optional,
                                  cl::desc("dump backreferences"), cl::Hidden,
-                                 cl::init(false));
+                                 cl::init(false), cl::cat(UndNameCategory));
 cl::opt<bool> NoAccessSpecifier("no-access-specifier", cl::Optional,
                                 cl::desc("skip access specifiers"), cl::Hidden,
-                                cl::init(false));
+                                cl::init(false), cl::cat(UndNameCategory));
 cl::opt<bool> NoCallingConvention("no-calling-convention", cl::Optional,
                                   cl::desc("skip calling convention"),
-                                  cl::Hidden, cl::init(false));
+                                  cl::Hidden, cl::init(false),
+                                  cl::cat(UndNameCategory));
 cl::opt<bool> NoReturnType("no-return-type", cl::Optional,
                            cl::desc("skip return types"), cl::Hidden,
-                           cl::init(false));
+                           cl::init(false), cl::cat(UndNameCategory));
 cl::opt<bool> NoMemberType("no-member-type", cl::Optional,
                            cl::desc("skip member types"), cl::Hidden,
-                           cl::init(false));
+                           cl::init(false), cl::cat(UndNameCategory));
 cl::opt<std::string> RawFile("raw-file", cl::Optional,
-                             cl::desc("for fuzzer data"), cl::Hidden);
+                             cl::desc("for fuzzer data"), cl::Hidden,
+                             cl::cat(UndNameCategory));
 cl::opt<bool> WarnTrailing("warn-trailing", cl::Optional,
                            cl::desc("warn on trailing characters"), cl::Hidden,
-                           cl::init(false));
+                           cl::init(false), cl::cat(UndNameCategory));
 cl::list<std::string> Symbols(cl::Positional, cl::desc("<input symbols>"),
-                              cl::ZeroOrMore);
+                              cl::ZeroOrMore, cl::cat(UndNameCategory));
 
 static bool msDemangle(const std::string &S) {
   int Status;
@@ -84,6 +88,7 @@
 int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
 
+  cl::HideUnrelatedOptions({&UndNameCategory, &getColorCategory()});
   cl::ParseCommandLineOptions(argc, argv, "llvm-undname\n");
 
   if (!RawFile.empty()) {
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-account.cpp b/src/llvm-project/llvm/tools/llvm-xray/xray-account.cpp
index bde028a..1117046 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-account.cpp
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-account.cpp
@@ -459,7 +459,7 @@
   }
 
   std::error_code EC;
-  raw_fd_ostream OS(AccountOutput, EC, sys::fs::OpenFlags::OF_Text);
+  raw_fd_ostream OS(AccountOutput, EC, sys::fs::OpenFlags::OF_TextWithCRLF);
   if (EC)
     return make_error<StringError>(
         Twine("Cannot open file '") + AccountOutput + "' for writing.", EC);
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-color-helper.cpp b/src/llvm-project/llvm/tools/llvm-xray/xray-color-helper.cpp
index ea7ff35..e2cae21 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-color-helper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-color-helper.cpp
@@ -13,6 +13,7 @@
 #include "xray-color-helper.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/raw_ostream.h"
+#include <cmath>
 
 using namespace llvm;
 using namespace xray;
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-color-helper.h b/src/llvm-project/llvm/tools/llvm-xray/xray-color-helper.h
index 0940fc2..3141e90 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-color-helper.h
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-color-helper.h
@@ -13,9 +13,8 @@
 #ifndef XRAY_COLOR_HELPER_H
 #define XRAY_COLOR_HELPER_H
 
-#include <tuple>
-
 #include "llvm/ADT/ArrayRef.h"
+#include <tuple>
 
 namespace llvm {
 namespace xray {
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-converter.cpp b/src/llvm-project/llvm/tools/llvm-xray/xray-converter.cpp
index c1a623f..47cb645 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-converter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-converter.cpp
@@ -269,19 +269,14 @@
   auto CycleFreq = FH.CycleFrequency;
 
   unsigned id_counter = 0;
+  int NumOutputRecords = 0;
 
-  OS << "{\n  \"traceEvents\": [";
+  OS << "{\n  \"traceEvents\": [\n";
   DenseMap<uint32_t, StackTrieNode *> StackCursorByThreadId{};
   DenseMap<uint32_t, SmallVector<StackTrieNode *, 4>> StackRootsByThreadId{};
   DenseMap<unsigned, StackTrieNode *> StacksByStackId{};
   std::forward_list<StackTrieNode> NodeStore{};
-  int loop_count = 0;
   for (const auto &R : Records) {
-    if (loop_count++ == 0)
-      OS << "\n";
-    else
-      OS << ",\n";
-
     // Chrome trace event format always wants data in micros.
     // CyclesPerMicro = CycleHertz / 10^6
     // TSC / CyclesPerMicro == TSC * 10^6 / CycleHertz == MicroTimestamp
@@ -306,6 +301,9 @@
       // type of B for begin or E for end, thread id, process id,
       // timestamp in microseconds, and a stack frame id. The ids are logged
       // in an id dictionary after the events.
+      if (NumOutputRecords++ > 0) {
+        OS << ",\n";
+      }
       writeTraceViewerRecord(Version, OS, R.FuncId, R.TId, R.PId, Symbolize,
                              FuncIdHelper, EventTimestampUs, *StackCursor, "B");
       break;
@@ -318,7 +316,7 @@
       // (And/Or in loop termination below)
       StackTrieNode *PreviousCursor = nullptr;
       do {
-        if (PreviousCursor != nullptr) {
+        if (NumOutputRecords++ > 0) {
           OS << ",\n";
         }
         writeTraceViewerRecord(Version, OS, StackCursor->FuncId, R.TId, R.PId,
@@ -383,7 +381,7 @@
   raw_fd_ostream OS(ConvertOutput, EC,
                     ConvertOutputFormat == ConvertFormats::BINARY
                         ? sys::fs::OpenFlags::OF_None
-                        : sys::fs::OpenFlags::OF_Text);
+                        : sys::fs::OpenFlags::OF_TextWithCRLF);
   if (EC)
     return make_error<StringError>(
         Twine("Cannot open file '") + ConvertOutput + "' for writing.", EC);
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-extract.cpp b/src/llvm-project/llvm/tools/llvm-xray/xray-extract.cpp
index 8304d2d..a6ffacc 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-extract.cpp
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-extract.cpp
@@ -83,7 +83,7 @@
                       InstrumentationMapOrError.takeError());
 
   std::error_code EC;
-  raw_fd_ostream OS(ExtractOutput, EC, sys::fs::OpenFlags::OF_Text);
+  raw_fd_ostream OS(ExtractOutput, EC, sys::fs::OpenFlags::OF_TextWithCRLF);
   if (EC)
     return make_error<StringError>(
         Twine("Cannot open file '") + ExtractOutput + "' for writing.", EC);
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-graph-diff.cpp b/src/llvm-project/llvm/tools/llvm-xray/xray-graph-diff.cpp
index 11210e2..f22ea06 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-graph-diff.cpp
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-graph-diff.cpp
@@ -294,10 +294,7 @@
 }
 
 template <typename T> static bool containsNullptr(const T &Collection) {
-  for (const auto &E : Collection)
-    if (E == nullptr)
-      return true;
-  return false;
+  return llvm::is_contained(Collection, nullptr);
 }
 
 static std::string getLabel(const GraphDiffRenderer::GraphT::EdgeValueType &E,
@@ -459,7 +456,7 @@
   auto &GDR = *GDROrErr;
 
   std::error_code EC;
-  raw_fd_ostream OS(GraphDiffOutput, EC, sys::fs::OpenFlags::OF_Text);
+  raw_fd_ostream OS(GraphDiffOutput, EC, sys::fs::OpenFlags::OF_TextWithCRLF);
   if (EC)
     return make_error<StringError>(
         Twine("Cannot open file '") + GraphDiffOutput + "' for writing.", EC);
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-graph.cpp b/src/llvm-project/llvm/tools/llvm-xray/xray-graph.cpp
index 00a1807..39d2c5c 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-graph.cpp
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-graph.cpp
@@ -523,7 +523,7 @@
   auto &GR = *GROrError;
 
   std::error_code EC;
-  raw_fd_ostream OS(GraphOutput, EC, sys::fs::OpenFlags::OF_Text);
+  raw_fd_ostream OS(GraphOutput, EC, sys::fs::OpenFlags::OF_TextWithCRLF);
   if (EC)
     return make_error<StringError>(
         Twine("Cannot open file '") + GraphOutput + "' for writing.", EC);
diff --git a/src/llvm-project/llvm/tools/llvm-yaml-numeric-parser-fuzzer/yaml-numeric-parser-fuzzer.cpp b/src/llvm-project/llvm/tools/llvm-yaml-numeric-parser-fuzzer/yaml-numeric-parser-fuzzer.cpp
index 7ffc75e..c61b509 100644
--- a/src/llvm-project/llvm/tools/llvm-yaml-numeric-parser-fuzzer/yaml-numeric-parser-fuzzer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-yaml-numeric-parser-fuzzer/yaml-numeric-parser-fuzzer.cpp
@@ -9,15 +9,14 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/YAMLTraits.h"
-#include <cassert>
 #include <string>
 
-llvm::Regex Infinity("^[-+]?(\\.inf|\\.Inf|\\.INF)$");
-llvm::Regex Base8("^0o[0-7]+$");
-llvm::Regex Base16("^0x[0-9a-fA-F]+$");
-llvm::Regex Float("^[-+]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)([eE][-+]?[0-9]+)?$");
-
 inline bool isNumericRegex(llvm::StringRef S) {
+  static llvm::Regex Infinity("^[-+]?(\\.inf|\\.Inf|\\.INF)$");
+  static llvm::Regex Base8("^0o[0-7]+$");
+  static llvm::Regex Base16("^0x[0-9a-fA-F]+$");
+  static llvm::Regex Float(
+      "^[-+]?(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)([eE][-+]?[0-9]+)?$");
 
   if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN"))
     return true;
diff --git a/src/llvm-project/llvm/tools/lto/CMakeLists.txt b/src/llvm-project/llvm/tools/lto/CMakeLists.txt
index 2963f97..0af29ad 100644
--- a/src/llvm-project/llvm/tools/lto/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/lto/CMakeLists.txt
@@ -21,8 +21,16 @@
 
 set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/lto.exports)
 
-add_llvm_library(LTO SHARED INSTALL_WITH_TOOLCHAIN ${SOURCES} DEPENDS
-    intrinsics_gen)
+if(CMAKE_SYSTEM_NAME STREQUAL AIX)
+    set(LTO_LIBRARY_TYPE MODULE)
+    set(LTO_LIBRARY_NAME libLTO)
+  else()
+    set(LTO_LIBRARY_TYPE SHARED)
+    set(LTO_LIBRARY_NAME LTO)
+endif()
+
+add_llvm_library(${LTO_LIBRARY_NAME} ${LTO_LIBRARY_TYPE} INSTALL_WITH_TOOLCHAIN
+    ${SOURCES} DEPENDS intrinsics_gen)
 
 install(FILES ${LLVM_MAIN_INCLUDE_DIR}/llvm-c/lto.h
   DESTINATION include/llvm-c
diff --git a/src/llvm-project/llvm/tools/lto/lto.cpp b/src/llvm-project/llvm/tools/lto/lto.cpp
index 688c7f2..2a560a0 100644
--- a/src/llvm-project/llvm/tools/lto/lto.cpp
+++ b/src/llvm-project/llvm/tools/lto/lto.cpp
@@ -63,8 +63,12 @@
 // *** Not thread safe ***
 static bool initialized = false;
 
-// Holds the command-line option parsing state of the LTO module.
-static bool parsedOptions = false;
+// Represent the state of parsing command line debug options.
+static enum class OptParsingState {
+  NotParsed, // Initial state.
+  Early,     // After lto_set_debug_options is called.
+  Done       // After maybeParseOptions is called.
+} optionParsingState = OptParsingState::NotParsed;
 
 static LLVMContext *LTOContext = nullptr;
 
@@ -418,10 +422,11 @@
 }
 
 static void maybeParseOptions(lto_code_gen_t cg) {
-  if (!parsedOptions) {
+  if (optionParsingState != OptParsingState::Done) {
+    // Parse options if any were set by the lto_codegen_debug_options* function.
     unwrap(cg)->parseCodeGenDebugOptions();
     lto_add_attrs(cg);
-    parsedOptions = true;
+    optionParsingState = OptParsingState::Done;
   }
 }
 
@@ -460,7 +465,22 @@
   return !unwrap(cg)->compile_to_file(name);
 }
 
+void lto_set_debug_options(const char *const *options, int number) {
+  assert(optionParsingState == OptParsingState::NotParsed &&
+         "option processing already happened");
+  // Need to put each suboption in a null-terminated string before passing to
+  // parseCommandLineOptions().
+  std::vector<std::string> Options;
+  for (int i = 0; i < number; ++i)
+    Options.push_back(options[i]);
+
+  llvm::parseCommandLineOptions(Options);
+  optionParsingState = OptParsingState::Early;
+}
+
 void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) {
+  assert(optionParsingState != OptParsingState::Early &&
+         "early option processing already happened");
   SmallVector<StringRef, 4> Options;
   for (std::pair<StringRef, StringRef> o = getToken(opt); !o.first.empty();
        o = getToken(o.second))
@@ -471,6 +491,8 @@
 
 void lto_codegen_debug_options_array(lto_code_gen_t cg,
                                      const char *const *options, int number) {
+  assert(optionParsingState != OptParsingState::Early &&
+         "early option processing already happened");
   SmallVector<StringRef, 4> Options;
   for (int i = 0; i < number; ++i)
     Options.push_back(options[i]);
@@ -564,8 +586,7 @@
   // if options were requested, set them
   if (number && options) {
     std::vector<const char *> CodegenArgv(1, "libLTO");
-    for (auto Arg : ArrayRef<const char *>(options, number))
-      CodegenArgv.push_back(Arg);
+    append_range(CodegenArgv, ArrayRef<const char *>(options, number));
     cl::ParseCommandLineOptions(CodegenArgv.size(), CodegenArgv.data());
   }
 }
diff --git a/src/llvm-project/llvm/tools/lto/lto.exports b/src/llvm-project/llvm/tools/lto/lto.exports
index 1f0a6b2..1948bba 100644
--- a/src/llvm-project/llvm/tools/lto/lto.exports
+++ b/src/llvm-project/llvm/tools/lto/lto.exports
@@ -43,6 +43,7 @@
 lto_codegen_compile_optimized
 lto_codegen_set_should_internalize
 lto_codegen_set_should_embed_uselists
+lto_set_debug_options
 LLVMCreateDisasm
 LLVMCreateDisasmCPU
 LLVMDisasmDispose
diff --git a/src/llvm-project/llvm/tools/obj2yaml/elf2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/elf2yaml.cpp
index c85e265..028758d 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -31,6 +31,7 @@
 
   DenseMap<StringRef, uint32_t> UsedSectionNames;
   std::vector<std::string> SectionNames;
+  Optional<uint32_t> ShStrTabIndex;
 
   DenseMap<StringRef, uint32_t> UsedSymbolNames;
   std::vector<std::string> SymbolNames;
@@ -289,6 +290,13 @@
   Sections = *SectionsOrErr;
   SectionNames.resize(Sections.size());
 
+  if (Sections.size() > 0) {
+    ShStrTabIndex = Obj.getHeader().e_shstrndx;
+    if (*ShStrTabIndex == ELF::SHN_XINDEX)
+      ShStrTabIndex = Sections[0].sh_link;
+    // TODO: Set EShStrndx if the value doesn't represent a real section.
+  }
+
   // Normally an object that does not have sections has e_shnum == 0.
   // Also, e_shnum might be 0, when the the number of entries in the section
   // header table is larger than or equal to SHN_LORESERVE (0xff00). In this
@@ -398,6 +406,29 @@
     return !shouldPrintSection(S, Sections[S.OriginalSecNdx], Y->DWARF);
   });
 
+  // The section header string table by default is assumed to be called
+  // ".shstrtab" and be in its own unique section. However, it's possible for it
+  // to be called something else and shared with another section. If the name
+  // isn't the default, provide this in the YAML.
+  if (ShStrTabIndex && *ShStrTabIndex != ELF::SHN_UNDEF &&
+      *ShStrTabIndex < Sections.size()) {
+    StringRef ShStrtabName;
+    if (SymTab && SymTab->sh_link == *ShStrTabIndex) {
+      // Section header string table is shared with the symbol table. Use that
+      // section's name (usually .strtab).
+      ShStrtabName = cantFail(Obj.getSectionName(Sections[SymTab->sh_link]));
+    } else if (DynSymTab && DynSymTab->sh_link == *ShStrTabIndex) {
+      // Section header string table is shared with the dynamic symbol table.
+      // Use that section's name (usually .dynstr).
+      ShStrtabName = cantFail(Obj.getSectionName(Sections[DynSymTab->sh_link]));
+    } else {
+      // Otherwise, the section name potentially needs uniquifying.
+      ShStrtabName = cantFail(getUniquedSectionName(Sections[*ShStrTabIndex]));
+    }
+    if (ShStrtabName != ".shstrtab")
+      Y->Header.SectionHeaderStringTable = ShStrtabName;
+  }
+
   Y->Chunks = std::move(Chunks);
   return Y.release();
 }
@@ -486,6 +517,12 @@
 
     if (ELFYAML::RawContentSection *RawSec =
             dyn_cast<ELFYAML::RawContentSection>(C.get())) {
+      // FIXME: The dumpDebug* functions should take the content as stored in
+      // RawSec. Currently, they just use the last section with the matching
+      // name, which defeats this attempt to skip reading a section header
+      // string table with the same name as a DWARF section.
+      if (ShStrTabIndex && RawSec->OriginalSecNdx == *ShStrTabIndex)
+        continue;
       Error Err = Error::success();
       cantFail(std::move(Err));
 
@@ -852,16 +889,16 @@
   DataExtractor::Cursor Cur(0);
   while (Cur && Cur.tell() < Content.size()) {
     uint64_t Address = Data.getAddress(Cur);
-    uint32_t NumBlocks = Data.getULEB128(Cur);
+    uint64_t NumBlocks = Data.getULEB128(Cur);
     std::vector<ELFYAML::BBAddrMapEntry::BBEntry> BBEntries;
     // Read the specified number of BB entries, or until decoding fails.
-    for (uint32_t BlockID = 0; Cur && BlockID < NumBlocks; ++BlockID) {
-      uint32_t Offset = Data.getULEB128(Cur);
-      uint32_t Size = Data.getULEB128(Cur);
-      uint32_t Metadata = Data.getULEB128(Cur);
+    for (uint64_t BlockID = 0; Cur && BlockID < NumBlocks; ++BlockID) {
+      uint64_t Offset = Data.getULEB128(Cur);
+      uint64_t Size = Data.getULEB128(Cur);
+      uint64_t Metadata = Data.getULEB128(Cur);
       BBEntries.push_back({Offset, Size, Metadata});
     }
-    Entries.push_back({Address, BBEntries});
+    Entries.push_back({Address, /*NumBlocks=*/{}, BBEntries});
   }
 
   if (!Cur) {
@@ -985,41 +1022,31 @@
   if (!ContentOrErr)
     return ContentOrErr.takeError();
   ArrayRef<uint8_t> Content = *ContentOrErr;
-
+  const uint32_t SizeOfEntry = ELFYAML::getDefaultShEntSize<ELFT>(
+      Obj.getHeader().e_machine, S->Type, S->Name);
   // Dump the section by using the Content key when it is truncated.
   // There is no need to create either "Content" or "Entries" fields when the
   // section is empty.
-  if (Content.empty() || Content.size() % 16 != 0) {
+  if (Content.empty() || Content.size() % SizeOfEntry != 0) {
     if (!Content.empty())
       S->Content = yaml::BinaryRef(Content);
     return S.release();
   }
 
-  std::vector<ELFYAML::CallGraphEntry> Entries(Content.size() / 16);
+  std::vector<ELFYAML::CallGraphEntryWeight> Entries(Content.size() /
+                                                     SizeOfEntry);
   DataExtractor Data(Content, Obj.isLE(), /*AddressSize=*/0);
   DataExtractor::Cursor Cur(0);
-  auto ReadEntry = [&](ELFYAML::CallGraphEntry &E) {
-    uint32_t FromSymIndex = Data.getU32(Cur);
-    uint32_t ToSymIndex = Data.getU32(Cur);
+  auto ReadEntry = [&](ELFYAML::CallGraphEntryWeight &E) {
     E.Weight = Data.getU64(Cur);
     if (!Cur) {
       consumeError(Cur.takeError());
       return false;
     }
-
-    Expected<StringRef> From = getSymbolName(Shdr->sh_link, FromSymIndex);
-    Expected<StringRef> To = getSymbolName(Shdr->sh_link, ToSymIndex);
-    if (From && To) {
-      E.From = *From;
-      E.To = *To;
-      return true;
-    }
-    consumeError(From.takeError());
-    consumeError(To.takeError());
-    return false;
+    return true;
   };
 
-  for (ELFYAML::CallGraphEntry &E : Entries) {
+  for (ELFYAML::CallGraphEntryWeight &E : Entries) {
     if (ReadEntry(E))
       continue;
     S->Content = yaml::BinaryRef(Content);
@@ -1191,7 +1218,7 @@
 
     Elf_Note Note(*Header);
     Entries.push_back(
-        {Note.getName(), Note.getDesc(), (llvm::yaml::Hex32)Note.getType()});
+        {Note.getName(), Note.getDesc(), (ELFYAML::ELF_NT)Note.getType()});
 
     Content = Content.drop_front(Header->getSize());
   }
diff --git a/src/llvm-project/llvm/tools/obj2yaml/macho2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/macho2yaml.cpp
index 4934743..b7289bf 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/macho2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/macho2yaml.cpp
@@ -226,7 +226,7 @@
   auto Start = LoadCmd.Ptr + sizeof(StructType);
   auto MaxSize = LoadCmd.C.cmdsize - sizeof(StructType);
   auto Size = strnlen(Start, MaxSize);
-  LC.PayloadString = StringRef(Start, Size).str();
+  LC.Content = StringRef(Start, Size).str();
   return Start + Size;
 }
 
diff --git a/src/llvm-project/llvm/tools/obj2yaml/obj2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/obj2yaml.cpp
index da70450..ff6b470 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/obj2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/obj2yaml.cpp
@@ -36,7 +36,7 @@
 
 static Error dumpInput(StringRef File) {
   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
-      MemoryBuffer::getFileOrSTDIN(File, /*FileSize=*/-1,
+      MemoryBuffer::getFileOrSTDIN(File, /*IsText=*/false,
                                    /*RequiresNullTerminator=*/false);
   if (std::error_code EC = FileOrErr.getError())
     return errorCodeToError(EC);
diff --git a/src/llvm-project/llvm/tools/obj2yaml/wasm2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/wasm2yaml.cpp
index 205ec1e..5b4f672 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/wasm2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/wasm2yaml.cpp
@@ -34,7 +34,7 @@
 static WasmYAML::Limits makeLimits(const wasm::WasmLimits &Limits) {
   WasmYAML::Limits L;
   L.Flags = Limits.Flags;
-  L.Initial = Limits.Initial;
+  L.Minimum = Limits.Minimum;
   L.Maximum = Limits.Maximum;
   return L;
 }
@@ -100,7 +100,7 @@
         SegmentInfo.Name = Segment.Data.Name;
         SegmentInfo.Index = SegmentIndex;
         SegmentInfo.Alignment = Segment.Data.Alignment;
-        SegmentInfo.Flags = Segment.Data.LinkerFlags;
+        SegmentInfo.Flags = Segment.Data.LinkingFlags;
         LinkingSec->SegmentInfos.push_back(SegmentInfo);
       }
       if (Segment.Data.Comdat != UINT32_MAX) {
@@ -132,7 +132,7 @@
       case wasm::WASM_SYMBOL_TYPE_FUNCTION:
       case wasm::WASM_SYMBOL_TYPE_GLOBAL:
       case wasm::WASM_SYMBOL_TYPE_TABLE:
-      case wasm::WASM_SYMBOL_TYPE_EVENT:
+      case wasm::WASM_SYMBOL_TYPE_TAG:
         Info.ElementIndex = Symbol.ElementIndex;
         break;
       case wasm::WASM_SYMBOL_TYPE_SECTION:
@@ -238,9 +238,9 @@
           Im.GlobalImport.Type = Import.Global.Type;
           Im.GlobalImport.Mutable = Import.Global.Mutable;
           break;
-        case wasm::WASM_EXTERNAL_EVENT:
-          Im.EventImport.Attribute = Import.Event.Attribute;
-          Im.EventImport.SigIndex = Import.Event.SigIndex;
+        case wasm::WASM_EXTERNAL_TAG:
+          Im.TagImport.Attribute = Import.Tag.Attribute;
+          Im.TagImport.SigIndex = Import.Tag.SigIndex;
           break;
         case wasm::WASM_EXTERNAL_TABLE:
           // FIXME: Currently we always output an index of 0 for any imported
@@ -280,16 +280,16 @@
       S = std::move(MemorySec);
       break;
     }
-    case wasm::WASM_SEC_EVENT: {
-      auto EventSec = std::make_unique<WasmYAML::EventSection>();
-      for (auto &Event : Obj.events()) {
-        WasmYAML::Event E;
-        E.Index = Event.Index;
-        E.Attribute = Event.Type.Attribute;
-        E.SigIndex = Event.Type.SigIndex;
-        EventSec->Events.push_back(E);
+    case wasm::WASM_SEC_TAG: {
+      auto TagSec = std::make_unique<WasmYAML::TagSection>();
+      for (auto &Tag : Obj.tags()) {
+        WasmYAML::Tag T;
+        T.Index = Tag.Index;
+        T.Attribute = Tag.Type.Attribute;
+        T.SigIndex = Tag.Type.SigIndex;
+        TagSec->Tags.push_back(T);
       }
-      S = std::move(EventSec);
+      S = std::move(TagSec);
       break;
     }
     case wasm::WASM_SEC_GLOBAL: {
@@ -327,11 +327,11 @@
       auto ElemSec = std::make_unique<WasmYAML::ElemSection>();
       for (auto &Segment : Obj.elements()) {
         WasmYAML::ElemSegment Seg;
-        Seg.TableIndex = Segment.TableIndex;
+        Seg.Flags = Segment.Flags;
+        Seg.TableNumber = Segment.TableNumber;
+        Seg.ElemKind = Segment.ElemKind;
         Seg.Offset = Segment.Offset;
-        for (auto &Func : Segment.Functions) {
-          Seg.Functions.push_back(Func);
-        }
+        append_range(Seg.Functions, Segment.Functions);
         ElemSec->Segments.push_back(Seg);
       }
       S = std::move(ElemSec);
diff --git a/src/llvm-project/llvm/tools/obj2yaml/xcoff2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/xcoff2yaml.cpp
index dd9d8e8..0309856 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/xcoff2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/xcoff2yaml.cpp
@@ -55,7 +55,7 @@
 
   for (const SymbolRef &S : Obj.symbols()) {
     DataRefImpl SymbolDRI = S.getRawDataRefImpl();
-    const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI);
+    const XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI);
     XCOFFYAML::Symbol Sym;
 
     Expected<StringRef> SymNameRefOrErr = Obj.getSymbolName(SymbolDRI);
@@ -64,18 +64,18 @@
     }
     Sym.SymbolName = SymNameRefOrErr.get();
 
-    Sym.Value = SymbolEntPtr->Value;
+    Sym.Value = SymbolEntRef.getValue();
 
     Expected<StringRef> SectionNameRefOrErr =
-        Obj.getSymbolSectionName(SymbolEntPtr);
+        Obj.getSymbolSectionName(SymbolEntRef);
     if (!SectionNameRefOrErr)
       return errorToErrorCode(SectionNameRefOrErr.takeError());
 
     Sym.SectionName = SectionNameRefOrErr.get();
 
-    Sym.Type = SymbolEntPtr->SymbolType;
-    Sym.StorageClass = SymbolEntPtr->StorageClass;
-    Sym.NumberOfAuxEntries = SymbolEntPtr->NumberOfAuxEntries;
+    Sym.Type = SymbolEntRef.getSymbolType();
+    Sym.StorageClass = SymbolEntRef.getStorageClass();
+    Sym.NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();
     Symbols.push_back(Sym);
   }
 
diff --git a/src/llvm-project/llvm/tools/opt/NewPMDriver.cpp b/src/llvm-project/llvm/tools/opt/NewPMDriver.cpp
index 401a58f..8b1fbd0 100644
--- a/src/llvm-project/llvm/tools/opt/NewPMDriver.cpp
+++ b/src/llvm-project/llvm/tools/opt/NewPMDriver.cpp
@@ -52,9 +52,19 @@
                    cl::value_desc("filename"));
 } // namespace llvm
 
-static cl::opt<bool>
-    DebugPM("debug-pass-manager", cl::Hidden,
-            cl::desc("Print pass management debugging information"));
+enum class DebugLogging { None, Normal, Verbose, Quiet };
+
+static cl::opt<DebugLogging> DebugPM(
+    "debug-pass-manager", cl::Hidden, cl::ValueOptional,
+    cl::desc("Print pass management debugging information"),
+    cl::init(DebugLogging::None),
+    cl::values(
+        clEnumValN(DebugLogging::Normal, "", ""),
+        clEnumValN(DebugLogging::Quiet, "quiet",
+                   "Skip printing info about analyses"),
+        clEnumValN(
+            DebugLogging::Verbose, "verbose",
+            "Print extra information about adaptors and pass managers")));
 
 static cl::list<std::string>
     PassPlugins("load-pass-plugin",
@@ -121,11 +131,13 @@
 // Individual pipeline tuning options.
 extern cl::opt<bool> DisableLoopUnrolling;
 
+namespace llvm {
 extern cl::opt<PGOKind> PGOKindFlag;
 extern cl::opt<std::string> ProfileFile;
 extern cl::opt<CSPGOKind> CSPGOKindFlag;
 extern cl::opt<std::string> CSProfileGenFile;
 extern cl::opt<bool> DisableBasicAA;
+} // namespace llvm
 
 static cl::opt<std::string>
     ProfileRemappingFile("profile-remapping-file",
@@ -137,10 +149,6 @@
 static cl::opt<bool> PseudoProbeForProfiling(
     "new-pm-pseudo-probe-for-profiling", cl::init(false), cl::Hidden,
     cl::desc("Emit pseudo probes to enable PGO profile generation."));
-static cl::opt<bool> UniqueInternalLinkageNames(
-    "new-pm-unique-internal-linkage-names", cl::init(false), cl::Hidden,
-    cl::desc("Uniqueify Internal Linkage Symbol Names by appending the MD5 "
-             "hash of the module path."));
 /// @}}
 
 template <typename PassManagerT>
@@ -235,7 +243,7 @@
                            bool ShouldPreserveAssemblyUseListOrder,
                            bool ShouldPreserveBitcodeUseListOrder,
                            bool EmitSummaryIndex, bool EmitModuleHash,
-                           bool EnableDebugify, bool Coroutines) {
+                           bool EnableDebugify) {
   bool VerifyEachPass = VK == VK_VerifyEachPass;
 
   Optional<PGOOptions> P;
@@ -279,9 +287,18 @@
       P->CSAction = PGOOptions::CSIRUse;
     }
   }
+  LoopAnalysisManager LAM;
+  FunctionAnalysisManager FAM;
+  CGSCCAnalysisManager CGAM;
+  ModuleAnalysisManager MAM;
+
   PassInstrumentationCallbacks PIC;
-  StandardInstrumentations SI(DebugPM, VerifyEachPass);
-  SI.registerCallbacks(PIC);
+  PrintPassOptions PrintPassOpts;
+  PrintPassOpts.Verbose = DebugPM == DebugLogging::Verbose;
+  PrintPassOpts.SkipAnalyses = DebugPM == DebugLogging::Quiet;
+  StandardInstrumentations SI(DebugPM != DebugLogging::None, VerifyEachPass,
+                              PrintPassOpts);
+  SI.registerCallbacks(PIC, &FAM);
   DebugifyEachInstrumentation Debugify;
   if (DebugifyEach)
     Debugify.registerCallbacks(PIC);
@@ -291,9 +308,7 @@
   // to false above so we shouldn't necessarily need to check whether or not the
   // option has been enabled.
   PTO.LoopUnrolling = !DisableLoopUnrolling;
-  PTO.Coroutines = Coroutines;
-  PTO.UniqueLinkageNames = UniqueInternalLinkageNames;
-  PassBuilder PB(DebugPM, TM, PTO, P, &PIC);
+  PassBuilder PB(TM, PTO, P, &PIC);
   registerEPCallbacks(PB);
 
   // Load requested pass plugins and let them register pass builder callbacks
@@ -378,11 +393,6 @@
     }
   }
 
-  LoopAnalysisManager LAM(DebugPM);
-  FunctionAnalysisManager FAM(DebugPM);
-  CGSCCAnalysisManager CGAM(DebugPM);
-  ModuleAnalysisManager MAM(DebugPM);
-
   // Register the AA manager first so that our version is the one used.
   FAM.registerPass([&] { return std::move(AA); });
   // Register our TargetLibraryInfoImpl.
@@ -395,7 +405,7 @@
   PB.registerLoopAnalyses(LAM);
   PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
 
-  ModulePassManager MPM(DebugPM);
+  ModulePassManager MPM;
   if (VK > VK_NoVerifier)
     MPM.addPass(VerifierPass());
   if (EnableDebugify)
@@ -463,3 +473,8 @@
 
   return true;
 }
+
+void llvm::printPasses(raw_ostream &OS) {
+  PassBuilder PB;
+  PB.printPassNames(OS);
+}
diff --git a/src/llvm-project/llvm/tools/opt/NewPMDriver.h b/src/llvm-project/llvm/tools/opt/NewPMDriver.h
index 87a71ce..056f7d6 100644
--- a/src/llvm-project/llvm/tools/opt/NewPMDriver.h
+++ b/src/llvm-project/llvm/tools/opt/NewPMDriver.h
@@ -54,6 +54,8 @@
 enum CSPGOKind { NoCSPGO, CSInstrGen, CSInstrUse };
 }
 
+void printPasses(raw_ostream &OS);
+
 /// Driver function to run the new pass manager over a module.
 ///
 /// This function only exists factored away from opt.cpp in order to prevent
@@ -71,7 +73,7 @@
                      bool ShouldPreserveAssemblyUseListOrder,
                      bool ShouldPreserveBitcodeUseListOrder,
                      bool EmitSummaryIndex, bool EmitModuleHash,
-                     bool EnableDebugify, bool Coroutines);
+                     bool EnableDebugify);
 } // namespace llvm
 
 #endif
diff --git a/src/llvm-project/llvm/tools/opt/opt.cpp b/src/llvm-project/llvm/tools/opt/opt.cpp
index 5cb59f8..094f517 100644
--- a/src/llvm-project/llvm/tools/opt/opt.cpp
+++ b/src/llvm-project/llvm/tools/opt/opt.cpp
@@ -66,14 +66,15 @@
 
 // The OptimizationList is automatically populated with registered Passes by the
 // PassNameParser.
-//
-static cl::list<const PassInfo*, bool, PassNameParser>
-PassList(cl::desc("Optimizations available:"));
+static cl::list<const PassInfo *, bool, PassNameParser> PassList(cl::desc(
+    "Optimizations available (use '-passes=' for the new pass manager)"));
 
-static cl::opt<bool>
-    EnableNewPassManager("enable-new-pm",
-                         cl::desc("Enable the new pass manager"),
-                         cl::init(LLVM_ENABLE_NEW_PASS_MANAGER));
+static cl::opt<bool> EnableNewPassManager(
+    "enable-new-pm",
+    cl::desc("Enable the new pass manager, translating "
+             "'opt -foo' to 'opt -passes=foo'. This is strictly for the new PM "
+             "migration, use '-passes=' when possible."),
+    cl::init(LLVM_ENABLE_NEW_PASS_MANAGER));
 
 // This flag specifies a textual description of the optimization pass pipeline
 // to run over the module. This flag switches opt to use the new pass manager
@@ -81,11 +82,14 @@
 // pass management.
 static cl::opt<std::string> PassPipeline(
     "passes",
-    cl::desc("A textual description of the pass pipeline for optimizing"),
-    cl::Hidden);
+    cl::desc(
+        "A textual description of the pass pipeline. To have analysis passes "
+        "available before a certain pass, add 'require<foo-analysis>'."));
 
-// Other command line options...
-//
+static cl::opt<bool> PrintPasses("print-passes",
+                                 cl::desc("Print available passes that can be "
+                                          "specified in -passes=foo and exit"));
+
 static cl::opt<std::string>
 InputFilename(cl::Positional, cl::desc("<input bitcode file>"),
     cl::init("-"), cl::value_desc("filename"));
@@ -142,44 +146,46 @@
     StripNamedMetadata("strip-named-metadata",
                        cl::desc("Strip module-level named metadata"));
 
-static cl::opt<bool> DisableInline("disable-inlining",
-                                   cl::desc("Do not run the inliner pass"));
+static cl::opt<bool>
+    DisableInline("disable-inlining",
+                  cl::desc("Do not run the inliner pass (legacy PM only)"));
 
 static cl::opt<bool>
 DisableOptimizations("disable-opt",
                      cl::desc("Do not run any optimization passes"));
 
-static cl::opt<bool>
-StandardLinkOpts("std-link-opts",
-                 cl::desc("Include the standard link time optimizations"));
+static cl::opt<bool> StandardLinkOpts(
+    "std-link-opts",
+    cl::desc("Include the standard link time optimizations (legacy PM only)"));
 
 static cl::opt<bool>
-OptLevelO0("O0",
-  cl::desc("Optimization level 0. Similar to clang -O0"));
+    OptLevelO0("O0", cl::desc("Optimization level 0. Similar to clang -O0. "
+                              "Use -passes='default<O0>' for the new PM"));
 
 static cl::opt<bool>
-OptLevelO1("O1",
-           cl::desc("Optimization level 1. Similar to clang -O1"));
+    OptLevelO1("O1", cl::desc("Optimization level 1. Similar to clang -O1. "
+                              "Use -passes='default<O1>' for the new PM"));
 
 static cl::opt<bool>
-OptLevelO2("O2",
-           cl::desc("Optimization level 2. Similar to clang -O2"));
+    OptLevelO2("O2", cl::desc("Optimization level 2. Similar to clang -O2. "
+                              "Use -passes='default<O2>' for the new PM"));
 
 static cl::opt<bool>
-OptLevelOs("Os",
-           cl::desc("Like -O2 with extra optimizations for size. Similar to clang -Os"));
+    OptLevelOs("Os", cl::desc("Like -O2 but size-conscious. Similar to clang "
+                              "-Os. Use -passes='default<Os>' for the new PM"));
+
+static cl::opt<bool> OptLevelOz(
+    "Oz",
+    cl::desc("Like -O2 but optimize for code size above all else. Similar to "
+             "clang -Oz. Use -passes='default<Oz>' for the new PM"));
 
 static cl::opt<bool>
-OptLevelOz("Oz",
-           cl::desc("Like -Os but reduces code size further. Similar to clang -Oz"));
+    OptLevelO3("O3", cl::desc("Optimization level 3. Similar to clang -O3. "
+                              "Use -passes='default<O3>' for the new PM"));
 
-static cl::opt<bool>
-OptLevelO3("O3",
-           cl::desc("Optimization level 3. Similar to clang -O3"));
-
-static cl::opt<unsigned>
-CodeGenOptLevel("codegen-opt-level",
-                cl::desc("Override optimization level for codegen hooks"));
+static cl::opt<unsigned> CodeGenOptLevel(
+    "codegen-opt-level",
+    cl::desc("Override optimization level for codegen hooks, legacy PM only"));
 
 static cl::opt<std::string>
 TargetTriple("mtriple", cl::desc("Override target triple for module"));
@@ -205,13 +211,31 @@
                 cl::ZeroOrMore);
 
 static cl::opt<bool>
-AnalyzeOnly("analyze", cl::desc("Only perform analysis, no optimization"));
+    AnalyzeOnly("analyze", cl::desc("Only perform analysis, no optimization. "
+                                    "Legacy pass manager only."));
 
 static cl::opt<bool> EnableDebugify(
     "enable-debugify",
     cl::desc(
         "Start the pipeline with debugify and end it with check-debugify"));
 
+static cl::opt<bool> VerifyDebugInfoPreserve(
+    "verify-debuginfo-preserve",
+    cl::desc("Start the pipeline with collecting and end it with checking of "
+             "debug info preservation."));
+
+static cl::opt<bool> VerifyEachDebugInfoPreserve(
+    "verify-each-debuginfo-preserve",
+    cl::desc("Start each pass with collecting and end it with checking of "
+             "debug info preservation."));
+
+static cl::opt<std::string>
+    VerifyDIPreserveExport("verify-di-preserve-export",
+                   cl::desc("Export debug info preservation failures into "
+                            "specified (JSON) file (should be abs path as we use"
+                            " append mode to insert new JSON objects)"),
+                   cl::value_desc("filename"), cl::init(""));
+
 static cl::opt<bool>
 PrintBreakpoints("print-breakpoints-for-testing",
                  cl::desc("Print select breakpoints location for testing"));
@@ -231,10 +255,10 @@
     cl::desc("Preserve use-list order when writing LLVM assembly."),
     cl::init(false), cl::Hidden);
 
-static cl::opt<bool>
-    RunTwice("run-twice",
-             cl::desc("Run all passes twice, re-using the same pass manager."),
-             cl::init(false), cl::Hidden);
+static cl::opt<bool> RunTwice("run-twice",
+                              cl::desc("Run all passes twice, re-using the "
+                                       "same pass manager (legacy PM only)."),
+                              cl::init(false), cl::Hidden);
 
 static cl::opt<bool> DiscardValueNames(
     "discard-value-names",
@@ -289,6 +313,7 @@
     cl::desc("The format used for serializing remarks (default: YAML)"),
     cl::value_desc("format"), cl::init("yaml"));
 
+namespace llvm {
 cl::opt<PGOKind>
     PGOKindFlag("pgo-kind", cl::init(NoPGO), cl::Hidden,
                 cl::desc("The kind of profile guided optimization"),
@@ -317,6 +342,7 @@
     "cs-profilegen-file",
     cl::desc("Path to the instrumented context sensitive profile."),
     cl::Hidden);
+} // namespace llvm
 
 static inline void addPass(legacy::PassManagerBase &PM, Pass *P) {
   // Add the pass to the pass manager...
@@ -477,9 +503,8 @@
       "amdgpu-unify-metadata",
       "amdgpu-printf-runtime-binding",
       "amdgpu-always-inline"};
-  for (const auto &P : PassNameExactToIgnore)
-    if (Pass == P)
-      return false;
+  if (llvm::is_contained(PassNameExactToIgnore, Pass))
+    return false;
 
   std::vector<StringRef> PassNamePrefix = {
       "x86-",  "xcore-", "wasm-",    "systemz-", "ppc-",    "nvvm-",   "nvptx-",
@@ -490,24 +515,22 @@
       "safe-stack",           "cost-model",
       "codegenprepare",       "interleaved-load-combine",
       "unreachableblockelim", "verify-safepoint-ir",
-      "divergence",           "atomic-expand",
+      "atomic-expand",        "expandvp",
       "hardware-loops",       "type-promotion",
       "mve-tail-predication", "interleaved-access",
       "global-merge",         "pre-isel-intrinsic-lowering",
       "expand-reductions",    "indirectbr-expand",
       "generic-to-nvvm",      "expandmemcmp",
       "loop-reduce",          "lower-amx-type",
-      "polyhedral-info"};
+      "pre-amx-config",       "lower-amx-intrinsics",
+      "polyhedral-info",      "replace-with-veclib"};
   for (const auto &P : PassNamePrefix)
     if (Pass.startswith(P))
       return true;
   for (const auto &P : PassNameContain)
     if (Pass.contains(P))
       return true;
-  for (const auto &P : PassNameExact)
-    if (Pass == P)
-      return true;
-  return false;
+  return llvm::is_contained(PassNameExact, Pass);
 }
 
 // For use in NPM transition.
@@ -529,8 +552,6 @@
   // Enable debug stream buffering.
   EnableDebugBuffering = true;
 
-  LLVMContext Context;
-
   InitializeAllTargets();
   InitializeAllTargetMCs();
   InitializeAllAsmPrinters();
@@ -570,10 +591,12 @@
   initializePostInlineEntryExitInstrumenterPass(Registry);
   initializeUnreachableBlockElimLegacyPassPass(Registry);
   initializeExpandReductionsPass(Registry);
+  initializeExpandVectorPredicationPass(Registry);
   initializeWasmEHPreparePass(Registry);
   initializeWriteBitcodePassPass(Registry);
   initializeHardwareLoopsPass(Registry);
   initializeTypePromotionPass(Registry);
+  initializeReplaceWithVeclibLegacyPass(Registry);
 
 #ifdef BUILD_EXAMPLES
   initializeExampleIRTransforms(Registry);
@@ -582,11 +605,21 @@
   cl::ParseCommandLineOptions(argc, argv,
     "llvm .bc -> .bc modular optimizer and analysis printer\n");
 
+  LLVMContext Context;
+
   if (AnalyzeOnly && NoOutput) {
     errs() << argv[0] << ": analyze mode conflicts with no-output mode.\n";
     return 1;
   }
 
+  // FIXME: once the legacy PM code is deleted, move runPassPipeline() here and
+  // construct the PassBuilder before parsing IR so we can reuse the same
+  // PassBuilder for print passes.
+  if (PrintPasses) {
+    printPasses(outs());
+    return 0;
+  }
+
   TimeTracerRAII TimeTracer(argv[0]);
 
   SMDiagnostic Err;
@@ -654,7 +687,8 @@
   // specified by an internal option. This is normally done during LTO which is
   // not performed via opt.
   updateVCallVisibilityInModule(*M,
-                                /* WholeProgramVisibilityEnabledInLTO */ false);
+                                /* WholeProgramVisibilityEnabledInLTO */ false,
+                                /* DynamicExportSymbols */ {});
 
   // Figure out what stream we are supposed to write to...
   std::unique_ptr<ToolOutputFile> Out;
@@ -669,8 +703,8 @@
       OutputFilename = "-";
 
     std::error_code EC;
-    sys::fs::OpenFlags Flags = OutputAssembly ? sys::fs::OF_Text
-                                              : sys::fs::OF_None;
+    sys::fs::OpenFlags Flags =
+        OutputAssembly ? sys::fs::OF_TextWithCRLF : sys::fs::OF_None;
     Out.reset(new ToolOutputFile(OutputFilename, EC, Flags));
     if (EC) {
       errs() << EC.message() << '\n';
@@ -746,7 +780,16 @@
   if ((EnableNewPassManager && !shouldForceLegacyPM()) ||
       PassPipeline.getNumOccurrences() > 0) {
     if (AnalyzeOnly) {
-      errs() << "Cannot specify -analyze under new pass manager\n";
+      errs() << "Cannot specify -analyze under new pass manager, either "
+                "specify '-enable-new-pm=0', or use the corresponding new pass "
+                "manager pass, e.g. '-passes=print<scalar-evolution>'. For a "
+                "full list of passes, see the '--print-passes' flag.\n";
+      return 1;
+    }
+    if (legacy::debugPassSpecified()) {
+      errs()
+          << "-debug-pass does not work with the new PM, either use "
+             "-debug-pass-manager, or use the legacy PM (-enable-new-pm=0)\n";
       return 1;
     }
     if (PassPipeline.getNumOccurrences() > 0 && PassList.size() > 0) {
@@ -788,7 +831,7 @@
                            ThinLinkOut.get(), RemarksFile.get(), PassPipeline,
                            Passes, OK, VK, PreserveAssemblyUseListOrder,
                            PreserveBitcodeUseListOrder, EmitSummaryIndex,
-                           EmitModuleHash, EnableDebugify, Coroutines)
+                           EmitModuleHash, EnableDebugify)
                ? 0
                : 1;
   }
@@ -797,10 +840,21 @@
   // about to build. If the -debugify-each option is set, wrap each pass with
   // the (-check)-debugify passes.
   DebugifyCustomPassManager Passes;
-  if (DebugifyEach)
-    Passes.enableDebugifyEach();
+  DebugifyStatsMap DIStatsMap;
+  DebugInfoPerPassMap DIPreservationMap;
+  if (DebugifyEach) {
+    Passes.setDebugifyMode(DebugifyMode::SyntheticDebugInfo);
+    Passes.setDIStatsMap(DIStatsMap);
+  } else if (VerifyEachDebugInfoPreserve) {
+    Passes.setDebugifyMode(DebugifyMode::OriginalDebugInfo);
+    Passes.setDIPreservationMap(DIPreservationMap);
+    if (!VerifyDIPreserveExport.empty())
+      Passes.setOrigDIVerifyBugsReportFilePath(VerifyDIPreserveExport);
+  }
 
-  bool AddOneTimeDebugifyPasses = EnableDebugify && !DebugifyEach;
+  bool AddOneTimeDebugifyPasses =
+      (EnableDebugify && !DebugifyEach) ||
+      (VerifyDebugInfoPreserve && !VerifyEachDebugInfoPreserve);
 
   Passes.add(new TargetLibraryInfoWrapperPass(TLII));
 
@@ -808,8 +862,17 @@
   Passes.add(createTargetTransformInfoWrapperPass(TM ? TM->getTargetIRAnalysis()
                                                      : TargetIRAnalysis()));
 
-  if (AddOneTimeDebugifyPasses)
-    Passes.add(createDebugifyModulePass());
+  if (AddOneTimeDebugifyPasses) {
+    if (EnableDebugify) {
+      Passes.setDIStatsMap(DIStatsMap);
+      Passes.add(createDebugifyModulePass());
+    } else if (VerifyDebugInfoPreserve) {
+      Passes.setDIPreservationMap(DIPreservationMap);
+      Passes.add(createDebugifyModulePass(
+          DebugifyMode::OriginalDebugInfo, "",
+          &(Passes.getDebugInfoPerPassMap())));
+    }
+  }
 
   std::unique_ptr<legacy::FunctionPassManager> FPasses;
   if (OptLevelO0 || OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz ||
@@ -953,8 +1016,17 @@
   if (!NoVerify && !VerifyEach)
     Passes.add(createVerifierPass());
 
-  if (AddOneTimeDebugifyPasses)
-    Passes.add(createCheckDebugifyModulePass(false));
+  if (AddOneTimeDebugifyPasses) {
+    if (EnableDebugify)
+      Passes.add(createCheckDebugifyModulePass(false));
+    else if (VerifyDebugInfoPreserve) {
+      if (!VerifyDIPreserveExport.empty())
+        Passes.setOrigDIVerifyBugsReportFilePath(VerifyDIPreserveExport);
+      Passes.add(createCheckDebugifyModulePass(
+          false, "", nullptr, DebugifyMode::OriginalDebugInfo,
+          &(Passes.getDebugInfoPerPassMap()), VerifyDIPreserveExport));
+    }
+  }
 
   // In run twice mode, we want to make sure the output is bit-by-bit
   // equivalent if we run the pass manager again, so setup two buffers and
diff --git a/src/llvm-project/llvm/tools/sancov/sancov.cpp b/src/llvm-project/llvm/tools/sancov/sancov.cpp
index f1d756f..b274310 100644
--- a/src/llvm-project/llvm/tools/sancov/sancov.cpp
+++ b/src/llvm-project/llvm/tools/sancov/sancov.cpp
@@ -726,8 +726,7 @@
       TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
   failIfEmpty(AsmInfo, "no asm info for target " + TripleName);
 
-  std::unique_ptr<const MCObjectFileInfo> MOFI(new MCObjectFileInfo);
-  MCContext Ctx(AsmInfo.get(), MRI.get(), MOFI.get());
+  MCContext Ctx(TheTriple, AsmInfo.get(), MRI.get(), STI.get());
   std::unique_ptr<MCDisassembler> DisAsm(
       TheTarget->createMCDisassembler(*STI, Ctx));
   failIfEmpty(DisAsm, "no disassembler info for target " + TripleName);
diff --git a/src/llvm-project/llvm/tools/sanstats/sanstats.cpp b/src/llvm-project/llvm/tools/sanstats/sanstats.cpp
index 1f154e0..54ad35b 100644
--- a/src/llvm-project/llvm/tools/sanstats/sanstats.cpp
+++ b/src/llvm-project/llvm/tools/sanstats/sanstats.cpp
@@ -125,8 +125,8 @@
   cl::ParseCommandLineOptions(argc, argv,
                               "Sanitizer Statistics Processing Tool");
 
-  ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
-      MemoryBuffer::getFile(ClInputFile, -1, false);
+  ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile(
+      ClInputFile, /*IsText=*/false, /*RequiresNullTerminator=*/false);
   if (!MBOrErr) {
     errs() << argv[0] << ": " << ClInputFile << ": "
            << MBOrErr.getError().message() << '\n';
diff --git a/src/llvm-project/llvm/tools/split-file/.clang-tidy b/src/llvm-project/llvm/tools/split-file/.clang-tidy
index 87ec2ff..acd9361 100644
--- a/src/llvm-project/llvm/tools/split-file/.clang-tidy
+++ b/src/llvm-project/llvm/tools/split-file/.clang-tidy
@@ -1,19 +1,8 @@
-# Almost identical to the top-level .clang-tidy, except that {Member,Parameter,Variable}Case use camelBack.
-Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,-misc-non-private-member-variables-in-classes,readability-identifier-naming'
+InheritParentConfig: true
 CheckOptions:
-  - key:             readability-identifier-naming.ClassCase
-    value:           CamelCase
-  - key:             readability-identifier-naming.EnumCase
-    value:           CamelCase
-  - key:             readability-identifier-naming.FunctionCase
-    value:           camelBack
   - key:             readability-identifier-naming.MemberCase
     value:           camelBack
   - key:             readability-identifier-naming.ParameterCase
     value:           camelBack
-  - key:             readability-identifier-naming.UnionCase
-    value:           CamelCase
   - key:             readability-identifier-naming.VariableCase
     value:           camelBack
-  - key:             readability-identifier-naming.IgnoreMainLikeFunctions
-    value:           1
diff --git a/src/llvm-project/llvm/tools/split-file/split-file.cpp b/src/llvm-project/llvm/tools/split-file/split-file.cpp
index a012b4a..3ebbda4 100644
--- a/src/llvm-project/llvm/tools/split-file/split-file.cpp
+++ b/src/llvm-project/llvm/tools/split-file/split-file.cpp
@@ -16,6 +16,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/LineIterator.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
diff --git a/src/llvm-project/llvm/tools/verify-uselistorder/verify-uselistorder.cpp b/src/llvm-project/llvm/tools/verify-uselistorder/verify-uselistorder.cpp
index cbd2f85..28d3467 100644
--- a/src/llvm-project/llvm/tools/verify-uselistorder/verify-uselistorder.cpp
+++ b/src/llvm-project/llvm/tools/verify-uselistorder/verify-uselistorder.cpp
@@ -136,7 +136,7 @@
 bool TempFile::writeAssembly(const Module &M) const {
   LLVM_DEBUG(dbgs() << " - write assembly\n");
   std::error_code EC;
-  raw_fd_ostream OS(Filename, EC, sys::fs::OF_Text);
+  raw_fd_ostream OS(Filename, EC, sys::fs::OF_TextWithCRLF);
   if (EC) {
     errs() << "verify-uselistorder: error: " << EC.message() << "\n";
     return true;