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