1b2a28edaSopenharmony_ci// Copyright (c) 2014-2020 The Khronos Group Inc. 2b2a28edaSopenharmony_ci// 3b2a28edaSopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a copy 4b2a28edaSopenharmony_ci// of this software and/or associated documentation files (the "Materials"), 5b2a28edaSopenharmony_ci// to deal in the Materials without restriction, including without limitation 6b2a28edaSopenharmony_ci// the rights to use, copy, modify, merge, publish, distribute, sublicense, 7b2a28edaSopenharmony_ci// and/or sell copies of the Materials, and to permit persons to whom the 8b2a28edaSopenharmony_ci// Materials are furnished to do so, subject to the following conditions: 9b2a28edaSopenharmony_ci// 10b2a28edaSopenharmony_ci// The above copyright notice and this permission notice shall be included in 11b2a28edaSopenharmony_ci// all copies or substantial portions of the Materials. 12b2a28edaSopenharmony_ci// 13b2a28edaSopenharmony_ci// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS 14b2a28edaSopenharmony_ci// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND 15b2a28edaSopenharmony_ci// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ 16b2a28edaSopenharmony_ci// 17b2a28edaSopenharmony_ci// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18b2a28edaSopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19b2a28edaSopenharmony_ci// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20b2a28edaSopenharmony_ci// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21b2a28edaSopenharmony_ci// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22b2a28edaSopenharmony_ci// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS 23b2a28edaSopenharmony_ci// IN THE MATERIALS. 24b2a28edaSopenharmony_ci 25b2a28edaSopenharmony_ci#include <assert.h> 26b2a28edaSopenharmony_ci#include <string.h> 27b2a28edaSopenharmony_ci#include <algorithm> 28b2a28edaSopenharmony_ci#include <cstdlib> 29b2a28edaSopenharmony_ci#include <iostream> 30b2a28edaSopenharmony_ci#include <unordered_map> 31b2a28edaSopenharmony_ci#include <unordered_set> 32b2a28edaSopenharmony_ci#include <utility> 33b2a28edaSopenharmony_ci#include <fstream> 34b2a28edaSopenharmony_ci 35b2a28edaSopenharmony_ci#include "jsoncpp/dist/json/json.h" 36b2a28edaSopenharmony_ci 37b2a28edaSopenharmony_ci#include "jsonToSpirv.h" 38b2a28edaSopenharmony_ci 39b2a28edaSopenharmony_cinamespace { 40b2a28edaSopenharmony_ci// Returns true if the given string is a valid SPIR-V version. 41b2a28edaSopenharmony_cibool validSpirvVersionString(const std::string s) { 42b2a28edaSopenharmony_ci return 43b2a28edaSopenharmony_ci s == "1.0" || 44b2a28edaSopenharmony_ci s == "1.1" || 45b2a28edaSopenharmony_ci s == "1.2" || 46b2a28edaSopenharmony_ci s == "1.3" || 47b2a28edaSopenharmony_ci s == "1.4" || 48b2a28edaSopenharmony_ci s == "1.5" || 49b2a28edaSopenharmony_ci s == "1.6"; 50b2a28edaSopenharmony_ci} 51b2a28edaSopenharmony_ci 52b2a28edaSopenharmony_ci// Returns true if the given string is a valid version 53b2a28edaSopenharmony_ci// specifier in the grammar file. 54b2a28edaSopenharmony_cibool validSpirvVersionStringSpecifier(const std::string s) { 55b2a28edaSopenharmony_ci return s == "None" || validSpirvVersionString(s); 56b2a28edaSopenharmony_ci} 57b2a28edaSopenharmony_ci} // anonymous namespace 58b2a28edaSopenharmony_ci 59b2a28edaSopenharmony_cinamespace spv { 60b2a28edaSopenharmony_ci 61b2a28edaSopenharmony_cibool IsLegacyDoublyEnabledInstruction(const std::string& instruction) { 62b2a28edaSopenharmony_ci static std::unordered_set<std::string> allowed = { 63b2a28edaSopenharmony_ci "OpSubgroupBallotKHR", 64b2a28edaSopenharmony_ci "OpSubgroupFirstInvocationKHR", 65b2a28edaSopenharmony_ci "OpSubgroupAllKHR", 66b2a28edaSopenharmony_ci "OpSubgroupAnyKHR", 67b2a28edaSopenharmony_ci "OpSubgroupAllEqualKHR", 68b2a28edaSopenharmony_ci "OpSubgroupReadInvocationKHR", 69b2a28edaSopenharmony_ci "OpTraceRayKHR", 70b2a28edaSopenharmony_ci "OpExecuteCallableKHR", 71b2a28edaSopenharmony_ci "OpConvertUToAccelerationStructureKHR", 72b2a28edaSopenharmony_ci "OpIgnoreIntersectionKHR", 73b2a28edaSopenharmony_ci "OpTerminateRayKHR", 74b2a28edaSopenharmony_ci "OpTypeRayQueryKHR", 75b2a28edaSopenharmony_ci "OpRayQueryInitializeKHR", 76b2a28edaSopenharmony_ci "OpRayQueryTerminateKHR", 77b2a28edaSopenharmony_ci "OpRayQueryGenerateIntersectionKHR", 78b2a28edaSopenharmony_ci "OpRayQueryConfirmIntersectionKHR", 79b2a28edaSopenharmony_ci "OpRayQueryProceedKHR", 80b2a28edaSopenharmony_ci "OpRayQueryGetIntersectionTypeKHR", 81b2a28edaSopenharmony_ci "OpGroupIAddNonUniformAMD", 82b2a28edaSopenharmony_ci "OpGroupFAddNonUniformAMD", 83b2a28edaSopenharmony_ci "OpGroupFMinNonUniformAMD", 84b2a28edaSopenharmony_ci "OpGroupUMinNonUniformAMD", 85b2a28edaSopenharmony_ci "OpGroupSMinNonUniformAMD", 86b2a28edaSopenharmony_ci "OpGroupFMaxNonUniformAMD", 87b2a28edaSopenharmony_ci "OpGroupUMaxNonUniformAMD", 88b2a28edaSopenharmony_ci "OpGroupSMaxNonUniformAMD", 89b2a28edaSopenharmony_ci "OpFragmentMaskFetchAMD", 90b2a28edaSopenharmony_ci "OpFragmentFetchAMD", 91b2a28edaSopenharmony_ci "OpImageSampleFootprintNV", 92b2a28edaSopenharmony_ci "OpGroupNonUniformPartitionNV", 93b2a28edaSopenharmony_ci "OpWritePackedPrimitiveIndices4x8NV", 94b2a28edaSopenharmony_ci "OpReportIntersectionNV", 95b2a28edaSopenharmony_ci "OpReportIntersectionKHR", 96b2a28edaSopenharmony_ci "OpIgnoreIntersectionNV", 97b2a28edaSopenharmony_ci "OpTerminateRayNV", 98b2a28edaSopenharmony_ci "OpTraceNV", 99b2a28edaSopenharmony_ci "OpTraceMotionNV", 100b2a28edaSopenharmony_ci "OpTraceRayMotionNV", 101b2a28edaSopenharmony_ci "OpTypeAccelerationStructureNV", 102b2a28edaSopenharmony_ci "OpTypeAccelerationStructureKHR", 103b2a28edaSopenharmony_ci "OpExecuteCallableNV", 104b2a28edaSopenharmony_ci "OpTypeCooperativeMatrixNV", 105b2a28edaSopenharmony_ci "OpCooperativeMatrixLoadNV", 106b2a28edaSopenharmony_ci "OpCooperativeMatrixStoreNV", 107b2a28edaSopenharmony_ci "OpCooperativeMatrixMulAddNV", 108b2a28edaSopenharmony_ci "OpCooperativeMatrixLengthNV", 109b2a28edaSopenharmony_ci "OpBeginInvocationInterlockEXT", 110b2a28edaSopenharmony_ci "OpEndInvocationInterlockEXT", 111b2a28edaSopenharmony_ci "OpIsHelperInvocationEXT", 112b2a28edaSopenharmony_ci "OpConstantFunctionPointerINTEL", 113b2a28edaSopenharmony_ci "OpFunctionPointerCallINTEL", 114b2a28edaSopenharmony_ci "OpAssumeTrueKHR", 115b2a28edaSopenharmony_ci "OpExpectKHR", 116b2a28edaSopenharmony_ci "OpLoopControlINTEL", 117b2a28edaSopenharmony_ci "OpAliasDomainDeclINTEL", 118b2a28edaSopenharmony_ci "OpAliasScopeDeclINTEL", 119b2a28edaSopenharmony_ci "OpAliasScopeListDeclINTEL", 120b2a28edaSopenharmony_ci "OpReadPipeBlockingINTEL", 121b2a28edaSopenharmony_ci "OpWritePipeBlockingINTEL", 122b2a28edaSopenharmony_ci "OpFPGARegINTEL", 123b2a28edaSopenharmony_ci "OpRayQueryGetRayTMinKHR", 124b2a28edaSopenharmony_ci "OpRayQueryGetRayFlagsKHR", 125b2a28edaSopenharmony_ci "OpRayQueryGetIntersectionTKHR", 126b2a28edaSopenharmony_ci "OpRayQueryGetIntersectionInstanceCustomIndexKHR", 127b2a28edaSopenharmony_ci "OpRayQueryGetIntersectionInstanceIdKHR", 128b2a28edaSopenharmony_ci "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR", 129b2a28edaSopenharmony_ci "OpRayQueryGetIntersectionGeometryIndexKHR", 130b2a28edaSopenharmony_ci "OpRayQueryGetIntersectionPrimitiveIndexKHR", 131b2a28edaSopenharmony_ci "OpRayQueryGetIntersectionBarycentricsKHR", 132b2a28edaSopenharmony_ci "OpRayQueryGetIntersectionFrontFaceKHR", 133b2a28edaSopenharmony_ci "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR", 134b2a28edaSopenharmony_ci "OpRayQueryGetIntersectionObjectRayDirectionKHR", 135b2a28edaSopenharmony_ci "OpRayQueryGetIntersectionObjectRayOriginKHR", 136b2a28edaSopenharmony_ci "OpRayQueryGetWorldRayDirectionKHR", 137b2a28edaSopenharmony_ci "OpRayQueryGetWorldRayOriginKHR", 138b2a28edaSopenharmony_ci "OpRayQueryGetIntersectionObjectToWorldKHR", 139b2a28edaSopenharmony_ci "OpRayQueryGetIntersectionWorldToObjectKHR", 140b2a28edaSopenharmony_ci "OpAtomicFAddEXT", 141b2a28edaSopenharmony_ci }; 142b2a28edaSopenharmony_ci return allowed.count(instruction) != 0; 143b2a28edaSopenharmony_ci} 144b2a28edaSopenharmony_ci 145b2a28edaSopenharmony_cibool EnumValue::IsValid(OperandClass oc, const std::string& context) const 146b2a28edaSopenharmony_ci{ 147b2a28edaSopenharmony_ci bool result = true; 148b2a28edaSopenharmony_ci if (firstVersion.empty()) { 149b2a28edaSopenharmony_ci std::cerr << "Error: " << context << " " << name << " \"version\" must be set, probably to \"None\"" << std::endl; 150b2a28edaSopenharmony_ci result = false; 151b2a28edaSopenharmony_ci } else if (!validSpirvVersionStringSpecifier(firstVersion)) { 152b2a28edaSopenharmony_ci std::cerr << "Error: " << context << " " << name << " \"version\" is invalid: " << firstVersion << std::endl; 153b2a28edaSopenharmony_ci result = false; 154b2a28edaSopenharmony_ci } 155b2a28edaSopenharmony_ci if (!lastVersion.empty() && !validSpirvVersionString(lastVersion)) { 156b2a28edaSopenharmony_ci std::cerr << "Error: " << context << " " << name << " \"lastVersion\" is invalid: " << lastVersion << std::endl; 157b2a28edaSopenharmony_ci result = false; 158b2a28edaSopenharmony_ci } 159b2a28edaSopenharmony_ci 160b2a28edaSopenharmony_ci // When a feature is introduced by an extension, the firstVersion is set to 161b2a28edaSopenharmony_ci // "None". There are three cases: 162b2a28edaSopenharmony_ci // - A new capability should be guarded/enabled by the extension 163b2a28edaSopenharmony_ci // - A new instruction should be: 164b2a28edaSopenharmony_ci // - Guarded/enabled by a new capability. 165b2a28edaSopenharmony_ci // - Not enabled by *both* a capability and an extension. 166b2a28edaSopenharmony_ci // There are many existing instructions that are already like this, 167b2a28edaSopenharmony_ci // and we grandparent them as allowed. 168b2a28edaSopenharmony_ci // - Other enums fall into two cases: 169b2a28edaSopenharmony_ci // 1. The enum is part of a new operand kind introduced by the extension. 170b2a28edaSopenharmony_ci // In this case we rely on transitivity: The use of the operand occurs 171b2a28edaSopenharmony_ci // in a new instruction that itself is guarded; or as the operand of 172b2a28edaSopenharmony_ci // another operand that itself is (recursively) guarded. 173b2a28edaSopenharmony_ci // 2. The enum is a new case in an existing operand kind. This case 174b2a28edaSopenharmony_ci // should be guarded by a capability. However, we do not check this 175b2a28edaSopenharmony_ci // here. Checking it requires more context than we have here. 176b2a28edaSopenharmony_ci if (oc == OperandOpcode) { 177b2a28edaSopenharmony_ci const bool instruction_unusable = 178b2a28edaSopenharmony_ci (firstVersion == "None") && extensions.empty() && capabilities.empty(); 179b2a28edaSopenharmony_ci if (instruction_unusable) { 180b2a28edaSopenharmony_ci std::cerr << "Error: " << context << " " << name << " is not usable: " 181b2a28edaSopenharmony_ci << "its version is set to \"None\", and it is not enabled by a " 182b2a28edaSopenharmony_ci << "capability or extension. Guard it with a capability." 183b2a28edaSopenharmony_ci << std::endl; 184b2a28edaSopenharmony_ci result = false; 185b2a28edaSopenharmony_ci } 186b2a28edaSopenharmony_ci // Complain if an instruction is not in any core version and also enabled by 187b2a28edaSopenharmony_ci // both an extension and a capability. 188b2a28edaSopenharmony_ci // It's important to check the "not in any core version" case, because, 189b2a28edaSopenharmony_ci // for example, OpTerminateInvocation is in SPIR-V 1.6 *and* enabled by an 190b2a28edaSopenharmony_ci // extension, and guarded by the Shader capability. 191b2a28edaSopenharmony_ci const bool instruction_doubly_enabled = (firstVersion == "None") && 192b2a28edaSopenharmony_ci !extensions.empty() && 193b2a28edaSopenharmony_ci !capabilities.empty(); 194b2a28edaSopenharmony_ci if (instruction_doubly_enabled && !IsLegacyDoublyEnabledInstruction(name)) { 195b2a28edaSopenharmony_ci std::cerr << "Error: " << context << " " << name << " is doubly-enabled: " 196b2a28edaSopenharmony_ci << "it is enabled by both a capability and an extension. " 197b2a28edaSopenharmony_ci << "Guard it with a capability only." << std::endl; 198b2a28edaSopenharmony_ci result = false; 199b2a28edaSopenharmony_ci } 200b2a28edaSopenharmony_ci } 201b2a28edaSopenharmony_ci if (oc == OperandCapability) { 202b2a28edaSopenharmony_ci // If capability X lists capabilities Y and Z, then Y and Z are *enabled* 203b2a28edaSopenharmony_ci // when X is enabled. They are not *guards* on X's use. 204b2a28edaSopenharmony_ci // Only versions and extensions can guard a capability. 205b2a28edaSopenharmony_ci const bool capability_unusable = 206b2a28edaSopenharmony_ci (firstVersion == "None") && extensions.empty(); 207b2a28edaSopenharmony_ci if (capability_unusable) { 208b2a28edaSopenharmony_ci std::cerr << "Error: " << context << " " << name << " is not usable: " 209b2a28edaSopenharmony_ci << "its version is set to \"None\", and it is not enabled by " 210b2a28edaSopenharmony_ci << "an extension. Guard it with an extension." << std::endl; 211b2a28edaSopenharmony_ci result = false; 212b2a28edaSopenharmony_ci } 213b2a28edaSopenharmony_ci } 214b2a28edaSopenharmony_ci 215b2a28edaSopenharmony_ci return result; 216b2a28edaSopenharmony_ci} 217b2a28edaSopenharmony_ci 218b2a28edaSopenharmony_ci// The set of objects that hold all the instruction/operand 219b2a28edaSopenharmony_ci// parameterization information. 220b2a28edaSopenharmony_ciInstructionValues InstructionDesc; 221b2a28edaSopenharmony_ci 222b2a28edaSopenharmony_ci// The ordered list (in printing order) of printing classes 223b2a28edaSopenharmony_ci// (specification subsections). 224b2a28edaSopenharmony_ciPrintingClasses InstructionPrintingClasses; 225b2a28edaSopenharmony_ci 226b2a28edaSopenharmony_ci// Note: There is no entry for OperandOpcode. Use InstructionDesc instead. 227b2a28edaSopenharmony_ciEnumDefinition OperandClassParams[OperandOpcode]; 228b2a28edaSopenharmony_ciEnumValues SourceLanguageParams; 229b2a28edaSopenharmony_ciEnumValues ExecutionModelParams; 230b2a28edaSopenharmony_ciEnumValues AddressingParams; 231b2a28edaSopenharmony_ciEnumValues MemoryParams; 232b2a28edaSopenharmony_ciEnumValues ExecutionModeParams; 233b2a28edaSopenharmony_ciEnumValues StorageParams; 234b2a28edaSopenharmony_ciEnumValues SamplerAddressingModeParams; 235b2a28edaSopenharmony_ciEnumValues SamplerFilterModeParams; 236b2a28edaSopenharmony_ciEnumValues ImageFormatParams; 237b2a28edaSopenharmony_ciEnumValues ImageChannelOrderParams; 238b2a28edaSopenharmony_ciEnumValues ImageChannelDataTypeParams; 239b2a28edaSopenharmony_ciEnumValues ImageOperandsParams; 240b2a28edaSopenharmony_ciEnumValues FPFastMathParams; 241b2a28edaSopenharmony_ciEnumValues FPRoundingModeParams; 242b2a28edaSopenharmony_ciEnumValues FPDenormModeParams; 243b2a28edaSopenharmony_ciEnumValues FPOperationModeParams; 244b2a28edaSopenharmony_ciEnumValues QuantizationModesParams; 245b2a28edaSopenharmony_ciEnumValues OverflowModesParams; 246b2a28edaSopenharmony_ciEnumValues LinkageTypeParams; 247b2a28edaSopenharmony_ciEnumValues DecorationParams; 248b2a28edaSopenharmony_ciEnumValues BuiltInParams; 249b2a28edaSopenharmony_ciEnumValues DimensionalityParams; 250b2a28edaSopenharmony_ciEnumValues FuncParamAttrParams; 251b2a28edaSopenharmony_ciEnumValues AccessQualifierParams; 252b2a28edaSopenharmony_ciEnumValues GroupOperationParams; 253b2a28edaSopenharmony_ciEnumValues LoopControlParams; 254b2a28edaSopenharmony_ciEnumValues SelectionControlParams; 255b2a28edaSopenharmony_ciEnumValues FunctionControlParams; 256b2a28edaSopenharmony_ciEnumValues MemorySemanticsParams; 257b2a28edaSopenharmony_ciEnumValues MemoryAccessParams; 258b2a28edaSopenharmony_ciEnumValues ScopeParams; 259b2a28edaSopenharmony_ciEnumValues KernelEnqueueFlagsParams; 260b2a28edaSopenharmony_ciEnumValues KernelProfilingInfoParams; 261b2a28edaSopenharmony_ciEnumValues CapabilityParams; 262b2a28edaSopenharmony_ciEnumValues RayFlagsParams; 263b2a28edaSopenharmony_ciEnumValues RayQueryIntersectionParams; 264b2a28edaSopenharmony_ciEnumValues RayQueryCommittedIntersectionTypeParams; 265b2a28edaSopenharmony_ciEnumValues RayQueryCandidateIntersectionTypeParams; 266b2a28edaSopenharmony_ciEnumValues FragmentShadingRateParams; 267b2a28edaSopenharmony_ciEnumValues PackedVectorFormatParams; 268b2a28edaSopenharmony_ciEnumValues CooperativeMatrixOperandsParams; 269b2a28edaSopenharmony_ciEnumValues CooperativeMatrixLayoutParams; 270b2a28edaSopenharmony_ciEnumValues CooperativeMatrixUseParams; 271b2a28edaSopenharmony_ciEnumValues InitializationModeQualifierParams; 272b2a28edaSopenharmony_ciEnumValues HostAccessQualifierParams; 273b2a28edaSopenharmony_ciEnumValues LoadCacheControlParams; 274b2a28edaSopenharmony_ciEnumValues StoreCacheControlParams; 275b2a28edaSopenharmony_ci 276b2a28edaSopenharmony_cistd::pair<bool, std::string> ReadFile(const std::string& path) 277b2a28edaSopenharmony_ci{ 278b2a28edaSopenharmony_ci std::ifstream fstream(path, std::ios::in); 279b2a28edaSopenharmony_ci if (fstream) { 280b2a28edaSopenharmony_ci std::string contents; 281b2a28edaSopenharmony_ci fstream.seekg(0, std::ios::end); 282b2a28edaSopenharmony_ci contents.reserve((unsigned int)fstream.tellg()); 283b2a28edaSopenharmony_ci fstream.seekg(0, std::ios::beg); 284b2a28edaSopenharmony_ci contents.assign((std::istreambuf_iterator<char>(fstream)), 285b2a28edaSopenharmony_ci std::istreambuf_iterator<char>()); 286b2a28edaSopenharmony_ci return std::make_pair(true, contents); 287b2a28edaSopenharmony_ci } 288b2a28edaSopenharmony_ci return std::make_pair(false, ""); 289b2a28edaSopenharmony_ci} 290b2a28edaSopenharmony_ci 291b2a28edaSopenharmony_cistruct ClassOptionality { 292b2a28edaSopenharmony_ci OperandClass type; 293b2a28edaSopenharmony_ci bool optional; 294b2a28edaSopenharmony_ci}; 295b2a28edaSopenharmony_ci 296b2a28edaSopenharmony_ci// Converts the |operandKind| and |quantifier| pair used to describe operands 297b2a28edaSopenharmony_ci// in the JSON grammar to OperandClass and optionality used in this repo. 298b2a28edaSopenharmony_ciClassOptionality ToOperandClassAndOptionality(const std::string& operandKind, const std::string& quantifier) 299b2a28edaSopenharmony_ci{ 300b2a28edaSopenharmony_ci assert(quantifier.empty() || quantifier == "?" || quantifier == "*"); 301b2a28edaSopenharmony_ci 302b2a28edaSopenharmony_ci if (operandKind == "IdRef") { 303b2a28edaSopenharmony_ci if (quantifier.empty()) 304b2a28edaSopenharmony_ci return {OperandId, false}; 305b2a28edaSopenharmony_ci else if (quantifier == "?") 306b2a28edaSopenharmony_ci return {OperandId, true}; 307b2a28edaSopenharmony_ci else 308b2a28edaSopenharmony_ci return {OperandVariableIds, false}; 309b2a28edaSopenharmony_ci } else if (operandKind == "LiteralInteger") { 310b2a28edaSopenharmony_ci if (quantifier.empty()) 311b2a28edaSopenharmony_ci return {OperandLiteralNumber, false}; 312b2a28edaSopenharmony_ci if (quantifier == "?") 313b2a28edaSopenharmony_ci return {OperandOptionalLiteral, true}; 314b2a28edaSopenharmony_ci else 315b2a28edaSopenharmony_ci return {OperandVariableLiterals, false}; 316b2a28edaSopenharmony_ci } else if (operandKind == "LiteralString") { 317b2a28edaSopenharmony_ci if (quantifier.empty()) 318b2a28edaSopenharmony_ci return {OperandLiteralString, false}; 319b2a28edaSopenharmony_ci else if (quantifier == "?") 320b2a28edaSopenharmony_ci return {OperandLiteralString, true}; 321b2a28edaSopenharmony_ci else { 322b2a28edaSopenharmony_ci return {OperandOptionalLiteralStrings, false}; 323b2a28edaSopenharmony_ci } 324b2a28edaSopenharmony_ci } else if (operandKind == "PairLiteralIntegerIdRef") { 325b2a28edaSopenharmony_ci // Used by OpSwitch in the grammar 326b2a28edaSopenharmony_ci return {OperandVariableLiteralId, false}; 327b2a28edaSopenharmony_ci } else if (operandKind == "PairIdRefLiteralInteger") { 328b2a28edaSopenharmony_ci // Used by OpGroupMemberDecorate in the grammar 329b2a28edaSopenharmony_ci return {OperandVariableIdLiteral, false}; 330b2a28edaSopenharmony_ci } else if (operandKind == "PairIdRefIdRef") { 331b2a28edaSopenharmony_ci // Used by OpPhi in the grammar 332b2a28edaSopenharmony_ci return {OperandVariableIds, false}; 333b2a28edaSopenharmony_ci } else { 334b2a28edaSopenharmony_ci OperandClass type = OperandNone; 335b2a28edaSopenharmony_ci if (operandKind == "IdMemorySemantics" || operandKind == "MemorySemantics") { 336b2a28edaSopenharmony_ci type = OperandMemorySemantics; 337b2a28edaSopenharmony_ci } else if (operandKind == "IdScope" || operandKind == "Scope") { 338b2a28edaSopenharmony_ci type = OperandScope; 339b2a28edaSopenharmony_ci } else if (operandKind == "LiteralExtInstInteger") { 340b2a28edaSopenharmony_ci type = OperandLiteralNumber; 341b2a28edaSopenharmony_ci } else if (operandKind == "LiteralSpecConstantOpInteger") { 342b2a28edaSopenharmony_ci type = OperandLiteralNumber; 343b2a28edaSopenharmony_ci } else if (operandKind == "LiteralContextDependentNumber") { 344b2a28edaSopenharmony_ci type = OperandAnySizeLiteralNumber; 345b2a28edaSopenharmony_ci } else if (operandKind == "LiteralFloat") { 346b2a28edaSopenharmony_ci type = OperandLiteralNumber; 347b2a28edaSopenharmony_ci } else if (operandKind == "SourceLanguage") { 348b2a28edaSopenharmony_ci type = OperandSource; 349b2a28edaSopenharmony_ci } else if (operandKind == "ExecutionModel") { 350b2a28edaSopenharmony_ci type = OperandExecutionModel; 351b2a28edaSopenharmony_ci } else if (operandKind == "AddressingModel") { 352b2a28edaSopenharmony_ci type = OperandAddressing; 353b2a28edaSopenharmony_ci } else if (operandKind == "MemoryModel") { 354b2a28edaSopenharmony_ci type = OperandMemory; 355b2a28edaSopenharmony_ci } else if (operandKind == "ExecutionMode") { 356b2a28edaSopenharmony_ci type = OperandExecutionMode; 357b2a28edaSopenharmony_ci } else if (operandKind == "StorageClass") { 358b2a28edaSopenharmony_ci type = OperandStorage; 359b2a28edaSopenharmony_ci } else if (operandKind == "Dim") { 360b2a28edaSopenharmony_ci type = OperandDimensionality; 361b2a28edaSopenharmony_ci } else if (operandKind == "SamplerAddressingMode") { 362b2a28edaSopenharmony_ci type = OperandSamplerAddressingMode; 363b2a28edaSopenharmony_ci } else if (operandKind == "SamplerFilterMode") { 364b2a28edaSopenharmony_ci type = OperandSamplerFilterMode; 365b2a28edaSopenharmony_ci } else if (operandKind == "ImageFormat") { 366b2a28edaSopenharmony_ci type = OperandSamplerImageFormat; 367b2a28edaSopenharmony_ci } else if (operandKind == "ImageChannelOrder") { 368b2a28edaSopenharmony_ci type = OperandImageChannelOrder; 369b2a28edaSopenharmony_ci } else if (operandKind == "ImageChannelDataType") { 370b2a28edaSopenharmony_ci type = OperandImageChannelDataType; 371b2a28edaSopenharmony_ci } else if (operandKind == "FPRoundingMode") { 372b2a28edaSopenharmony_ci type = OperandFPRoundingMode; 373b2a28edaSopenharmony_ci } else if (operandKind == "FPDenormMode") { 374b2a28edaSopenharmony_ci type = OperandFPDenormMode; 375b2a28edaSopenharmony_ci } else if (operandKind == "FPOperationMode") { 376b2a28edaSopenharmony_ci type = OperandFPOperationMode; 377b2a28edaSopenharmony_ci } else if (operandKind == "QuantizationModes") { 378b2a28edaSopenharmony_ci type = OperandQuantizationModes; 379b2a28edaSopenharmony_ci } else if (operandKind == "OverflowModes") { 380b2a28edaSopenharmony_ci type = OperandOverflowModes; 381b2a28edaSopenharmony_ci } else if (operandKind == "LinkageType") { 382b2a28edaSopenharmony_ci type = OperandLinkageType; 383b2a28edaSopenharmony_ci } else if (operandKind == "AccessQualifier") { 384b2a28edaSopenharmony_ci type = OperandAccessQualifier; 385b2a28edaSopenharmony_ci } else if (operandKind == "FunctionParameterAttribute") { 386b2a28edaSopenharmony_ci type = OperandFuncParamAttr; 387b2a28edaSopenharmony_ci } else if (operandKind == "Decoration") { 388b2a28edaSopenharmony_ci type = OperandDecoration; 389b2a28edaSopenharmony_ci } else if (operandKind == "BuiltIn") { 390b2a28edaSopenharmony_ci type = OperandBuiltIn; 391b2a28edaSopenharmony_ci } else if (operandKind == "GroupOperation") { 392b2a28edaSopenharmony_ci type = OperandGroupOperation; 393b2a28edaSopenharmony_ci } else if (operandKind == "KernelEnqueueFlags") { 394b2a28edaSopenharmony_ci type = OperandKernelEnqueueFlags; 395b2a28edaSopenharmony_ci } else if (operandKind == "KernelProfilingInfo") { 396b2a28edaSopenharmony_ci type = OperandKernelProfilingInfo; 397b2a28edaSopenharmony_ci } else if (operandKind == "Capability") { 398b2a28edaSopenharmony_ci type = OperandCapability; 399b2a28edaSopenharmony_ci } else if (operandKind == "ImageOperands") { 400b2a28edaSopenharmony_ci type = OperandImageOperands; 401b2a28edaSopenharmony_ci } else if (operandKind == "FPFastMathMode") { 402b2a28edaSopenharmony_ci type = OperandFPFastMath; 403b2a28edaSopenharmony_ci } else if (operandKind == "SelectionControl") { 404b2a28edaSopenharmony_ci type = OperandSelect; 405b2a28edaSopenharmony_ci } else if (operandKind == "LoopControl") { 406b2a28edaSopenharmony_ci type = OperandLoop; 407b2a28edaSopenharmony_ci } else if (operandKind == "FunctionControl") { 408b2a28edaSopenharmony_ci type = OperandFunction; 409b2a28edaSopenharmony_ci } else if (operandKind == "MemoryAccess") { 410b2a28edaSopenharmony_ci type = OperandMemoryOperands; 411b2a28edaSopenharmony_ci } else if (operandKind == "RayFlags") { 412b2a28edaSopenharmony_ci type = OperandRayFlags; 413b2a28edaSopenharmony_ci } else if (operandKind == "RayQueryIntersection") { 414b2a28edaSopenharmony_ci type = OperandRayQueryIntersection; 415b2a28edaSopenharmony_ci } else if (operandKind == "RayQueryCommittedIntersectionType") { 416b2a28edaSopenharmony_ci type = OperandRayQueryCommittedIntersectionType; 417b2a28edaSopenharmony_ci } else if (operandKind == "RayQueryCandidateIntersectionType") { 418b2a28edaSopenharmony_ci type = OperandRayQueryCandidateIntersectionType; 419b2a28edaSopenharmony_ci } else if (operandKind == "FragmentShadingRate") { 420b2a28edaSopenharmony_ci type = OperandFragmentShadingRate; 421b2a28edaSopenharmony_ci } else if (operandKind == "PackedVectorFormat") { 422b2a28edaSopenharmony_ci type = OperandPackedVectorFormat; 423b2a28edaSopenharmony_ci } else if (operandKind == "CooperativeMatrixOperands") { 424b2a28edaSopenharmony_ci type = OperandCooperativeMatrixOperands; 425b2a28edaSopenharmony_ci } else if (operandKind == "CooperativeMatrixLayout") { 426b2a28edaSopenharmony_ci type = OperandCooperativeMatrixLayout; 427b2a28edaSopenharmony_ci } else if (operandKind == "CooperativeMatrixUse") { 428b2a28edaSopenharmony_ci type = OperandCooperativeMatrixUse; 429b2a28edaSopenharmony_ci } else if (operandKind == "InitializationModeQualifier") { 430b2a28edaSopenharmony_ci type = OperandInitializationModeQualifier; 431b2a28edaSopenharmony_ci } else if (operandKind == "HostAccessQualifier") { 432b2a28edaSopenharmony_ci type = OperandHostAccessQualifier; 433b2a28edaSopenharmony_ci } else if (operandKind == "LoadCacheControl") { 434b2a28edaSopenharmony_ci type = OperandLoadCacheControl; 435b2a28edaSopenharmony_ci } else if (operandKind == "StoreCacheControl") { 436b2a28edaSopenharmony_ci type = OperandStoreCacheControl; 437b2a28edaSopenharmony_ci } 438b2a28edaSopenharmony_ci 439b2a28edaSopenharmony_ci if (type == OperandNone) { 440b2a28edaSopenharmony_ci std::cerr << "Unhandled operand kind found: " << operandKind << std::endl; 441b2a28edaSopenharmony_ci exit(1); 442b2a28edaSopenharmony_ci } 443b2a28edaSopenharmony_ci return {type, !quantifier.empty()}; 444b2a28edaSopenharmony_ci } 445b2a28edaSopenharmony_ci} 446b2a28edaSopenharmony_ci 447b2a28edaSopenharmony_cibool IsTypeOrResultId(const std::string& str, bool* isType, bool* isResult) 448b2a28edaSopenharmony_ci{ 449b2a28edaSopenharmony_ci if (str == "IdResultType") 450b2a28edaSopenharmony_ci return *isType = true; 451b2a28edaSopenharmony_ci if (str == "IdResult") 452b2a28edaSopenharmony_ci return *isResult = true; 453b2a28edaSopenharmony_ci return false; 454b2a28edaSopenharmony_ci} 455b2a28edaSopenharmony_ci 456b2a28edaSopenharmony_ci// Given a number string, returns the position of the only bits set in the number. 457b2a28edaSopenharmony_ci// So it requires the number is a power of two. 458b2a28edaSopenharmony_ciunsigned int NumberStringToBit(const std::string& str) 459b2a28edaSopenharmony_ci{ 460b2a28edaSopenharmony_ci char* parseEnd; 461b2a28edaSopenharmony_ci unsigned int value = (unsigned int)std::strtol(str.c_str(), &parseEnd, 16); 462b2a28edaSopenharmony_ci assert(!(value & (value - 1)) && "input number is not a power of 2"); 463b2a28edaSopenharmony_ci unsigned int bit = 0; 464b2a28edaSopenharmony_ci for (; value; value >>= 1) ++bit; 465b2a28edaSopenharmony_ci return bit; 466b2a28edaSopenharmony_ci} 467b2a28edaSopenharmony_ci 468b2a28edaSopenharmony_civoid jsonToSpirv(const std::string& jsonPath, bool buildingHeaders) 469b2a28edaSopenharmony_ci{ 470b2a28edaSopenharmony_ci // only do this once. 471b2a28edaSopenharmony_ci static bool initialized = false; 472b2a28edaSopenharmony_ci if (initialized) 473b2a28edaSopenharmony_ci return; 474b2a28edaSopenharmony_ci initialized = true; 475b2a28edaSopenharmony_ci 476b2a28edaSopenharmony_ci size_t errorCount = 0; 477b2a28edaSopenharmony_ci 478b2a28edaSopenharmony_ci // Read the JSON grammar file. 479b2a28edaSopenharmony_ci bool fileReadOk = false; 480b2a28edaSopenharmony_ci std::string content; 481b2a28edaSopenharmony_ci std::tie(fileReadOk, content) = ReadFile(jsonPath); 482b2a28edaSopenharmony_ci if (!fileReadOk) { 483b2a28edaSopenharmony_ci std::cerr << "Failed to read JSON grammar file: " 484b2a28edaSopenharmony_ci << jsonPath << std::endl; 485b2a28edaSopenharmony_ci exit(1); 486b2a28edaSopenharmony_ci } 487b2a28edaSopenharmony_ci 488b2a28edaSopenharmony_ci // Decode the JSON grammar file. 489b2a28edaSopenharmony_ci Json::Reader reader; 490b2a28edaSopenharmony_ci Json::Value root; 491b2a28edaSopenharmony_ci if (!reader.parse(content, root)) { 492b2a28edaSopenharmony_ci std::cerr << "Failed to parse JSON grammar:\n" 493b2a28edaSopenharmony_ci << reader.getFormattedErrorMessages(); 494b2a28edaSopenharmony_ci exit(1); 495b2a28edaSopenharmony_ci } 496b2a28edaSopenharmony_ci 497b2a28edaSopenharmony_ci // Layouts for all instructions. 498b2a28edaSopenharmony_ci 499b2a28edaSopenharmony_ci // A lambda for returning capabilities from a JSON object as strings. 500b2a28edaSopenharmony_ci const auto getCaps = [](const Json::Value& object) { 501b2a28edaSopenharmony_ci EnumCaps result; 502b2a28edaSopenharmony_ci const auto& caps = object["capabilities"]; 503b2a28edaSopenharmony_ci if (!caps.empty()) { 504b2a28edaSopenharmony_ci assert(caps.isArray()); 505b2a28edaSopenharmony_ci for (const auto& cap : caps) { 506b2a28edaSopenharmony_ci result.emplace_back(cap.asString()); 507b2a28edaSopenharmony_ci } 508b2a28edaSopenharmony_ci } 509b2a28edaSopenharmony_ci return result; 510b2a28edaSopenharmony_ci }; 511b2a28edaSopenharmony_ci 512b2a28edaSopenharmony_ci // A lambda for returning extensions from a JSON object as strings. 513b2a28edaSopenharmony_ci const auto getExts = [](const Json::Value& object) { 514b2a28edaSopenharmony_ci Extensions result; 515b2a28edaSopenharmony_ci const auto& exts = object["extensions"]; 516b2a28edaSopenharmony_ci if (!exts.empty()) { 517b2a28edaSopenharmony_ci assert(exts.isArray()); 518b2a28edaSopenharmony_ci for (const auto& ext : exts) { 519b2a28edaSopenharmony_ci result.emplace_back(ext.asString()); 520b2a28edaSopenharmony_ci } 521b2a28edaSopenharmony_ci } 522b2a28edaSopenharmony_ci return result; 523b2a28edaSopenharmony_ci }; 524b2a28edaSopenharmony_ci 525b2a28edaSopenharmony_ci // set up the printing classes 526b2a28edaSopenharmony_ci std::unordered_set<std::string> tags; // short-lived local for error checking below 527b2a28edaSopenharmony_ci const Json::Value printingClasses = root["instruction_printing_class"]; 528b2a28edaSopenharmony_ci for (const auto& printingClass : printingClasses) { 529b2a28edaSopenharmony_ci if (printingClass["tag"].asString().size() > 0) 530b2a28edaSopenharmony_ci tags.insert(printingClass["tag"].asString()); // just for error checking 531b2a28edaSopenharmony_ci else { 532b2a28edaSopenharmony_ci std::cerr << "Error: each instruction_printing_class requires a non-empty \"tag\"" << std::endl; 533b2a28edaSopenharmony_ci std::exit(1); 534b2a28edaSopenharmony_ci } 535b2a28edaSopenharmony_ci if (buildingHeaders || printingClass["tag"].asString() != "@exclude") { 536b2a28edaSopenharmony_ci InstructionPrintingClasses.push_back({printingClass["tag"].asString(), 537b2a28edaSopenharmony_ci printingClass["heading"].asString()}); 538b2a28edaSopenharmony_ci } 539b2a28edaSopenharmony_ci } 540b2a28edaSopenharmony_ci 541b2a28edaSopenharmony_ci // process the instructions 542b2a28edaSopenharmony_ci const Json::Value insts = root["instructions"]; 543b2a28edaSopenharmony_ci unsigned maxOpcode = 0; 544b2a28edaSopenharmony_ci bool firstOpcode = true; 545b2a28edaSopenharmony_ci for (const auto& inst : insts) { 546b2a28edaSopenharmony_ci const auto printingClass = inst["class"].asString(); 547b2a28edaSopenharmony_ci if (printingClass.size() == 0) { 548b2a28edaSopenharmony_ci std::cerr << "Error: " << inst["opname"].asString() 549b2a28edaSopenharmony_ci << " requires a non-empty printing \"class\" tag" << std::endl; 550b2a28edaSopenharmony_ci std::exit(1); 551b2a28edaSopenharmony_ci } 552b2a28edaSopenharmony_ci if (!buildingHeaders && printingClass == "@exclude") 553b2a28edaSopenharmony_ci continue; 554b2a28edaSopenharmony_ci if (tags.find(printingClass) == tags.end()) { 555b2a28edaSopenharmony_ci std::cerr << "Error: " << inst["opname"].asString() 556b2a28edaSopenharmony_ci << " requires a \"class\" declared as a \"tag\" in \"instruction printing_class\"" 557b2a28edaSopenharmony_ci << std::endl; 558b2a28edaSopenharmony_ci std::exit(1); 559b2a28edaSopenharmony_ci } 560b2a28edaSopenharmony_ci const auto opcode = inst["opcode"].asUInt(); 561b2a28edaSopenharmony_ci const std::string name = inst["opname"].asString(); 562b2a28edaSopenharmony_ci if (firstOpcode) { 563b2a28edaSopenharmony_ci maxOpcode = opcode; 564b2a28edaSopenharmony_ci firstOpcode = false; 565b2a28edaSopenharmony_ci } else { 566b2a28edaSopenharmony_ci if (maxOpcode > opcode) { 567b2a28edaSopenharmony_ci std::cerr << "Error: " << name 568b2a28edaSopenharmony_ci << " is out of order. It follows the instruction with opcode " << maxOpcode 569b2a28edaSopenharmony_ci << std::endl; 570b2a28edaSopenharmony_ci std::exit(1); 571b2a28edaSopenharmony_ci } else { 572b2a28edaSopenharmony_ci maxOpcode = opcode; 573b2a28edaSopenharmony_ci } 574b2a28edaSopenharmony_ci } 575b2a28edaSopenharmony_ci EnumCaps caps = getCaps(inst); 576b2a28edaSopenharmony_ci std::string version = inst["version"].asString(); 577b2a28edaSopenharmony_ci std::string lastVersion = inst["lastVersion"].asString(); 578b2a28edaSopenharmony_ci Extensions exts = getExts(inst); 579b2a28edaSopenharmony_ci OperandParameters operands; 580b2a28edaSopenharmony_ci bool defResultId = false; 581b2a28edaSopenharmony_ci bool defTypeId = false; 582b2a28edaSopenharmony_ci for (const auto& operand : inst["operands"]) { 583b2a28edaSopenharmony_ci const std::string kind = operand["kind"].asString(); 584b2a28edaSopenharmony_ci const std::string quantifier = operand.get("quantifier", "").asString(); 585b2a28edaSopenharmony_ci const std::string doc = operand.get("name", "").asString(); 586b2a28edaSopenharmony_ci if (!IsTypeOrResultId(kind, &defTypeId, &defResultId)) { 587b2a28edaSopenharmony_ci const auto p = ToOperandClassAndOptionality(kind, quantifier); 588b2a28edaSopenharmony_ci operands.push(p.type, doc, p.optional); 589b2a28edaSopenharmony_ci } 590b2a28edaSopenharmony_ci } 591b2a28edaSopenharmony_ci InstructionDesc.emplace_back( 592b2a28edaSopenharmony_ci std::move(EnumValue(opcode, name, 593b2a28edaSopenharmony_ci std::move(caps), std::move(version), std::move(lastVersion), std::move(exts), 594b2a28edaSopenharmony_ci std::move(operands))), 595b2a28edaSopenharmony_ci printingClass, defTypeId, defResultId); 596b2a28edaSopenharmony_ci if (!InstructionDesc.back().IsValid(OperandOpcode, "instruction")) { 597b2a28edaSopenharmony_ci errorCount++; 598b2a28edaSopenharmony_ci } 599b2a28edaSopenharmony_ci } 600b2a28edaSopenharmony_ci 601b2a28edaSopenharmony_ci // Specific additional context-dependent operands 602b2a28edaSopenharmony_ci 603b2a28edaSopenharmony_ci // Populate dest with EnumValue objects constructed from source. 604b2a28edaSopenharmony_ci const auto populateEnumValues = [&getCaps,&getExts,&errorCount](EnumValues* dest, const Json::Value& source, bool bitEnum) { 605b2a28edaSopenharmony_ci // A lambda for determining the numeric value to be used for a given 606b2a28edaSopenharmony_ci // enumerant in JSON form, and whether that value is a 0 in a bitfield. 607b2a28edaSopenharmony_ci auto getValue = [&bitEnum](const Json::Value& enumerant) { 608b2a28edaSopenharmony_ci std::pair<unsigned, bool> result{0u,false}; 609b2a28edaSopenharmony_ci if (!bitEnum) { 610b2a28edaSopenharmony_ci result.first = enumerant["value"].asUInt(); 611b2a28edaSopenharmony_ci } else { 612b2a28edaSopenharmony_ci const unsigned int bit = NumberStringToBit(enumerant["value"].asString()); 613b2a28edaSopenharmony_ci if (bit == 0) 614b2a28edaSopenharmony_ci result.second = true; 615b2a28edaSopenharmony_ci else 616b2a28edaSopenharmony_ci result.first = bit - 1; // This is the *shift* amount. 617b2a28edaSopenharmony_ci } 618b2a28edaSopenharmony_ci return result; 619b2a28edaSopenharmony_ci }; 620b2a28edaSopenharmony_ci 621b2a28edaSopenharmony_ci unsigned maxValue = 0; 622b2a28edaSopenharmony_ci bool firstValue = true; 623b2a28edaSopenharmony_ci for (const auto& enumerant : source["enumerants"]) { 624b2a28edaSopenharmony_ci unsigned value; 625b2a28edaSopenharmony_ci bool skip_zero_in_bitfield; 626b2a28edaSopenharmony_ci std::tie(value, skip_zero_in_bitfield) = getValue(enumerant); 627b2a28edaSopenharmony_ci if (skip_zero_in_bitfield) 628b2a28edaSopenharmony_ci continue; 629b2a28edaSopenharmony_ci if (firstValue) { 630b2a28edaSopenharmony_ci maxValue = value; 631b2a28edaSopenharmony_ci firstValue = false; 632b2a28edaSopenharmony_ci } else { 633b2a28edaSopenharmony_ci if (maxValue > value) { 634b2a28edaSopenharmony_ci std::cerr << "Error: " << source["kind"] << " enumerant " << enumerant["enumerant"] 635b2a28edaSopenharmony_ci << " is out of order. It has value " << value 636b2a28edaSopenharmony_ci << " but follows the enumerant with value " << maxValue << std::endl; 637b2a28edaSopenharmony_ci std::exit(1); 638b2a28edaSopenharmony_ci } else { 639b2a28edaSopenharmony_ci maxValue = value; 640b2a28edaSopenharmony_ci } 641b2a28edaSopenharmony_ci } 642b2a28edaSopenharmony_ci EnumCaps caps(getCaps(enumerant)); 643b2a28edaSopenharmony_ci std::string version = enumerant["version"].asString(); 644b2a28edaSopenharmony_ci std::string lastVersion = enumerant["lastVersion"].asString(); 645b2a28edaSopenharmony_ci Extensions exts(getExts(enumerant)); 646b2a28edaSopenharmony_ci OperandParameters params; 647b2a28edaSopenharmony_ci const Json::Value& paramsJson = enumerant["parameters"]; 648b2a28edaSopenharmony_ci if (!paramsJson.empty()) { // This enumerant has parameters. 649b2a28edaSopenharmony_ci assert(paramsJson.isArray()); 650b2a28edaSopenharmony_ci for (const auto& param : paramsJson) { 651b2a28edaSopenharmony_ci const std::string kind = param["kind"].asString(); 652b2a28edaSopenharmony_ci const std::string doc = param.get("name", "").asString(); 653b2a28edaSopenharmony_ci const auto p = ToOperandClassAndOptionality(kind, ""); // All parameters are required! 654b2a28edaSopenharmony_ci params.push(p.type, doc); 655b2a28edaSopenharmony_ci } 656b2a28edaSopenharmony_ci } 657b2a28edaSopenharmony_ci dest->emplace_back( 658b2a28edaSopenharmony_ci value, enumerant["enumerant"].asString(), 659b2a28edaSopenharmony_ci std::move(caps), std::move(version), std::move(lastVersion), std::move(exts), std::move(params)); 660b2a28edaSopenharmony_ci } 661b2a28edaSopenharmony_ci }; 662b2a28edaSopenharmony_ci 663b2a28edaSopenharmony_ci const auto establishOperandClass = [&populateEnumValues,&errorCount]( 664b2a28edaSopenharmony_ci const std::string& enumName, spv::OperandClass operandClass, 665b2a28edaSopenharmony_ci spv::EnumValues* enumValues, const Json::Value& operandEnum, const std::string& category) { 666b2a28edaSopenharmony_ci assert(category == "BitEnum" || category == "ValueEnum"); 667b2a28edaSopenharmony_ci bool bitEnum = (category == "BitEnum"); 668b2a28edaSopenharmony_ci if (!operandEnum["version"].empty()) { 669b2a28edaSopenharmony_ci std::cerr << "Error: container for " << enumName << " operand_kind must not have a version field" << std::endl; 670b2a28edaSopenharmony_ci errorCount++; 671b2a28edaSopenharmony_ci } 672b2a28edaSopenharmony_ci populateEnumValues(enumValues, operandEnum, bitEnum); 673b2a28edaSopenharmony_ci const std::string errContext = "enum " + enumName; 674b2a28edaSopenharmony_ci for (const auto& e: *enumValues) { 675b2a28edaSopenharmony_ci if (!e.IsValid(operandClass, errContext)) { 676b2a28edaSopenharmony_ci errorCount++; 677b2a28edaSopenharmony_ci } 678b2a28edaSopenharmony_ci } 679b2a28edaSopenharmony_ci OperandClassParams[operandClass].set(enumName, enumValues, bitEnum); 680b2a28edaSopenharmony_ci }; 681b2a28edaSopenharmony_ci 682b2a28edaSopenharmony_ci const Json::Value operandEnums = root["operand_kinds"]; 683b2a28edaSopenharmony_ci for (const auto& operandEnum : operandEnums) { 684b2a28edaSopenharmony_ci const std::string enumName = operandEnum["kind"].asString(); 685b2a28edaSopenharmony_ci const std::string category = operandEnum["category"].asString(); 686b2a28edaSopenharmony_ci if (enumName == "SourceLanguage") { 687b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandSource, &SourceLanguageParams, operandEnum, category); 688b2a28edaSopenharmony_ci } else if (enumName == "Decoration") { 689b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandDecoration, &DecorationParams, operandEnum, category); 690b2a28edaSopenharmony_ci } else if (enumName == "ExecutionMode") { 691b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandExecutionMode, &ExecutionModeParams, operandEnum, category); 692b2a28edaSopenharmony_ci } else if (enumName == "Capability") { 693b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandCapability, &CapabilityParams, operandEnum, category); 694b2a28edaSopenharmony_ci } else if (enumName == "AddressingModel") { 695b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandAddressing, &AddressingParams, operandEnum, category); 696b2a28edaSopenharmony_ci } else if (enumName == "MemoryModel") { 697b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandMemory, &MemoryParams, operandEnum, category); 698b2a28edaSopenharmony_ci } else if (enumName == "MemorySemantics") { 699b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandMemorySemantics, &MemorySemanticsParams, operandEnum, category); 700b2a28edaSopenharmony_ci } else if (enumName == "ExecutionModel") { 701b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandExecutionModel, &ExecutionModelParams, operandEnum, category); 702b2a28edaSopenharmony_ci } else if (enumName == "StorageClass") { 703b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandStorage, &StorageParams, operandEnum, category); 704b2a28edaSopenharmony_ci } else if (enumName == "SamplerAddressingMode") { 705b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandSamplerAddressingMode, &SamplerAddressingModeParams, operandEnum, category); 706b2a28edaSopenharmony_ci } else if (enumName == "SamplerFilterMode") { 707b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandSamplerFilterMode, &SamplerFilterModeParams, operandEnum, category); 708b2a28edaSopenharmony_ci } else if (enumName == "ImageFormat") { 709b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandSamplerImageFormat, &ImageFormatParams, operandEnum, category); 710b2a28edaSopenharmony_ci } else if (enumName == "ImageChannelOrder") { 711b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandImageChannelOrder, &ImageChannelOrderParams, operandEnum, category); 712b2a28edaSopenharmony_ci } else if (enumName == "ImageChannelDataType") { 713b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandImageChannelDataType, &ImageChannelDataTypeParams, operandEnum, category); 714b2a28edaSopenharmony_ci } else if (enumName == "ImageOperands") { 715b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandImageOperands, &ImageOperandsParams, operandEnum, category); 716b2a28edaSopenharmony_ci } else if (enumName == "FPFastMathMode") { 717b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandFPFastMath, &FPFastMathParams, operandEnum, category); 718b2a28edaSopenharmony_ci } else if (enumName == "FPRoundingMode") { 719b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandFPRoundingMode, &FPRoundingModeParams, operandEnum, category); 720b2a28edaSopenharmony_ci } else if (enumName == "FPDenormMode") { 721b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandFPDenormMode, &FPDenormModeParams, operandEnum, category); 722b2a28edaSopenharmony_ci } else if (enumName == "FPOperationMode") { 723b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandFPOperationMode, &FPOperationModeParams, operandEnum, category); 724b2a28edaSopenharmony_ci } else if (enumName == "QuantizationModes") { 725b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandQuantizationModes, &QuantizationModesParams, operandEnum, category); 726b2a28edaSopenharmony_ci } else if (enumName == "OverflowModes") { 727b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandOverflowModes, &OverflowModesParams, operandEnum, category); 728b2a28edaSopenharmony_ci } else if (enumName == "LinkageType") { 729b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandLinkageType, &LinkageTypeParams, operandEnum, category); 730b2a28edaSopenharmony_ci } else if (enumName == "FunctionParameterAttribute") { 731b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandFuncParamAttr, &FuncParamAttrParams, operandEnum, category); 732b2a28edaSopenharmony_ci } else if (enumName == "AccessQualifier") { 733b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandAccessQualifier, &AccessQualifierParams, operandEnum, category); 734b2a28edaSopenharmony_ci } else if (enumName == "BuiltIn") { 735b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandBuiltIn, &BuiltInParams, operandEnum, category); 736b2a28edaSopenharmony_ci } else if (enumName == "SelectionControl") { 737b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandSelect, &SelectionControlParams, operandEnum, category); 738b2a28edaSopenharmony_ci } else if (enumName == "LoopControl") { 739b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandLoop, &LoopControlParams, operandEnum, category); 740b2a28edaSopenharmony_ci } else if (enumName == "FunctionControl") { 741b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandFunction, &FunctionControlParams, operandEnum, category); 742b2a28edaSopenharmony_ci } else if (enumName == "Dim") { 743b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandDimensionality, &DimensionalityParams, operandEnum, category); 744b2a28edaSopenharmony_ci } else if (enumName == "MemoryAccess") { 745b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandMemoryOperands, &MemoryAccessParams, operandEnum, category); 746b2a28edaSopenharmony_ci } else if (enumName == "Scope") { 747b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandScope, &ScopeParams, operandEnum, category); 748b2a28edaSopenharmony_ci } else if (enumName == "GroupOperation") { 749b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandGroupOperation, &GroupOperationParams, operandEnum, category); 750b2a28edaSopenharmony_ci } else if (enumName == "KernelEnqueueFlags") { 751b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandKernelEnqueueFlags, &KernelEnqueueFlagsParams, operandEnum, category); 752b2a28edaSopenharmony_ci } else if (enumName == "KernelProfilingInfo") { 753b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandKernelProfilingInfo, &KernelProfilingInfoParams, operandEnum, category); 754b2a28edaSopenharmony_ci } else if (enumName == "RayFlags") { 755b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandRayFlags, &RayFlagsParams, operandEnum, category); 756b2a28edaSopenharmony_ci } else if (enumName == "RayQueryIntersection") { 757b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandRayQueryIntersection, &RayQueryIntersectionParams, operandEnum, category); 758b2a28edaSopenharmony_ci } else if (enumName == "RayQueryCommittedIntersectionType") { 759b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandRayQueryCommittedIntersectionType, &RayQueryCommittedIntersectionTypeParams, operandEnum, category); 760b2a28edaSopenharmony_ci } else if (enumName == "RayQueryCandidateIntersectionType") { 761b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandRayQueryCandidateIntersectionType, &RayQueryCandidateIntersectionTypeParams, operandEnum, category); 762b2a28edaSopenharmony_ci } else if (enumName == "FragmentShadingRate") { 763b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandFragmentShadingRate, &FragmentShadingRateParams, operandEnum, category); 764b2a28edaSopenharmony_ci } else if (enumName == "PackedVectorFormat") { 765b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandPackedVectorFormat, &PackedVectorFormatParams, operandEnum, category); 766b2a28edaSopenharmony_ci } else if (enumName == "CooperativeMatrixOperands") { 767b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandCooperativeMatrixOperands, &CooperativeMatrixOperandsParams, operandEnum, category); 768b2a28edaSopenharmony_ci } else if (enumName == "CooperativeMatrixLayout") { 769b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandCooperativeMatrixLayout, &CooperativeMatrixLayoutParams, operandEnum, category); 770b2a28edaSopenharmony_ci } else if (enumName == "CooperativeMatrixUse") { 771b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandCooperativeMatrixUse, &CooperativeMatrixUseParams, operandEnum, category); 772b2a28edaSopenharmony_ci } else if (enumName == "InitializationModeQualifier") { 773b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandInitializationModeQualifier, &InitializationModeQualifierParams, operandEnum, category); 774b2a28edaSopenharmony_ci } else if (enumName == "HostAccessQualifier") { 775b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandHostAccessQualifier, &HostAccessQualifierParams, operandEnum, category); 776b2a28edaSopenharmony_ci } else if (enumName == "LoadCacheControl") { 777b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandLoadCacheControl, &LoadCacheControlParams, operandEnum, category); 778b2a28edaSopenharmony_ci } else if (enumName == "StoreCacheControl") { 779b2a28edaSopenharmony_ci establishOperandClass(enumName, OperandStoreCacheControl, &StoreCacheControlParams, operandEnum, category); 780b2a28edaSopenharmony_ci } 781b2a28edaSopenharmony_ci } 782b2a28edaSopenharmony_ci 783b2a28edaSopenharmony_ci if (errorCount > 0) { 784b2a28edaSopenharmony_ci std::exit(1); 785b2a28edaSopenharmony_ci } 786b2a28edaSopenharmony_ci} 787b2a28edaSopenharmony_ci 788b2a28edaSopenharmony_ci}; // end namespace spv 789