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 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 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 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 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 CapabilityList 133 getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension) { 134 const SPIRV::ExtensionEntry *Entry = 135 SPIRV::lookupSymbolicOperandsEnabledByExtension( 136 Extension, SPIRV::OperandCategory::CapabilityOperand); 137 138 CapabilityList Capabilities; 139 while (Entry && 140 Entry->Category == SPIRV::OperandCategory::CapabilityOperand && 141 Entry->ReqExtension == Extension) { 142 Capabilities.push_back( 143 static_cast<SPIRV::Capability::Capability>(Entry->Value)); 144 ++Entry; 145 } 146 147 return Capabilities; 148 } 149 150 ExtensionList 151 getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category, 152 uint32_t Value) { 153 const SPIRV::ExtensionEntry *Extension = 154 SPIRV::lookupExtensionByCategoryAndValue(Category, Value); 155 156 ExtensionList Extensions; 157 while (Extension && Extension->Category == Category && 158 Extension->Value == Value) { 159 Extensions.push_back( 160 static_cast<SPIRV::Extension::Extension>(Extension->ReqExtension)); 161 ++Extension; 162 } 163 164 return Extensions; 165 } 166 167 std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue) { 168 const SPIRV::SymbolicOperand *Lookup = 169 SPIRV::lookupSymbolicOperandByCategoryAndValue( 170 SPIRV::OperandCategory::BuiltInOperand, BuiltInValue); 171 172 if (Lookup) 173 return "__spirv_BuiltIn" + Lookup->Mnemonic.str(); 174 return "UNKNOWN_BUILTIN"; 175 } 176 177 bool getSpirvBuiltInIdByName(llvm::StringRef Name, 178 SPIRV::BuiltIn::BuiltIn &BI) { 179 const std::string Prefix = "__spirv_BuiltIn"; 180 if (!Name.starts_with(Prefix)) 181 return false; 182 183 const SPIRV::SymbolicOperand *Lookup = 184 SPIRV::lookupSymbolicOperandByCategoryAndMnemonic( 185 SPIRV::OperandCategory::BuiltInOperand, 186 Name.drop_front(Prefix.length())); 187 188 if (!Lookup) 189 return false; 190 191 BI = static_cast<SPIRV::BuiltIn::BuiltIn>(Lookup->Value); 192 return true; 193 } 194 195 std::string getExtInstSetName(SPIRV::InstructionSet::InstructionSet Set) { 196 switch (Set) { 197 case SPIRV::InstructionSet::OpenCL_std: 198 return "OpenCL.std"; 199 case SPIRV::InstructionSet::GLSL_std_450: 200 return "GLSL.std.450"; 201 case SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax: 202 return "SPV_AMD_shader_trinary_minmax"; 203 } 204 return "UNKNOWN_EXT_INST_SET"; 205 } 206 207 SPIRV::InstructionSet::InstructionSet 208 getExtInstSetFromString(std::string SetName) { 209 for (auto Set : {SPIRV::InstructionSet::GLSL_std_450, 210 SPIRV::InstructionSet::OpenCL_std}) { 211 if (SetName == getExtInstSetName(Set)) 212 return Set; 213 } 214 llvm_unreachable("UNKNOWN_EXT_INST_SET"); 215 } 216 217 std::string getExtInstName(SPIRV::InstructionSet::InstructionSet Set, 218 uint32_t InstructionNumber) { 219 const SPIRV::ExtendedBuiltin *Lookup = 220 SPIRV::lookupExtendedBuiltinBySetAndNumber(Set, InstructionNumber); 221 222 if (!Lookup) 223 return "UNKNOWN_EXT_INST"; 224 225 return Lookup->Name.str(); 226 } 227 } // namespace llvm 228