1bdd1243dSDimitry Andric //===-- SPIRVBaseInfo.cpp - Top level SPIRV definitions ---------*- C++ -*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 9bdd1243dSDimitry Andric // This file contains the implementation for helper mnemonic lookup functions, 10bdd1243dSDimitry Andric // versioning/capabilities/extensions getters for symbolic/named operands used 11bdd1243dSDimitry Andric // in various SPIR-V instructions. 1281ad6265SDimitry Andric // 1381ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1481ad6265SDimitry Andric 1581ad6265SDimitry Andric #include "SPIRVBaseInfo.h" 16bdd1243dSDimitry Andric #include "llvm/ADT/ArrayRef.h" 17bdd1243dSDimitry Andric #include "llvm/ADT/StringRef.h" 1881ad6265SDimitry Andric 1981ad6265SDimitry Andric namespace llvm { 2081ad6265SDimitry Andric namespace SPIRV { 21bdd1243dSDimitry Andric struct SymbolicOperand { 22bdd1243dSDimitry Andric OperandCategory::OperandCategory Category; 23bdd1243dSDimitry Andric uint32_t Value; 24bdd1243dSDimitry Andric StringRef Mnemonic; 25bdd1243dSDimitry Andric uint32_t MinVersion; 26bdd1243dSDimitry Andric uint32_t MaxVersion; 2781ad6265SDimitry Andric }; 2881ad6265SDimitry Andric 29bdd1243dSDimitry Andric struct ExtensionEntry { 30bdd1243dSDimitry Andric OperandCategory::OperandCategory Category; 31bdd1243dSDimitry Andric uint32_t Value; 32bdd1243dSDimitry Andric Extension::Extension ReqExtension; 3381ad6265SDimitry Andric }; 3481ad6265SDimitry Andric 35bdd1243dSDimitry Andric struct CapabilityEntry { 36bdd1243dSDimitry Andric OperandCategory::OperandCategory Category; 37bdd1243dSDimitry Andric uint32_t Value; 38bdd1243dSDimitry Andric Capability::Capability ReqCapability; 3981ad6265SDimitry Andric }; 4081ad6265SDimitry Andric 41bdd1243dSDimitry Andric using namespace OperandCategory; 42bdd1243dSDimitry Andric using namespace Extension; 43bdd1243dSDimitry Andric using namespace Capability; 44bdd1243dSDimitry Andric using namespace InstructionSet; 45bdd1243dSDimitry Andric #define GET_SymbolicOperands_DECL 46bdd1243dSDimitry Andric #define GET_SymbolicOperands_IMPL 47bdd1243dSDimitry Andric #define GET_ExtensionEntries_DECL 48bdd1243dSDimitry Andric #define GET_ExtensionEntries_IMPL 49bdd1243dSDimitry Andric #define GET_CapabilityEntries_DECL 50bdd1243dSDimitry Andric #define GET_CapabilityEntries_IMPL 51bdd1243dSDimitry Andric #define GET_ExtendedBuiltins_DECL 52bdd1243dSDimitry Andric #define GET_ExtendedBuiltins_IMPL 53bdd1243dSDimitry Andric #include "SPIRVGenTables.inc" 5481ad6265SDimitry Andric } // namespace SPIRV 55bdd1243dSDimitry Andric 56bdd1243dSDimitry Andric std::string 57bdd1243dSDimitry Andric getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, 58bdd1243dSDimitry Andric int32_t Value) { 59bdd1243dSDimitry Andric const SPIRV::SymbolicOperand *Lookup = 60bdd1243dSDimitry Andric SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value); 61bdd1243dSDimitry Andric // Value that encodes just one enum value. 62bdd1243dSDimitry Andric if (Lookup) 63bdd1243dSDimitry Andric return Lookup->Mnemonic.str(); 64bdd1243dSDimitry Andric if (Category != SPIRV::OperandCategory::ImageOperandOperand && 65bdd1243dSDimitry Andric Category != SPIRV::OperandCategory::FPFastMathModeOperand && 66bdd1243dSDimitry Andric Category != SPIRV::OperandCategory::SelectionControlOperand && 67bdd1243dSDimitry Andric Category != SPIRV::OperandCategory::LoopControlOperand && 68bdd1243dSDimitry Andric Category != SPIRV::OperandCategory::FunctionControlOperand && 69bdd1243dSDimitry Andric Category != SPIRV::OperandCategory::MemorySemanticsOperand && 70bdd1243dSDimitry Andric Category != SPIRV::OperandCategory::MemoryOperandOperand && 71bdd1243dSDimitry Andric Category != SPIRV::OperandCategory::KernelProfilingInfoOperand) 72bdd1243dSDimitry Andric return "UNKNOWN"; 73bdd1243dSDimitry Andric // Value that encodes many enum values (one bit per enum value). 74bdd1243dSDimitry Andric std::string Name; 75bdd1243dSDimitry Andric std::string Separator; 76bdd1243dSDimitry Andric const SPIRV::SymbolicOperand *EnumValueInCategory = 77bdd1243dSDimitry Andric SPIRV::lookupSymbolicOperandByCategory(Category); 78bdd1243dSDimitry Andric 79bdd1243dSDimitry Andric while (EnumValueInCategory && EnumValueInCategory->Category == Category) { 80bdd1243dSDimitry Andric if ((EnumValueInCategory->Value != 0) && 81bdd1243dSDimitry Andric (Value & EnumValueInCategory->Value)) { 82bdd1243dSDimitry Andric Name += Separator + EnumValueInCategory->Mnemonic.str(); 83bdd1243dSDimitry Andric Separator = "|"; 84bdd1243dSDimitry Andric } 85bdd1243dSDimitry Andric ++EnumValueInCategory; 86bdd1243dSDimitry Andric } 87bdd1243dSDimitry Andric 88bdd1243dSDimitry Andric return Name; 89bdd1243dSDimitry Andric } 90bdd1243dSDimitry Andric 91*0fca6ea1SDimitry Andric VersionTuple 92bdd1243dSDimitry Andric getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category, 93bdd1243dSDimitry Andric uint32_t Value) { 94bdd1243dSDimitry Andric const SPIRV::SymbolicOperand *Lookup = 95bdd1243dSDimitry Andric SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value); 96bdd1243dSDimitry Andric 97bdd1243dSDimitry Andric if (Lookup) 98*0fca6ea1SDimitry Andric return VersionTuple(Lookup->MinVersion / 10, Lookup->MinVersion % 10); 99bdd1243dSDimitry Andric 100*0fca6ea1SDimitry Andric return VersionTuple(0); 101bdd1243dSDimitry Andric } 102bdd1243dSDimitry Andric 103*0fca6ea1SDimitry Andric VersionTuple 104bdd1243dSDimitry Andric getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, 105bdd1243dSDimitry Andric uint32_t Value) { 106bdd1243dSDimitry Andric const SPIRV::SymbolicOperand *Lookup = 107bdd1243dSDimitry Andric SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value); 108bdd1243dSDimitry Andric 109bdd1243dSDimitry Andric if (Lookup) 110*0fca6ea1SDimitry Andric return VersionTuple(Lookup->MaxVersion / 10, Lookup->MaxVersion % 10); 111bdd1243dSDimitry Andric 112*0fca6ea1SDimitry Andric return VersionTuple(); 113bdd1243dSDimitry Andric } 114bdd1243dSDimitry Andric 115bdd1243dSDimitry Andric CapabilityList 116bdd1243dSDimitry Andric getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category, 117bdd1243dSDimitry Andric uint32_t Value) { 118bdd1243dSDimitry Andric const SPIRV::CapabilityEntry *Capability = 119bdd1243dSDimitry Andric SPIRV::lookupCapabilityByCategoryAndValue(Category, Value); 120bdd1243dSDimitry Andric 121bdd1243dSDimitry Andric CapabilityList Capabilities; 122bdd1243dSDimitry Andric while (Capability && Capability->Category == Category && 123bdd1243dSDimitry Andric Capability->Value == Value) { 124bdd1243dSDimitry Andric Capabilities.push_back( 125bdd1243dSDimitry Andric static_cast<SPIRV::Capability::Capability>(Capability->ReqCapability)); 126bdd1243dSDimitry Andric ++Capability; 127bdd1243dSDimitry Andric } 128bdd1243dSDimitry Andric 129bdd1243dSDimitry Andric return Capabilities; 130bdd1243dSDimitry Andric } 131bdd1243dSDimitry Andric 1325f757f3fSDimitry Andric CapabilityList 1335f757f3fSDimitry Andric getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension) { 1345f757f3fSDimitry Andric const SPIRV::ExtensionEntry *Entry = 1355f757f3fSDimitry Andric SPIRV::lookupSymbolicOperandsEnabledByExtension( 1365f757f3fSDimitry Andric Extension, SPIRV::OperandCategory::CapabilityOperand); 1375f757f3fSDimitry Andric 1385f757f3fSDimitry Andric CapabilityList Capabilities; 1395f757f3fSDimitry Andric while (Entry && 1405f757f3fSDimitry Andric Entry->Category == SPIRV::OperandCategory::CapabilityOperand && 1415f757f3fSDimitry Andric Entry->ReqExtension == Extension) { 1425f757f3fSDimitry Andric Capabilities.push_back( 1435f757f3fSDimitry Andric static_cast<SPIRV::Capability::Capability>(Entry->Value)); 1445f757f3fSDimitry Andric ++Entry; 1455f757f3fSDimitry Andric } 1465f757f3fSDimitry Andric 1475f757f3fSDimitry Andric return Capabilities; 1485f757f3fSDimitry Andric } 1495f757f3fSDimitry Andric 150bdd1243dSDimitry Andric ExtensionList 151bdd1243dSDimitry Andric getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category, 152bdd1243dSDimitry Andric uint32_t Value) { 153bdd1243dSDimitry Andric const SPIRV::ExtensionEntry *Extension = 154bdd1243dSDimitry Andric SPIRV::lookupExtensionByCategoryAndValue(Category, Value); 155bdd1243dSDimitry Andric 156bdd1243dSDimitry Andric ExtensionList Extensions; 157bdd1243dSDimitry Andric while (Extension && Extension->Category == Category && 158bdd1243dSDimitry Andric Extension->Value == Value) { 159bdd1243dSDimitry Andric Extensions.push_back( 160bdd1243dSDimitry Andric static_cast<SPIRV::Extension::Extension>(Extension->ReqExtension)); 161bdd1243dSDimitry Andric ++Extension; 162bdd1243dSDimitry Andric } 163bdd1243dSDimitry Andric 164bdd1243dSDimitry Andric return Extensions; 165bdd1243dSDimitry Andric } 166bdd1243dSDimitry Andric 167bdd1243dSDimitry Andric std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue) { 168bdd1243dSDimitry Andric const SPIRV::SymbolicOperand *Lookup = 169bdd1243dSDimitry Andric SPIRV::lookupSymbolicOperandByCategoryAndValue( 170bdd1243dSDimitry Andric SPIRV::OperandCategory::BuiltInOperand, BuiltInValue); 171bdd1243dSDimitry Andric 172bdd1243dSDimitry Andric if (Lookup) 173bdd1243dSDimitry Andric return "__spirv_BuiltIn" + Lookup->Mnemonic.str(); 174bdd1243dSDimitry Andric return "UNKNOWN_BUILTIN"; 175bdd1243dSDimitry Andric } 176bdd1243dSDimitry Andric 177bdd1243dSDimitry Andric bool getSpirvBuiltInIdByName(llvm::StringRef Name, 178bdd1243dSDimitry Andric SPIRV::BuiltIn::BuiltIn &BI) { 179bdd1243dSDimitry Andric const std::string Prefix = "__spirv_BuiltIn"; 1805f757f3fSDimitry Andric if (!Name.starts_with(Prefix)) 181bdd1243dSDimitry Andric return false; 182bdd1243dSDimitry Andric 183bdd1243dSDimitry Andric const SPIRV::SymbolicOperand *Lookup = 184bdd1243dSDimitry Andric SPIRV::lookupSymbolicOperandByCategoryAndMnemonic( 185bdd1243dSDimitry Andric SPIRV::OperandCategory::BuiltInOperand, 186bdd1243dSDimitry Andric Name.drop_front(Prefix.length())); 187bdd1243dSDimitry Andric 188bdd1243dSDimitry Andric if (!Lookup) 189bdd1243dSDimitry Andric return false; 190bdd1243dSDimitry Andric 191bdd1243dSDimitry Andric BI = static_cast<SPIRV::BuiltIn::BuiltIn>(Lookup->Value); 192bdd1243dSDimitry Andric return true; 193bdd1243dSDimitry Andric } 194bdd1243dSDimitry Andric 195bdd1243dSDimitry Andric std::string getExtInstSetName(SPIRV::InstructionSet::InstructionSet Set) { 196bdd1243dSDimitry Andric switch (Set) { 197bdd1243dSDimitry Andric case SPIRV::InstructionSet::OpenCL_std: 198bdd1243dSDimitry Andric return "OpenCL.std"; 199bdd1243dSDimitry Andric case SPIRV::InstructionSet::GLSL_std_450: 200bdd1243dSDimitry Andric return "GLSL.std.450"; 201*0fca6ea1SDimitry Andric case SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100: 202*0fca6ea1SDimitry Andric return "NonSemantic.Shader.DebugInfo.100"; 203bdd1243dSDimitry Andric case SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax: 204bdd1243dSDimitry Andric return "SPV_AMD_shader_trinary_minmax"; 205bdd1243dSDimitry Andric } 206bdd1243dSDimitry Andric return "UNKNOWN_EXT_INST_SET"; 207bdd1243dSDimitry Andric } 208bdd1243dSDimitry Andric 209bdd1243dSDimitry Andric SPIRV::InstructionSet::InstructionSet 210bdd1243dSDimitry Andric getExtInstSetFromString(std::string SetName) { 211*0fca6ea1SDimitry Andric for (auto Set : 212*0fca6ea1SDimitry Andric {SPIRV::InstructionSet::GLSL_std_450, SPIRV::InstructionSet::OpenCL_std, 213*0fca6ea1SDimitry Andric SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100}) { 214bdd1243dSDimitry Andric if (SetName == getExtInstSetName(Set)) 215bdd1243dSDimitry Andric return Set; 216bdd1243dSDimitry Andric } 217bdd1243dSDimitry Andric llvm_unreachable("UNKNOWN_EXT_INST_SET"); 218bdd1243dSDimitry Andric } 219bdd1243dSDimitry Andric 220bdd1243dSDimitry Andric std::string getExtInstName(SPIRV::InstructionSet::InstructionSet Set, 221bdd1243dSDimitry Andric uint32_t InstructionNumber) { 222bdd1243dSDimitry Andric const SPIRV::ExtendedBuiltin *Lookup = 2235f757f3fSDimitry Andric SPIRV::lookupExtendedBuiltinBySetAndNumber(Set, InstructionNumber); 224bdd1243dSDimitry Andric 225bdd1243dSDimitry Andric if (!Lookup) 226bdd1243dSDimitry Andric return "UNKNOWN_EXT_INST"; 227bdd1243dSDimitry Andric 228bdd1243dSDimitry Andric return Lookup->Name.str(); 229bdd1243dSDimitry Andric } 23081ad6265SDimitry Andric } // namespace llvm 231