blob: e7da5504b2d587a9f3fc44777a497705eb960488 [file] [log] [blame] [edit]
//===--- SPIRVCommandLine.cpp ---- Command Line Options ---------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains definitions of classes and functions needed for
// processing, parsing, and using CLI options for the SPIR-V backend.
//
//===----------------------------------------------------------------------===//
#include "SPIRVCommandLine.h"
#include "MCTargetDesc/SPIRVBaseInfo.h"
#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <map>
#define DEBUG_TYPE "spirv-commandline"
using namespace llvm;
static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
SPIRVExtensionMap = {
{"SPV_EXT_shader_atomic_float_add",
SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_add},
{"SPV_EXT_shader_atomic_float16_add",
SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float16_add},
{"SPV_EXT_shader_atomic_float_min_max",
SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_min_max},
{"SPV_EXT_arithmetic_fence",
SPIRV::Extension::Extension::SPV_EXT_arithmetic_fence},
{"SPV_EXT_demote_to_helper_invocation",
SPIRV::Extension::Extension::SPV_EXT_demote_to_helper_invocation},
{"SPV_EXT_descriptor_indexing",
SPIRV::Extension::Extension::SPV_EXT_descriptor_indexing},
{"SPV_EXT_fragment_fully_covered",
SPIRV::Extension::Extension::SPV_EXT_fragment_fully_covered},
{"SPV_EXT_fragment_invocation_density",
SPIRV::Extension::Extension::SPV_EXT_fragment_invocation_density},
{"SPV_EXT_fragment_shader_interlock",
SPIRV::Extension::Extension::SPV_EXT_fragment_shader_interlock},
{"SPV_EXT_mesh_shader",
SPIRV::Extension::Extension::SPV_EXT_mesh_shader},
{"SPV_EXT_shader_stencil_export",
SPIRV::Extension::Extension::SPV_EXT_shader_stencil_export},
{"SPV_EXT_shader_viewport_index_layer",
SPIRV::Extension::Extension::SPV_EXT_shader_viewport_index_layer},
{"SPV_GOOGLE_hlsl_functionality1",
SPIRV::Extension::Extension::SPV_GOOGLE_hlsl_functionality1},
{"SPV_GOOGLE_user_type",
SPIRV::Extension::Extension::SPV_GOOGLE_user_type},
{"SPV_INTEL_arbitrary_precision_integers",
SPIRV::Extension::Extension::SPV_INTEL_arbitrary_precision_integers},
{"SPV_INTEL_cache_controls",
SPIRV::Extension::Extension::SPV_INTEL_cache_controls},
{"SPV_INTEL_float_controls2",
SPIRV::Extension::Extension::SPV_INTEL_float_controls2},
{"SPV_INTEL_global_variable_fpga_decorations",
SPIRV::Extension::Extension::
SPV_INTEL_global_variable_fpga_decorations},
{"SPV_INTEL_global_variable_host_access",
SPIRV::Extension::Extension::SPV_INTEL_global_variable_host_access},
{"SPV_INTEL_optnone", SPIRV::Extension::Extension::SPV_INTEL_optnone},
{"SPV_EXT_optnone", SPIRV::Extension::Extension::SPV_EXT_optnone},
{"SPV_INTEL_usm_storage_classes",
SPIRV::Extension::Extension::SPV_INTEL_usm_storage_classes},
{"SPV_INTEL_split_barrier",
SPIRV::Extension::Extension::SPV_INTEL_split_barrier},
{"SPV_INTEL_subgroups",
SPIRV::Extension::Extension::SPV_INTEL_subgroups},
{"SPV_INTEL_media_block_io",
SPIRV::Extension::Extension::SPV_INTEL_media_block_io},
{"SPV_INTEL_memory_access_aliasing",
SPIRV::Extension::Extension::SPV_INTEL_memory_access_aliasing},
{"SPV_INTEL_joint_matrix",
SPIRV::Extension::Extension::SPV_INTEL_joint_matrix},
{"SPV_KHR_16bit_storage",
SPIRV::Extension::Extension::SPV_KHR_16bit_storage},
{"SPV_KHR_device_group",
SPIRV::Extension::Extension::SPV_KHR_device_group},
{"SPV_KHR_fragment_shading_rate",
SPIRV::Extension::Extension::SPV_KHR_fragment_shading_rate},
{"SPV_KHR_multiview", SPIRV::Extension::Extension::SPV_KHR_multiview},
{"SPV_KHR_post_depth_coverage",
SPIRV::Extension::Extension::SPV_KHR_post_depth_coverage},
{"SPV_KHR_shader_draw_parameters",
SPIRV::Extension::Extension::SPV_KHR_shader_draw_parameters},
{"SPV_KHR_ray_tracing",
SPIRV::Extension::Extension::SPV_KHR_ray_tracing},
{"SPV_KHR_uniform_group_instructions",
SPIRV::Extension::Extension::SPV_KHR_uniform_group_instructions},
{"SPV_KHR_no_integer_wrap_decoration",
SPIRV::Extension::Extension::SPV_KHR_no_integer_wrap_decoration},
{"SPV_KHR_float_controls",
SPIRV::Extension::Extension::SPV_KHR_float_controls},
{"SPV_KHR_expect_assume",
SPIRV::Extension::Extension::SPV_KHR_expect_assume},
{"SPV_KHR_bit_instructions",
SPIRV::Extension::Extension::SPV_KHR_bit_instructions},
{"SPV_KHR_integer_dot_product",
SPIRV::Extension::Extension::SPV_KHR_integer_dot_product},
{"SPV_KHR_linkonce_odr",
SPIRV::Extension::Extension::SPV_KHR_linkonce_odr},
{"SPV_INTEL_inline_assembly",
SPIRV::Extension::Extension::SPV_INTEL_inline_assembly},
{"SPV_INTEL_bindless_images",
SPIRV::Extension::Extension::SPV_INTEL_bindless_images},
{"SPV_INTEL_bfloat16_conversion",
SPIRV::Extension::Extension::SPV_INTEL_bfloat16_conversion},
{"SPV_KHR_subgroup_rotate",
SPIRV::Extension::Extension::SPV_KHR_subgroup_rotate},
{"SPV_INTEL_variable_length_array",
SPIRV::Extension::Extension::SPV_INTEL_variable_length_array},
{"SPV_INTEL_function_pointers",
SPIRV::Extension::Extension::SPV_INTEL_function_pointers},
{"SPV_KHR_shader_clock",
SPIRV::Extension::Extension::SPV_KHR_shader_clock},
{"SPV_KHR_cooperative_matrix",
SPIRV::Extension::Extension::SPV_KHR_cooperative_matrix},
{"SPV_KHR_non_semantic_info",
SPIRV::Extension::Extension::SPV_KHR_non_semantic_info},
{"SPV_KHR_ray_query", SPIRV::Extension::Extension::SPV_KHR_ray_query},
{"SPV_EXT_shader_image_int64",
SPIRV::Extension::Extension::SPV_EXT_shader_image_int64},
{"SPV_KHR_fragment_shader_barycentric",
SPIRV::Extension::Extension::SPV_KHR_fragment_shader_barycentric},
{"SPV_KHR_physical_storage_buffer",
SPIRV::Extension::Extension::SPV_KHR_physical_storage_buffer},
{"SPV_KHR_vulkan_memory_model",
SPIRV::Extension::Extension::SPV_KHR_vulkan_memory_model},
{"SPV_NV_shader_subgroup_partitioned",
SPIRV::Extension::Extension::SPV_NV_shader_subgroup_partitioned},
{"SPV_INTEL_long_composites",
SPIRV::Extension::Extension::SPV_INTEL_long_composites},
{"SPV_INTEL_fp_max_error",
SPIRV::Extension::Extension::SPV_INTEL_fp_max_error},
{"SPV_INTEL_subgroup_matrix_multiply_accumulate",
SPIRV::Extension::Extension::
SPV_INTEL_subgroup_matrix_multiply_accumulate},
{"SPV_INTEL_ternary_bitwise_function",
SPIRV::Extension::Extension::SPV_INTEL_ternary_bitwise_function},
{"SPV_INTEL_2d_block_io",
SPIRV::Extension::Extension::SPV_INTEL_2d_block_io},
{"SPV_INTEL_int4", SPIRV::Extension::Extension::SPV_INTEL_int4},
{"SPV_KHR_float_controls2",
SPIRV::Extension::Extension::SPV_KHR_float_controls2},
{"SPV_INTEL_tensor_float32_conversion",
SPIRV::Extension::Extension::SPV_INTEL_tensor_float32_conversion}};
bool SPIRVExtensionsParser::parse(cl::Option &O, StringRef ArgName,
StringRef ArgValue,
std::set<SPIRV::Extension::Extension> &Vals) {
SmallVector<StringRef, 10> Tokens;
ArgValue.split(Tokens, ",", -1, false);
std::sort(Tokens.begin(), Tokens.end());
std::set<SPIRV::Extension::Extension> EnabledExtensions;
for (const auto &Token : Tokens) {
if (Token == "all") {
for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap)
EnabledExtensions.insert(ExtensionEnum);
continue;
}
if (Token.size() == 3 && Token.upper() == "KHR") {
for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap)
if (StringRef(ExtensionName).starts_with("SPV_KHR_"))
EnabledExtensions.insert(ExtensionEnum);
continue;
}
if (Token.empty() || (!Token.starts_with("+") && !Token.starts_with("-")))
return O.error("Invalid extension list format: " + Token.str());
StringRef ExtensionName = Token.substr(1);
auto NameValuePair = SPIRVExtensionMap.find(ExtensionName);
if (NameValuePair == SPIRVExtensionMap.end())
return O.error("Unknown SPIR-V extension: " + Token.str());
if (Token.starts_with("+")) {
EnabledExtensions.insert(NameValuePair->second);
} else if (EnabledExtensions.count(NameValuePair->second)) {
if (llvm::is_contained(Tokens, "+" + ExtensionName.str()))
return O.error(
"Extension cannot be allowed and disallowed at the same time: " +
ExtensionName.str());
EnabledExtensions.erase(NameValuePair->second);
}
}
Vals = std::move(EnabledExtensions);
return false;
}
StringRef SPIRVExtensionsParser::checkExtensions(
const std::vector<std::string> &ExtNames,
std::set<SPIRV::Extension::Extension> &AllowedExtensions) {
for (const auto &Ext : ExtNames) {
if (Ext == "all") {
for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap)
AllowedExtensions.insert(ExtensionEnum);
break;
}
auto It = SPIRVExtensionMap.find(Ext);
if (It == SPIRVExtensionMap.end())
return Ext;
AllowedExtensions.insert(It->second);
}
return StringRef();
}
std::set<SPIRV::Extension::Extension>
SPIRVExtensionsParser::getValidExtensions(const Triple &TT) {
std::set<SPIRV::Extension::Extension> R;
SPIRV::Environment::Environment CurrentEnvironment =
SPIRV::Environment::Environment::EnvOpenCL;
if (TT.getOS() == Triple::Vulkan)
CurrentEnvironment = SPIRV::Environment::Environment::EnvVulkan;
for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap) {
EnvironmentList AllowedEnv = getSymbolicOperandAllowedEnvironments(
SPIRV::OperandCategory::OperandCategory::ExtensionOperand,
ExtensionEnum);
if (llvm::is_contained(AllowedEnv, CurrentEnvironment))
R.insert(ExtensionEnum);
}
return R;
}