clover/llvm: Clean up compile_native().
This switches compile_native() to the C++ API (which the rest of this file makes use of anyway so there is little benefit from using the C API), what should get rid of an amount of boilerplate and fix a leak of the TargetMachine object in the error path. v2: Additional fixes for LLVM 3.6. v3: Update for the latest LLVM SVN changes. Reviewed-by: Serge Martin <edb+mesa@sigluy.net> Tested-by: Jan Vesely <jan.vesely@rutgers.edu>
This commit is contained in:
parent
7bcefa5903
commit
3ce6ab068c
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include <llvm/Linker/Linker.h>
|
||||
#include <llvm/Transforms/IPO.h>
|
||||
#include <llvm/Target/TargetMachine.h>
|
||||
|
||||
#if HAVE_LLVM >= 0x0307
|
||||
#include <llvm/IR/LegacyPassManager.h>
|
||||
|
@ -45,6 +46,8 @@
|
|||
#else
|
||||
#include <llvm/PassManager.h>
|
||||
#include <llvm/Target/TargetLibraryInfo.h>
|
||||
#include <llvm/Target/TargetSubtargetInfo.h>
|
||||
#include <llvm/Support/FormattedStream.h>
|
||||
#endif
|
||||
|
||||
#include <clang/Frontend/CodeGenOptions.h>
|
||||
|
@ -109,6 +112,33 @@ namespace clover {
|
|||
map(std::mem_fn(&std::string::data), names))));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_LLVM >= 0x0307
|
||||
typedef ::llvm::raw_svector_ostream &raw_ostream_to_emit_file;
|
||||
#else
|
||||
typedef ::llvm::formatted_raw_ostream raw_ostream_to_emit_file;
|
||||
#endif
|
||||
|
||||
#if HAVE_LLVM >= 0x0307
|
||||
typedef ::llvm::DataLayout data_layout;
|
||||
#else
|
||||
typedef const ::llvm::DataLayout *data_layout;
|
||||
#endif
|
||||
|
||||
inline data_layout
|
||||
get_data_layout(::llvm::TargetMachine &tm) {
|
||||
#if HAVE_LLVM >= 0x0307
|
||||
return tm.createDataLayout();
|
||||
#else
|
||||
return tm.getSubtargetImpl()->getDataLayout();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_LLVM >= 0x0309
|
||||
const auto default_reloc_model = ::llvm::None;
|
||||
#else
|
||||
const auto default_reloc_model = ::llvm::Reloc::Default;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ using ::llvm::Function;
|
|||
using ::llvm::LLVMContext;
|
||||
using ::llvm::Module;
|
||||
using ::llvm::raw_string_ostream;
|
||||
using ::llvm::TargetMachine;
|
||||
|
||||
namespace {
|
||||
// XXX - Temporary hack to avoid breaking the build for the moment, will
|
||||
|
@ -542,80 +543,55 @@ namespace {
|
|||
return m;
|
||||
}
|
||||
|
||||
void
|
||||
emit_code(LLVMTargetMachineRef tm, LLVMModuleRef mod,
|
||||
LLVMCodeGenFileType file_type,
|
||||
LLVMMemoryBufferRef *out_buffer,
|
||||
std::vector<char>
|
||||
emit_code(::llvm::Module &mod, const target &target,
|
||||
TargetMachine::CodeGenFileType ft,
|
||||
std::string &r_log) {
|
||||
char *err_message = NULL;
|
||||
std::string err;
|
||||
auto t = ::llvm::TargetRegistry::lookupTarget(target.triple, err);
|
||||
if (!t)
|
||||
fail(r_log, compile_error(), err);
|
||||
|
||||
try {
|
||||
if (LLVMTargetMachineEmitToMemoryBuffer(tm, mod, file_type,
|
||||
&err_message, out_buffer))
|
||||
fail(r_log, compile_error(), err_message);
|
||||
std::unique_ptr<TargetMachine> tm {
|
||||
t->createTargetMachine(target.triple, target.cpu, "", {},
|
||||
compat::default_reloc_model,
|
||||
::llvm::CodeModel::Default,
|
||||
::llvm::CodeGenOpt::Default) };
|
||||
if (!tm)
|
||||
fail(r_log, compile_error(),
|
||||
"Could not create TargetMachine: " + target.triple);
|
||||
|
||||
} catch (...) {
|
||||
LLVMDisposeMessage(err_message);
|
||||
throw;
|
||||
::llvm::SmallVector<char, 1024> data;
|
||||
|
||||
{
|
||||
compat::pass_manager pm;
|
||||
::llvm::raw_svector_ostream os { data };
|
||||
compat::raw_ostream_to_emit_file fos { os };
|
||||
|
||||
mod.setDataLayout(compat::get_data_layout(*tm));
|
||||
tm->Options.MCOptions.AsmVerbose =
|
||||
(ft == TargetMachine::CGFT_AssemblyFile);
|
||||
|
||||
if (tm->addPassesToEmitFile(pm, fos, ft))
|
||||
fail(r_log, compile_error(), "TargetMachine can't emit this file");
|
||||
|
||||
pm.run(mod);
|
||||
}
|
||||
|
||||
return { data.begin(), data.end() };
|
||||
}
|
||||
|
||||
std::vector<char>
|
||||
compile_native(const llvm::Module *mod, const target &t,
|
||||
compile_native(llvm::Module *mod, const target &target,
|
||||
std::string &r_log) {
|
||||
|
||||
std::string log;
|
||||
LLVMTargetRef target;
|
||||
char *error_message;
|
||||
LLVMMemoryBufferRef out_buffer;
|
||||
unsigned buffer_size;
|
||||
const char *buffer_data;
|
||||
LLVMModuleRef mod_ref = wrap(mod);
|
||||
|
||||
try {
|
||||
if (LLVMGetTargetFromTriple(t.triple.c_str(), &target, &error_message))
|
||||
fail(r_log, compile_error(), error_message);
|
||||
|
||||
} catch (...) {
|
||||
LLVMDisposeMessage(error_message);
|
||||
throw;
|
||||
}
|
||||
|
||||
LLVMTargetMachineRef tm = LLVMCreateTargetMachine(
|
||||
target, t.triple.c_str(), t.cpu.c_str(), "",
|
||||
LLVMCodeGenLevelDefault, LLVMRelocDefault, LLVMCodeModelDefault);
|
||||
if (!tm)
|
||||
fail(r_log, compile_error(),
|
||||
"Could not create TargetMachine: " + t.triple);
|
||||
|
||||
if (has_flag(debug::native)) {
|
||||
LLVMSetTargetMachineAsmVerbosity(tm, true);
|
||||
#if HAVE_LLVM >= 0x0308
|
||||
LLVMModuleRef debug_mod = wrap(llvm::CloneModule(mod).release());
|
||||
#else
|
||||
LLVMModuleRef debug_mod = wrap(llvm::CloneModule(mod));
|
||||
#endif
|
||||
emit_code(tm, debug_mod, LLVMAssemblyFile, &out_buffer, r_log);
|
||||
buffer_size = LLVMGetBufferSize(out_buffer);
|
||||
buffer_data = LLVMGetBufferStart(out_buffer);
|
||||
debug::log(".asm", std::string(buffer_data, buffer_size));
|
||||
|
||||
LLVMSetTargetMachineAsmVerbosity(tm, false);
|
||||
LLVMDisposeMemoryBuffer(out_buffer);
|
||||
LLVMDisposeModule(debug_mod);
|
||||
std::unique_ptr<llvm::Module> cmod { CloneModule(mod) };
|
||||
debug::log(".asm", as_string(
|
||||
emit_code(*cmod, target,
|
||||
TargetMachine::CGFT_AssemblyFile, r_log)));
|
||||
}
|
||||
|
||||
emit_code(tm, mod_ref, LLVMObjectFile, &out_buffer, r_log);
|
||||
|
||||
buffer_size = LLVMGetBufferSize(out_buffer);
|
||||
buffer_data = LLVMGetBufferStart(out_buffer);
|
||||
|
||||
std::vector<char> code(buffer_data, buffer_data + buffer_size);
|
||||
|
||||
LLVMDisposeMemoryBuffer(out_buffer);
|
||||
LLVMDisposeTargetMachine(tm);
|
||||
|
||||
return code;
|
||||
return emit_code(*mod, target, TargetMachine::CGFT_ObjectFile, r_log);
|
||||
}
|
||||
|
||||
namespace elf {
|
||||
|
|
|
@ -51,6 +51,11 @@ namespace clover {
|
|||
return ss;
|
||||
}
|
||||
|
||||
inline std::string
|
||||
as_string(const std::vector<char> &v) {
|
||||
return { v.begin(), v.end() };
|
||||
}
|
||||
|
||||
struct target {
|
||||
target(const std::string &s) :
|
||||
cpu(s.begin(), s.begin() + s.find_first_of("-")),
|
||||
|
|
Loading…
Reference in New Issue