266 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the implementation for helper mnemonic lookup functions,10// versioning/capabilities/extensions getters for symbolic/named operands used11// 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 19namespace llvm {20namespace SPIRV {21struct SymbolicOperand {22 OperandCategory::OperandCategory Category;23 uint32_t Value;24 StringRef Mnemonic;25 uint32_t MinVersion;26 uint32_t MaxVersion;27};28 29struct ExtensionEntry {30 OperandCategory::OperandCategory Category;31 uint32_t Value;32 Extension::Extension ReqExtension;33};34 35struct CapabilityEntry {36 OperandCategory::OperandCategory Category;37 uint32_t Value;38 Capability::Capability ReqCapability;39};40 41struct EnvironmentEntry {42 OperandCategory::OperandCategory Category;43 uint32_t Value;44 Environment::Environment AllowedEnvironment;45};46 47using namespace OperandCategory;48using namespace Extension;49using namespace Environment;50using namespace Capability;51using namespace InstructionSet;52#define GET_SymbolicOperands_DECL53#define GET_SymbolicOperands_IMPL54#define GET_ExtensionEntries_DECL55#define GET_ExtensionEntries_IMPL56#define GET_CapabilityEntries_DECL57#define GET_CapabilityEntries_IMPL58#define GET_EnvironmentEntries_DECL59#define GET_EnvironmentEntries_IMPL60#define GET_ExtendedBuiltins_DECL61#define GET_ExtendedBuiltins_IMPL62#include "SPIRVGenTables.inc"63} // namespace SPIRV64 65std::string66getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category,67 int32_t Value) {68 const SPIRV::SymbolicOperand *Lookup =69 SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value);70 // Value that encodes just one enum value.71 if (Lookup)72 return Lookup->Mnemonic.str();73 if (Category != SPIRV::OperandCategory::ImageOperandOperand &&74 Category != SPIRV::OperandCategory::FPFastMathModeOperand &&75 Category != SPIRV::OperandCategory::SelectionControlOperand &&76 Category != SPIRV::OperandCategory::LoopControlOperand &&77 Category != SPIRV::OperandCategory::FunctionControlOperand &&78 Category != SPIRV::OperandCategory::MemorySemanticsOperand &&79 Category != SPIRV::OperandCategory::MemoryOperandOperand &&80 Category != SPIRV::OperandCategory::KernelProfilingInfoOperand &&81 Category != SPIRV::OperandCategory::SpecConstantOpOperandsOperand)82 return "UNKNOWN";83 // Value that encodes many enum values (one bit per enum value).84 std::string Name;85 std::string Separator;86 const SPIRV::SymbolicOperand *EnumValueInCategory =87 SPIRV::lookupSymbolicOperandByCategory(Category);88 89 auto TableEnd = ArrayRef(SPIRV::SymbolicOperands).end();90 while (EnumValueInCategory && EnumValueInCategory->Category == Category) {91 if ((EnumValueInCategory->Value != 0) &&92 (Value & EnumValueInCategory->Value)) {93 Name += Separator + EnumValueInCategory->Mnemonic.str();94 Separator = "|";95 }96 if (++EnumValueInCategory == TableEnd)97 break;98 }99 100 return Name;101}102 103VersionTuple104getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category,105 uint32_t Value) {106 const SPIRV::SymbolicOperand *Lookup =107 SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value);108 109 if (Lookup)110 return VersionTuple(Lookup->MinVersion / 10, Lookup->MinVersion % 10);111 112 return VersionTuple(0);113}114 115VersionTuple116getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category,117 uint32_t Value) {118 const SPIRV::SymbolicOperand *Lookup =119 SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value);120 121 if (Lookup)122 return VersionTuple(Lookup->MaxVersion / 10, Lookup->MaxVersion % 10);123 124 return VersionTuple();125}126 127CapabilityList128getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category,129 uint32_t Value) {130 CapabilityList Capabilities;131 const SPIRV::CapabilityEntry *Capability =132 SPIRV::lookupCapabilityByCategoryAndValue(Category, Value);133 auto TableEnd = ArrayRef(SPIRV::CapabilityEntries).end();134 while (Capability && Capability->Category == Category &&135 Capability->Value == Value) {136 Capabilities.push_back(137 static_cast<SPIRV::Capability::Capability>(Capability->ReqCapability));138 if (++Capability == TableEnd)139 break;140 }141 142 return Capabilities;143}144 145EnvironmentList getSymbolicOperandAllowedEnvironments(146 SPIRV::OperandCategory::OperandCategory Category, uint32_t Value) {147 EnvironmentList Environments;148 const SPIRV::EnvironmentEntry *Environment =149 SPIRV::lookupEnvironmentByCategoryAndValue(Category, Value);150 auto TableEnd = ArrayRef(SPIRV::EnvironmentEntries).end();151 while (Environment && Environment->Category == Category &&152 Environment->Value == Value) {153 Environments.push_back(static_cast<SPIRV::Environment::Environment>(154 Environment->AllowedEnvironment));155 if (++Environment == TableEnd)156 break;157 }158 159 return Environments;160}161 162CapabilityList163getCapabilitiesEnabledByExtension(SPIRV::Extension::Extension Extension) {164 const SPIRV::ExtensionEntry *Entry =165 SPIRV::lookupSymbolicOperandsEnabledByExtension(166 Extension, SPIRV::OperandCategory::CapabilityOperand);167 168 CapabilityList Capabilities;169 auto TableEnd = ArrayRef(SPIRV::ExtensionEntries).end();170 while (Entry &&171 Entry->Category == SPIRV::OperandCategory::CapabilityOperand) {172 // Some capabilities' codes might go not in order.173 if (Entry->ReqExtension == Extension)174 Capabilities.push_back(175 static_cast<SPIRV::Capability::Capability>(Entry->Value));176 if (++Entry == TableEnd)177 break;178 }179 180 return Capabilities;181}182 183ExtensionList184getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category,185 uint32_t Value) {186 const SPIRV::ExtensionEntry *Extension =187 SPIRV::lookupExtensionByCategoryAndValue(Category, Value);188 189 ExtensionList Extensions;190 auto TableEnd = ArrayRef(SPIRV::ExtensionEntries).end();191 while (Extension && Extension->Category == Category &&192 Extension->Value == Value) {193 Extensions.push_back(194 static_cast<SPIRV::Extension::Extension>(Extension->ReqExtension));195 if (++Extension == TableEnd)196 break;197 }198 199 return Extensions;200}201 202std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue) {203 const SPIRV::SymbolicOperand *Lookup =204 SPIRV::lookupSymbolicOperandByCategoryAndValue(205 SPIRV::OperandCategory::BuiltInOperand, BuiltInValue);206 207 if (Lookup)208 return "__spirv_BuiltIn" + Lookup->Mnemonic.str();209 return "UNKNOWN_BUILTIN";210}211 212bool getSpirvBuiltInIdByName(llvm::StringRef Name,213 SPIRV::BuiltIn::BuiltIn &BI) {214 const std::string Prefix = "__spirv_BuiltIn";215 if (!Name.starts_with(Prefix))216 return false;217 218 const SPIRV::SymbolicOperand *Lookup =219 SPIRV::lookupSymbolicOperandByCategoryAndMnemonic(220 SPIRV::OperandCategory::BuiltInOperand,221 Name.drop_front(Prefix.length()));222 223 if (!Lookup)224 return false;225 226 BI = static_cast<SPIRV::BuiltIn::BuiltIn>(Lookup->Value);227 return true;228}229 230std::string getExtInstSetName(SPIRV::InstructionSet::InstructionSet Set) {231 switch (Set) {232 case SPIRV::InstructionSet::OpenCL_std:233 return "OpenCL.std";234 case SPIRV::InstructionSet::GLSL_std_450:235 return "GLSL.std.450";236 case SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100:237 return "NonSemantic.Shader.DebugInfo.100";238 case SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax:239 return "SPV_AMD_shader_trinary_minmax";240 }241 return "UNKNOWN_EXT_INST_SET";242}243 244SPIRV::InstructionSet::InstructionSet245getExtInstSetFromString(std::string SetName) {246 for (auto Set :247 {SPIRV::InstructionSet::GLSL_std_450, SPIRV::InstructionSet::OpenCL_std,248 SPIRV::InstructionSet::NonSemantic_Shader_DebugInfo_100}) {249 if (SetName == getExtInstSetName(Set))250 return Set;251 }252 llvm_unreachable("UNKNOWN_EXT_INST_SET");253}254 255std::string getExtInstName(SPIRV::InstructionSet::InstructionSet Set,256 uint32_t InstructionNumber) {257 const SPIRV::ExtendedBuiltin *Lookup =258 SPIRV::lookupExtendedBuiltinBySetAndNumber(Set, InstructionNumber);259 260 if (!Lookup)261 return "UNKNOWN_EXT_INST";262 263 return Lookup->Name.str();264}265} // namespace llvm266