xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ThreadSafeModule.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
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 
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 
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