mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 06:50:11 +01:00
clover/llvm: Add functions for compiling from source to SPIR-V
Reviewed-by: Karol Herbst <kherbst@redhat.com> Reviewed-by: Francisco Jerez <currojerez@riseup.net>
This commit is contained in:
parent
975a3c6ad3
commit
2043c5f37c
3 changed files with 92 additions and 17 deletions
|
|
@ -30,6 +30,9 @@
|
||||||
#include <llvm/Support/raw_ostream.h>
|
#include <llvm/Support/raw_ostream.h>
|
||||||
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
|
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
|
||||||
#include <llvm-c/Target.h>
|
#include <llvm-c/Target.h>
|
||||||
|
#ifdef HAVE_CLOVER_SPIRV
|
||||||
|
#include <LLVMSPIRVLib/LLVMSPIRVLib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <clang/CodeGen/CodeGenAction.h>
|
#include <clang/CodeGen/CodeGenAction.h>
|
||||||
#include <clang/Lex/PreprocessorOptions.h>
|
#include <clang/Lex/PreprocessorOptions.h>
|
||||||
|
|
@ -51,6 +54,9 @@
|
||||||
#include "llvm/invocation.hpp"
|
#include "llvm/invocation.hpp"
|
||||||
#include "llvm/metadata.hpp"
|
#include "llvm/metadata.hpp"
|
||||||
#include "llvm/util.hpp"
|
#include "llvm/util.hpp"
|
||||||
|
#ifdef HAVE_CLOVER_SPIRV
|
||||||
|
#include "spirv/invocation.hpp"
|
||||||
|
#endif
|
||||||
#include "util/algorithm.hpp"
|
#include "util/algorithm.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -182,7 +188,7 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<clang::CompilerInstance>
|
std::unique_ptr<clang::CompilerInstance>
|
||||||
create_compiler_instance(const device &dev,
|
create_compiler_instance(const device &dev, const std::string& ir_target,
|
||||||
const std::vector<std::string> &opts,
|
const std::vector<std::string> &opts,
|
||||||
std::string &r_log) {
|
std::string &r_log) {
|
||||||
std::unique_ptr<clang::CompilerInstance> c { new clang::CompilerInstance };
|
std::unique_ptr<clang::CompilerInstance> c { new clang::CompilerInstance };
|
||||||
|
|
@ -196,7 +202,7 @@ namespace {
|
||||||
const std::vector<const char *> copts =
|
const std::vector<const char *> copts =
|
||||||
map(std::mem_fn(&std::string::c_str), opts);
|
map(std::mem_fn(&std::string::c_str), opts);
|
||||||
|
|
||||||
const target &target = dev.ir_target();
|
const target &target = ir_target;
|
||||||
const std::string &device_clc_version = dev.device_clc_version();
|
const std::string &device_clc_version = dev.device_clc_version();
|
||||||
|
|
||||||
if (!compat::create_compiler_invocation_from_args(
|
if (!compat::create_compiler_invocation_from_args(
|
||||||
|
|
@ -235,19 +241,29 @@ namespace {
|
||||||
compile(LLVMContext &ctx, clang::CompilerInstance &c,
|
compile(LLVMContext &ctx, clang::CompilerInstance &c,
|
||||||
const std::string &name, const std::string &source,
|
const std::string &name, const std::string &source,
|
||||||
const header_map &headers, const device &dev,
|
const header_map &headers, const device &dev,
|
||||||
const std::string &opts, std::string &r_log) {
|
const std::string &opts, bool use_libclc, std::string &r_log) {
|
||||||
c.getFrontendOpts().ProgramAction = clang::frontend::EmitLLVMOnly;
|
c.getFrontendOpts().ProgramAction = clang::frontend::EmitLLVMOnly;
|
||||||
c.getHeaderSearchOpts().UseBuiltinIncludes = true;
|
c.getHeaderSearchOpts().UseBuiltinIncludes = true;
|
||||||
c.getHeaderSearchOpts().UseStandardSystemIncludes = true;
|
c.getHeaderSearchOpts().UseStandardSystemIncludes = true;
|
||||||
c.getHeaderSearchOpts().ResourceDir = CLANG_RESOURCE_DIR;
|
c.getHeaderSearchOpts().ResourceDir = CLANG_RESOURCE_DIR;
|
||||||
|
|
||||||
// Add libclc generic search path
|
if (use_libclc) {
|
||||||
c.getHeaderSearchOpts().AddPath(LIBCLC_INCLUDEDIR,
|
// Add libclc generic search path
|
||||||
clang::frontend::Angled,
|
c.getHeaderSearchOpts().AddPath(LIBCLC_INCLUDEDIR,
|
||||||
false, false);
|
clang::frontend::Angled,
|
||||||
|
false, false);
|
||||||
|
|
||||||
// Add libclc include
|
// Add libclc include
|
||||||
c.getPreprocessorOpts().Includes.push_back("clc/clc.h");
|
c.getPreprocessorOpts().Includes.push_back("clc/clc.h");
|
||||||
|
} else {
|
||||||
|
// Add opencl-c generic search path
|
||||||
|
c.getHeaderSearchOpts().AddPath(CLANG_RESOURCE_DIR,
|
||||||
|
clang::frontend::Angled,
|
||||||
|
false, false);
|
||||||
|
|
||||||
|
// Add opencl include
|
||||||
|
c.getPreprocessorOpts().Includes.push_back("opencl-c.h");
|
||||||
|
}
|
||||||
|
|
||||||
// Add definition for the OpenCL version
|
// Add definition for the OpenCL version
|
||||||
c.getPreprocessorOpts().addMacroDef("__OPENCL_VERSION__=" +
|
c.getPreprocessorOpts().addMacroDef("__OPENCL_VERSION__=" +
|
||||||
|
|
@ -279,8 +295,9 @@ namespace {
|
||||||
// attribute will prevent Clang from creating illegal uses of
|
// attribute will prevent Clang from creating illegal uses of
|
||||||
// barrier() (e.g. Moving barrier() inside a conditional that is
|
// barrier() (e.g. Moving barrier() inside a conditional that is
|
||||||
// no executed by all threads) during its optimizaton passes.
|
// no executed by all threads) during its optimizaton passes.
|
||||||
compat::add_link_bitcode_file(c.getCodeGenOpts(),
|
if (use_libclc)
|
||||||
LIBCLC_LIBEXECDIR + dev.ir_target() + ".bc");
|
compat::add_link_bitcode_file(c.getCodeGenOpts(),
|
||||||
|
LIBCLC_LIBEXECDIR + dev.ir_target() + ".bc");
|
||||||
|
|
||||||
// Compile the code
|
// Compile the code
|
||||||
clang::EmitLLVMOnlyAction act(&ctx);
|
clang::EmitLLVMOnlyAction act(&ctx);
|
||||||
|
|
@ -301,8 +318,10 @@ clover::llvm::compile_program(const std::string &source,
|
||||||
debug::log(".cl", "// Options: " + opts + '\n' + source);
|
debug::log(".cl", "// Options: " + opts + '\n' + source);
|
||||||
|
|
||||||
auto ctx = create_context(r_log);
|
auto ctx = create_context(r_log);
|
||||||
auto c = create_compiler_instance(dev, tokenize(opts + " input.cl"), r_log);
|
auto c = create_compiler_instance(dev, dev.ir_target(),
|
||||||
auto mod = compile(*ctx, *c, "input.cl", source, headers, dev, opts, r_log);
|
tokenize(opts + " input.cl"), r_log);
|
||||||
|
auto mod = compile(*ctx, *c, "input.cl", source, headers, dev, opts, true,
|
||||||
|
r_log);
|
||||||
|
|
||||||
if (has_flag(debug::llvm))
|
if (has_flag(debug::llvm))
|
||||||
debug::log(".ll", print_module_bitcode(*mod));
|
debug::log(".ll", print_module_bitcode(*mod));
|
||||||
|
|
@ -363,14 +382,14 @@ namespace {
|
||||||
|
|
||||||
module
|
module
|
||||||
clover::llvm::link_program(const std::vector<module> &modules,
|
clover::llvm::link_program(const std::vector<module> &modules,
|
||||||
const device &dev,
|
const device &dev, const std::string &opts,
|
||||||
const std::string &opts, std::string &r_log) {
|
std::string &r_log) {
|
||||||
std::vector<std::string> options = tokenize(opts + " input.cl");
|
std::vector<std::string> options = tokenize(opts + " input.cl");
|
||||||
const bool create_library = count("-create-library", options);
|
const bool create_library = count("-create-library", options);
|
||||||
erase_if(equals("-create-library"), options);
|
erase_if(equals("-create-library"), options);
|
||||||
|
|
||||||
auto ctx = create_context(r_log);
|
auto ctx = create_context(r_log);
|
||||||
auto c = create_compiler_instance(dev, options, r_log);
|
auto c = create_compiler_instance(dev, dev.ir_target(), options, r_log);
|
||||||
auto mod = link(*ctx, *c, modules, r_log);
|
auto mod = link(*ctx, *c, modules, r_log);
|
||||||
|
|
||||||
optimize(*mod, c->getCodeGenOpts().OptimizationLevel, !create_library);
|
optimize(*mod, c->getCodeGenOpts().OptimizationLevel, !create_library);
|
||||||
|
|
@ -395,3 +414,51 @@ clover::llvm::link_program(const std::vector<module> &modules,
|
||||||
unreachable("Unsupported IR.");
|
unreachable("Unsupported IR.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_CLOVER_SPIRV
|
||||||
|
module
|
||||||
|
clover::llvm::compile_to_spirv(const std::string &source,
|
||||||
|
const header_map &headers,
|
||||||
|
const device &dev,
|
||||||
|
const std::string &opts,
|
||||||
|
std::string &r_log) {
|
||||||
|
if (has_flag(debug::clc))
|
||||||
|
debug::log(".cl", "// Options: " + opts + '\n' + source);
|
||||||
|
|
||||||
|
auto ctx = create_context(r_log);
|
||||||
|
const std::string target = dev.address_bits() == 32u ?
|
||||||
|
"-spir-unknown-unknown" :
|
||||||
|
"-spir64-unknown-unknown";
|
||||||
|
auto c = create_compiler_instance(dev, target,
|
||||||
|
tokenize(opts + " input.cl"), r_log);
|
||||||
|
auto mod = compile(*ctx, *c, "input.cl", source, headers, dev, opts, false,
|
||||||
|
r_log);
|
||||||
|
|
||||||
|
if (has_flag(debug::llvm))
|
||||||
|
debug::log(".ll", print_module_bitcode(*mod));
|
||||||
|
|
||||||
|
std::string error_msg;
|
||||||
|
if (!::llvm::regularizeLlvmForSpirv(mod.get(), error_msg)) {
|
||||||
|
r_log += "Failed to regularize LLVM IR for SPIR-V: " + error_msg + ".\n";
|
||||||
|
throw error(CL_INVALID_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
if (!::llvm::writeSpirv(mod.get(), os, error_msg)) {
|
||||||
|
r_log += "Translation from LLVM IR to SPIR-V failed: " + error_msg + ".\n";
|
||||||
|
throw error(CL_INVALID_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string osContent = os.str();
|
||||||
|
std::vector<char> binary(osContent.begin(), osContent.end());
|
||||||
|
if (binary.empty()) {
|
||||||
|
r_log += "Failed to retrieve SPIR-V binary.\n";
|
||||||
|
throw error(CL_INVALID_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_flag(debug::spirv))
|
||||||
|
debug::log(".spvasm", spirv::print_module(binary, dev.device_version()));
|
||||||
|
|
||||||
|
return spirv::compile_program(binary, dev, r_log);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,14 @@ namespace clover {
|
||||||
const device &device,
|
const device &device,
|
||||||
const std::string &opts,
|
const std::string &opts,
|
||||||
std::string &r_log);
|
std::string &r_log);
|
||||||
|
|
||||||
|
#ifdef HAVE_CLOVER_SPIRV
|
||||||
|
module compile_to_spirv(const std::string &source,
|
||||||
|
const header_map &headers,
|
||||||
|
const device &dev,
|
||||||
|
const std::string &opts,
|
||||||
|
std::string &r_log);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ libclllvm = static_library(
|
||||||
dep_llvm.version(), 'include',
|
dep_llvm.version(), 'include',
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
dependencies : [dep_llvm, dep_elf],
|
dependencies : [dep_llvm, dep_elf, dep_llvmspirvlib],
|
||||||
override_options : clover_cpp_std,
|
override_options : clover_cpp_std,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue