xref: /llvm-project/llvm/lib/Target/SPIRV/MCTargetDesc/SPIRVBaseInfo.cpp (revision 489db6538e5c90190cfdc50e497b4916af46dfe1)
1b25b507cSIlia Diachkov //===-- SPIRVBaseInfo.cpp - Top level SPIRV definitions ---------*- C++ -*-===//
2eab7d363SIlia Diachkov //
3eab7d363SIlia Diachkov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4eab7d363SIlia Diachkov // See https://llvm.org/LICENSE.txt for license information.
5eab7d363SIlia Diachkov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6eab7d363SIlia Diachkov //
7eab7d363SIlia Diachkov //===----------------------------------------------------------------------===//
8eab7d363SIlia Diachkov //
9b25b507cSIlia Diachkov // This file contains the implementation for helper mnemonic lookup functions,
10b25b507cSIlia Diachkov // versioning/capabilities/extensions getters for symbolic/named operands used
11b25b507cSIlia Diachkov // in various SPIR-V instructions.
12eab7d363SIlia Diachkov //
13eab7d363SIlia Diachkov //===----------------------------------------------------------------------===//
14eab7d363SIlia Diachkov 
15eab7d363SIlia Diachkov #include "SPIRVBaseInfo.h"
16b25b507cSIlia Diachkov #include "llvm/ADT/ArrayRef.h"
17b25b507cSIlia Diachkov #include "llvm/ADT/StringRef.h"
18eab7d363SIlia Diachkov 
19eab7d363SIlia Diachkov namespace llvm {
20eab7d363SIlia Diachkov namespace SPIRV {
21b25b507cSIlia Diachkov struct SymbolicOperand {
22b25b507cSIlia Diachkov   OperandCategory::OperandCategory Category;
23b25b507cSIlia Diachkov   uint32_t Value;
24b25b507cSIlia Diachkov   StringRef Mnemonic;
25b25b507cSIlia Diachkov   uint32_t MinVersion;
26b25b507cSIlia Diachkov   uint32_t MaxVersion;
27b25b507cSIlia Diachkov };
28b25b507cSIlia Diachkov 
29b25b507cSIlia Diachkov struct ExtensionEntry {
30b25b507cSIlia Diachkov   OperandCategory::OperandCategory Category;
31b25b507cSIlia Diachkov   uint32_t Value;
32b25b507cSIlia Diachkov   Extension::Extension ReqExtension;
33b25b507cSIlia Diachkov };
34b25b507cSIlia Diachkov 
35b25b507cSIlia Diachkov struct CapabilityEntry {
36b25b507cSIlia Diachkov   OperandCategory::OperandCategory Category;
37b25b507cSIlia Diachkov   uint32_t Value;
38b25b507cSIlia Diachkov   Capability::Capability ReqCapability;
39b25b507cSIlia Diachkov };
40b25b507cSIlia Diachkov 
41b25b507cSIlia Diachkov using namespace OperandCategory;
42b25b507cSIlia Diachkov using namespace Extension;
43b25b507cSIlia Diachkov using namespace Capability;
44f61eb416SIlia Diachkov using namespace InstructionSet;
45b25b507cSIlia Diachkov #define GET_SymbolicOperands_DECL
46b25b507cSIlia Diachkov #define GET_SymbolicOperands_IMPL
47b25b507cSIlia Diachkov #define GET_ExtensionEntries_DECL
48b25b507cSIlia Diachkov #define GET_ExtensionEntries_IMPL
49b25b507cSIlia Diachkov #define GET_CapabilityEntries_DECL
50b25b507cSIlia Diachkov #define GET_CapabilityEntries_IMPL
51b25b507cSIlia Diachkov #define GET_ExtendedBuiltins_DECL
52b25b507cSIlia Diachkov #define GET_ExtendedBuiltins_IMPL
53b25b507cSIlia Diachkov #include "SPIRVGenTables.inc"
54eab7d363SIlia Diachkov } // namespace SPIRV
55b25b507cSIlia Diachkov 
56b25b507cSIlia Diachkov std::string
57b25b507cSIlia Diachkov getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category,
58b25b507cSIlia Diachkov                            int32_t Value) {
59b25b507cSIlia Diachkov   const SPIRV::SymbolicOperand *Lookup =
60b25b507cSIlia Diachkov       SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value);
61b25b507cSIlia Diachkov   // Value that encodes just one enum value.
62b25b507cSIlia Diachkov   if (Lookup)
63b25b507cSIlia Diachkov     return Lookup->Mnemonic.str();
64b25b507cSIlia Diachkov   if (Category != SPIRV::OperandCategory::ImageOperandOperand &&
65b25b507cSIlia Diachkov       Category != SPIRV::OperandCategory::FPFastMathModeOperand &&
66b25b507cSIlia Diachkov       Category != SPIRV::OperandCategory::SelectionControlOperand &&
67b25b507cSIlia Diachkov       Category != SPIRV::OperandCategory::LoopControlOperand &&
68b25b507cSIlia Diachkov       Category != SPIRV::OperandCategory::FunctionControlOperand &&
69b25b507cSIlia Diachkov       Category != SPIRV::OperandCategory::MemorySemanticsOperand &&
70b25b507cSIlia Diachkov       Category != SPIRV::OperandCategory::MemoryOperandOperand &&
71b25b507cSIlia Diachkov       Category != SPIRV::OperandCategory::KernelProfilingInfoOperand)
72b25b507cSIlia Diachkov     return "UNKNOWN";
73b25b507cSIlia Diachkov   // Value that encodes many enum values (one bit per enum value).
74b25b507cSIlia Diachkov   std::string Name;
75b25b507cSIlia Diachkov   std::string Separator;
76b25b507cSIlia Diachkov   const SPIRV::SymbolicOperand *EnumValueInCategory =
77b25b507cSIlia Diachkov       SPIRV::lookupSymbolicOperandByCategory(Category);
78b25b507cSIlia Diachkov 
79*489db653SVyacheslav Levytskyy   auto TableEnd = ArrayRef(SPIRV::SymbolicOperands).end();
80b25b507cSIlia Diachkov   while (EnumValueInCategory && EnumValueInCategory->Category == Category) {
81b25b507cSIlia Diachkov     if ((EnumValueInCategory->Value != 0) &&
82b25b507cSIlia Diachkov         (Value & EnumValueInCategory->Value)) {
83b25b507cSIlia Diachkov       Name += Separator + EnumValueInCategory->Mnemonic.str();
84b25b507cSIlia Diachkov       Separator = "|";
85b25b507cSIlia Diachkov     }
86*489db653SVyacheslav Levytskyy     if (++EnumValueInCategory == TableEnd)
87*489db653SVyacheslav Levytskyy       break;
88b25b507cSIlia Diachkov   }
89b25b507cSIlia Diachkov 
90b25b507cSIlia Diachkov   return Name;
91b25b507cSIlia Diachkov }
92b25b507cSIlia Diachkov 
93f352ce36SMichal Paszkowski VersionTuple
94b25b507cSIlia Diachkov getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category,
95b25b507cSIlia Diachkov                              uint32_t Value) {
96b25b507cSIlia Diachkov   const SPIRV::SymbolicOperand *Lookup =
97b25b507cSIlia Diachkov       SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value);
98b25b507cSIlia Diachkov 
99b25b507cSIlia Diachkov   if (Lookup)
100f352ce36SMichal Paszkowski     return VersionTuple(Lookup->MinVersion / 10, Lookup->MinVersion % 10);
101b25b507cSIlia Diachkov 
102f352ce36SMichal Paszkowski   return VersionTuple(0);
103b25b507cSIlia Diachkov }
104b25b507cSIlia Diachkov 
105f352ce36SMichal Paszkowski VersionTuple
106b25b507cSIlia Diachkov getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category,
107b25b507cSIlia Diachkov                              uint32_t Value) {
108b25b507cSIlia Diachkov   const SPIRV::SymbolicOperand *Lookup =
109b25b507cSIlia Diachkov       SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value);
110b25b507cSIlia Diachkov 
111b25b507cSIlia Diachkov   if (Lookup)
112f352ce36SMichal Paszkowski     return VersionTuple(Lookup->MaxVersion / 10, Lookup->MaxVersion % 10);
113b25b507cSIlia Diachkov 
114f352ce36SMichal Paszkowski   return VersionTuple();
115b25b507cSIlia Diachkov }
116b25b507cSIlia Diachkov 
117b25b507cSIlia Diachkov CapabilityList
118b25b507cSIlia Diachkov getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category,
119b25b507cSIlia Diachkov                                uint32_t Value) {
120*489db653SVyacheslav Levytskyy   CapabilityList Capabilities;
121b25b507cSIlia Diachkov   const SPIRV::CapabilityEntry *Capability =
122b25b507cSIlia Diachkov       SPIRV::lookupCapabilityByCategoryAndValue(Category, Value);
123*489db653SVyacheslav Levytskyy   auto TableEnd = ArrayRef(SPIRV::CapabilityEntries).end();
124b25b507cSIlia Diachkov   while (Capability && Capability->Category == Category &&
125b25b507cSIlia Diachkov          Capability->Value == Value) {
126b25b507cSIlia Diachkov     Capabilities.push_back(
127b25b507cSIlia Diachkov         static_cast<SPIRV::Capability::Capability>(Capability->ReqCapability));
128*489db653SVyacheslav Levytskyy     if (++Capability == TableEnd)
129*489db653SVyacheslav Levytskyy       break;
130b25b507cSIlia Diachkov   }
131b25b507cSIlia Diachkov 
132b25b507cSIlia Diachkov   return Capabilities;
133b25b507cSIlia Diachkov }
134b25b507cSIlia Diachkov 
135efe0e107SMichal Paszkowski CapabilityList
136efe0e107SMichal Paszkowski getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension) {
137efe0e107SMichal Paszkowski   const SPIRV::ExtensionEntry *Entry =
138efe0e107SMichal Paszkowski       SPIRV::lookupSymbolicOperandsEnabledByExtension(
139efe0e107SMichal Paszkowski           Extension, SPIRV::OperandCategory::CapabilityOperand);
140efe0e107SMichal Paszkowski 
141efe0e107SMichal Paszkowski   CapabilityList Capabilities;
142*489db653SVyacheslav Levytskyy   auto TableEnd = ArrayRef(SPIRV::ExtensionEntries).end();
143efe0e107SMichal Paszkowski   while (Entry &&
144d057b53aSDmitry Sidorov          Entry->Category == SPIRV::OperandCategory::CapabilityOperand) {
145d057b53aSDmitry Sidorov     // Some capabilities' codes might go not in order.
146*489db653SVyacheslav Levytskyy     if (Entry->ReqExtension == Extension)
147efe0e107SMichal Paszkowski       Capabilities.push_back(
148efe0e107SMichal Paszkowski           static_cast<SPIRV::Capability::Capability>(Entry->Value));
149*489db653SVyacheslav Levytskyy     if (++Entry == TableEnd)
150*489db653SVyacheslav Levytskyy       break;
151efe0e107SMichal Paszkowski   }
152efe0e107SMichal Paszkowski 
153efe0e107SMichal Paszkowski   return Capabilities;
154efe0e107SMichal Paszkowski }
155efe0e107SMichal Paszkowski 
156b25b507cSIlia Diachkov ExtensionList
157b25b507cSIlia Diachkov getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category,
158b25b507cSIlia Diachkov                              uint32_t Value) {
159b25b507cSIlia Diachkov   const SPIRV::ExtensionEntry *Extension =
160b25b507cSIlia Diachkov       SPIRV::lookupExtensionByCategoryAndValue(Category, Value);
161b25b507cSIlia Diachkov 
162b25b507cSIlia Diachkov   ExtensionList Extensions;
163*489db653SVyacheslav Levytskyy   auto TableEnd = ArrayRef(SPIRV::ExtensionEntries).end();
164b25b507cSIlia Diachkov   while (Extension && Extension->Category == Category &&
165b25b507cSIlia Diachkov          Extension->Value == Value) {
166b25b507cSIlia Diachkov     Extensions.push_back(
167b25b507cSIlia Diachkov         static_cast<SPIRV::Extension::Extension>(Extension->ReqExtension));
168*489db653SVyacheslav Levytskyy     if (++Extension == TableEnd)
169*489db653SVyacheslav Levytskyy       break;
170b25b507cSIlia Diachkov   }
171b25b507cSIlia Diachkov 
172b25b507cSIlia Diachkov   return Extensions;
173b25b507cSIlia Diachkov }
174b25b507cSIlia Diachkov 
175b25b507cSIlia Diachkov std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue) {
176b25b507cSIlia Diachkov   const SPIRV::SymbolicOperand *Lookup =
177b25b507cSIlia Diachkov       SPIRV::lookupSymbolicOperandByCategoryAndValue(
178b25b507cSIlia Diachkov           SPIRV::OperandCategory::BuiltInOperand, BuiltInValue);
179b25b507cSIlia Diachkov 
180b25b507cSIlia Diachkov   if (Lookup)
181b25b507cSIlia Diachkov     return "__spirv_BuiltIn" + Lookup->Mnemonic.str();
182b25b507cSIlia Diachkov   return "UNKNOWN_BUILTIN";
183b25b507cSIlia Diachkov }
184b25b507cSIlia Diachkov 
185b25b507cSIlia Diachkov bool getSpirvBuiltInIdByName(llvm::StringRef Name,
186b25b507cSIlia Diachkov                              SPIRV::BuiltIn::BuiltIn &BI) {
187b25b507cSIlia Diachkov   const std::string Prefix = "__spirv_BuiltIn";
188395f9ce3SKazu Hirata   if (!Name.starts_with(Prefix))
189b25b507cSIlia Diachkov     return false;
190b25b507cSIlia Diachkov 
191b25b507cSIlia Diachkov   const SPIRV::SymbolicOperand *Lookup =
192b25b507cSIlia Diachkov       SPIRV::lookupSymbolicOperandByCategoryAndMnemonic(
193b25b507cSIlia Diachkov           SPIRV::OperandCategory::BuiltInOperand,
194b25b507cSIlia Diachkov           Name.drop_front(Prefix.length()));
195b25b507cSIlia Diachkov 
196b25b507cSIlia Diachkov   if (!Lookup)
197b25b507cSIlia Diachkov     return false;
198b25b507cSIlia Diachkov 
199b25b507cSIlia Diachkov   BI = static_cast<SPIRV::BuiltIn::BuiltIn>(Lookup->Value);
200b25b507cSIlia Diachkov   return true;
201b25b507cSIlia Diachkov }
202f61eb416SIlia Diachkov 
203f61eb416SIlia Diachkov std::string getExtInstSetName(SPIRV::InstructionSet::InstructionSet Set) {
204f61eb416SIlia Diachkov   switch (Set) {
205f61eb416SIlia Diachkov   case SPIRV::InstructionSet::OpenCL_std:
206f61eb416SIlia Diachkov     return "OpenCL.std";
207f61eb416SIlia Diachkov   case SPIRV::InstructionSet::GLSL_std_450:
208f61eb416SIlia Diachkov     return "GLSL.std.450";
209a4045299Sbwlodarcz   case SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100:
210a4045299Sbwlodarcz     return "NonSemantic.Shader.DebugInfo.100";
211f61eb416SIlia Diachkov   case SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax:
212f61eb416SIlia Diachkov     return "SPV_AMD_shader_trinary_minmax";
213f61eb416SIlia Diachkov   }
214f61eb416SIlia Diachkov   return "UNKNOWN_EXT_INST_SET";
215f61eb416SIlia Diachkov }
216f61eb416SIlia Diachkov 
217f61eb416SIlia Diachkov SPIRV::InstructionSet::InstructionSet
218f61eb416SIlia Diachkov getExtInstSetFromString(std::string SetName) {
219a4045299Sbwlodarcz   for (auto Set :
220a4045299Sbwlodarcz        {SPIRV::InstructionSet::GLSL_std_450, SPIRV::InstructionSet::OpenCL_std,
221a4045299Sbwlodarcz         SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100}) {
222f61eb416SIlia Diachkov     if (SetName == getExtInstSetName(Set))
223f61eb416SIlia Diachkov       return Set;
224f61eb416SIlia Diachkov   }
225f61eb416SIlia Diachkov   llvm_unreachable("UNKNOWN_EXT_INST_SET");
226f61eb416SIlia Diachkov }
227f61eb416SIlia Diachkov 
228f61eb416SIlia Diachkov std::string getExtInstName(SPIRV::InstructionSet::InstructionSet Set,
229f61eb416SIlia Diachkov                            uint32_t InstructionNumber) {
230f61eb416SIlia Diachkov   const SPIRV::ExtendedBuiltin *Lookup =
2314abe3f18SNatalie Chouinard       SPIRV::lookupExtendedBuiltinBySetAndNumber(Set, InstructionNumber);
232f61eb416SIlia Diachkov 
233f61eb416SIlia Diachkov   if (!Lookup)
234f61eb416SIlia Diachkov     return "UNKNOWN_EXT_INST";
235f61eb416SIlia Diachkov 
236f61eb416SIlia Diachkov   return Lookup->Name.str();
237f61eb416SIlia Diachkov }
238eab7d363SIlia Diachkov } // namespace llvm
239