1*bdd1243dSDimitry 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 // 9*bdd1243dSDimitry Andric // This file contains the implementation for helper mnemonic lookup functions, 10*bdd1243dSDimitry Andric // versioning/capabilities/extensions getters for symbolic/named operands used 11*bdd1243dSDimitry Andric // in various SPIR-V instructions. 1281ad6265SDimitry Andric // 1381ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1481ad6265SDimitry Andric 1581ad6265SDimitry Andric #include "SPIRVBaseInfo.h" 16*bdd1243dSDimitry Andric #include "llvm/ADT/ArrayRef.h" 17*bdd1243dSDimitry Andric #include "llvm/ADT/StringRef.h" 1881ad6265SDimitry Andric 1981ad6265SDimitry Andric namespace llvm { 2081ad6265SDimitry Andric namespace SPIRV { 21*bdd1243dSDimitry Andric struct SymbolicOperand { 22*bdd1243dSDimitry Andric OperandCategory::OperandCategory Category; 23*bdd1243dSDimitry Andric uint32_t Value; 24*bdd1243dSDimitry Andric StringRef Mnemonic; 25*bdd1243dSDimitry Andric uint32_t MinVersion; 26*bdd1243dSDimitry Andric uint32_t MaxVersion; 2781ad6265SDimitry Andric }; 2881ad6265SDimitry Andric 29*bdd1243dSDimitry Andric struct ExtensionEntry { 30*bdd1243dSDimitry Andric OperandCategory::OperandCategory Category; 31*bdd1243dSDimitry Andric uint32_t Value; 32*bdd1243dSDimitry Andric Extension::Extension ReqExtension; 3381ad6265SDimitry Andric }; 3481ad6265SDimitry Andric 35*bdd1243dSDimitry Andric struct CapabilityEntry { 36*bdd1243dSDimitry Andric OperandCategory::OperandCategory Category; 37*bdd1243dSDimitry Andric uint32_t Value; 38*bdd1243dSDimitry Andric Capability::Capability ReqCapability; 3981ad6265SDimitry Andric }; 4081ad6265SDimitry Andric 41*bdd1243dSDimitry Andric using namespace OperandCategory; 42*bdd1243dSDimitry Andric using namespace Extension; 43*bdd1243dSDimitry Andric using namespace Capability; 44*bdd1243dSDimitry Andric using namespace InstructionSet; 45*bdd1243dSDimitry Andric #define GET_SymbolicOperands_DECL 46*bdd1243dSDimitry Andric #define GET_SymbolicOperands_IMPL 47*bdd1243dSDimitry Andric #define GET_ExtensionEntries_DECL 48*bdd1243dSDimitry Andric #define GET_ExtensionEntries_IMPL 49*bdd1243dSDimitry Andric #define GET_CapabilityEntries_DECL 50*bdd1243dSDimitry Andric #define GET_CapabilityEntries_IMPL 51*bdd1243dSDimitry Andric #define GET_ExtendedBuiltins_DECL 52*bdd1243dSDimitry Andric #define GET_ExtendedBuiltins_IMPL 53*bdd1243dSDimitry Andric #include "SPIRVGenTables.inc" 5481ad6265SDimitry Andric } // namespace SPIRV 55*bdd1243dSDimitry Andric 56*bdd1243dSDimitry Andric std::string 57*bdd1243dSDimitry Andric getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, 58*bdd1243dSDimitry Andric int32_t Value) { 59*bdd1243dSDimitry Andric const SPIRV::SymbolicOperand *Lookup = 60*bdd1243dSDimitry Andric SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value); 61*bdd1243dSDimitry Andric // Value that encodes just one enum value. 62*bdd1243dSDimitry Andric if (Lookup) 63*bdd1243dSDimitry Andric return Lookup->Mnemonic.str(); 64*bdd1243dSDimitry Andric if (Category != SPIRV::OperandCategory::ImageOperandOperand && 65*bdd1243dSDimitry Andric Category != SPIRV::OperandCategory::FPFastMathModeOperand && 66*bdd1243dSDimitry Andric Category != SPIRV::OperandCategory::SelectionControlOperand && 67*bdd1243dSDimitry Andric Category != SPIRV::OperandCategory::LoopControlOperand && 68*bdd1243dSDimitry Andric Category != SPIRV::OperandCategory::FunctionControlOperand && 69*bdd1243dSDimitry Andric Category != SPIRV::OperandCategory::MemorySemanticsOperand && 70*bdd1243dSDimitry Andric Category != SPIRV::OperandCategory::MemoryOperandOperand && 71*bdd1243dSDimitry Andric Category != SPIRV::OperandCategory::KernelProfilingInfoOperand) 72*bdd1243dSDimitry Andric return "UNKNOWN"; 73*bdd1243dSDimitry Andric // Value that encodes many enum values (one bit per enum value). 74*bdd1243dSDimitry Andric std::string Name; 75*bdd1243dSDimitry Andric std::string Separator; 76*bdd1243dSDimitry Andric const SPIRV::SymbolicOperand *EnumValueInCategory = 77*bdd1243dSDimitry Andric SPIRV::lookupSymbolicOperandByCategory(Category); 78*bdd1243dSDimitry Andric 79*bdd1243dSDimitry Andric while (EnumValueInCategory && EnumValueInCategory->Category == Category) { 80*bdd1243dSDimitry Andric if ((EnumValueInCategory->Value != 0) && 81*bdd1243dSDimitry Andric (Value & EnumValueInCategory->Value)) { 82*bdd1243dSDimitry Andric Name += Separator + EnumValueInCategory->Mnemonic.str(); 83*bdd1243dSDimitry Andric Separator = "|"; 84*bdd1243dSDimitry Andric } 85*bdd1243dSDimitry Andric ++EnumValueInCategory; 86*bdd1243dSDimitry Andric } 87*bdd1243dSDimitry Andric 88*bdd1243dSDimitry Andric return Name; 89*bdd1243dSDimitry Andric } 90*bdd1243dSDimitry Andric 91*bdd1243dSDimitry Andric uint32_t 92*bdd1243dSDimitry Andric getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category, 93*bdd1243dSDimitry Andric uint32_t Value) { 94*bdd1243dSDimitry Andric const SPIRV::SymbolicOperand *Lookup = 95*bdd1243dSDimitry Andric SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value); 96*bdd1243dSDimitry Andric 97*bdd1243dSDimitry Andric if (Lookup) 98*bdd1243dSDimitry Andric return Lookup->MinVersion; 99*bdd1243dSDimitry Andric 100*bdd1243dSDimitry Andric return 0; 101*bdd1243dSDimitry Andric } 102*bdd1243dSDimitry Andric 103*bdd1243dSDimitry Andric uint32_t 104*bdd1243dSDimitry Andric getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, 105*bdd1243dSDimitry Andric uint32_t Value) { 106*bdd1243dSDimitry Andric const SPIRV::SymbolicOperand *Lookup = 107*bdd1243dSDimitry Andric SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value); 108*bdd1243dSDimitry Andric 109*bdd1243dSDimitry Andric if (Lookup) 110*bdd1243dSDimitry Andric return Lookup->MaxVersion; 111*bdd1243dSDimitry Andric 112*bdd1243dSDimitry Andric return 0; 113*bdd1243dSDimitry Andric } 114*bdd1243dSDimitry Andric 115*bdd1243dSDimitry Andric CapabilityList 116*bdd1243dSDimitry Andric getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category, 117*bdd1243dSDimitry Andric uint32_t Value) { 118*bdd1243dSDimitry Andric const SPIRV::CapabilityEntry *Capability = 119*bdd1243dSDimitry Andric SPIRV::lookupCapabilityByCategoryAndValue(Category, Value); 120*bdd1243dSDimitry Andric 121*bdd1243dSDimitry Andric CapabilityList Capabilities; 122*bdd1243dSDimitry Andric while (Capability && Capability->Category == Category && 123*bdd1243dSDimitry Andric Capability->Value == Value) { 124*bdd1243dSDimitry Andric Capabilities.push_back( 125*bdd1243dSDimitry Andric static_cast<SPIRV::Capability::Capability>(Capability->ReqCapability)); 126*bdd1243dSDimitry Andric ++Capability; 127*bdd1243dSDimitry Andric } 128*bdd1243dSDimitry Andric 129*bdd1243dSDimitry Andric return Capabilities; 130*bdd1243dSDimitry Andric } 131*bdd1243dSDimitry Andric 132*bdd1243dSDimitry Andric ExtensionList 133*bdd1243dSDimitry Andric getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category, 134*bdd1243dSDimitry Andric uint32_t Value) { 135*bdd1243dSDimitry Andric const SPIRV::ExtensionEntry *Extension = 136*bdd1243dSDimitry Andric SPIRV::lookupExtensionByCategoryAndValue(Category, Value); 137*bdd1243dSDimitry Andric 138*bdd1243dSDimitry Andric ExtensionList Extensions; 139*bdd1243dSDimitry Andric while (Extension && Extension->Category == Category && 140*bdd1243dSDimitry Andric Extension->Value == Value) { 141*bdd1243dSDimitry Andric Extensions.push_back( 142*bdd1243dSDimitry Andric static_cast<SPIRV::Extension::Extension>(Extension->ReqExtension)); 143*bdd1243dSDimitry Andric ++Extension; 144*bdd1243dSDimitry Andric } 145*bdd1243dSDimitry Andric 146*bdd1243dSDimitry Andric return Extensions; 147*bdd1243dSDimitry Andric } 148*bdd1243dSDimitry Andric 149*bdd1243dSDimitry Andric std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue) { 150*bdd1243dSDimitry Andric const SPIRV::SymbolicOperand *Lookup = 151*bdd1243dSDimitry Andric SPIRV::lookupSymbolicOperandByCategoryAndValue( 152*bdd1243dSDimitry Andric SPIRV::OperandCategory::BuiltInOperand, BuiltInValue); 153*bdd1243dSDimitry Andric 154*bdd1243dSDimitry Andric if (Lookup) 155*bdd1243dSDimitry Andric return "__spirv_BuiltIn" + Lookup->Mnemonic.str(); 156*bdd1243dSDimitry Andric return "UNKNOWN_BUILTIN"; 157*bdd1243dSDimitry Andric } 158*bdd1243dSDimitry Andric 159*bdd1243dSDimitry Andric bool getSpirvBuiltInIdByName(llvm::StringRef Name, 160*bdd1243dSDimitry Andric SPIRV::BuiltIn::BuiltIn &BI) { 161*bdd1243dSDimitry Andric const std::string Prefix = "__spirv_BuiltIn"; 162*bdd1243dSDimitry Andric if (!Name.startswith(Prefix)) 163*bdd1243dSDimitry Andric return false; 164*bdd1243dSDimitry Andric 165*bdd1243dSDimitry Andric const SPIRV::SymbolicOperand *Lookup = 166*bdd1243dSDimitry Andric SPIRV::lookupSymbolicOperandByCategoryAndMnemonic( 167*bdd1243dSDimitry Andric SPIRV::OperandCategory::BuiltInOperand, 168*bdd1243dSDimitry Andric Name.drop_front(Prefix.length())); 169*bdd1243dSDimitry Andric 170*bdd1243dSDimitry Andric if (!Lookup) 171*bdd1243dSDimitry Andric return false; 172*bdd1243dSDimitry Andric 173*bdd1243dSDimitry Andric BI = static_cast<SPIRV::BuiltIn::BuiltIn>(Lookup->Value); 174*bdd1243dSDimitry Andric return true; 175*bdd1243dSDimitry Andric } 176*bdd1243dSDimitry Andric 177*bdd1243dSDimitry Andric std::string getExtInstSetName(SPIRV::InstructionSet::InstructionSet Set) { 178*bdd1243dSDimitry Andric switch (Set) { 179*bdd1243dSDimitry Andric case SPIRV::InstructionSet::OpenCL_std: 180*bdd1243dSDimitry Andric return "OpenCL.std"; 181*bdd1243dSDimitry Andric case SPIRV::InstructionSet::GLSL_std_450: 182*bdd1243dSDimitry Andric return "GLSL.std.450"; 183*bdd1243dSDimitry Andric case SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax: 184*bdd1243dSDimitry Andric return "SPV_AMD_shader_trinary_minmax"; 185*bdd1243dSDimitry Andric } 186*bdd1243dSDimitry Andric return "UNKNOWN_EXT_INST_SET"; 187*bdd1243dSDimitry Andric } 188*bdd1243dSDimitry Andric 189*bdd1243dSDimitry Andric SPIRV::InstructionSet::InstructionSet 190*bdd1243dSDimitry Andric getExtInstSetFromString(std::string SetName) { 191*bdd1243dSDimitry Andric for (auto Set : {SPIRV::InstructionSet::GLSL_std_450, 192*bdd1243dSDimitry Andric SPIRV::InstructionSet::OpenCL_std}) { 193*bdd1243dSDimitry Andric if (SetName == getExtInstSetName(Set)) 194*bdd1243dSDimitry Andric return Set; 195*bdd1243dSDimitry Andric } 196*bdd1243dSDimitry Andric llvm_unreachable("UNKNOWN_EXT_INST_SET"); 197*bdd1243dSDimitry Andric } 198*bdd1243dSDimitry Andric 199*bdd1243dSDimitry Andric std::string getExtInstName(SPIRV::InstructionSet::InstructionSet Set, 200*bdd1243dSDimitry Andric uint32_t InstructionNumber) { 201*bdd1243dSDimitry Andric const SPIRV::ExtendedBuiltin *Lookup = 202*bdd1243dSDimitry Andric SPIRV::lookupExtendedBuiltinBySetAndNumber( 203*bdd1243dSDimitry Andric SPIRV::InstructionSet::OpenCL_std, InstructionNumber); 204*bdd1243dSDimitry Andric 205*bdd1243dSDimitry Andric if (!Lookup) 206*bdd1243dSDimitry Andric return "UNKNOWN_EXT_INST"; 207*bdd1243dSDimitry Andric 208*bdd1243dSDimitry Andric return Lookup->Name.str(); 209*bdd1243dSDimitry Andric } 21081ad6265SDimitry Andric } // namespace llvm 211