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