diff options
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/slang-compiler.cpp | 4 | ||||
| -rw-r--r-- | source/slang/slang-compiler.h | 3 | ||||
| -rw-r--r-- | source/slang/slang-ir-serialize-types.cpp | 411 | ||||
| -rw-r--r-- | source/slang/slang-ir-serialize-types.h | 423 | ||||
| -rw-r--r-- | source/slang/slang-ir-serialize.cpp | 440 | ||||
| -rw-r--r-- | source/slang/slang-ir-serialize.h | 402 | ||||
| -rw-r--r-- | source/slang/slang-options.cpp | 6 | ||||
| -rw-r--r-- | source/slang/slang.vcxproj | 6 | ||||
| -rw-r--r-- | source/slang/slang.vcxproj.filters | 6 |
9 files changed, 900 insertions, 801 deletions
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> |
