https://github.com/halide/Halide
Tip revision: 4f7073f55a723cd963832f9b96491c86cd35e14e authored by Andrew Adams on 27 January 2016, 23:39:08 UTC
Forbid bounds queries on buffers whose bounds are used in the algorithm
Forbid bounds queries on buffers whose bounds are used in the algorithm
Tip revision: 4f7073f
LLVM_Output.cpp
#include "LLVM_Headers.h"
#include "LLVM_Output.h"
#include "CodeGen_LLVM.h"
#include "CodeGen_C.h"
#include <iostream>
#include <fstream>
namespace Halide {
llvm::raw_fd_ostream *new_raw_fd_ostream(const std::string &filename) {
std::string error_string;
#if LLVM_VERSION < 35
llvm::raw_fd_ostream *raw_out = new llvm::raw_fd_ostream(filename.c_str(), error_string);
#elif LLVM_VERSION == 35
llvm::raw_fd_ostream *raw_out = new llvm::raw_fd_ostream(filename.c_str(), error_string, llvm::sys::fs::F_None);
#else // llvm 3.6
std::error_code err;
llvm::raw_fd_ostream *raw_out = new llvm::raw_fd_ostream(filename.c_str(), err, llvm::sys::fs::F_None);
if (err) error_string = err.message();
#endif
internal_assert(error_string.empty())
<< "Error opening output " << filename << ": " << error_string << "\n";
return raw_out;
}
namespace Internal {
bool get_md_bool(LLVMMDNodeArgumentType value, bool &result) {
#if LLVM_VERSION < 36 || defined(WITH_NATIVE_CLIENT)
llvm::ConstantInt *c = llvm::cast<llvm::ConstantInt>(value);
#else
llvm::ConstantAsMetadata *cam = llvm::cast<llvm::ConstantAsMetadata>(value);
llvm::ConstantInt *c = llvm::cast<llvm::ConstantInt>(cam->getValue());
#endif
if (c) {
result = !c->isZero();
return true;
}
return false;
}
bool get_md_string(LLVMMDNodeArgumentType value, std::string &result) {
#if LLVM_VERSION < 36
if (llvm::dyn_cast<llvm::ConstantAggregateZero>(value)) {
result = "";
return true;
}
llvm::ConstantDataArray *c = llvm::cast<llvm::ConstantDataArray>(value);
if (c) {
result = c->getAsCString();
return true;
}
#else
llvm::MDString *c = llvm::dyn_cast<llvm::MDString>(value);
if (c) {
result = c->getString();
return true;
}
#endif
return false;
}
}
void get_target_options(const llvm::Module &module, llvm::TargetOptions &options, std::string &mcpu, std::string &mattrs) {
bool use_soft_float_abi = false;
Internal::get_md_bool(module.getModuleFlag("halide_use_soft_float_abi"), use_soft_float_abi);
Internal::get_md_string(module.getModuleFlag("halide_mcpu"), mcpu);
Internal::get_md_string(module.getModuleFlag("halide_mattrs"), mattrs);
options = llvm::TargetOptions();
options.LessPreciseFPMADOption = true;
options.AllowFPOpFusion = llvm::FPOpFusion::Fast;
options.UnsafeFPMath = true;
options.NoInfsFPMath = true;
options.NoNaNsFPMath = true;
options.HonorSignDependentRoundingFPMathOption = false;
#if LLVM_VERSION < 37
options.NoFramePointerElim = false;
options.UseSoftFloat = false;
#endif
options.NoZerosInBSS = false;
options.GuaranteedTailCallOpt = false;
#if LLVM_VERSION < 37
options.DisableTailCalls = false;
#endif
options.StackAlignmentOverride = 0;
#if LLVM_VERSION < 37
options.TrapFuncName = "";
#endif
options.PositionIndependentExecutable = true;
options.FunctionSections = true;
#ifdef WITH_NATIVE_CLIENT
options.UseInitArray = true;
#else
options.UseInitArray = false;
#endif
options.FloatABIType =
use_soft_float_abi ? llvm::FloatABI::Soft : llvm::FloatABI::Hard;
}
void clone_target_options(const llvm::Module &from, llvm::Module &to) {
to.setTargetTriple(from.getTargetTriple());
llvm::LLVMContext &context = to.getContext();
bool use_soft_float_abi = false;
if (Internal::get_md_bool(from.getModuleFlag("halide_use_soft_float_abi"), use_soft_float_abi))
to.addModuleFlag(llvm::Module::Warning, "halide_use_soft_float_abi", use_soft_float_abi ? 1 : 0);
std::string mcpu;
if (Internal::get_md_string(from.getModuleFlag("halide_mcpu"), mcpu)) {
#if LLVM_VERSION < 36
to.addModuleFlag(llvm::Module::Warning, "halide_mcpu", llvm::ConstantDataArray::getString(context, mcpu));
#else
to.addModuleFlag(llvm::Module::Warning, "halide_mcpu", llvm::MDString::get(context, mcpu));
#endif
}
std::string mattrs;
if (Internal::get_md_string(from.getModuleFlag("halide_mattrs"), mattrs)) {
#if LLVM_VERSION < 36
to.addModuleFlag(llvm::Module::Warning, "halide_mattrs", llvm::ConstantDataArray::getString(context, mattrs));
#else
to.addModuleFlag(llvm::Module::Warning, "halide_mattrs", llvm::MDString::get(context, mattrs));
#endif
}
}
llvm::TargetMachine *get_target_machine(const llvm::Module &module) {
std::string error_string;
const llvm::Target *target = llvm::TargetRegistry::lookupTarget(module.getTargetTriple(), error_string);
if (!target) {
std::cout << error_string << std::endl;
llvm::TargetRegistry::printRegisteredTargetsForVersion();
}
internal_assert(target) << "Could not create target for " << module.getTargetTriple() << "\n";
llvm::TargetOptions options;
std::string mcpu = "";
std::string mattrs = "";
get_target_options(module, options, mcpu, mattrs);
return target->createTargetMachine(module.getTargetTriple(),
mcpu, mattrs,
options,
llvm::Reloc::PIC_,
llvm::CodeModel::Default,
llvm::CodeGenOpt::Aggressive);
}
#if LLVM_VERSION < 37
void emit_file_legacy(llvm::Module &module, const std::string &filename, llvm::TargetMachine::CodeGenFileType file_type) {
Internal::debug(1) << "emit_file_legacy.Compiling to native code...\n";
Internal::debug(2) << "Target triple: " << module.getTargetTriple() << "\n";
// Get the target specific parser.
llvm::TargetMachine *target_machine = get_target_machine(module);
internal_assert(target_machine) << "Could not allocate target machine!\n";
// Build up all of the passes that we want to do to the module.
llvm::PassManager pass_manager;
// Add an appropriate TargetLibraryInfo pass for the module's triple.
pass_manager.add(new llvm::TargetLibraryInfo(llvm::Triple(module.getTargetTriple())));
#if LLVM_VERSION < 33
pass_manager.add(new llvm::TargetTransformInfo(target_machine->getScalarTargetTransformInfo(),
target_machine->getVectorTargetTransformInfo()));
#else
target_machine->addAnalysisPasses(pass_manager);
#endif
#if LLVM_VERSION < 35
llvm::DataLayout *layout = new llvm::DataLayout(module.get());
Internal::debug(2) << "Data layout: " << layout->getStringRepresentation();
pass_manager.add(layout);
#endif
// Make sure things marked as always-inline get inlined
pass_manager.add(llvm::createAlwaysInlinerPass());
// Override default to generate verbose assembly.
target_machine->setAsmVerbosityDefault(true);
llvm::raw_fd_ostream *raw_out = new_raw_fd_ostream(filename);
llvm::formatted_raw_ostream *out = new llvm::formatted_raw_ostream(*raw_out);
// Ask the target to add backend passes as necessary.
target_machine->addPassesToEmitFile(pass_manager, *out, file_type);
pass_manager.run(module);
delete out;
delete raw_out;
delete target_machine;
}
#endif
void emit_file(llvm::Module &module, const std::string &filename, llvm::TargetMachine::CodeGenFileType file_type) {
#if LLVM_VERSION < 37
emit_file_legacy(module, filename, file_type);
#else
Internal::debug(1) << "emit_file.Compiling to native code...\n";
Internal::debug(2) << "Target triple: " << module.getTargetTriple() << "\n";
// Get the target specific parser.
llvm::TargetMachine *target_machine = get_target_machine(module);
internal_assert(target_machine) << "Could not allocate target machine!\n";
#if LLVM_VERSION == 37
llvm::DataLayout target_data_layout(*(target_machine->getDataLayout()));
#else
llvm::DataLayout target_data_layout(target_machine->createDataLayout());
#endif
if (!(target_data_layout == module.getDataLayout())) {
internal_error << "Warning: module's data layout does not match target machine's\n"
<< target_data_layout.getStringRepresentation() << "\n"
<< module.getDataLayout().getStringRepresentation() << "\n";
}
std::unique_ptr<llvm::raw_fd_ostream> out(new_raw_fd_ostream(filename));
// Build up all of the passes that we want to do to the module.
llvm::legacy::PassManager pass_manager;
pass_manager.add(new llvm::TargetLibraryInfoWrapperPass(llvm::Triple(module.getTargetTriple())));
// Make sure things marked as always-inline get inlined
pass_manager.add(llvm::createAlwaysInlinerPass());
// Override default to generate verbose assembly.
target_machine->Options.MCOptions.AsmVerbose = true;
// Ask the target to add backend passes as necessary.
target_machine->addPassesToEmitFile(pass_manager, *out, file_type);
pass_manager.run(module);
delete target_machine;
#endif
}
std::unique_ptr<llvm::Module> compile_module_to_llvm_module(const Module &module, llvm::LLVMContext &context) {
return codegen_llvm(module, context);
}
void compile_llvm_module_to_object(llvm::Module &module, const std::string &filename) {
emit_file(module, filename, llvm::TargetMachine::CGFT_ObjectFile);
}
void compile_llvm_module_to_assembly(llvm::Module &module, const std::string &filename) {
emit_file(module, filename, llvm::TargetMachine::CGFT_AssemblyFile);
}
void compile_llvm_module_to_native(llvm::Module &module,
const std::string &object_filename,
const std::string &assembly_filename) {
emit_file(module, object_filename, llvm::TargetMachine::CGFT_ObjectFile);
emit_file(module, assembly_filename, llvm::TargetMachine::CGFT_AssemblyFile);
}
void compile_llvm_module_to_llvm_bitcode(llvm::Module &module, const std::string &filename) {
llvm::raw_fd_ostream *file = new_raw_fd_ostream(filename);
WriteBitcodeToFile(&module, *file);
delete file;
}
void compile_llvm_module_to_llvm_assembly(llvm::Module &module, const std::string &filename) {
llvm::raw_fd_ostream *file = new_raw_fd_ostream(filename);
module.print(*file, NULL);
delete file;
}
} // namespace Halide