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