clc: add support for the native spir-v backend

This allows us to easily test if the LLVM SPIR-V backend is viable to
replace the translator.

Signed-off-by: Karol Herbst <kherbst@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26955>
This commit is contained in:
Karol Herbst 2024-01-09 19:49:47 +01:00 committed by Marge Bot
parent 22fa315ee0
commit 75ff6ca470
3 changed files with 47 additions and 0 deletions

View file

@ -78,6 +78,7 @@ struct clc_compile_args {
/* SPIRV version to target. */
enum clc_spirv_version spirv_version;
struct clc_optional_features features;
bool use_llvm_spirv_target;
/* Allowed extensions SPIRV extensions the OpenCL->SPIRV translation can
* enable. A pointer to a NULL terminated array of strings, allow any

View file

@ -30,8 +30,11 @@
#include <llvm/ADT/ArrayRef.h>
#include <llvm/IR/DiagnosticPrinter.h>
#include <llvm/IR/DiagnosticInfo.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Type.h>
#include <llvm/MC/TargetRegistry.h>
#include <llvm/Target/TargetMachine.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Bitcode/BitcodeWriter.h>
#include <llvm/Bitcode/BitcodeReader.h>
@ -74,9 +77,11 @@ constexpr spv_target_env spirv_target = SPV_ENV_UNIVERSAL_1_5;
constexpr SPIRV::VersionNumber invalid_spirv_trans_version = static_cast<SPIRV::VersionNumber>(0);
using ::llvm::Function;
using ::llvm::legacy::PassManager;
using ::llvm::LLVMContext;
using ::llvm::Module;
using ::llvm::raw_string_ostream;
using ::llvm::TargetRegistry;
using ::clang::driver::Driver;
static void
@ -1052,6 +1057,46 @@ llvm_mod_to_spirv(std::unique_ptr<::llvm::Module> mod,
spirv_opts.setPreserveOCLKernelArgTypeMetadataThroughString(true);
#endif
#if LLVM_VERSION_MAJOR >= 17
if (args->use_llvm_spirv_target) {
const char *triple = args->address_bits == 32 ? "spirv-unknown-unknown" : "spirv64-unknown-unknown";
std::string error_msg("");
auto target = TargetRegistry::lookupTarget(triple, error_msg);
if (target) {
auto TM = target->createTargetMachine(
triple, "", "", {}, std::nullopt, std::nullopt,
#if LLVM_VERSION_MAJOR >= 18
::llvm::CodeGenOptLevel::None
#else
::llvm::CodeGenOpt::None
#endif
);
auto PM = PassManager();
::llvm::SmallVector<char> buf;
auto OS = ::llvm::raw_svector_ostream(buf);
TM->addPassesToEmitFile(
PM, OS, nullptr,
#if LLVM_VERSION_MAJOR >= 18
::llvm::CodeGenFileType::ObjectFile
#else
::llvm::CGFT_ObjectFile
#endif
);
PM.run(*mod);
out_spirv->size = buf.size_in_bytes();
out_spirv->data = malloc(out_spirv->size);
memcpy(out_spirv->data, buf.data(), out_spirv->size);
return 0;
} else {
clc_error(logger, "LLVM SPIR-V target not found.\n");
return -1;
}
}
#endif
std::ostringstream spv_stream;
if (!::llvm::writeSpirv(mod.get(), spirv_opts, spv_stream, log)) {
clc_error(logger, "%sTranslation from LLVM IR to SPIR-V failed.\n",

View file

@ -143,6 +143,7 @@ impl SPIRVBin {
num_args: c_args.len() as u32,
spirv_version: clc_spirv_version::CLC_SPIRV_VERSION_MAX,
features: features,
use_llvm_spirv_target: false,
allowed_spirv_extensions: spirv_extensions.as_ptr(),
address_bits: address_bits,
};