diff --git a/source/binary.cpp b/source/binary.cpp index 207d4a9b37..01322be0af 100644 --- a/source/binary.cpp +++ b/source/binary.cpp @@ -173,7 +173,7 @@ class Parser { // Returns the endian-corrected word at the given position. uint32_t peekAt(size_t index) const { assert(index < _.num_words); - return spvFixWord(_.words[index], _.endian); + return _.native_words[index]; } // Data members @@ -218,6 +218,7 @@ class Parser { // Is the SPIR-V binary in a different endianness from the host native // endianness? bool requires_endian_conversion; + std::unique_ptr native_words; // Maps a result ID to its type ID. By convention: // - a result ID that is a type definition maps to itself. @@ -262,6 +263,9 @@ spv_result_t Parser::parseModule() { << _.words[0] << "'."; } _.requires_endian_conversion = !spvIsHostEndian(_.endian); + _.native_words = std::make_unique(_.num_words); + for (size_t i = 0; i < _.num_words; i++) + _.native_words[i] = _.requires_endian_conversion ? spvFixWord(_.words[i], _.endian) : _.words[i]; // Process the header. spv_header_t header; @@ -440,10 +444,6 @@ spv_result_t Parser::parseOperand(size_t inst_offset, const uint32_t word = peek(); - // Do the words in this operand have to be converted to native endianness? - // True for all but literal strings. - bool convert_operand_endianness = true; - switch (type) { case SPV_OPERAND_TYPE_TYPE_ID: if (!word) @@ -590,7 +590,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset, case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: { const size_t max_words = _.num_words - _.word_index; std::string string = - spvtools::utils::MakeString(_.words + _.word_index, max_words, false); + spvtools::utils::MakeString(_.native_words.get() + _.word_index, max_words, false); if (string.length() == max_words * 4) return exhaustedInputDiagnostic(inst_offset, opcode, type); @@ -752,17 +752,8 @@ spv_result_t Parser::parseOperand(size_t inst_offset, if (_.requires_endian_conversion) { // Copy instruction words. Translate to native endianness as needed. - if (convert_operand_endianness) { - const spv_endianness_t endianness = _.endian; - std::transform(_.words + _.word_index, _.words + index_after_operand, - std::back_inserter(*words), - [endianness](const uint32_t raw_word) { - return spvFixWord(raw_word, endianness); - }); - } else { - words->insert(words->end(), _.words + _.word_index, - _.words + index_after_operand); - } + words->insert(words->end(), _.native_words.get() + _.word_index, + _.native_words.get() + index_after_operand); } // Advance past the operand. diff --git a/tools/objdump/extract_source.cpp b/tools/objdump/extract_source.cpp index 02959525c6..a179c722a0 100644 --- a/tools/objdump/extract_source.cpp +++ b/tools/objdump/extract_source.cpp @@ -23,45 +23,12 @@ #include "spirv-tools/libspirv.hpp" #include "spirv/unified1/spirv.hpp" #include "tools/util/cli_consumer.h" +#include "source/binary.h" namespace { constexpr auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_6; -// Extract a string literal from a given range. -// Copies all the characters from `begin` to the first '\0' it encounters, while -// removing escape patterns. -// Not finding a '\0' before reaching `end` fails the extraction. -// -// Returns `true` if the extraction succeeded. -// `output` value is undefined if false is returned. -spv_result_t ExtractStringLiteral(const spv_position_t& loc, const char* begin, - const char* end, std::string* output) { - size_t sourceLength = std::distance(begin, end); - std::string escapedString; - escapedString.resize(sourceLength); - - size_t writeIndex = 0; - size_t readIndex = 0; - for (; readIndex < sourceLength; writeIndex++, readIndex++) { - const char read = begin[readIndex]; - if (read == '\0') { - escapedString.resize(writeIndex); - output->append(escapedString); - return SPV_SUCCESS; - } - - if (read == '\\') { - ++readIndex; - } - escapedString[writeIndex] = begin[readIndex]; - } - - spvtools::Error(spvtools::utils::CLIMessageConsumer, "", loc, - "Missing NULL terminator for literal string."); - return SPV_ERROR_INVALID_BINARY; -} - spv_result_t extractOpString(const spv_position_t& loc, const spv_parsed_instruction_t& instruction, std::string* output) { @@ -73,12 +40,8 @@ spv_result_t extractOpString(const spv_position_t& loc, return SPV_ERROR_INVALID_BINARY; } - const auto& operand = instruction.operands[1]; - const char* stringBegin = - reinterpret_cast(instruction.words + operand.offset); - const char* stringEnd = reinterpret_cast( - instruction.words + operand.offset + operand.num_words); - return ExtractStringLiteral(loc, stringBegin, stringEnd, output); + *output = spvDecodeLiteralStringOperand(instruction, 1); + return SPV_SUCCESS; } spv_result_t extractOpSourceContinued( @@ -92,12 +55,8 @@ spv_result_t extractOpSourceContinued( return SPV_ERROR_INVALID_BINARY; } - const auto& operand = instruction.operands[0]; - const char* stringBegin = - reinterpret_cast(instruction.words + operand.offset); - const char* stringEnd = reinterpret_cast( - instruction.words + operand.offset + operand.num_words); - return ExtractStringLiteral(loc, stringBegin, stringEnd, output); + *output = *output + spvDecodeLiteralStringOperand(instruction, 0); + return SPV_SUCCESS; } spv_result_t extractOpSource(const spv_position_t& loc, @@ -123,11 +82,8 @@ spv_result_t extractOpSource(const spv_position_t& loc, return SPV_SUCCESS; } - const char* stringBegin = - reinterpret_cast(instruction.words + 4); - const char* stringEnd = - reinterpret_cast(instruction.words + instruction.num_words); - return ExtractStringLiteral(loc, stringBegin, stringEnd, code); + *code = spvDecodeLiteralStringOperand(instruction, 3); + return SPV_SUCCESS; } } // namespace