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