263 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains definitions of classes and functions needed for10// processing, parsing, and using CLI options for the SPIR-V backend.11//12//===----------------------------------------------------------------------===//13 14#include "SPIRVCommandLine.h"15#include "MCTargetDesc/SPIRVBaseInfo.h"16#include "llvm/TargetParser/Triple.h"17#include <algorithm>18#include <map>19 20#define DEBUG_TYPE "spirv-commandline"21 22using namespace llvm;23 24static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>25 SPIRVExtensionMap = {26 {"SPV_EXT_shader_atomic_float_add",27 SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_add},28 {"SPV_EXT_shader_atomic_float16_add",29 SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float16_add},30 {"SPV_EXT_shader_atomic_float_min_max",31 SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_min_max},32 {"SPV_INTEL_16bit_atomics",33 SPIRV::Extension::Extension::SPV_INTEL_16bit_atomics},34 {"SPV_EXT_arithmetic_fence",35 SPIRV::Extension::Extension::SPV_EXT_arithmetic_fence},36 {"SPV_EXT_demote_to_helper_invocation",37 SPIRV::Extension::Extension::SPV_EXT_demote_to_helper_invocation},38 {"SPV_EXT_descriptor_indexing",39 SPIRV::Extension::Extension::SPV_EXT_descriptor_indexing},40 {"SPV_EXT_fragment_fully_covered",41 SPIRV::Extension::Extension::SPV_EXT_fragment_fully_covered},42 {"SPV_EXT_fragment_invocation_density",43 SPIRV::Extension::Extension::SPV_EXT_fragment_invocation_density},44 {"SPV_EXT_fragment_shader_interlock",45 SPIRV::Extension::Extension::SPV_EXT_fragment_shader_interlock},46 {"SPV_EXT_mesh_shader",47 SPIRV::Extension::Extension::SPV_EXT_mesh_shader},48 {"SPV_EXT_shader_stencil_export",49 SPIRV::Extension::Extension::SPV_EXT_shader_stencil_export},50 {"SPV_EXT_shader_viewport_index_layer",51 SPIRV::Extension::Extension::SPV_EXT_shader_viewport_index_layer},52 {"SPV_GOOGLE_hlsl_functionality1",53 SPIRV::Extension::Extension::SPV_GOOGLE_hlsl_functionality1},54 {"SPV_GOOGLE_user_type",55 SPIRV::Extension::Extension::SPV_GOOGLE_user_type},56 {"SPV_ALTERA_arbitrary_precision_integers",57 SPIRV::Extension::Extension::SPV_ALTERA_arbitrary_precision_integers},58 {"SPV_INTEL_cache_controls",59 SPIRV::Extension::Extension::SPV_INTEL_cache_controls},60 {"SPV_INTEL_float_controls2",61 SPIRV::Extension::Extension::SPV_INTEL_float_controls2},62 {"SPV_INTEL_global_variable_fpga_decorations",63 SPIRV::Extension::Extension::64 SPV_INTEL_global_variable_fpga_decorations},65 {"SPV_INTEL_global_variable_host_access",66 SPIRV::Extension::Extension::SPV_INTEL_global_variable_host_access},67 {"SPV_INTEL_optnone", SPIRV::Extension::Extension::SPV_INTEL_optnone},68 {"SPV_EXT_optnone", SPIRV::Extension::Extension::SPV_EXT_optnone},69 {"SPV_INTEL_usm_storage_classes",70 SPIRV::Extension::Extension::SPV_INTEL_usm_storage_classes},71 {"SPV_INTEL_split_barrier",72 SPIRV::Extension::Extension::SPV_INTEL_split_barrier},73 {"SPV_INTEL_subgroups",74 SPIRV::Extension::Extension::SPV_INTEL_subgroups},75 {"SPV_INTEL_media_block_io",76 SPIRV::Extension::Extension::SPV_INTEL_media_block_io},77 {"SPV_INTEL_memory_access_aliasing",78 SPIRV::Extension::Extension::SPV_INTEL_memory_access_aliasing},79 {"SPV_INTEL_joint_matrix",80 SPIRV::Extension::Extension::SPV_INTEL_joint_matrix},81 {"SPV_KHR_16bit_storage",82 SPIRV::Extension::Extension::SPV_KHR_16bit_storage},83 {"SPV_KHR_device_group",84 SPIRV::Extension::Extension::SPV_KHR_device_group},85 {"SPV_KHR_fragment_shading_rate",86 SPIRV::Extension::Extension::SPV_KHR_fragment_shading_rate},87 {"SPV_KHR_multiview", SPIRV::Extension::Extension::SPV_KHR_multiview},88 {"SPV_KHR_post_depth_coverage",89 SPIRV::Extension::Extension::SPV_KHR_post_depth_coverage},90 {"SPV_KHR_shader_draw_parameters",91 SPIRV::Extension::Extension::SPV_KHR_shader_draw_parameters},92 {"SPV_KHR_ray_tracing",93 SPIRV::Extension::Extension::SPV_KHR_ray_tracing},94 {"SPV_KHR_uniform_group_instructions",95 SPIRV::Extension::Extension::SPV_KHR_uniform_group_instructions},96 {"SPV_KHR_no_integer_wrap_decoration",97 SPIRV::Extension::Extension::SPV_KHR_no_integer_wrap_decoration},98 {"SPV_KHR_float_controls",99 SPIRV::Extension::Extension::SPV_KHR_float_controls},100 {"SPV_KHR_expect_assume",101 SPIRV::Extension::Extension::SPV_KHR_expect_assume},102 {"SPV_KHR_bit_instructions",103 SPIRV::Extension::Extension::SPV_KHR_bit_instructions},104 {"SPV_KHR_integer_dot_product",105 SPIRV::Extension::Extension::SPV_KHR_integer_dot_product},106 {"SPV_KHR_linkonce_odr",107 SPIRV::Extension::Extension::SPV_KHR_linkonce_odr},108 {"SPV_INTEL_inline_assembly",109 SPIRV::Extension::Extension::SPV_INTEL_inline_assembly},110 {"SPV_INTEL_bindless_images",111 SPIRV::Extension::Extension::SPV_INTEL_bindless_images},112 {"SPV_INTEL_bfloat16_arithmetic",113 SPIRV::Extension::Extension::SPV_INTEL_bfloat16_arithmetic},114 {"SPV_INTEL_bfloat16_conversion",115 SPIRV::Extension::Extension::SPV_INTEL_bfloat16_conversion},116 {"SPV_KHR_subgroup_rotate",117 SPIRV::Extension::Extension::SPV_KHR_subgroup_rotate},118 {"SPV_INTEL_variable_length_array",119 SPIRV::Extension::Extension::SPV_INTEL_variable_length_array},120 {"SPV_INTEL_function_pointers",121 SPIRV::Extension::Extension::SPV_INTEL_function_pointers},122 {"SPV_KHR_shader_clock",123 SPIRV::Extension::Extension::SPV_KHR_shader_clock},124 {"SPV_KHR_cooperative_matrix",125 SPIRV::Extension::Extension::SPV_KHR_cooperative_matrix},126 {"SPV_KHR_non_semantic_info",127 SPIRV::Extension::Extension::SPV_KHR_non_semantic_info},128 {"SPV_KHR_ray_query", SPIRV::Extension::Extension::SPV_KHR_ray_query},129 {"SPV_EXT_shader_image_int64",130 SPIRV::Extension::Extension::SPV_EXT_shader_image_int64},131 {"SPV_KHR_fragment_shader_barycentric",132 SPIRV::Extension::Extension::SPV_KHR_fragment_shader_barycentric},133 {"SPV_KHR_physical_storage_buffer",134 SPIRV::Extension::Extension::SPV_KHR_physical_storage_buffer},135 {"SPV_KHR_vulkan_memory_model",136 SPIRV::Extension::Extension::SPV_KHR_vulkan_memory_model},137 {"SPV_NV_shader_subgroup_partitioned",138 SPIRV::Extension::Extension::SPV_NV_shader_subgroup_partitioned},139 {"SPV_INTEL_long_composites",140 SPIRV::Extension::Extension::SPV_INTEL_long_composites},141 {"SPV_INTEL_fp_max_error",142 SPIRV::Extension::Extension::SPV_INTEL_fp_max_error},143 {"SPV_INTEL_subgroup_matrix_multiply_accumulate",144 SPIRV::Extension::Extension::145 SPV_INTEL_subgroup_matrix_multiply_accumulate},146 {"SPV_INTEL_ternary_bitwise_function",147 SPIRV::Extension::Extension::SPV_INTEL_ternary_bitwise_function},148 {"SPV_INTEL_2d_block_io",149 SPIRV::Extension::Extension::SPV_INTEL_2d_block_io},150 {"SPV_INTEL_int4", SPIRV::Extension::Extension::SPV_INTEL_int4},151 {"SPV_KHR_float_controls2",152 SPIRV::Extension::Extension::SPV_KHR_float_controls2},153 {"SPV_INTEL_tensor_float32_conversion",154 SPIRV::Extension::Extension::SPV_INTEL_tensor_float32_conversion},155 {"SPV_KHR_bfloat16", SPIRV::Extension::Extension::SPV_KHR_bfloat16},156 {"SPV_EXT_relaxed_printf_string_address_space",157 SPIRV::Extension::Extension::158 SPV_EXT_relaxed_printf_string_address_space},159 {"SPV_INTEL_predicated_io",160 SPIRV::Extension::Extension::SPV_INTEL_predicated_io},161 {"SPV_KHR_maximal_reconvergence",162 SPIRV::Extension::Extension::SPV_KHR_maximal_reconvergence},163 {"SPV_INTEL_kernel_attributes",164 SPIRV::Extension::Extension::SPV_INTEL_kernel_attributes},165 {"SPV_ALTERA_blocking_pipes",166 SPIRV::Extension::Extension::SPV_ALTERA_blocking_pipes},167 {"SPV_INTEL_int4", SPIRV::Extension::Extension::SPV_INTEL_int4},168 {"SPV_ALTERA_arbitrary_precision_fixed_point",169 SPIRV::Extension::Extension::170 SPV_ALTERA_arbitrary_precision_fixed_point}};171 172bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName,173 StringRef ArgValue,174 std::set<SPIRV::Extension::Extension> &Vals) {175 SmallVector<StringRef, 10> Tokens;176 ArgValue.split(Tokens, ",", -1, false);177 std::sort(Tokens.begin(), Tokens.end());178 179 std::set<SPIRV::Extension::Extension> EnabledExtensions;180 181 for (const auto &Token : Tokens) {182 if (Token == "all") {183 for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap)184 EnabledExtensions.insert(ExtensionEnum);185 186 continue;187 }188 189 if (Token.size() == 3 && Token.upper() == "KHR") {190 for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap)191 if (StringRef(ExtensionName).starts_with("SPV_KHR_"))192 EnabledExtensions.insert(ExtensionEnum);193 continue;194 }195 196 if (Token.empty() || (!Token.starts_with("+") && !Token.starts_with("-")))197 return O.error("Invalid extension list format: " + Token.str());198 199 StringRef ExtensionName = Token.substr(1);200 auto NameValuePair = SPIRVExtensionMap.find(ExtensionName);201 202 if (NameValuePair == SPIRVExtensionMap.end())203 return O.error("Unknown SPIR-V extension: " + Token.str());204 205 if (Token.starts_with("+")) {206 EnabledExtensions.insert(NameValuePair->second);207 } else if (EnabledExtensions.count(NameValuePair->second)) {208 if (llvm::is_contained(Tokens, "+" + ExtensionName.str()))209 return O.error(210 "Extension cannot be allowed and disallowed at the same time: " +211 ExtensionName.str());212 213 EnabledExtensions.erase(NameValuePair->second);214 }215 }216 217 Vals = std::move(EnabledExtensions);218 return false;219}220 221StringRef SPIRVExtensionsParser::checkExtensions(222 const std::vector<std::string> &ExtNames,223 std::set<SPIRV::Extension::Extension> &AllowedExtensions) {224 for (const auto &Ext : ExtNames) {225 if (Ext == "all") {226 for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap)227 AllowedExtensions.insert(ExtensionEnum);228 break;229 }230 auto It = SPIRVExtensionMap.find(Ext);231 if (It == SPIRVExtensionMap.end())232 return Ext;233 AllowedExtensions.insert(It->second);234 }235 return StringRef();236}237 238std::set<SPIRV::Extension::Extension>239SPIRVExtensionsParser::getValidExtensions(const Triple &TT) {240 std::set<SPIRV::Extension::Extension> R;241 SPIRV::Environment::Environment CurrentEnvironment =242 SPIRV::Environment::Environment::EnvOpenCL;243 if (TT.getOS() == Triple::Vulkan)244 CurrentEnvironment = SPIRV::Environment::Environment::EnvVulkan;245 246 for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap) {247 EnvironmentList AllowedEnv = getSymbolicOperandAllowedEnvironments(248 SPIRV::OperandCategory::OperandCategory::ExtensionOperand,249 ExtensionEnum);250 251 if (llvm::is_contained(AllowedEnv, CurrentEnvironment))252 R.insert(ExtensionEnum);253 }254 255 if (TT.getVendor() == Triple::AMD) {256 // AMD uses the translator to recover LLVM-IR from SPIRV. Currently, the257 // translator doesn't implement the SPV_KHR_float_controls2 extension.258 R.erase(SPIRV::Extension::SPV_KHR_float_controls2);259 }260 261 return R;262}263