| //===-- SPIRVBaseInfo.cpp - Top level SPIRV definitions ---------*- C++ -*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file contains the implementation for helper mnemonic lookup functions, | |
| // versioning/capabilities/extensions getters for symbolic/named operands used | |
| // in various SPIR-V instructions. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "SPIRVBaseInfo.h" | |
| #include "llvm/ADT/ArrayRef.h" | |
| #include "llvm/ADT/StringRef.h" | |
| namespace llvm { | |
| namespace SPIRV { | |
| struct SymbolicOperand { | |
| OperandCategory::OperandCategory Category; | |
| uint32_t Value; | |
| StringRef Mnemonic; | |
| uint32_t MinVersion; | |
| uint32_t MaxVersion; | |
| }; | |
| struct ExtensionEntry { | |
| OperandCategory::OperandCategory Category; | |
| uint32_t Value; | |
| Extension::Extension ReqExtension; | |
| }; | |
| struct CapabilityEntry { | |
| OperandCategory::OperandCategory Category; | |
| uint32_t Value; | |
| Capability::Capability ReqCapability; | |
| }; | |
| using namespace OperandCategory; | |
| using namespace Extension; | |
| using namespace Capability; | |
| using namespace InstructionSet; | |
| #define GET_SymbolicOperands_DECL | |
| #define GET_SymbolicOperands_IMPL | |
| #define GET_ExtensionEntries_DECL | |
| #define GET_ExtensionEntries_IMPL | |
| #define GET_CapabilityEntries_DECL | |
| #define GET_CapabilityEntries_IMPL | |
| #define GET_ExtendedBuiltins_DECL | |
| #define GET_ExtendedBuiltins_IMPL | |
| #include "SPIRVGenTables.inc" | |
| } // namespace SPIRV | |
| std::string | |
| getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, | |
| int32_t Value) { | |
| const SPIRV::SymbolicOperand *Lookup = | |
| SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value); | |
| // Value that encodes just one enum value. | |
| if (Lookup) | |
| return Lookup->Mnemonic.str(); | |
| if (Category != SPIRV::OperandCategory::ImageOperandOperand && | |
| Category != SPIRV::OperandCategory::FPFastMathModeOperand && | |
| Category != SPIRV::OperandCategory::SelectionControlOperand && | |
| Category != SPIRV::OperandCategory::LoopControlOperand && | |
| Category != SPIRV::OperandCategory::FunctionControlOperand && | |
| Category != SPIRV::OperandCategory::MemorySemanticsOperand && | |
| Category != SPIRV::OperandCategory::MemoryOperandOperand && | |
| Category != SPIRV::OperandCategory::KernelProfilingInfoOperand) | |
| return "UNKNOWN"; | |
| // Value that encodes many enum values (one bit per enum value). | |
| std::string Name; | |
| std::string Separator; | |
| const SPIRV::SymbolicOperand *EnumValueInCategory = | |
| SPIRV::lookupSymbolicOperandByCategory(Category); | |
| while (EnumValueInCategory && EnumValueInCategory->Category == Category) { | |
| if ((EnumValueInCategory->Value != 0) && | |
| (Value & EnumValueInCategory->Value)) { | |
| Name += Separator + EnumValueInCategory->Mnemonic.str(); | |
| Separator = "|"; | |
| } | |
| ++EnumValueInCategory; | |
| } | |
| return Name; | |
| } | |
| uint32_t | |
| getSymbolicOperandMinVersion(SPIRV::OperandCategory::OperandCategory Category, | |
| uint32_t Value) { | |
| const SPIRV::SymbolicOperand *Lookup = | |
| SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value); | |
| if (Lookup) | |
| return Lookup->MinVersion; | |
| return 0; | |
| } | |
| uint32_t | |
| getSymbolicOperandMaxVersion(SPIRV::OperandCategory::OperandCategory Category, | |
| uint32_t Value) { | |
| const SPIRV::SymbolicOperand *Lookup = | |
| SPIRV::lookupSymbolicOperandByCategoryAndValue(Category, Value); | |
| if (Lookup) | |
| return Lookup->MaxVersion; | |
| return 0; | |
| } | |
| CapabilityList | |
| getSymbolicOperandCapabilities(SPIRV::OperandCategory::OperandCategory Category, | |
| uint32_t Value) { | |
| const SPIRV::CapabilityEntry *Capability = | |
| SPIRV::lookupCapabilityByCategoryAndValue(Category, Value); | |
| CapabilityList Capabilities; | |
| while (Capability && Capability->Category == Category && | |
| Capability->Value == Value) { | |
| Capabilities.push_back( | |
| static_cast<SPIRV::Capability::Capability>(Capability->ReqCapability)); | |
| ++Capability; | |
| } | |
| return Capabilities; | |
| } | |
| ExtensionList | |
| getSymbolicOperandExtensions(SPIRV::OperandCategory::OperandCategory Category, | |
| uint32_t Value) { | |
| const SPIRV::ExtensionEntry *Extension = | |
| SPIRV::lookupExtensionByCategoryAndValue(Category, Value); | |
| ExtensionList Extensions; | |
| while (Extension && Extension->Category == Category && | |
| Extension->Value == Value) { | |
| Extensions.push_back( | |
| static_cast<SPIRV::Extension::Extension>(Extension->ReqExtension)); | |
| ++Extension; | |
| } | |
| return Extensions; | |
| } | |
| std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue) { | |
| const SPIRV::SymbolicOperand *Lookup = | |
| SPIRV::lookupSymbolicOperandByCategoryAndValue( | |
| SPIRV::OperandCategory::BuiltInOperand, BuiltInValue); | |
| if (Lookup) | |
| return "__spirv_BuiltIn" + Lookup->Mnemonic.str(); | |
| return "UNKNOWN_BUILTIN"; | |
| } | |
| bool getSpirvBuiltInIdByName(llvm::StringRef Name, | |
| SPIRV::BuiltIn::BuiltIn &BI) { | |
| const std::string Prefix = "__spirv_BuiltIn"; | |
| if (!Name.startswith(Prefix)) | |
| return false; | |
| const SPIRV::SymbolicOperand *Lookup = | |
| SPIRV::lookupSymbolicOperandByCategoryAndMnemonic( | |
| SPIRV::OperandCategory::BuiltInOperand, | |
| Name.drop_front(Prefix.length())); | |
| if (!Lookup) | |
| return false; | |
| BI = static_cast<SPIRV::BuiltIn::BuiltIn>(Lookup->Value); | |
| return true; | |
| } | |
| std::string getExtInstSetName(SPIRV::InstructionSet::InstructionSet Set) { | |
| switch (Set) { | |
| case SPIRV::InstructionSet::OpenCL_std: | |
| return "OpenCL.std"; | |
| case SPIRV::InstructionSet::GLSL_std_450: | |
| return "GLSL.std.450"; | |
| case SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax: | |
| return "SPV_AMD_shader_trinary_minmax"; | |
| } | |
| return "UNKNOWN_EXT_INST_SET"; | |
| } | |
| SPIRV::InstructionSet::InstructionSet | |
| getExtInstSetFromString(std::string SetName) { | |
| for (auto Set : {SPIRV::InstructionSet::GLSL_std_450, | |
| SPIRV::InstructionSet::OpenCL_std}) { | |
| if (SetName == getExtInstSetName(Set)) | |
| return Set; | |
| } | |
| llvm_unreachable("UNKNOWN_EXT_INST_SET"); | |
| } | |
| std::string getExtInstName(SPIRV::InstructionSet::InstructionSet Set, | |
| uint32_t InstructionNumber) { | |
| const SPIRV::ExtendedBuiltin *Lookup = | |
| SPIRV::lookupExtendedBuiltinBySetAndNumber( | |
| SPIRV::InstructionSet::OpenCL_std, InstructionNumber); | |
| if (!Lookup) | |
| return "UNKNOWN_EXT_INST"; | |
| return Lookup->Name.str(); | |
| } | |
| } // namespace llvm |