Update prebuilt Clang to r416183b from Android.

https://android.googlesource.com/platform/prebuilts/clang/host/
linux-x86/+/06a71ddac05c22edb2d10b590e1769b3f8619bef

clang 12.0.5 (based on r416183b) from build 7284624.

Change-Id: I277a316abcf47307562d8b748b84870f31a72866
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h
new file mode 100644
index 0000000..1097ae6
--- /dev/null
+++ b/linux-x64/clang/include/llvm/ExecutionEngine/Orc/OrcRPCTargetProcessControl.h
@@ -0,0 +1,415 @@
+//===--- OrcRPCTargetProcessControl.h - Remote target control ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utilities for interacting with target processes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H
+#define LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H
+
+#include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h"
+#include "llvm/ExecutionEngine/Orc/Shared/RawByteChannel.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/OrcRPCTPCServer.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcessControl.h"
+#include "llvm/Support/MSVCErrorWorkarounds.h"
+
+namespace llvm {
+namespace orc {
+
+/// JITLinkMemoryManager implementation for a process connected via an ORC RPC
+/// endpoint.
+template <typename OrcRPCTPCImplT>
+class OrcRPCTPCJITLinkMemoryManager : public jitlink::JITLinkMemoryManager {
+private:
+  struct HostAlloc {
+    std::unique_ptr<char[]> Mem;
+    uint64_t Size;
+  };
+
+  struct TargetAlloc {
+    JITTargetAddress Address = 0;
+    uint64_t AllocatedSize = 0;
+  };
+
+  using HostAllocMap = DenseMap<int, HostAlloc>;
+  using TargetAllocMap = DenseMap<int, TargetAlloc>;
+
+public:
+  class OrcRPCAllocation : public Allocation {
+  public:
+    OrcRPCAllocation(OrcRPCTPCJITLinkMemoryManager<OrcRPCTPCImplT> &Parent,
+                     HostAllocMap HostAllocs, TargetAllocMap TargetAllocs)
+        : Parent(Parent), HostAllocs(std::move(HostAllocs)),
+          TargetAllocs(std::move(TargetAllocs)) {
+      assert(HostAllocs.size() == TargetAllocs.size() &&
+             "HostAllocs size should match TargetAllocs");
+    }
+
+    ~OrcRPCAllocation() override {
+      assert(TargetAllocs.empty() && "failed to deallocate");
+    }
+
+    MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) override {
+      auto I = HostAllocs.find(Seg);
+      assert(I != HostAllocs.end() && "No host allocation for segment");
+      auto &HA = I->second;
+      return {HA.Mem.get(), static_cast<size_t>(HA.Size)};
+    }
+
+    JITTargetAddress getTargetMemory(ProtectionFlags Seg) override {
+      auto I = TargetAllocs.find(Seg);
+      assert(I != TargetAllocs.end() && "No target allocation for segment");
+      return I->second.Address;
+    }
+
+    void finalizeAsync(FinalizeContinuation OnFinalize) override {
+
+      std::vector<tpctypes::BufferWrite> BufferWrites;
+      orcrpctpc::ReleaseOrFinalizeMemRequest FMR;
+
+      for (auto &KV : HostAllocs) {
+        assert(TargetAllocs.count(KV.first) &&
+               "No target allocation for buffer");
+        auto &HA = KV.second;
+        auto &TA = TargetAllocs[KV.first];
+        BufferWrites.push_back({TA.Address, StringRef(HA.Mem.get(), HA.Size)});
+        FMR.push_back({orcrpctpc::toWireProtectionFlags(
+                           static_cast<sys::Memory::ProtectionFlags>(KV.first)),
+                       TA.Address, TA.AllocatedSize});
+      }
+
+      DEBUG_WITH_TYPE("orc", {
+        dbgs() << "finalizeAsync " << (void *)this << ":\n";
+        auto FMRI = FMR.begin();
+        for (auto &B : BufferWrites) {
+          auto Prot = FMRI->Prot;
+          ++FMRI;
+          dbgs() << "  Writing " << formatv("{0:x16}", B.Buffer.size())
+                 << " bytes to " << ((Prot & orcrpctpc::WPF_Read) ? 'R' : '-')
+                 << ((Prot & orcrpctpc::WPF_Write) ? 'W' : '-')
+                 << ((Prot & orcrpctpc::WPF_Exec) ? 'X' : '-')
+                 << " segment: local " << (const void *)B.Buffer.data()
+                 << " -> target " << formatv("{0:x16}", B.Address) << "\n";
+        }
+      });
+      if (auto Err =
+              Parent.Parent.getMemoryAccess().writeBuffers(BufferWrites)) {
+        OnFinalize(std::move(Err));
+        return;
+      }
+
+      DEBUG_WITH_TYPE("orc", dbgs() << " Applying permissions...\n");
+      if (auto Err =
+              Parent.getEndpoint().template callAsync<orcrpctpc::FinalizeMem>(
+                  [OF = std::move(OnFinalize)](Error Err2) {
+                    // FIXME: Dispatch to work queue.
+                    std::thread([OF = std::move(OF),
+                                 Err3 = std::move(Err2)]() mutable {
+                      DEBUG_WITH_TYPE(
+                          "orc", { dbgs() << "  finalizeAsync complete\n"; });
+                      OF(std::move(Err3));
+                    }).detach();
+                    return Error::success();
+                  },
+                  FMR)) {
+        DEBUG_WITH_TYPE("orc", dbgs() << "    failed.\n");
+        Parent.getEndpoint().abandonPendingResponses();
+        Parent.reportError(std::move(Err));
+      }
+      DEBUG_WITH_TYPE("orc", {
+        dbgs() << "Leaving finalizeAsync (finalization may continue in "
+                  "background)\n";
+      });
+    }
+
+    Error deallocate() override {
+      orcrpctpc::ReleaseOrFinalizeMemRequest RMR;
+      for (auto &KV : TargetAllocs)
+        RMR.push_back({orcrpctpc::toWireProtectionFlags(
+                           static_cast<sys::Memory::ProtectionFlags>(KV.first)),
+                       KV.second.Address, KV.second.AllocatedSize});
+      TargetAllocs.clear();
+
+      return Parent.getEndpoint().template callB<orcrpctpc::ReleaseMem>(RMR);
+    }
+
+  private:
+    OrcRPCTPCJITLinkMemoryManager<OrcRPCTPCImplT> &Parent;
+    HostAllocMap HostAllocs;
+    TargetAllocMap TargetAllocs;
+  };
+
+  OrcRPCTPCJITLinkMemoryManager(OrcRPCTPCImplT &Parent) : Parent(Parent) {}
+
+  Expected<std::unique_ptr<Allocation>>
+  allocate(const jitlink::JITLinkDylib *JD,
+           const SegmentsRequestMap &Request) override {
+    orcrpctpc::ReserveMemRequest RMR;
+    HostAllocMap HostAllocs;
+
+    for (auto &KV : Request) {
+      assert(KV.second.getContentSize() <= std::numeric_limits<size_t>::max() &&
+             "Content size is out-of-range for host");
+
+      RMR.push_back({orcrpctpc::toWireProtectionFlags(
+                         static_cast<sys::Memory::ProtectionFlags>(KV.first)),
+                     KV.second.getContentSize() + KV.second.getZeroFillSize(),
+                     KV.second.getAlignment()});
+      HostAllocs[KV.first] = {
+          std::make_unique<char[]>(KV.second.getContentSize()),
+          KV.second.getContentSize()};
+    }
+
+    DEBUG_WITH_TYPE("orc", {
+      dbgs() << "Orc remote memmgr got request:\n";
+      for (auto &KV : Request)
+        dbgs() << "  permissions: "
+               << ((KV.first & sys::Memory::MF_READ) ? 'R' : '-')
+               << ((KV.first & sys::Memory::MF_WRITE) ? 'W' : '-')
+               << ((KV.first & sys::Memory::MF_EXEC) ? 'X' : '-')
+               << ", content size: "
+               << formatv("{0:x16}", KV.second.getContentSize())
+               << " + zero-fill-size: "
+               << formatv("{0:x16}", KV.second.getZeroFillSize())
+               << ", align: " << KV.second.getAlignment() << "\n";
+    });
+
+    // FIXME: LLVM RPC needs to be fixed to support alt
+    // serialization/deserialization on return types. For now just
+    // translate from std::map to DenseMap manually.
+    auto TmpTargetAllocs =
+        Parent.getEndpoint().template callB<orcrpctpc::ReserveMem>(RMR);
+    if (!TmpTargetAllocs)
+      return TmpTargetAllocs.takeError();
+
+    if (TmpTargetAllocs->size() != RMR.size())
+      return make_error<StringError>(
+          "Number of target allocations does not match request",
+          inconvertibleErrorCode());
+
+    TargetAllocMap TargetAllocs;
+    for (auto &E : *TmpTargetAllocs)
+      TargetAllocs[orcrpctpc::fromWireProtectionFlags(E.Prot)] = {
+          E.Address, E.AllocatedSize};
+
+    DEBUG_WITH_TYPE("orc", {
+      auto HAI = HostAllocs.begin();
+      for (auto &KV : TargetAllocs)
+        dbgs() << "  permissions: "
+               << ((KV.first & sys::Memory::MF_READ) ? 'R' : '-')
+               << ((KV.first & sys::Memory::MF_WRITE) ? 'W' : '-')
+               << ((KV.first & sys::Memory::MF_EXEC) ? 'X' : '-')
+               << " assigned local " << (void *)HAI->second.Mem.get()
+               << ", target " << formatv("{0:x16}", KV.second.Address) << "\n";
+    });
+
+    return std::make_unique<OrcRPCAllocation>(*this, std::move(HostAllocs),
+                                              std::move(TargetAllocs));
+  }
+
+private:
+  void reportError(Error Err) { Parent.reportError(std::move(Err)); }
+
+  decltype(std::declval<OrcRPCTPCImplT>().getEndpoint()) getEndpoint() {
+    return Parent.getEndpoint();
+  }
+
+  OrcRPCTPCImplT &Parent;
+};
+
+/// TargetProcessControl::MemoryAccess implementation for a process connected
+/// via an ORC RPC endpoint.
+template <typename OrcRPCTPCImplT>
+class OrcRPCTPCMemoryAccess : public TargetProcessControl::MemoryAccess {
+public:
+  OrcRPCTPCMemoryAccess(OrcRPCTPCImplT &Parent) : Parent(Parent) {}
+
+  void writeUInt8s(ArrayRef<tpctypes::UInt8Write> Ws,
+                   WriteResultFn OnWriteComplete) override {
+    writeViaRPC<orcrpctpc::WriteUInt8s>(Ws, std::move(OnWriteComplete));
+  }
+
+  void writeUInt16s(ArrayRef<tpctypes::UInt16Write> Ws,
+                    WriteResultFn OnWriteComplete) override {
+    writeViaRPC<orcrpctpc::WriteUInt16s>(Ws, std::move(OnWriteComplete));
+  }
+
+  void writeUInt32s(ArrayRef<tpctypes::UInt32Write> Ws,
+                    WriteResultFn OnWriteComplete) override {
+    writeViaRPC<orcrpctpc::WriteUInt32s>(Ws, std::move(OnWriteComplete));
+  }
+
+  void writeUInt64s(ArrayRef<tpctypes::UInt64Write> Ws,
+                    WriteResultFn OnWriteComplete) override {
+    writeViaRPC<orcrpctpc::WriteUInt64s>(Ws, std::move(OnWriteComplete));
+  }
+
+  void writeBuffers(ArrayRef<tpctypes::BufferWrite> Ws,
+                    WriteResultFn OnWriteComplete) override {
+    writeViaRPC<orcrpctpc::WriteBuffers>(Ws, std::move(OnWriteComplete));
+  }
+
+private:
+  template <typename WriteRPCFunction, typename WriteElementT>
+  void writeViaRPC(ArrayRef<WriteElementT> Ws, WriteResultFn OnWriteComplete) {
+    if (auto Err = Parent.getEndpoint().template callAsync<WriteRPCFunction>(
+            [OWC = std::move(OnWriteComplete)](Error Err2) mutable -> Error {
+              OWC(std::move(Err2));
+              return Error::success();
+            },
+            Ws)) {
+      Parent.reportError(std::move(Err));
+      Parent.getEndpoint().abandonPendingResponses();
+    }
+  }
+
+  OrcRPCTPCImplT &Parent;
+};
+
+// TargetProcessControl for a process connected via an ORC RPC Endpoint.
+template <typename RPCEndpointT>
+class OrcRPCTargetProcessControlBase : public TargetProcessControl {
+public:
+  using ErrorReporter = unique_function<void(Error)>;
+
+  using OnCloseConnectionFunction = unique_function<Error(Error)>;
+
+  OrcRPCTargetProcessControlBase(std::shared_ptr<SymbolStringPool> SSP,
+                                 RPCEndpointT &EP, ErrorReporter ReportError)
+      : TargetProcessControl(std::move(SSP)),
+        ReportError(std::move(ReportError)), EP(EP) {}
+
+  void reportError(Error Err) { ReportError(std::move(Err)); }
+
+  RPCEndpointT &getEndpoint() { return EP; }
+
+  Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override {
+    DEBUG_WITH_TYPE("orc", {
+      dbgs() << "Loading dylib \"" << (DylibPath ? DylibPath : "") << "\" ";
+      if (!DylibPath)
+        dbgs() << "(process symbols)";
+      dbgs() << "\n";
+    });
+    if (!DylibPath)
+      DylibPath = "";
+    auto H = EP.template callB<orcrpctpc::LoadDylib>(DylibPath);
+    DEBUG_WITH_TYPE("orc", {
+      if (H)
+        dbgs() << "  got handle " << formatv("{0:x16}", *H) << "\n";
+      else
+        dbgs() << "  error, unable to load\n";
+    });
+    return H;
+  }
+
+  Expected<std::vector<tpctypes::LookupResult>>
+  lookupSymbols(ArrayRef<tpctypes::LookupRequest> Request) override {
+    std::vector<orcrpctpc::RemoteLookupRequest> RR;
+    for (auto &E : Request) {
+      RR.push_back({});
+      RR.back().first = E.Handle;
+      for (auto &KV : E.Symbols)
+        RR.back().second.push_back(
+            {(*KV.first).str(),
+             KV.second == SymbolLookupFlags::WeaklyReferencedSymbol});
+    }
+    DEBUG_WITH_TYPE("orc", {
+      dbgs() << "Compound lookup:\n";
+      for (auto &R : Request) {
+        dbgs() << "  In " << formatv("{0:x16}", R.Handle) << ": {";
+        bool First = true;
+        for (auto &KV : R.Symbols) {
+          dbgs() << (First ? "" : ",") << " " << *KV.first;
+          First = false;
+        }
+        dbgs() << " }\n";
+      }
+    });
+    return EP.template callB<orcrpctpc::LookupSymbols>(RR);
+  }
+
+  Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr,
+                              ArrayRef<std::string> Args) override {
+    DEBUG_WITH_TYPE("orc", {
+      dbgs() << "Running as main: " << formatv("{0:x16}", MainFnAddr)
+             << ", args = [";
+      for (unsigned I = 0; I != Args.size(); ++I)
+        dbgs() << (I ? "," : "") << " \"" << Args[I] << "\"";
+      dbgs() << "]\n";
+    });
+    auto Result = EP.template callB<orcrpctpc::RunMain>(MainFnAddr, Args);
+    DEBUG_WITH_TYPE("orc", {
+      dbgs() << "  call to " << formatv("{0:x16}", MainFnAddr);
+      if (Result)
+        dbgs() << " returned result " << *Result << "\n";
+      else
+        dbgs() << " failed\n";
+    });
+    return Result;
+  }
+
+  Expected<tpctypes::WrapperFunctionResult>
+  runWrapper(JITTargetAddress WrapperFnAddr,
+             ArrayRef<uint8_t> ArgBuffer) override {
+    DEBUG_WITH_TYPE("orc", {
+      dbgs() << "Running as wrapper function "
+             << formatv("{0:x16}", WrapperFnAddr) << " with "
+             << formatv("{0:x16}", ArgBuffer.size()) << " argument buffer\n";
+    });
+    auto Result =
+        EP.template callB<orcrpctpc::RunWrapper>(WrapperFnAddr, ArgBuffer);
+    // dbgs() << "Returned from runWrapper...\n";
+    return Result;
+  }
+
+  Error closeConnection(OnCloseConnectionFunction OnCloseConnection) {
+    DEBUG_WITH_TYPE("orc", dbgs() << "Closing connection to remote\n");
+    return EP.template callAsync<orcrpctpc::CloseConnection>(
+        std::move(OnCloseConnection));
+  }
+
+  Error closeConnectionAndWait() {
+    std::promise<MSVCPError> P;
+    auto F = P.get_future();
+    if (auto Err = closeConnection([&](Error Err2) -> Error {
+          P.set_value(std::move(Err2));
+          return Error::success();
+        })) {
+      EP.abandonAllPendingResponses();
+      return joinErrors(std::move(Err), F.get());
+    }
+    return F.get();
+  }
+
+protected:
+  /// Subclasses must call this during construction to initialize the
+  /// TargetTriple and PageSize members.
+  Error initializeORCRPCTPCBase() {
+    if (auto TripleOrErr = EP.template callB<orcrpctpc::GetTargetTriple>())
+      TargetTriple = Triple(*TripleOrErr);
+    else
+      return TripleOrErr.takeError();
+
+    if (auto PageSizeOrErr = EP.template callB<orcrpctpc::GetPageSize>())
+      PageSize = *PageSizeOrErr;
+    else
+      return PageSizeOrErr.takeError();
+
+    return Error::success();
+  }
+
+private:
+  ErrorReporter ReportError;
+  RPCEndpointT &EP;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_ORCRPCTARGETPROCESSCONTROL_H