1*b5893f02SDimitry Andric //===-- ThreadSafeModule.cpp - Thread safe Module, Context, and Utilities
2*b5893f02SDimitry Andric //h-===//
3*b5893f02SDimitry Andric //
4*b5893f02SDimitry Andric //                     The LLVM Compiler Infrastructure
5*b5893f02SDimitry Andric //
6*b5893f02SDimitry Andric // This file is distributed under the University of Illinois Open Source
7*b5893f02SDimitry Andric // License. See LICENSE.TXT for details.
8*b5893f02SDimitry Andric //
9*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
10*b5893f02SDimitry Andric 
11*b5893f02SDimitry Andric #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
12*b5893f02SDimitry Andric #include "llvm/Bitcode/BitcodeReader.h"
13*b5893f02SDimitry Andric #include "llvm/Bitcode/BitcodeWriter.h"
14*b5893f02SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h"
15*b5893f02SDimitry Andric 
16*b5893f02SDimitry Andric namespace llvm {
17*b5893f02SDimitry Andric namespace orc {
18*b5893f02SDimitry Andric 
cloneToNewContext(ThreadSafeModule & TSM,GVPredicate ShouldCloneDef,GVModifier UpdateClonedDefSource)19*b5893f02SDimitry Andric ThreadSafeModule cloneToNewContext(ThreadSafeModule &TSM,
20*b5893f02SDimitry Andric                                    GVPredicate ShouldCloneDef,
21*b5893f02SDimitry Andric                                    GVModifier UpdateClonedDefSource) {
22*b5893f02SDimitry Andric   assert(TSM && "Can not clone null module");
23*b5893f02SDimitry Andric 
24*b5893f02SDimitry Andric   if (!ShouldCloneDef)
25*b5893f02SDimitry Andric     ShouldCloneDef = [](const GlobalValue &) { return true; };
26*b5893f02SDimitry Andric 
27*b5893f02SDimitry Andric   auto Lock = TSM.getContextLock();
28*b5893f02SDimitry Andric 
29*b5893f02SDimitry Andric   SmallVector<char, 1> ClonedModuleBuffer;
30*b5893f02SDimitry Andric 
31*b5893f02SDimitry Andric   {
32*b5893f02SDimitry Andric     std::set<GlobalValue *> ClonedDefsInSrc;
33*b5893f02SDimitry Andric     ValueToValueMapTy VMap;
34*b5893f02SDimitry Andric     auto Tmp = CloneModule(*TSM.getModule(), VMap, [&](const GlobalValue *GV) {
35*b5893f02SDimitry Andric       if (ShouldCloneDef(*GV)) {
36*b5893f02SDimitry Andric         ClonedDefsInSrc.insert(const_cast<GlobalValue *>(GV));
37*b5893f02SDimitry Andric         return true;
38*b5893f02SDimitry Andric       }
39*b5893f02SDimitry Andric       return false;
40*b5893f02SDimitry Andric     });
41*b5893f02SDimitry Andric 
42*b5893f02SDimitry Andric     if (UpdateClonedDefSource)
43*b5893f02SDimitry Andric       for (auto *GV : ClonedDefsInSrc)
44*b5893f02SDimitry Andric         UpdateClonedDefSource(*GV);
45*b5893f02SDimitry Andric 
46*b5893f02SDimitry Andric     BitcodeWriter BCWriter(ClonedModuleBuffer);
47*b5893f02SDimitry Andric 
48*b5893f02SDimitry Andric     BCWriter.writeModule(*Tmp);
49*b5893f02SDimitry Andric     BCWriter.writeSymtab();
50*b5893f02SDimitry Andric     BCWriter.writeStrtab();
51*b5893f02SDimitry Andric   }
52*b5893f02SDimitry Andric 
53*b5893f02SDimitry Andric   MemoryBufferRef ClonedModuleBufferRef(
54*b5893f02SDimitry Andric       StringRef(ClonedModuleBuffer.data(), ClonedModuleBuffer.size()),
55*b5893f02SDimitry Andric       "cloned module buffer");
56*b5893f02SDimitry Andric   ThreadSafeContext NewTSCtx(llvm::make_unique<LLVMContext>());
57*b5893f02SDimitry Andric 
58*b5893f02SDimitry Andric   auto ClonedModule =
59*b5893f02SDimitry Andric       cantFail(parseBitcodeFile(ClonedModuleBufferRef, *NewTSCtx.getContext()));
60*b5893f02SDimitry Andric   ClonedModule->setModuleIdentifier(TSM.getModule()->getName());
61*b5893f02SDimitry Andric   return ThreadSafeModule(std::move(ClonedModule), std::move(NewTSCtx));
62*b5893f02SDimitry Andric }
63*b5893f02SDimitry Andric 
64*b5893f02SDimitry Andric } // end namespace orc
65*b5893f02SDimitry Andric } // end namespace llvm
66