mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
59b89a3124
All these potential null pointer dereferences are reported by my static analyzer for null smart pointer dereferences, which has a different implementation from `alpha.cplusplus.SmartPtr`. The checked pointers in this patch are initialized by Target::createXXX functions. When the creator function pointer is not correctly set, a null pointer will be returned, or the creator function may originally return a null pointer. Some of them may not make sense as they may be checked before entering the function, but I fixed them all in this patch. I submit this fix because 1) similar checks are found in some other places in the LLVM codebase for the same return value of the function; and, 2) some of the pointers are dereferenced before they are checked, which may definitely trigger a null pointer dereference if the return value is nullptr. Reviewed By: tejohnson, MaskRay, jpienaar Differential Revision: https://reviews.llvm.org/D91410
101 lines
3.8 KiB
C++
101 lines
3.8 KiB
C++
//===-- ParallelCG.cpp ----------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines functions that can be used for parallel code generation.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#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/ErrorOr.h"
|
|
#include "llvm/Support/MemoryBuffer.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);
|
|
}
|
|
|
|
std::unique_ptr<Module> llvm::splitCodeGen(
|
|
std::unique_ptr<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.get(), *OSs[0], TMFactory, FileType);
|
|
return M;
|
|
}
|
|
|
|
// Create ThreadPool in nested scope so that threads will be joined
|
|
// on destruction.
|
|
{
|
|
ThreadPool CodegenThreadPool(hardware_concurrency(OSs.size()));
|
|
int ThreadCount = 0;
|
|
|
|
SplitModule(
|
|
std::move(M), OSs.size(),
|
|
[&](std::unique_ptr<Module> MPart) {
|
|
// We want to clone the module in a new context to multi-thread the
|
|
// codegen. We do it by serializing partition modules to bitcode
|
|
// (while still on the main thread, in order to avoid data races) and
|
|
// spinning up new threads which deserialize the partitions into
|
|
// separate contexts.
|
|
// FIXME: Provide a more direct way to do this in LLVM.
|
|
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++];
|
|
// Enqueue the task
|
|
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);
|
|
},
|
|
// Pass BC using std::move to ensure that it get moved rather than
|
|
// copied into the thread's context.
|
|
std::move(BC));
|
|
},
|
|
PreserveLocals);
|
|
}
|
|
|
|
return {};
|
|
}
|