xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
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