Module: Mesa Branch: main Commit: 75ff6ca470dcceaba317877e636968278a044ac2 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=75ff6ca470dcceaba317877e636968278a044ac2
Author: Karol Herbst <kher...@redhat.com> Date: Tue Jan 9 19:49:47 2024 +0100 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 <kher...@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26955> --- src/compiler/clc/clc.h | 1 + src/compiler/clc/clc_helpers.cpp | 45 ++++++++++++++++++++++ .../frontends/rusticl/mesa/compiler/clc/spirv.rs | 1 + 3 files changed, 47 insertions(+) diff --git a/src/compiler/clc/clc.h b/src/compiler/clc/clc.h index 9d736b16e66..f359fd16892 100644 --- a/src/compiler/clc/clc.h +++ b/src/compiler/clc/clc.h @@ -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 diff --git a/src/compiler/clc/clc_helpers.cpp b/src/compiler/clc/clc_helpers.cpp index 93186b5775a..589feddb114 100644 --- a/src/compiler/clc/clc_helpers.cpp +++ b/src/compiler/clc/clc_helpers.cpp @@ -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", diff --git a/src/gallium/frontends/rusticl/mesa/compiler/clc/spirv.rs b/src/gallium/frontends/rusticl/mesa/compiler/clc/spirv.rs index e6d8214eaa1..e0fab75afa9 100644 --- a/src/gallium/frontends/rusticl/mesa/compiler/clc/spirv.rs +++ b/src/gallium/frontends/rusticl/mesa/compiler/clc/spirv.rs @@ -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, };