xref: /llvm-project/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp (revision 489db6538e5c90190cfdc50e497b4916af46dfe1)
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
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   auto TableEnd = ArrayRef(SPIRV::SymbolicOperands).end();
80   while (EnumValueInCategory && EnumValueInCategory->Category == Category) {
81     if ((EnumValueInCategory->Value != 0) &&
82         (Value & EnumValueInCategory->Value)) {
83       Name += Separator + EnumValueInCategory->Mnemonic.str();
84       Separator = "|";
85     }
86     if (++EnumValueInCategory == TableEnd)
87       break;
88   }
89 
90   return Name;
91 }
92 
93 VersionTuple
94 getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category,
95                              uint32_t Value) {
96   const SPIRV::SymbolicOperand *Lookup =
97       SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value);
98 
99   if (Lookup)
100     return VersionTuple(Lookup->MinVersion / 10, Lookup->MinVersion % 10);
101 
102   return VersionTuple(0);
103 }
104 
105 VersionTuple
106 getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category,
107                              uint32_t Value) {
108   const SPIRV::SymbolicOperand *Lookup =
109       SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value);
110 
111   if (Lookup)
112     return VersionTuple(Lookup->MaxVersion / 10, Lookup->MaxVersion % 10);
113 
114   return VersionTuple();
115 }
116 
117 CapabilityList
118 getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category,
119                                uint32_t Value) {
120   CapabilityList Capabilities;
121   const SPIRV::CapabilityEntry *Capability =
122       SPIRV::lookupCapabilityByCategoryAndValue(Category, Value);
123   auto TableEnd = ArrayRef(SPIRV::CapabilityEntries).end();
124   while (Capability && Capability->Category == Category &&
125          Capability->Value == Value) {
126     Capabilities.push_back(
127         static_cast<SPIRV::Capability::Capability>(Capability->ReqCapability));
128     if (++Capability == TableEnd)
129       break;
130   }
131 
132   return Capabilities;
133 }
134 
135 CapabilityList
136 getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension) {
137   const SPIRV::ExtensionEntry *Entry =
138       SPIRV::lookupSymbolicOperandsEnabledByExtension(
139           Extension, SPIRV::OperandCategory::CapabilityOperand);
140 
141   CapabilityList Capabilities;
142   auto TableEnd = ArrayRef(SPIRV::ExtensionEntries).end();
143   while (Entry &&
144          Entry->Category == SPIRV::OperandCategory::CapabilityOperand) {
145     // Some capabilities' codes might go not in order.
146     if (Entry->ReqExtension == Extension)
147       Capabilities.push_back(
148           static_cast<SPIRV::Capability::Capability>(Entry->Value));
149     if (++Entry == TableEnd)
150       break;
151   }
152 
153   return Capabilities;
154 }
155 
156 ExtensionList
157 getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category,
158                              uint32_t Value) {
159   const SPIRV::ExtensionEntry *Extension =
160       SPIRV::lookupExtensionByCategoryAndValue(Category, Value);
161 
162   ExtensionList Extensions;
163   auto TableEnd = ArrayRef(SPIRV::ExtensionEntries).end();
164   while (Extension && Extension->Category == Category &&
165          Extension->Value == Value) {
166     Extensions.push_back(
167         static_cast<SPIRV::Extension::Extension>(Extension->ReqExtension));
168     if (++Extension == TableEnd)
169       break;
170   }
171 
172   return Extensions;
173 }
174 
175 std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue) {
176   const SPIRV::SymbolicOperand *Lookup =
177       SPIRV::lookupSymbolicOperandByCategoryAndValue(
178           SPIRV::OperandCategory::BuiltInOperand, BuiltInValue);
179 
180   if (Lookup)
181     return "__spirv_BuiltIn" + Lookup->Mnemonic.str();
182   return "UNKNOWN_BUILTIN";
183 }
184 
185 bool getSpirvBuiltInIdByName(llvm::StringRef Name,
186                              SPIRV::BuiltIn::BuiltIn &BI) {
187   const std::string Prefix = "__spirv_BuiltIn";
188   if (!Name.starts_with(Prefix))
189     return false;
190 
191   const SPIRV::SymbolicOperand *Lookup =
192       SPIRV::lookupSymbolicOperandByCategoryAndMnemonic(
193           SPIRV::OperandCategory::BuiltInOperand,
194           Name.drop_front(Prefix.length()));
195 
196   if (!Lookup)
197     return false;
198 
199   BI = static_cast<SPIRV::BuiltIn::BuiltIn>(Lookup->Value);
200   return true;
201 }
202 
203 std::string getExtInstSetName(SPIRV::InstructionSet::InstructionSet Set) {
204   switch (Set) {
205   case SPIRV::InstructionSet::OpenCL_std:
206     return "OpenCL.std";
207   case SPIRV::InstructionSet::GLSL_std_450:
208     return "GLSL.std.450";
209   case SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100:
210     return "NonSemantic.Shader.DebugInfo.100";
211   case SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax:
212     return "SPV_AMD_shader_trinary_minmax";
213   }
214   return "UNKNOWN_EXT_INST_SET";
215 }
216 
217 SPIRV::InstructionSet::InstructionSet
218 getExtInstSetFromString(std::string SetName) {
219   for (auto Set :
220        {SPIRV::InstructionSet::GLSL_std_450, SPIRV::InstructionSet::OpenCL_std,
221         SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100}) {
222     if (SetName == getExtInstSetName(Set))
223       return Set;
224   }
225   llvm_unreachable("UNKNOWN_EXT_INST_SET");
226 }
227 
228 std::string getExtInstName(SPIRV::InstructionSet::InstructionSet Set,
229                            uint32_t InstructionNumber) {
230   const SPIRV::ExtendedBuiltin *Lookup =
231       SPIRV::lookupExtendedBuiltinBySetAndNumber(Set, InstructionNumber);
232 
233   if (!Lookup)
234     return "UNKNOWN_EXT_INST";
235 
236   return Lookup->Name.str();
237 }
238 } // namespace llvm
239