1 //===-- SPIRVBaseInfo.cpp - Top level SPIRV definitions ---------*- 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 the implementation for helper mnemonic lookup functions,
10 // versioning/capabilities/extensions getters for symbolic/named operands used
11 // in various SPIR-V instructions.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "SPIRVBaseInfo.h"
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/ADT/StringRef.h"
18
19 namespace llvm {
20 namespace SPIRV {
21 struct SymbolicOperand {
22 OperandCategory::OperandCategory Category;
23 uint32_t Value;
24 StringRef Mnemonic;
25 uint32_t MinVersion;
26 uint32_t MaxVersion;
27 };
28
29 struct ExtensionEntry {
30 OperandCategory::OperandCategory Category;
31 uint32_t Value;
32 Extension::Extension ReqExtension;
33 };
34
35 struct CapabilityEntry {
36 OperandCategory::OperandCategory Category;
37 uint32_t Value;
38 Capability::Capability ReqCapability;
39 };
40
41 using namespace OperandCategory;
42 using namespace Extension;
43 using namespace Capability;
44 using namespace InstructionSet;
45 #define GET_SymbolicOperands_DECL
46 #define GET_SymbolicOperands_IMPL
47 #define GET_ExtensionEntries_DECL
48 #define GET_ExtensionEntries_IMPL
49 #define GET_CapabilityEntries_DECL
50 #define GET_CapabilityEntries_IMPL
51 #define GET_ExtendedBuiltins_DECL
52 #define GET_ExtendedBuiltins_IMPL
53 #include "SPIRVGenTables.inc"
54 } // namespace SPIRV
55
56 std::string
getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category,int32_t Value)57 getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category,
58 int32_t Value) {
59 const SPIRV::SymbolicOperand *Lookup =
60 SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value);
61 // Value that encodes just one enum value.
62 if (Lookup)
63 return Lookup->Mnemonic.str();
64 if (Category != SPIRV::OperandCategory::ImageOperandOperand &&
65 Category != SPIRV::OperandCategory::FPFastMathModeOperand &&
66 Category != SPIRV::OperandCategory::SelectionControlOperand &&
67 Category != SPIRV::OperandCategory::LoopControlOperand &&
68 Category != SPIRV::OperandCategory::FunctionControlOperand &&
69 Category != SPIRV::OperandCategory::MemorySemanticsOperand &&
70 Category != SPIRV::OperandCategory::MemoryOperandOperand &&
71 Category != SPIRV::OperandCategory::KernelProfilingInfoOperand)
72 return "UNKNOWN";
73 // Value that encodes many enum values (one bit per enum value).
74 std::string Name;
75 std::string Separator;
76 const SPIRV::SymbolicOperand *EnumValueInCategory =
77 SPIRV::lookupSymbolicOperandByCategory(Category);
78
79 while (EnumValueInCategory && EnumValueInCategory->Category == Category) {
80 if ((EnumValueInCategory->Value != 0) &&
81 (Value & EnumValueInCategory->Value)) {
82 Name += Separator + EnumValueInCategory->Mnemonic.str();
83 Separator = "|";
84 }
85 ++EnumValueInCategory;
86 }
87
88 return Name;
89 }
90
91 uint32_t
getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category,uint32_t Value)92 getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category,
93 uint32_t Value) {
94 const SPIRV::SymbolicOperand *Lookup =
95 SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value);
96
97 if (Lookup)
98 return Lookup->MinVersion;
99
100 return 0;
101 }
102
103 uint32_t
getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category,uint32_t Value)104 getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category,
105 uint32_t Value) {
106 const SPIRV::SymbolicOperand *Lookup =
107 SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value);
108
109 if (Lookup)
110 return Lookup->MaxVersion;
111
112 return 0;
113 }
114
115 CapabilityList
getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category,uint32_t Value)116 getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category,
117 uint32_t Value) {
118 const SPIRV::CapabilityEntry *Capability =
119 SPIRV::lookupCapabilityByCategoryAndValue(Category, Value);
120
121 CapabilityList Capabilities;
122 while (Capability && Capability->Category == Category &&
123 Capability->Value == Value) {
124 Capabilities.push_back(
125 static_cast<SPIRV::Capability::Capability>(Capability->ReqCapability));
126 ++Capability;
127 }
128
129 return Capabilities;
130 }
131
132 ExtensionList
getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category,uint32_t Value)133 getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category,
134 uint32_t Value) {
135 const SPIRV::ExtensionEntry *Extension =
136 SPIRV::lookupExtensionByCategoryAndValue(Category, Value);
137
138 ExtensionList Extensions;
139 while (Extension && Extension->Category == Category &&
140 Extension->Value == Value) {
141 Extensions.push_back(
142 static_cast<SPIRV::Extension::Extension>(Extension->ReqExtension));
143 ++Extension;
144 }
145
146 return Extensions;
147 }
148
getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue)149 std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue) {
150 const SPIRV::SymbolicOperand *Lookup =
151 SPIRV::lookupSymbolicOperandByCategoryAndValue(
152 SPIRV::OperandCategory::BuiltInOperand, BuiltInValue);
153
154 if (Lookup)
155 return "__spirv_BuiltIn" + Lookup->Mnemonic.str();
156 return "UNKNOWN_BUILTIN";
157 }
158
getSpirvBuiltInIdByName(llvm::StringRef Name,SPIRV::BuiltIn::BuiltIn & BI)159 bool getSpirvBuiltInIdByName(llvm::StringRef Name,
160 SPIRV::BuiltIn::BuiltIn &BI) {
161 const std::string Prefix = "__spirv_BuiltIn";
162 if (!Name.startswith(Prefix))
163 return false;
164
165 const SPIRV::SymbolicOperand *Lookup =
166 SPIRV::lookupSymbolicOperandByCategoryAndMnemonic(
167 SPIRV::OperandCategory::BuiltInOperand,
168 Name.drop_front(Prefix.length()));
169
170 if (!Lookup)
171 return false;
172
173 BI = static_cast<SPIRV::BuiltIn::BuiltIn>(Lookup->Value);
174 return true;
175 }
176
getExtInstSetName(SPIRV::InstructionSet::InstructionSet Set)177 std::string getExtInstSetName(SPIRV::InstructionSet::InstructionSet Set) {
178 switch (Set) {
179 case SPIRV::InstructionSet::OpenCL_std:
180 return "OpenCL.std";
181 case SPIRV::InstructionSet::GLSL_std_450:
182 return "GLSL.std.450";
183 case SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax:
184 return "SPV_AMD_shader_trinary_minmax";
185 }
186 return "UNKNOWN_EXT_INST_SET";
187 }
188
189 SPIRV::InstructionSet::InstructionSet
getExtInstSetFromString(std::string SetName)190 getExtInstSetFromString(std::string SetName) {
191 for (auto Set : {SPIRV::InstructionSet::GLSL_std_450,
192 SPIRV::InstructionSet::OpenCL_std}) {
193 if (SetName == getExtInstSetName(Set))
194 return Set;
195 }
196 llvm_unreachable("UNKNOWN_EXT_INST_SET");
197 }
198
getExtInstName(SPIRV::InstructionSet::InstructionSet Set,uint32_t InstructionNumber)199 std::string getExtInstName(SPIRV::InstructionSet::InstructionSet Set,
200 uint32_t InstructionNumber) {
201 const SPIRV::ExtendedBuiltin *Lookup =
202 SPIRV::lookupExtendedBuiltinBySetAndNumber(
203 SPIRV::InstructionSet::OpenCL_std, InstructionNumber);
204
205 if (!Lookup)
206 return "UNKNOWN_EXT_INST";
207
208 return Lookup->Name.str();
209 }
210 } // namespace llvm
211