@@ -6744,7 +6744,6 @@ bool LLVMToSPIRVBase::joinFPContract(Function *F, FPContract C) {
67446744 }
67456745 llvm_unreachable (" Unhandled FPContract value." );
67466746}
6747-
67486747} // namespace SPIRV
67496748
67506749char LLVMToSPIRVLegacy::ID = 0 ;
@@ -6790,8 +6789,123 @@ bool isValidLLVMModule(Module *M, SPIRVErrorLog &ErrorLog) {
67906789 return true ;
67916790}
67926791
6792+ #if defined(LLVM_SPIRV_BACKEND_TARGET_PRESENT)
6793+ namespace llvm {
6794+ extern " C" bool
6795+ SPIRVTranslateModule (Module *M, std::string &SpirvObj, std::string &ErrMsg,
6796+ const std::vector<std::string> &AllowExtNames,
6797+ const std::vector<std::string> &Opts);
6798+ } // namespace llvm
6799+ #if defined(_SPIRV_SUPPORT_TEXT_FMT)
6800+ namespace SPIRV {
6801+ bool convertSpirv (std::istream &IS, std::ostream &OS, std::string &ErrMsg,
6802+ bool FromText, bool ToText);
6803+ } // namespace SPIRV
6804+ #endif // _SPIRV_SUPPORT_TEXT_FMT
6805+ #endif // LLVM_SPIRV_BACKEND_TARGET_PRESENT
6806+
67936807namespace {
67946808
6809+ #if defined(LLVM_SPIRV_BACKEND_TARGET_PRESENT)
6810+ static inline Triple::SubArchType spirvVersionToSubArch (VersionNumber VN) {
6811+ switch (VN) {
6812+ case VersionNumber::SPIRV_1_0:
6813+ return Triple::SPIRVSubArch_v10;
6814+ case VersionNumber::SPIRV_1_1:
6815+ return Triple::SPIRVSubArch_v11;
6816+ case VersionNumber::SPIRV_1_2:
6817+ return Triple::SPIRVSubArch_v12;
6818+ case VersionNumber::SPIRV_1_3:
6819+ return Triple::SPIRVSubArch_v13;
6820+ case VersionNumber::SPIRV_1_4:
6821+ return Triple::SPIRVSubArch_v14;
6822+ case VersionNumber::SPIRV_1_5:
6823+ return Triple::SPIRVSubArch_v15;
6824+ case VersionNumber::SPIRV_1_6:
6825+ return Triple::SPIRVSubArch_v16;
6826+ }
6827+ return Triple::NoSubArch;
6828+ }
6829+
6830+ bool runSpirvBackend (Module *M, std::string &Result, std::string &ErrMsg,
6831+ const SPIRV::TranslatorOpts &TranslatorOpts) {
6832+ // A list of known extensions supported by SPIR-V Backend: it's to be updated
6833+ // each time when SPIR-V Backend introduces support for a new extension.
6834+ static const std::set<ExtensionID> ImplementedBySpirvBE{
6835+ SPIRV::ExtensionID::SPV_EXT_shader_atomic_float_add,
6836+ SPIRV::ExtensionID::SPV_EXT_shader_atomic_float16_add,
6837+ SPIRV::ExtensionID::SPV_EXT_shader_atomic_float_min_max,
6838+ SPIRV::ExtensionID::SPV_INTEL_arbitrary_precision_integers,
6839+ SPIRV::ExtensionID::SPV_INTEL_cache_controls,
6840+ SPIRV::ExtensionID::SPV_INTEL_global_variable_fpga_decorations,
6841+ SPIRV::ExtensionID::SPV_INTEL_global_variable_host_access,
6842+ SPIRV::ExtensionID::SPV_INTEL_optnone,
6843+ SPIRV::ExtensionID::SPV_INTEL_usm_storage_classes,
6844+ SPIRV::ExtensionID::SPV_INTEL_subgroups,
6845+ SPIRV::ExtensionID::SPV_KHR_uniform_group_instructions,
6846+ SPIRV::ExtensionID::SPV_KHR_no_integer_wrap_decoration,
6847+ SPIRV::ExtensionID::SPV_KHR_float_controls,
6848+ SPIRV::ExtensionID::SPV_KHR_expect_assume,
6849+ SPIRV::ExtensionID::SPV_KHR_bit_instructions,
6850+ SPIRV::ExtensionID::SPV_KHR_linkonce_odr,
6851+ SPIRV::ExtensionID::SPV_INTEL_inline_assembly,
6852+ SPIRV::ExtensionID::SPV_INTEL_bfloat16_conversion,
6853+ SPIRV::ExtensionID::SPV_KHR_subgroup_rotate,
6854+ SPIRV::ExtensionID::SPV_INTEL_variable_length_array,
6855+ SPIRV::ExtensionID::SPV_INTEL_function_pointers,
6856+ SPIRV::ExtensionID::SPV_KHR_shader_clock,
6857+ SPIRV::ExtensionID::SPV_KHR_cooperative_matrix,
6858+ SPIRV::ExtensionID::SPV_KHR_non_semantic_info};
6859+ // The fallback for the Triple value.
6860+ static const std::string DefaultTriple = " spirv64-unknown-unknown" ;
6861+ // SPIR-V backend uses the following command line options to conform with
6862+ // Translator's way to generate SPIR-V or with requirements of the Compute
6863+ // flavor of SPIR-V. This list is subject to changes and may become empty
6864+ // eventually.
6865+ static const std::vector<std::string> Opts{" --avoid-spirv-capabilities" ,
6866+ " Shader" ,
6867+ " --translator-compatibility-mode" };
6868+
6869+ std::function<bool (SPIRV::ExtensionID)> Filter =
6870+ [](SPIRV::ExtensionID Ext) -> bool {
6871+ return ImplementedBySpirvBE.find (Ext) != ImplementedBySpirvBE.end ();
6872+ };
6873+ const std::vector<std::string> AllowExtNames =
6874+ TranslatorOpts.getAllowedSPIRVExtensionNames (Filter);
6875+
6876+ // Correct the Triple value if needed
6877+ Triple TargetTriple (M->getTargetTriple ());
6878+ if (TargetTriple.isSPIR ()) {
6879+ TargetTriple.setArch (TargetTriple.getArch () == Triple::spir64
6880+ ? Triple::spirv64
6881+ : Triple::spirv32,
6882+ TargetTriple.getSubArch ());
6883+ M->setTargetTriple (TargetTriple.str ());
6884+ // We need to reset Data Layout to conform with the TargetMachine
6885+ M->setDataLayout (" " );
6886+ }
6887+ if (TranslatorOpts.getMaxVersion () != VersionNumber::MaximumVersion) {
6888+ if (TargetTriple.getTriple ().empty ())
6889+ TargetTriple.setTriple (DefaultTriple);
6890+ TargetTriple.setArch (TargetTriple.getArch (),
6891+ spirvVersionToSubArch (TranslatorOpts.getMaxVersion ()));
6892+ M->setTargetTriple (TargetTriple.str ());
6893+ }
6894+
6895+ // Translate the Module into SPIR-V
6896+ return llvm::SPIRVTranslateModule (M, Result, ErrMsg, AllowExtNames, Opts);
6897+ }
6898+
6899+ bool runSpirvBackend (Module *M, std::ostream *OS, std::string &ErrMsg,
6900+ const SPIRV::TranslatorOpts &TranslatorOpts) {
6901+ std::string Result;
6902+ bool Status = runSpirvBackend (M, Result, ErrMsg, TranslatorOpts);
6903+ if (Status && OS)
6904+ *OS << Result;
6905+ return Status;
6906+ }
6907+ #endif // LLVM_SPIRV_BACKEND_TARGET_PRESENT
6908+
67956909VersionNumber getVersionFromTriple (const Triple &TT, SPIRVErrorLog &ErrorLog) {
67966910 switch (TT.getSubArch ()) {
67976911 case Triple::SPIRVSubArch_v10:
@@ -6885,6 +6999,28 @@ bool llvm::writeSpirv(Module *M, std::ostream &OS, std::string &ErrMsg) {
68856999
68867000bool llvm::writeSpirv (Module *M, const SPIRV::TranslatorOpts &Opts,
68877001 std::ostream &OS, std::string &ErrMsg) {
7002+ #if defined(LLVM_SPIRV_BACKEND_TARGET_PRESENT)
7003+ // Check if a user asks to convert LLVM to SPIR-V using the LLVM SPIR-V
7004+ // Backend target
7005+ if (Opts.getUseLLVMTarget ()) {
7006+ #if !defined(_SPIRV_SUPPORT_TEXT_FMT)
7007+ return runSpirvBackend (M, &OS, ErrMsg, Opts);
7008+ #else
7009+ if (!SPIRVUseTextFormat)
7010+ return runSpirvBackend (M, &OS, ErrMsg, Opts);
7011+
7012+ // SPIR-V Backend always returns a binary: let's use temporary buffers to
7013+ // store the binary representation and convert it later into Translator's
7014+ // textual representation
7015+ std::string BinResult;
7016+ if (!runSpirvBackend (M, BinResult, ErrMsg, Opts))
7017+ return false ;
7018+ std::istringstream IS (BinResult);
7019+ return SPIRV::convertSpirv (IS, OS, ErrMsg, false /* FromText*/ ,
7020+ true /* ToText*/ );
7021+ #endif // _SPIRV_SUPPORT_TEXT_FMT
7022+ }
7023+ #endif // LLVM_SPIRV_BACKEND_TARGET_PRESENT
68887024 return runSpirvWriterPasses (M, &OS, ErrMsg, Opts);
68897025}
68907026
0 commit comments