1 // Copyright (c) 2015-2016 The Khronos Group Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "operand.h" 16 17 #include <assert.h> 18 #include <string.h> 19 #include <algorithm> 20 21 #include "macro.h" 22 23 // Pull in operand info tables automatically generated from JSON grammar. 24 namespace v1_0 { 25 #include "operand.kinds-1.0.inc" 26 } // namespace v1_0 27 namespace v1_1 { 28 #include "operand.kinds-1.1.inc" 29 } // namespace v1_1 30 namespace v1_2 { 31 #include "operand.kinds-1.2.inc" 32 } // namespace v1_2 33 34 spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable, 35 spv_target_env env) { 36 if (!pOperandTable) return SPV_ERROR_INVALID_POINTER; 37 38 static const spv_operand_table_t table_1_0 = { 39 ARRAY_SIZE(v1_0::pygen_variable_OperandInfoTable), 40 v1_0::pygen_variable_OperandInfoTable}; 41 static const spv_operand_table_t table_1_1 = { 42 ARRAY_SIZE(v1_1::pygen_variable_OperandInfoTable), 43 v1_1::pygen_variable_OperandInfoTable}; 44 static const spv_operand_table_t table_1_2 = { 45 ARRAY_SIZE(v1_2::pygen_variable_OperandInfoTable), 46 v1_2::pygen_variable_OperandInfoTable}; 47 48 switch (env) { 49 case SPV_ENV_UNIVERSAL_1_0: 50 case SPV_ENV_VULKAN_1_0: 51 case SPV_ENV_OPENCL_2_1: 52 case SPV_ENV_OPENGL_4_0: 53 case SPV_ENV_OPENGL_4_1: 54 case SPV_ENV_OPENGL_4_2: 55 case SPV_ENV_OPENGL_4_3: 56 case SPV_ENV_OPENGL_4_5: 57 *pOperandTable = &table_1_0; 58 return SPV_SUCCESS; 59 case SPV_ENV_UNIVERSAL_1_1: 60 *pOperandTable = &table_1_1; 61 return SPV_SUCCESS; 62 case SPV_ENV_UNIVERSAL_1_2: 63 case SPV_ENV_OPENCL_2_2: 64 *pOperandTable = &table_1_2; 65 return SPV_SUCCESS; 66 } 67 assert(0 && "Unknown spv_target_env in spvOperandTableGet()"); 68 return SPV_ERROR_INVALID_TABLE; 69 } 70 71 #undef ARRAY_SIZE 72 73 spv_result_t spvOperandTableNameLookup(const spv_operand_table table, 74 const spv_operand_type_t type, 75 const char* name, 76 const size_t nameLength, 77 spv_operand_desc* pEntry) { 78 if (!table) return SPV_ERROR_INVALID_TABLE; 79 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER; 80 81 for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) { 82 const auto& group = table->types[typeIndex]; 83 if (type != group.type) continue; 84 for (uint64_t index = 0; index < group.count; ++index) { 85 const auto& entry = group.entries[index]; 86 if (nameLength == strlen(entry.name) && 87 !strncmp(entry.name, name, nameLength)) { 88 *pEntry = &entry; 89 return SPV_SUCCESS; 90 } 91 } 92 } 93 94 return SPV_ERROR_INVALID_LOOKUP; 95 } 96 97 spv_result_t spvOperandTableValueLookup(const spv_operand_table table, 98 const spv_operand_type_t type, 99 const uint32_t value, 100 spv_operand_desc* pEntry) { 101 if (!table) return SPV_ERROR_INVALID_TABLE; 102 if (!pEntry) return SPV_ERROR_INVALID_POINTER; 103 104 for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) { 105 const auto& group = table->types[typeIndex]; 106 if (type != group.type) continue; 107 for (uint64_t index = 0; index < group.count; ++index) { 108 const auto& entry = group.entries[index]; 109 if (value == entry.value) { 110 *pEntry = &entry; 111 return SPV_SUCCESS; 112 } 113 } 114 } 115 116 return SPV_ERROR_INVALID_LOOKUP; 117 } 118 119 const char* spvOperandTypeStr(spv_operand_type_t type) { 120 switch (type) { 121 case SPV_OPERAND_TYPE_ID: 122 case SPV_OPERAND_TYPE_OPTIONAL_ID: 123 return "ID"; 124 case SPV_OPERAND_TYPE_TYPE_ID: 125 return "type ID"; 126 case SPV_OPERAND_TYPE_RESULT_ID: 127 return "result ID"; 128 case SPV_OPERAND_TYPE_LITERAL_INTEGER: 129 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER: 130 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER: 131 return "literal number"; 132 case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER: 133 return "possibly multi-word literal integer"; 134 case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER: 135 return "possibly multi-word literal number"; 136 case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: 137 return "extension instruction number"; 138 case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: 139 return "OpSpecConstantOp opcode"; 140 case SPV_OPERAND_TYPE_LITERAL_STRING: 141 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: 142 return "literal string"; 143 case SPV_OPERAND_TYPE_SOURCE_LANGUAGE: 144 return "source language"; 145 case SPV_OPERAND_TYPE_EXECUTION_MODEL: 146 return "execution model"; 147 case SPV_OPERAND_TYPE_ADDRESSING_MODEL: 148 return "addressing model"; 149 case SPV_OPERAND_TYPE_MEMORY_MODEL: 150 return "memory model"; 151 case SPV_OPERAND_TYPE_EXECUTION_MODE: 152 return "execution mode"; 153 case SPV_OPERAND_TYPE_STORAGE_CLASS: 154 return "storage class"; 155 case SPV_OPERAND_TYPE_DIMENSIONALITY: 156 return "dimensionality"; 157 case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE: 158 return "sampler addressing mode"; 159 case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE: 160 return "sampler filter mode"; 161 case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT: 162 return "image format"; 163 case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE: 164 return "floating-point fast math mode"; 165 case SPV_OPERAND_TYPE_FP_ROUNDING_MODE: 166 return "floating-point rounding mode"; 167 case SPV_OPERAND_TYPE_LINKAGE_TYPE: 168 return "linkage type"; 169 case SPV_OPERAND_TYPE_ACCESS_QUALIFIER: 170 case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER: 171 return "access qualifier"; 172 case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE: 173 return "function parameter attribute"; 174 case SPV_OPERAND_TYPE_DECORATION: 175 return "decoration"; 176 case SPV_OPERAND_TYPE_BUILT_IN: 177 return "built-in"; 178 case SPV_OPERAND_TYPE_SELECTION_CONTROL: 179 return "selection control"; 180 case SPV_OPERAND_TYPE_LOOP_CONTROL: 181 return "loop control"; 182 case SPV_OPERAND_TYPE_FUNCTION_CONTROL: 183 return "function control"; 184 case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID: 185 return "memory semantics ID"; 186 case SPV_OPERAND_TYPE_MEMORY_ACCESS: 187 case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS: 188 return "memory access"; 189 case SPV_OPERAND_TYPE_SCOPE_ID: 190 return "scope ID"; 191 case SPV_OPERAND_TYPE_GROUP_OPERATION: 192 return "group operation"; 193 case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS: 194 return "kernel enqeue flags"; 195 case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO: 196 return "kernel profiling info"; 197 case SPV_OPERAND_TYPE_CAPABILITY: 198 return "capability"; 199 case SPV_OPERAND_TYPE_IMAGE: 200 case SPV_OPERAND_TYPE_OPTIONAL_IMAGE: 201 return "image"; 202 case SPV_OPERAND_TYPE_OPTIONAL_CIV: 203 return "context-insensitive value"; 204 205 // The next values are for values returned from an instruction, not actually 206 // an operand. So the specific strings don't matter. But let's add them 207 // for completeness and ease of testing. 208 case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER: 209 return "image channel order"; 210 case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE: 211 return "image channel data type"; 212 213 case SPV_OPERAND_TYPE_NONE: 214 return "NONE"; 215 default: 216 assert(0 && "Unhandled operand type!"); 217 break; 218 } 219 return "unknown"; 220 } 221 222 void spvPushOperandTypes(const spv_operand_type_t* types, 223 spv_operand_pattern_t* pattern) { 224 const spv_operand_type_t* endTypes; 225 for (endTypes = types; *endTypes != SPV_OPERAND_TYPE_NONE; ++endTypes) 226 ; 227 while (endTypes-- != types) { 228 pattern->push_back(*endTypes); 229 } 230 } 231 232 void spvPushOperandTypesForMask(const spv_operand_table operandTable, 233 const spv_operand_type_t type, 234 const uint32_t mask, 235 spv_operand_pattern_t* pattern) { 236 // Scan from highest bits to lowest bits because we will append in LIFO 237 // fashion, and we need the operands for lower order bits to be consumed first 238 for (uint32_t candidate_bit = (1u << 31u); candidate_bit; candidate_bit >>= 1) { 239 if (candidate_bit & mask) { 240 spv_operand_desc entry = nullptr; 241 if (SPV_SUCCESS == spvOperandTableValueLookup(operandTable, type, 242 candidate_bit, &entry)) { 243 spvPushOperandTypes(entry->operandTypes, pattern); 244 } 245 } 246 } 247 } 248 249 bool spvOperandIsConcreteMask(spv_operand_type_t type) { 250 return SPV_OPERAND_TYPE_FIRST_CONCRETE_MASK_TYPE <= type && 251 type <= SPV_OPERAND_TYPE_LAST_CONCRETE_MASK_TYPE; 252 } 253 254 bool spvOperandIsOptional(spv_operand_type_t type) { 255 return SPV_OPERAND_TYPE_FIRST_OPTIONAL_TYPE <= type && 256 type <= SPV_OPERAND_TYPE_LAST_OPTIONAL_TYPE; 257 } 258 259 bool spvOperandIsVariable(spv_operand_type_t type) { 260 return SPV_OPERAND_TYPE_FIRST_VARIABLE_TYPE <= type && 261 type <= SPV_OPERAND_TYPE_LAST_VARIABLE_TYPE; 262 } 263 264 bool spvExpandOperandSequenceOnce(spv_operand_type_t type, 265 spv_operand_pattern_t* pattern) { 266 switch (type) { 267 case SPV_OPERAND_TYPE_VARIABLE_ID: 268 pattern->push_back(type); 269 pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_ID); 270 return true; 271 case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER: 272 pattern->push_back(type); 273 pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER); 274 return true; 275 case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID: 276 // Represents Zero or more (Literal number, Id) pairs, 277 // where the literal number must be a scalar integer. 278 pattern->push_back(type); 279 pattern->push_back(SPV_OPERAND_TYPE_ID); 280 pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER); 281 return true; 282 case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER: 283 // Represents Zero or more (Id, Literal number) pairs. 284 pattern->push_back(type); 285 pattern->push_back(SPV_OPERAND_TYPE_LITERAL_INTEGER); 286 pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_ID); 287 return true; 288 default: 289 break; 290 } 291 return false; 292 } 293 294 spv_operand_type_t spvTakeFirstMatchableOperand( 295 spv_operand_pattern_t* pattern) { 296 assert(!pattern->empty()); 297 spv_operand_type_t result; 298 do { 299 result = pattern->back(); 300 pattern->pop_back(); 301 } while (spvExpandOperandSequenceOnce(result, pattern)); 302 return result; 303 } 304 305 spv_operand_pattern_t spvAlternatePatternFollowingImmediate( 306 const spv_operand_pattern_t& pattern) { 307 308 auto it = std::find(pattern.crbegin(), pattern.crend(), SPV_OPERAND_TYPE_RESULT_ID); 309 if (it != pattern.crend()) { 310 spv_operand_pattern_t alternatePattern(it - pattern.crbegin() + 2, SPV_OPERAND_TYPE_OPTIONAL_CIV); 311 alternatePattern[1] = SPV_OPERAND_TYPE_RESULT_ID; 312 return alternatePattern; 313 } 314 315 // No result-id found, so just expect CIVs. 316 return{ SPV_OPERAND_TYPE_OPTIONAL_CIV }; 317 } 318 319 bool spvIsIdType(spv_operand_type_t type) { 320 switch (type) { 321 case SPV_OPERAND_TYPE_ID: 322 case SPV_OPERAND_TYPE_TYPE_ID: 323 case SPV_OPERAND_TYPE_RESULT_ID: 324 case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID: 325 case SPV_OPERAND_TYPE_SCOPE_ID: 326 return true; 327 default: 328 return false; 329 } 330 } 331