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> 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_INTEL_arbitrary_precision_integers", 32 SPIRV::Extension::Extension::SPV_INTEL_arbitrary_precision_integers}, 33 {"SPV_INTEL_cache_controls", 34 SPIRV::Extension::Extension::SPV_INTEL_cache_controls}, 35 {"SPV_INTEL_global_variable_fpga_decorations", 36 SPIRV::Extension::Extension:: 37 SPV_INTEL_global_variable_fpga_decorations}, 38 {"SPV_INTEL_global_variable_host_access", 39 SPIRV::Extension::Extension::SPV_INTEL_global_variable_host_access}, 40 {"SPV_INTEL_optnone", SPIRV::Extension::Extension::SPV_INTEL_optnone}, 41 {"SPV_INTEL_usm_storage_classes", 42 SPIRV::Extension::Extension::SPV_INTEL_usm_storage_classes}, 43 {"SPV_INTEL_subgroups", 44 SPIRV::Extension::Extension::SPV_INTEL_subgroups}, 45 {"SPV_KHR_uniform_group_instructions", 46 SPIRV::Extension::Extension::SPV_KHR_uniform_group_instructions}, 47 {"SPV_KHR_no_integer_wrap_decoration", 48 SPIRV::Extension::Extension::SPV_KHR_no_integer_wrap_decoration}, 49 {"SPV_KHR_float_controls", 50 SPIRV::Extension::Extension::SPV_KHR_float_controls}, 51 {"SPV_KHR_expect_assume", 52 SPIRV::Extension::Extension::SPV_KHR_expect_assume}, 53 {"SPV_KHR_bit_instructions", 54 SPIRV::Extension::Extension::SPV_KHR_bit_instructions}, 55 {"SPV_KHR_linkonce_odr", 56 SPIRV::Extension::Extension::SPV_KHR_linkonce_odr}, 57 {"SPV_INTEL_inline_assembly", 58 SPIRV::Extension::Extension::SPV_INTEL_inline_assembly}, 59 {"SPV_INTEL_bfloat16_conversion", 60 SPIRV::Extension::Extension::SPV_INTEL_bfloat16_conversion}, 61 {"SPV_KHR_subgroup_rotate", 62 SPIRV::Extension::Extension::SPV_KHR_subgroup_rotate}, 63 {"SPV_INTEL_variable_length_array", 64 SPIRV::Extension::Extension::SPV_INTEL_variable_length_array}, 65 {"SPV_INTEL_function_pointers", 66 SPIRV::Extension::Extension::SPV_INTEL_function_pointers}, 67 {"SPV_KHR_shader_clock", 68 SPIRV::Extension::Extension::SPV_KHR_shader_clock}, 69 {"SPV_KHR_cooperative_matrix", 70 SPIRV::Extension::Extension::SPV_KHR_cooperative_matrix}, 71 }; 72 73 bool SPIRVExtensionsParser::parse(cl::Option &O, llvm::StringRef ArgName, 74 llvm::StringRef ArgValue, 75 std::set<SPIRV::Extension::Extension> &Vals) { 76 llvm::SmallVector<llvm::StringRef, 10> Tokens; 77 ArgValue.split(Tokens, ",", -1, false); 78 std::sort(Tokens.begin(), Tokens.end()); 79 80 std::set<SPIRV::Extension::Extension> EnabledExtensions; 81 82 for (const auto &Token : Tokens) { 83 if (Token == "all") { 84 for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap) 85 EnabledExtensions.insert(ExtensionEnum); 86 87 continue; 88 } 89 90 if (Token.empty() || (!Token.starts_with("+") && !Token.starts_with("-"))) 91 return O.error("Invalid extension list format: " + Token.str()); 92 93 llvm::StringRef ExtensionName = Token.substr(1); 94 auto NameValuePair = SPIRVExtensionMap.find(ExtensionName.str()); 95 96 if (NameValuePair == SPIRVExtensionMap.end()) 97 return O.error("Unknown SPIR-V extension: " + Token.str()); 98 99 if (Token.starts_with("+")) { 100 EnabledExtensions.insert(NameValuePair->second); 101 } else if (EnabledExtensions.count(NameValuePair->second)) { 102 if (std::find(Tokens.begin(), Tokens.end(), "+" + ExtensionName.str()) != 103 Tokens.end()) 104 return O.error( 105 "Extension cannot be allowed and disallowed at the same time: " + 106 ExtensionName.str()); 107 108 EnabledExtensions.erase(NameValuePair->second); 109 } 110 } 111 112 Vals = std::move(EnabledExtensions); 113 return false; 114 } 115