summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/core/slang-riff.h19
-rw-r--r--source/slang/slang-compiler.cpp4
-rw-r--r--source/slang/slang-compiler.h3
-rw-r--r--source/slang/slang-ir-serialize-types.cpp411
-rw-r--r--source/slang/slang-ir-serialize-types.h423
-rw-r--r--source/slang/slang-ir-serialize.cpp440
-rw-r--r--source/slang/slang-ir-serialize.h402
-rw-r--r--source/slang/slang-options.cpp6
-rw-r--r--source/slang/slang.vcxproj6
-rw-r--r--source/slang/slang.vcxproj.filters6
10 files changed, 918 insertions, 802 deletions
diff --git a/source/core/slang-riff.h b/source/core/slang-riff.h
index 1622f60f4..535eaffc2 100644
--- a/source/core/slang-riff.h
+++ b/source/core/slang-riff.h
@@ -12,9 +12,26 @@ namespace Slang
// http://fileformats.archiveteam.org/wiki/RIFF
// http://www.fileformat.info/format/riff/egff.htm
+
typedef uint32_t FourCC;
-#define SLANG_FOUR_CC(c0, c1, c2, c3) FourCC((uint32_t(c0) << 0) | (uint32_t(c1) << 8) | (uint32_t(c2) << 16) | (uint32_t(c3) << 24))
+/* Use of macros to construct and extract from FourCC means the FourCC ordering can be fixed for endian differences. */
+
+#if SLANG_LITTLE_ENDIAN
+
+#define SLANG_FOUR_CC(c0, c1, c2, c3) ((FourCC(c0) << 0) | (FourCC(c1) << 8) | (FourCC(c2) << 16) | (FourCC(c3) << 24))
+
+#define SLANG_FOUR_CC_GET_FIRST_CHAR(x) char((x) & 0xff)
+#define SLANG_FOUR_CC_REPLACE_FIRST_CHAR(x, c) (((x) & 0xffffff00) | FourCC(c))
+
+#else
+
+#define SLANG_FOUR_CC(c0, c1, c2, c3) ((FourCC(c0) << 24) | (FourCC(c1) << 16) | (FourCC(c2) << 8) | (FourCC(c3) << 0))
+
+#define SLANG_FOUR_CC_GET_FIRST_CHAR(x) char((x) >> 24)
+#define SLANG_FOUR_CC_REPLACE_FIRST_CHAR(x, c) (((x) & 0x00ffffff) | (FourCC(c) << 24))
+
+#endif
enum
{
diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp
index 3cfb845d7..a5c078dc4 100644
--- a/source/slang/slang-compiler.cpp
+++ b/source/slang/slang-compiler.cpp
@@ -2245,9 +2245,7 @@ SlangResult dissassembleDXILUsingDXC(
{
RiffContainer container;
- // TODO(JS): We may want a switch to control is we use compression and/or we may just want compressed by default.
- // For now uncompressed is fine.
- const auto compressionType = IRSerialBinary::CompressionType::None;
+ const IRSerialBinary::CompressionType compressionType = getLinkage()->irCompressionType;
{
// Module list
diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h
index a628e86a3..1a2076c93 100644
--- a/source/slang/slang-compiler.h
+++ b/source/slang/slang-compiler.h
@@ -15,6 +15,8 @@
#include "slang-file-system.h"
+#include "slang-ir-serialize-types.h"
+
#include "../../slang.h"
namespace Slang
@@ -1268,6 +1270,7 @@ namespace Slang
OptimizationLevel optimizationLevel = OptimizationLevel::Default;
+ IRSerialCompressionType irCompressionType = IRSerialCompressionType::VariableByteLite;
bool m_requireCacheFileSystem = false;
bool m_useFalcorCustomSharedKeywordSemantics = false;
diff --git a/source/slang/slang-ir-serialize-types.cpp b/source/slang/slang-ir-serialize-types.cpp
new file mode 100644
index 000000000..998fc9d7f
--- /dev/null
+++ b/source/slang/slang-ir-serialize-types.cpp
@@ -0,0 +1,411 @@
+// slang-ir-serialize-types.cpp
+#include "slang-ir-serialize-types.h"
+
+#include "../core/slang-text-io.h"
+#include "../core/slang-byte-encode-util.h"
+
+#include "slang-ir-insts.h"
+
+#include "../core/slang-math.h"
+
+namespace Slang {
+
+// Needed for linkage with some compilers
+/* static */ const IRSerialData::StringIndex IRSerialData::kNullStringIndex;
+/* static */ const IRSerialData::StringIndex IRSerialData::kEmptyStringIndex;
+
+/* Note that an IRInst can be derived from, but when it derived from it's new members are IRUse variables, and they in
+effect alias over the operands - and reflected in the operand count. There _could_ be other members after these IRUse
+variables, but only a few types include extra data, and these do not have any operands:
+
+* IRConstant - Needs special-case handling
+* IRModuleInst - Presumably we can just set to the module pointer on reconstruction
+
+Note! That on an IRInst there is an IRType* variable (accessed as getFullType()). As it stands it may NOT actually point
+to an IRType derived type. Its 'ok' as long as it's an instruction that can be used in the place of the type. So this code does not
+bother to check if it's correct, and just casts it.
+*/
+
+/* static */const IRSerialData::PayloadInfo IRSerialData::s_payloadInfos[int(Inst::PayloadType::CountOf)] =
+{
+ { 0, 0 }, // Empty
+ { 1, 0 }, // Operand_1
+ { 2, 0 }, // Operand_2
+ { 1, 0 }, // OperandAndUInt32,
+ { 0, 0 }, // OperandExternal - This isn't correct, Operand has to be specially handled
+ { 0, 1 }, // String_1,
+ { 0, 2 }, // String_2,
+ { 0, 0 }, // UInt32,
+ { 0, 0 }, // Float64,
+ { 0, 0 } // Int64,
+};
+
+// Check all compressible chunk ids, start with upper case 'S'
+SLANG_COMPILE_TIME_ASSERT(SLANG_FOUR_CC_GET_FIRST_CHAR(IRSerialBinary::kInstFourCc) == 'S');
+SLANG_COMPILE_TIME_ASSERT(SLANG_FOUR_CC_GET_FIRST_CHAR(IRSerialBinary::kChildRunFourCc) == 'S');
+SLANG_COMPILE_TIME_ASSERT(SLANG_FOUR_CC_GET_FIRST_CHAR(IRSerialBinary::kExternalOperandsFourCc) == 'S');
+
+// Compressed version starts with 's'
+SLANG_COMPILE_TIME_ASSERT(SLANG_FOUR_CC_GET_FIRST_CHAR(SLANG_MAKE_COMPRESSED_FOUR_CC(IRSerialBinary::kInstFourCc)) == 's');
+
+struct PrefixString;
+
+namespace { // anonymous
+
+struct CharReader
+{
+ char operator()(int pos) const { SLANG_UNUSED(pos); return *m_pos++; }
+ CharReader(const char* pos) :m_pos(pos) {}
+ mutable const char* m_pos;
+};
+
+} // anonymous
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! StringRepresentationCache !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+StringRepresentationCache::StringRepresentationCache():
+ m_stringTable(nullptr),
+ m_namePool(nullptr),
+ m_scopeManager(nullptr)
+{
+}
+
+void StringRepresentationCache::init(const List<char>* stringTable, NamePool* namePool, ObjectScopeManager* scopeManager)
+{
+ m_stringTable = stringTable;
+ m_namePool = namePool;
+ m_scopeManager = scopeManager;
+
+ // Decode the table
+ m_entries.setCount(StringSlicePool::kNumDefaultHandles);
+ SLANG_COMPILE_TIME_ASSERT(StringSlicePool::kNumDefaultHandles == 2);
+
+ {
+ Entry& entry = m_entries[0];
+ entry.m_numChars = 0;
+ entry.m_startIndex = 0;
+ entry.m_object = nullptr;
+ }
+ {
+ Entry& entry = m_entries[1];
+ entry.m_numChars = 0;
+ entry.m_startIndex = 0;
+ entry.m_object = nullptr;
+ }
+
+ {
+ const char* start = stringTable->begin();
+ const char* cur = start;
+ const char* end = stringTable->end();
+
+ while (cur < end)
+ {
+ CharReader reader(cur);
+ const int len = GetUnicodePointFromUTF8(reader);
+
+ Entry entry;
+ entry.m_startIndex = uint32_t(reader.m_pos - start);
+ entry.m_numChars = len;
+ entry.m_object = nullptr;
+
+ m_entries.add(entry);
+
+ cur = reader.m_pos + len;
+ }
+ }
+
+ m_entries.compress();
+}
+
+Name* StringRepresentationCache::getName(Handle handle)
+{
+ if (handle == StringSlicePool::kNullHandle)
+ {
+ return nullptr;
+ }
+
+ Entry& entry = m_entries[int(handle)];
+ if (entry.m_object)
+ {
+ Name* name = dynamicCast<Name>(entry.m_object);
+ if (name)
+ {
+ return name;
+ }
+ StringRepresentation* stringRep = static_cast<StringRepresentation*>(entry.m_object);
+ // Promote it to a name
+ name = m_namePool->getName(String(stringRep));
+ entry.m_object = name;
+ return name;
+ }
+
+ Name* name = m_namePool->getName(String(getStringSlice(handle)));
+ entry.m_object = name;
+ return name;
+}
+
+String StringRepresentationCache::getString(Handle handle)
+{
+ return String(getStringRepresentation(handle));
+}
+
+UnownedStringSlice StringRepresentationCache::getStringSlice(Handle handle) const
+{
+ const Entry& entry = m_entries[int(handle)];
+ const char* start = m_stringTable->begin();
+
+ return UnownedStringSlice(start + entry.m_startIndex, int(entry.m_numChars));
+}
+
+StringRepresentation* StringRepresentationCache::getStringRepresentation(Handle handle)
+{
+ if (handle == StringSlicePool::kNullHandle || handle == StringSlicePool::kEmptyHandle)
+ {
+ return nullptr;
+ }
+
+ Entry& entry = m_entries[int(handle)];
+ if (entry.m_object)
+ {
+ Name* name = dynamicCast<Name>(entry.m_object);
+ if (name)
+ {
+ return name->text.getStringRepresentation();
+ }
+ return static_cast<StringRepresentation*>(entry.m_object);
+ }
+
+ const UnownedStringSlice slice = getStringSlice(handle);
+ const UInt size = slice.size();
+
+ StringRepresentation* stringRep = StringRepresentation::createWithCapacityAndLength(size, size);
+ memcpy(stringRep->getData(), slice.begin(), size);
+ entry.m_object = stringRep;
+
+ // Keep the StringRepresentation in scope
+ m_scopeManager->add(stringRep);
+
+ return stringRep;
+}
+
+char* StringRepresentationCache::getCStr(Handle handle)
+{
+ // It turns out StringRepresentation is always 0 terminated, so can just use that
+ StringRepresentation* rep = getStringRepresentation(handle);
+ return rep->getData();
+}
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SerialStringTableUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+/* static */void SerialStringTableUtil::encodeStringTable(const StringSlicePool& pool, List<char>& stringTable)
+{
+ // Skip the default handles -> nothing is encoded via them
+ return encodeStringTable(pool.getSlices().begin() + StringSlicePool::kNumDefaultHandles, pool.getNumSlices() - StringSlicePool::kNumDefaultHandles, stringTable);
+}
+
+/* static */void SerialStringTableUtil::encodeStringTable(const UnownedStringSlice* slices, size_t numSlices, List<char>& stringTable)
+{
+ stringTable.clear();
+ for (size_t i = 0; i < numSlices; ++i)
+ {
+ const UnownedStringSlice slice = slices[i];
+ const int len = int(slice.size());
+
+ // We need to write into the the string array
+ char prefixBytes[6];
+ const int numPrefixBytes = EncodeUnicodePointToUTF8(prefixBytes, len);
+ const Index baseIndex = stringTable.getCount();
+
+ stringTable.setCount(baseIndex + numPrefixBytes + len);
+
+ char* dst = stringTable.begin() + baseIndex;
+
+ memcpy(dst, prefixBytes, numPrefixBytes);
+ memcpy(dst + numPrefixBytes, slice.begin(), len);
+ }
+}
+
+/* static */void SerialStringTableUtil::appendDecodedStringTable(const List<char>& stringTable, List<UnownedStringSlice>& slicesOut)
+{
+ const char* start = stringTable.begin();
+ const char* cur = start;
+ const char* end = stringTable.end();
+
+ while (cur < end)
+ {
+ CharReader reader(cur);
+ const int len = GetUnicodePointFromUTF8(reader);
+ slicesOut.add(UnownedStringSlice(reader.m_pos, len));
+ cur = reader.m_pos + len;
+ }
+}
+
+/* static */void SerialStringTableUtil::decodeStringTable(const List<char>& stringTable, List<UnownedStringSlice>& slicesOut)
+{
+ slicesOut.setCount(2);
+ slicesOut[0] = UnownedStringSlice(nullptr, size_t(0));
+ slicesOut[1] = UnownedStringSlice("", size_t(0));
+
+ appendDecodedStringTable(stringTable, slicesOut);
+}
+
+/* static */void SerialStringTableUtil::calcStringSlicePoolMap(const List<UnownedStringSlice>& slices, StringSlicePool& pool, List<StringSlicePool::Handle>& indexMapOut)
+{
+ SLANG_ASSERT(slices.getCount() >= StringSlicePool::kNumDefaultHandles);
+ SLANG_ASSERT(slices[int(StringSlicePool::kNullHandle)] == "" && slices[int(StringSlicePool::kNullHandle)].begin() == nullptr);
+ SLANG_ASSERT(slices[int(StringSlicePool::kEmptyHandle)] == "");
+
+ indexMapOut.setCount(slices.getCount());
+ // Set up all of the defaults
+ for (int i = 0; i < StringSlicePool::kNumDefaultHandles; ++i)
+ {
+ indexMapOut[i] = StringSlicePool::Handle(i);
+ }
+
+ const Index numSlices = slices.getCount();
+ for (Index i = StringSlicePool::kNumDefaultHandles; i < numSlices ; ++i)
+ {
+ indexMapOut[i] = pool.add(slices[i]);
+ }
+}
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! IRSerialData !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+template<typename T>
+static size_t _calcArraySize(const List<T>& list)
+{
+ return list.getCount() * sizeof(T);
+}
+
+size_t IRSerialData::calcSizeInBytes() const
+{
+ return
+ _calcArraySize(m_insts) +
+ _calcArraySize(m_childRuns) +
+ _calcArraySize(m_externalOperands) +
+ _calcArraySize(m_stringTable) +
+ /* Raw source locs */
+ _calcArraySize(m_rawSourceLocs) +
+ /* Debug */
+ _calcArraySize(m_debugStringTable) +
+ _calcArraySize(m_debugLineInfos) +
+ _calcArraySize(m_debugSourceInfos) +
+ _calcArraySize(m_debugAdjustedLineInfos) +
+ _calcArraySize(m_debugSourceLocRuns);
+}
+
+IRSerialData::IRSerialData()
+{
+ clear();
+}
+
+void IRSerialData::clear()
+{
+ // First Instruction is null
+ m_insts.setCount(1);
+ memset(&m_insts[0], 0, sizeof(Inst));
+
+ m_childRuns.clear();
+ m_externalOperands.clear();
+ m_rawSourceLocs.clear();
+
+ m_stringTable.clear();
+
+ // Debug data
+ m_debugLineInfos.clear();
+ m_debugAdjustedLineInfos.clear();
+ m_debugSourceInfos.clear();
+ m_debugSourceLocRuns.clear();
+ m_debugStringTable.clear();
+}
+
+template <typename T>
+static bool _isEqual(const List<T>& aIn, const List<T>& bIn)
+{
+ if (aIn.getCount() != bIn.getCount())
+ {
+ return false;
+ }
+
+ size_t size = size_t(aIn.getCount());
+
+ const T* a = aIn.begin();
+ const T* b = bIn.begin();
+
+ if (a == b)
+ {
+ return true;
+ }
+
+ for (size_t i = 0; i < size; ++i)
+ {
+ if (a[i] != b[i])
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool IRSerialData::operator==(const ThisType& rhs) const
+{
+ return (this == &rhs) ||
+ (_isEqual(m_insts, rhs.m_insts) &&
+ _isEqual(m_childRuns, rhs.m_childRuns) &&
+ _isEqual(m_externalOperands, rhs.m_externalOperands) &&
+ _isEqual(m_rawSourceLocs, rhs.m_rawSourceLocs) &&
+ _isEqual(m_stringTable, rhs.m_stringTable) &&
+ /* Debug */
+ _isEqual(m_debugStringTable, rhs.m_debugStringTable) &&
+ _isEqual(m_debugLineInfos, rhs.m_debugLineInfos) &&
+ _isEqual(m_debugAdjustedLineInfos, rhs.m_debugAdjustedLineInfos) &&
+ _isEqual(m_debugSourceInfos, rhs.m_debugSourceInfos) &&
+ _isEqual(m_debugSourceLocRuns, rhs.m_debugSourceLocRuns));
+}
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!! IRSerialTypeUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+#define SLANG_SERIAL_BINARY_COMPRESSION_TYPE(x) \
+ x(None, none) \
+ x(VariableByteLite, lite)
+
+/* static */SlangResult IRSerialTypeUtil::parseCompressionType(const UnownedStringSlice& text, IRSerialCompressionType& outType)
+{
+ struct Pair
+ {
+ UnownedStringSlice name;
+ IRSerialCompressionType type;
+ };
+
+#define SLANG_SERIAL_BINARY_PAIR(type, name) { UnownedStringSlice::fromLiteral(#name), IRSerialCompressionType::type},
+
+ static const Pair s_pairs[] = {
+ SLANG_SERIAL_BINARY_COMPRESSION_TYPE(SLANG_SERIAL_BINARY_PAIR)
+ };
+
+ for (const auto& pair : s_pairs)
+ {
+ if (pair.name == text)
+ {
+ outType = pair.type;
+ return SLANG_OK;
+ }
+ }
+ return SLANG_FAIL;
+}
+
+/* static */UnownedStringSlice IRSerialTypeUtil::getText(IRSerialCompressionType type)
+{
+#define SLANG_SERIAL_BINARY_CASE(type, name) case IRSerialCompressionType::type: return UnownedStringSlice::fromLiteral(#name);
+ switch (type)
+ {
+ SLANG_SERIAL_BINARY_COMPRESSION_TYPE(SLANG_SERIAL_BINARY_CASE)
+ default: break;
+ }
+
+ SLANG_ASSERT(!"Unknown compression type");
+ return UnownedStringSlice::fromLiteral("unknown");
+}
+
+} // namespace Slang
diff --git a/source/slang/slang-ir-serialize-types.h b/source/slang/slang-ir-serialize-types.h
new file mode 100644
index 000000000..0de9769c5
--- /dev/null
+++ b/source/slang/slang-ir-serialize-types.h
@@ -0,0 +1,423 @@
+// slang-ir-serialize-types.h
+#ifndef SLANG_IR_SERIALIZE_TYPES_H_INCLUDED
+#define SLANG_IR_SERIALIZE_TYPES_H_INCLUDED
+
+#include "../core/slang-object-scope-manager.h"
+#include "../core/slang-riff.h"
+#include "../core/slang-string-slice-pool.h"
+
+#include "slang-name.h"
+#include "slang-source-loc.h"
+
+#include "slang-ir.h"
+
+namespace Slang {
+
+enum class IRSerialCompressionType : uint8_t
+{
+ None,
+ VariableByteLite,
+};
+
+class StringRepresentationCache
+{
+ public:
+ typedef StringSlicePool::Handle Handle;
+
+ struct Entry
+ {
+ uint32_t m_startIndex;
+ uint32_t m_numChars;
+ RefObject* m_object; ///< Could be nullptr, Name, or StringRepresentation.
+ };
+
+ /// Get as a name
+ Name* getName(Handle handle);
+ /// Get as a string
+ String getString(Handle handle);
+ /// Get as string representation
+ StringRepresentation* getStringRepresentation(Handle handle);
+ /// Get as a string slice
+ UnownedStringSlice getStringSlice(Handle handle) const;
+ /// Get as a 0 terminated 'c style' string
+ char* getCStr(Handle handle);
+
+ /// Initialize a cache to use a string table, namePool and scopeManager
+ void init(const List<char>* stringTable, NamePool* namePool, ObjectScopeManager* scopeManager);
+
+ /// Ctor
+ StringRepresentationCache();
+
+ protected:
+ ObjectScopeManager* m_scopeManager;
+ NamePool* m_namePool;
+ const List<char>* m_stringTable;
+ List<Entry> m_entries;
+};
+
+struct SerialStringTableUtil
+{
+ /// Convert a pool into a string table
+ static void encodeStringTable(const StringSlicePool& pool, List<char>& stringTable);
+ static void encodeStringTable(const UnownedStringSlice* slices, size_t numSlices, List<char>& stringTable);
+ /// Appends the decoded strings into slicesOut
+ static void appendDecodedStringTable(const List<char>& stringTable, List<UnownedStringSlice>& slicesOut);
+ /// Decodes a string table (and does so such that the indices are compatible with StringSlicePool)
+ static void decodeStringTable(const List<char>& stringTable, List<UnownedStringSlice>& slicesOut);
+
+ /// Produces an index map, from slices to indices in pool
+ static void calcStringSlicePoolMap(const List<UnownedStringSlice>& slices, StringSlicePool& pool, List<StringSlicePool::Handle>& indexMap);
+};
+
+// Pre-declare
+class Name;
+
+struct IRSerialData
+{
+ typedef IRSerialData ThisType;
+
+ enum class InstIndex : uint32_t;
+ enum class StringIndex : uint32_t;
+ enum class ArrayIndex : uint32_t;
+
+ enum class RawSourceLoc : SourceLoc::RawValue; ///< This is just to copy over source loc data (ie not strictly serialize)
+ enum class StringOffset : uint32_t; ///< Offset into the m_stringsBuffer
+
+ typedef uint32_t SizeType;
+
+ static const StringIndex kNullStringIndex = StringIndex(StringSlicePool::kNullHandle);
+ static const StringIndex kEmptyStringIndex = StringIndex(StringSlicePool::kEmptyHandle);
+
+ /// A run of instructions
+ struct InstRun
+ {
+ typedef InstRun ThisType;
+ SLANG_FORCE_INLINE bool operator==(const ThisType& rhs) const
+ {
+ return m_parentIndex == rhs.m_parentIndex &&
+ m_startInstIndex == rhs.m_startInstIndex &&
+ m_numChildren == rhs.m_numChildren;
+ }
+ SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
+
+ InstIndex m_parentIndex; ///< The parent instruction
+ InstIndex m_startInstIndex; ///< The index to the first instruction
+ SizeType m_numChildren; ///< The number of children
+ };
+
+ struct SourceLocRun
+ {
+ typedef SourceLocRun ThisType;
+
+ bool operator==(const ThisType& rhs) const { return m_sourceLoc == rhs.m_sourceLoc && m_startInstIndex == rhs.m_startInstIndex && m_numInst == rhs.m_numInst; }
+ bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
+ bool operator<(const ThisType& rhs) const { return m_sourceLoc < rhs.m_sourceLoc; }
+
+ uint32_t m_sourceLoc; ///< The source location
+ InstIndex m_startInstIndex; ///< The index to the first instruction
+ SizeType m_numInst; ///< The number of children
+ };
+
+ struct PayloadInfo
+ {
+ uint8_t m_numOperands;
+ uint8_t m_numStrings;
+ };
+
+ struct DebugSourceInfo
+ {
+ typedef DebugSourceInfo ThisType;
+
+ bool operator==(const ThisType& rhs) const
+ {
+ return m_pathIndex == rhs.m_pathIndex &&
+ m_startSourceLoc == rhs.m_startSourceLoc &&
+ m_endSourceLoc == rhs.m_endSourceLoc &&
+ m_numLineInfos == rhs.m_numLineInfos &&
+ m_lineInfosStartIndex == rhs.m_lineInfosStartIndex &&
+ m_numLineInfos == rhs.m_numLineInfos;
+ }
+ bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
+
+ bool isSourceLocInRange(uint32_t sourceLoc) const { return sourceLoc >= m_startSourceLoc && sourceLoc <= m_endSourceLoc; }
+
+ StringIndex m_pathIndex; ///< Index to the string table
+ uint32_t m_startSourceLoc; ///< The offset to the source
+ uint32_t m_endSourceLoc; ///< The number of bytes in the source
+
+ uint32_t m_numLines; ///< Total number of lines in source file
+
+ uint32_t m_lineInfosStartIndex; ///< Index into m_debugLineInfos
+ uint32_t m_numLineInfos; ///< The number of line infos
+
+ uint32_t m_adjustedLineInfosStartIndex; ///< Adjusted start index
+ uint32_t m_numAdjustedLineInfos; ///< The number of line infos
+ };
+
+ struct DebugLineInfo
+ {
+ typedef DebugLineInfo ThisType;
+ bool operator<(const ThisType& rhs) const { return m_lineStartOffset < rhs.m_lineStartOffset; }
+ bool operator==(const ThisType& rhs) const
+ {
+ return m_lineStartOffset == rhs.m_lineStartOffset &&
+ m_lineIndex == rhs.m_lineIndex;
+ }
+ bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
+
+ uint32_t m_lineStartOffset; ///< The offset into the source file
+ uint32_t m_lineIndex; ///< Original line index
+ };
+
+ struct DebugAdjustedLineInfo
+ {
+ typedef DebugAdjustedLineInfo ThisType;
+ bool operator==(const ThisType& rhs) const
+ {
+ return m_lineInfo == rhs.m_lineInfo &&
+ m_adjustedLineIndex == rhs.m_adjustedLineIndex &&
+ m_pathStringIndex == rhs.m_pathStringIndex;
+ }
+ bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
+ bool operator<(const ThisType& rhs) const { return m_lineInfo < rhs.m_lineInfo; }
+
+ DebugLineInfo m_lineInfo;
+ uint32_t m_adjustedLineIndex; ///< The line index with the adjustment (if there is any). Is 0 if m_pathStringIndex is 0.
+ StringIndex m_pathStringIndex; ///< The path as an index
+ };
+
+ // Instruction...
+ // We can store SourceLoc values separately. Just store per index information.
+ // Parent information is stored in m_childRuns
+ // Decoration information is stored in m_decorationRuns
+ struct Inst
+ {
+ typedef Inst ThisType;
+ enum
+ {
+ kMaxOperands = 2, ///< Maximum number of operands that can be held in an instruction (otherwise held 'externally')
+ };
+
+ // NOTE! Can't change order or list without changing appropriate s_payloadInfos
+ enum class PayloadType : uint8_t
+ {
+ // First 3 must be in this order so a cast from 0-2 is directly represented as number of operands
+ Empty, ///< Has no payload (or operands)
+ Operand_1, ///< 1 Operand
+ Operand_2, ///< 2 Operands
+
+ OperandAndUInt32, ///< 1 Operand and a single UInt32
+ OperandExternal, ///< Operands are held externally
+ String_1, ///< 1 String
+ String_2, ///< 2 Strings
+ UInt32, ///< Holds an unsigned 32 bit integral (might represent a type)
+ Float64,
+ Int64,
+
+ CountOf,
+ };
+
+ /// Get the number of operands
+ SLANG_FORCE_INLINE int getNumOperands() const;
+
+ bool operator==(const ThisType& rhs) const;
+
+ SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
+
+ uint8_t m_op; ///< For now one of IROp
+ PayloadType m_payloadType; ///< The type of payload
+ uint16_t m_pad0; ///< Not currently used
+
+ InstIndex m_resultTypeIndex; //< 0 if has no type. The result type of this instruction
+
+ struct ExternalOperandPayload
+ {
+ ArrayIndex m_arrayIndex; ///< Index into the m_externalOperands table
+ SizeType m_size; ///< The amount of entries in that table
+ };
+
+ struct OperandAndUInt32
+ {
+ InstIndex m_operand;
+ uint32_t m_uint32;
+ };
+
+ union Payload
+ {
+ double m_float64;
+ int64_t m_int64;
+ uint32_t m_uint32; ///< Unsigned integral value
+ IRFloatingPointValue m_float; ///< Floating point value
+ IRIntegerValue m_int; ///< Integral value
+ InstIndex m_operands[kMaxOperands]; ///< For items that 2 or less operands it can use this.
+ StringIndex m_stringIndices[kMaxOperands];
+ ExternalOperandPayload m_externalOperand; ///< Operands are stored in an an index of an operand array
+ OperandAndUInt32 m_operandAndUInt32;
+ };
+
+ Payload m_payload;
+ };
+
+ /// Clear to initial state
+ void clear();
+ /// Get the operands of an instruction
+ SLANG_FORCE_INLINE int getOperands(const Inst& inst, const InstIndex** operandsOut) const;
+
+ /// ==
+ bool operator==(const ThisType& rhs) const;
+ SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
+
+ /// Calculate the amount of memory used by this IRSerialData
+ size_t calcSizeInBytes() const;
+
+ /// Ctor
+ IRSerialData();
+
+ List<Inst> m_insts; ///< The instructions
+
+ List<InstRun> m_childRuns; ///< Holds the information about children that belong to an instruction
+
+ List<InstIndex> m_externalOperands; ///< Holds external operands (for instructions with more than kNumOperands)
+
+ List<char> m_stringTable; ///< All strings. Indexed into by StringIndex
+
+ List<RawSourceLoc> m_rawSourceLocs; ///< A source location per instruction (saved without modification from IRInst)s
+
+ // Data only set if we have debug information
+
+ List<char> m_debugStringTable; ///< String table for debug use only
+ List<DebugLineInfo> m_debugLineInfos; ///< Debug line information
+ List<DebugAdjustedLineInfo> m_debugAdjustedLineInfos; ///< Adjusted line infos
+ List<DebugSourceInfo> m_debugSourceInfos; ///< Debug source information
+ List<SourceLocRun> m_debugSourceLocRuns; ///< Runs of instructions that use a source loc
+
+ static const PayloadInfo s_payloadInfos[int(Inst::PayloadType::CountOf)];
+};
+
+// --------------------------------------------------------------------------
+SLANG_FORCE_INLINE int IRSerialData::Inst::getNumOperands() const
+{
+ return (m_payloadType == PayloadType::OperandExternal) ? m_payload.m_externalOperand.m_size : s_payloadInfos[int(m_payloadType)].m_numOperands;
+}
+
+// --------------------------------------------------------------------------
+SLANG_FORCE_INLINE bool IRSerialData::Inst::operator==(const ThisType& rhs) const
+{
+ if (m_op == rhs.m_op &&
+ m_payloadType == rhs.m_payloadType &&
+ m_resultTypeIndex == rhs.m_resultTypeIndex)
+ {
+ switch (m_payloadType)
+ {
+ case PayloadType::Empty:
+ {
+ return true;
+ }
+ case PayloadType::Operand_1:
+ case PayloadType::String_1:
+ case PayloadType::UInt32:
+ {
+ return m_payload.m_operands[0] == rhs.m_payload.m_operands[0];
+ }
+ case PayloadType::OperandAndUInt32:
+ case PayloadType::OperandExternal:
+ case PayloadType::Operand_2:
+ case PayloadType::String_2:
+ {
+ return m_payload.m_operands[0] == rhs.m_payload.m_operands[0] &&
+ m_payload.m_operands[1] == rhs.m_payload.m_operands[1];
+ }
+ case PayloadType::Float64:
+ case PayloadType::Int64:
+ {
+ return m_payload.m_int64 == rhs.m_payload.m_int64;
+ }
+ default: break;
+ }
+ }
+
+ return false;
+}
+// --------------------------------------------------------------------------
+SLANG_FORCE_INLINE int IRSerialData::getOperands(const Inst& inst, const InstIndex** operandsOut) const
+{
+ if (inst.m_payloadType == Inst::PayloadType::OperandExternal)
+ {
+ *operandsOut = m_externalOperands.begin() + int(inst.m_payload.m_externalOperand.m_arrayIndex);
+ return int(inst.m_payload.m_externalOperand.m_size);
+ }
+ else
+ {
+ *operandsOut = inst.m_payload.m_operands;
+ return s_payloadInfos[int(inst.m_payloadType)].m_numOperands;
+ }
+}
+
+// Replace first char with 's'
+#define SLANG_MAKE_COMPRESSED_FOUR_CC(fourCc) SLANG_FOUR_CC_REPLACE_FIRST_CHAR(fourCc, 's')
+
+struct IRSerialBinary
+{
+
+ static const FourCC kRiffFourCc = RiffFourCC::kRiff;
+
+ static const FourCC kSlangModuleListFourCc = SLANG_FOUR_CC('S', 'L', 'm', 'l');
+
+ static const FourCC kSlangModuleFourCc = SLANG_FOUR_CC('S', 'L', 'm', 'd'); ///< Holds all the slang specific chunks
+
+ static const FourCC kSlangModuleHeaderFourCc = SLANG_FOUR_CC('S', 'L', 'h', 'd');
+
+ /* NOTE! All FourCC that can be compressed must start with capital 'S', because compressed version is the same FourCC
+ with the 'S' replaced with 's' */
+
+ static const FourCC kInstFourCc = SLANG_FOUR_CC('S', 'L', 'i', 'n');
+ static const FourCC kChildRunFourCc = SLANG_FOUR_CC('S', 'L', 'c', 'r');
+ static const FourCC kExternalOperandsFourCc = SLANG_FOUR_CC('S', 'L', 'e', 'o');
+
+ static const FourCC kCompressedInstFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kInstFourCc);
+ static const FourCC kCompressedChildRunFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kChildRunFourCc);
+ static const FourCC kCompressedExternalOperandsFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kExternalOperandsFourCc);
+
+
+ static const FourCC kStringFourCc = SLANG_FOUR_CC('S', 'L', 's', 't');
+
+ static const FourCC kUInt32SourceLocFourCc = SLANG_FOUR_CC('S', 'r', 's', '4');
+
+ static const FourCC kDebugStringFourCc = SLANG_FOUR_CC('S', 'd', 's', 't');
+ static const FourCC kDebugLineInfoFourCc = SLANG_FOUR_CC('S', 'd', 'l', 'n');
+ static const FourCC kDebugAdjustedLineInfoFourCc = SLANG_FOUR_CC('S', 'd', 'a', 'l');
+ static const FourCC kDebugSourceInfoFourCc = SLANG_FOUR_CC('S', 'd', 's', 'o');
+ static const FourCC kDebugSourceLocRunFourCc = SLANG_FOUR_CC('S', 'd', 's', 'r');
+
+ static const FourCC kEntryPointFourCc = SLANG_FOUR_CC('E', 'P', 'n', 't');
+
+ typedef IRSerialCompressionType CompressionType;
+
+ struct ModuleHeader
+ {
+ uint32_t compressionType; ///< Holds the compression type used (if used at all)
+ };
+ struct ArrayHeader
+ {
+ uint32_t numEntries;
+ };
+ struct CompressedArrayHeader
+ {
+ uint32_t numEntries; ///< The number of entries
+ uint32_t numCompressedEntries; ///< The amount of compressed entries
+ };
+
+};
+
+struct IRSerialTypeUtil
+{
+ /// Given text, finds the compression type
+ static SlangResult parseCompressionType(const UnownedStringSlice& text, IRSerialCompressionType& outType);
+ /// Given a compression type, return text
+ static UnownedStringSlice getText(IRSerialCompressionType type);
+};
+
+
+} // namespace Slang
+
+#endif
diff --git a/source/slang/slang-ir-serialize.cpp b/source/slang/slang-ir-serialize.cpp
index fcde8dcda..1b734c6b2 100644
--- a/source/slang/slang-ir-serialize.cpp
+++ b/source/slang/slang-ir-serialize.cpp
@@ -10,364 +10,18 @@
namespace Slang {
-// Needed for linkage with some compilers
-/* static */ const IRSerialData::StringIndex IRSerialData::kNullStringIndex;
-/* static */ const IRSerialData::StringIndex IRSerialData::kEmptyStringIndex;
-
-/* Note that an IRInst can be derived from, but when it derived from it's new members are IRUse variables, and they in
-effect alias over the operands - and reflected in the operand count. There _could_ be other members after these IRUse
-variables, but only a few types include extra data, and these do not have any operands:
-
-* IRConstant - Needs special-case handling
-* IRModuleInst - Presumably we can just set to the module pointer on reconstruction
-
-Note! That on an IRInst there is an IRType* variable (accessed as getFullType()). As it stands it may NOT actually point
-to an IRType derived type. Its 'ok' as long as it's an instruction that can be used in the place of the type. So this code does not
-bother to check if it's correct, and just casts it.
-*/
-
-/* static */const IRSerialData::PayloadInfo IRSerialData::s_payloadInfos[int(Inst::PayloadType::CountOf)] =
-{
- { 0, 0 }, // Empty
- { 1, 0 }, // Operand_1
- { 2, 0 }, // Operand_2
- { 1, 0 }, // OperandAndUInt32,
- { 0, 0 }, // OperandExternal - This isn't correct, Operand has to be specially handled
- { 0, 1 }, // String_1,
- { 0, 2 }, // String_2,
- { 0, 0 }, // UInt32,
- { 0, 0 }, // Float64,
- { 0, 0 } // Int64,
-};
-
-static bool isTextureTypeBase(IROp opIn)
+static bool _isTextureTypeBase(IROp opIn)
{
const int op = (kIROpMeta_PseudoOpMask & opIn);
return op >= kIROp_FirstTextureTypeBase && op <= kIROp_LastTextureTypeBase;
}
-static bool isConstant(IROp opIn)
+static bool _isConstant(IROp opIn)
{
const int op = (kIROpMeta_PseudoOpMask & opIn);
return op >= kIROp_FirstConstant && op <= kIROp_LastConstant;
}
-struct PrefixString;
-
-namespace { // anonymous
-
-struct CharReader
-{
- char operator()(int pos) const { SLANG_UNUSED(pos); return *m_pos++; }
- CharReader(const char* pos) :m_pos(pos) {}
- mutable const char* m_pos;
-};
-
-} // anonymous
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! StringRepresentationCache !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-StringRepresentationCache::StringRepresentationCache():
- m_stringTable(nullptr),
- m_namePool(nullptr),
- m_scopeManager(nullptr)
-{
-}
-
-void StringRepresentationCache::init(const List<char>* stringTable, NamePool* namePool, ObjectScopeManager* scopeManager)
-{
- m_stringTable = stringTable;
- m_namePool = namePool;
- m_scopeManager = scopeManager;
-
- // Decode the table
- m_entries.setCount(StringSlicePool::kNumDefaultHandles);
- SLANG_COMPILE_TIME_ASSERT(StringSlicePool::kNumDefaultHandles == 2);
-
- {
- Entry& entry = m_entries[0];
- entry.m_numChars = 0;
- entry.m_startIndex = 0;
- entry.m_object = nullptr;
- }
- {
- Entry& entry = m_entries[1];
- entry.m_numChars = 0;
- entry.m_startIndex = 0;
- entry.m_object = nullptr;
- }
-
- {
- const char* start = stringTable->begin();
- const char* cur = start;
- const char* end = stringTable->end();
-
- while (cur < end)
- {
- CharReader reader(cur);
- const int len = GetUnicodePointFromUTF8(reader);
-
- Entry entry;
- entry.m_startIndex = uint32_t(reader.m_pos - start);
- entry.m_numChars = len;
- entry.m_object = nullptr;
-
- m_entries.add(entry);
-
- cur = reader.m_pos + len;
- }
- }
-
- m_entries.compress();
-}
-
-Name* StringRepresentationCache::getName(Handle handle)
-{
- if (handle == StringSlicePool::kNullHandle)
- {
- return nullptr;
- }
-
- Entry& entry = m_entries[int(handle)];
- if (entry.m_object)
- {
- Name* name = dynamicCast<Name>(entry.m_object);
- if (name)
- {
- return name;
- }
- StringRepresentation* stringRep = static_cast<StringRepresentation*>(entry.m_object);
- // Promote it to a name
- name = m_namePool->getName(String(stringRep));
- entry.m_object = name;
- return name;
- }
-
- Name* name = m_namePool->getName(String(getStringSlice(handle)));
- entry.m_object = name;
- return name;
-}
-
-String StringRepresentationCache::getString(Handle handle)
-{
- return String(getStringRepresentation(handle));
-}
-
-UnownedStringSlice StringRepresentationCache::getStringSlice(Handle handle) const
-{
- const Entry& entry = m_entries[int(handle)];
- const char* start = m_stringTable->begin();
-
- return UnownedStringSlice(start + entry.m_startIndex, int(entry.m_numChars));
-}
-
-StringRepresentation* StringRepresentationCache::getStringRepresentation(Handle handle)
-{
- if (handle == StringSlicePool::kNullHandle || handle == StringSlicePool::kEmptyHandle)
- {
- return nullptr;
- }
-
- Entry& entry = m_entries[int(handle)];
- if (entry.m_object)
- {
- Name* name = dynamicCast<Name>(entry.m_object);
- if (name)
- {
- return name->text.getStringRepresentation();
- }
- return static_cast<StringRepresentation*>(entry.m_object);
- }
-
- const UnownedStringSlice slice = getStringSlice(handle);
- const UInt size = slice.size();
-
- StringRepresentation* stringRep = StringRepresentation::createWithCapacityAndLength(size, size);
- memcpy(stringRep->getData(), slice.begin(), size);
- entry.m_object = stringRep;
-
- // Keep the StringRepresentation in scope
- m_scopeManager->add(stringRep);
-
- return stringRep;
-}
-
-char* StringRepresentationCache::getCStr(Handle handle)
-{
- // It turns out StringRepresentation is always 0 terminated, so can just use that
- StringRepresentation* rep = getStringRepresentation(handle);
- return rep->getData();
-}
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SerialStringTableUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-/* static */void SerialStringTableUtil::encodeStringTable(const StringSlicePool& pool, List<char>& stringTable)
-{
- // Skip the default handles -> nothing is encoded via them
- return encodeStringTable(pool.getSlices().begin() + StringSlicePool::kNumDefaultHandles, pool.getNumSlices() - StringSlicePool::kNumDefaultHandles, stringTable);
-}
-
-/* static */void SerialStringTableUtil::encodeStringTable(const UnownedStringSlice* slices, size_t numSlices, List<char>& stringTable)
-{
- stringTable.clear();
- for (size_t i = 0; i < numSlices; ++i)
- {
- const UnownedStringSlice slice = slices[i];
- const int len = int(slice.size());
-
- // We need to write into the the string array
- char prefixBytes[6];
- const int numPrefixBytes = EncodeUnicodePointToUTF8(prefixBytes, len);
- const Index baseIndex = stringTable.getCount();
-
- stringTable.setCount(baseIndex + numPrefixBytes + len);
-
- char* dst = stringTable.begin() + baseIndex;
-
- memcpy(dst, prefixBytes, numPrefixBytes);
- memcpy(dst + numPrefixBytes, slice.begin(), len);
- }
-}
-
-/* static */void SerialStringTableUtil::appendDecodedStringTable(const List<char>& stringTable, List<UnownedStringSlice>& slicesOut)
-{
- const char* start = stringTable.begin();
- const char* cur = start;
- const char* end = stringTable.end();
-
- while (cur < end)
- {
- CharReader reader(cur);
- const int len = GetUnicodePointFromUTF8(reader);
- slicesOut.add(UnownedStringSlice(reader.m_pos, len));
- cur = reader.m_pos + len;
- }
-}
-
-/* static */void SerialStringTableUtil::decodeStringTable(const List<char>& stringTable, List<UnownedStringSlice>& slicesOut)
-{
- slicesOut.setCount(2);
- slicesOut[0] = UnownedStringSlice(nullptr, size_t(0));
- slicesOut[1] = UnownedStringSlice("", size_t(0));
-
- appendDecodedStringTable(stringTable, slicesOut);
-}
-
-/* static */void SerialStringTableUtil::calcStringSlicePoolMap(const List<UnownedStringSlice>& slices, StringSlicePool& pool, List<StringSlicePool::Handle>& indexMapOut)
-{
- SLANG_ASSERT(slices.getCount() >= StringSlicePool::kNumDefaultHandles);
- SLANG_ASSERT(slices[int(StringSlicePool::kNullHandle)] == "" && slices[int(StringSlicePool::kNullHandle)].begin() == nullptr);
- SLANG_ASSERT(slices[int(StringSlicePool::kEmptyHandle)] == "");
-
- indexMapOut.setCount(slices.getCount());
- // Set up all of the defaults
- for (int i = 0; i < StringSlicePool::kNumDefaultHandles; ++i)
- {
- indexMapOut[i] = StringSlicePool::Handle(i);
- }
-
- const Index numSlices = slices.getCount();
- for (Index i = StringSlicePool::kNumDefaultHandles; i < numSlices ; ++i)
- {
- indexMapOut[i] = pool.add(slices[i]);
- }
-}
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! IRSerialData !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-template<typename T>
-static size_t _calcArraySize(const List<T>& list)
-{
- return list.getCount() * sizeof(T);
-}
-
-size_t IRSerialData::calcSizeInBytes() const
-{
- return
- _calcArraySize(m_insts) +
- _calcArraySize(m_childRuns) +
- _calcArraySize(m_externalOperands) +
- _calcArraySize(m_stringTable) +
- /* Raw source locs */
- _calcArraySize(m_rawSourceLocs) +
- /* Debug */
- _calcArraySize(m_debugStringTable) +
- _calcArraySize(m_debugLineInfos) +
- _calcArraySize(m_debugSourceInfos) +
- _calcArraySize(m_debugAdjustedLineInfos) +
- _calcArraySize(m_debugSourceLocRuns);
-}
-
-IRSerialData::IRSerialData()
-{
- clear();
-}
-
-void IRSerialData::clear()
-{
- // First Instruction is null
- m_insts.setCount(1);
- memset(&m_insts[0], 0, sizeof(Inst));
-
- m_childRuns.clear();
- m_externalOperands.clear();
- m_rawSourceLocs.clear();
-
- m_stringTable.clear();
-
- // Debug data
- m_debugLineInfos.clear();
- m_debugAdjustedLineInfos.clear();
- m_debugSourceInfos.clear();
- m_debugSourceLocRuns.clear();
- m_debugStringTable.clear();
-}
-
-template <typename T>
-static bool _isEqual(const List<T>& aIn, const List<T>& bIn)
-{
- if (aIn.getCount() != bIn.getCount())
- {
- return false;
- }
-
- size_t size = size_t(aIn.getCount());
-
- const T* a = aIn.begin();
- const T* b = bIn.begin();
-
- if (a == b)
- {
- return true;
- }
-
- for (size_t i = 0; i < size; ++i)
- {
- if (a[i] != b[i])
- {
- return false;
- }
- }
-
- return true;
-}
-
-bool IRSerialData::operator==(const ThisType& rhs) const
-{
- return (this == &rhs) ||
- (_isEqual(m_insts, rhs.m_insts) &&
- _isEqual(m_childRuns, rhs.m_childRuns) &&
- _isEqual(m_externalOperands, rhs.m_externalOperands) &&
- _isEqual(m_rawSourceLocs, rhs.m_rawSourceLocs) &&
- _isEqual(m_stringTable, rhs.m_stringTable) &&
- /* Debug */
- _isEqual(m_debugStringTable, rhs.m_debugStringTable) &&
- _isEqual(m_debugLineInfos, rhs.m_debugLineInfos) &&
- _isEqual(m_debugAdjustedLineInfos, rhs.m_debugAdjustedLineInfos) &&
- _isEqual(m_debugSourceInfos, rhs.m_debugSourceInfos) &&
- _isEqual(m_debugSourceLocRuns, rhs.m_debugSourceLocRuns));
-}
-
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! IRSerialWriter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
void IRSerialWriter::_addInstruction(IRInst* inst)
@@ -380,29 +34,6 @@ void IRSerialWriter::_addInstruction(IRInst* inst)
m_insts.add(inst);
}
-#if 0
-// Find a view index that matches the view by file (and perhaps other characteristics in the future)
-static int _findSourceViewIndex(const List<SourceView*>& viewsIn, SourceView* view)
-{
- const int numViews = int(viewsIn.Count());
- SourceView*const* views = viewsIn.begin();
-
- SourceFile* sourceFile = view->getSourceFile();
-
- for (int i = 0; i < numViews; ++i)
- {
- SourceView* curView = views[i];
- // For now we just match on source file
- if (curView->getSourceFile() == sourceFile)
- {
- // It's a hit
- return i;
- }
- }
- return -1;
-}
-#endif
-
void IRSerialWriter::_addDebugSourceLocRun(SourceLoc sourceLoc, uint32_t startInstIndex, uint32_t numInsts)
{
SourceView* sourceView = m_sourceManager->findSourceView(sourceLoc);
@@ -792,7 +423,7 @@ Result IRSerialWriter::write(IRModule* module, SourceManager* sourceManager, Opt
return SLANG_OK;
}
-static Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType, uint32_t chunkId, const void* data, size_t numEntries, size_t typeSize, RiffContainer* container)
+static Result _writeArrayChunk(IRSerialCompressionType compressionType, FourCC chunkId, const void* data, size_t numEntries, size_t typeSize, RiffContainer* container)
{
typedef RiffContainer::Chunk Chunk;
typedef RiffContainer::ScopeChunk ScopeChunk;
@@ -803,11 +434,15 @@ static Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType,
return SLANG_OK;
}
+ // Make compressed fourCC
+ chunkId = (compressionType != IRSerialCompressionType::None) ? SLANG_MAKE_COMPRESSED_FOUR_CC(chunkId) : chunkId;
+
+ ScopeChunk scope(container, Chunk::Kind::Data, chunkId);
+
switch (compressionType)
{
- case Bin::CompressionType::None:
+ case IRSerialCompressionType::None:
{
- ScopeChunk scope(container, Chunk::Kind::Data, chunkId);
Bin::ArrayHeader header;
header.numEntries = uint32_t(numEntries);
@@ -815,7 +450,7 @@ static Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType,
container->write(data, typeSize * numEntries);
break;
}
- case Bin::CompressionType::VariableByteLite:
+ case IRSerialCompressionType::VariableByteLite:
{
List<uint8_t> compressedPayload;
@@ -841,17 +476,17 @@ static Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType,
}
template <typename T>
-Result _writeArrayChunk(IRSerialBinary::CompressionType compressionType, uint32_t chunkId, const List<T>& array, RiffContainer* container)
+Result _writeArrayChunk(IRSerialCompressionType compressionType, FourCC chunkId, const List<T>& array, RiffContainer* container)
{
return _writeArrayChunk(compressionType, chunkId, array.begin(), size_t(array.getCount()), sizeof(T), container);
}
-Result _encodeInsts(IRSerialBinary::CompressionType compressionType, const List<IRSerialData::Inst>& instsIn, List<uint8_t>& encodeArrayOut)
+Result _encodeInsts(IRSerialCompressionType compressionType, const List<IRSerialData::Inst>& instsIn, List<uint8_t>& encodeArrayOut)
{
typedef IRSerialBinary Bin;
typedef IRSerialData::Inst::PayloadType PayloadType;
- if (compressionType != Bin::CompressionType::VariableByteLite)
+ if (compressionType != IRSerialCompressionType::VariableByteLite)
{
return SLANG_FAIL;
}
@@ -936,7 +571,7 @@ Result _encodeInsts(IRSerialBinary::CompressionType compressionType, const List<
return SLANG_OK;
}
-Result _writeInstArrayChunk(IRSerialBinary::CompressionType compressionType, uint32_t chunkId, const List<IRSerialData::Inst>& array, RiffContainer* container)
+Result _writeInstArrayChunk(IRSerialCompressionType compressionType, FourCC chunkId, const List<IRSerialData::Inst>& array, RiffContainer* container)
{
typedef RiffContainer::Chunk Chunk;
typedef RiffContainer::ScopeChunk ScopeChunk;
@@ -949,11 +584,11 @@ Result _writeInstArrayChunk(IRSerialBinary::CompressionType compressionType, uin
switch (compressionType)
{
- case Bin::CompressionType::None:
+ case IRSerialCompressionType::None:
{
return _writeArrayChunk(compressionType, chunkId, array, container);
}
- case Bin::CompressionType::VariableByteLite:
+ case IRSerialCompressionType::VariableByteLite:
{
List<uint8_t> compressedPayload;
SLANG_RETURN_ON_FAIL(_encodeInsts(compressionType, array, compressedPayload));
@@ -976,7 +611,7 @@ Result _writeInstArrayChunk(IRSerialBinary::CompressionType compressionType, uin
return SLANG_FAIL;
}
-/* static */Result IRSerialWriter::writeContainer(const IRSerialData& data, Bin::CompressionType compressionType, RiffContainer* container)
+/* static */Result IRSerialWriter::writeContainer(const IRSerialData& data, IRSerialCompressionType compressionType, RiffContainer* container)
{
typedef RiffContainer::Chunk Chunk;
typedef RiffContainer::ScopeChunk ScopeChunk;
@@ -986,7 +621,8 @@ Result _writeInstArrayChunk(IRSerialBinary::CompressionType compressionType, uin
// Write the header
{
Bin::ModuleHeader moduleHeader;
- moduleHeader.compressionType = uint32_t(Bin::CompressionType::VariableByteLite);
+ moduleHeader.compressionType = uint32_t(IRSerialCompressionType::VariableByteLite);
+
ScopeChunk scopeHeader(container, Chunk::Kind::Data, Bin::kSlangModuleHeaderFourCc);
container->write(&moduleHeader, sizeof(moduleHeader));
}
@@ -994,23 +630,23 @@ Result _writeInstArrayChunk(IRSerialBinary::CompressionType compressionType, uin
SLANG_RETURN_ON_FAIL(_writeInstArrayChunk(compressionType, Bin::kInstFourCc, data.m_insts, container));
SLANG_RETURN_ON_FAIL(_writeArrayChunk(compressionType, Bin::kChildRunFourCc, data.m_childRuns, container));
SLANG_RETURN_ON_FAIL(_writeArrayChunk(compressionType, Bin::kExternalOperandsFourCc, data.m_externalOperands, container));
- SLANG_RETURN_ON_FAIL(_writeArrayChunk(Bin::CompressionType::None, Bin::kStringFourCc, data.m_stringTable, container));
+ SLANG_RETURN_ON_FAIL(_writeArrayChunk(IRSerialCompressionType::None, Bin::kStringFourCc, data.m_stringTable, container));
- SLANG_RETURN_ON_FAIL(_writeArrayChunk(Bin::CompressionType::None, Bin::kUInt32SourceLocFourCc, data.m_rawSourceLocs, container));
+ SLANG_RETURN_ON_FAIL(_writeArrayChunk(IRSerialCompressionType::None, Bin::kUInt32SourceLocFourCc, data.m_rawSourceLocs, container));
if (data.m_debugSourceInfos.getCount())
{
- _writeArrayChunk(Bin::CompressionType::None, Bin::kDebugStringFourCc, data.m_debugStringTable, container);
- _writeArrayChunk(Bin::CompressionType::None, Bin::kDebugLineInfoFourCc, data.m_debugLineInfos, container);
- _writeArrayChunk(Bin::CompressionType::None, Bin::kDebugAdjustedLineInfoFourCc, data.m_debugAdjustedLineInfos, container);
- _writeArrayChunk(Bin::CompressionType::None, Bin::kDebugSourceInfoFourCc, data.m_debugSourceInfos, container);
+ _writeArrayChunk(IRSerialCompressionType::None, Bin::kDebugStringFourCc, data.m_debugStringTable, container);
+ _writeArrayChunk(IRSerialCompressionType::None, Bin::kDebugLineInfoFourCc, data.m_debugLineInfos, container);
+ _writeArrayChunk(IRSerialCompressionType::None, Bin::kDebugAdjustedLineInfoFourCc, data.m_debugAdjustedLineInfos, container);
+ _writeArrayChunk(IRSerialCompressionType::None, Bin::kDebugSourceInfoFourCc, data.m_debugSourceInfos, container);
_writeArrayChunk(compressionType, Bin::kDebugSourceLocRunFourCc, data.m_debugSourceLocRuns, container);
}
return SLANG_OK;
}
-/* static */Result IRSerialWriter::writeStream(const IRSerialData& data, Bin::CompressionType compressionType, Stream* stream)
+/* static */Result IRSerialWriter::writeStream(const IRSerialData& data, IRSerialCompressionType compressionType, Stream* stream)
{
RiffContainer container;
SLANG_RETURN_ON_FAIL(writeContainer(data, compressionType, &container));
@@ -1051,7 +687,7 @@ class ListResizerForType: public ListResizer
List<T>& m_list;
};
-static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, RiffContainer::DataChunk* dataChunk, ListResizer& listOut)
+static Result _readArrayChunk(IRSerialCompressionType compressionType, RiffContainer::DataChunk* dataChunk, ListResizer& listOut)
{
typedef IRSerialBinary Bin;
@@ -1060,7 +696,7 @@ static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, R
switch (compressionType)
{
- case Bin::CompressionType::VariableByteLite:
+ case IRSerialCompressionType::VariableByteLite:
{
Bin::CompressedArrayHeader header;
SLANG_RETURN_ON_FAIL(read.read(header));
@@ -1072,7 +708,7 @@ static Result _readArrayChunk(IRSerialBinary::CompressionType compressionType, R
ByteEncodeUtil::decodeLiteUInt32(read.getData(), header.numCompressedEntries, (uint32_t*)dst);
break;
}
- case Bin::CompressionType::None:
+ case IRSerialCompressionType::None:
{
// Read uncompressed
Bin::ArrayHeader header;
@@ -1111,14 +747,14 @@ static Result _readArrayUncompressedChunk(const IRSerialBinary::ModuleHeader* he
return _readArrayChunk(IRSerialBinary::CompressionType::None, chunk, resizer);
}
-static Result _decodeInsts(IRSerialBinary::CompressionType compressionType, const uint8_t* encodeCur, size_t encodeInSize, List<IRSerialData::Inst>& instsOut)
+static Result _decodeInsts(IRSerialCompressionType compressionType, const uint8_t* encodeCur, size_t encodeInSize, List<IRSerialData::Inst>& instsOut)
{
const uint8_t* encodeEnd = encodeCur + encodeInSize;
typedef IRSerialBinary Bin;
typedef IRSerialData::Inst::PayloadType PayloadType;
- if (compressionType != Bin::CompressionType::VariableByteLite)
+ if (compressionType != IRSerialCompressionType::VariableByteLite)
{
return SLANG_FAIL;
}
@@ -1188,20 +824,20 @@ static Result _readInstArrayChunk(const IRSerialBinary::ModuleHeader* moduleHead
{
typedef IRSerialBinary Bin;
- Bin::CompressionType compressionType = Bin::CompressionType::None;
+ IRSerialCompressionType compressionType = IRSerialCompressionType::None;
if (chunk->m_fourCC == SLANG_MAKE_COMPRESSED_FOUR_CC(chunk->m_fourCC))
{
- compressionType = Bin::CompressionType(moduleHeader->compressionType);
+ compressionType = IRSerialCompressionType(moduleHeader->compressionType);
}
switch (compressionType)
{
- case Bin::CompressionType::None:
+ case IRSerialCompressionType::None:
{
ListResizerForType<IRSerialData::Inst> resizer(arrayOut);
return _readArrayChunk(compressionType, chunk, resizer);
}
- case Bin::CompressionType::VariableByteLite:
+ case IRSerialCompressionType::VariableByteLite:
{
RiffReadHelper read = chunk->asReadHelper();
@@ -1481,7 +1117,7 @@ static int _calcFixSourceLoc(const IRSerialData::DebugSourceInfo& info, SourceVi
const IROp op((IROp)srcInst.m_op);
- if (isConstant(op))
+ if (_isConstant(op))
{
// Handling of constants
@@ -1548,7 +1184,7 @@ static int _calcFixSourceLoc(const IRSerialData::DebugSourceInfo& info, SourceVi
insts[i] = irConst;
}
- else if (isTextureTypeBase(op))
+ else if (_isTextureTypeBase(op))
{
IRTextureTypeBase* inst = static_cast<IRTextureTypeBase*>(createEmptyInst(module, op, 1));
SLANG_ASSERT(srcInst.m_payloadType == PayloadType::OperandAndUInt32);
@@ -1823,7 +1459,7 @@ static int _calcFixSourceLoc(const IRSerialData::DebugSourceInfo& info, SourceVi
}
}
-/* static */SlangResult IRSerialUtil::verifySerialize(IRModule* module, Session* session, SourceManager* sourceManager, IRSerialBinary::CompressionType compressionType, IRSerialWriter::OptionFlags optionFlags)
+/* static */SlangResult IRSerialUtil::verifySerialize(IRModule* module, Session* session, SourceManager* sourceManager, IRSerialCompressionType compressionType, IRSerialWriter::OptionFlags optionFlags)
{
// Verify if we can stream out with debug information
diff --git a/source/slang/slang-ir-serialize.h b/source/slang/slang-ir-serialize.h
index 644e533ae..7e80aeaad 100644
--- a/source/slang/slang-ir-serialize.h
+++ b/source/slang/slang-ir-serialize.h
@@ -2,405 +2,21 @@
#ifndef SLANG_IR_SERIALIZE_H_INCLUDED
#define SLANG_IR_SERIALIZE_H_INCLUDED
+#include "slang-ir-serialize-types.h"
+
#include "../core/slang-object-scope-manager.h"
#include "../core/slang-riff.h"
#include "slang-ir.h"
+#include "slang-ir-serialize-types.h"
+
// For TranslationUnitRequest
+// and FrontEndCompileRequest::ExtraEntryPointInfo
#include "slang-compiler.h"
namespace Slang {
-class StringRepresentationCache
-{
- public:
- typedef StringSlicePool::Handle Handle;
-
- struct Entry
- {
- uint32_t m_startIndex;
- uint32_t m_numChars;
- RefObject* m_object; ///< Could be nullptr, Name, or StringRepresentation.
- };
-
- /// Get as a name
- Name* getName(Handle handle);
- /// Get as a string
- String getString(Handle handle);
- /// Get as string representation
- StringRepresentation* getStringRepresentation(Handle handle);
- /// Get as a string slice
- UnownedStringSlice getStringSlice(Handle handle) const;
- /// Get as a 0 terminated 'c style' string
- char* getCStr(Handle handle);
-
- /// Initialize a cache to use a string table, namePool and scopeManager
- void init(const List<char>* stringTable, NamePool* namePool, ObjectScopeManager* scopeManager);
-
- /// Ctor
- StringRepresentationCache();
-
- protected:
- ObjectScopeManager* m_scopeManager;
- NamePool* m_namePool;
- const List<char>* m_stringTable;
- List<Entry> m_entries;
-};
-
-struct SerialStringTableUtil
-{
- /// Convert a pool into a string table
- static void encodeStringTable(const StringSlicePool& pool, List<char>& stringTable);
- static void encodeStringTable(const UnownedStringSlice* slices, size_t numSlices, List<char>& stringTable);
- /// Appends the decoded strings into slicesOut
- static void appendDecodedStringTable(const List<char>& stringTable, List<UnownedStringSlice>& slicesOut);
- /// Decodes a string table (and does so such that the indices are compatible with StringSlicePool)
- static void decodeStringTable(const List<char>& stringTable, List<UnownedStringSlice>& slicesOut);
-
- /// Produces an index map, from slices to indices in pool
- static void calcStringSlicePoolMap(const List<UnownedStringSlice>& slices, StringSlicePool& pool, List<StringSlicePool::Handle>& indexMap);
-};
-
-// Pre-declare
-class Name;
-
-struct IRSerialData
-{
- typedef IRSerialData ThisType;
-
- enum class InstIndex : uint32_t;
- enum class StringIndex : uint32_t;
- enum class ArrayIndex : uint32_t;
-
- enum class RawSourceLoc : SourceLoc::RawValue; ///< This is just to copy over source loc data (ie not strictly serialize)
- enum class StringOffset : uint32_t; ///< Offset into the m_stringsBuffer
-
- typedef uint32_t SizeType;
-
- static const StringIndex kNullStringIndex = StringIndex(StringSlicePool::kNullHandle);
- static const StringIndex kEmptyStringIndex = StringIndex(StringSlicePool::kEmptyHandle);
-
- /// A run of instructions
- struct InstRun
- {
- typedef InstRun ThisType;
- SLANG_FORCE_INLINE bool operator==(const ThisType& rhs) const
- {
- return m_parentIndex == rhs.m_parentIndex &&
- m_startInstIndex == rhs.m_startInstIndex &&
- m_numChildren == rhs.m_numChildren;
- }
- SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
-
- InstIndex m_parentIndex; ///< The parent instruction
- InstIndex m_startInstIndex; ///< The index to the first instruction
- SizeType m_numChildren; ///< The number of children
- };
-
- struct SourceLocRun
- {
- typedef SourceLocRun ThisType;
-
- bool operator==(const ThisType& rhs) const { return m_sourceLoc == rhs.m_sourceLoc && m_startInstIndex == rhs.m_startInstIndex && m_numInst == rhs.m_numInst; }
- bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
- bool operator<(const ThisType& rhs) const { return m_sourceLoc < rhs.m_sourceLoc; }
-
- uint32_t m_sourceLoc; ///< The source location
- InstIndex m_startInstIndex; ///< The index to the first instruction
- SizeType m_numInst; ///< The number of children
- };
-
- struct PayloadInfo
- {
- uint8_t m_numOperands;
- uint8_t m_numStrings;
- };
-
- struct DebugSourceInfo
- {
- typedef DebugSourceInfo ThisType;
-
- bool operator==(const ThisType& rhs) const
- {
- return m_pathIndex == rhs.m_pathIndex &&
- m_startSourceLoc == rhs.m_startSourceLoc &&
- m_endSourceLoc == rhs.m_endSourceLoc &&
- m_numLineInfos == rhs.m_numLineInfos &&
- m_lineInfosStartIndex == rhs.m_lineInfosStartIndex &&
- m_numLineInfos == rhs.m_numLineInfos;
- }
- bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
-
- bool isSourceLocInRange(uint32_t sourceLoc) const { return sourceLoc >= m_startSourceLoc && sourceLoc <= m_endSourceLoc; }
-
- StringIndex m_pathIndex; ///< Index to the string table
- uint32_t m_startSourceLoc; ///< The offset to the source
- uint32_t m_endSourceLoc; ///< The number of bytes in the source
-
- uint32_t m_numLines; ///< Total number of lines in source file
-
- uint32_t m_lineInfosStartIndex; ///< Index into m_debugLineInfos
- uint32_t m_numLineInfos; ///< The number of line infos
-
- uint32_t m_adjustedLineInfosStartIndex; ///< Adjusted start index
- uint32_t m_numAdjustedLineInfos; ///< The number of line infos
- };
-
- struct DebugLineInfo
- {
- typedef DebugLineInfo ThisType;
- bool operator<(const ThisType& rhs) const { return m_lineStartOffset < rhs.m_lineStartOffset; }
- bool operator==(const ThisType& rhs) const
- {
- return m_lineStartOffset == rhs.m_lineStartOffset &&
- m_lineIndex == rhs.m_lineIndex;
- }
- bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
-
- uint32_t m_lineStartOffset; ///< The offset into the source file
- uint32_t m_lineIndex; ///< Original line index
- };
-
- struct DebugAdjustedLineInfo
- {
- typedef DebugAdjustedLineInfo ThisType;
- bool operator==(const ThisType& rhs) const
- {
- return m_lineInfo == rhs.m_lineInfo &&
- m_adjustedLineIndex == rhs.m_adjustedLineIndex &&
- m_pathStringIndex == rhs.m_pathStringIndex;
- }
- bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
- bool operator<(const ThisType& rhs) const { return m_lineInfo < rhs.m_lineInfo; }
-
- DebugLineInfo m_lineInfo;
- uint32_t m_adjustedLineIndex; ///< The line index with the adjustment (if there is any). Is 0 if m_pathStringIndex is 0.
- StringIndex m_pathStringIndex; ///< The path as an index
- };
-
- // Instruction...
- // We can store SourceLoc values separately. Just store per index information.
- // Parent information is stored in m_childRuns
- // Decoration information is stored in m_decorationRuns
- struct Inst
- {
- typedef Inst ThisType;
- enum
- {
- kMaxOperands = 2, ///< Maximum number of operands that can be held in an instruction (otherwise held 'externally')
- };
-
- // NOTE! Can't change order or list without changing appropriate s_payloadInfos
- enum class PayloadType : uint8_t
- {
- // First 3 must be in this order so a cast from 0-2 is directly represented as number of operands
- Empty, ///< Has no payload (or operands)
- Operand_1, ///< 1 Operand
- Operand_2, ///< 2 Operands
-
- OperandAndUInt32, ///< 1 Operand and a single UInt32
- OperandExternal, ///< Operands are held externally
- String_1, ///< 1 String
- String_2, ///< 2 Strings
- UInt32, ///< Holds an unsigned 32 bit integral (might represent a type)
- Float64,
- Int64,
-
- CountOf,
- };
-
- /// Get the number of operands
- SLANG_FORCE_INLINE int getNumOperands() const;
-
- bool operator==(const ThisType& rhs) const;
-
- SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
-
- uint8_t m_op; ///< For now one of IROp
- PayloadType m_payloadType; ///< The type of payload
- uint16_t m_pad0; ///< Not currently used
-
- InstIndex m_resultTypeIndex; //< 0 if has no type. The result type of this instruction
-
- struct ExternalOperandPayload
- {
- ArrayIndex m_arrayIndex; ///< Index into the m_externalOperands table
- SizeType m_size; ///< The amount of entries in that table
- };
-
- struct OperandAndUInt32
- {
- InstIndex m_operand;
- uint32_t m_uint32;
- };
-
- union Payload
- {
- double m_float64;
- int64_t m_int64;
- uint32_t m_uint32; ///< Unsigned integral value
- IRFloatingPointValue m_float; ///< Floating point value
- IRIntegerValue m_int; ///< Integral value
- InstIndex m_operands[kMaxOperands]; ///< For items that 2 or less operands it can use this.
- StringIndex m_stringIndices[kMaxOperands];
- ExternalOperandPayload m_externalOperand; ///< Operands are stored in an an index of an operand array
- OperandAndUInt32 m_operandAndUInt32;
- };
-
- Payload m_payload;
- };
-
- /// Clear to initial state
- void clear();
- /// Get the operands of an instruction
- SLANG_FORCE_INLINE int getOperands(const Inst& inst, const InstIndex** operandsOut) const;
-
- /// ==
- bool operator==(const ThisType& rhs) const;
- SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
-
- /// Calculate the amount of memory used by this IRSerialData
- size_t calcSizeInBytes() const;
-
- /// Ctor
- IRSerialData();
-
- List<Inst> m_insts; ///< The instructions
-
- List<InstRun> m_childRuns; ///< Holds the information about children that belong to an instruction
-
- List<InstIndex> m_externalOperands; ///< Holds external operands (for instructions with more than kNumOperands)
-
- List<char> m_stringTable; ///< All strings. Indexed into by StringIndex
-
- List<RawSourceLoc> m_rawSourceLocs; ///< A source location per instruction (saved without modification from IRInst)s
-
- // Data only set if we have debug information
-
- List<char> m_debugStringTable; ///< String table for debug use only
- List<DebugLineInfo> m_debugLineInfos; ///< Debug line information
- List<DebugAdjustedLineInfo> m_debugAdjustedLineInfos; ///< Adjusted line infos
- List<DebugSourceInfo> m_debugSourceInfos; ///< Debug source information
- List<SourceLocRun> m_debugSourceLocRuns; ///< Runs of instructions that use a source loc
-
- static const PayloadInfo s_payloadInfos[int(Inst::PayloadType::CountOf)];
-};
-
-// --------------------------------------------------------------------------
-SLANG_FORCE_INLINE int IRSerialData::Inst::getNumOperands() const
-{
- return (m_payloadType == PayloadType::OperandExternal) ? m_payload.m_externalOperand.m_size : s_payloadInfos[int(m_payloadType)].m_numOperands;
-}
-
-// --------------------------------------------------------------------------
-SLANG_FORCE_INLINE bool IRSerialData::Inst::operator==(const ThisType& rhs) const
-{
- if (m_op == rhs.m_op &&
- m_payloadType == rhs.m_payloadType &&
- m_resultTypeIndex == rhs.m_resultTypeIndex)
- {
- switch (m_payloadType)
- {
- case PayloadType::Empty:
- {
- return true;
- }
- case PayloadType::Operand_1:
- case PayloadType::String_1:
- case PayloadType::UInt32:
- {
- return m_payload.m_operands[0] == rhs.m_payload.m_operands[0];
- }
- case PayloadType::OperandAndUInt32:
- case PayloadType::OperandExternal:
- case PayloadType::Operand_2:
- case PayloadType::String_2:
- {
- return m_payload.m_operands[0] == rhs.m_payload.m_operands[0] &&
- m_payload.m_operands[1] == rhs.m_payload.m_operands[1];
- }
- case PayloadType::Float64:
- case PayloadType::Int64:
- {
- return m_payload.m_int64 == rhs.m_payload.m_int64;
- }
- default: break;
- }
- }
-
- return false;
-}
-// --------------------------------------------------------------------------
-SLANG_FORCE_INLINE int IRSerialData::getOperands(const Inst& inst, const InstIndex** operandsOut) const
-{
- if (inst.m_payloadType == Inst::PayloadType::OperandExternal)
- {
- *operandsOut = m_externalOperands.begin() + int(inst.m_payload.m_externalOperand.m_arrayIndex);
- return int(inst.m_payload.m_externalOperand.m_size);
- }
- else
- {
- *operandsOut = inst.m_payload.m_operands;
- return s_payloadInfos[int(inst.m_payloadType)].m_numOperands;
- }
-}
-
-
-#define SLANG_MAKE_COMPRESSED_FOUR_CC(fourCc) (((fourCc) & 0xffff00ff) | (uint32_t('c') << 8))
-
-struct IRSerialBinary
-{
- enum class CompressionType
- {
- None,
- VariableByteLite,
- };
-
- static const FourCC kRiffFourCc = RiffFourCC::kRiff;
-
- static const FourCC kSlangModuleListFourCc = SLANG_FOUR_CC('S', 'L', 'm', 'l');
-
- static const FourCC kSlangModuleFourCc = SLANG_FOUR_CC('S', 'L', 'm', 'd'); ///< Holds all the slang specific chunks
-
- static const FourCC kSlangModuleHeaderFourCc = SLANG_FOUR_CC('S', 'L', 'h', 'd');
-
- static const FourCC kInstFourCc = SLANG_FOUR_CC('S', 'L', 'i', 'n');
- static const FourCC kChildRunFourCc = SLANG_FOUR_CC('S', 'L', 'c', 'r');
- static const FourCC kExternalOperandsFourCc = SLANG_FOUR_CC('S', 'L', 'e', 'o');
-
- static const FourCC kCompressedInstFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kInstFourCc);
- static const FourCC kCompressedChildRunFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kChildRunFourCc);
- static const FourCC kCompressedExternalOperandsFourCc = SLANG_MAKE_COMPRESSED_FOUR_CC(kExternalOperandsFourCc);
-
- static const FourCC kStringFourCc = SLANG_FOUR_CC('S', 'L', 's', 't');
-
- static const FourCC kUInt32SourceLocFourCc = SLANG_FOUR_CC('S', 'r', 's', '4');
-
- static const FourCC kDebugStringFourCc = SLANG_FOUR_CC('S', 'd', 's', 't');
- static const FourCC kDebugLineInfoFourCc = SLANG_FOUR_CC('S', 'd', 'l', 'n');
- static const FourCC kDebugAdjustedLineInfoFourCc = SLANG_FOUR_CC('S', 'd', 'a', 'l');
- static const FourCC kDebugSourceInfoFourCc = SLANG_FOUR_CC('S', 'd', 's', 'o');
- static const FourCC kDebugSourceLocRunFourCc = SLANG_FOUR_CC('S', 'd', 's', 'r');
-
- static const FourCC kEntryPointFourCc = SLANG_FOUR_CC('E', 'P', 'n', 't');
-
- struct ModuleHeader
- {
- uint32_t compressionType; ///< Holds the compression type used (if used at all)
- };
- struct ArrayHeader
- {
- uint32_t numEntries;
- };
- struct CompressedArrayHeader
- {
- uint32_t numEntries; ///< The number of entries
- uint32_t numCompressedEntries; ///< The amount of compressed entries
- };
-};
-
-
struct IRSerialWriter
{
typedef IRSerialData Ser;
@@ -419,10 +35,10 @@ struct IRSerialWriter
Result write(IRModule* module, SourceManager* sourceManager, OptionFlags options, IRSerialData* serialData);
- static Result writeStream(const IRSerialData& data, Bin::CompressionType compressionType, Stream* stream);
+ static Result writeStream(const IRSerialData& data, IRSerialCompressionType compressionType, Stream* stream);
/// Write to a container
- static Result writeContainer(const IRSerialData& data, Bin::CompressionType compressionType, RiffContainer* container);
+ static Result writeContainer(const IRSerialData& data, IRSerialCompressionType compressionType, RiffContainer* container);
/// Get an instruction index from an instruction
Ser::InstIndex getInstIndex(IRInst* inst) const { return inst ? Ser::InstIndex(m_instMap[inst]) : Ser::InstIndex(0); }
@@ -514,8 +130,6 @@ struct IRSerialReader
/// Read a module from serial data
Result read(const IRSerialData& data, Session* session, SourceManager* sourceManager, RefPtr<IRModule>& moduleOut);
-
-
/// Get the representation cache
StringRepresentationCache& getStringRepresentationCache() { return m_stringRepresentationCache; }
@@ -539,7 +153,7 @@ struct IRSerialUtil
static void calcInstructionList(IRModule* module, List<IRInst*>& instsOut);
/// Verify serialization
- static SlangResult verifySerialize(IRModule* module, Session* session, SourceManager* sourceManager, IRSerialBinary::CompressionType compressionType, IRSerialWriter::OptionFlags optionFlags);
+ static SlangResult verifySerialize(IRModule* module, Session* session, SourceManager* sourceManager, IRSerialCompressionType compressionType, IRSerialWriter::OptionFlags optionFlags);
};
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index 0e55c6f3d..97dca94ca 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -627,6 +627,12 @@ struct OptionsParser
{
getCurrentTarget()->targetFlags |= SLANG_TARGET_FLAG_PARAMETER_BLOCKS_USE_REGISTER_SPACES;
}
+ else if (argStr == "-ir-compression")
+ {
+ String name;
+ SLANG_RETURN_ON_FAIL(tryReadCommandLineArgument(sink, arg, &argCursor, argEnd, name));
+ SLANG_RETURN_ON_FAIL(IRSerialTypeUtil::parseCompressionType(name.getUnownedSlice(), requestImpl->getLinkage()->irCompressionType));
+ }
else if (argStr == "-target")
{
String name;
diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj
index 142a90b12..fc1f3c421 100644
--- a/source/slang/slang.vcxproj
+++ b/source/slang/slang.vcxproj
@@ -221,6 +221,7 @@
<ClInclude Include="slang-ir-restructure-scoping.h" />
<ClInclude Include="slang-ir-restructure.h" />
<ClInclude Include="slang-ir-sccp.h" />
+ <ClInclude Include="slang-ir-serialize-types.h" />
<ClInclude Include="slang-ir-serialize.h" />
<ClInclude Include="slang-ir-specialize-resources.h" />
<ClInclude Include="slang-ir-specialize.h" />
@@ -298,6 +299,7 @@
<ClCompile Include="slang-ir-restructure-scoping.cpp" />
<ClCompile Include="slang-ir-restructure.cpp" />
<ClCompile Include="slang-ir-sccp.cpp" />
+ <ClCompile Include="slang-ir-serialize-types.cpp" />
<ClCompile Include="slang-ir-serialize.cpp" />
<ClCompile Include="slang-ir-specialize-resources.cpp" />
<ClCompile Include="slang-ir-specialize.cpp" />
@@ -335,7 +337,7 @@
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"../../bin/windows-x64/debug/slang-generate" %(Identity)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"../../bin/windows-x86/release/slang-generate" %(Identity)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"../../bin/windows-x64/release/slang-generate" %(Identity)</Command>
- <Outputs>../../core.meta.slang.h</Outputs>
+ <Outputs>%(Identity).h</Outputs>
<Message>slang-generate %(Identity)</Message>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../bin/windows-x86/debug/slang-generate.exe</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../bin/windows-x64/debug/slang-generate.exe</AdditionalInputs>
@@ -348,7 +350,7 @@
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"../../bin/windows-x64/debug/slang-generate" %(Identity)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"../../bin/windows-x86/release/slang-generate" %(Identity)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"../../bin/windows-x64/release/slang-generate" %(Identity)</Command>
- <Outputs>../../hlsl.meta.slang.h</Outputs>
+ <Outputs>%(Identity).h</Outputs>
<Message>slang-generate %(Identity)</Message>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../bin/windows-x86/debug/slang-generate.exe</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../bin/windows-x64/debug/slang-generate.exe</AdditionalInputs>
diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters
index 9153206b6..754fc8aa6 100644
--- a/source/slang/slang.vcxproj.filters
+++ b/source/slang/slang.vcxproj.filters
@@ -114,6 +114,9 @@
<ClInclude Include="slang-ir-sccp.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-ir-serialize-types.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="slang-ir-serialize.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -341,6 +344,9 @@
<ClCompile Include="slang-ir-sccp.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="slang-ir-serialize-types.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="slang-ir-serialize.cpp">
<Filter>Source Files</Filter>
</ClCompile>