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