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 91bdd1243dSDimitry Andric uint32_t 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) 98bdd1243dSDimitry Andric return Lookup->MinVersion; 99bdd1243dSDimitry Andric 100bdd1243dSDimitry Andric return 0; 101bdd1243dSDimitry Andric } 102bdd1243dSDimitry Andric 103bdd1243dSDimitry Andric uint32_t 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) 110bdd1243dSDimitry Andric return Lookup->MaxVersion; 111bdd1243dSDimitry Andric 112bdd1243dSDimitry Andric return 0; 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 132*5f757f3fSDimitry Andric CapabilityList 133*5f757f3fSDimitry Andric getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension) { 134*5f757f3fSDimitry Andric const SPIRV::ExtensionEntry *Entry = 135*5f757f3fSDimitry Andric SPIRV::lookupSymbolicOperandsEnabledByExtension( 136*5f757f3fSDimitry Andric Extension, SPIRV::OperandCategory::CapabilityOperand); 137*5f757f3fSDimitry Andric 138*5f757f3fSDimitry Andric CapabilityList Capabilities; 139*5f757f3fSDimitry Andric while (Entry && 140*5f757f3fSDimitry Andric Entry->Category == SPIRV::OperandCategory::CapabilityOperand && 141*5f757f3fSDimitry Andric Entry->ReqExtension == Extension) { 142*5f757f3fSDimitry Andric Capabilities.push_back( 143*5f757f3fSDimitry Andric static_cast<SPIRV::Capability::Capability>(Entry->Value)); 144*5f757f3fSDimitry Andric ++Entry; 145*5f757f3fSDimitry Andric } 146*5f757f3fSDimitry Andric 147*5f757f3fSDimitry Andric return Capabilities; 148*5f757f3fSDimitry Andric } 149*5f757f3fSDimitry 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"; 180*5f757f3fSDimitry 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"; 201bdd1243dSDimitry Andric case SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax: 202bdd1243dSDimitry Andric return "SPV_AMD_shader_trinary_minmax"; 203bdd1243dSDimitry Andric } 204bdd1243dSDimitry Andric return "UNKNOWN_EXT_INST_SET"; 205bdd1243dSDimitry Andric } 206bdd1243dSDimitry Andric 207bdd1243dSDimitry Andric SPIRV::InstructionSet::InstructionSet 208bdd1243dSDimitry Andric getExtInstSetFromString(std::string SetName) { 209bdd1243dSDimitry Andric for (auto Set : {SPIRV::InstructionSet::GLSL_std_450, 210bdd1243dSDimitry Andric SPIRV::InstructionSet::OpenCL_std}) { 211bdd1243dSDimitry Andric if (SetName == getExtInstSetName(Set)) 212bdd1243dSDimitry Andric return Set; 213bdd1243dSDimitry Andric } 214bdd1243dSDimitry Andric llvm_unreachable("UNKNOWN_EXT_INST_SET"); 215bdd1243dSDimitry Andric } 216bdd1243dSDimitry Andric 217bdd1243dSDimitry Andric std::string getExtInstName(SPIRV::InstructionSet::InstructionSet Set, 218bdd1243dSDimitry Andric uint32_t InstructionNumber) { 219bdd1243dSDimitry Andric const SPIRV::ExtendedBuiltin *Lookup = 220*5f757f3fSDimitry Andric SPIRV::lookupExtendedBuiltinBySetAndNumber(Set, InstructionNumber); 221bdd1243dSDimitry Andric 222bdd1243dSDimitry Andric if (!Lookup) 223bdd1243dSDimitry Andric return "UNKNOWN_EXT_INST"; 224bdd1243dSDimitry Andric 225bdd1243dSDimitry Andric return Lookup->Name.str(); 226bdd1243dSDimitry Andric } 22781ad6265SDimitry Andric } // namespace llvm 228