#include "llvm/CodeGen/ParallelCG.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/MemoryBufferRef.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Utils/SplitModule.h"
using namespace llvm;
static void codegen(Module *M, llvm::raw_pwrite_stream &OS,
function_ref<std::unique_ptr<TargetMachine>()> TMFactory,
CodeGenFileType FileType) {
std::unique_ptr<TargetMachine> TM = TMFactory();
assert(TM && "Failed to create target machine!");
legacy::PassManager CodeGenPasses;
if (TM->addPassesToEmitFile(CodeGenPasses, OS, nullptr, FileType))
report_fatal_error("Failed to setup codegen");
CodeGenPasses.run(*M);
}
void llvm::splitCodeGen(
Module &M, ArrayRef<llvm::raw_pwrite_stream *> OSs,
ArrayRef<llvm::raw_pwrite_stream *> BCOSs,
const std::function<std::unique_ptr<TargetMachine>()> &TMFactory,
CodeGenFileType FileType, bool PreserveLocals) {
assert(BCOSs.empty() || BCOSs.size() == OSs.size());
if (OSs.size() == 1) {
if (!BCOSs.empty())
WriteBitcodeToFile(M, *BCOSs[0]);
codegen(&M, *OSs[0], TMFactory, FileType);
return;
}
{
ThreadPool CodegenThreadPool(hardware_concurrency(OSs.size()));
int ThreadCount = 0;
SplitModule(
M, OSs.size(),
[&](std::unique_ptr<Module> MPart) {
SmallString<0> BC;
raw_svector_ostream BCOS(BC);
WriteBitcodeToFile(*MPart, BCOS);
if (!BCOSs.empty()) {
BCOSs[ThreadCount]->write(BC.begin(), BC.size());
BCOSs[ThreadCount]->flush();
}
llvm::raw_pwrite_stream *ThreadOS = OSs[ThreadCount++];
CodegenThreadPool.async(
[TMFactory, FileType, ThreadOS](const SmallString<0> &BC) {
LLVMContext Ctx;
Expected<std::unique_ptr<Module>> MOrErr = parseBitcodeFile(
MemoryBufferRef(StringRef(BC.data(), BC.size()),
"<split-module>"),
Ctx);
if (!MOrErr)
report_fatal_error("Failed to read bitcode");
std::unique_ptr<Module> MPartInCtx = std::move(MOrErr.get());
codegen(MPartInCtx.get(), *ThreadOS, TMFactory, FileType);
},
std::move(BC));
},
PreserveLocals);
}
}