Home | History | Annotate | Download | only in source
      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 "source/operand.h"
     16 
     17 #include <assert.h>
     18 #include <string.h>
     19 #include <algorithm>
     20 
     21 #include "source/macro.h"
     22 #include "source/spirv_constant.h"
     23 #include "source/spirv_target_env.h"
     24 
     25 // For now, assume unified1 contains up to SPIR-V 1.3 and no later
     26 // SPIR-V version.
     27 // TODO(dneto): Make one set of tables, but with version tags on a
     28 // per-item basis. https://github.com/KhronosGroup/SPIRV-Tools/issues/1195
     29 
     30 #include "operand.kinds-unified1.inc"
     31 
     32 static const spv_operand_table_t kOperandTable = {
     33     ARRAY_SIZE(pygen_variable_OperandInfoTable),
     34     pygen_variable_OperandInfoTable};
     35 
     36 spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable,
     37                                 spv_target_env) {
     38   if (!pOperandTable) return SPV_ERROR_INVALID_POINTER;
     39 
     40   *pOperandTable = &kOperandTable;
     41   return SPV_SUCCESS;
     42 }
     43 
     44 spv_result_t spvOperandTableNameLookup(spv_target_env env,
     45                                        const spv_operand_table table,
     46                                        const spv_operand_type_t type,
     47                                        const char* name,
     48                                        const size_t nameLength,
     49                                        spv_operand_desc* pEntry) {
     50   if (!table) return SPV_ERROR_INVALID_TABLE;
     51   if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
     52 
     53   for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
     54     const auto& group = table->types[typeIndex];
     55     if (type != group.type) continue;
     56     for (uint64_t index = 0; index < group.count; ++index) {
     57       const auto& entry = group.entries[index];
     58       // We consider the current operand as available as long as
     59       // 1. The target environment satisfies the minimal requirement of the
     60       //    operand; or
     61       // 2. There is at least one extension enabling this operand; or
     62       // 3. There is at least one capability enabling this operand.
     63       //
     64       // Note that the second rule assumes the extension enabling this operand
     65       // is indeed requested in the SPIR-V code; checking that should be
     66       // validator's work.
     67       if ((spvVersionForTargetEnv(env) >= entry.minVersion ||
     68            entry.numExtensions > 0u || entry.numCapabilities > 0u) &&
     69           nameLength == strlen(entry.name) &&
     70           !strncmp(entry.name, name, nameLength)) {
     71         *pEntry = &entry;
     72         return SPV_SUCCESS;
     73       }
     74     }
     75   }
     76 
     77   return SPV_ERROR_INVALID_LOOKUP;
     78 }
     79 
     80 spv_result_t spvOperandTableValueLookup(spv_target_env env,
     81                                         const spv_operand_table table,
     82                                         const spv_operand_type_t type,
     83                                         const uint32_t value,
     84                                         spv_operand_desc* pEntry) {
     85   if (!table) return SPV_ERROR_INVALID_TABLE;
     86   if (!pEntry) return SPV_ERROR_INVALID_POINTER;
     87 
     88   spv_operand_desc_t needle = {"", value, 0, nullptr, 0, nullptr, {}, ~0u};
     89 
     90   auto comp = [](const spv_operand_desc_t& lhs, const spv_operand_desc_t& rhs) {
     91     return lhs.value < rhs.value;
     92   };
     93 
     94   for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
     95     const auto& group = table->types[typeIndex];
     96     if (type != group.type) continue;
     97 
     98     const auto beg = group.entries;
     99     const auto end = group.entries + group.count;
    100 
    101     // We need to loop here because there can exist multiple symbols for the
    102     // same operand value, and they can be introduced in different target
    103     // environments, which means they can have different minimal version
    104     // requirements. For example, SubgroupEqMaskKHR can exist in any SPIR-V
    105     // version as long as the SPV_KHR_shader_ballot extension is there; but
    106     // starting from SPIR-V 1.3, SubgroupEqMask, which has the same numeric
    107     // value as SubgroupEqMaskKHR, is available in core SPIR-V without extension
    108     // requirements.
    109     // Assumes the underlying table is already sorted ascendingly according to
    110     // opcode value.
    111     for (auto it = std::lower_bound(beg, end, needle, comp);
    112          it != end && it->value == value; ++it) {
    113       // We consider the current operand as available as long as
    114       // 1. The target environment satisfies the minimal requirement of the
    115       //    operand; or
    116       // 2. There is at least one extension enabling this operand; or
    117       // 3. There is at least one capability enabling this operand.
    118       //
    119       // Note that the second rule assumes the extension enabling this operand
    120       // is indeed requested in the SPIR-V code; checking that should be
    121       // validator's work.
    122       if (spvVersionForTargetEnv(env) >= it->minVersion ||
    123           it->numExtensions > 0u || it->numCapabilities > 0u) {
    124         *pEntry = it;
    125         return SPV_SUCCESS;
    126       }
    127     }
    128   }
    129 
    130   return SPV_ERROR_INVALID_LOOKUP;
    131 }
    132 
    133 const char* spvOperandTypeStr(spv_operand_type_t type) {
    134   switch (type) {
    135     case SPV_OPERAND_TYPE_ID:
    136     case SPV_OPERAND_TYPE_OPTIONAL_ID:
    137       return "ID";
    138     case SPV_OPERAND_TYPE_TYPE_ID:
    139       return "type ID";
    140     case SPV_OPERAND_TYPE_RESULT_ID:
    141       return "result ID";
    142     case SPV_OPERAND_TYPE_LITERAL_INTEGER:
    143     case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER:
    144     case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER:
    145       return "literal number";
    146     case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
    147       return "possibly multi-word literal integer";
    148     case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
    149       return "possibly multi-word literal number";
    150     case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
    151       return "extension instruction number";
    152     case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER:
    153       return "OpSpecConstantOp opcode";
    154     case SPV_OPERAND_TYPE_LITERAL_STRING:
    155     case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING:
    156       return "literal string";
    157     case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
    158       return "source language";
    159     case SPV_OPERAND_TYPE_EXECUTION_MODEL:
    160       return "execution model";
    161     case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
    162       return "addressing model";
    163     case SPV_OPERAND_TYPE_MEMORY_MODEL:
    164       return "memory model";
    165     case SPV_OPERAND_TYPE_EXECUTION_MODE:
    166       return "execution mode";
    167     case SPV_OPERAND_TYPE_STORAGE_CLASS:
    168       return "storage class";
    169     case SPV_OPERAND_TYPE_DIMENSIONALITY:
    170       return "dimensionality";
    171     case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
    172       return "sampler addressing mode";
    173     case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
    174       return "sampler filter mode";
    175     case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
    176       return "image format";
    177     case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
    178       return "floating-point fast math mode";
    179     case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
    180       return "floating-point rounding mode";
    181     case SPV_OPERAND_TYPE_LINKAGE_TYPE:
    182       return "linkage type";
    183     case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
    184     case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER:
    185       return "access qualifier";
    186     case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
    187       return "function parameter attribute";
    188     case SPV_OPERAND_TYPE_DECORATION:
    189       return "decoration";
    190     case SPV_OPERAND_TYPE_BUILT_IN:
    191       return "built-in";
    192     case SPV_OPERAND_TYPE_SELECTION_CONTROL:
    193       return "selection control";
    194     case SPV_OPERAND_TYPE_LOOP_CONTROL:
    195       return "loop control";
    196     case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
    197       return "function control";
    198     case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
    199       return "memory semantics ID";
    200     case SPV_OPERAND_TYPE_MEMORY_ACCESS:
    201     case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
    202       return "memory access";
    203     case SPV_OPERAND_TYPE_SCOPE_ID:
    204       return "scope ID";
    205     case SPV_OPERAND_TYPE_GROUP_OPERATION:
    206       return "group operation";
    207     case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
    208       return "kernel enqeue flags";
    209     case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
    210       return "kernel profiling info";
    211     case SPV_OPERAND_TYPE_CAPABILITY:
    212       return "capability";
    213     case SPV_OPERAND_TYPE_IMAGE:
    214     case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
    215       return "image";
    216     case SPV_OPERAND_TYPE_OPTIONAL_CIV:
    217       return "context-insensitive value";
    218     case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
    219       return "debug info flags";
    220     case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
    221       return "debug base type encoding";
    222     case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
    223       return "debug composite type";
    224     case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
    225       return "debug type qualifier";
    226     case SPV_OPERAND_TYPE_DEBUG_OPERATION:
    227       return "debug operation";
    228 
    229     // The next values are for values returned from an instruction, not actually
    230     // an operand.  So the specific strings don't matter.  But let's add them
    231     // for completeness and ease of testing.
    232     case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER:
    233       return "image channel order";
    234     case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE:
    235       return "image channel data type";
    236 
    237     case SPV_OPERAND_TYPE_NONE:
    238       return "NONE";
    239     default:
    240       assert(0 && "Unhandled operand type!");
    241       break;
    242   }
    243   return "unknown";
    244 }
    245 
    246 void spvPushOperandTypes(const spv_operand_type_t* types,
    247                          spv_operand_pattern_t* pattern) {
    248   const spv_operand_type_t* endTypes;
    249   for (endTypes = types; *endTypes != SPV_OPERAND_TYPE_NONE; ++endTypes) {
    250   }
    251 
    252   while (endTypes-- != types) {
    253     pattern->push_back(*endTypes);
    254   }
    255 }
    256 
    257 void spvPushOperandTypesForMask(spv_target_env env,
    258                                 const spv_operand_table operandTable,
    259                                 const spv_operand_type_t type,
    260                                 const uint32_t mask,
    261                                 spv_operand_pattern_t* pattern) {
    262   // Scan from highest bits to lowest bits because we will append in LIFO
    263   // fashion, and we need the operands for lower order bits to be consumed first
    264   for (uint32_t candidate_bit = (1u << 31u); candidate_bit;
    265        candidate_bit >>= 1) {
    266     if (candidate_bit & mask) {
    267       spv_operand_desc entry = nullptr;
    268       if (SPV_SUCCESS == spvOperandTableValueLookup(env, operandTable, type,
    269                                                     candidate_bit, &entry)) {
    270         spvPushOperandTypes(entry->operandTypes, pattern);
    271       }
    272     }
    273   }
    274 }
    275 
    276 bool spvOperandIsConcrete(spv_operand_type_t type) {
    277   if (spvIsIdType(type) || spvOperandIsConcreteMask(type)) {
    278     return true;
    279   }
    280   switch (type) {
    281     case SPV_OPERAND_TYPE_LITERAL_INTEGER:
    282     case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
    283     case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER:
    284     case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
    285     case SPV_OPERAND_TYPE_LITERAL_STRING:
    286     case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
    287     case SPV_OPERAND_TYPE_EXECUTION_MODEL:
    288     case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
    289     case SPV_OPERAND_TYPE_MEMORY_MODEL:
    290     case SPV_OPERAND_TYPE_EXECUTION_MODE:
    291     case SPV_OPERAND_TYPE_STORAGE_CLASS:
    292     case SPV_OPERAND_TYPE_DIMENSIONALITY:
    293     case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
    294     case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
    295     case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
    296     case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER:
    297     case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE:
    298     case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
    299     case SPV_OPERAND_TYPE_LINKAGE_TYPE:
    300     case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
    301     case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
    302     case SPV_OPERAND_TYPE_DECORATION:
    303     case SPV_OPERAND_TYPE_BUILT_IN:
    304     case SPV_OPERAND_TYPE_GROUP_OPERATION:
    305     case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
    306     case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
    307     case SPV_OPERAND_TYPE_CAPABILITY:
    308     case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
    309     case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
    310     case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
    311     case SPV_OPERAND_TYPE_DEBUG_OPERATION:
    312       return true;
    313     default:
    314       break;
    315   }
    316   return false;
    317 }
    318 
    319 bool spvOperandIsConcreteMask(spv_operand_type_t type) {
    320   switch (type) {
    321     case SPV_OPERAND_TYPE_IMAGE:
    322     case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
    323     case SPV_OPERAND_TYPE_SELECTION_CONTROL:
    324     case SPV_OPERAND_TYPE_LOOP_CONTROL:
    325     case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
    326     case SPV_OPERAND_TYPE_MEMORY_ACCESS:
    327     case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
    328       return true;
    329     default:
    330       break;
    331   }
    332   return false;
    333 }
    334 
    335 bool spvOperandIsOptional(spv_operand_type_t type) {
    336   return SPV_OPERAND_TYPE_FIRST_OPTIONAL_TYPE <= type &&
    337          type <= SPV_OPERAND_TYPE_LAST_OPTIONAL_TYPE;
    338 }
    339 
    340 bool spvOperandIsVariable(spv_operand_type_t type) {
    341   return SPV_OPERAND_TYPE_FIRST_VARIABLE_TYPE <= type &&
    342          type <= SPV_OPERAND_TYPE_LAST_VARIABLE_TYPE;
    343 }
    344 
    345 bool spvExpandOperandSequenceOnce(spv_operand_type_t type,
    346                                   spv_operand_pattern_t* pattern) {
    347   switch (type) {
    348     case SPV_OPERAND_TYPE_VARIABLE_ID:
    349       pattern->push_back(type);
    350       pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_ID);
    351       return true;
    352     case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER:
    353       pattern->push_back(type);
    354       pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER);
    355       return true;
    356     case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID:
    357       // Represents Zero or more (Literal number, Id) pairs,
    358       // where the literal number must be a scalar integer.
    359       pattern->push_back(type);
    360       pattern->push_back(SPV_OPERAND_TYPE_ID);
    361       pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER);
    362       return true;
    363     case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER:
    364       // Represents Zero or more (Id, Literal number) pairs.
    365       pattern->push_back(type);
    366       pattern->push_back(SPV_OPERAND_TYPE_LITERAL_INTEGER);
    367       pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_ID);
    368       return true;
    369     default:
    370       break;
    371   }
    372   return false;
    373 }
    374 
    375 spv_operand_type_t spvTakeFirstMatchableOperand(
    376     spv_operand_pattern_t* pattern) {
    377   assert(!pattern->empty());
    378   spv_operand_type_t result;
    379   do {
    380     result = pattern->back();
    381     pattern->pop_back();
    382   } while (spvExpandOperandSequenceOnce(result, pattern));
    383   return result;
    384 }
    385 
    386 spv_operand_pattern_t spvAlternatePatternFollowingImmediate(
    387     const spv_operand_pattern_t& pattern) {
    388   auto it =
    389       std::find(pattern.crbegin(), pattern.crend(), SPV_OPERAND_TYPE_RESULT_ID);
    390   if (it != pattern.crend()) {
    391     spv_operand_pattern_t alternatePattern(it - pattern.crbegin() + 2,
    392                                            SPV_OPERAND_TYPE_OPTIONAL_CIV);
    393     alternatePattern[1] = SPV_OPERAND_TYPE_RESULT_ID;
    394     return alternatePattern;
    395   }
    396 
    397   // No result-id found, so just expect CIVs.
    398   return {SPV_OPERAND_TYPE_OPTIONAL_CIV};
    399 }
    400 
    401 bool spvIsIdType(spv_operand_type_t type) {
    402   switch (type) {
    403     case SPV_OPERAND_TYPE_ID:
    404     case SPV_OPERAND_TYPE_TYPE_ID:
    405     case SPV_OPERAND_TYPE_RESULT_ID:
    406     case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
    407     case SPV_OPERAND_TYPE_SCOPE_ID:
    408       return true;
    409     default:
    410       return false;
    411   }
    412 }
    413 
    414 bool spvIsInIdType(spv_operand_type_t type) {
    415   if (!spvIsIdType(type)) {
    416     // If it is not an ID it cannot be an input ID.
    417     return false;
    418   }
    419   switch (type) {
    420     // Blacklist non-input IDs.
    421     case SPV_OPERAND_TYPE_TYPE_ID:
    422     case SPV_OPERAND_TYPE_RESULT_ID:
    423       return false;
    424     default:
    425       return true;
    426   }
    427 }
    428 
    429 std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
    430     SpvOp opcode) {
    431   std::function<bool(unsigned index)> out;
    432   switch (opcode) {
    433     case SpvOpExecutionMode:
    434     case SpvOpExecutionModeId:
    435     case SpvOpEntryPoint:
    436     case SpvOpName:
    437     case SpvOpMemberName:
    438     case SpvOpSelectionMerge:
    439     case SpvOpDecorate:
    440     case SpvOpMemberDecorate:
    441     case SpvOpDecorateId:
    442     case SpvOpDecorateStringGOOGLE:
    443     case SpvOpMemberDecorateStringGOOGLE:
    444     case SpvOpTypeStruct:
    445     case SpvOpBranch:
    446     case SpvOpLoopMerge:
    447       out = [](unsigned) { return true; };
    448       break;
    449     case SpvOpGroupDecorate:
    450     case SpvOpGroupMemberDecorate:
    451     case SpvOpBranchConditional:
    452     case SpvOpSwitch:
    453       out = [](unsigned index) { return index != 0; };
    454       break;
    455 
    456     case SpvOpFunctionCall:
    457       // The Function parameter.
    458       out = [](unsigned index) { return index == 2; };
    459       break;
    460 
    461     case SpvOpPhi:
    462       out = [](unsigned index) { return index > 1; };
    463       break;
    464 
    465     case SpvOpEnqueueKernel:
    466       // The Invoke parameter.
    467       out = [](unsigned index) { return index == 8; };
    468       break;
    469 
    470     case SpvOpGetKernelNDrangeSubGroupCount:
    471     case SpvOpGetKernelNDrangeMaxSubGroupSize:
    472       // The Invoke parameter.
    473       out = [](unsigned index) { return index == 3; };
    474       break;
    475 
    476     case SpvOpGetKernelWorkGroupSize:
    477     case SpvOpGetKernelPreferredWorkGroupSizeMultiple:
    478       // The Invoke parameter.
    479       out = [](unsigned index) { return index == 2; };
    480       break;
    481     case SpvOpTypeForwardPointer:
    482       out = [](unsigned index) { return index == 0; };
    483       break;
    484     default:
    485       out = [](unsigned) { return false; };
    486       break;
    487   }
    488   return out;
    489 }
    490