Home | History | Annotate | Download | only in source
      1 // Copyright (c) 2016 Google 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 #ifndef LIBSPIRV_NAME_MAPPER_H_
     28 #define LIBSPIRV_NAME_MAPPER_H_
     29 
     30 #include <functional>
     31 #include <string>
     32 #include <unordered_map>
     33 #include <unordered_set>
     34 
     35 #include "spirv-tools/libspirv.h"
     36 #include "assembly_grammar.h"
     37 
     38 namespace libspirv {
     39 
     40 // A NameMapper maps SPIR-V Id values to names.  Each name is valid to use in
     41 // SPIR-V assembly.  The mapping is one-to-one, i.e. no two Ids map to the same
     42 // name.
     43 using NameMapper = std::function<std::string(uint32_t)>;
     44 
     45 // Returns a NameMapper which always maps an Id to its decimal representation.
     46 NameMapper GetTrivialNameMapper();
     47 
     48 // A FriendlyNameMapper parses a module upon construction.  If the parse is
     49 // successful, then the NameForId method maps an Id to a friendly name
     50 // while also satisfying the constraints on a NameMapper.
     51 //
     52 // The mapping is friendly in the following sense:
     53 //  - If an Id has a debug name (via OpName), then that will be used when
     54 //    possible.
     55 //  - Well known scalar types map to friendly names.  For example,
     56 //    OpTypeVoid should be %void.  Scalar types map to their names in OpenCL when
     57 //    there is a correspondence, and otherwise as follows:
     58 //    - unsigned integer type of n bits map to "u" followed by n
     59 //    - signed integer type of n bits map to "i" followed by n
     60 //    - floating point type of n bits map to "fp" followed by n
     61 //  - Vector type names map to "v" followed by the number of components,
     62 //    followed by the friendly name for the base type.
     63 //  - Matrix type names map to "mat" followed by the number of columns,
     64 //    followed by the friendly name for the base vector type.
     65 //  - Pointer types map to "_ptr_", then the name of the storage class, then the
     66 //    name for the pointee type.
     67 //  - Exotic types like event, pipe, opaque, queue, reserve-id map to their own
     68 //    human readable names.
     69 //  - A struct type maps to "_struct_" followed by the raw Id number.  That's
     70 //    pretty simplistic, but workable.
     71 class FriendlyNameMapper {
     72  public:
     73   // Construct a friendly name mapper, and determine friendly names for each
     74   // defined Id in the specified module.  The module is specified by the code
     75   // wordCount, and should be parseable in the specified context.
     76   FriendlyNameMapper(const spv_const_context context, const uint32_t* code,
     77                      const size_t wordCount);
     78 
     79   // Returns a NameMapper which maps ids to the friendly names parsed from the
     80   // module provided to the constructor.
     81   NameMapper GetNameMapper() {
     82     return [this](uint32_t id) { return this->NameForId(id); };
     83   }
     84 
     85   // Returns the friendly name for the given id.  If the module parsed during
     86   // construction is valid, then the mapping satisfies the rules for a
     87   // NameMapper.
     88   std::string NameForId(uint32_t id);
     89 
     90  private:
     91   // Transforms the given string so that it is acceptable as an Id name in
     92   // assembly language.  Two distinct inputs can map to the same output.
     93   std::string Sanitize(const std::string& suggested_name);
     94 
     95   // Records a name for the given id.  Use the given suggested_name if it
     96   // hasn't already been taken, and otherwise generate a new (unused) name
     97   // based on the suggested name.
     98   void SaveName(uint32_t id, const std::string& suggested_name);
     99 
    100   // Collects information from the given parsed instruction to populate
    101   // name_for_id_.  Returns SPV_SUCCESS;
    102   spv_result_t ParseInstruction(const spv_parsed_instruction_t& inst);
    103 
    104   // Forwards a parsed-instruction callback from the binary parser into the
    105   // FriendlyNameMapper hidden inside the user_data parameter.
    106   static spv_result_t ParseInstructionForwarder(
    107       void* user_data, const spv_parsed_instruction_t* parsed_instruction) {
    108     return reinterpret_cast<FriendlyNameMapper*>(user_data)->ParseInstruction(
    109         *parsed_instruction);
    110   }
    111 
    112   // Returns the friendly name for an enumerant.
    113   std::string NameForEnumOperand(spv_operand_type_t type, uint32_t word);
    114 
    115   // Maps an id to its friendly name.  This will have an entry for each Id
    116   // defined in the module.
    117   std::unordered_map<uint32_t, std::string> name_for_id_;
    118   // The set of names that have a mapping in name_for_id_;
    119   std::unordered_set<std::string> used_names_;
    120   // The assembly grammar for the current context.
    121   const libspirv::AssemblyGrammar grammar_;
    122 };
    123 
    124 }  // namespace libspirv
    125 
    126 #endif  // _LIBSPIRV_NAME_MAPPER_H_
    127