clover: Add support for compiler flags
Reviewed-by: Francisco Jerez <currojerez@riseup.net>
This commit is contained in:
parent
7f71efcf7a
commit
c68babfc3c
|
@ -142,15 +142,18 @@ clBuildProgram(cl_program prog, cl_uint count, const cl_device_id *devs,
|
|||
(!pfn_notify && user_data))
|
||||
throw error(CL_INVALID_VALUE);
|
||||
|
||||
if (!opts)
|
||||
opts = "";
|
||||
|
||||
if (devs) {
|
||||
if (any_of([&](const cl_device_id dev) {
|
||||
return !prog->ctx.has_device(dev);
|
||||
}, devs, devs + count))
|
||||
throw error(CL_INVALID_DEVICE);
|
||||
|
||||
prog->build({ devs, devs + count });
|
||||
prog->build({ devs, devs + count }, opts);
|
||||
} else {
|
||||
prog->build(prog->ctx.devs);
|
||||
prog->build(prog->ctx.devs, opts);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
|
|
@ -44,9 +44,19 @@ namespace clover {
|
|||
compat::vector<char> log;
|
||||
};
|
||||
|
||||
class invalid_option_error {
|
||||
public:
|
||||
invalid_option_error() {
|
||||
}
|
||||
|
||||
virtual ~invalid_option_error() {
|
||||
}
|
||||
};
|
||||
|
||||
module compile_program_llvm(const compat::string &source,
|
||||
enum pipe_shader_ir ir,
|
||||
const compat::string &target);
|
||||
const compat::string &target,
|
||||
const compat::string &opts);
|
||||
|
||||
module compile_program_tgsi(const compat::string &source);
|
||||
}
|
||||
|
|
|
@ -41,21 +41,27 @@ _cl_program::_cl_program(clover::context &ctx,
|
|||
}
|
||||
|
||||
void
|
||||
_cl_program::build(const std::vector<clover::device *> &devs) {
|
||||
_cl_program::build(const std::vector<clover::device *> &devs,
|
||||
const char *opts) {
|
||||
|
||||
for (auto dev : devs) {
|
||||
__binaries.erase(dev);
|
||||
__logs.erase(dev);
|
||||
__opts.erase(dev);
|
||||
|
||||
__opts.insert({ dev, opts });
|
||||
try {
|
||||
auto module = (dev->ir_format() == PIPE_SHADER_IR_TGSI ?
|
||||
compile_program_tgsi(__source) :
|
||||
compile_program_llvm(__source, dev->ir_format(),
|
||||
dev->ir_target()));
|
||||
dev->ir_target(), build_opts(dev)));
|
||||
__binaries.insert({ dev, module });
|
||||
|
||||
} catch (build_error &e) {
|
||||
__logs.insert({ dev, e.what() });
|
||||
throw error(CL_BUILD_PROGRAM_FAILURE);
|
||||
} catch (invalid_option_error &e) {
|
||||
throw error(CL_INVALID_BUILD_OPTIONS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +83,7 @@ _cl_program::build_status(clover::device *dev) const {
|
|||
|
||||
std::string
|
||||
_cl_program::build_opts(clover::device *dev) const {
|
||||
return {};
|
||||
return __opts.count(dev) ? __opts.find(dev)->second : "";
|
||||
}
|
||||
|
||||
std::string
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
const std::vector<clover::device *> &devs,
|
||||
const std::vector<clover::module> &binaries);
|
||||
|
||||
void build(const std::vector<clover::device *> &devs);
|
||||
void build(const std::vector<clover::device *> &devs, const char *opts);
|
||||
|
||||
const std::string &source() const;
|
||||
const std::map<clover::device *, clover::module> &binaries() const;
|
||||
|
@ -55,6 +55,7 @@ public:
|
|||
private:
|
||||
std::map<clover::device *, clover::module> __binaries;
|
||||
std::map<clover::device *, std::string> __logs;
|
||||
std::map<clover::device *, std::string> __opts;
|
||||
std::string __source;
|
||||
};
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "core/compiler.hpp"
|
||||
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
#include <clang/Frontend/TextDiagnosticBuffer.h>
|
||||
#include <clang/Frontend/TextDiagnosticPrinter.h>
|
||||
#include <clang/CodeGen/CodeGenAction.h>
|
||||
#include <llvm/Bitcode/BitstreamWriter.h>
|
||||
|
@ -51,6 +52,7 @@
|
|||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
|
||||
using namespace clover;
|
||||
|
||||
|
@ -98,15 +100,49 @@ namespace {
|
|||
|
||||
llvm::Module *
|
||||
compile(const std::string &source, const std::string &name,
|
||||
const std::string &triple) {
|
||||
const std::string &triple, const std::string &opts) {
|
||||
|
||||
clang::CompilerInstance c;
|
||||
clang::CompilerInvocation invocation;
|
||||
clang::EmitLLVMOnlyAction act(&llvm::getGlobalContext());
|
||||
std::string log;
|
||||
llvm::raw_string_ostream s_log(log);
|
||||
|
||||
c.getFrontendOpts().Inputs.push_back(
|
||||
clang::FrontendInputFile(name, clang::IK_OpenCL));
|
||||
// Parse the compiler options:
|
||||
std::vector<std::string> opts_array;
|
||||
std::istringstream ss(opts);
|
||||
|
||||
while (!ss.eof()) {
|
||||
std::string opt;
|
||||
getline(ss, opt, ' ');
|
||||
opts_array.push_back(opt);
|
||||
}
|
||||
|
||||
opts_array.push_back(name);
|
||||
|
||||
std::vector<const char *> opts_carray;
|
||||
for (unsigned i = 0; i < opts_array.size(); i++) {
|
||||
opts_carray.push_back(opts_array.at(i).c_str());
|
||||
}
|
||||
|
||||
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID;
|
||||
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts;
|
||||
clang::TextDiagnosticBuffer *DiagsBuffer;
|
||||
|
||||
DiagID = new clang::DiagnosticIDs();
|
||||
DiagOpts = new clang::DiagnosticOptions();
|
||||
DiagsBuffer = new clang::TextDiagnosticBuffer();
|
||||
|
||||
clang::DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
|
||||
bool Success;
|
||||
|
||||
Success = clang::CompilerInvocation::CreateFromArgs(c.getInvocation(),
|
||||
opts_carray.data(),
|
||||
opts_carray.data() + opts_carray.size(),
|
||||
Diags);
|
||||
if (!Success) {
|
||||
throw invalid_option_error();
|
||||
}
|
||||
c.getFrontendOpts().ProgramAction = clang::frontend::EmitLLVMOnly;
|
||||
c.getHeaderSearchOpts().UseBuiltinIncludes = true;
|
||||
c.getHeaderSearchOpts().UseStandardSystemIncludes = true;
|
||||
|
@ -271,11 +307,14 @@ namespace {
|
|||
module
|
||||
clover::compile_program_llvm(const compat::string &source,
|
||||
enum pipe_shader_ir ir,
|
||||
const compat::string &triple) {
|
||||
const compat::string &triple,
|
||||
const compat::string &opts) {
|
||||
|
||||
std::vector<llvm::Function *> kernels;
|
||||
|
||||
llvm::Module *mod = compile(source, "cl_input", triple);
|
||||
// The input file name must have the .cl extension in order for the
|
||||
// CompilerInvocation class to recognize it as an OpenCL source file.
|
||||
llvm::Module *mod = compile(source, "input.cl", triple, opts);
|
||||
|
||||
find_kernels(mod, kernels);
|
||||
|
||||
|
|
Loading…
Reference in New Issue