summaryrefslogblamecommitdiff
path: root/user/spirv-tools/endian.patch
blob: 82a2812ad3ed5e1cffb59fa8d0be91a6415f5749 (plain) (tree)


























































































































































































































































































                                                                                                      
From 4826b6eabc6102e49562c48effcabb7b87ceb041 Mon Sep 17 00:00:00 2001
From: Hugo Devillers <hugo@xol.io>
Date: Sat, 1 Jul 2023 11:33:17 +0200
Subject: [PATCH 1/6] remove dead code dealing with operand endianness

---
 source/binary.cpp | 21 ++++++---------------
 1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/source/binary.cpp b/source/binary.cpp
index 207d4a9b37..b1e1922445 100644
--- a/source/binary.cpp
+++ b/source/binary.cpp
@@ -440,10 +440,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)
@@ -752,17 +748,12 @@ 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);
-    }
+    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);
+                   });
   }
 
   // Advance past the operand.

From 39a63f822f0d1d93cabba4f4f3d980bc6ec1737b Mon Sep 17 00:00:00 2001
From: Hugo Devillers <hugo@xol.io>
Date: Sat, 1 Jul 2023 11:50:03 +0200
Subject: [PATCH 2/6] perform endianness conversion eagerly

---
 source/binary.cpp | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/source/binary.cpp b/source/binary.cpp
index b1e1922445..d46dbc1d9e 100644
--- a/source/binary.cpp
+++ b/source/binary.cpp
@@ -207,6 +207,10 @@ class Parser {
       operands.reserve(25);
       endian_converted_words.reserve(25);
       expected_operands.reserve(25);
+
+      native_words = std::make_unique<uint32_t[]>(num_words);
+      for (size_t i = 0; i < num_words; i++)
+        native_words[i] = spvFixWord(words[i], endian);
     }
     State() : State(0, 0, nullptr) {}
     const uint32_t* words;       // Words in the binary SPIR-V module.
@@ -218,6 +222,7 @@ class Parser {
     // Is the SPIR-V binary in a different endianness from the host native
     // endianness?
     bool requires_endian_conversion;
+    std::unique_ptr<uint32_t[]> native_words;
 
     // Maps a result ID to its type ID.  By convention:
     //  - a result ID that is a type definition maps to itself.
@@ -748,12 +753,8 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
 
   if (_.requires_endian_conversion) {
     // Copy instruction words.  Translate to native endianness as needed.
-    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);
-                   });
+      words->insert(words->end(), _.native_words.get() + _.word_index,
+                    _.native_words.get() + index_after_operand);
   }
 
   // Advance past the operand.

From e6005633e64f4dac33aa2c4de42fe6bd3fb648ca Mon Sep 17 00:00:00 2001
From: Hugo Devillers <hugo@xol.io>
Date: Sat, 1 Jul 2023 11:51:37 +0200
Subject: [PATCH 3/6] fix string literals when file has non-native endianness

---
 source/binary.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source/binary.cpp b/source/binary.cpp
index d46dbc1d9e..34cb608abe 100644
--- a/source/binary.cpp
+++ b/source/binary.cpp
@@ -591,7 +591,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);

From 3ccc744e814609fe63b755e37240e03cf07e2f2b Mon Sep 17 00:00:00 2001
From: Hugo Devillers <hugo@xol.io>
Date: Sat, 1 Jul 2023 12:24:16 +0200
Subject: [PATCH 4/6] don't convert endianness if not required

---
 source/binary.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/source/binary.cpp b/source/binary.cpp
index 34cb608abe..69bd082598 100644
--- a/source/binary.cpp
+++ b/source/binary.cpp
@@ -207,10 +207,6 @@ class Parser {
       operands.reserve(25);
       endian_converted_words.reserve(25);
       expected_operands.reserve(25);
-
-      native_words = std::make_unique<uint32_t[]>(num_words);
-      for (size_t i = 0; i < num_words; i++)
-        native_words[i] = spvFixWord(words[i], endian);
     }
     State() : State(0, 0, nullptr) {}
     const uint32_t* words;       // Words in the binary SPIR-V module.
@@ -267,6 +263,9 @@ spv_result_t Parser::parseModule() {
                         << _.words[0] << "'.";
   }
   _.requires_endian_conversion = !spvIsHostEndian(_.endian);
+  _.native_words = std::make_unique<uint32_t[]>(_.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;

From 74df3cf1b49c9ae296ebbb16cf8e2e7b45584454 Mon Sep 17 00:00:00 2001
From: Hugo Devillers <hugo@xol.io>
Date: Sat, 1 Jul 2023 12:42:04 +0200
Subject: [PATCH 5/6] use native_words as a cache for spvFixWord

---
 source/binary.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source/binary.cpp b/source/binary.cpp
index 69bd082598..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

From 458eb86f866b489e93d17eee12f76207b93dd60d Mon Sep 17 00:00:00 2001
From: Hugo Devillers <hugo@xol.io>
Date: Sat, 1 Jul 2023 16:59:06 +0200
Subject: [PATCH 6/6] simplify and fix mismatched endian string parsing for
 extract_source.cpp

---
 tools/objdump/extract_source.cpp | 58 ++++----------------------------
 1 file changed, 7 insertions(+), 51 deletions(-)

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<const char*>(instruction.words + operand.offset);
-  const char* stringEnd = reinterpret_cast<const char*>(
-      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<const char*>(instruction.words + operand.offset);
-  const char* stringEnd = reinterpret_cast<const char*>(
-      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<const char*>(instruction.words + 4);
-  const char* stringEnd =
-      reinterpret_cast<const char*>(instruction.words + instruction.num_words);
-  return ExtractStringLiteral(loc, stringBegin, stringEnd, code);
+  *code = spvDecodeLiteralStringOperand(instruction, 3);
+  return SPV_SUCCESS;
 }
 
 }  // namespace