1 //===--- SPIRVCommandLine.cpp ---- Command Line Options ---------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains definitions of classes and functions needed for 10 // processing, parsing, and using CLI options for the SPIR-V backend. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "SPIRVCommandLine.h" 15 #include "llvm/ADT/StringRef.h" 16 #include <algorithm> 17 #include <map> 18 19 #define DEBUG_TYPE "spirv-commandline" 20 21 using namespace llvm; 22 23 static const std::map<std::string, SPIRV::Extension::Extension, std::less<>> 24 SPIRVExtensionMap = { 25 {"SPV_EXT_shader_atomic_float_add", 26 SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_add}, 27 {"SPV_EXT_shader_atomic_float16_add", 28 SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float16_add}, 29 {"SPV_EXT_shader_atomic_float_min_max", 30 SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_min_max}, 31 {"SPV_EXT_arithmetic_fence", 32 SPIRV::Extension::Extension::SPV_EXT_arithmetic_fence}, 33 {"SPV_EXT_demote_to_helper_invocation", 34 SPIRV::Extension::Extension::SPV_EXT_demote_to_helper_invocation}, 35 {"SPV_INTEL_arbitrary_precision_integers", 36 SPIRV::Extension::Extension::SPV_INTEL_arbitrary_precision_integers}, 37 {"SPV_INTEL_cache_controls", 38 SPIRV::Extension::Extension::SPV_INTEL_cache_controls}, 39 {"SPV_INTEL_float_controls2", 40 SPIRV::Extension::Extension::SPV_INTEL_float_controls2}, 41 {"SPV_INTEL_global_variable_fpga_decorations", 42 SPIRV::Extension::Extension:: 43 SPV_INTEL_global_variable_fpga_decorations}, 44 {"SPV_INTEL_global_variable_host_access", 45 SPIRV::Extension::Extension::SPV_INTEL_global_variable_host_access}, 46 {"SPV_INTEL_optnone", SPIRV::Extension::Extension::SPV_INTEL_optnone}, 47 {"SPV_EXT_optnone", SPIRV::Extension::Extension::SPV_EXT_optnone}, 48 {"SPV_INTEL_usm_storage_classes", 49 SPIRV::Extension::Extension::SPV_INTEL_usm_storage_classes}, 50 {"SPV_INTEL_split_barrier", 51 SPIRV::Extension::Extension::SPV_INTEL_split_barrier}, 52 {"SPV_INTEL_subgroups", 53 SPIRV::Extension::Extension::SPV_INTEL_subgroups}, 54 {"SPV_INTEL_media_block_io", 55 SPIRV::Extension::Extension::SPV_INTEL_media_block_io}, 56 {"SPV_INTEL_joint_matrix", 57 SPIRV::Extension::Extension::SPV_INTEL_joint_matrix}, 58 {"SPV_KHR_uniform_group_instructions", 59 SPIRV::Extension::Extension::SPV_KHR_uniform_group_instructions}, 60 {"SPV_KHR_no_integer_wrap_decoration", 61 SPIRV::Extension::Extension::SPV_KHR_no_integer_wrap_decoration}, 62 {"SPV_KHR_float_controls", 63 SPIRV::Extension::Extension::SPV_KHR_float_controls}, 64 {"SPV_KHR_expect_assume", 65 SPIRV::Extension::Extension::SPV_KHR_expect_assume}, 66 {"SPV_KHR_bit_instructions", 67 SPIRV::Extension::Extension::SPV_KHR_bit_instructions}, 68 {"SPV_KHR_integer_dot_product", 69 SPIRV::Extension::Extension::SPV_KHR_integer_dot_product}, 70 {"SPV_KHR_linkonce_odr", 71 SPIRV::Extension::Extension::SPV_KHR_linkonce_odr}, 72 {"SPV_INTEL_inline_assembly", 73 SPIRV::Extension::Extension::SPV_INTEL_inline_assembly}, 74 {"SPV_INTEL_bfloat16_conversion", 75 SPIRV::Extension::Extension::SPV_INTEL_bfloat16_conversion}, 76 {"SPV_KHR_subgroup_rotate", 77 SPIRV::Extension::Extension::SPV_KHR_subgroup_rotate}, 78 {"SPV_INTEL_variable_length_array", 79 SPIRV::Extension::Extension::SPV_INTEL_variable_length_array}, 80 {"SPV_INTEL_function_pointers", 81 SPIRV::Extension::Extension::SPV_INTEL_function_pointers}, 82 {"SPV_KHR_shader_clock", 83 SPIRV::Extension::Extension::SPV_KHR_shader_clock}, 84 {"SPV_KHR_cooperative_matrix", 85 SPIRV::Extension::Extension::SPV_KHR_cooperative_matrix}, 86 {"SPV_KHR_non_semantic_info", 87 SPIRV::Extension::Extension::SPV_KHR_non_semantic_info}}; 88 89 bool SPIRVExtensionsParser::parse(cl::Option &O, llvm::StringRef ArgName, 90 llvm::StringRef ArgValue, 91 std::set<SPIRV::Extension::Extension> &Vals) { 92 llvm::SmallVector<llvm::StringRef, 10> Tokens; 93 ArgValue.split(Tokens, ",", -1, false); 94 std::sort(Tokens.begin(), Tokens.end()); 95 96 std::set<SPIRV::Extension::Extension> EnabledExtensions; 97 98 for (const auto &Token : Tokens) { 99 if (Token == "all") { 100 for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap) 101 EnabledExtensions.insert(ExtensionEnum); 102 103 continue; 104 } 105 106 if (Token.empty() || (!Token.starts_with("+") && !Token.starts_with("-"))) 107 return O.error("Invalid extension list format: " + Token.str()); 108 109 llvm::StringRef ExtensionName = Token.substr(1); 110 auto NameValuePair = SPIRVExtensionMap.find(ExtensionName); 111 112 if (NameValuePair == SPIRVExtensionMap.end()) 113 return O.error("Unknown SPIR-V extension: " + Token.str()); 114 115 if (Token.starts_with("+")) { 116 EnabledExtensions.insert(NameValuePair->second); 117 } else if (EnabledExtensions.count(NameValuePair->second)) { 118 if (std::find(Tokens.begin(), Tokens.end(), "+" + ExtensionName.str()) != 119 Tokens.end()) 120 return O.error( 121 "Extension cannot be allowed and disallowed at the same time: " + 122 ExtensionName.str()); 123 124 EnabledExtensions.erase(NameValuePair->second); 125 } 126 } 127 128 Vals = std::move(EnabledExtensions); 129 return false; 130 } 131 132 llvm::StringRef SPIRVExtensionsParser::checkExtensions( 133 const std::vector<std::string> &ExtNames, 134 std::set<SPIRV::Extension::Extension> &AllowedExtensions) { 135 for (const auto &Ext : ExtNames) { 136 if (Ext == "all") { 137 for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap) 138 AllowedExtensions.insert(ExtensionEnum); 139 break; 140 } 141 auto It = SPIRVExtensionMap.find(Ext); 142 if (It == SPIRVExtensionMap.end()) 143 return Ext; 144 AllowedExtensions.insert(It->second); 145 } 146 return StringRef(); 147 } 148