Most of `MemoryBuffer` interfaces expose a `RequiresNullTerminator` parameter that's being used to: * determine how to open a file (`mmap` vs `open`), * assert newly initialized buffer indeed has an implicit null terminator. This patch adds the paramater to the `SmallVectorMemoryBuffer` constructors, meaning: * null terminator can now be added to `SmallVector`s that didn't have one before, * `SmallVectors` that had a null terminator before keep it even after the move. In line with existing code, the new parameter is defaulted to `true`. This patch makes sure all calls to the `SmallVectorMemoryBuffer` constructor set it to `false` to preserve the current semantics. Reviewed By: dexonsmith Differential Revision: https://reviews.llvm.org/D115331
96 lines
2.8 KiB
C++
96 lines
2.8 KiB
C++
//===------ CompileUtils.cpp - Utilities for compiling IR in the JIT ------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/ExecutionEngine/ObjectCache.h"
|
|
#include "llvm/IR/LegacyPassManager.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/Object/ObjectFile.h"
|
|
#include "llvm/Support/Error.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
#include "llvm/Support/SmallVectorMemoryBuffer.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
|
|
#include <algorithm>
|
|
|
|
namespace llvm {
|
|
namespace orc {
|
|
|
|
IRSymbolMapper::ManglingOptions
|
|
irManglingOptionsFromTargetOptions(const TargetOptions &Opts) {
|
|
IRSymbolMapper::ManglingOptions MO;
|
|
|
|
MO.EmulatedTLS = Opts.EmulatedTLS;
|
|
|
|
return MO;
|
|
}
|
|
|
|
/// Compile a Module to an ObjectFile.
|
|
Expected<SimpleCompiler::CompileResult> SimpleCompiler::operator()(Module &M) {
|
|
CompileResult CachedObject = tryToLoadFromObjectCache(M);
|
|
if (CachedObject)
|
|
return std::move(CachedObject);
|
|
|
|
SmallVector<char, 0> ObjBufferSV;
|
|
|
|
{
|
|
raw_svector_ostream ObjStream(ObjBufferSV);
|
|
|
|
legacy::PassManager PM;
|
|
MCContext *Ctx;
|
|
if (TM.addPassesToEmitMC(PM, Ctx, ObjStream))
|
|
return make_error<StringError>("Target does not support MC emission",
|
|
inconvertibleErrorCode());
|
|
PM.run(M);
|
|
}
|
|
|
|
auto ObjBuffer = std::make_unique<SmallVectorMemoryBuffer>(
|
|
std::move(ObjBufferSV), M.getModuleIdentifier() + "-jitted-objectbuffer",
|
|
/*RequiresNullTerminator=*/false);
|
|
|
|
auto Obj = object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
|
|
|
|
if (!Obj)
|
|
return Obj.takeError();
|
|
|
|
notifyObjectCompiled(M, *ObjBuffer);
|
|
return std::move(ObjBuffer);
|
|
}
|
|
|
|
SimpleCompiler::CompileResult
|
|
SimpleCompiler::tryToLoadFromObjectCache(const Module &M) {
|
|
if (!ObjCache)
|
|
return CompileResult();
|
|
|
|
return ObjCache->getObject(&M);
|
|
}
|
|
|
|
void SimpleCompiler::notifyObjectCompiled(const Module &M,
|
|
const MemoryBuffer &ObjBuffer) {
|
|
if (ObjCache)
|
|
ObjCache->notifyObjectCompiled(&M, ObjBuffer.getMemBufferRef());
|
|
}
|
|
|
|
ConcurrentIRCompiler::ConcurrentIRCompiler(JITTargetMachineBuilder JTMB,
|
|
ObjectCache *ObjCache)
|
|
: IRCompiler(irManglingOptionsFromTargetOptions(JTMB.getOptions())),
|
|
JTMB(std::move(JTMB)), ObjCache(ObjCache) {}
|
|
|
|
Expected<std::unique_ptr<MemoryBuffer>>
|
|
ConcurrentIRCompiler::operator()(Module &M) {
|
|
auto TM = cantFail(JTMB.createTargetMachine());
|
|
SimpleCompiler C(*TM, ObjCache);
|
|
return C(M);
|
|
}
|
|
|
|
} // end namespace orc
|
|
} // end namespace llvm
|