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-exception
6 //
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
14 namespace llvm {
15 namespace orc {
16
cloneToContext(const ThreadSafeModule & TSM,ThreadSafeContext TSCtx,GVPredicate ShouldCloneDef,GVModifier UpdateClonedDefSource)17 ThreadSafeModule cloneToContext(const ThreadSafeModule &TSM,
18 ThreadSafeContext TSCtx,
19 GVPredicate ShouldCloneDef,
20 GVModifier UpdateClonedDefSource) {
21 assert(TSM && "Can not clone null module");
22
23 if (!ShouldCloneDef)
24 ShouldCloneDef = [](const GlobalValue &) { return true; };
25
26 // First copy the source module into a buffer.
27 std::string ModuleName;
28 SmallVector<char, 1> ClonedModuleBuffer;
29 TSM.withModuleDo([&](Module &M) {
30 ModuleName = M.getModuleIdentifier();
31 std::set<GlobalValue *> ClonedDefsInSrc;
32 ValueToValueMapTy VMap;
33 auto Tmp = CloneModule(M, VMap, [&](const GlobalValue *GV) {
34 if (ShouldCloneDef(*GV)) {
35 ClonedDefsInSrc.insert(const_cast<GlobalValue *>(GV));
36 return true;
37 }
38 return false;
39 });
40
41 if (UpdateClonedDefSource)
42 for (auto *GV : ClonedDefsInSrc)
43 UpdateClonedDefSource(*GV);
44
45 BitcodeWriter BCWriter(ClonedModuleBuffer);
46 BCWriter.writeModule(*Tmp);
47 BCWriter.writeSymtab();
48 BCWriter.writeStrtab();
49 });
50
51 MemoryBufferRef ClonedModuleBufferRef(
52 StringRef(ClonedModuleBuffer.data(), ClonedModuleBuffer.size()),
53 "cloned module buffer");
54
55 // Then parse the buffer into the new Module.
56 auto M = TSCtx.withContextDo([&](LLVMContext *Ctx) {
57 assert(Ctx && "No LLVMContext provided");
58 auto TmpM = cantFail(parseBitcodeFile(ClonedModuleBufferRef, *Ctx));
59 TmpM->setModuleIdentifier(ModuleName);
60 return TmpM;
61 });
62
63 return ThreadSafeModule(std::move(M), std::move(TSCtx));
64 }
65
cloneToNewContext(const ThreadSafeModule & TSM,GVPredicate ShouldCloneDef,GVModifier UpdateClonedDefSource)66 ThreadSafeModule cloneToNewContext(const ThreadSafeModule &TSM,
67 GVPredicate ShouldCloneDef,
68 GVModifier UpdateClonedDefSource) {
69 assert(TSM && "Can not clone null module");
70
71 ThreadSafeContext TSCtx(std::make_unique<LLVMContext>());
72 return cloneToContext(TSM, std::move(TSCtx), std::move(ShouldCloneDef),
73 std::move(UpdateClonedDefSource));
74 }
75
76 } // end namespace orc
77 } // end namespace llvm
78