LLVM 23.0.0git
SPIRVCommandLine.cpp
Go to the documentation of this file.
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"
16#include "llvm/ADT/STLExtras.h"
18
19#include <functional>
20#include <iterator>
21#include <map>
22#include <set>
23#include <string>
24#include <utility>
25#include <vector>
26
27#define DEBUG_TYPE "spirv-commandline"
28
29using namespace llvm;
30
31std::set<SPIRV::Extension::Extension> SPIRVExtensionsParser::DisabledExtensions;
32
33static const std::map<StringRef, SPIRV::Extension::Extension>
35 {"SPV_EXT_shader_atomic_float_add",
36 SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_add},
37 {"SPV_EXT_shader_atomic_float16_add",
38 SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float16_add},
39 {"SPV_EXT_shader_atomic_float_min_max",
40 SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_min_max},
41 {"SPV_INTEL_16bit_atomics",
42 SPIRV::Extension::Extension::SPV_INTEL_16bit_atomics},
43 {"SPV_NV_shader_atomic_fp16_vector",
44 SPIRV::Extension::Extension::SPV_NV_shader_atomic_fp16_vector},
45 {"SPV_EXT_arithmetic_fence",
46 SPIRV::Extension::Extension::SPV_EXT_arithmetic_fence},
47 {"SPV_EXT_demote_to_helper_invocation",
48 SPIRV::Extension::Extension::SPV_EXT_demote_to_helper_invocation},
49 {"SPV_EXT_descriptor_indexing",
50 SPIRV::Extension::Extension::SPV_EXT_descriptor_indexing},
51 {"SPV_EXT_fragment_fully_covered",
52 SPIRV::Extension::Extension::SPV_EXT_fragment_fully_covered},
53 {"SPV_EXT_fragment_invocation_density",
54 SPIRV::Extension::Extension::SPV_EXT_fragment_invocation_density},
55 {"SPV_EXT_fragment_shader_interlock",
56 SPIRV::Extension::Extension::SPV_EXT_fragment_shader_interlock},
57 {"SPV_EXT_mesh_shader",
58 SPIRV::Extension::Extension::SPV_EXT_mesh_shader},
59 {"SPV_EXT_shader_stencil_export",
60 SPIRV::Extension::Extension::SPV_EXT_shader_stencil_export},
61 {"SPV_EXT_shader_viewport_index_layer",
62 SPIRV::Extension::Extension::SPV_EXT_shader_viewport_index_layer},
63 {"SPV_GOOGLE_hlsl_functionality1",
64 SPIRV::Extension::Extension::SPV_GOOGLE_hlsl_functionality1},
65 {"SPV_GOOGLE_user_type",
66 SPIRV::Extension::Extension::SPV_GOOGLE_user_type},
67 {"SPV_ALTERA_arbitrary_precision_integers",
68 SPIRV::Extension::Extension::SPV_ALTERA_arbitrary_precision_integers},
69 {"SPV_ALTERA_arbitrary_precision_floating_point",
70 SPIRV::Extension::Extension::
71 SPV_ALTERA_arbitrary_precision_floating_point},
72 {"SPV_INTEL_cache_controls",
73 SPIRV::Extension::Extension::SPV_INTEL_cache_controls},
74 {"SPV_INTEL_float_controls2",
75 SPIRV::Extension::Extension::SPV_INTEL_float_controls2},
76 {"SPV_INTEL_global_variable_fpga_decorations",
77 SPIRV::Extension::Extension::
78 SPV_INTEL_global_variable_fpga_decorations},
79 {"SPV_INTEL_global_variable_host_access",
80 SPIRV::Extension::Extension::SPV_INTEL_global_variable_host_access},
81 {"SPV_INTEL_optnone", SPIRV::Extension::Extension::SPV_INTEL_optnone},
82 {"SPV_EXT_optnone", SPIRV::Extension::Extension::SPV_EXT_optnone},
83 {"SPV_INTEL_usm_storage_classes",
84 SPIRV::Extension::Extension::SPV_INTEL_usm_storage_classes},
85 {"SPV_INTEL_split_barrier",
86 SPIRV::Extension::Extension::SPV_INTEL_split_barrier},
87 {"SPV_INTEL_subgroups",
88 SPIRV::Extension::Extension::SPV_INTEL_subgroups},
89 {"SPV_INTEL_media_block_io",
90 SPIRV::Extension::Extension::SPV_INTEL_media_block_io},
91 {"SPV_INTEL_memory_access_aliasing",
92 SPIRV::Extension::Extension::SPV_INTEL_memory_access_aliasing},
93 {"SPV_INTEL_joint_matrix",
94 SPIRV::Extension::Extension::SPV_INTEL_joint_matrix},
95 {"SPV_KHR_16bit_storage",
96 SPIRV::Extension::Extension::SPV_KHR_16bit_storage},
97 {"SPV_KHR_device_group",
98 SPIRV::Extension::Extension::SPV_KHR_device_group},
99 {"SPV_KHR_fragment_shading_rate",
100 SPIRV::Extension::Extension::SPV_KHR_fragment_shading_rate},
101 {"SPV_KHR_multiview", SPIRV::Extension::Extension::SPV_KHR_multiview},
102 {"SPV_KHR_post_depth_coverage",
103 SPIRV::Extension::Extension::SPV_KHR_post_depth_coverage},
104 {"SPV_KHR_shader_draw_parameters",
105 SPIRV::Extension::Extension::SPV_KHR_shader_draw_parameters},
106 {"SPV_KHR_ray_tracing",
107 SPIRV::Extension::Extension::SPV_KHR_ray_tracing},
108 {"SPV_KHR_uniform_group_instructions",
109 SPIRV::Extension::Extension::SPV_KHR_uniform_group_instructions},
110 {"SPV_KHR_no_integer_wrap_decoration",
111 SPIRV::Extension::Extension::SPV_KHR_no_integer_wrap_decoration},
112 {"SPV_KHR_float_controls",
113 SPIRV::Extension::Extension::SPV_KHR_float_controls},
114 {"SPV_KHR_expect_assume",
115 SPIRV::Extension::Extension::SPV_KHR_expect_assume},
116 {"SPV_KHR_bit_instructions",
117 SPIRV::Extension::Extension::SPV_KHR_bit_instructions},
118 {"SPV_KHR_integer_dot_product",
119 SPIRV::Extension::Extension::SPV_KHR_integer_dot_product},
120 {"SPV_KHR_linkonce_odr",
121 SPIRV::Extension::Extension::SPV_KHR_linkonce_odr},
122 {"SPV_KHR_fma", SPIRV::Extension::Extension::SPV_KHR_fma},
123 {"SPV_INTEL_inline_assembly",
124 SPIRV::Extension::Extension::SPV_INTEL_inline_assembly},
125 {"SPV_INTEL_bindless_images",
126 SPIRV::Extension::Extension::SPV_INTEL_bindless_images},
127 {"SPV_INTEL_bfloat16_arithmetic",
128 SPIRV::Extension::Extension::SPV_INTEL_bfloat16_arithmetic},
129 {"SPV_INTEL_bfloat16_conversion",
130 SPIRV::Extension::Extension::SPV_INTEL_bfloat16_conversion},
131 {"SPV_KHR_subgroup_rotate",
132 SPIRV::Extension::Extension::SPV_KHR_subgroup_rotate},
133 {"SPV_INTEL_variable_length_array",
134 SPIRV::Extension::Extension::SPV_INTEL_variable_length_array},
135 {"SPV_INTEL_function_pointers",
136 SPIRV::Extension::Extension::SPV_INTEL_function_pointers},
137 {"SPV_KHR_shader_clock",
138 SPIRV::Extension::Extension::SPV_KHR_shader_clock},
139 {"SPV_KHR_cooperative_matrix",
140 SPIRV::Extension::Extension::SPV_KHR_cooperative_matrix},
141 {"SPV_KHR_non_semantic_info",
142 SPIRV::Extension::Extension::SPV_KHR_non_semantic_info},
143 {"SPV_KHR_ray_query", SPIRV::Extension::Extension::SPV_KHR_ray_query},
144 {"SPV_EXT_shader_image_int64",
145 SPIRV::Extension::Extension::SPV_EXT_shader_image_int64},
146 {"SPV_KHR_fragment_shader_barycentric",
147 SPIRV::Extension::Extension::SPV_KHR_fragment_shader_barycentric},
148 {"SPV_KHR_physical_storage_buffer",
149 SPIRV::Extension::Extension::SPV_KHR_physical_storage_buffer},
150 {"SPV_KHR_vulkan_memory_model",
151 SPIRV::Extension::Extension::SPV_KHR_vulkan_memory_model},
152 {"SPV_NV_shader_subgroup_partitioned",
153 SPIRV::Extension::Extension::SPV_NV_shader_subgroup_partitioned},
154 {"SPV_INTEL_long_composites",
155 SPIRV::Extension::Extension::SPV_INTEL_long_composites},
156 {"SPV_INTEL_fp_max_error",
157 SPIRV::Extension::Extension::SPV_INTEL_fp_max_error},
158 {"SPV_INTEL_subgroup_matrix_multiply_accumulate",
159 SPIRV::Extension::Extension::
160 SPV_INTEL_subgroup_matrix_multiply_accumulate},
161 {"SPV_INTEL_ternary_bitwise_function",
162 SPIRV::Extension::Extension::SPV_INTEL_ternary_bitwise_function},
163 {"SPV_INTEL_2d_block_io",
164 SPIRV::Extension::Extension::SPV_INTEL_2d_block_io},
165 {"SPV_INTEL_int4", SPIRV::Extension::Extension::SPV_INTEL_int4},
166 {"SPV_KHR_float_controls2",
167 SPIRV::Extension::Extension::SPV_KHR_float_controls2},
168 {"SPV_INTEL_tensor_float32_conversion",
169 SPIRV::Extension::Extension::SPV_INTEL_tensor_float32_conversion},
170 {"SPV_KHR_bfloat16", SPIRV::Extension::Extension::SPV_KHR_bfloat16},
171 {"SPV_EXT_relaxed_printf_string_address_space",
172 SPIRV::Extension::Extension::
173 SPV_EXT_relaxed_printf_string_address_space},
174 {"SPV_INTEL_predicated_io",
175 SPIRV::Extension::Extension::SPV_INTEL_predicated_io},
176 {"SPV_KHR_maximal_reconvergence",
177 SPIRV::Extension::Extension::SPV_KHR_maximal_reconvergence},
178 {"SPV_INTEL_kernel_attributes",
179 SPIRV::Extension::Extension::SPV_INTEL_kernel_attributes},
180 {"SPV_ALTERA_blocking_pipes",
181 SPIRV::Extension::Extension::SPV_ALTERA_blocking_pipes},
182 {"SPV_INTEL_int4", SPIRV::Extension::Extension::SPV_INTEL_int4},
183 {"SPV_ALTERA_arbitrary_precision_fixed_point",
184 SPIRV::Extension::Extension::
185 SPV_ALTERA_arbitrary_precision_fixed_point},
186 {"SPV_EXT_image_raw10_raw12",
187 SPIRV::Extension::Extension::SPV_EXT_image_raw10_raw12},
188 {"SPV_INTEL_unstructured_loop_controls",
189 SPIRV::Extension::Extension::SPV_INTEL_unstructured_loop_controls}};
190
192 StringRef ArgValue,
193 std::set<SPIRV::Extension::Extension> &Vals) {
195 ArgValue.split(Tokens, ",", -1, false);
196
197 std::set<SPIRV::Extension::Extension> EnabledExtensions;
198
199 auto M = partition(Tokens, [](auto &&T) { return T.starts_with('+'); });
200
201 if (std::any_of(M, Tokens.end(), equal_to("all")))
202 copy(make_second_range(SPIRVExtensionMap), std::inserter(Vals, Vals.end()));
203
204 for (auto &&Token : make_range(Tokens.begin(), M)) {
205 StringRef ExtensionName = Token.substr(1);
206 auto NameValuePair = SPIRVExtensionMap.find(ExtensionName);
207
208 if (NameValuePair == SPIRVExtensionMap.end())
209 return O.error("Unknown SPIR-V extension: " + Token.str());
210
211 EnabledExtensions.insert(NameValuePair->second);
212 }
213
214 for (auto &&Token : make_range(M, Tokens.end())) {
215 if (Token == "all")
216 continue;
217
218 if (Token.size() == 3 && Token.upper() == "KHR") {
219 for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap)
220 if (StringRef(ExtensionName).starts_with("SPV_KHR_"))
221 Vals.insert(ExtensionEnum);
222 continue;
223 }
224
225 if (Token.empty() || (!Token.starts_with("+") && !Token.starts_with("-")))
226 return O.error("Invalid extension list format: " + Token);
227
228 auto NameValuePair = SPIRVExtensionMap.find(Token.substr(1));
229
230 if (NameValuePair == SPIRVExtensionMap.cend())
231 return O.error("Unknown SPIR-V extension: " + Token.str());
232 if (EnabledExtensions.count(NameValuePair->second))
233 return O.error(
234 "Extension cannot be allowed and disallowed at the same time: " +
235 NameValuePair->first);
236 DisabledExtensions.insert(NameValuePair->second);
237 Vals.erase(NameValuePair->second);
238 }
239
240 Vals.insert(EnabledExtensions.cbegin(), EnabledExtensions.cend());
241
242 return false;
243}
244
246 const std::vector<std::string> &ExtNames,
247 std::set<SPIRV::Extension::Extension> &AllowedExtensions) {
248 for (const auto &Ext : ExtNames) {
249 if (Ext == "all") {
250 for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap)
251 AllowedExtensions.insert(ExtensionEnum);
252 break;
253 }
254 auto It = SPIRVExtensionMap.find(Ext);
255 if (It == SPIRVExtensionMap.end())
256 return Ext;
257 AllowedExtensions.insert(It->second);
258 }
259 return StringRef();
260}
261
262std::set<SPIRV::Extension::Extension>
264 std::set<SPIRV::Extension::Extension> R;
265 SPIRV::Environment::Environment CurrentEnvironment =
266 SPIRV::Environment::Environment::EnvOpenCL;
267 if (TT.getOS() == Triple::Vulkan)
268 CurrentEnvironment = SPIRV::Environment::Environment::EnvVulkan;
269
270 for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap) {
272 SPIRV::OperandCategory::OperandCategory::ExtensionOperand,
273 ExtensionEnum);
274
275 if (llvm::is_contained(AllowedEnv, CurrentEnvironment) &&
276 !llvm::is_contained(DisabledExtensions, ExtensionEnum))
277 R.insert(ExtensionEnum);
278 }
279
280 return R;
281}
#define T
static const std::map< StringRef, SPIRV::Extension::Extension > SPIRVExtensionMap
This file contains some templates that are useful if you are working with the STL at all.
DEMANGLE_NAMESPACE_BEGIN bool starts_with(std::string_view self, char C) noexcept
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:730
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:591
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
SmallVector< SPIRV::Environment::Environment, 8 > EnvironmentList
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
Definition STLExtras.h:2173
EnvironmentList getSymbolicOperandAllowedEnvironments(SPIRV::OperandCategory::OperandCategory Category, uint32_t Value)
OutputIt copy(R &&Range, OutputIt Out)
Definition STLExtras.h:1885
auto partition(R &&Range, UnaryPredicate P)
Provide wrappers to std::partition which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:2033
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
Definition STLExtras.h:1409
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
static std::set< SPIRV::Extension::Extension > getValidExtensions(const Triple &TT)
Returns the list of extensions that are valid for a particular target environment (i....
bool parse(cl::Option &O, StringRef ArgName, StringRef ArgValue, std::set< SPIRV::Extension::Extension > &Vals)
Parses SPIR-V extension name from CLI arguments.
static StringRef checkExtensions(const std::vector< std::string > &ExtNames, std::set< SPIRV::Extension::Extension > &AllowedExtensions)
Validates and converts extension names into internal enum values.