Update clang to r339409.

Change-Id: I800772d2d838223be1f6b40d490c4591b937fca2
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/ExecutionEngine.h b/linux-x64/clang/include/llvm/ExecutionEngine/ExecutionEngine.h
index 7932688..b61cb24 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/ExecutionEngine.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/ExecutionEngine.h
@@ -60,7 +60,7 @@
 
 } // end namespace object
 
-/// \brief Helper class for helping synchronize access to the global address map
+/// Helper class for helping synchronize access to the global address map
 /// table.  Access to this class should be serialized under a mutex.
 class ExecutionEngineState {
 public:
@@ -86,7 +86,7 @@
     return GlobalAddressReverseMap;
   }
 
-  /// \brief Erase an entry from the mapping table.
+  /// Erase an entry from the mapping table.
   ///
   /// \returns The address that \p ToUnmap was happed to.
   uint64_t RemoveMapping(StringRef Name);
@@ -94,7 +94,7 @@
 
 using FunctionCreator = std::function<void *(const std::string &)>;
 
-/// \brief Abstract interface for implementation execution of LLVM modules,
+/// Abstract interface for implementation execution of LLVM modules,
 /// designed to support both interpreter and just-in-time (JIT) compiler
 /// implementations.
 class ExecutionEngine {
@@ -634,7 +634,7 @@
     return *this;
   }
 
-  // \brief Use OrcMCJITReplacement instead of MCJIT. Off by default.
+  // Use OrcMCJITReplacement instead of MCJIT. Off by default.
   void setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement) {
     this->UseOrcMCJITReplacement = UseOrcMCJITReplacement;
   }
@@ -642,7 +642,7 @@
   void setEmulatedTLS(bool EmulatedTLS) {
     this->EmulatedTLS = EmulatedTLS;
   }
-  
+
   TargetMachine *selectTarget();
 
   /// selectTarget - Pick a target either via -march or by guessing the native
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/JITEventListener.h b/linux-x64/clang/include/llvm/ExecutionEngine/JITEventListener.h
index ff7840f..1ce772c 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/JITEventListener.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/JITEventListener.h
@@ -15,9 +15,11 @@
 #ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
 #define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
 
+#include "llvm-c/ExecutionEngine.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/ExecutionEngine/RuntimeDyld.h"
 #include "llvm/IR/DebugLoc.h"
+#include "llvm/Support/CBindingWrapping.h"
 #include <cstdint>
 #include <vector>
 
@@ -115,10 +117,21 @@
   }
 #endif // USE_OPROFILE
 
+#if LLVM_USE_PERF
+  static JITEventListener *createPerfJITEventListener();
+#else
+  static JITEventListener *createPerfJITEventListener()
+  {
+    return nullptr;
+  }
+#endif // USE_PERF
+
 private:
   virtual void anchor();
 };
 
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITEventListener, LLVMJITEventListenerRef)
+
 } // end namespace llvm
 
 #endif // LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/JITSymbol.h b/linux-x64/clang/include/llvm/ExecutionEngine/JITSymbol.h
index 86ab173..0e33f01 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/JITSymbol.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/JITSymbol.h
@@ -32,14 +32,14 @@
 
 namespace object {
 
-class BasicSymbolRef;
+class SymbolRef;
 
 } // end namespace object
 
-/// @brief Represents an address in the target process's address space.
+/// Represents an address in the target process's address space.
 using JITTargetAddress = uint64_t;
 
-/// @brief Flags for symbols in the JIT.
+/// Flags for symbols in the JIT.
 class JITSymbolFlags {
 public:
   using UnderlyingType = uint8_t;
@@ -52,63 +52,77 @@
     Common = 1U << 2,
     Absolute = 1U << 3,
     Exported = 1U << 4,
-    NotMaterialized = 1U << 5
+    Callable = 1U << 5,
+    Lazy = 1U << 6,
+    Materializing = 1U << 7
   };
 
   static JITSymbolFlags stripTransientFlags(JITSymbolFlags Orig) {
-    return static_cast<FlagNames>(Orig.Flags & ~NotMaterialized);
+    return static_cast<FlagNames>(Orig.Flags & ~Lazy & ~Materializing);
   }
 
-  /// @brief Default-construct a JITSymbolFlags instance.
+  /// Default-construct a JITSymbolFlags instance.
   JITSymbolFlags() = default;
 
-  /// @brief Construct a JITSymbolFlags instance from the given flags.
+  /// Construct a JITSymbolFlags instance from the given flags.
   JITSymbolFlags(FlagNames Flags) : Flags(Flags) {}
 
-  /// @brief Construct a JITSymbolFlags instance from the given flags and target
+  /// Construct a JITSymbolFlags instance from the given flags and target
   ///        flags.
   JITSymbolFlags(FlagNames Flags, TargetFlagsType TargetFlags)
     : Flags(Flags), TargetFlags(TargetFlags) {}
 
-  /// @brief Return true if there was an error retrieving this symbol.
+  /// Return true if there was an error retrieving this symbol.
   bool hasError() const {
     return (Flags & HasError) == HasError;
   }
 
-  /// @brief Returns true if this symbol has been fully materialized (i.e. is
-  ///        callable).
-  bool isMaterialized() const { return !(Flags & NotMaterialized); }
+  /// Returns true if this is a lazy symbol.
+  ///        This flag is used internally by the JIT APIs to track
+  ///        materialization states.
+  bool isLazy() const { return Flags & Lazy; }
 
-  /// @brief Returns true if the Weak flag is set.
+  /// Returns true if this symbol is in the process of being
+  ///        materialized.
+  bool isMaterializing() const { return Flags & Materializing; }
+
+  /// Returns true if this symbol is fully materialized.
+  ///        (i.e. neither lazy, nor materializing).
+  bool isMaterialized() const { return !(Flags & (Lazy | Materializing)); }
+
+  /// Returns true if the Weak flag is set.
   bool isWeak() const {
     return (Flags & Weak) == Weak;
   }
 
-  /// @brief Returns true if the Common flag is set.
+  /// Returns true if the Common flag is set.
   bool isCommon() const {
     return (Flags & Common) == Common;
   }
 
-  /// @brief Returns true if the symbol isn't weak or common.
+  /// Returns true if the symbol isn't weak or common.
   bool isStrong() const {
     return !isWeak() && !isCommon();
   }
 
-  /// @brief Returns true if the Exported flag is set.
+  /// Returns true if the Exported flag is set.
   bool isExported() const {
     return (Flags & Exported) == Exported;
   }
 
-  /// @brief Implicitly convert to the underlying flags type.
+  /// Returns true if the given symbol is known to be callable.
+  bool isCallable() const { return (Flags & Callable) == Callable; }
+
+  /// Implicitly convert to the underlying flags type.
   operator UnderlyingType&() { return Flags; }
 
-  /// @brief Implicitly convert to the underlying flags type.
+  /// Implicitly convert to the underlying flags type.
   operator const UnderlyingType&() const { return Flags; }
 
-  /// @brief Return a reference to the target-specific flags.
+  /// Return a reference to the target-specific flags.
   TargetFlagsType& getTargetFlags() { return TargetFlags; }
 
-  /// @brief Return a reference to the target-specific flags.
+  /// Return a reference to the target-specific flags.
   const TargetFlagsType& getTargetFlags() const { return TargetFlags; }
 
   /// Construct a JITSymbolFlags value based on the flags of the given global
@@ -117,14 +131,15 @@
 
   /// Construct a JITSymbolFlags value based on the flags of the given libobject
   /// symbol.
-  static JITSymbolFlags fromObjectSymbol(const object::BasicSymbolRef &Symbol);
+  static Expected<JITSymbolFlags>
+  fromObjectSymbol(const object::SymbolRef &Symbol);
 
 private:
   UnderlyingType Flags = None;
   TargetFlagsType TargetFlags = 0;
 };
 
-/// @brief ARM-specific JIT symbol flags.
+/// ARM-specific JIT symbol flags.
 /// FIXME: This should be moved into a target-specific header.
 class ARMJITSymbolFlags {
 public:
@@ -137,62 +152,65 @@
 
   operator JITSymbolFlags::TargetFlagsType&() { return Flags; }
 
-  static ARMJITSymbolFlags fromObjectSymbol(
-                                           const object::BasicSymbolRef &Symbol);
+  static ARMJITSymbolFlags fromObjectSymbol(const object::SymbolRef &Symbol);
+
 private:
   JITSymbolFlags::TargetFlagsType Flags = 0;
 };
 
-/// @brief Represents a symbol that has been evaluated to an address already.
+/// Represents a symbol that has been evaluated to an address already.
 class JITEvaluatedSymbol {
 public:
   JITEvaluatedSymbol() = default;
 
-  /// @brief Create a 'null' symbol.
+  /// Create a 'null' symbol.
   JITEvaluatedSymbol(std::nullptr_t) {}
 
-  /// @brief Create a symbol for the given address and flags.
+  /// Create a symbol for the given address and flags.
   JITEvaluatedSymbol(JITTargetAddress Address, JITSymbolFlags Flags)
       : Address(Address), Flags(Flags) {}
 
-  /// @brief An evaluated symbol converts to 'true' if its address is non-zero.
+  /// An evaluated symbol converts to 'true' if its address is non-zero.
   explicit operator bool() const { return Address != 0; }
 
-  /// @brief Return the address of this symbol.
+  /// Return the address of this symbol.
   JITTargetAddress getAddress() const { return Address; }
 
-  /// @brief Return the flags for this symbol.
+  /// Return the flags for this symbol.
   JITSymbolFlags getFlags() const { return Flags; }
 
+  /// Set the flags for this symbol.
+  void setFlags(JITSymbolFlags Flags) { this->Flags = std::move(Flags); }
+
 private:
   JITTargetAddress Address = 0;
   JITSymbolFlags Flags;
 };
 
-/// @brief Represents a symbol in the JIT.
+/// Represents a symbol in the JIT.
 class JITSymbol {
 public:
   using GetAddressFtor = std::function<Expected<JITTargetAddress>()>;
 
-  /// @brief Create a 'null' symbol, used to represent a "symbol not found"
+  /// Create a 'null' symbol, used to represent a "symbol not found"
   ///        result from a successful (non-erroneous) lookup.
   JITSymbol(std::nullptr_t)
       : CachedAddr(0) {}
 
-  /// @brief Create a JITSymbol representing an error in the symbol lookup
+  /// Create a JITSymbol representing an error in the symbol lookup
   ///        process (e.g. a network failure during a remote lookup).
   JITSymbol(Error Err)
     : Err(std::move(Err)), Flags(JITSymbolFlags::HasError) {}
 
-  /// @brief Create a symbol for a definition with a known address.
+  /// Create a symbol for a definition with a known address.
   JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags)
       : CachedAddr(Addr), Flags(Flags) {}
 
-  /// @brief Construct a JITSymbol from a JITEvaluatedSymbol.
+  /// Construct a JITSymbol from a JITEvaluatedSymbol.
   JITSymbol(JITEvaluatedSymbol Sym)
       : CachedAddr(Sym.getAddress()), Flags(Sym.getFlags()) {}
 
-  /// @brief Create a symbol for a definition that doesn't have a known address
+  /// Create a symbol for a definition that doesn't have a known address
   ///        yet.
   /// @param GetAddress A functor to materialize a definition (fixing the
   ///        address) on demand.
@@ -232,19 +250,19 @@
       CachedAddr.~JITTargetAddress();
   }
 
-  /// @brief Returns true if the symbol exists, false otherwise.
+  /// Returns true if the symbol exists, false otherwise.
   explicit operator bool() const {
     return !Flags.hasError() && (CachedAddr || GetAddress);
   }
 
-  /// @brief Move the error field value out of this JITSymbol.
+  /// Move the error field value out of this JITSymbol.
   Error takeError() {
     if (Flags.hasError())
       return std::move(Err);
     return Error::success();
   }
 
-  /// @brief Get the address of the symbol in the target address space. Returns
+  /// Get the address of the symbol in the target address space. Returns
   ///        '0' if the symbol does not exist.
   Expected<JITTargetAddress> getAddress() {
     assert(!Flags.hasError() && "getAddress called on error value");
@@ -270,7 +288,7 @@
   JITSymbolFlags Flags;
 };
 
-/// @brief Symbol resolution interface.
+/// Symbol resolution interface.
 ///
 /// Allows symbol flags and addresses to be looked up by name.
 /// Symbol queries are done in bulk (i.e. you request resolution of a set of
@@ -284,14 +302,14 @@
 
   virtual ~JITSymbolResolver() = default;
 
-  /// @brief Returns the fully resolved address and flags for each of the given
+  /// Returns the fully resolved address and flags for each of the given
   ///        symbols.
   ///
   /// This method will return an error if any of the given symbols can not be
   /// resolved, or if the resolution process itself triggers an error.
   virtual Expected<LookupResult> lookup(const LookupSet &Symbols) = 0;
 
-  /// @brief Returns the symbol flags for each of the given symbols.
+  /// Returns the symbol flags for each of the given symbols.
   ///
   /// This method does NOT return an error if any of the given symbols is
   /// missing. Instead, that symbol will be left out of the result map.
@@ -301,15 +319,15 @@
   virtual void anchor();
 };
 
-/// \brief Legacy symbol resolution interface.
+/// Legacy symbol resolution interface.
 class LegacyJITSymbolResolver : public JITSymbolResolver {
 public:
-  /// @brief Performs lookup by, for each symbol, first calling
+  /// Performs lookup by, for each symbol, first calling
   ///        findSymbolInLogicalDylib and if that fails calling
   ///        findSymbol.
   Expected<LookupResult> lookup(const LookupSet &Symbols) final;
 
-  /// @brief Performs flags lookup by calling findSymbolInLogicalDylib and
+  /// Performs flags lookup by calling findSymbolInLogicalDylib and
   ///        returning the flags value for that symbol.
   Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) final;
 
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h b/linux-x64/clang/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h
deleted file mode 100644
index 0f00ad0..0000000
--- a/linux-x64/clang/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//===- ObjectMemoryBuffer.h - SmallVector-backed MemoryBuffrer  -*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares a wrapper class to hold the memory into which an
-// object will be generated.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H
-#define LLVM_EXECUTIONENGINE_OBJECTMEMORYBUFFER_H
-
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-
-/// \brief SmallVector-backed MemoryBuffer instance.
-///
-/// This class enables efficient construction of MemoryBuffers from SmallVector
-/// instances. This is useful for MCJIT and Orc, where object files are streamed
-/// into SmallVectors, then inspected using ObjectFile (which takes a
-/// MemoryBuffer).
-class ObjectMemoryBuffer : public MemoryBuffer {
-public:
-
-  /// \brief Construct an ObjectMemoryBuffer from the given SmallVector r-value.
-  ///
-  /// FIXME: It'd be nice for this to be a non-templated constructor taking a
-  /// SmallVectorImpl here instead of a templated one taking a SmallVector<N>,
-  /// but SmallVector's move-construction/assignment currently only take
-  /// SmallVectors. If/when that is fixed we can simplify this constructor and
-  /// the following one.
-  ObjectMemoryBuffer(SmallVectorImpl<char> &&SV)
-    : SV(std::move(SV)), BufferName("<in-memory object>") {
-    init(this->SV.begin(), this->SV.end(), false);
-  }
-
-  /// \brief Construct a named ObjectMemoryBuffer from the given SmallVector
-  ///        r-value and StringRef.
-  ObjectMemoryBuffer(SmallVectorImpl<char> &&SV, StringRef Name)
-    : SV(std::move(SV)), BufferName(Name) {
-    init(this->SV.begin(), this->SV.end(), false);
-  }
-
-  StringRef getBufferIdentifier() const override { return BufferName; }
-
-  BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
-
-private:
-  SmallVector<char, 0> SV;
-  std::string BufferName;
-};
-
-} // namespace llvm
-
-#endif
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
index a64a6dd..8bd21a0 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
@@ -20,9 +20,10 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/Orc/Core.h"
 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
+#include "llvm/ExecutionEngine/Orc/Legacy.h"
 #include "llvm/ExecutionEngine/Orc/OrcError.h"
 #include "llvm/ExecutionEngine/RuntimeDyld.h"
 #include "llvm/IR/Attributes.h"
@@ -57,7 +58,47 @@
 
 namespace orc {
 
-/// @brief Compile-on-demand layer.
+class ExtractingIRMaterializationUnit;
+
+class CompileOnDemandLayer2 : public IRLayer {
+  friend class ExtractingIRMaterializationUnit;
+
+public:
+  /// Builder for IndirectStubsManagers.
+  using IndirectStubsManagerBuilder =
+      std::function<std::unique_ptr<IndirectStubsManager>()>;
+
+  using GetAvailableContextFunction = std::function<LLVMContext &()>;
+
+  CompileOnDemandLayer2(ExecutionSession &ES, IRLayer &BaseLayer,
+                        JITCompileCallbackManager &CCMgr,
+                        IndirectStubsManagerBuilder BuildIndirectStubsManager,
+                        GetAvailableContextFunction GetAvailableContext);
+
+  Error add(VSO &V, VModuleKey K, std::unique_ptr<Module> M) override;
+
+  void emit(MaterializationResponsibility R, VModuleKey K,
+            std::unique_ptr<Module> M) override;
+
+private:
+  using StubManagersMap =
+      std::map<const VSO *, std::unique_ptr<IndirectStubsManager>>;
+
+  IndirectStubsManager &getStubsManager(const VSO &V);
+
+  void emitExtractedFunctionsModule(MaterializationResponsibility R,
+                                    std::unique_ptr<Module> M);
+
+  mutable std::mutex CODLayerMutex;
+
+  IRLayer &BaseLayer;
+  JITCompileCallbackManager &CCMgr;
+  IndirectStubsManagerBuilder BuildIndirectStubsManager;
+  StubManagersMap StubsMgrs;
+  GetAvailableContextFunction GetAvailableContext;
+};
+
+/// Compile-on-demand layer.
 ///
 ///   When a module is added to this layer a stub is created for each of its
 /// function definitions. The stubs and other global values are immediately
@@ -196,10 +237,10 @@
 
 public:
 
-  /// @brief Module partitioning functor.
+  /// Module partitioning functor.
   using PartitioningFtor = std::function<std::set<Function*>(Function&)>;
 
-  /// @brief Builder for IndirectStubsManagers.
+  /// Builder for IndirectStubsManagers.
   using IndirectStubsManagerBuilderT =
       std::function<std::unique_ptr<IndirectStubsMgrT>()>;
 
@@ -209,7 +250,7 @@
   using SymbolResolverSetter =
       std::function<void(VModuleKey K, std::shared_ptr<SymbolResolver> R)>;
 
-  /// @brief Construct a compile-on-demand layer instance.
+  /// Construct a compile-on-demand layer instance.
   CompileOnDemandLayer(ExecutionSession &ES, BaseLayerT &BaseLayer,
                        SymbolResolverGetter GetSymbolResolver,
                        SymbolResolverSetter SetSymbolResolver,
@@ -230,7 +271,7 @@
       consumeError(removeModule(LogicalDylibs.begin()->first));
   }
 
-  /// @brief Add a module to the compile-on-demand layer.
+  /// Add a module to the compile-on-demand layer.
   Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
 
     assert(!LogicalDylibs.count(K) && "VModuleKey K already in use");
@@ -242,12 +283,12 @@
     return addLogicalModule(I->second, std::move(M));
   }
 
-  /// @brief Add extra modules to an existing logical module.
+  /// Add extra modules to an existing logical module.
   Error addExtraModule(VModuleKey K, std::unique_ptr<Module> M) {
     return addLogicalModule(LogicalDylibs[K], std::move(M));
   }
 
-  /// @brief Remove the module represented by the given key.
+  /// Remove the module represented by the given key.
   ///
   ///   This will remove all modules in the layers below that were derived from
   /// the module represented by K.
@@ -259,7 +300,7 @@
     return Err;
   }
 
-  /// @brief Search for the given named symbol.
+  /// Search for the given named symbol.
   /// @param Name The name of the symbol to search for.
   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
   /// @return A handle for the given named symbol, if it exists.
@@ -275,7 +316,7 @@
     return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
   }
 
-  /// @brief Get the address of a symbol provided by this layer, or some layer
+  /// Get the address of a symbol provided by this layer, or some layer
   ///        below this one.
   JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
                          bool ExportedSymbolsOnly) {
@@ -283,7 +324,7 @@
     return LogicalDylibs[K].findSymbol(BaseLayer, Name, ExportedSymbolsOnly);
   }
 
-  /// @brief Update the stub for the given function to point at FnBodyAddr.
+  /// Update the stub for the given function to point at FnBodyAddr.
   /// This can be used to support re-optimization.
   /// @return true if the function exists and the stub is updated, false
   ///         otherwise.
@@ -316,7 +357,7 @@
     // simplifying symbol lookup.
     LD.StaticRenamer.rename(*SrcMPtr);
 
-    // Bump the linkage and rename any anonymous/privote members in SrcM to
+    // Bump the linkage and rename any anonymous/private members in SrcM to
     // ensure that everything will resolve properly after we partition SrcM.
     makeAllSymbolsExternallyAccessible(*SrcMPtr);
 
@@ -349,22 +390,21 @@
         // Create a callback, associate it with the stub for the function,
         // and set the compile action to compile the partition containing the
         // function.
-        if (auto CCInfoOrErr = CompileCallbackMgr.getCompileCallback()) {
-          auto &CCInfo = *CCInfoOrErr;
+        auto CompileAction = [this, &LD, LMId, &F]() -> JITTargetAddress {
+          if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
+            return *FnImplAddrOrErr;
+          else {
+            // FIXME: Report error, return to 'abort' or something similar.
+            consumeError(FnImplAddrOrErr.takeError());
+            return 0;
+          }
+        };
+        if (auto CCAddr =
+                CompileCallbackMgr.getCompileCallback(std::move(CompileAction)))
           StubInits[MangledName] =
-            std::make_pair(CCInfo.getAddress(),
-                           JITSymbolFlags::fromGlobalValue(F));
-          CCInfo.setCompileAction([this, &LD, LMId, &F]() -> JITTargetAddress {
-              if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
-                return *FnImplAddrOrErr;
-              else {
-                // FIXME: Report error, return to 'abort' or something similar.
-                consumeError(FnImplAddrOrErr.takeError());
-                return 0;
-              }
-            });
-        } else
-          return CCInfoOrErr.takeError();
+              std::make_pair(*CCAddr, JITSymbolFlags::fromGlobalValue(F));
+        else
+          return CCAddr.takeError();
       }
 
       if (auto Err = LD.StubsMgr->createStubs(StubInits))
@@ -402,9 +442,8 @@
 
     // Initializers may refer to functions declared (but not defined) in this
     // module. Build a materializer to clone decls on demand.
-    Error MaterializerErrors = Error::success();
     auto Materializer = createLambdaMaterializer(
-      [&LD, &GVsM, &MaterializerErrors](Value *V) -> Value* {
+      [&LD, &GVsM](Value *V) -> Value* {
         if (auto *F = dyn_cast<Function>(V)) {
           // Decls in the original module just get cloned.
           if (F->isDeclaration())
@@ -416,18 +455,8 @@
           const DataLayout &DL = GVsM->getDataLayout();
           std::string FName = mangle(F->getName(), DL);
           unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
-          JITTargetAddress StubAddr = 0;
-
-          // Get the address for the stub. If we encounter an error while
-          // doing so, stash it in the MaterializerErrors variable and use a
-          // null address as a placeholder.
-          if (auto StubSym = LD.StubsMgr->findStub(FName, false)) {
-            if (auto StubAddrOrErr = StubSym.getAddress())
-              StubAddr = *StubAddrOrErr;
-            else
-              MaterializerErrors = joinErrors(std::move(MaterializerErrors),
-                                              StubAddrOrErr.takeError());
-          }
+          JITTargetAddress StubAddr =
+            LD.StubsMgr->findStub(FName, false).getAddress();
 
           ConstantInt *StubAddrCI =
             ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr));
@@ -456,15 +485,10 @@
       NewA->setAliasee(cast<Constant>(Init));
     }
 
-    if (MaterializerErrors)
-      return MaterializerErrors;
-
     // Build a resolver for the globals module and add it to the base layer.
     auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol {
       if (auto Sym = LD.StubsMgr->findStub(Name, false))
         return Sym;
-      else if (auto Err = Sym.takeError())
-        return std::move(Err);
 
       if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
         return Sym;
@@ -475,25 +499,35 @@
     };
 
     auto GVsResolver = createSymbolResolver(
-        [&LD, LegacyLookup](SymbolFlagsMap &SymbolFlags,
-                            const SymbolNameSet &Symbols) {
-          auto NotFoundViaLegacyLookup =
-              lookupFlagsWithLegacyFn(SymbolFlags, Symbols, LegacyLookup);
+        [&LD, LegacyLookup](const SymbolNameSet &Symbols) {
+          auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup);
 
-          if (!NotFoundViaLegacyLookup) {
-            logAllUnhandledErrors(NotFoundViaLegacyLookup.takeError(), errs(),
+          if (!SymbolFlags) {
+            logAllUnhandledErrors(SymbolFlags.takeError(), errs(),
                                   "CODLayer/GVsResolver flags lookup failed: ");
-            SymbolFlags.clear();
-            return SymbolNameSet();
+            return SymbolFlagsMap();
           }
 
-          return LD.BackingResolver->lookupFlags(SymbolFlags,
-                                                 *NotFoundViaLegacyLookup);
+          if (SymbolFlags->size() == Symbols.size())
+            return *SymbolFlags;
+
+          SymbolNameSet NotFoundViaLegacyLookup;
+          for (auto &S : Symbols)
+            if (!SymbolFlags->count(S))
+              NotFoundViaLegacyLookup.insert(S);
+          auto SymbolFlags2 =
+              LD.BackingResolver->lookupFlags(NotFoundViaLegacyLookup);
+
+          for (auto &KV : SymbolFlags2)
+            (*SymbolFlags)[KV.first] = std::move(KV.second);
+
+          return *SymbolFlags;
         },
-        [&LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Query,
-                            SymbolNameSet Symbols) {
+        [this, &LD,
+         LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Query,
+                       SymbolNameSet Symbols) {
           auto NotFoundViaLegacyLookup =
-              lookupWithLegacyFn(*Query, Symbols, LegacyLookup);
+              lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
           return LD.BackingResolver->lookup(Query, NotFoundViaLegacyLookup);
         });
 
@@ -634,23 +668,34 @@
 
     // Create memory manager and symbol resolver.
     auto Resolver = createSymbolResolver(
-        [&LD, LegacyLookup](SymbolFlagsMap &SymbolFlags,
-                            const SymbolNameSet &Symbols) {
-          auto NotFoundViaLegacyLookup =
-              lookupFlagsWithLegacyFn(SymbolFlags, Symbols, LegacyLookup);
-          if (!NotFoundViaLegacyLookup) {
-            logAllUnhandledErrors(NotFoundViaLegacyLookup.takeError(), errs(),
+        [&LD, LegacyLookup](const SymbolNameSet &Symbols) {
+          auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup);
+          if (!SymbolFlags) {
+            logAllUnhandledErrors(SymbolFlags.takeError(), errs(),
                                   "CODLayer/SubResolver flags lookup failed: ");
-            SymbolFlags.clear();
-            return SymbolNameSet();
+            return SymbolFlagsMap();
           }
-          return LD.BackingResolver->lookupFlags(SymbolFlags,
-                                                 *NotFoundViaLegacyLookup);
+
+          if (SymbolFlags->size() == Symbols.size())
+            return *SymbolFlags;
+
+          SymbolNameSet NotFoundViaLegacyLookup;
+          for (auto &S : Symbols)
+            if (!SymbolFlags->count(S))
+              NotFoundViaLegacyLookup.insert(S);
+
+          auto SymbolFlags2 =
+              LD.BackingResolver->lookupFlags(NotFoundViaLegacyLookup);
+
+          for (auto &KV : SymbolFlags2)
+            (*SymbolFlags)[KV.first] = std::move(KV.second);
+
+          return *SymbolFlags;
         },
-        [&LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Q,
-                            SymbolNameSet Symbols) {
+        [this, &LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Q,
+                                  SymbolNameSet Symbols) {
           auto NotFoundViaLegacyLookup =
-              lookupWithLegacyFn(*Q, Symbols, LegacyLookup);
+              lookupWithLegacyFn(ES, *Q, Symbols, LegacyLookup);
           return LD.BackingResolver->lookup(Q,
                                             std::move(NotFoundViaLegacyLookup));
         });
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
index a8050ff..213a591 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/CompileUtils.h
@@ -16,13 +16,14 @@
 
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ExecutionEngine/ObjectCache.h"
-#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/Object/Binary.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SmallVectorMemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetMachine.h"
 #include <algorithm>
@@ -35,35 +36,21 @@
 
 namespace orc {
 
-/// @brief Simple compile functor: Takes a single IR module and returns an
-///        ObjectFile.
+/// Simple compile functor: Takes a single IR module and returns an ObjectFile.
+/// This compiler supports a single compilation thread and LLVMContext only.
+/// For multithreaded compilation, use MultiThreadedSimpleCompiler below.
 class SimpleCompiler {
-private:
-  class SmallVectorMemoryBuffer : public MemoryBuffer {
-  public:
-    SmallVectorMemoryBuffer(SmallVector<char, 0> Buffer)
-        : Buffer(std::move(Buffer)) {
-      init(this->Buffer.data(), this->Buffer.data() + this->Buffer.size(),
-           false);
-    }
-
-    BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
-
-  private:
-    SmallVector<char, 0> Buffer;
-  };
-
 public:
   using CompileResult = std::unique_ptr<MemoryBuffer>;
 
-  /// @brief Construct a simple compile functor with the given target.
+  /// Construct a simple compile functor with the given target.
   SimpleCompiler(TargetMachine &TM, ObjectCache *ObjCache = nullptr)
     : TM(TM), ObjCache(ObjCache) {}
 
-  /// @brief Set an ObjectCache to query before compiling.
+  /// Set an ObjectCache to query before compiling.
   void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; }
 
-  /// @brief Compile a Module to an ObjectFile.
+  /// Compile a Module to an ObjectFile.
   CompileResult operator()(Module &M) {
     CompileResult CachedObject = tryToLoadFromObjectCache(M);
     if (CachedObject)
@@ -114,6 +101,29 @@
   ObjectCache *ObjCache = nullptr;
 };
 
+/// A thread-safe version of SimpleCompiler.
+///
+/// This class creates a new TargetMachine and SimpleCompiler instance for each
+/// compile.
+class MultiThreadedSimpleCompiler {
+public:
+  MultiThreadedSimpleCompiler(JITTargetMachineBuilder JTMB,
+                              ObjectCache *ObjCache = nullptr)
+      : JTMB(std::move(JTMB)), ObjCache(ObjCache) {}
+
+  void setObjectCache(ObjectCache *ObjCache) { this->ObjCache = ObjCache; }
+
+  std::unique_ptr<MemoryBuffer> operator()(Module &M) {
+    auto TM = cantFail(JTMB.createTargetMachine());
+    SimpleCompiler C(*TM, ObjCache);
+    return C(M);
+  }
+
+private:
+  JITTargetMachineBuilder JTMB;
+  ObjectCache *ObjCache = nullptr;
+};
+
 } // end namespace orc
 
 } // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
index 26fec8b..8456dff 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Core.h
@@ -14,9 +14,12 @@
 #ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H
 #define LLVM_EXECUTIONENGINE_ORC_CORE_H
 
+#include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/ExecutionEngine/JITSymbol.h"
 #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
+#include "llvm/IR/Module.h"
 
+#include <list>
 #include <map>
 #include <memory>
 #include <set>
@@ -25,139 +28,173 @@
 namespace llvm {
 namespace orc {
 
+// Forward declare some classes.
+class AsynchronousSymbolQuery;
+class ExecutionSession;
+class MaterializationUnit;
+class MaterializationResponsibility;
+class VSO;
+
 /// VModuleKey provides a unique identifier (allocated and managed by
 /// ExecutionSessions) for a module added to the JIT.
 using VModuleKey = uint64_t;
 
-class VSO;
-
-/// @brief A set of symbol names (represented by SymbolStringPtrs for
+/// A set of symbol names (represented by SymbolStringPtrs for
 //         efficiency).
 using SymbolNameSet = std::set<SymbolStringPtr>;
 
-/// @brief A map from symbol names (as SymbolStringPtrs) to JITSymbols
+/// Render a SymbolNameSet to an ostream.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols);
+
+/// A map from symbol names (as SymbolStringPtrs) to JITSymbols
 ///        (address/flags pairs).
 using SymbolMap = std::map<SymbolStringPtr, JITEvaluatedSymbol>;
 
-/// @brief A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
+/// Render a SymbolMap to an ostream.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols);
+
+/// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
 using SymbolFlagsMap = std::map<SymbolStringPtr, JITSymbolFlags>;
 
-/// @brief A symbol query that returns results via a callback when results are
-///        ready.
+/// Render a SymbolMap to an ostream.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &Symbols);
+
+/// A base class for materialization failures that allows the failing
+///        symbols to be obtained for logging.
+using SymbolDependenceMap = std::map<VSO *, SymbolNameSet>;
+
+/// Render a SymbolDependendeMap.
+raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps);
+
+/// A list of VSO pointers.
+using VSOList = std::vector<VSO *>;
+
+/// Render a VSOList.
+raw_ostream &operator<<(raw_ostream &OS, const VSOList &VSOs);
+
+/// Callback to notify client that symbols have been resolved.
+using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
+
+/// Callback to notify client that symbols are ready for execution.
+using SymbolsReadyCallback = std::function<void(Error)>;
+
+/// Callback to register the dependencies for a given query.
+using RegisterDependenciesFunction =
+    std::function<void(const SymbolDependenceMap &)>;
+
+/// This can be used as the value for a RegisterDependenciesFunction if there
+/// are no dependants to register with.
+extern RegisterDependenciesFunction NoDependenciesToRegister;
+
+/// Used to notify a VSO that the given set of symbols failed to materialize.
+class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
+public:
+  static char ID;
+
+  FailedToMaterialize(SymbolNameSet Symbols);
+  std::error_code convertToErrorCode() const override;
+  void log(raw_ostream &OS) const override;
+  const SymbolNameSet &getSymbols() const { return Symbols; }
+
+private:
+  SymbolNameSet Symbols;
+};
+
+/// Used to notify clients when symbols can not be found during a lookup.
+class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> {
+public:
+  static char ID;
+
+  SymbolsNotFound(SymbolNameSet Symbols);
+  std::error_code convertToErrorCode() const override;
+  void log(raw_ostream &OS) const override;
+  const SymbolNameSet &getSymbols() const { return Symbols; }
+
+private:
+  SymbolNameSet Symbols;
+};
+
+/// Tracks responsibility for materialization, and mediates interactions between
+/// MaterializationUnits and VSOs.
 ///
-/// makes a callback when all symbols are available.
-class AsynchronousSymbolQuery {
+/// An instance of this class is passed to MaterializationUnits when their
+/// materialize method is called. It allows MaterializationUnits to resolve and
+/// finalize symbols, or abandon materialization by notifying any unmaterialized
+/// symbols of an error.
+class MaterializationResponsibility {
+  friend class MaterializationUnit;
 public:
-  /// @brief Callback to notify client that symbols have been resolved.
-  using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
+  MaterializationResponsibility(MaterializationResponsibility &&) = default;
+  MaterializationResponsibility &
+  operator=(MaterializationResponsibility &&) = default;
 
-  /// @brief Callback to notify client that symbols are ready for execution.
-  using SymbolsReadyCallback = std::function<void(Error)>;
+  /// Destruct a MaterializationResponsibility instance. In debug mode
+  ///        this asserts that all symbols being tracked have been either
+  ///        finalized or notified of an error.
+  ~MaterializationResponsibility();
 
-  /// @brief Create a query for the given symbols, notify-resolved and
-  ///        notify-ready callbacks.
-  AsynchronousSymbolQuery(const SymbolNameSet &Symbols,
-                          SymbolsResolvedCallback NotifySymbolsResolved,
-                          SymbolsReadyCallback NotifySymbolsReady);
+  /// Returns the target VSO that these symbols are being materialized
+  ///        into.
+  VSO &getTargetVSO() const { return V; }
 
-  /// @brief Notify client that the query failed.
-  ///
-  /// If the notify-resolved callback has not been made yet, then it is called
-  /// with the given error, and the notify-finalized callback is never made.
-  ///
-  /// If the notify-resolved callback has already been made then then the
-  /// notify-finalized callback is called with the given error.
-  ///
-  /// It is illegal to call setFailed after both callbacks have been made.
-  void setFailed(Error Err);
+  /// Returns the symbol flags map for this responsibility instance.
+  SymbolFlagsMap getSymbols() { return SymbolFlags; }
 
-  /// @brief Set the resolved symbol information for the given symbol name.
-  ///
-  /// If this symbol was the last one not resolved, this will trigger a call to
-  /// the notify-finalized callback passing the completed sybol map.
-  void setDefinition(SymbolStringPtr Name, JITEvaluatedSymbol Sym);
+  /// Returns the names of any symbols covered by this
+  /// MaterializationResponsibility object that have queries pending. This
+  /// information can be used to return responsibility for unrequested symbols
+  /// back to the VSO via the delegate method.
+  SymbolNameSet getRequestedSymbols();
 
-  /// @brief Notify the query that a requested symbol is ready for execution.
+  /// Resolves the given symbols. Individual calls to this method may
+  ///        resolve a subset of the symbols, but all symbols must have been
+  ///        resolved prior to calling finalize.
+  void resolve(const SymbolMap &Symbols);
+
+  /// Finalizes all symbols tracked by this instance.
+  void finalize();
+
+  /// Adds new symbols to the VSO and this responsibility instance.
+  ///        VSO entries start out in the materializing state.
   ///
-  /// This decrements the query's internal count of not-yet-ready symbols. If
-  /// this call to notifySymbolFinalized sets the counter to zero, it will call
-  /// the notify-finalized callback with Error::success as the value.
-  void notifySymbolFinalized();
+  ///   This method can be used by materialization units that want to add
+  /// additional symbols at materialization time (e.g. stubs, compile
+  /// callbacks, metadata).
+  Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
+
+  /// Notify all unfinalized symbols that an error has occurred.
+  /// This will remove all symbols covered by this MaterializationResponsibilty
+  /// from V, and send an error to any queries waiting on these symbols.
+  void failMaterialization();
+
+  /// Transfers responsibility to the given MaterializationUnit for all
+  /// symbols defined by that MaterializationUnit. This allows
+  /// materializers to break up work based on run-time information (e.g.
+  /// by introspecting which symbols have actually been looked up and
+  /// materializing only those).
+  void replace(std::unique_ptr<MaterializationUnit> MU);
+
+  /// Delegates responsibility for the given symbols to the returned
+  /// materialization responsibility. Useful for breaking up work between
+  /// threads, or different kinds of materialization processes.
+  MaterializationResponsibility delegate(const SymbolNameSet &Symbols);
+
+  void addDependencies(const SymbolStringPtr &Name,
+                       const SymbolDependenceMap &Dependencies);
+
+  /// Add dependencies that apply to all symbols covered by this instance.
+  void addDependenciesForAll(const SymbolDependenceMap &Dependencies);
 
 private:
-  SymbolMap Symbols;
-  size_t OutstandingResolutions = 0;
-  size_t OutstandingFinalizations = 0;
-  SymbolsResolvedCallback NotifySymbolsResolved;
-  SymbolsReadyCallback NotifySymbolsReady;
+  /// Create a MaterializationResponsibility for the given VSO and
+  ///        initial symbols.
+  MaterializationResponsibility(VSO &V, SymbolFlagsMap SymbolFlags);
+
+  VSO &V;
+  SymbolFlagsMap SymbolFlags;
 };
 
-/// @brief SymbolResolver is a composable interface for looking up symbol flags
-///        and addresses using the AsynchronousSymbolQuery type. It will
-///        eventually replace the LegacyJITSymbolResolver interface as the
-///        stardard ORC symbol resolver type.
-class SymbolResolver {
-public:
-  virtual ~SymbolResolver() = default;
-
-  /// @brief Returns the flags for each symbol in Symbols that can be found,
-  ///        along with the set of symbol that could not be found.
-  virtual SymbolNameSet lookupFlags(SymbolFlagsMap &Flags,
-                                    const SymbolNameSet &Symbols) = 0;
-
-  /// @brief For each symbol in Symbols that can be found, assigns that symbols
-  ///        value in Query. Returns the set of symbols that could not be found.
-  virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
-                               SymbolNameSet Symbols) = 0;
-
-private:
-  virtual void anchor();
-};
-
-/// @brief Implements SymbolResolver with a pair of supplied function objects
-///        for convenience. See createSymbolResolver.
-template <typename LookupFlagsFn, typename LookupFn>
-class LambdaSymbolResolver final : public SymbolResolver {
-public:
-  template <typename LookupFlagsFnRef, typename LookupFnRef>
-  LambdaSymbolResolver(LookupFlagsFnRef &&LookupFlags, LookupFnRef &&Lookup)
-      : LookupFlags(std::forward<LookupFlagsFnRef>(LookupFlags)),
-        Lookup(std::forward<LookupFnRef>(Lookup)) {}
-
-  SymbolNameSet lookupFlags(SymbolFlagsMap &Flags,
-                            const SymbolNameSet &Symbols) final {
-    return LookupFlags(Flags, Symbols);
-  }
-
-  SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
-                       SymbolNameSet Symbols) final {
-    return Lookup(std::move(Query), std::move(Symbols));
-  }
-
-private:
-  LookupFlagsFn LookupFlags;
-  LookupFn Lookup;
-};
-
-/// @brief Creates a SymbolResolver implementation from the pair of supplied
-///        function objects.
-template <typename LookupFlagsFn, typename LookupFn>
-std::unique_ptr<LambdaSymbolResolver<
-    typename std::remove_cv<
-        typename std::remove_reference<LookupFlagsFn>::type>::type,
-    typename std::remove_cv<
-        typename std::remove_reference<LookupFn>::type>::type>>
-createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) {
-  using LambdaSymbolResolverImpl = LambdaSymbolResolver<
-      typename std::remove_cv<
-          typename std::remove_reference<LookupFlagsFn>::type>::type,
-      typename std::remove_cv<
-          typename std::remove_reference<LookupFn>::type>::type>;
-  return llvm::make_unique<LambdaSymbolResolverImpl>(
-      std::forward<LookupFlagsFn>(LookupFlags), std::forward<LookupFn>(Lookup));
-}
-
-/// @brief A MaterializationUnit represents a set of symbol definitions that can
+/// A MaterializationUnit represents a set of symbol definitions that can
 ///        be materialized as a group, or individually discarded (when
 ///        overriding definitions are encountered).
 ///
@@ -167,226 +204,585 @@
 /// definition is added or already present.
 class MaterializationUnit {
 public:
+  MaterializationUnit(SymbolFlagsMap InitalSymbolFlags)
+      : SymbolFlags(std::move(InitalSymbolFlags)) {}
+
   virtual ~MaterializationUnit() {}
 
-  /// @brief Return the set of symbols that this source provides.
-  virtual SymbolFlagsMap getSymbols() = 0;
+  /// Return the set of symbols that this source provides.
+  const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
 
-  /// @brief Implementations of this method should materialize all symbols
-  ///        in the materialzation unit, except for those that have been
-  ///        previously discarded.
-  virtual Error materialize(VSO &V) = 0;
+  /// Called by materialization dispatchers (see
+  /// ExecutionSession::DispatchMaterializationFunction) to trigger
+  /// materialization of this MaterializationUnit.
+  void doMaterialize(VSO &V) {
+    materialize(MaterializationResponsibility(V, std::move(SymbolFlags)));
+  }
 
-  /// @brief Implementations of this method should discard the given symbol
-  ///        from the source (e.g. if the source is an LLVM IR Module and the
-  ///        symbol is a function, delete the function body or mark it available
-  ///        externally).
-  virtual void discard(VSO &V, SymbolStringPtr Name) = 0;
+  /// Called by VSOs to notify MaterializationUnits that the given symbol has
+  /// been overridden.
+  void doDiscard(const VSO &V, SymbolStringPtr Name) {
+    SymbolFlags.erase(Name);
+    discard(V, std::move(Name));
+  }
+
+protected:
+  SymbolFlagsMap SymbolFlags;
 
 private:
   virtual void anchor();
+
+  /// Implementations of this method should materialize all symbols
+  ///        in the materialzation unit, except for those that have been
+  ///        previously discarded.
+  virtual void materialize(MaterializationResponsibility R) = 0;
+
+  /// Implementations of this method should discard the given symbol
+  ///        from the source (e.g. if the source is an LLVM IR Module and the
+  ///        symbol is a function, delete the function body or mark it available
+  ///        externally).
+  virtual void discard(const VSO &V, SymbolStringPtr Name) = 0;
 };
 
-/// @brief Represents a dynamic linkage unit in a JIT process.
+using MaterializationUnitList =
+    std::vector<std::unique_ptr<MaterializationUnit>>;
+
+/// A MaterializationUnit implementation for pre-existing absolute symbols.
 ///
-/// VSO acts as a symbol table (symbol definitions can be set and the dylib
-/// queried to find symbol addresses) and as a key for tracking resources
-/// (since a VSO's address is fixed).
-class VSO {
-  friend class ExecutionSession;
+/// All symbols will be resolved and marked ready as soon as the unit is
+/// materialized.
+class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit {
+public:
+  AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols);
+
+private:
+  void materialize(MaterializationResponsibility R) override;
+  void discard(const VSO &V, SymbolStringPtr Name) override;
+  static SymbolFlagsMap extractFlags(const SymbolMap &Symbols);
+
+  SymbolMap Symbols;
+};
+
+/// Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
+/// Useful for inserting absolute symbols into a VSO. E.g.:
+/// \code{.cpp}
+///   VSO &V = ...;
+///   SymbolStringPtr Foo = ...;
+///   JITEvaluatedSymbol FooSym = ...;
+///   if (auto Err = V.define(absoluteSymbols({{Foo, FooSym}})))
+///     return Err;
+/// \endcode
+///
+inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit>
+absoluteSymbols(SymbolMap Symbols) {
+  return llvm::make_unique<AbsoluteSymbolsMaterializationUnit>(
+      std::move(Symbols));
+}
+
+struct SymbolAliasMapEntry {
+  SymbolAliasMapEntry() = default;
+  SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags)
+      : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {}
+
+  SymbolStringPtr Aliasee;
+  JITSymbolFlags AliasFlags;
+};
+
+/// A map of Symbols to (Symbol, Flags) pairs.
+using SymbolAliasMap = std::map<SymbolStringPtr, SymbolAliasMapEntry>;
+
+/// A materialization unit for symbol aliases. Allows existing symbols to be
+/// aliased with alternate flags.
+class ReExportsMaterializationUnit : public MaterializationUnit {
+public:
+  /// SourceVSO is allowed to be nullptr, in which case the source VSO is
+  /// taken to be whatever VSO these definitions are materialized in. This
+  /// is useful for defining aliases within a VSO.
+  ///
+  /// Note: Care must be taken that no sets of aliases form a cycle, as such
+  ///       a cycle will result in a deadlock when any symbol in the cycle is
+  ///       resolved.
+  ReExportsMaterializationUnit(VSO *SourceVSO, SymbolAliasMap Aliases);
+
+private:
+  void materialize(MaterializationResponsibility R) override;
+  void discard(const VSO &V, SymbolStringPtr Name) override;
+  static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
+
+  VSO *SourceVSO = nullptr;
+  SymbolAliasMap Aliases;
+};
+
+/// Create a ReExportsMaterializationUnit with the given aliases.
+/// Useful for defining symbol aliases.: E.g., given a VSO V containing symbols
+/// "foo" and "bar", we can define aliases "baz" (for "foo") and "qux" (for
+/// "bar") with:
+/// \code{.cpp}
+///   SymbolStringPtr Baz = ...;
+///   SymbolStringPtr Qux = ...;
+///   if (auto Err = V.define(symbolAliases({
+///       {Baz, { Foo, JITSymbolFlags::Exported }},
+///       {Qux, { Bar, JITSymbolFlags::Weak }}}))
+///     return Err;
+/// \endcode
+inline std::unique_ptr<ReExportsMaterializationUnit>
+symbolAliases(SymbolAliasMap Aliases) {
+  return llvm::make_unique<ReExportsMaterializationUnit>(nullptr,
+                                                         std::move(Aliases));
+}
+
+/// Create a materialization unit for re-exporting symbols from another VSO
+/// with alternative names/flags.
+inline std::unique_ptr<ReExportsMaterializationUnit>
+reexports(VSO &SourceV, SymbolAliasMap Aliases) {
+  return llvm::make_unique<ReExportsMaterializationUnit>(&SourceV,
+                                                         std::move(Aliases));
+}
+
+/// Build a SymbolAliasMap for the common case where you want to re-export
+/// symbols from another VSO with the same linkage/flags.
+Expected<SymbolAliasMap>
+buildSimpleReexportsAliasMap(VSO &SourceV, const SymbolNameSet &Symbols);
+
+class ReexportsFallbackDefinitionGenerator {
+public:
+  using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
+  ReexportsFallbackDefinitionGenerator(VSO &BackingVSO, SymbolPredicate Allow);
+  SymbolNameSet operator()(VSO &V, const SymbolNameSet &Names);
+
+private:
+  VSO &BackingVSO;
+  SymbolPredicate Allow;
+};
+
+/// Base utilities for ExecutionSession.
+class ExecutionSessionBase {
+  // FIXME: Remove this when we remove the old ORC layers.
+  friend class VSO;
 
 public:
-  enum RelativeLinkageStrength {
-    NewDefinitionIsStronger,
-    DuplicateDefinition,
-    ExistingDefinitionIsStronger
-  };
+  /// For reporting errors.
+  using ErrorReporter = std::function<void(Error)>;
 
-  using SetDefinitionsResult =
-      std::map<SymbolStringPtr, RelativeLinkageStrength>;
+  /// For dispatching MaterializationUnit::materialize calls.
+  using DispatchMaterializationFunction =
+      std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> MU)>;
 
-  using MaterializationUnitList =
-      std::vector<std::unique_ptr<MaterializationUnit>>;
+  /// Construct an ExecutionSessionBase.
+  ///
+  /// SymbolStringPools may be shared between ExecutionSessions.
+  ExecutionSessionBase(std::shared_ptr<SymbolStringPool> SSP = nullptr)
+      : SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) {}
 
-  struct LookupResult {
-    MaterializationUnitList MaterializationUnits;
-    SymbolNameSet UnresolvedSymbols;
-  };
+  /// Returns the SymbolStringPool for this ExecutionSession.
+  SymbolStringPool &getSymbolStringPool() const { return *SSP; }
 
-  VSO() = default;
+  /// Run the given lambda with the session mutex locked.
+  template <typename Func> auto runSessionLocked(Func &&F) -> decltype(F()) {
+    std::lock_guard<std::recursive_mutex> Lock(SessionMutex);
+    return F();
+  }
+
+  /// Set the error reporter function.
+  ExecutionSessionBase &setErrorReporter(ErrorReporter ReportError) {
+    this->ReportError = std::move(ReportError);
+    return *this;
+  }
+
+  /// Set the materialization dispatch function.
+  ExecutionSessionBase &setDispatchMaterialization(
+      DispatchMaterializationFunction DispatchMaterialization) {
+    this->DispatchMaterialization = std::move(DispatchMaterialization);
+    return *this;
+  }
+
+  /// Report a error for this execution session.
+  ///
+  /// Unhandled errors can be sent here to log them.
+  void reportError(Error Err) { ReportError(std::move(Err)); }
+
+  /// Allocate a module key for a new module to add to the JIT.
+  VModuleKey allocateVModule() { return ++LastKey; }
+
+  /// Return a module key to the ExecutionSession so that it can be
+  ///        re-used. This should only be done once all resources associated
+  ///        with the original key have been released.
+  void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */
+  }
+
+  void legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err);
+
+  using LegacyAsyncLookupFunction = std::function<SymbolNameSet(
+      std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>;
+
+  /// A legacy lookup function for JITSymbolResolverAdapter.
+  /// Do not use -- this will be removed soon.
+  Expected<SymbolMap>
+  legacyLookup(ExecutionSessionBase &ES, LegacyAsyncLookupFunction AsyncLookup,
+               SymbolNameSet Names, bool WaiUntilReady,
+               RegisterDependenciesFunction RegisterDependencies);
+
+  /// Search the given VSO list for the given symbols.
+  ///
+  ///
+  /// The OnResolve callback will be called once all requested symbols are
+  /// resolved, or if an error occurs prior to resolution.
+  ///
+  /// The OnReady callback will be called once all requested symbols are ready,
+  /// or if an error occurs after resolution but before all symbols are ready.
+  ///
+  /// If all symbols are found, the RegisterDependencies function will be called
+  /// while the session lock is held. This gives clients a chance to register
+  /// dependencies for on the queried symbols for any symbols they are
+  /// materializing (if a MaterializationResponsibility instance is present,
+  /// this can be implemented by calling
+  /// MaterializationResponsibility::addDependencies). If there are no
+  /// dependenant symbols for this query (e.g. it is being made by a top level
+  /// client to get an address to call) then the value NoDependenciesToRegister
+  /// can be used.
+  void lookup(const VSOList &VSOs, const SymbolNameSet &Symbols,
+              SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady,
+              RegisterDependenciesFunction RegisterDependencies);
+
+  /// Blocking version of lookup above. Returns the resolved symbol map.
+  /// If WaitUntilReady is true (the default), will not return until all
+  /// requested symbols are ready (or an error occurs). If WaitUntilReady is
+  /// false, will return as soon as all requested symbols are resolved,
+  /// or an error occurs. If WaitUntilReady is false and an error occurs
+  /// after resolution, the function will return a success value, but the
+  /// error will be reported via reportErrors.
+  Expected<SymbolMap> lookup(const VSOList &VSOs, const SymbolNameSet &Symbols,
+                             RegisterDependenciesFunction RegisterDependencies,
+                             bool WaitUntilReady = true);
+
+  /// Materialize the given unit.
+  void dispatchMaterialization(VSO &V,
+                               std::unique_ptr<MaterializationUnit> MU) {
+    DispatchMaterialization(V, std::move(MU));
+  }
+
+private:
+  static void logErrorsToStdErr(Error Err) {
+    logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
+  }
+
+  static void
+  materializeOnCurrentThread(VSO &V, std::unique_ptr<MaterializationUnit> MU) {
+    MU->doMaterialize(V);
+  }
+
+  void runOutstandingMUs();
+
+  mutable std::recursive_mutex SessionMutex;
+  std::shared_ptr<SymbolStringPool> SSP;
+  VModuleKey LastKey = 0;
+  ErrorReporter ReportError = logErrorsToStdErr;
+  DispatchMaterializationFunction DispatchMaterialization =
+      materializeOnCurrentThread;
+
+  // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
+  //        with callbacks from asynchronous queries.
+  mutable std::recursive_mutex OutstandingMUsMutex;
+  std::vector<std::pair<VSO *, std::unique_ptr<MaterializationUnit>>>
+      OutstandingMUs;
+};
+
+/// A symbol query that returns results via a callback when results are
+///        ready.
+///
+/// makes a callback when all symbols are available.
+class AsynchronousSymbolQuery {
+  friend class ExecutionSessionBase;
+  friend class VSO;
+
+public:
+
+  /// Create a query for the given symbols, notify-resolved and
+  ///        notify-ready callbacks.
+  AsynchronousSymbolQuery(const SymbolNameSet &Symbols,
+                          SymbolsResolvedCallback NotifySymbolsResolved,
+                          SymbolsReadyCallback NotifySymbolsReady);
+
+  /// Set the resolved symbol information for the given symbol name.
+  void resolve(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym);
+
+  /// Returns true if all symbols covered by this query have been
+  ///        resolved.
+  bool isFullyResolved() const { return NotYetResolvedCount == 0; }
+
+  /// Call the NotifySymbolsResolved callback.
+  ///
+  /// This should only be called if all symbols covered by the query have been
+  /// resolved.
+  void handleFullyResolved();
+
+  /// Notify the query that a requested symbol is ready for execution.
+  void notifySymbolReady();
+
+  /// Returns true if all symbols covered by this query are ready.
+  bool isFullyReady() const { return NotYetReadyCount == 0; }
+
+  /// Calls the NotifySymbolsReady callback.
+  ///
+  /// This should only be called if all symbols covered by this query are ready.
+  void handleFullyReady();
+
+private:
+  void addQueryDependence(VSO &V, SymbolStringPtr Name);
+
+  void removeQueryDependence(VSO &V, const SymbolStringPtr &Name);
+
+  bool canStillFail();
+
+  void handleFailed(Error Err);
+
+  void detach();
+
+  SymbolsResolvedCallback NotifySymbolsResolved;
+  SymbolsReadyCallback NotifySymbolsReady;
+  SymbolDependenceMap QueryRegistrations;
+  SymbolMap ResolvedSymbols;
+  size_t NotYetResolvedCount;
+  size_t NotYetReadyCount;
+};
+
+/// A symbol table that supports asynchoronous symbol queries.
+///
+/// Represents a virtual shared object. Instances can not be copied or moved, so
+/// their addresses may be used as keys for resource management.
+/// VSO state changes must be made via an ExecutionSession to guarantee that
+/// they are synchronized with respect to other VSO operations.
+class VSO {
+  friend class AsynchronousSymbolQuery;
+  friend class ExecutionSession;
+  friend class ExecutionSessionBase;
+  friend class MaterializationResponsibility;
+public:
+  using FallbackDefinitionGeneratorFunction =
+      std::function<SymbolNameSet(VSO &Parent, const SymbolNameSet &Names)>;
+
+  using AsynchronousSymbolQuerySet =
+      std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
 
   VSO(const VSO &) = delete;
   VSO &operator=(const VSO &) = delete;
   VSO(VSO &&) = delete;
   VSO &operator=(VSO &&) = delete;
 
-  /// @brief Compare new linkage with existing linkage.
-  static RelativeLinkageStrength
-  compareLinkage(Optional<JITSymbolFlags> OldFlags, JITSymbolFlags NewFlags);
+  /// Get the name for this VSO.
+  const std::string &getName() const { return VSOName; }
 
-  /// @brief Compare new linkage with an existing symbol's linkage.
-  RelativeLinkageStrength compareLinkage(SymbolStringPtr Name,
-                                         JITSymbolFlags NewFlags) const;
+  /// Get a reference to the ExecutionSession for this VSO.
+  ExecutionSessionBase &getExecutionSession() const { return ES; }
 
-  /// @brief Adds the given symbols to the mapping as resolved, finalized
-  ///        symbols.
+  /// Set a fallback defenition generator. If set, lookup and lookupFlags will
+  /// pass the unresolved symbols set to the fallback definition generator,
+  /// allowing it to add a new definition to the VSO.
+  void setFallbackDefinitionGenerator(
+      FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator) {
+    this->FallbackDefinitionGenerator = std::move(FallbackDefinitionGenerator);
+  }
+
+  /// Set the search order to be used when fixing up definitions in VSO.
+  /// This will replace the previous search order, and apply to any symbol
+  /// resolutions made for definitions in this VSO after the call to
+  /// setSearchOrder (even if the definition itself was added before the
+  /// call).
   ///
-  /// FIXME: We can take this by const-ref once symbol-based laziness is
-  ///        removed.
-  Error define(SymbolMap NewSymbols);
-
-  /// @brief Adds the given symbols to the mapping as lazy symbols.
-  Error defineLazy(std::unique_ptr<MaterializationUnit> Source);
-
-  /// @brief Add the given symbol/address mappings to the dylib, but do not
-  ///        mark the symbols as finalized yet.
-  void resolve(SymbolMap SymbolValues);
-
-  /// @brief Finalize the given symbols.
-  void finalize(SymbolNameSet SymbolsToFinalize);
-
-  /// @brief Look up the flags for the given symbols.
+  /// If SearchThisVSOFirst is set, which by default it is, then this VSO will
+  /// add itself to the beginning of the SearchOrder (Clients should *not*
+  /// put this VSO in the list in this case, to avoid redundant lookups).
   ///
-  /// Returns the flags for the give symbols, together with the set of symbols
-  /// not found.
-  SymbolNameSet lookupFlags(SymbolFlagsMap &Flags, SymbolNameSet Symbols);
+  /// If SearchThisVSOFirst is false then the search order will be used as
+  /// given. The main motivation for this feature is to support deliberate
+  /// shadowing of symbols in this VSO by a facade VSO. For example, the
+  /// facade may resolve function names to stubs, and the stubs may compile
+  /// lazily by looking up symbols in this dylib. Adding the facade dylib
+  /// as the first in the search order (instead of this dylib) ensures that
+  /// definitions within this dylib resolve to the lazy-compiling stubs,
+  /// rather than immediately materializing the definitions in this dylib.
+  void setSearchOrder(VSOList NewSearchOrder, bool SearchThisVSOFirst = true);
 
-  /// @brief Apply the given query to the given symbols in this VSO.
+  /// Add the given VSO to the search order for definitions in this VSO.
+  void addToSearchOrder(VSO &V);
+
+  /// Replace OldV with NewV in the search order if OldV is present. Otherwise
+  /// this operation is a no-op.
+  void replaceInSearchOrder(VSO &OldV, VSO &NewV);
+
+  /// Remove the given VSO from the search order for this VSO if it is
+  /// present. Otherwise this operation is a no-op.
+  void removeFromSearchOrder(VSO &V);
+
+  /// Do something with the search order (run under the session lock).
+  template <typename Func>
+  auto withSearchOrderDo(Func &&F)
+      -> decltype(F(std::declval<const VSOList &>())) {
+    return ES.runSessionLocked([&]() { return F(SearchOrder); });
+  }
+
+  /// Define all symbols provided by the materialization unit to be part
+  ///        of the given VSO.
+  template <typename UniquePtrToMaterializationUnit>
+  typename std::enable_if<
+      std::is_convertible<
+          typename std::decay<UniquePtrToMaterializationUnit>::type,
+          std::unique_ptr<MaterializationUnit>>::value,
+      Error>::type
+  define(UniquePtrToMaterializationUnit &&MU) {
+    return ES.runSessionLocked([&, this]() -> Error {
+      assert(MU && "Can't define with a null MU");
+
+      if (auto Err = defineImpl(*MU))
+        return Err;
+
+      /// defineImpl succeeded.
+      auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
+      for (auto &KV : UMI->MU->getSymbols())
+        UnmaterializedInfos[KV.first] = UMI;
+
+      return Error::success();
+    });
+  }
+
+  /// Search the given VSO for the symbols in Symbols. If found, store
+  ///        the flags for each symbol in Flags. Returns any unresolved symbols.
+  SymbolFlagsMap lookupFlags(const SymbolNameSet &Names);
+
+  /// Dump current VSO state to OS.
+  void dump(raw_ostream &OS);
+
+  /// FIXME: Remove this when we remove the old ORC layers.
+  /// Search the given VSOs in order for the symbols in Symbols. Results
+  ///        (once they become available) will be returned via the given Query.
   ///
-  /// For symbols in this VSO that have already been materialized, their address
-  /// will be set in the query immediately.
-  ///
-  /// For symbols in this VSO that have not been materialized, the query will be
-  /// recorded and the source for those symbols (plus the set of symbols to be
-  /// materialized by that source) will be returned as the MaterializationWork
-  /// field of the LookupResult.
-  ///
-  /// Any symbols not found in this VSO will be returned in the
-  /// UnresolvedSymbols field of the LookupResult.
-  LookupResult lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
-                      SymbolNameSet Symbols);
+  /// If any symbol is not found then the unresolved symbols will be returned,
+  /// and the query will not be applied. The Query is not failed and can be
+  /// re-used in a subsequent lookup once the symbols have been added, or
+  /// manually failed.
+  SymbolNameSet legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
+                             SymbolNameSet Names);
 
 private:
-  class MaterializationInfo {
-  public:
-    using QueryList = std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
+  using AsynchronousSymbolQueryList =
+      std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
 
-    MaterializationInfo(size_t SymbolsRemaining,
-                        std::unique_ptr<MaterializationUnit> MU);
+  struct UnmaterializedInfo {
+    UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU)
+        : MU(std::move(MU)) {}
 
-    uint64_t SymbolsRemaining;
     std::unique_ptr<MaterializationUnit> MU;
-    SymbolMap Symbols;
-    std::map<SymbolStringPtr, QueryList> PendingResolution;
-    std::map<SymbolStringPtr, QueryList> PendingFinalization;
   };
 
-  using MaterializationInfoSet = std::set<std::unique_ptr<MaterializationInfo>>;
+  using UnmaterializedInfosMap =
+      std::map<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
 
-  using MaterializationInfoIterator = MaterializationInfoSet::iterator;
-
-  class SymbolTableEntry {
-  public:
-    SymbolTableEntry(JITSymbolFlags SymbolFlags,
-                     MaterializationInfoIterator MaterializationInfoItr);
-    SymbolTableEntry(JITEvaluatedSymbol Sym);
-    SymbolTableEntry(SymbolTableEntry &&Other);
-    ~SymbolTableEntry();
-
-    SymbolTableEntry &operator=(JITEvaluatedSymbol Sym);
-
-    JITSymbolFlags getFlags() const;
-    void replaceWith(VSO &V, SymbolStringPtr Name, JITSymbolFlags Flags,
-                     MaterializationInfoIterator NewMaterializationInfoItr);
-    std::unique_ptr<MaterializationUnit>
-    query(SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query);
-    void resolve(VSO &V, SymbolStringPtr Name, JITEvaluatedSymbol Sym);
-    void finalize(VSO &V, SymbolStringPtr Name);
-    void discard(VSO &V, SymbolStringPtr Name);
-
-  private:
-    void destroy();
-
-    JITSymbolFlags Flags;
-    MaterializationInfoIterator MII;
-    union {
-      JITTargetAddress Address;
-      MaterializationInfoIterator MaterializationInfoItr;
-    };
+  struct MaterializingInfo {
+    AsynchronousSymbolQueryList PendingQueries;
+    SymbolDependenceMap Dependants;
+    SymbolDependenceMap UnfinalizedDependencies;
+    bool IsFinalized = false;
   };
 
-  std::map<SymbolStringPtr, SymbolTableEntry> Symbols;
-  MaterializationInfoSet MaterializationInfos;
+  using MaterializingInfosMap = std::map<SymbolStringPtr, MaterializingInfo>;
+
+  using LookupImplActionFlags = enum {
+    None = 0,
+    NotifyFullyResolved = 1 << 0U,
+    NotifyFullyReady = 1 << 1U,
+    LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady)
+  };
+
+  VSO(ExecutionSessionBase &ES, std::string Name);
+
+  Error defineImpl(MaterializationUnit &MU);
+
+  SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags,
+                                const SymbolNameSet &Names);
+
+  void lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
+                  SymbolNameSet &Unresolved, MaterializationUnitList &MUs);
+
+  void lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
+                      SymbolNameSet &Unresolved, MaterializationUnitList &MUs);
+
+  LookupImplActionFlags
+  lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
+             std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
+             SymbolNameSet &Unresolved);
+
+  void detachQueryHelper(AsynchronousSymbolQuery &Q,
+                         const SymbolNameSet &QuerySymbols);
+
+  void transferFinalizedNodeDependencies(MaterializingInfo &DependantMI,
+                                         const SymbolStringPtr &DependantName,
+                                         MaterializingInfo &FinalizedMI);
+
+  Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
+
+  void replace(std::unique_ptr<MaterializationUnit> MU);
+
+  SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags);
+
+  void addDependencies(const SymbolStringPtr &Name,
+                       const SymbolDependenceMap &Dependants);
+
+  void resolve(const SymbolMap &Resolved);
+
+  void finalize(const SymbolFlagsMap &Finalized);
+
+  void notifyFailed(const SymbolNameSet &FailedSymbols);
+
+  ExecutionSessionBase &ES;
+  std::string VSOName;
+  SymbolMap Symbols;
+  UnmaterializedInfosMap UnmaterializedInfos;
+  MaterializingInfosMap MaterializingInfos;
+  FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator;
+  VSOList SearchOrder;
 };
 
-/// @brief An ExecutionSession represents a running JIT program.
-class ExecutionSession {
+/// An ExecutionSession represents a running JIT program.
+class ExecutionSession : public ExecutionSessionBase {
 public:
   using ErrorReporter = std::function<void(Error)>;
 
-  /// @brief Construct an ExecutionEngine.
+  using DispatchMaterializationFunction =
+      std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> MU)>;
+
+  /// Construct an ExecutionEngine.
   ///
   /// SymbolStringPools may be shared between ExecutionSessions.
-  ExecutionSession(SymbolStringPool &SSP);
+  ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr)
+      : ExecutionSessionBase(std::move(SSP)) {}
 
-  /// @brief Returns the SymbolStringPool for this ExecutionSession.
-  SymbolStringPool &getSymbolStringPool() const { return SSP; }
-
-  /// @brief Set the error reporter function.
-  void setErrorReporter(ErrorReporter ReportError) {
-    this->ReportError = std::move(ReportError);
-  }
-
-  /// @brief Report a error for this execution session.
-  ///
-  /// Unhandled errors can be sent here to log them.
-  void reportError(Error Err) { ReportError(std::move(Err)); }
-
-  /// @brief Allocate a module key for a new module to add to the JIT.
-  VModuleKey allocateVModule();
-
-  /// @brief Return a module key to the ExecutionSession so that it can be
-  ///        re-used. This should only be done once all resources associated
-  ////       with the original key have been released.
-  void releaseVModule(VModuleKey Key);
-
-public:
-  static void logErrorsToStdErr(Error Err);
-
-  SymbolStringPool &SSP;
-  VModuleKey LastKey = 0;
-  ErrorReporter ReportError = logErrorsToStdErr;
-};
-
-/// Runs Materializers on the current thread and reports errors to the given
-/// ExecutionSession.
-class MaterializeOnCurrentThread {
-public:
-  MaterializeOnCurrentThread(ExecutionSession &ES) : ES(ES) {}
-
-  void operator()(VSO &V, std::unique_ptr<MaterializationUnit> MU) {
-    if (auto Err = MU->materialize(V))
-      ES.reportError(std::move(Err));
-  }
+  /// Add a new VSO to this ExecutionSession.
+  VSO &createVSO(std::string Name);
 
 private:
-  ExecutionSession &ES;
+  std::vector<std::unique_ptr<VSO>> VSOs;
 };
 
-/// Materialization function object wrapper for the lookup method.
-using MaterializationDispatcher =
-    std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> S)>;
+/// Look up the given names in the given VSOs.
+/// VSOs will be searched in order and no VSO pointer may be null.
+/// All symbols must be found within the given VSOs or an error
+/// will be returned.
+Expected<SymbolMap> lookup(const VSOList &VSOs, SymbolNameSet Names);
 
-/// @brief Look up a set of symbols by searching a list of VSOs.
-///
-/// All VSOs in the list should be non-null.
-Expected<SymbolMap> lookup(const std::vector<VSO *> &VSOs, SymbolNameSet Names,
-                           MaterializationDispatcher DispatchMaterialization);
+/// Look up a symbol by searching a list of VSOs.
+Expected<JITEvaluatedSymbol> lookup(const VSOList &VSOs, SymbolStringPtr Name);
 
-/// @brief Look up a symbol by searching a list of VSOs.
-Expected<JITEvaluatedSymbol>
-lookup(const std::vector<VSO *> VSOs, SymbolStringPtr Name,
-       MaterializationDispatcher DispatchMaterialization);
+/// Mangles symbol names then uniques them in the context of an
+/// ExecutionSession.
+class MangleAndInterner {
+public:
+  MangleAndInterner(ExecutionSessionBase &ES, const DataLayout &DL);
+  SymbolStringPtr operator()(StringRef Name);
+
+private:
+  ExecutionSessionBase &ES;
+  const DataLayout &DL;
+};
 
 } // End namespace orc
 } // End namespace llvm
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
index d466df8..e27f6e1 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
@@ -20,6 +20,8 @@
 #include "llvm/ExecutionEngine/Orc/Core.h"
 #include "llvm/ExecutionEngine/Orc/OrcError.h"
 #include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Target/TargetOptions.h"
 #include <algorithm>
 #include <cstdint>
 #include <string>
@@ -32,18 +34,58 @@
 class GlobalVariable;
 class Function;
 class Module;
+class TargetMachine;
 class Value;
 
 namespace orc {
 
-/// @brief This iterator provides a convenient way to iterate over the elements
+/// A utility class for building TargetMachines for JITs.
+class JITTargetMachineBuilder {
+public:
+  JITTargetMachineBuilder(Triple TT);
+  static Expected<JITTargetMachineBuilder> detectHost();
+  Expected<std::unique_ptr<TargetMachine>> createTargetMachine();
+
+  JITTargetMachineBuilder &setArch(std::string Arch) {
+    this->Arch = std::move(Arch);
+    return *this;
+  }
+  JITTargetMachineBuilder &setCPU(std::string CPU) {
+    this->CPU = std::move(CPU);
+    return *this;
+  }
+  JITTargetMachineBuilder &setRelocationModel(Optional<Reloc::Model> RM) {
+    this->RM = std::move(RM);
+    return *this;
+  }
+  JITTargetMachineBuilder &setCodeModel(Optional<CodeModel::Model> CM) {
+    this->CM = std::move(CM);
+    return *this;
+  }
+  JITTargetMachineBuilder &
+  addFeatures(const std::vector<std::string> &FeatureVec);
+  SubtargetFeatures &getFeatures() { return Features; }
+  TargetOptions &getOptions() { return Options; }
+
+private:
+  Triple TT;
+  std::string Arch;
+  std::string CPU;
+  SubtargetFeatures Features;
+  TargetOptions Options;
+  Optional<Reloc::Model> RM;
+  Optional<CodeModel::Model> CM;
+  CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
+};
+
+/// This iterator provides a convenient way to iterate over the elements
 ///        of an llvm.global_ctors/llvm.global_dtors instance.
 ///
 ///   The easiest way to get hold of instances of this class is to use the
 /// getConstructors/getDestructors functions.
 class CtorDtorIterator {
 public:
-  /// @brief Accessor for an element of the global_ctors/global_dtors array.
+  /// Accessor for an element of the global_ctors/global_dtors array.
   ///
   ///   This class provides a read-only view of the element with any casts on
   /// the function stripped away.
@@ -56,23 +98,23 @@
     Value *Data;
   };
 
-  /// @brief Construct an iterator instance. If End is true then this iterator
+  /// Construct an iterator instance. If End is true then this iterator
   ///        acts as the end of the range, otherwise it is the beginning.
   CtorDtorIterator(const GlobalVariable *GV, bool End);
 
-  /// @brief Test iterators for equality.
+  /// Test iterators for equality.
   bool operator==(const CtorDtorIterator &Other) const;
 
-  /// @brief Test iterators for inequality.
+  /// Test iterators for inequality.
   bool operator!=(const CtorDtorIterator &Other) const;
 
-  /// @brief Pre-increment iterator.
+  /// Pre-increment iterator.
   CtorDtorIterator& operator++();
 
-  /// @brief Post-increment iterator.
+  /// Post-increment iterator.
   CtorDtorIterator operator++(int);
 
-  /// @brief Dereference iterator. The resulting value provides a read-only view
+  /// Dereference iterator. The resulting value provides a read-only view
   ///        of this element of the global_ctors/global_dtors list.
   Element operator*() const;
 
@@ -81,25 +123,25 @@
   unsigned I;
 };
 
-/// @brief Create an iterator range over the entries of the llvm.global_ctors
+/// Create an iterator range over the entries of the llvm.global_ctors
 ///        array.
 iterator_range<CtorDtorIterator> getConstructors(const Module &M);
 
-/// @brief Create an iterator range over the entries of the llvm.global_ctors
+/// Create an iterator range over the entries of the llvm.global_ctors
 ///        array.
 iterator_range<CtorDtorIterator> getDestructors(const Module &M);
 
-/// @brief Convenience class for recording constructor/destructor names for
+/// Convenience class for recording constructor/destructor names for
 ///        later execution.
 template <typename JITLayerT>
 class CtorDtorRunner {
 public:
-  /// @brief Construct a CtorDtorRunner for the given range using the given
+  /// Construct a CtorDtorRunner for the given range using the given
   ///        name mangling function.
   CtorDtorRunner(std::vector<std::string> CtorDtorNames, VModuleKey K)
       : CtorDtorNames(std::move(CtorDtorNames)), K(K) {}
 
-  /// @brief Run the recorded constructors/destructors through the given JIT
+  /// Run the recorded constructors/destructors through the given JIT
   ///        layer.
   Error runViaLayer(JITLayerT &JITLayer) const {
     using CtorDtorTy = void (*)();
@@ -127,7 +169,21 @@
   orc::VModuleKey K;
 };
 
-/// @brief Support class for static dtor execution. For hosted (in-process) JITs
+class CtorDtorRunner2 {
+public:
+  CtorDtorRunner2(VSO &V) : V(V) {}
+  void add(iterator_range<CtorDtorIterator> CtorDtors);
+  Error run();
+
+private:
+  using CtorDtorList = std::vector<SymbolStringPtr>;
+  using CtorDtorPriorityMap = std::map<unsigned, CtorDtorList>;
+
+  VSO &V;
+  CtorDtorPriorityMap CtorDtorsByPriority;
+};
+
+/// Support class for static dtor execution. For hosted (in-process) JITs
 ///        only!
 ///
 ///   If a __cxa_atexit function isn't found C++ programs that use static
@@ -142,7 +198,26 @@
 /// the client determines that destructors should be run (generally at JIT
 /// teardown or after a return from main), the runDestructors method should be
 /// called.
-class LocalCXXRuntimeOverrides {
+class LocalCXXRuntimeOverridesBase {
+public:
+  /// Run any destructors recorded by the overriden __cxa_atexit function
+  /// (CXAAtExitOverride).
+  void runDestructors();
+
+protected:
+  template <typename PtrTy> JITTargetAddress toTargetAddress(PtrTy *P) {
+    return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P));
+  }
+
+  using DestructorPtr = void (*)(void *);
+  using CXXDestructorDataPair = std::pair<DestructorPtr, void *>;
+  using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>;
+  CXXDestructorDataPairList DSOHandleOverride;
+  static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
+                               void *DSOHandle);
+};
+
+class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {
 public:
   /// Create a runtime-overrides class.
   template <typename MangleFtorT>
@@ -159,32 +234,38 @@
     return nullptr;
   }
 
-  /// Run any destructors recorded by the overriden __cxa_atexit function
-  /// (CXAAtExitOverride).
-  void runDestructors();
-
 private:
-  template <typename PtrTy>
-  JITTargetAddress toTargetAddress(PtrTy* P) {
-    return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P));
-  }
-
   void addOverride(const std::string &Name, JITTargetAddress Addr) {
     CXXRuntimeOverrides.insert(std::make_pair(Name, Addr));
   }
 
   StringMap<JITTargetAddress> CXXRuntimeOverrides;
+};
 
-  using DestructorPtr = void (*)(void *);
-  using CXXDestructorDataPair = std::pair<DestructorPtr, void *>;
-  using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>;
-  CXXDestructorDataPairList DSOHandleOverride;
-  static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
-                               void *DSOHandle);
+class LocalCXXRuntimeOverrides2 : public LocalCXXRuntimeOverridesBase {
+public:
+  Error enable(VSO &V, MangleAndInterner &Mangler);
+};
+
+/// A utility class to expose symbols found via dlsym to the JIT.
+///
+/// If an instance of this class is attached to a VSO as a fallback definition
+/// generator, then any symbol found in the given DynamicLibrary that passes
+/// the 'Allow' predicate will be added to the VSO.
+class DynamicLibraryFallbackGenerator {
+public:
+  using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
+  DynamicLibraryFallbackGenerator(sys::DynamicLibrary Dylib,
+                                  const DataLayout &DL, SymbolPredicate Allow);
+  SymbolNameSet operator()(VSO &V, const SymbolNameSet &Names);
+
+private:
+  sys::DynamicLibrary Dylib;
+  SymbolPredicate Allow;
+  char GlobalPrefix;
 };
 
 } // end namespace orc
-
 } // end namespace llvm
 
 #endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h
index 8a48c36..a8a88d7 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h
@@ -27,7 +27,7 @@
 
 namespace orc {
 
-/// @brief Global mapping layer.
+/// Global mapping layer.
 ///
 ///   This layer overrides the findSymbol method to first search a local symbol
 /// table that the client can define. It can be used to inject new symbol
@@ -38,13 +38,13 @@
 class GlobalMappingLayer {
 public:
 
-  /// @brief Handle to an added module.
+  /// Handle to an added module.
   using ModuleHandleT = typename BaseLayerT::ModuleHandleT;
 
-  /// @brief Construct an GlobalMappingLayer with the given BaseLayer
+  /// Construct an GlobalMappingLayer with the given BaseLayer
   GlobalMappingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
 
-  /// @brief Add the given module to the JIT.
+  /// Add the given module to the JIT.
   /// @return A handle for the added modules.
   Expected<ModuleHandleT>
   addModule(std::shared_ptr<Module> M,
@@ -52,20 +52,20 @@
     return BaseLayer.addModule(std::move(M), std::move(Resolver));
   }
 
-  /// @brief Remove the module set associated with the handle H.
+  /// Remove the module set associated with the handle H.
   Error removeModule(ModuleHandleT H) { return BaseLayer.removeModule(H); }
 
-  /// @brief Manually set the address to return for the given symbol.
+  /// Manually set the address to return for the given symbol.
   void setGlobalMapping(const std::string &Name, JITTargetAddress Addr) {
     SymbolTable[Name] = Addr;
   }
 
-  /// @brief Remove the given symbol from the global mapping.
+  /// Remove the given symbol from the global mapping.
   void eraseGlobalMapping(const std::string &Name) {
     SymbolTable.erase(Name);
   }
 
-  /// @brief Search for the given named symbol.
+  /// Search for the given named symbol.
   ///
   ///          This method will first search the local symbol table, returning
   ///        any symbol found there. If the symbol is not found in the local
@@ -81,7 +81,7 @@
     return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
   }
 
-  /// @brief Get the address of the given symbol in the context of the of the
+  /// Get the address of the given symbol in the context of the of the
   ///        module represented by the handle H. This call is forwarded to the
   ///        base layer's implementation.
   /// @param H The handle for the module to search in.
@@ -94,7 +94,7 @@
     return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
   }
 
-  /// @brief Immediately emit and finalize the module set represented by the
+  /// Immediately emit and finalize the module set represented by the
   ///        given handle.
   /// @param H Handle for module set to emit/finalize.
   Error emitAndFinalize(ModuleHandleT H) {
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
index a7f9416..ad64815 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
@@ -16,8 +16,9 @@
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include <memory>
 #include <string>
 
@@ -27,7 +28,30 @@
 
 namespace orc {
 
-/// @brief Eager IR compiling layer.
+class IRCompileLayer2 : public IRLayer {
+public:
+  using CompileFunction =
+      std::function<Expected<std::unique_ptr<MemoryBuffer>>(Module &)>;
+
+  using NotifyCompiledFunction =
+      std::function<void(VModuleKey K, std::unique_ptr<Module>)>;
+
+  IRCompileLayer2(ExecutionSession &ES, ObjectLayer &BaseLayer,
+                  CompileFunction Compile);
+
+  void setNotifyCompiled(NotifyCompiledFunction NotifyCompiled);
+
+  void emit(MaterializationResponsibility R, VModuleKey K,
+            std::unique_ptr<Module> M) override;
+
+private:
+  mutable std::mutex IRLayerMutex;
+  ObjectLayer &BaseLayer;
+  CompileFunction Compile;
+  NotifyCompiledFunction NotifyCompiled = NotifyCompiledFunction();
+};
+
+/// Eager IR compiling layer.
 ///
 ///   This layer immediately compiles each IR module added via addModule to an
 /// object file and adds this module file to the layer below, which must
@@ -35,11 +59,11 @@
 template <typename BaseLayerT, typename CompileFtor>
 class IRCompileLayer {
 public:
-  /// @brief Callback type for notifications when modules are compiled.
+  /// Callback type for notifications when modules are compiled.
   using NotifyCompiledCallback =
       std::function<void(VModuleKey K, std::unique_ptr<Module>)>;
 
-  /// @brief Construct an IRCompileLayer with the given BaseLayer, which must
+  /// Construct an IRCompileLayer with the given BaseLayer, which must
   ///        implement the ObjectLayer concept.
   IRCompileLayer(
       BaseLayerT &BaseLayer, CompileFtor Compile,
@@ -47,15 +71,15 @@
       : BaseLayer(BaseLayer), Compile(std::move(Compile)),
         NotifyCompiled(std::move(NotifyCompiled)) {}
 
-  /// @brief Get a reference to the compiler functor.
+  /// Get a reference to the compiler functor.
   CompileFtor& getCompiler() { return Compile; }
 
-  /// @brief (Re)set the NotifyCompiled callback.
+  /// (Re)set the NotifyCompiled callback.
   void setNotifyCompiled(NotifyCompiledCallback NotifyCompiled) {
     this->NotifyCompiled = std::move(NotifyCompiled);
   }
 
-  /// @brief Compile the module, and add the resulting object to the base layer
+  /// Compile the module, and add the resulting object to the base layer
   ///        along with the given memory manager and symbol resolver.
   Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
     if (auto Err = BaseLayer.addObject(std::move(K), Compile(*M)))
@@ -65,10 +89,10 @@
     return Error::success();
   }
 
-  /// @brief Remove the module associated with the VModuleKey K.
+  /// Remove the module associated with the VModuleKey K.
   Error removeModule(VModuleKey K) { return BaseLayer.removeObject(K); }
 
-  /// @brief Search for the given named symbol.
+  /// Search for the given named symbol.
   /// @param Name The name of the symbol to search for.
   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
   /// @return A handle for the given named symbol, if it exists.
@@ -76,7 +100,7 @@
     return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
   }
 
-  /// @brief Get the address of the given symbol in compiled module represented
+  /// Get the address of the given symbol in compiled module represented
   ///        by the handle H. This call is forwarded to the base layer's
   ///        implementation.
   /// @param K The VModuleKey for the module to search in.
@@ -89,7 +113,7 @@
     return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
   }
 
-  /// @brief Immediately emit and finalize the module represented by the given
+  /// Immediately emit and finalize the module represented by the given
   ///        handle.
   /// @param K The VModuleKey for the module to emit/finalize.
   Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); }
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
index 4f1fe7b..266a0f4 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
@@ -15,7 +15,7 @@
 #define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
 
 #include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
 #include <memory>
 #include <string>
 
@@ -23,7 +23,32 @@
 class Module;
 namespace orc {
 
-/// @brief IR mutating layer.
+class IRTransformLayer2 : public IRLayer {
+public:
+
+  using TransformFunction =
+    std::function<Expected<std::unique_ptr<Module>>(std::unique_ptr<Module>)>;
+
+  IRTransformLayer2(ExecutionSession &ES, IRLayer &BaseLayer,
+                    TransformFunction Transform = identityTransform);
+
+  void setTransform(TransformFunction Transform) {
+    this->Transform = std::move(Transform);
+  }
+
+  void emit(MaterializationResponsibility R, VModuleKey K,
+            std::unique_ptr<Module> M) override;
+
+  static std::unique_ptr<Module> identityTransform(std::unique_ptr<Module> M) {
+    return M;
+  }
+
+private:
+  IRLayer &BaseLayer;
+  TransformFunction Transform;
+};
+
+/// IR mutating layer.
 ///
 ///   This layer applies a user supplied transform to each module that is added,
 /// then adds the transformed module to the layer below.
@@ -31,12 +56,12 @@
 class IRTransformLayer {
 public:
 
-  /// @brief Construct an IRTransformLayer with the given BaseLayer
+  /// Construct an IRTransformLayer with the given BaseLayer
   IRTransformLayer(BaseLayerT &BaseLayer,
                    TransformFtor Transform = TransformFtor())
     : BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
 
-  /// @brief Apply the transform functor to the module, then add the module to
+  /// Apply the transform functor to the module, then add the module to
   ///        the layer below, along with the memory manager and symbol resolver.
   ///
   /// @return A handle for the added modules.
@@ -44,10 +69,10 @@
     return BaseLayer.addModule(std::move(K), Transform(std::move(M)));
   }
 
-  /// @brief Remove the module associated with the VModuleKey K.
+  /// Remove the module associated with the VModuleKey K.
   Error removeModule(VModuleKey K) { return BaseLayer.removeModule(K); }
 
-  /// @brief Search for the given named symbol.
+  /// Search for the given named symbol.
   /// @param Name The name of the symbol to search for.
   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
   /// @return A handle for the given named symbol, if it exists.
@@ -55,7 +80,7 @@
     return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
   }
 
-  /// @brief Get the address of the given symbol in the context of the module
+  /// Get the address of the given symbol in the context of the module
   ///        represented by the VModuleKey K. This call is forwarded to the base
   ///        layer's implementation.
   /// @param K The VModuleKey for the module to search in.
@@ -68,15 +93,15 @@
     return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
   }
 
-  /// @brief Immediately emit and finalize the module represented by the given
+  /// Immediately emit and finalize the module represented by the given
   ///        VModuleKey.
   /// @param K The VModuleKey for the module to emit/finalize.
   Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); }
 
-  /// @brief Access the transform functor directly.
+  /// Access the transform functor directly.
   TransformFtor& getTransform() { return Transform; }
 
-  /// @brief Access the mumate functor directly.
+  /// Access the mumate functor directly.
   const TransformFtor& getTransform() const { return Transform; }
 
 private:
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
index 029b86a..8b0b3fd 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
@@ -18,6 +18,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Memory.h"
 #include "llvm/Support/Process.h"
@@ -46,98 +47,29 @@
 
 namespace orc {
 
-/// @brief Target-independent base class for compile callback management.
+/// Target-independent base class for compile callback management.
 class JITCompileCallbackManager {
 public:
-  using CompileFtor = std::function<JITTargetAddress()>;
+  using CompileFunction = std::function<JITTargetAddress()>;
 
-  /// @brief Handle to a newly created compile callback. Can be used to get an
-  ///        IR constant representing the address of the trampoline, and to set
-  ///        the compile action for the callback.
-  class CompileCallbackInfo {
-  public:
-    CompileCallbackInfo(JITTargetAddress Addr, CompileFtor &Compile)
-        : Addr(Addr), Compile(Compile) {}
-
-    JITTargetAddress getAddress() const { return Addr; }
-    void setCompileAction(CompileFtor Compile) {
-      this->Compile = std::move(Compile);
-    }
-
-  private:
-    JITTargetAddress Addr;
-    CompileFtor &Compile;
-  };
-
-  /// @brief Construct a JITCompileCallbackManager.
+  /// Construct a JITCompileCallbackManager.
   /// @param ErrorHandlerAddress The address of an error handler in the target
   ///                            process to be used if a compile callback fails.
-  JITCompileCallbackManager(JITTargetAddress ErrorHandlerAddress)
-      : ErrorHandlerAddress(ErrorHandlerAddress) {}
+  JITCompileCallbackManager(ExecutionSession &ES,
+                            JITTargetAddress ErrorHandlerAddress)
+      : ES(ES), CallbacksVSO(ES.createVSO("<Callbacks>")),
+        ErrorHandlerAddress(ErrorHandlerAddress) {}
 
   virtual ~JITCompileCallbackManager() = default;
 
-  /// @brief Execute the callback for the given trampoline id. Called by the JIT
+  /// Reserve a compile callback.
+  Expected<JITTargetAddress> getCompileCallback(CompileFunction Compile);
+
+  /// Execute the callback for the given trampoline id. Called by the JIT
   ///        to compile functions on demand.
-  JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr) {
-    auto I = ActiveTrampolines.find(TrampolineAddr);
-    // FIXME: Also raise an error in the Orc error-handler when we finally have
-    //        one.
-    if (I == ActiveTrampolines.end())
-      return ErrorHandlerAddress;
-
-    // Found a callback handler. Yank this trampoline out of the active list and
-    // put it back in the available trampolines list, then try to run the
-    // handler's compile and update actions.
-    // Moving the trampoline ID back to the available list first means there's
-    // at
-    // least one available trampoline if the compile action triggers a request
-    // for
-    // a new one.
-    auto Compile = std::move(I->second);
-    ActiveTrampolines.erase(I);
-    AvailableTrampolines.push_back(TrampolineAddr);
-
-    if (auto Addr = Compile())
-      return Addr;
-
-    return ErrorHandlerAddress;
-  }
-
-  /// @brief Reserve a compile callback.
-  Expected<CompileCallbackInfo> getCompileCallback() {
-    if (auto TrampolineAddrOrErr = getAvailableTrampolineAddr()) {
-      const auto &TrampolineAddr = *TrampolineAddrOrErr;
-      auto &Compile = this->ActiveTrampolines[TrampolineAddr];
-      return CompileCallbackInfo(TrampolineAddr, Compile);
-    } else
-      return TrampolineAddrOrErr.takeError();
-  }
-
-  /// @brief Get a CompileCallbackInfo for an existing callback.
-  CompileCallbackInfo getCompileCallbackInfo(JITTargetAddress TrampolineAddr) {
-    auto I = ActiveTrampolines.find(TrampolineAddr);
-    assert(I != ActiveTrampolines.end() && "Not an active trampoline.");
-    return CompileCallbackInfo(I->first, I->second);
-  }
-
-  /// @brief Release a compile callback.
-  ///
-  ///   Note: Callbacks are auto-released after they execute. This method should
-  /// only be called to manually release a callback that is not going to
-  /// execute.
-  void releaseCompileCallback(JITTargetAddress TrampolineAddr) {
-    auto I = ActiveTrampolines.find(TrampolineAddr);
-    assert(I != ActiveTrampolines.end() && "Not an active trampoline.");
-    ActiveTrampolines.erase(I);
-    AvailableTrampolines.push_back(TrampolineAddr);
-  }
+  JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr);
 
 protected:
-  JITTargetAddress ErrorHandlerAddress;
-
-  using TrampolineMapT = std::map<JITTargetAddress, CompileFtor>;
-  TrampolineMapT ActiveTrampolines;
   std::vector<JITTargetAddress> AvailableTrampolines;
 
 private:
@@ -156,17 +88,25 @@
   virtual Error grow() = 0;
 
   virtual void anchor();
+
+  std::mutex CCMgrMutex;
+  ExecutionSession &ES;
+  VSO &CallbacksVSO;
+  JITTargetAddress ErrorHandlerAddress;
+  std::map<JITTargetAddress, SymbolStringPtr> AddrToSymbol;
+  size_t NextCallbackId = 0;
 };
 
-/// @brief Manage compile callbacks for in-process JITs.
+/// Manage compile callbacks for in-process JITs.
 template <typename TargetT>
 class LocalJITCompileCallbackManager : public JITCompileCallbackManager {
 public:
-  /// @brief Construct a InProcessJITCompileCallbackManager.
+  /// Construct a InProcessJITCompileCallbackManager.
   /// @param ErrorHandlerAddress The address of an error handler in the target
   ///                            process to be used if a compile callback fails.
-  LocalJITCompileCallbackManager(JITTargetAddress ErrorHandlerAddress)
-      : JITCompileCallbackManager(ErrorHandlerAddress) {
+  LocalJITCompileCallbackManager(ExecutionSession &ES,
+                                 JITTargetAddress ErrorHandlerAddress)
+      : JITCompileCallbackManager(ES, ErrorHandlerAddress) {
     /// Set up the resolver block.
     std::error_code EC;
     ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
@@ -229,38 +169,38 @@
   std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
 };
 
-/// @brief Base class for managing collections of named indirect stubs.
+/// Base class for managing collections of named indirect stubs.
 class IndirectStubsManager {
 public:
-  /// @brief Map type for initializing the manager. See init.
+  /// Map type for initializing the manager. See init.
   using StubInitsMap = StringMap<std::pair<JITTargetAddress, JITSymbolFlags>>;
 
   virtual ~IndirectStubsManager() = default;
 
-  /// @brief Create a single stub with the given name, target address and flags.
+  /// Create a single stub with the given name, target address and flags.
   virtual Error createStub(StringRef StubName, JITTargetAddress StubAddr,
                            JITSymbolFlags StubFlags) = 0;
 
-  /// @brief Create StubInits.size() stubs with the given names, target
+  /// Create StubInits.size() stubs with the given names, target
   ///        addresses, and flags.
   virtual Error createStubs(const StubInitsMap &StubInits) = 0;
 
-  /// @brief Find the stub with the given name. If ExportedStubsOnly is true,
+  /// Find the stub with the given name. If ExportedStubsOnly is true,
   ///        this will only return a result if the stub's flags indicate that it
   ///        is exported.
-  virtual JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) = 0;
+  virtual JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) = 0;
 
-  /// @brief Find the implementation-pointer for the stub.
-  virtual JITSymbol findPointer(StringRef Name) = 0;
+  /// Find the implementation-pointer for the stub.
+  virtual JITEvaluatedSymbol findPointer(StringRef Name) = 0;
 
-  /// @brief Change the value of the implementation pointer for the stub.
+  /// Change the value of the implementation pointer for the stub.
   virtual Error updatePointer(StringRef Name, JITTargetAddress NewAddr) = 0;
 
 private:
   virtual void anchor();
 };
 
-/// @brief IndirectStubsManager implementation for the host architecture, e.g.
+/// IndirectStubsManager implementation for the host architecture, e.g.
 ///        OrcX86_64. (See OrcArchitectureSupport.h).
 template <typename TargetT>
 class LocalIndirectStubsManager : public IndirectStubsManager {
@@ -286,7 +226,7 @@
     return Error::success();
   }
 
-  JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
+  JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
     auto I = StubIndexes.find(Name);
     if (I == StubIndexes.end())
       return nullptr;
@@ -295,13 +235,13 @@
     assert(StubAddr && "Missing stub address");
     auto StubTargetAddr =
         static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(StubAddr));
-    auto StubSymbol = JITSymbol(StubTargetAddr, I->second.second);
+    auto StubSymbol = JITEvaluatedSymbol(StubTargetAddr, I->second.second);
     if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
       return nullptr;
     return StubSymbol;
   }
 
-  JITSymbol findPointer(StringRef Name) override {
+  JITEvaluatedSymbol findPointer(StringRef Name) override {
     auto I = StubIndexes.find(Name);
     if (I == StubIndexes.end())
       return nullptr;
@@ -310,7 +250,7 @@
     assert(PtrAddr && "Missing pointer address");
     auto PtrTargetAddr =
         static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(PtrAddr));
-    return JITSymbol(PtrTargetAddr, I->second.second);
+    return JITEvaluatedSymbol(PtrTargetAddr, I->second.second);
   }
 
   Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
@@ -354,45 +294,45 @@
   StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
 };
 
-/// @brief Create a local compile callback manager.
+/// Create a local compile callback manager.
 ///
 /// The given target triple will determine the ABI, and the given
 /// ErrorHandlerAddress will be used by the resulting compile callback
 /// manager if a compile callback fails.
 std::unique_ptr<JITCompileCallbackManager>
-createLocalCompileCallbackManager(const Triple &T,
+createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
                                   JITTargetAddress ErrorHandlerAddress);
 
-/// @brief Create a local indriect stubs manager builder.
+/// Create a local indriect stubs manager builder.
 ///
 /// The given target triple will determine the ABI.
 std::function<std::unique_ptr<IndirectStubsManager>()>
 createLocalIndirectStubsManagerBuilder(const Triple &T);
 
-/// @brief Build a function pointer of FunctionType with the given constant
+/// Build a function pointer of FunctionType with the given constant
 ///        address.
 ///
 ///   Usage example: Turn a trampoline address into a function pointer constant
 /// for use in a stub.
 Constant *createIRTypedAddress(FunctionType &FT, JITTargetAddress Addr);
 
-/// @brief Create a function pointer with the given type, name, and initializer
+/// Create a function pointer with the given type, name, and initializer
 ///        in the given Module.
 GlobalVariable *createImplPointer(PointerType &PT, Module &M, const Twine &Name,
                                   Constant *Initializer);
 
-/// @brief Turn a function declaration into a stub function that makes an
+/// Turn a function declaration into a stub function that makes an
 ///        indirect call using the given function pointer.
 void makeStub(Function &F, Value &ImplPointer);
 
-/// @brief Raise linkage types and rename as necessary to ensure that all
+/// Raise linkage types and rename as necessary to ensure that all
 ///        symbols are accessible for other modules.
 ///
 ///   This should be called before partitioning a module to ensure that the
 /// partitions retain access to each other's symbols.
 void makeAllSymbolsExternallyAccessible(Module &M);
 
-/// @brief Clone a function declaration into a new module.
+/// Clone a function declaration into a new module.
 ///
 ///   This function can be used as the first step towards creating a callback
 /// stub (see makeStub), or moving a function body (see moveFunctionBody).
@@ -407,7 +347,7 @@
 Function *cloneFunctionDecl(Module &Dst, const Function &F,
                             ValueToValueMapTy *VMap = nullptr);
 
-/// @brief Move the body of function 'F' to a cloned function declaration in a
+/// Move the body of function 'F' to a cloned function declaration in a
 ///        different module (See related cloneFunctionDecl).
 ///
 ///   If the target function declaration is not supplied via the NewF parameter
@@ -419,11 +359,11 @@
                       ValueMaterializer *Materializer = nullptr,
                       Function *NewF = nullptr);
 
-/// @brief Clone a global variable declaration into a new module.
+/// Clone a global variable declaration into a new module.
 GlobalVariable *cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
                                         ValueToValueMapTy *VMap = nullptr);
 
-/// @brief Move global variable GV from its parent module to cloned global
+/// Move global variable GV from its parent module to cloned global
 ///        declaration in a different module.
 ///
 ///   If the target global declaration is not supplied via the NewGV parameter
@@ -436,11 +376,11 @@
                                    ValueMaterializer *Materializer = nullptr,
                                    GlobalVariable *NewGV = nullptr);
 
-/// @brief Clone a global alias declaration into a new module.
+/// Clone a global alias declaration into a new module.
 GlobalAlias *cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
                                   ValueToValueMapTy &VMap);
 
-/// @brief Clone module flags metadata into the destination module.
+/// Clone module flags metadata into the destination module.
 void cloneModuleFlagsMetadata(Module &Dst, const Module &Src,
                               ValueToValueMapTy &VMap);
 
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h
new file mode 100644
index 0000000..df655bd
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LLJIT.h
@@ -0,0 +1,143 @@
+//===----- LLJIT.h -- An ORC-based JIT for compiling LLVM IR ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for 3Bdetails.
+//
+//===----------------------------------------------------------------------===//
+//
+// An ORC-based JIT for compiling LLVM IR.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LLJIT_H
+#define LLVM_EXECUTIONENGINE_ORC_LLJIT_H
+
+#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
+#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
+#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/Target/TargetMachine.h"
+
+namespace llvm {
+namespace orc {
+
+/// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT.
+class LLJIT {
+public:
+  /// Create an LLJIT instance.
+  static Expected<std::unique_ptr<LLJIT>>
+  Create(std::unique_ptr<ExecutionSession> ES,
+         std::unique_ptr<TargetMachine> TM, DataLayout DL);
+
+  /// Returns a reference to the ExecutionSession for this JIT instance.
+  ExecutionSession &getExecutionSession() { return *ES; }
+
+  /// Returns a reference to the VSO representing the JIT'd main program.
+  VSO &getMainVSO() { return Main; }
+
+  /// Convenience method for defining an absolute symbol.
+  Error defineAbsolute(StringRef Name, JITEvaluatedSymbol Address);
+
+  /// Adds an IR module to the given VSO.
+  Error addIRModule(VSO &V, std::unique_ptr<Module> M);
+
+  /// Adds an IR module to the Main VSO.
+  Error addIRModule(std::unique_ptr<Module> M) {
+    return addIRModule(Main, std::move(M));
+  }
+
+  /// Look up a symbol in VSO V by the symbol's linker-mangled name (to look up
+  /// symbols based on their IR name use the lookup function instead).
+  Expected<JITEvaluatedSymbol> lookupLinkerMangled(VSO &V, StringRef Name);
+
+  /// Look up a symbol in the main VSO by the symbol's linker-mangled name (to
+  /// look up symbols based on their IR name use the lookup function instead).
+  Expected<JITEvaluatedSymbol> lookupLinkerMangled(StringRef Name) {
+    return lookupLinkerMangled(Main, Name);
+  }
+
+  /// Look up a symbol in VSO V based on its IR symbol name.
+  Expected<JITEvaluatedSymbol> lookup(VSO &V, StringRef UnmangledName) {
+    return lookupLinkerMangled(V, mangle(UnmangledName));
+  }
+
+  /// Look up a symbol in the main VSO based on its IR symbol name.
+  Expected<JITEvaluatedSymbol> lookup(StringRef UnmangledName) {
+    return lookup(Main, UnmangledName);
+  }
+
+  /// Runs all not-yet-run static constructors.
+  Error runConstructors() { return CtorRunner.run(); }
+
+  /// Runs all not-yet-run static destructors.
+  Error runDestructors() { return DtorRunner.run(); }
+
+protected:
+  LLJIT(std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM,
+        DataLayout DL);
+
+  std::shared_ptr<RuntimeDyld::MemoryManager> getMemoryManager(VModuleKey K);
+
+  std::string mangle(StringRef UnmangledName);
+
+  Error applyDataLayout(Module &M);
+
+  void recordCtorDtors(Module &M);
+
+  std::unique_ptr<ExecutionSession> ES;
+  VSO &Main;
+
+  std::unique_ptr<TargetMachine> TM;
+  DataLayout DL;
+
+  RTDyldObjectLinkingLayer2 ObjLinkingLayer;
+  IRCompileLayer2 CompileLayer;
+
+  CtorDtorRunner2 CtorRunner, DtorRunner;
+};
+
+/// An extended version of LLJIT that supports lazy function-at-a-time
+/// compilation of LLVM IR.
+class LLLazyJIT : public LLJIT {
+public:
+  /// Create an LLLazyJIT instance.
+  static Expected<std::unique_ptr<LLLazyJIT>>
+  Create(std::unique_ptr<ExecutionSession> ES,
+         std::unique_ptr<TargetMachine> TM, DataLayout DL, LLVMContext &Ctx);
+
+  /// Set an IR transform (e.g. pass manager pipeline) to run on each function
+  /// when it is compiled.
+  void setLazyCompileTransform(IRTransformLayer2::TransformFunction Transform) {
+    TransformLayer.setTransform(std::move(Transform));
+  }
+
+  /// Add a module to be lazily compiled to VSO V.
+  Error addLazyIRModule(VSO &V, std::unique_ptr<Module> M);
+
+  /// Add a module to be lazily compiled to the main VSO.
+  Error addLazyIRModule(std::unique_ptr<Module> M) {
+    return addLazyIRModule(Main, std::move(M));
+  }
+
+private:
+  LLLazyJIT(std::unique_ptr<ExecutionSession> ES,
+            std::unique_ptr<TargetMachine> TM, DataLayout DL, LLVMContext &Ctx,
+            std::unique_ptr<JITCompileCallbackManager> CCMgr,
+            std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder);
+
+  std::unique_ptr<JITCompileCallbackManager> CCMgr;
+  std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder;
+
+  IRTransformLayer2 TransformLayer;
+  CompileOnDemandLayer2 CODLayer;
+};
+
+} // End namespace orc
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Layer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Layer.h
new file mode 100644
index 0000000..da37266
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Layer.h
@@ -0,0 +1,136 @@
+//===---------------- Layer.h -- Layer interfaces --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Layer interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LAYER_H
+#define LLVM_EXECUTIONENGINE_ORC_LAYER_H
+
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace llvm {
+namespace orc {
+
+/// Interface for layers that accept LLVM IR.
+class IRLayer {
+public:
+  IRLayer(ExecutionSession &ES);
+  virtual ~IRLayer();
+
+  /// Returns the ExecutionSession for this layer.
+  ExecutionSession &getExecutionSession() { return ES; }
+
+  /// Adds a MaterializationUnit representing the given IR to the given VSO.
+  virtual Error add(VSO &V, VModuleKey K, std::unique_ptr<Module> M);
+
+  /// Emit should materialize the given IR.
+  virtual void emit(MaterializationResponsibility R, VModuleKey K,
+                    std::unique_ptr<Module> M) = 0;
+
+private:
+  ExecutionSession &ES;
+};
+
+/// IRMaterializationUnit is a convenient base class for MaterializationUnits
+/// wrapping LLVM IR. Represents materialization responsibility for all symbols
+/// in the given module. If symbols are overridden by other definitions, then
+/// their linkage is changed to available-externally.
+class IRMaterializationUnit : public MaterializationUnit {
+public:
+  using SymbolNameToDefinitionMap = std::map<SymbolStringPtr, GlobalValue *>;
+
+  /// Create an IRMaterializationLayer. Scans the module to build the
+  /// SymbolFlags and SymbolToDefinition maps.
+  IRMaterializationUnit(ExecutionSession &ES, std::unique_ptr<Module> M);
+
+  /// Create an IRMaterializationLayer from a module, and pre-existing
+  /// SymbolFlags and SymbolToDefinition maps. The maps must provide
+  /// entries for each definition in M.
+  /// This constructor is useful for delegating work from one
+  /// IRMaterializationUnit to another.
+  IRMaterializationUnit(std::unique_ptr<Module> M, SymbolFlagsMap SymbolFlags,
+                        SymbolNameToDefinitionMap SymbolToDefinition);
+
+protected:
+  std::unique_ptr<Module> M;
+  SymbolNameToDefinitionMap SymbolToDefinition;
+
+private:
+  void discard(const VSO &V, SymbolStringPtr Name) override;
+};
+
+/// MaterializationUnit that materializes modules by calling the 'emit' method
+/// on the given IRLayer.
+class BasicIRLayerMaterializationUnit : public IRMaterializationUnit {
+public:
+  BasicIRLayerMaterializationUnit(IRLayer &L, VModuleKey K,
+                                  std::unique_ptr<Module> M);
+private:
+
+  void materialize(MaterializationResponsibility R) override;
+
+  IRLayer &L;
+  VModuleKey K;
+};
+
+/// Interface for Layers that accept object files.
+class ObjectLayer {
+public:
+  ObjectLayer(ExecutionSession &ES);
+  virtual ~ObjectLayer();
+
+  /// Returns the execution session for this layer.
+  ExecutionSession &getExecutionSession() { return ES; }
+
+  /// Adds a MaterializationUnit representing the given IR to the given VSO.
+  virtual Error add(VSO &V, VModuleKey K, std::unique_ptr<MemoryBuffer> O);
+
+  /// Emit should materialize the given IR.
+  virtual void emit(MaterializationResponsibility R, VModuleKey K,
+                    std::unique_ptr<MemoryBuffer> O) = 0;
+
+private:
+  ExecutionSession &ES;
+};
+
+/// Materializes the given object file (represented by a MemoryBuffer
+/// instance) by calling 'emit' on the given ObjectLayer.
+class BasicObjectLayerMaterializationUnit : public MaterializationUnit {
+public:
+  static Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
+  Create(ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O);
+
+  BasicObjectLayerMaterializationUnit(ObjectLayer &L, VModuleKey K,
+                                      std::unique_ptr<MemoryBuffer> O,
+                                      SymbolFlagsMap SymbolFlags);
+
+private:
+
+  void materialize(MaterializationResponsibility R) override;
+  void discard(const VSO &V, SymbolStringPtr Name) override;
+
+  ObjectLayer &L;
+  VModuleKey K;
+  std::unique_ptr<MemoryBuffer> O;
+};
+
+/// Returns a SymbolFlagsMap for the object file represented by the given
+/// buffer, or an error if the buffer does not contain a valid object file.
+// FIXME: Maybe move to Core.h?
+Expected<SymbolFlagsMap> getObjectSymbolFlags(ExecutionSession &ES,
+                                              MemoryBufferRef ObjBuffer);
+
+} // End namespace orc
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LAYER_H
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
index 4117a92..46761b0 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
@@ -33,7 +33,7 @@
 namespace llvm {
 namespace orc {
 
-/// @brief Lazy-emitting IR layer.
+/// Lazy-emitting IR layer.
 ///
 ///   This layer accepts LLVM IR Modules (via addModule), but does not
 /// immediately emit them the layer below. Instead, emissing to the base layer
@@ -196,10 +196,10 @@
 
 public:
 
-  /// @brief Construct a lazy emitting layer.
+  /// Construct a lazy emitting layer.
   LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
 
-  /// @brief Add the given module to the lazy emitting layer.
+  /// Add the given module to the lazy emitting layer.
   Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
     assert(!ModuleMap.count(K) && "VModuleKey K already in use");
     ModuleMap[K] =
@@ -207,7 +207,7 @@
     return Error::success();
   }
 
-  /// @brief Remove the module represented by the given handle.
+  /// Remove the module represented by the given handle.
   ///
   ///   This method will free the memory associated with the given module, both
   /// in this layer, and the base layer.
@@ -219,7 +219,7 @@
     return EDM->removeModuleFromBaseLayer(BaseLayer);
   }
 
-  /// @brief Search for the given named symbol.
+  /// Search for the given named symbol.
   /// @param Name The name of the symbol to search for.
   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
   /// @return A handle for the given named symbol, if it exists.
@@ -239,7 +239,7 @@
     return nullptr;
   }
 
-  /// @brief Get the address of the given symbol in the context of the of
+  /// Get the address of the given symbol in the context of the of
   ///        compiled modules represented by the key K.
   JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
                          bool ExportedSymbolsOnly) {
@@ -247,7 +247,7 @@
     return ModuleMap[K]->find(Name, ExportedSymbolsOnly, BaseLayer);
   }
 
-  /// @brief Immediately emit and finalize the module represented by the given
+  /// Immediately emit and finalize the module represented by the given
   ///        key.
   Error emitAndFinalize(VModuleKey K) {
     assert(ModuleMap.count(K) && "VModuleKey K not valid here");
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h
index b2b389a..52c8c16 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/Legacy.h
@@ -20,9 +20,76 @@
 namespace llvm {
 namespace orc {
 
+/// SymbolResolver is a composable interface for looking up symbol flags
+///        and addresses using the AsynchronousSymbolQuery type. It will
+///        eventually replace the LegacyJITSymbolResolver interface as the
+///        stardard ORC symbol resolver type.
+///
+/// FIXME: SymbolResolvers should go away and be replaced with VSOs with
+///        defenition generators.
+class SymbolResolver {
+public:
+  virtual ~SymbolResolver() = default;
+
+  /// Returns the flags for each symbol in Symbols that can be found,
+  ///        along with the set of symbol that could not be found.
+  virtual SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) = 0;
+
+  /// For each symbol in Symbols that can be found, assigns that symbols
+  ///        value in Query. Returns the set of symbols that could not be found.
+  virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
+                               SymbolNameSet Symbols) = 0;
+
+private:
+  virtual void anchor();
+};
+
+/// Implements SymbolResolver with a pair of supplied function objects
+///        for convenience. See createSymbolResolver.
+template <typename LookupFlagsFn, typename LookupFn>
+class LambdaSymbolResolver final : public SymbolResolver {
+public:
+  template <typename LookupFlagsFnRef, typename LookupFnRef>
+  LambdaSymbolResolver(LookupFlagsFnRef &&LookupFlags, LookupFnRef &&Lookup)
+      : LookupFlags(std::forward<LookupFlagsFnRef>(LookupFlags)),
+        Lookup(std::forward<LookupFnRef>(Lookup)) {}
+
+  SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) final {
+    return LookupFlags(Symbols);
+  }
+
+  SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
+                       SymbolNameSet Symbols) final {
+    return Lookup(std::move(Query), std::move(Symbols));
+  }
+
+private:
+  LookupFlagsFn LookupFlags;
+  LookupFn Lookup;
+};
+
+/// Creates a SymbolResolver implementation from the pair of supplied
+///        function objects.
+template <typename LookupFlagsFn, typename LookupFn>
+std::unique_ptr<LambdaSymbolResolver<
+    typename std::remove_cv<
+        typename std::remove_reference<LookupFlagsFn>::type>::type,
+    typename std::remove_cv<
+        typename std::remove_reference<LookupFn>::type>::type>>
+createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) {
+  using LambdaSymbolResolverImpl = LambdaSymbolResolver<
+      typename std::remove_cv<
+          typename std::remove_reference<LookupFlagsFn>::type>::type,
+      typename std::remove_cv<
+          typename std::remove_reference<LookupFn>::type>::type>;
+  return llvm::make_unique<LambdaSymbolResolverImpl>(
+      std::forward<LookupFlagsFn>(LookupFlags), std::forward<LookupFn>(Lookup));
+}
+
 class JITSymbolResolverAdapter : public JITSymbolResolver {
 public:
-  JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R);
+  JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R,
+                           MaterializationResponsibility *MR);
   Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) override;
   Expected<LookupResult> lookup(const LookupSet &Symbols) override;
 
@@ -30,9 +97,10 @@
   ExecutionSession &ES;
   std::set<SymbolStringPtr> ResolvedStrings;
   SymbolResolver &R;
+  MaterializationResponsibility *MR;
 };
 
-/// @brief Use the given legacy-style FindSymbol function (i.e. a function that
+/// Use the given legacy-style FindSymbol function (i.e. a function that
 ///        takes a const std::string& or StringRef and returns a JITSymbol) to
 ///        find the flags for each symbol in Symbols and store their flags in
 ///        SymbolFlags. If any JITSymbol returned by FindSymbol is in an error
@@ -41,95 +109,100 @@
 ///
 /// Useful for implementing lookupFlags bodies that query legacy resolvers.
 template <typename FindSymbolFn>
-Expected<SymbolNameSet> lookupFlagsWithLegacyFn(SymbolFlagsMap &SymbolFlags,
-                                                const SymbolNameSet &Symbols,
-                                                FindSymbolFn FindSymbol) {
-  SymbolNameSet SymbolsNotFound;
+Expected<SymbolFlagsMap> lookupFlagsWithLegacyFn(const SymbolNameSet &Symbols,
+                                                 FindSymbolFn FindSymbol) {
+  SymbolFlagsMap SymbolFlags;
 
   for (auto &S : Symbols) {
     if (JITSymbol Sym = FindSymbol(*S))
       SymbolFlags[S] = Sym.getFlags();
     else if (auto Err = Sym.takeError())
       return std::move(Err);
-    else
-      SymbolsNotFound.insert(S);
   }
 
-  return SymbolsNotFound;
+  return SymbolFlags;
 }
 
-/// @brief Use the given legacy-style FindSymbol function (i.e. a function that
+/// Use the given legacy-style FindSymbol function (i.e. a function that
 ///        takes a const std::string& or StringRef and returns a JITSymbol) to
 ///        find the address and flags for each symbol in Symbols and store the
 ///        result in Query. If any JITSymbol returned by FindSymbol is in an
-///        error then Query.setFailed(...) is called with that error and the
+///        error then Query.notifyFailed(...) is called with that error and the
 ///        function returns immediately. On success, returns the set of symbols
 ///        not found.
 ///
 /// Useful for implementing lookup bodies that query legacy resolvers.
 template <typename FindSymbolFn>
-SymbolNameSet lookupWithLegacyFn(AsynchronousSymbolQuery &Query,
-                                 const SymbolNameSet &Symbols,
-                                 FindSymbolFn FindSymbol) {
+SymbolNameSet
+lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query,
+                   const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) {
   SymbolNameSet SymbolsNotFound;
+  bool NewSymbolsResolved = false;
 
   for (auto &S : Symbols) {
     if (JITSymbol Sym = FindSymbol(*S)) {
       if (auto Addr = Sym.getAddress()) {
-        Query.setDefinition(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
-        Query.notifySymbolFinalized();
+        Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
+        Query.notifySymbolReady();
+        NewSymbolsResolved = true;
       } else {
-        Query.setFailed(Addr.takeError());
+        ES.legacyFailQuery(Query, Addr.takeError());
         return SymbolNameSet();
       }
     } else if (auto Err = Sym.takeError()) {
-      Query.setFailed(std::move(Err));
+      ES.legacyFailQuery(Query, std::move(Err));
       return SymbolNameSet();
     } else
       SymbolsNotFound.insert(S);
   }
 
+  if (NewSymbolsResolved && Query.isFullyResolved())
+    Query.handleFullyResolved();
+
+  if (NewSymbolsResolved && Query.isFullyReady())
+    Query.handleFullyReady();
+
   return SymbolsNotFound;
 }
 
-/// @brief An ORC SymbolResolver implementation that uses a legacy
+/// An ORC SymbolResolver implementation that uses a legacy
 ///        findSymbol-like function to perform lookup;
 template <typename LegacyLookupFn>
 class LegacyLookupFnResolver final : public SymbolResolver {
 public:
   using ErrorReporter = std::function<void(Error)>;
 
-  LegacyLookupFnResolver(LegacyLookupFn LegacyLookup, ErrorReporter ReportError)
-      : LegacyLookup(std::move(LegacyLookup)),
+  LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
+                         ErrorReporter ReportError)
+      : ES(ES), LegacyLookup(std::move(LegacyLookup)),
         ReportError(std::move(ReportError)) {}
 
-  SymbolNameSet lookupFlags(SymbolFlagsMap &Flags,
-                            const SymbolNameSet &Symbols) final {
-    if (auto RemainingSymbols =
-            lookupFlagsWithLegacyFn(Flags, Symbols, LegacyLookup))
-      return std::move(*RemainingSymbols);
+  SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) final {
+    if (auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup))
+      return std::move(*SymbolFlags);
     else {
-      ReportError(RemainingSymbols.takeError());
-      return Symbols;
+      ReportError(SymbolFlags.takeError());
+      return SymbolFlagsMap();
     }
   }
 
   SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
                        SymbolNameSet Symbols) final {
-    return lookupWithLegacyFn(*Query, Symbols, LegacyLookup);
+    return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
   }
 
 private:
+  ExecutionSession &ES;
   LegacyLookupFn LegacyLookup;
   ErrorReporter ReportError;
 };
 
 template <typename LegacyLookupFn>
 std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>>
-createLegacyLookupResolver(LegacyLookupFn LegacyLookup,
+createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
                            std::function<void(Error)> ErrorReporter) {
   return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>(
-      std::move(LegacyLookup), std::move(ErrorReporter));
+      ES, std::move(LegacyLookup), std::move(ErrorReporter));
 }
 
 } // End namespace orc
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h
index eba9b95..3dd3cfe 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/NullResolver.h
@@ -15,7 +15,7 @@
 #ifndef LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H
 #define LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H
 
-#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Legacy.h"
 #include "llvm/ExecutionEngine/RuntimeDyld.h"
 
 namespace llvm {
@@ -23,8 +23,7 @@
 
 class NullResolver : public SymbolResolver {
 public:
-  SymbolNameSet lookupFlags(SymbolFlagsMap &Flags,
-                            const SymbolNameSet &Symbols) override;
+  SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) override;
 
   SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
                        SymbolNameSet Symbols) override;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
index cfc3922..c6b43a9 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h
@@ -15,7 +15,7 @@
 #define LLVM_EXECUTIONENGINE_ORC_OBJECTTRANSFORMLAYER_H
 
 #include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
 #include <algorithm>
 #include <memory>
 #include <string>
@@ -23,7 +23,24 @@
 namespace llvm {
 namespace orc {
 
-/// @brief Object mutating layer.
+class ObjectTransformLayer2 : public ObjectLayer {
+public:
+  using TransformFunction =
+      std::function<Expected<std::unique_ptr<MemoryBuffer>>(
+          std::unique_ptr<MemoryBuffer>)>;
+
+  ObjectTransformLayer2(ExecutionSession &ES, ObjectLayer &BaseLayer,
+                        TransformFunction Transform);
+
+  void emit(MaterializationResponsibility R, VModuleKey K,
+            std::unique_ptr<MemoryBuffer> O) override;
+
+private:
+  ObjectLayer &BaseLayer;
+  TransformFunction Transform;
+};
+
+/// Object mutating layer.
 ///
 ///   This layer accepts sets of ObjectFiles (via addObject). It
 /// immediately applies the user supplied functor to each object, then adds
@@ -31,12 +48,12 @@
 template <typename BaseLayerT, typename TransformFtor>
 class ObjectTransformLayer {
 public:
-  /// @brief Construct an ObjectTransformLayer with the given BaseLayer
+  /// Construct an ObjectTransformLayer with the given BaseLayer
   ObjectTransformLayer(BaseLayerT &BaseLayer,
                        TransformFtor Transform = TransformFtor())
       : BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
 
-  /// @brief Apply the transform functor to each object in the object set, then
+  /// Apply the transform functor to each object in the object set, then
   ///        add the resulting set of objects to the base layer, along with the
   ///        memory manager and symbol resolver.
   ///
@@ -45,10 +62,10 @@
     return BaseLayer.addObject(std::move(K), Transform(std::move(Obj)));
   }
 
-  /// @brief Remove the object set associated with the VModuleKey K.
+  /// Remove the object set associated with the VModuleKey K.
   Error removeObject(VModuleKey K) { return BaseLayer.removeObject(K); }
 
-  /// @brief Search for the given named symbol.
+  /// Search for the given named symbol.
   /// @param Name The name of the symbol to search for.
   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
   /// @return A handle for the given named symbol, if it exists.
@@ -56,7 +73,7 @@
     return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
   }
 
-  /// @brief Get the address of the given symbol in the context of the set of
+  /// Get the address of the given symbol in the context of the set of
   ///        objects represented by the VModuleKey K. This call is forwarded to
   ///        the base layer's implementation.
   /// @param K The VModuleKey associated with the object set to search in.
@@ -69,21 +86,21 @@
     return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
   }
 
-  /// @brief Immediately emit and finalize the object set represented by the
+  /// Immediately emit and finalize the object set represented by the
   ///        given VModuleKey K.
   Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); }
 
-  /// @brief Map section addresses for the objects associated with the
+  /// Map section addresses for the objects associated with the
   /// VModuleKey K.
   void mapSectionAddress(VModuleKey K, const void *LocalAddress,
                          JITTargetAddress TargetAddr) {
     BaseLayer.mapSectionAddress(K, LocalAddress, TargetAddr);
   }
 
-  /// @brief Access the transform functor directly.
+  /// Access the transform functor directly.
   TransformFtor &getTransform() { return Transform; }
 
-  /// @brief Access the mumate functor directly.
+  /// Access the mumate functor directly.
   const TransformFtor &getTransform() const { return Transform; }
 
 private:
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
index e1b5564..581c598 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcABISupport.h
@@ -71,7 +71,7 @@
   }
 };
 
-/// @brief Provide information about stub blocks generated by the
+/// Provide information about stub blocks generated by the
 ///        makeIndirectStubsBlock function.
 template <unsigned StubSizeVal> class GenericIndirectStubsInfo {
 public:
@@ -92,16 +92,16 @@
     return *this;
   }
 
-  /// @brief Number of stubs in this block.
+  /// Number of stubs in this block.
   unsigned getNumStubs() const { return NumStubs; }
 
-  /// @brief Get a pointer to the stub at the given index, which must be in
+  /// Get a pointer to the stub at the given index, which must be in
   ///        the range 0 .. getNumStubs() - 1.
   void *getStub(unsigned Idx) const {
     return static_cast<char *>(StubsMem.base()) + Idx * StubSize;
   }
 
-  /// @brief Get a pointer to the implementation-pointer at the given index,
+  /// Get a pointer to the implementation-pointer at the given index,
   ///        which must be in the range 0 .. getNumStubs() - 1.
   void **getPtr(unsigned Idx) const {
     char *PtrsBase = static_cast<char *>(StubsMem.base()) + NumStubs * StubSize;
@@ -124,18 +124,18 @@
   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
                                             void *TrampolineId);
 
-  /// @brief Write the resolver code into the given memory. The user is be
+  /// Write the resolver code into the given memory. The user is be
   ///        responsible for allocating the memory and setting permissions.
   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
                                 void *CallbackMgr);
 
-  /// @brief Write the requsted number of trampolines into the given memory,
+  /// Write the requsted number of trampolines into the given memory,
   ///        which must be big enough to hold 1 pointer, plus NumTrampolines
   ///        trampolines.
   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
                                unsigned NumTrampolines);
 
-  /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
+  /// Emit at least MinStubs worth of indirect call stubs, rounded out to
   ///        the nearest page size.
   ///
   ///   E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
@@ -145,7 +145,7 @@
                                       unsigned MinStubs, void *InitialPtrVal);
 };
 
-/// @brief X86_64 code that's common to all ABIs.
+/// X86_64 code that's common to all ABIs.
 ///
 /// X86_64 supports lazy JITing.
 class OrcX86_64_Base {
@@ -155,13 +155,13 @@
 
   using IndirectStubsInfo = GenericIndirectStubsInfo<8>;
 
-  /// @brief Write the requsted number of trampolines into the given memory,
+  /// Write the requsted number of trampolines into the given memory,
   ///        which must be big enough to hold 1 pointer, plus NumTrampolines
   ///        trampolines.
   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
                                unsigned NumTrampolines);
 
-  /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
+  /// Emit at least MinStubs worth of indirect call stubs, rounded out to
   ///        the nearest page size.
   ///
   ///   E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k
@@ -171,7 +171,7 @@
                                       unsigned MinStubs, void *InitialPtrVal);
 };
 
-/// @brief X86_64 support for SysV ABI (Linux, MacOSX).
+/// X86_64 support for SysV ABI (Linux, MacOSX).
 ///
 /// X86_64_SysV supports lazy JITing.
 class OrcX86_64_SysV : public OrcX86_64_Base {
@@ -181,13 +181,13 @@
   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
                                             void *TrampolineId);
 
-  /// @brief Write the resolver code into the given memory. The user is be
+  /// Write the resolver code into the given memory. The user is be
   ///        responsible for allocating the memory and setting permissions.
   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
                                 void *CallbackMgr);
 };
 
-/// @brief X86_64 support for Win32.
+/// X86_64 support for Win32.
 ///
 /// X86_64_Win32 supports lazy JITing.
 class OrcX86_64_Win32 : public OrcX86_64_Base {
@@ -197,13 +197,13 @@
   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
                                             void *TrampolineId);
 
-  /// @brief Write the resolver code into the given memory. The user is be
+  /// Write the resolver code into the given memory. The user is be
   ///        responsible for allocating the memory and setting permissions.
   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
                                 void *CallbackMgr);
 };
 
-/// @brief I386 support.
+/// I386 support.
 ///
 /// I386 supports lazy JITing.
 class OrcI386 {
@@ -217,18 +217,18 @@
   using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
                                             void *TrampolineId);
 
-  /// @brief Write the resolver code into the given memory. The user is be
+  /// Write the resolver code into the given memory. The user is be
   ///        responsible for allocating the memory and setting permissions.
   static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,
                                 void *CallbackMgr);
 
-  /// @brief Write the requsted number of trampolines into the given memory,
+  /// Write the requsted number of trampolines into the given memory,
   ///        which must be big enough to hold 1 pointer, plus NumTrampolines
   ///        trampolines.
   static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
                                unsigned NumTrampolines);
 
-  /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
+  /// Emit at least MinStubs worth of indirect call stubs, rounded out to
   ///        the nearest page size.
   ///
   ///   E.g. Asking for 4 stubs on i386, where stubs are 8-bytes, with 4k
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcError.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcError.h
index c2ff41e..dc60e8d 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcError.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcError.h
@@ -22,7 +22,8 @@
 
 enum class OrcErrorCode : int {
   // RPC Errors
-  DuplicateDefinition = 1,
+  UnknownORCError = 1,
+  DuplicateDefinition,
   JITSymbolNotFound,
   RemoteAllocatorDoesNotExist,
   RemoteAllocatorIdAlreadyInUse,
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
index 7179e5f..739e5ba 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h
@@ -63,7 +63,7 @@
   public:
     ~RemoteRTDyldMemoryManager() {
       Client.destroyRemoteAllocator(Id);
-      DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
+      LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n");
     }
 
     RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager &) = delete;
@@ -79,9 +79,9 @@
       Unmapped.back().CodeAllocs.emplace_back(Size, Alignment);
       uint8_t *Alloc = reinterpret_cast<uint8_t *>(
           Unmapped.back().CodeAllocs.back().getLocalAddress());
-      DEBUG(dbgs() << "Allocator " << Id << " allocated code for "
-                   << SectionName << ": " << Alloc << " (" << Size
-                   << " bytes, alignment " << Alignment << ")\n");
+      LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated code for "
+                        << SectionName << ": " << Alloc << " (" << Size
+                        << " bytes, alignment " << Alignment << ")\n");
       return Alloc;
     }
 
@@ -92,18 +92,18 @@
         Unmapped.back().RODataAllocs.emplace_back(Size, Alignment);
         uint8_t *Alloc = reinterpret_cast<uint8_t *>(
             Unmapped.back().RODataAllocs.back().getLocalAddress());
-        DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for "
-                     << SectionName << ": " << Alloc << " (" << Size
-                     << " bytes, alignment " << Alignment << ")\n");
+        LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for "
+                          << SectionName << ": " << Alloc << " (" << Size
+                          << " bytes, alignment " << Alignment << ")\n");
         return Alloc;
       } // else...
 
       Unmapped.back().RWDataAllocs.emplace_back(Size, Alignment);
       uint8_t *Alloc = reinterpret_cast<uint8_t *>(
           Unmapped.back().RWDataAllocs.back().getLocalAddress());
-      DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for "
-                   << SectionName << ": " << Alloc << " (" << Size
-                   << " bytes, alignment " << Alignment << ")\n");
+      LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for "
+                        << SectionName << ": " << Alloc << " (" << Size
+                        << " bytes, alignment " << Alignment << ")\n");
       return Alloc;
     }
 
@@ -113,36 +113,36 @@
                                 uint32_t RWDataAlign) override {
       Unmapped.push_back(ObjectAllocs());
 
-      DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
+      LLVM_DEBUG(dbgs() << "Allocator " << Id << " reserved:\n");
 
       if (CodeSize != 0) {
         Unmapped.back().RemoteCodeAddr =
             Client.reserveMem(Id, CodeSize, CodeAlign);
 
-        DEBUG(dbgs() << "  code: "
-                     << format("0x%016x", Unmapped.back().RemoteCodeAddr)
-                     << " (" << CodeSize << " bytes, alignment " << CodeAlign
-                     << ")\n");
+        LLVM_DEBUG(dbgs() << "  code: "
+                          << format("0x%016x", Unmapped.back().RemoteCodeAddr)
+                          << " (" << CodeSize << " bytes, alignment "
+                          << CodeAlign << ")\n");
       }
 
       if (RODataSize != 0) {
         Unmapped.back().RemoteRODataAddr =
             Client.reserveMem(Id, RODataSize, RODataAlign);
 
-        DEBUG(dbgs() << "  ro-data: "
-                     << format("0x%016x", Unmapped.back().RemoteRODataAddr)
-                     << " (" << RODataSize << " bytes, alignment "
-                     << RODataAlign << ")\n");
+        LLVM_DEBUG(dbgs() << "  ro-data: "
+                          << format("0x%016x", Unmapped.back().RemoteRODataAddr)
+                          << " (" << RODataSize << " bytes, alignment "
+                          << RODataAlign << ")\n");
       }
 
       if (RWDataSize != 0) {
         Unmapped.back().RemoteRWDataAddr =
             Client.reserveMem(Id, RWDataSize, RWDataAlign);
 
-        DEBUG(dbgs() << "  rw-data: "
-                     << format("0x%016x", Unmapped.back().RemoteRWDataAddr)
-                     << " (" << RWDataSize << " bytes, alignment "
-                     << RWDataAlign << ")\n");
+        LLVM_DEBUG(dbgs() << "  rw-data: "
+                          << format("0x%016x", Unmapped.back().RemoteRWDataAddr)
+                          << " (" << RWDataSize << " bytes, alignment "
+                          << RWDataAlign << ")\n");
       }
     }
 
@@ -162,7 +162,7 @@
 
     void notifyObjectLoaded(RuntimeDyld &Dyld,
                             const object::ObjectFile &Obj) override {
-      DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
+      LLVM_DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n");
       for (auto &ObjAllocs : Unmapped) {
         mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs,
                                ObjAllocs.RemoteCodeAddr);
@@ -176,7 +176,7 @@
     }
 
     bool finalizeMemory(std::string *ErrMsg = nullptr) override {
-      DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
+      LLVM_DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n");
 
       for (auto &ObjAllocs : Unfinalized) {
         if (copyAndProtect(ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr,
@@ -261,7 +261,7 @@
     RemoteRTDyldMemoryManager(OrcRemoteTargetClient &Client,
                               ResourceIdMgr::ResourceId Id)
         : Client(Client), Id(Id) {
-      DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
+      LLVM_DEBUG(dbgs() << "Created remote allocator " << Id << "\n");
     }
 
     // Maps all allocations in Allocs to aligned blocks
@@ -270,8 +270,9 @@
       for (auto &Alloc : Allocs) {
         NextAddr = alignTo(NextAddr, Alloc.getAlign());
         Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextAddr);
-        DEBUG(dbgs() << "     " << static_cast<void *>(Alloc.getLocalAddress())
-                     << " -> " << format("0x%016x", NextAddr) << "\n");
+        LLVM_DEBUG(dbgs() << "     "
+                          << static_cast<void *>(Alloc.getLocalAddress())
+                          << " -> " << format("0x%016x", NextAddr) << "\n");
         Alloc.setRemoteAddress(NextAddr);
 
         // Only advance NextAddr if it was non-null to begin with,
@@ -290,22 +291,23 @@
         assert(!Allocs.empty() && "No sections in allocated segment");
 
         for (auto &Alloc : Allocs) {
-          DEBUG(dbgs() << "  copying section: "
-                       << static_cast<void *>(Alloc.getLocalAddress()) << " -> "
-                       << format("0x%016x", Alloc.getRemoteAddress()) << " ("
-                       << Alloc.getSize() << " bytes)\n";);
+          LLVM_DEBUG(dbgs() << "  copying section: "
+                            << static_cast<void *>(Alloc.getLocalAddress())
+                            << " -> "
+                            << format("0x%016x", Alloc.getRemoteAddress())
+                            << " (" << Alloc.getSize() << " bytes)\n";);
 
           if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
                               Alloc.getSize()))
             return true;
         }
 
-        DEBUG(dbgs() << "  setting "
-                     << (Permissions & sys::Memory::MF_READ ? 'R' : '-')
-                     << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')
-                     << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')
-                     << " permissions on block: "
-                     << format("0x%016x", RemoteSegmentAddr) << "\n");
+        LLVM_DEBUG(dbgs() << "  setting "
+                          << (Permissions & sys::Memory::MF_READ ? 'R' : '-')
+                          << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-')
+                          << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-')
+                          << " permissions on block: "
+                          << format("0x%016x", RemoteSegmentAddr) << "\n");
         if (Client.setProtections(Id, RemoteSegmentAddr, Permissions))
           return true;
       }
@@ -356,25 +358,25 @@
       return Error::success();
     }
 
-    JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
+    JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
       auto I = StubIndexes.find(Name);
       if (I == StubIndexes.end())
         return nullptr;
       auto Key = I->second.first;
       auto Flags = I->second.second;
-      auto StubSymbol = JITSymbol(getStubAddr(Key), Flags);
+      auto StubSymbol = JITEvaluatedSymbol(getStubAddr(Key), Flags);
       if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
         return nullptr;
       return StubSymbol;
     }
 
-    JITSymbol findPointer(StringRef Name) override {
+    JITEvaluatedSymbol findPointer(StringRef Name) override {
       auto I = StubIndexes.find(Name);
       if (I == StubIndexes.end())
         return nullptr;
       auto Key = I->second.first;
       auto Flags = I->second.second;
-      return JITSymbol(getPtrAddr(Key), Flags);
+      return JITEvaluatedSymbol(getPtrAddr(Key), Flags);
     }
 
     Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override {
@@ -449,8 +451,9 @@
   class RemoteCompileCallbackManager : public JITCompileCallbackManager {
   public:
     RemoteCompileCallbackManager(OrcRemoteTargetClient &Client,
+                                 ExecutionSession &ES,
                                  JITTargetAddress ErrorHandlerAddress)
-        : JITCompileCallbackManager(ErrorHandlerAddress), Client(Client) {}
+        : JITCompileCallbackManager(ES, ErrorHandlerAddress), Client(Client) {}
 
   private:
     Error grow() override {
@@ -475,10 +478,10 @@
   /// Channel is the ChannelT instance to communicate on. It is assumed that
   /// the channel is ready to be read from and written to.
   static Expected<std::unique_ptr<OrcRemoteTargetClient>>
-  Create(rpc::RawByteChannel &Channel, std::function<void(Error)> ReportError) {
+  Create(rpc::RawByteChannel &Channel, ExecutionSession &ES) {
     Error Err = Error::success();
     auto Client = std::unique_ptr<OrcRemoteTargetClient>(
-        new OrcRemoteTargetClient(Channel, std::move(ReportError), Err));
+        new OrcRemoteTargetClient(Channel, ES, Err));
     if (Err)
       return std::move(Err);
     return std::move(Client);
@@ -487,7 +490,8 @@
   /// Call the int(void) function at the given address in the target and return
   /// its result.
   Expected<int> callIntVoid(JITTargetAddress Addr) {
-    DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n");
+    LLVM_DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr)
+                      << "\n");
     return callB<exec::CallIntVoid>(Addr);
   }
 
@@ -495,16 +499,16 @@
   /// return its result.
   Expected<int> callMain(JITTargetAddress Addr,
                          const std::vector<std::string> &Args) {
-    DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr)
-                 << "\n");
+    LLVM_DEBUG(dbgs() << "Calling int(*)(int, char*[]) "
+                      << format("0x%016x", Addr) << "\n");
     return callB<exec::CallMain>(Addr, Args);
   }
 
   /// Call the void() function at the given address in the target and wait for
   /// it to finish.
   Error callVoidVoid(JITTargetAddress Addr) {
-    DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
-                 << "\n");
+    LLVM_DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr)
+                      << "\n");
     return callB<exec::CallVoidVoid>(Addr);
   }
 
@@ -531,12 +535,14 @@
 
   Expected<RemoteCompileCallbackManager &>
   enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) {
+    assert(!CallbackManager && "CallbackManager already obtained");
+
     // Emit the resolver block on the JIT server.
     if (auto Err = callB<stubs::EmitResolverBlock>())
       return std::move(Err);
 
     // Create the callback manager.
-    CallbackManager.emplace(*this, ErrorHandlerAddress);
+    CallbackManager.emplace(*this, ES, ErrorHandlerAddress);
     RemoteCompileCallbackManager &Mgr = *CallbackManager;
     return Mgr;
   }
@@ -554,10 +560,10 @@
   Error terminateSession() { return callB<utils::TerminateSession>(); }
 
 private:
-  OrcRemoteTargetClient(rpc::RawByteChannel &Channel,
-                        std::function<void(Error)> ReportError, Error &Err)
+  OrcRemoteTargetClient(rpc::RawByteChannel &Channel, ExecutionSession &ES,
+                        Error &Err)
       : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true),
-        ReportError(std::move(ReportError)) {
+        ES(ES) {
     ErrorAsOutParameter EAO(&Err);
 
     addHandler<utils::RequestCompile>(
@@ -577,7 +583,7 @@
 
   void deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) {
     if (auto Err = callB<eh::RegisterEHFrames>(Addr, Size))
-      ReportError(std::move(Err));
+      ES.reportError(std::move(Err));
   }
 
   void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) {
@@ -592,7 +598,7 @@
   void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) {
     IndirectStubOwnerIds.release(Id);
     if (auto Err = callB<stubs::DestroyIndirectStubsOwner>(Id))
-      ReportError(std::move(Err));
+      ES.reportError(std::move(Err));
   }
 
   Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
@@ -625,7 +631,7 @@
     if (auto AddrOrErr = callB<mem::ReserveMem>(Id, Size, Align))
       return *AddrOrErr;
     else {
-      ReportError(AddrOrErr.takeError());
+      ES.reportError(AddrOrErr.takeError());
       return 0;
     }
   }
@@ -633,7 +639,7 @@
   bool setProtections(ResourceIdMgr::ResourceId Id,
                       JITTargetAddress RemoteSegAddr, unsigned ProtFlags) {
     if (auto Err = callB<mem::SetProtections>(Id, RemoteSegAddr, ProtFlags)) {
-      ReportError(std::move(Err));
+      ES.reportError(std::move(Err));
       return true;
     } else
       return false;
@@ -641,7 +647,7 @@
 
   bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) {
     if (auto Err = callB<mem::WriteMem>(DirectBufferWriter(Src, Addr, Size))) {
-      ReportError(std::move(Err));
+      ES.reportError(std::move(Err));
       return true;
     } else
       return false;
@@ -653,6 +659,7 @@
 
   static Error doNothing() { return Error::success(); }
 
+  ExecutionSession &ES;
   std::function<void(Error)> ReportError;
   std::string RemoteTargetTriple;
   uint32_t RemotePointerSize = 0;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
index cf419d3..acbc168 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
@@ -161,9 +161,9 @@
     IntVoidFnTy Fn =
         reinterpret_cast<IntVoidFnTy>(static_cast<uintptr_t>(Addr));
 
-    DEBUG(dbgs() << "  Calling " << format("0x%016x", Addr) << "\n");
+    LLVM_DEBUG(dbgs() << "  Calling " << format("0x%016x", Addr) << "\n");
     int Result = Fn();
-    DEBUG(dbgs() << "  Result = " << Result << "\n");
+    LLVM_DEBUG(dbgs() << "  Result = " << Result << "\n");
 
     return Result;
   }
@@ -180,15 +180,13 @@
     for (auto &Arg : Args)
       ArgV[Idx++] = Arg.c_str();
     ArgV[ArgC] = 0;
-    DEBUG(
-      for (int Idx = 0; Idx < ArgC; ++Idx) {
-        llvm::dbgs() << "Arg " << Idx << ": " << ArgV[Idx] << "\n";
-      }
-    );
+    LLVM_DEBUG(for (int Idx = 0; Idx < ArgC; ++Idx) {
+      llvm::dbgs() << "Arg " << Idx << ": " << ArgV[Idx] << "\n";
+    });
 
-    DEBUG(dbgs() << "  Calling " << format("0x%016x", Addr) << "\n");
+    LLVM_DEBUG(dbgs() << "  Calling " << format("0x%016x", Addr) << "\n");
     int Result = Fn(ArgC, ArgV.get());
-    DEBUG(dbgs() << "  Result = " << Result << "\n");
+    LLVM_DEBUG(dbgs() << "  Result = " << Result << "\n");
 
     return Result;
   }
@@ -199,9 +197,9 @@
     VoidVoidFnTy Fn =
         reinterpret_cast<VoidVoidFnTy>(static_cast<uintptr_t>(Addr));
 
-    DEBUG(dbgs() << "  Calling " << format("0x%016x", Addr) << "\n");
+    LLVM_DEBUG(dbgs() << "  Calling " << format("0x%016x", Addr) << "\n");
     Fn();
-    DEBUG(dbgs() << "  Complete.\n");
+    LLVM_DEBUG(dbgs() << "  Complete.\n");
 
     return Error::success();
   }
@@ -211,7 +209,7 @@
     if (I != Allocators.end())
       return errorCodeToError(
                orcError(OrcErrorCode::RemoteAllocatorIdAlreadyInUse));
-    DEBUG(dbgs() << "  Created allocator " << Id << "\n");
+    LLVM_DEBUG(dbgs() << "  Created allocator " << Id << "\n");
     Allocators[Id] = Allocator();
     return Error::success();
   }
@@ -221,15 +219,16 @@
     if (I != IndirectStubsOwners.end())
       return errorCodeToError(
                orcError(OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse));
-    DEBUG(dbgs() << "  Create indirect stubs owner " << Id << "\n");
+    LLVM_DEBUG(dbgs() << "  Create indirect stubs owner " << Id << "\n");
     IndirectStubsOwners[Id] = ISBlockOwnerList();
     return Error::success();
   }
 
   Error handleDeregisterEHFrames(JITTargetAddress TAddr, uint32_t Size) {
     uint8_t *Addr = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(TAddr));
-    DEBUG(dbgs() << "  Registering EH frames at " << format("0x%016x", TAddr)
-                 << ", Size = " << Size << " bytes\n");
+    LLVM_DEBUG(dbgs() << "  Registering EH frames at "
+                      << format("0x%016x", TAddr) << ", Size = " << Size
+                      << " bytes\n");
     EHFramesDeregister(Addr, Size);
     return Error::success();
   }
@@ -240,7 +239,7 @@
       return errorCodeToError(
                orcError(OrcErrorCode::RemoteAllocatorDoesNotExist));
     Allocators.erase(I);
-    DEBUG(dbgs() << "  Destroyed allocator " << Id << "\n");
+    LLVM_DEBUG(dbgs() << "  Destroyed allocator " << Id << "\n");
     return Error::success();
   }
 
@@ -256,8 +255,8 @@
   Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>>
   handleEmitIndirectStubs(ResourceIdMgr::ResourceId Id,
                           uint32_t NumStubsRequired) {
-    DEBUG(dbgs() << "  ISMgr " << Id << " request " << NumStubsRequired
-                 << " stubs.\n");
+    LLVM_DEBUG(dbgs() << "  ISMgr " << Id << " request " << NumStubsRequired
+                      << " stubs.\n");
 
     auto StubOwnerItr = IndirectStubsOwners.find(Id);
     if (StubOwnerItr == IndirectStubsOwners.end())
@@ -328,8 +327,8 @@
 
   Expected<JITTargetAddress> handleGetSymbolAddress(const std::string &Name) {
     JITTargetAddress Addr = SymbolLookup(Name);
-    DEBUG(dbgs() << "  Symbol '" << Name << "' =  " << format("0x%016x", Addr)
-                 << "\n");
+    LLVM_DEBUG(dbgs() << "  Symbol '" << Name
+                      << "' =  " << format("0x%016x", Addr) << "\n");
     return Addr;
   }
 
@@ -340,12 +339,13 @@
     uint32_t PageSize = sys::Process::getPageSize();
     uint32_t TrampolineSize = TargetT::TrampolineSize;
     uint32_t IndirectStubSize = TargetT::IndirectStubsInfo::StubSize;
-    DEBUG(dbgs() << "  Remote info:\n"
-                 << "    triple             = '" << ProcessTriple << "'\n"
-                 << "    pointer size       = " << PointerSize << "\n"
-                 << "    page size          = " << PageSize << "\n"
-                 << "    trampoline size    = " << TrampolineSize << "\n"
-                 << "    indirect stub size = " << IndirectStubSize << "\n");
+    LLVM_DEBUG(dbgs() << "  Remote info:\n"
+                      << "    triple             = '" << ProcessTriple << "'\n"
+                      << "    pointer size       = " << PointerSize << "\n"
+                      << "    page size          = " << PageSize << "\n"
+                      << "    trampoline size    = " << TrampolineSize << "\n"
+                      << "    indirect stub size = " << IndirectStubSize
+                      << "\n");
     return std::make_tuple(ProcessTriple, PointerSize, PageSize, TrampolineSize,
                            IndirectStubSize);
   }
@@ -354,8 +354,8 @@
                                                uint64_t Size) {
     uint8_t *Src = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(RSrc));
 
-    DEBUG(dbgs() << "  Reading " << Size << " bytes from "
-                 << format("0x%016x", RSrc) << "\n");
+    LLVM_DEBUG(dbgs() << "  Reading " << Size << " bytes from "
+                      << format("0x%016x", RSrc) << "\n");
 
     std::vector<uint8_t> Buffer;
     Buffer.resize(Size);
@@ -367,8 +367,9 @@
 
   Error handleRegisterEHFrames(JITTargetAddress TAddr, uint32_t Size) {
     uint8_t *Addr = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(TAddr));
-    DEBUG(dbgs() << "  Registering EH frames at " << format("0x%016x", TAddr)
-                 << ", Size = " << Size << " bytes\n");
+    LLVM_DEBUG(dbgs() << "  Registering EH frames at "
+                      << format("0x%016x", TAddr) << ", Size = " << Size
+                      << " bytes\n");
     EHFramesRegister(Addr, Size);
     return Error::success();
   }
@@ -384,8 +385,9 @@
     if (auto Err = Allocator.allocate(LocalAllocAddr, Size, Align))
       return std::move(Err);
 
-    DEBUG(dbgs() << "  Allocator " << Id << " reserved " << LocalAllocAddr
-                 << " (" << Size << " bytes, alignment " << Align << ")\n");
+    LLVM_DEBUG(dbgs() << "  Allocator " << Id << " reserved " << LocalAllocAddr
+                      << " (" << Size << " bytes, alignment " << Align
+                      << ")\n");
 
     JITTargetAddress AllocAddr = static_cast<JITTargetAddress>(
         reinterpret_cast<uintptr_t>(LocalAllocAddr));
@@ -401,10 +403,11 @@
                orcError(OrcErrorCode::RemoteAllocatorDoesNotExist));
     auto &Allocator = I->second;
     void *LocalAddr = reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
-    DEBUG(dbgs() << "  Allocator " << Id << " set permissions on " << LocalAddr
-                 << " to " << (Flags & sys::Memory::MF_READ ? 'R' : '-')
-                 << (Flags & sys::Memory::MF_WRITE ? 'W' : '-')
-                 << (Flags & sys::Memory::MF_EXEC ? 'X' : '-') << "\n");
+    LLVM_DEBUG(dbgs() << "  Allocator " << Id << " set permissions on "
+                      << LocalAddr << " to "
+                      << (Flags & sys::Memory::MF_READ ? 'R' : '-')
+                      << (Flags & sys::Memory::MF_WRITE ? 'W' : '-')
+                      << (Flags & sys::Memory::MF_EXEC ? 'X' : '-') << "\n");
     return Allocator.setProtections(LocalAddr, Flags);
   }
 
@@ -414,14 +417,14 @@
   }
 
   Error handleWriteMem(DirectBufferWriter DBW) {
-    DEBUG(dbgs() << "  Writing " << DBW.getSize() << " bytes to "
-                 << format("0x%016x", DBW.getDst()) << "\n");
+    LLVM_DEBUG(dbgs() << "  Writing " << DBW.getSize() << " bytes to "
+                      << format("0x%016x", DBW.getDst()) << "\n");
     return Error::success();
   }
 
   Error handleWritePtr(JITTargetAddress Addr, JITTargetAddress PtrVal) {
-    DEBUG(dbgs() << "  Writing pointer *" << format("0x%016x", Addr) << " = "
-                 << format("0x%016x", PtrVal) << "\n");
+    LLVM_DEBUG(dbgs() << "  Writing pointer *" << format("0x%016x", Addr)
+                      << " = " << format("0x%016x", PtrVal) << "\n");
     uintptr_t *Ptr =
         reinterpret_cast<uintptr_t *>(static_cast<uintptr_t>(Addr));
     *Ptr = static_cast<uintptr_t>(PtrVal);
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCSerialization.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
index 569c506..1e5f6ce 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCSerialization.h
@@ -14,7 +14,10 @@
 #include "llvm/Support/thread.h"
 #include <map>
 #include <mutex>
+#include <set>
 #include <sstream>
+#include <string>
+#include <vector>
 
 namespace llvm {
 namespace orc {
@@ -205,6 +208,42 @@
 template <typename T>
 std::string RPCTypeName<std::vector<T>>::Name;
 
+template <typename T> class RPCTypeName<std::set<T>> {
+public:
+  static const char *getName() {
+    std::lock_guard<std::mutex> Lock(NameMutex);
+    if (Name.empty())
+      raw_string_ostream(Name)
+          << "std::set<" << RPCTypeName<T>::getName() << ">";
+    return Name.data();
+  }
+
+private:
+  static std::mutex NameMutex;
+  static std::string Name;
+};
+
+template <typename T> std::mutex RPCTypeName<std::set<T>>::NameMutex;
+template <typename T> std::string RPCTypeName<std::set<T>>::Name;
+
+template <typename K, typename V> class RPCTypeName<std::map<K, V>> {
+public:
+  static const char *getName() {
+    std::lock_guard<std::mutex> Lock(NameMutex);
+    if (Name.empty())
+      raw_string_ostream(Name)
+          << "std::map<" << RPCTypeNameSequence<K, V>() << ">";
+    return Name.data();
+  }
+
+private:
+  static std::mutex NameMutex;
+  static std::string Name;
+};
+
+template <typename K, typename V>
+std::mutex RPCTypeName<std::map<K, V>>::NameMutex;
+template <typename K, typename V> std::string RPCTypeName<std::map<K, V>>::Name;
 
 /// The SerializationTraits<ChannelT, T> class describes how to serialize and
 /// deserialize an instance of type T to/from an abstract channel of type
@@ -527,15 +566,20 @@
 };
 
 /// SerializationTraits default specialization for std::pair.
-template <typename ChannelT, typename T1, typename T2>
-class SerializationTraits<ChannelT, std::pair<T1, T2>> {
+template <typename ChannelT, typename T1, typename T2, typename T3, typename T4>
+class SerializationTraits<ChannelT, std::pair<T1, T2>, std::pair<T3, T4>> {
 public:
-  static Error serialize(ChannelT &C, const std::pair<T1, T2> &V) {
-    return serializeSeq(C, V.first, V.second);
+  static Error serialize(ChannelT &C, const std::pair<T3, T4> &V) {
+    if (auto Err = SerializationTraits<ChannelT, T1, T3>::serialize(C, V.first))
+      return Err;
+    return SerializationTraits<ChannelT, T2, T4>::serialize(C, V.second);
   }
 
-  static Error deserialize(ChannelT &C, std::pair<T1, T2> &V) {
-    return deserializeSeq(C, V.first, V.second);
+  static Error deserialize(ChannelT &C, std::pair<T3, T4> &V) {
+    if (auto Err =
+            SerializationTraits<ChannelT, T1, T3>::deserialize(C, V.first))
+      return Err;
+    return SerializationTraits<ChannelT, T2, T4>::deserialize(C, V.second);
   }
 };
 
@@ -589,6 +633,9 @@
 
   /// Deserialize a std::vector<T> to a std::vector<T>.
   static Error deserialize(ChannelT &C, std::vector<T> &V) {
+    assert(V.empty() &&
+           "Expected default-constructed vector to deserialize into");
+
     uint64_t Count = 0;
     if (auto Err = deserializeSeq(C, Count))
       return Err;
@@ -602,6 +649,92 @@
   }
 };
 
+template <typename ChannelT, typename T, typename T2>
+class SerializationTraits<ChannelT, std::set<T>, std::set<T2>> {
+public:
+  /// Serialize a std::set<T> from std::set<T2>.
+  static Error serialize(ChannelT &C, const std::set<T2> &S) {
+    if (auto Err = serializeSeq(C, static_cast<uint64_t>(S.size())))
+      return Err;
+
+    for (const auto &E : S)
+      if (auto Err = SerializationTraits<ChannelT, T, T2>::serialize(C, E))
+        return Err;
+
+    return Error::success();
+  }
+
+  /// Deserialize a std::set<T> to a std::set<T>.
+  static Error deserialize(ChannelT &C, std::set<T2> &S) {
+    assert(S.empty() && "Expected default-constructed set to deserialize into");
+
+    uint64_t Count = 0;
+    if (auto Err = deserializeSeq(C, Count))
+      return Err;
+
+    while (Count-- != 0) {
+      T2 Val;
+      if (auto Err = SerializationTraits<ChannelT, T, T2>::deserialize(C, Val))
+        return Err;
+
+      auto Added = S.insert(Val).second;
+      if (!Added)
+        return make_error<StringError>("Duplicate element in deserialized set",
+                                       orcError(OrcErrorCode::UnknownORCError));
+    }
+
+    return Error::success();
+  }
+};
+
+template <typename ChannelT, typename K, typename V, typename K2, typename V2>
+class SerializationTraits<ChannelT, std::map<K, V>, std::map<K2, V2>> {
+public:
+  /// Serialize a std::map<K, V> from std::map<K2, V2>.
+  static Error serialize(ChannelT &C, const std::map<K2, V2> &M) {
+    if (auto Err = serializeSeq(C, static_cast<uint64_t>(M.size())))
+      return Err;
+
+    for (const auto &E : M) {
+      if (auto Err =
+              SerializationTraits<ChannelT, K, K2>::serialize(C, E.first))
+        return Err;
+      if (auto Err =
+              SerializationTraits<ChannelT, V, V2>::serialize(C, E.second))
+        return Err;
+    }
+
+    return Error::success();
+  }
+
+  /// Deserialize a std::map<K, V> to a std::map<K, V>.
+  static Error deserialize(ChannelT &C, std::map<K2, V2> &M) {
+    assert(M.empty() && "Expected default-constructed map to deserialize into");
+
+    uint64_t Count = 0;
+    if (auto Err = deserializeSeq(C, Count))
+      return Err;
+
+    while (Count-- != 0) {
+      std::pair<K2, V2> Val;
+      if (auto Err =
+              SerializationTraits<ChannelT, K, K2>::deserialize(C, Val.first))
+        return Err;
+
+      if (auto Err =
+              SerializationTraits<ChannelT, V, V2>::deserialize(C, Val.second))
+        return Err;
+
+      auto Added = M.insert(Val).second;
+      if (!Added)
+        return make_error<StringError>("Duplicate element in deserialized map",
+                                       orcError(OrcErrorCode::UnknownORCError));
+    }
+
+    return Error::success();
+  }
+};
+
 } // end namespace rpc
 } // end namespace orc
 } // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h
index c278cb1..47bd90b 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RPCUtils.h
@@ -1631,7 +1631,7 @@
   return RPCAsyncDispatch<RPCEndpointT, Func>(Endpoint);
 }
 
-/// \brief Allows a set of asynchrounous calls to be dispatched, and then
+/// Allows a set of asynchrounous calls to be dispatched, and then
 ///        waited on as a group.
 class ParallelCallGroup {
 public:
@@ -1640,7 +1640,7 @@
   ParallelCallGroup(const ParallelCallGroup &) = delete;
   ParallelCallGroup &operator=(const ParallelCallGroup &) = delete;
 
-  /// \brief Make as asynchronous call.
+  /// Make as asynchronous call.
   template <typename AsyncDispatcher, typename HandlerT, typename... ArgTs>
   Error call(const AsyncDispatcher &AsyncDispatch, HandlerT Handler,
              const ArgTs &... Args) {
@@ -1669,7 +1669,7 @@
     return AsyncDispatch(std::move(WrappedHandler), Args...);
   }
 
-  /// \brief Blocks until all calls have been completed and their return value
+  /// Blocks until all calls have been completed and their return value
   ///        handlers run.
   void wait() {
     std::unique_lock<std::mutex> Lock(M);
@@ -1683,21 +1683,21 @@
   uint32_t NumOutstandingCalls = 0;
 };
 
-/// @brief Convenience class for grouping RPC Functions into APIs that can be
+/// Convenience class for grouping RPC Functions into APIs that can be
 ///        negotiated as a block.
 ///
 template <typename... Funcs>
 class APICalls {
 public:
 
-  /// @brief Test whether this API contains Function F.
+  /// Test whether this API contains Function F.
   template <typename F>
   class Contains {
   public:
     static const bool value = false;
   };
 
-  /// @brief Negotiate all functions in this API.
+  /// Negotiate all functions in this API.
   template <typename RPCEndpoint>
   static Error negotiate(RPCEndpoint &R) {
     return Error::success();
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
index 8f0d9fa..6510976 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
@@ -19,6 +19,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ExecutionEngine/JITSymbol.h"
 #include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
 #include "llvm/ExecutionEngine/Orc/Legacy.h"
 #include "llvm/ExecutionEngine/RuntimeDyld.h"
 #include "llvm/Object/ObjectFile.h"
@@ -35,13 +36,62 @@
 namespace llvm {
 namespace orc {
 
+class RTDyldObjectLinkingLayer2 : public ObjectLayer {
+public:
+  /// Functor for receiving object-loaded notifications.
+  using NotifyLoadedFunction =
+      std::function<void(VModuleKey, const object::ObjectFile &Obj,
+                         const RuntimeDyld::LoadedObjectInfo &)>;
+
+  /// Functor for receiving finalization notifications.
+  using NotifyFinalizedFunction = std::function<void(VModuleKey)>;
+
+  using GetMemoryManagerFunction =
+      std::function<std::shared_ptr<RuntimeDyld::MemoryManager>(VModuleKey)>;
+
+  /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
+  ///        and NotifyFinalized functors.
+  RTDyldObjectLinkingLayer2(
+      ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager,
+      NotifyLoadedFunction NotifyLoaded = NotifyLoadedFunction(),
+      NotifyFinalizedFunction NotifyFinalized = NotifyFinalizedFunction());
+
+  /// Emit the object.
+  void emit(MaterializationResponsibility R, VModuleKey K,
+            std::unique_ptr<MemoryBuffer> O) override;
+
+  /// Map section addresses for the object associated with the
+  ///        VModuleKey K.
+  void mapSectionAddress(VModuleKey K, const void *LocalAddress,
+                         JITTargetAddress TargetAddr) const;
+
+  /// Set the 'ProcessAllSections' flag.
+  ///
+  /// If set to true, all sections in each object file will be allocated using
+  /// the memory manager, rather than just the sections required for execution.
+  ///
+  /// This is kludgy, and may be removed in the future.
+  void setProcessAllSections(bool ProcessAllSections) {
+    this->ProcessAllSections = ProcessAllSections;
+  }
+
+private:
+  mutable std::mutex RTDyldLayerMutex;
+  GetMemoryManagerFunction GetMemoryManager;
+  NotifyLoadedFunction NotifyLoaded;
+  NotifyFinalizedFunction NotifyFinalized;
+  bool ProcessAllSections;
+  std::map<VModuleKey, RuntimeDyld *> ActiveRTDylds;
+  std::map<VModuleKey, std::shared_ptr<RuntimeDyld::MemoryManager>> MemMgrs;
+};
+
 class RTDyldObjectLinkingLayerBase {
 public:
   using ObjectPtr = std::unique_ptr<MemoryBuffer>;
 
 protected:
 
-  /// @brief Holds an object to be allocated/linked as a unit in the JIT.
+  /// Holds an object to be allocated/linked as a unit in the JIT.
   ///
   /// An instance of this class will be created for each object added
   /// via JITObjectLayer::addObject. Deleting the instance (via
@@ -81,7 +131,7 @@
   };
 };
 
-/// @brief Bare bones object linking layer.
+/// Bare bones object linking layer.
 ///
 ///   This class is intended to be used as the base layer for a JIT. It allows
 /// object files to be loaded into memory, linked, and the addresses of their
@@ -92,13 +142,18 @@
 
   using RTDyldObjectLinkingLayerBase::ObjectPtr;
 
-  /// @brief Functor for receiving object-loaded notifications.
+  /// Functor for receiving object-loaded notifications.
   using NotifyLoadedFtor =
       std::function<void(VModuleKey, const object::ObjectFile &Obj,
                          const RuntimeDyld::LoadedObjectInfo &)>;
 
-  /// @brief Functor for receiving finalization notifications.
-  using NotifyFinalizedFtor = std::function<void(VModuleKey)>;
+  /// Functor for receiving finalization notifications.
+  using NotifyFinalizedFtor =
+      std::function<void(VModuleKey, const object::ObjectFile &Obj,
+                         const RuntimeDyld::LoadedObjectInfo &)>;
+
+  /// Functor for receiving deallocation notifications.
+  using NotifyFreedFtor = std::function<void(VModuleKey, const object::ObjectFile &Obj)>;
 
 private:
   using OwnedObject = object::OwningBinary<object::ObjectFile>;
@@ -110,21 +165,27 @@
                          OwnedObject Obj, MemoryManagerPtrT MemMgr,
                          std::shared_ptr<SymbolResolver> Resolver,
                          bool ProcessAllSections)
-        : MemMgr(std::move(MemMgr)),
+        : K(std::move(K)),
+          Parent(Parent),
+          MemMgr(std::move(MemMgr)),
           PFC(llvm::make_unique<PreFinalizeContents>(
-              Parent, std::move(K), std::move(Obj), std::move(Resolver),
+              std::move(Obj), std::move(Resolver),
               ProcessAllSections)) {
       buildInitialSymbolTable(PFC->Obj);
     }
 
     ~ConcreteLinkedObject() override {
+      if (this->Parent.NotifyFreed)
+        this->Parent.NotifyFreed(K, *ObjForNotify.getBinary());
+
       MemMgr->deregisterEHFrames();
     }
 
     Error finalize() override {
       assert(PFC && "mapSectionAddress called on finalized LinkedObject");
 
-      JITSymbolResolverAdapter ResolverAdapter(PFC->Parent.ES, *PFC->Resolver);
+      JITSymbolResolverAdapter ResolverAdapter(Parent.ES, *PFC->Resolver,
+					       nullptr);
       PFC->RTDyld = llvm::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter);
       PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections);
 
@@ -140,8 +201,8 @@
           SymbolTable[KV.first] = KV.second;
       }
 
-      if (PFC->Parent.NotifyLoaded)
-        PFC->Parent.NotifyLoaded(PFC->K, *PFC->Obj.getBinary(), *Info);
+      if (Parent.NotifyLoaded)
+        Parent.NotifyLoaded(K, *PFC->Obj.getBinary(), *Info);
 
       PFC->RTDyld->finalizeWithMemoryManagerLocking();
 
@@ -149,10 +210,12 @@
         return make_error<StringError>(PFC->RTDyld->getErrorString(),
                                        inconvertibleErrorCode());
 
-      if (PFC->Parent.NotifyFinalized)
-        PFC->Parent.NotifyFinalized(PFC->K);
+      if (Parent.NotifyFinalized)
+        Parent.NotifyFinalized(K, *PFC->Obj.getBinary(), *Info);
 
       // Release resources.
+      if (this->Parent.NotifyFreed)
+        ObjForNotify = std::move(PFC->Obj); // needed for callback
       PFC = nullptr;
       return Error::success();
     }
@@ -186,32 +249,37 @@
           consumeError(SymbolName.takeError());
           continue;
         }
+        // FIXME: Raise an error for bad symbols.
         auto Flags = JITSymbolFlags::fromObjectSymbol(Symbol);
+        if (!Flags) {
+          consumeError(Flags.takeError());
+          continue;
+        }
         SymbolTable.insert(
-          std::make_pair(*SymbolName, JITEvaluatedSymbol(0, Flags)));
+            std::make_pair(*SymbolName, JITEvaluatedSymbol(0, *Flags)));
       }
     }
 
     // Contains the information needed prior to finalization: the object files,
     // memory manager, resolver, and flags needed for RuntimeDyld.
     struct PreFinalizeContents {
-      PreFinalizeContents(RTDyldObjectLinkingLayer &Parent, VModuleKey K,
-                          OwnedObject Obj,
+      PreFinalizeContents(OwnedObject Obj,
                           std::shared_ptr<SymbolResolver> Resolver,
                           bool ProcessAllSections)
-          : Parent(Parent), K(std::move(K)), Obj(std::move(Obj)),
+          : Obj(std::move(Obj)),
             Resolver(std::move(Resolver)),
             ProcessAllSections(ProcessAllSections) {}
 
-      RTDyldObjectLinkingLayer &Parent;
-      VModuleKey K;
       OwnedObject Obj;
       std::shared_ptr<SymbolResolver> Resolver;
       bool ProcessAllSections;
       std::unique_ptr<RuntimeDyld> RTDyld;
     };
 
+    VModuleKey K;
+    RTDyldObjectLinkingLayer &Parent;
     MemoryManagerPtrT MemMgr;
+    OwnedObject ObjForNotify;
     std::unique_ptr<PreFinalizeContents> PFC;
   };
 
@@ -235,18 +303,21 @@
 
   using ResourcesGetter = std::function<Resources(VModuleKey)>;
 
-  /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
+  /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
   ///        and NotifyFinalized functors.
   RTDyldObjectLinkingLayer(
       ExecutionSession &ES, ResourcesGetter GetResources,
       NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
-      NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
+      NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(),
+      NotifyFreedFtor NotifyFreed = NotifyFreedFtor())
       : ES(ES), GetResources(std::move(GetResources)),
         NotifyLoaded(std::move(NotifyLoaded)),
-        NotifyFinalized(std::move(NotifyFinalized)), ProcessAllSections(false) {
+        NotifyFinalized(std::move(NotifyFinalized)),
+        NotifyFreed(std::move(NotifyFreed)),
+        ProcessAllSections(false) {
   }
 
-  /// @brief Set the 'ProcessAllSections' flag.
+  /// Set the 'ProcessAllSections' flag.
   ///
   /// If set to true, all sections in each object file will be allocated using
   /// the memory manager, rather than just the sections required for execution.
@@ -256,7 +327,7 @@
     this->ProcessAllSections = ProcessAllSections;
   }
 
-  /// @brief Add an object to the JIT.
+  /// Add an object to the JIT.
   Error addObject(VModuleKey K, ObjectPtr ObjBuffer) {
 
     auto Obj =
@@ -275,7 +346,7 @@
     return Error::success();
   }
 
-  /// @brief Remove the object associated with VModuleKey K.
+  /// Remove the object associated with VModuleKey K.
   ///
   ///   All memory allocated for the object will be freed, and the sections and
   /// symbols it provided will no longer be available. No attempt is made to
@@ -290,7 +361,7 @@
     return Error::success();
   }
 
-  /// @brief Search for the given named symbol.
+  /// Search for the given named symbol.
   /// @param Name The name of the symbol to search for.
   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
   /// @return A handle for the given named symbol, if it exists.
@@ -304,7 +375,7 @@
     return nullptr;
   }
 
-  /// @brief Search for the given named symbol in the context of the loaded
+  /// Search for the given named symbol in the context of the loaded
   ///        object represented by the VModuleKey K.
   /// @param K The VModuleKey for the object to search in.
   /// @param Name The name of the symbol to search for.
@@ -317,7 +388,7 @@
     return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly);
   }
 
-  /// @brief Map section addresses for the object associated with the
+  /// Map section addresses for the object associated with the
   ///        VModuleKey K.
   void mapSectionAddress(VModuleKey K, const void *LocalAddress,
                          JITTargetAddress TargetAddr) {
@@ -325,7 +396,7 @@
     LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr);
   }
 
-  /// @brief Immediately emit and finalize the object represented by the given
+  /// Immediately emit and finalize the object represented by the given
   ///        VModuleKey.
   /// @param K VModuleKey for object to emit/finalize.
   Error emitAndFinalize(VModuleKey K) {
@@ -340,6 +411,7 @@
   ResourcesGetter GetResources;
   NotifyLoadedFtor NotifyLoaded;
   NotifyFinalizedFtor NotifyFinalized;
+  NotifyFreedFtor NotifyFreed;
   bool ProcessAllSections = false;
 };
 
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h
index b95faaa..955e776 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h
@@ -322,7 +322,7 @@
             *this, &ThisT::lookupInLogicalDylib);
   }
 
-  /// @brief Add an object to the JIT.
+  /// Add an object to the JIT.
   ///
   /// @return A handle that can be used to refer to the loaded object (for
   ///         symbol searching, finalization, freeing memory, etc.).
@@ -340,26 +340,26 @@
       return HandleOrErr.takeError();
   }
 
-  /// @brief Remove the given object from the JIT.
+  /// Remove the given object from the JIT.
   Error removeObject(ObjHandleT H) {
     return this->Remote.template callB<RemoveObject>(H);
   }
 
-  /// @brief Search for the given named symbol.
+  /// Search for the given named symbol.
   JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
     return remoteToJITSymbol(
              this->Remote.template callB<FindSymbol>(Name,
                                                      ExportedSymbolsOnly));
   }
 
-  /// @brief Search for the given named symbol within the given context.
+  /// Search for the given named symbol within the given context.
   JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, bool ExportedSymbolsOnly) {
     return remoteToJITSymbol(
              this->Remote.template callB<FindSymbolIn>(H, Name,
                                                        ExportedSymbolsOnly));
   }
 
-  /// @brief Immediately emit and finalize the object with the given handle.
+  /// Immediately emit and finalize the object with the given handle.
   Error emitAndFinalize(ObjHandleT H) {
     return this->Remote.template callB<EmitAndFinalize>(H);
   }
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
index da40d1c..4c45cfd 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h
@@ -23,17 +23,20 @@
 
 class SymbolStringPtr;
 
-/// @brief String pool for symbol names used by the JIT.
+/// String pool for symbol names used by the JIT.
 class SymbolStringPool {
   friend class SymbolStringPtr;
 public:
-  /// @brief Create a symbol string pointer from the given string.
+  /// Destroy a SymbolStringPool.
+  ~SymbolStringPool();
+
+  /// Create a symbol string pointer from the given string.
   SymbolStringPtr intern(StringRef S);
 
-  /// @brief Remove from the pool any entries that are no longer referenced.
+  /// Remove from the pool any entries that are no longer referenced.
   void clearDeadEntries();
 
-  /// @brief Returns true if the pool is empty.
+  /// Returns true if the pool is empty.
   bool empty() const;
 private:
   using RefCountType = std::atomic<size_t>;
@@ -43,7 +46,7 @@
   PoolMap Pool;
 };
 
-/// @brief Pointer to a pooled string representing a symbol name.
+/// Pointer to a pooled string representing a symbol name.
 class SymbolStringPtr {
   friend class SymbolStringPool;
   friend bool operator==(const SymbolStringPtr &LHS,
@@ -109,6 +112,13 @@
   return LHS.S < RHS.S;
 }
 
+inline SymbolStringPool::~SymbolStringPool() {
+#ifndef NDEBUG
+  clearDeadEntries();
+  assert(Pool.empty() && "Dangling references at pool destruction time");
+#endif // NDEBUG
+}
+
 inline SymbolStringPtr SymbolStringPool::intern(StringRef S) {
   std::lock_guard<std::mutex> Lock(PoolMutex);
   PoolMap::iterator I;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/linux-x64/clang/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
index ee75202..23d651f 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
@@ -47,6 +47,9 @@
   /// newly loaded object.
   virtual void notifyObjectLoaded(ExecutionEngine *EE,
                                   const object::ObjectFile &) {}
+
+private:
+  void anchor() override;
 };
 
 // RuntimeDyld clients often want to handle the memory management of
@@ -142,6 +145,9 @@
   };
   typedef std::vector<EHFrame> EHFrameInfos;
   EHFrameInfos EHFrames;
+
+private:
+  void anchor() override;
 };
 
 // Create wrappers for C Binding types (see CBindingWrapping.h).
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyld.h b/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyld.h
index 14da5af..5dd5add 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyld.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyld.h
@@ -65,7 +65,7 @@
   void reassignSectionAddress(unsigned SectionID, uint64_t Addr);
 
 public:
-  /// \brief Information about the loaded object.
+  /// Information about the loaded object.
   class LoadedObjectInfo : public llvm::LoadedObjectInfo {
     friend class RuntimeDyldImpl;
 
@@ -88,7 +88,7 @@
     ObjSectionToIDMap ObjSecToIDMap;
   };
 
-  /// \brief Memory Management.
+  /// Memory Management.
   class MemoryManager {
     friend class RuntimeDyld;
 
@@ -170,7 +170,7 @@
     bool FinalizationLocked = false;
   };
 
-  /// \brief Construct a RuntimeDyld instance.
+  /// Construct a RuntimeDyld instance.
   RuntimeDyld(MemoryManager &MemMgr, JITSymbolResolver &Resolver);
   RuntimeDyld(const RuntimeDyld &) = delete;
   RuntimeDyld &operator=(const RuntimeDyld &) = delete;
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
index de89f40..13fc5fd 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/RuntimeDyldChecker.h
@@ -27,7 +27,7 @@
 class RuntimeDyldCheckerImpl;
 class raw_ostream;
 
-/// \brief RuntimeDyld invariant checker for verifying that RuntimeDyld has
+/// RuntimeDyld invariant checker for verifying that RuntimeDyld has
 ///        correctly applied relocations.
 ///
 /// The RuntimeDyldChecker class evaluates expressions against an attached
@@ -74,22 +74,22 @@
                      MCInstPrinter *InstPrinter, raw_ostream &ErrStream);
   ~RuntimeDyldChecker();
 
-  // \brief Get the associated RTDyld instance.
+  // Get the associated RTDyld instance.
   RuntimeDyld& getRTDyld();
 
-  // \brief Get the associated RTDyld instance.
+  // Get the associated RTDyld instance.
   const RuntimeDyld& getRTDyld() const;
 
-  /// \brief Check a single expression against the attached RuntimeDyld
+  /// Check a single expression against the attached RuntimeDyld
   ///        instance.
   bool check(StringRef CheckExpr) const;
 
-  /// \brief Scan the given memory buffer for lines beginning with the string
+  /// Scan the given memory buffer for lines beginning with the string
   ///        in RulePrefix. The remainder of the line is passed to the check
   ///        method to be evaluated as an expression.
   bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
 
-  /// \brief Returns the address of the requested section (or an error message
+  /// Returns the address of the requested section (or an error message
   ///        in the second element of the pair if the address cannot be found).
   ///
   /// if 'LocalAddress' is true, this returns the address of the section
@@ -99,7 +99,7 @@
                                                   StringRef SectionName,
                                                   bool LocalAddress);
 
-  /// \brief If there is a section at the given local address, return its load
+  /// If there is a section at the given local address, return its load
   ///        address, otherwise return none.
   Optional<uint64_t> getSectionLoadAddress(void *LocalAddress) const;
 
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/SectionMemoryManager.h b/linux-x64/clang/include/llvm/ExecutionEngine/SectionMemoryManager.h
index d76e371..3cf131c 100644
--- a/linux-x64/clang/include/llvm/ExecutionEngine/SectionMemoryManager.h
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/SectionMemoryManager.h
@@ -111,7 +111,7 @@
   void operator=(const SectionMemoryManager &) = delete;
   ~SectionMemoryManager() override;
 
-  /// \brief Allocates a memory block of (at least) the given size suitable for
+  /// Allocates a memory block of (at least) the given size suitable for
   /// executable code.
   ///
   /// The value of \p Alignment must be a power of two.  If \p Alignment is zero
@@ -120,7 +120,7 @@
                                unsigned SectionID,
                                StringRef SectionName) override;
 
-  /// \brief Allocates a memory block of (at least) the given size suitable for
+  /// Allocates a memory block of (at least) the given size suitable for
   /// executable code.
   ///
   /// The value of \p Alignment must be a power of two.  If \p Alignment is zero
@@ -129,7 +129,7 @@
                                unsigned SectionID, StringRef SectionName,
                                bool isReadOnly) override;
 
-  /// \brief Update section-specific memory permissions and other attributes.
+  /// Update section-specific memory permissions and other attributes.
   ///
   /// This method is called when object loading is complete and section page
   /// permissions can be applied.  It is up to the memory manager implementation
@@ -142,7 +142,7 @@
   /// \returns true if an error occurred, false otherwise.
   bool finalizeMemory(std::string *ErrMsg = nullptr) override;
 
-  /// \brief Invalidate instruction cache for code sections.
+  /// Invalidate instruction cache for code sections.
   ///
   /// Some platforms with separate data cache and instruction cache require
   /// explicit cache flush, otherwise JIT code manipulations (like resolved
@@ -182,6 +182,8 @@
   std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup,
                                               unsigned Permissions);
 
+  void anchor() override;
+
   MemoryGroup CodeMem;
   MemoryGroup RWDataMem;
   MemoryGroup RODataMem;