111 lines · cpp
1//===-- ThreadSafeModule.cpp - Thread safe Module, Context, and Utilities -===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"10#include "llvm/Bitcode/BitcodeReader.h"11#include "llvm/Bitcode/BitcodeWriter.h"12#include "llvm/Transforms/Utils/Cloning.h"13 14namespace llvm {15namespace orc {16 17static std::pair<std::string, SmallVector<char, 1>>18serializeModule(const Module &M, GVPredicate ShouldCloneDef,19 GVModifier UpdateClonedDefSource) {20 std::string ModuleName;21 SmallVector<char, 1> ClonedModuleBuffer;22 23 ModuleName = M.getModuleIdentifier();24 std::set<GlobalValue *> ClonedDefsInSrc;25 ValueToValueMapTy VMap;26 auto Tmp = CloneModule(M, VMap, [&](const GlobalValue *GV) {27 if (ShouldCloneDef(*GV)) {28 ClonedDefsInSrc.insert(const_cast<GlobalValue *>(GV));29 return true;30 }31 return false;32 });33 34 if (UpdateClonedDefSource)35 for (auto *GV : ClonedDefsInSrc)36 UpdateClonedDefSource(*GV);37 38 BitcodeWriter BCWriter(ClonedModuleBuffer);39 BCWriter.writeModule(*Tmp);40 BCWriter.writeSymtab();41 BCWriter.writeStrtab();42 43 return {std::move(ModuleName), std::move(ClonedModuleBuffer)};44}45 46ThreadSafeModule47deserializeModule(std::string ModuleName,48 const SmallVector<char, 1> &ClonedModuleBuffer,49 ThreadSafeContext TSCtx) {50 MemoryBufferRef ClonedModuleBufferRef(51 StringRef(ClonedModuleBuffer.data(), ClonedModuleBuffer.size()),52 "cloned module buffer");53 54 // Then parse the buffer into the new Module.55 auto M = TSCtx.withContextDo([&](LLVMContext *Ctx) {56 assert(Ctx && "No LLVMContext provided");57 auto TmpM = cantFail(parseBitcodeFile(ClonedModuleBufferRef, *Ctx));58 TmpM->setModuleIdentifier(ModuleName);59 return TmpM;60 });61 62 return ThreadSafeModule(std::move(M), std::move(TSCtx));63}64 65ThreadSafeModule66cloneExternalModuleToContext(const Module &M, ThreadSafeContext TSCtx,67 GVPredicate ShouldCloneDef,68 GVModifier UpdateClonedDefSource) {69 70 if (!ShouldCloneDef)71 ShouldCloneDef = [](const GlobalValue &) { return true; };72 73 auto [ModuleName, ClonedModuleBuffer] = serializeModule(74 M, std::move(ShouldCloneDef), std::move(UpdateClonedDefSource));75 76 return deserializeModule(std::move(ModuleName), ClonedModuleBuffer,77 std::move(TSCtx));78}79 80ThreadSafeModule cloneToContext(const ThreadSafeModule &TSM,81 ThreadSafeContext TSCtx,82 GVPredicate ShouldCloneDef,83 GVModifier UpdateClonedDefSource) {84 assert(TSM && "Can not clone null module");85 86 if (!ShouldCloneDef)87 ShouldCloneDef = [](const GlobalValue &) { return true; };88 89 // First copy the source module into a buffer.90 auto [ModuleName, ClonedModuleBuffer] = TSM.withModuleDo([&](Module &M) {91 return serializeModule(M, std::move(ShouldCloneDef),92 std::move(UpdateClonedDefSource));93 });94 95 return deserializeModule(std::move(ModuleName), ClonedModuleBuffer,96 std::move(TSCtx));97}98 99ThreadSafeModule cloneToNewContext(const ThreadSafeModule &TSM,100 GVPredicate ShouldCloneDef,101 GVModifier UpdateClonedDefSource) {102 assert(TSM && "Can not clone null module");103 104 ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());105 return cloneToContext(TSM, std::move(TSCtx), std::move(ShouldCloneDef),106 std::move(UpdateClonedDefSource));107}108 109} // end namespace orc110} // end namespace llvm111