1 // Copyright (c) 2018 Google 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 #ifndef SOURCE_DISASSEMBLE_H_ 16 #define SOURCE_DISASSEMBLE_H_ 17 18 #include <ios> 19 #include <sstream> 20 #include <string> 21 22 #include "source/name_mapper.h" 23 #include "spirv-tools/libspirv.h" 24 25 namespace spvtools { 26 27 // Decodes the given SPIR-V instruction binary representation to its assembly 28 // text. The context is inferred from the provided module binary. The options 29 // parameter is a bit field of spv_binary_to_text_options_t (note: the option 30 // SPV_BINARY_TO_TEXT_OPTION_PRINT will be ignored). Decoded text will be 31 // stored into *text. Any error will be written into *diagnostic if diagnostic 32 // is non-null. 33 std::string spvInstructionBinaryToText(const spv_target_env env, 34 const uint32_t* inst_binary, 35 const size_t inst_word_count, 36 const uint32_t* binary, 37 const size_t word_count, 38 const uint32_t options); 39 40 class AssemblyGrammar; 41 namespace disassemble { 42 43 // Shared code with other tools (than the disassembler) that might need to 44 // output disassembly. An InstructionDisassembler instance converts SPIR-V 45 // binary for an instruction to its assembly representation. 46 class InstructionDisassembler { 47 public: 48 InstructionDisassembler(const AssemblyGrammar& grammar, std::ostream& stream, 49 uint32_t options, NameMapper name_mapper); 50 51 // Emits the assembly header for the module. 52 void EmitHeaderSpirv(); 53 void EmitHeaderVersion(uint32_t version); 54 void EmitHeaderGenerator(uint32_t generator); 55 void EmitHeaderIdBound(uint32_t id_bound); 56 void EmitHeaderSchema(uint32_t schema); 57 58 // Emits the assembly text for the given instruction. 59 void EmitInstruction(const spv_parsed_instruction_t& inst, 60 size_t inst_byte_offset); 61 // Same as EmitInstruction, but only for block instructions (including 62 // OpLabel) and useful for nested indentation. If nested indentation is not 63 // desired, EmitInstruction can still be used for block instructions. 64 void EmitInstructionInBlock(const spv_parsed_instruction_t& inst, 65 size_t inst_byte_offset, uint32_t block_indent); 66 67 // Emits a comment between different sections of the module. 68 void EmitSectionComment(const spv_parsed_instruction_t& inst, 69 bool& inserted_decoration_space, 70 bool& inserted_debug_space, 71 bool& inserted_type_space); 72 73 // Resets the output color, if color is turned on. 74 void ResetColor(); 75 // Set the output color, if color is turned on. 76 void SetGrey(); 77 void SetBlue(); 78 void SetYellow(); 79 void SetRed(); 80 void SetGreen(); 81 82 private: 83 void ResetColor(std::ostream& stream) const; 84 void SetGrey(std::ostream& stream) const; 85 void SetBlue(std::ostream& stream) const; 86 void SetYellow(std::ostream& stream) const; 87 void SetRed(std::ostream& stream) const; 88 void SetGreen(std::ostream& stream) const; 89 90 void EmitInstructionImpl(const spv_parsed_instruction_t& inst, 91 size_t inst_byte_offset, uint32_t block_indent, 92 bool is_in_block); 93 94 // Emits an operand for the given instruction, where the instruction 95 // is at offset words from the start of the binary. 96 void EmitOperand(std::ostream& stream, const spv_parsed_instruction_t& inst, 97 uint16_t operand_index) const; 98 99 // Emits a mask expression for the given mask word of the specified type. 100 void EmitMaskOperand(std::ostream& stream, spv_operand_type_t type, 101 uint32_t word) const; 102 103 // Generate part of the instruction as a comment to be added to 104 // |id_comments_|. 105 void GenerateCommentForDecoratedId(const spv_parsed_instruction_t& inst); 106 107 const spvtools::AssemblyGrammar& grammar_; 108 std::ostream& stream_; 109 const bool print_; // Should we also print to the standard output stream? 110 const bool color_; // Should we print in colour? 111 const int indent_; // How much to indent. 0 means don't indent 112 const bool nested_indent_; // Whether indentation should indicate nesting 113 const int comment_; // Should we comment the source 114 const bool show_byte_offset_; // Should we print byte offset, in hex? 115 spvtools::NameMapper name_mapper_; 116 117 // Some comments are generated as instructions (such as OpDecorate) are 118 // visited so that when the instruction with that result id is visited, the 119 // comment can be output. 120 std::unordered_map<uint32_t, std::ostringstream> id_comments_; 121 // Align the comments in consecutive lines for more readability. 122 uint32_t last_instruction_comment_alignment_; 123 }; 124 125 } // namespace disassemble 126 } // namespace spvtools 127 128 #endif // SOURCE_DISASSEMBLE_H_ 129