Home | History | Annotate | Download | only in source
      1 // Copyright (c) 2015-2016 The Khronos Group Inc.
      2 //
      3 // Permission is hereby granted, free of charge, to any person obtaining a
      4 // copy of this software and/or associated documentation files (the
      5 // "Materials"), to deal in the Materials without restriction, including
      6 // without limitation the rights to use, copy, modify, merge, publish,
      7 // distribute, sublicense, and/or sell copies of the Materials, and to
      8 // permit persons to whom the Materials are furnished to do so, subject to
      9 // the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included
     12 // in all copies or substantial portions of the Materials.
     13 //
     14 // MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
     15 // KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
     16 // SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
     17 //    https://www.khronos.org/registry/
     18 //
     19 // THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     22 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     23 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     24 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     25 // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
     26 
     27 #include "operand.h"
     28 
     29 #include <assert.h>
     30 #include <string.h>
     31 
     32 #include "macro.h"
     33 
     34 // Pull in operand info tables automatically generated from JSON grammar.
     35 namespace v1_0 {
     36 #include "operand.kinds-1.0.inc"
     37 }  // namespace v1_0
     38 namespace v1_1 {
     39 #include "operand.kinds-1.1.inc"
     40 }  // namespace v1_1
     41 
     42 spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable,
     43                                 spv_target_env env) {
     44   if (!pOperandTable) return SPV_ERROR_INVALID_POINTER;
     45 
     46   static const spv_operand_table_t table_1_0 = {
     47       ARRAY_SIZE(v1_0::pygen_variable_OperandInfoTable),
     48       v1_0::pygen_variable_OperandInfoTable};
     49   static const spv_operand_table_t table_1_1 = {
     50       ARRAY_SIZE(v1_1::pygen_variable_OperandInfoTable),
     51       v1_1::pygen_variable_OperandInfoTable};
     52 
     53   switch (env) {
     54     case SPV_ENV_UNIVERSAL_1_0:
     55     case SPV_ENV_VULKAN_1_0:
     56       *pOperandTable = &table_1_0;
     57       return SPV_SUCCESS;
     58     case SPV_ENV_UNIVERSAL_1_1:
     59       *pOperandTable = &table_1_1;
     60       return SPV_SUCCESS;
     61   }
     62   assert(0 && "Unknown spv_target_env in spvOperandTableGet()");
     63   return SPV_ERROR_INVALID_TABLE;
     64 }
     65 
     66 #undef ARRAY_SIZE
     67 
     68 spv_result_t spvOperandTableNameLookup(const spv_operand_table table,
     69                                        const spv_operand_type_t type,
     70                                        const char* name,
     71                                        const size_t nameLength,
     72                                        spv_operand_desc* pEntry) {
     73   if (!table) return SPV_ERROR_INVALID_TABLE;
     74   if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
     75 
     76   for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
     77     const auto& group = table->types[typeIndex];
     78     if (type != group.type) continue;
     79     for (uint64_t index = 0; index < group.count; ++index) {
     80       const auto& entry = group.entries[index];
     81       if (nameLength == strlen(entry.name) &&
     82           !strncmp(entry.name, name, nameLength)) {
     83         *pEntry = &entry;
     84         return SPV_SUCCESS;
     85       }
     86     }
     87   }
     88 
     89   return SPV_ERROR_INVALID_LOOKUP;
     90 }
     91 
     92 spv_result_t spvOperandTableValueLookup(const spv_operand_table table,
     93                                         const spv_operand_type_t type,
     94                                         const uint32_t value,
     95                                         spv_operand_desc* pEntry) {
     96   if (!table) return SPV_ERROR_INVALID_TABLE;
     97   if (!pEntry) return SPV_ERROR_INVALID_POINTER;
     98 
     99   for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
    100     const auto& group = table->types[typeIndex];
    101     if (type != group.type) continue;
    102     for (uint64_t index = 0; index < group.count; ++index) {
    103       const auto& entry = group.entries[index];
    104       if (value == entry.value) {
    105         *pEntry = &entry;
    106         return SPV_SUCCESS;
    107       }
    108     }
    109   }
    110 
    111   return SPV_ERROR_INVALID_LOOKUP;
    112 }
    113 
    114 const char* spvOperandTypeStr(spv_operand_type_t type) {
    115   switch (type) {
    116     case SPV_OPERAND_TYPE_ID:
    117     case SPV_OPERAND_TYPE_OPTIONAL_ID:
    118       return "ID";
    119     case SPV_OPERAND_TYPE_TYPE_ID:
    120       return "type ID";
    121     case SPV_OPERAND_TYPE_RESULT_ID:
    122       return "result ID";
    123     case SPV_OPERAND_TYPE_LITERAL_INTEGER:
    124     case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER:
    125     case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER:
    126       return "literal number";
    127     case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
    128       return "possibly multi-word literal integer";
    129     case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
    130       return "possibly multi-word literal number";
    131     case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
    132       return "extension instruction number";
    133     case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER:
    134       return "OpSpecConstantOp opcode";
    135     case SPV_OPERAND_TYPE_LITERAL_STRING:
    136     case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING:
    137       return "literal string";
    138     case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
    139       return "source language";
    140     case SPV_OPERAND_TYPE_EXECUTION_MODEL:
    141       return "execution model";
    142     case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
    143       return "addressing model";
    144     case SPV_OPERAND_TYPE_MEMORY_MODEL:
    145       return "memory model";
    146     case SPV_OPERAND_TYPE_EXECUTION_MODE:
    147       return "execution mode";
    148     case SPV_OPERAND_TYPE_STORAGE_CLASS:
    149       return "storage class";
    150     case SPV_OPERAND_TYPE_DIMENSIONALITY:
    151       return "dimensionality";
    152     case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
    153       return "sampler addressing mode";
    154     case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
    155       return "sampler filter mode";
    156     case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
    157       return "image format";
    158     case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
    159       return "floating-point fast math mode";
    160     case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
    161       return "floating-point rounding mode";
    162     case SPV_OPERAND_TYPE_LINKAGE_TYPE:
    163       return "linkage type";
    164     case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
    165     case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER:
    166       return "access qualifier";
    167     case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
    168       return "function parameter attribute";
    169     case SPV_OPERAND_TYPE_DECORATION:
    170       return "decoration";
    171     case SPV_OPERAND_TYPE_BUILT_IN:
    172       return "built-in";
    173     case SPV_OPERAND_TYPE_SELECTION_CONTROL:
    174       return "selection control";
    175     case SPV_OPERAND_TYPE_LOOP_CONTROL:
    176       return "loop control";
    177     case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
    178       return "function control";
    179     case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
    180       return "memory semantics ID";
    181     case SPV_OPERAND_TYPE_MEMORY_ACCESS:
    182     case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
    183       return "memory access";
    184     case SPV_OPERAND_TYPE_SCOPE_ID:
    185       return "scope ID";
    186     case SPV_OPERAND_TYPE_GROUP_OPERATION:
    187       return "group operation";
    188     case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
    189       return "kernel enqeue flags";
    190     case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
    191       return "kernel profiling info";
    192     case SPV_OPERAND_TYPE_CAPABILITY:
    193       return "capability";
    194     case SPV_OPERAND_TYPE_IMAGE:
    195     case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
    196       return "image";
    197     case SPV_OPERAND_TYPE_OPTIONAL_CIV:
    198       return "context-insensitive value";
    199 
    200     // The next values are for values returned from an instruction, not actually
    201     // an operand.  So the specific strings don't matter.  But let's add them
    202     // for completeness and ease of testing.
    203     case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER:
    204       return "image channel order";
    205     case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE:
    206       return "image channel data type";
    207 
    208     case SPV_OPERAND_TYPE_NONE:
    209       return "NONE";
    210     default:
    211       assert(0 && "Unhandled operand type!");
    212       break;
    213   }
    214   return "unknown";
    215 }
    216 
    217 void spvPrependOperandTypes(const spv_operand_type_t* types,
    218                             spv_operand_pattern_t* pattern) {
    219   const spv_operand_type_t* endTypes;
    220   for (endTypes = types; *endTypes != SPV_OPERAND_TYPE_NONE; ++endTypes)
    221     ;
    222   pattern->insert(pattern->begin(), types, endTypes);
    223 }
    224 
    225 void spvPrependOperandTypesForMask(const spv_operand_table operandTable,
    226                                    const spv_operand_type_t type,
    227                                    const uint32_t mask,
    228                                    spv_operand_pattern_t* pattern) {
    229   // Scan from highest bits to lowest bits because we will prepend in LIFO
    230   // fashion, and we need the operands for lower order bits to appear first.
    231   for (uint32_t candidate_bit = (1u << 31u); candidate_bit; candidate_bit >>= 1) {
    232     if (candidate_bit & mask) {
    233       spv_operand_desc entry = nullptr;
    234       if (SPV_SUCCESS == spvOperandTableValueLookup(operandTable, type,
    235                                                     candidate_bit, &entry)) {
    236         spvPrependOperandTypes(entry->operandTypes, pattern);
    237       }
    238     }
    239   }
    240 }
    241 
    242 bool spvOperandIsConcreteMask(spv_operand_type_t type) {
    243   return SPV_OPERAND_TYPE_FIRST_CONCRETE_MASK_TYPE <= type &&
    244          type <= SPV_OPERAND_TYPE_LAST_CONCRETE_MASK_TYPE;
    245 }
    246 
    247 bool spvOperandIsOptional(spv_operand_type_t type) {
    248   return SPV_OPERAND_TYPE_FIRST_OPTIONAL_TYPE <= type &&
    249          type <= SPV_OPERAND_TYPE_LAST_OPTIONAL_TYPE;
    250 }
    251 
    252 bool spvOperandIsVariable(spv_operand_type_t type) {
    253   return SPV_OPERAND_TYPE_FIRST_VARIABLE_TYPE <= type &&
    254          type <= SPV_OPERAND_TYPE_LAST_VARIABLE_TYPE;
    255 }
    256 
    257 bool spvExpandOperandSequenceOnce(spv_operand_type_t type,
    258                                   spv_operand_pattern_t* pattern) {
    259   switch (type) {
    260     case SPV_OPERAND_TYPE_VARIABLE_ID:
    261       pattern->insert(pattern->begin(), {SPV_OPERAND_TYPE_OPTIONAL_ID, type});
    262       return true;
    263     case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER:
    264       pattern->insert(pattern->begin(),
    265                       {SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, type});
    266       return true;
    267     case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID:
    268       // Represents Zero or more (Literal number, Id) pairs,
    269       // where the literal number must be a scalar integer.
    270       pattern->insert(pattern->begin(),
    271                       {SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER,
    272                        SPV_OPERAND_TYPE_ID, type});
    273       return true;
    274     case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER:
    275       // Represents Zero or more (Id, Literal number) pairs.
    276       pattern->insert(pattern->begin(),
    277                       {SPV_OPERAND_TYPE_OPTIONAL_ID,
    278                        SPV_OPERAND_TYPE_LITERAL_INTEGER, type});
    279       return true;
    280     default:
    281       break;
    282   }
    283   return false;
    284 }
    285 
    286 spv_operand_type_t spvTakeFirstMatchableOperand(
    287     spv_operand_pattern_t* pattern) {
    288   assert(!pattern->empty());
    289   spv_operand_type_t result;
    290   do {
    291     result = pattern->front();
    292     pattern->pop_front();
    293   } while (spvExpandOperandSequenceOnce(result, pattern));
    294   return result;
    295 }
    296 
    297 spv_operand_pattern_t spvAlternatePatternFollowingImmediate(
    298     const spv_operand_pattern_t& pattern) {
    299   spv_operand_pattern_t alternatePattern;
    300   for (const auto& operand : pattern) {
    301     if (operand == SPV_OPERAND_TYPE_RESULT_ID) {
    302       alternatePattern.push_back(operand);
    303       alternatePattern.push_back(SPV_OPERAND_TYPE_OPTIONAL_CIV);
    304       return alternatePattern;
    305     }
    306     alternatePattern.push_back(SPV_OPERAND_TYPE_OPTIONAL_CIV);
    307   }
    308   // No result-id found, so just expect CIVs.
    309   return {SPV_OPERAND_TYPE_OPTIONAL_CIV};
    310 }
    311 
    312 bool spvIsIdType(spv_operand_type_t type) {
    313   switch (type) {
    314     case SPV_OPERAND_TYPE_ID:
    315     case SPV_OPERAND_TYPE_TYPE_ID:
    316     case SPV_OPERAND_TYPE_RESULT_ID:
    317     case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
    318     case SPV_OPERAND_TYPE_SCOPE_ID:
    319       return true;
    320     default:
    321       return false;
    322   }
    323 }
    324