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