diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2020-11-05 13:43:00 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-11-05 13:43:00 -0500 |
| commit | c985f5f2f95dc95998fdfb8400baa0a04760ada2 (patch) | |
| tree | f79ba0576dd4f85c284f3c300a42d79964413796 /source | |
| parent | 8d4c0ea875b186648ff75b4f04891ba8f1286aac (diff) | |
Standard library save/loadable (#1592)
* #include an absolute path didn't work - because paths were taken to always be relative.
* Fix handling of access modifiers inside type definition.
* Fix access problem for AST node.
Make dumping produce a single function with switch, to potentially make available without Dump specific access.
* WIP on serialization design doc.
* Remove project references to previously generated files.
* More docs on serialization design.
* Improve serialization documentation.
Remove unused function from IRSerialReader.
* Small fixes around naming. Remove long comment from slang-serialize.h - as covered in serialization.md
* Remove long comment in slang-serialize.h as covered in serialization.md
* More information about doing replacements on read for AST and problems surrounding.
* Typo fix.
* Spelling fixes.
* Value serialize.
* Value types with inheritence.
* Use value reflection serial conversion for more AST types
* Use automatic serialization on more of AST.
* Get the types via decltype, simplifies what the extractor has to do.
* Update the serialization.md for the value serialization.
* Small doc improvements.
* Update project.
* Remove ImportExternalDecl type
Added addImportSymbol and ImportSymbol type
Fixed bug in container which meant it wouldn't read back AST module
* Because of change of how imports and handled, store objects as SerialPointers.
* First pass symbol lookup from mangled names.
* Cache current module looked up from mangled name.
* Fix SourceLoc bug.
Improve comments.
* Added diagnostic on mangled symbol not being found
* Fix typo.
* WIP serializing stdlib.
* WIP serializing stdlib in.
* Fix problem serializing arrays that hold data that is already serialized.
* Remove clash of names in MagicTypeModifier.
* Make conversion from char to String explicit.
Fix reference count issue with SerialReader.
* Add code to save/load stdlib.
* Use return code to avoid warning - SerialContainerUtil::write(module, options, &stream))
* Make all String numeric ctors explicit.
Added isChar to UnownedStringSlice.
Added operator== for UnownedStringSlice to String to avoid need to convert to String and allocate.
* Add error check to readAllText.
* tabs -> spaces on String.h
* tab -> spaces String.cpp
* Remove msg for StringBuilder, just build inplace for exceptions.
* Check SerialClasses - for name clashes.
Renamed Modifier::name as Modifier::keywordName
* Handling of extensions when deserializing AST - updating the moduleDecl->mapTypeToCandidateExtensions
Co-authored-by: Tim Foley <tim.foley.is@gmail.com>
Diffstat (limited to 'source')
25 files changed, 1060 insertions, 681 deletions
diff --git a/source/core/slang-string.cpp b/source/core/slang-string.cpp index 3ce4c7ec9..975c83315 100644 --- a/source/core/slang-string.cpp +++ b/source/core/slang-string.cpp @@ -147,112 +147,112 @@ namespace Slang // - _EndLine EndLine; + _EndLine EndLine; String operator+(const char * op1, const String & op2) - { + { String result(op1); result.append(op2); return result; - } + } - String operator+(const String & op1, const char * op2) - { + String operator+(const String & op1, const char * op2) + { String result(op1); result.append(op2); return result; - } + } - String operator+(const String & op1, const String & op2) - { + String operator+(const String & op1, const String & op2) + { String result(op1); result.append(op2); return result; - } - - int StringToInt(const String & str, int radix) - { - if (str.startsWith("0x")) - return (int)strtoll(str.getBuffer(), NULL, 16); - else - return (int)strtoll(str.getBuffer(), NULL, radix); - } - unsigned int StringToUInt(const String & str, int radix) - { - if (str.startsWith("0x")) - return (unsigned int)strtoull(str.getBuffer(), NULL, 16); - else - return (unsigned int)strtoull(str.getBuffer(), NULL, radix); - } - double StringToDouble(const String & str) - { - return (double)strtod(str.getBuffer(), NULL); - } - float StringToFloat(const String & str) - { - return strtof(str.getBuffer(), NULL); - } + } + + int StringToInt(const String & str, int radix) + { + if (str.startsWith("0x")) + return (int)strtoll(str.getBuffer(), NULL, 16); + else + return (int)strtoll(str.getBuffer(), NULL, radix); + } + unsigned int StringToUInt(const String & str, int radix) + { + if (str.startsWith("0x")) + return (unsigned int)strtoull(str.getBuffer(), NULL, 16); + else + return (unsigned int)strtoull(str.getBuffer(), NULL, radix); + } + double StringToDouble(const String & str) + { + return (double)strtod(str.getBuffer(), NULL); + } + float StringToFloat(const String & str) + { + return strtof(str.getBuffer(), NULL); + } #if 0 - String String::ReplaceAll(String src, String dst) const - { - String rs = *this; - int index = 0; - int srcLen = src.length; - int len = rs.length; - while ((index = rs.IndexOf(src, index)) != -1) - { - rs = rs.SubString(0, index) + dst + rs.SubString(index + srcLen, len - index - srcLen); - len = rs.length; - } - return rs; - } + String String::ReplaceAll(String src, String dst) const + { + String rs = *this; + int index = 0; + int srcLen = src.length; + int len = rs.length; + while ((index = rs.IndexOf(src, index)) != -1) + { + rs = rs.SubString(0, index) + dst + rs.SubString(index + srcLen, len - index - srcLen); + len = rs.length; + } + return rs; + } #endif - String String::fromWString(const wchar_t * wstr) - { + String String::fromWString(const wchar_t * wstr) + { #ifdef _WIN32 - return Slang::Encoding::UTF16->ToString((const char*)wstr, (int)(wcslen(wstr) * sizeof(wchar_t))); + return Slang::Encoding::UTF16->ToString((const char*)wstr, (int)(wcslen(wstr) * sizeof(wchar_t))); #else - return Slang::Encoding::UTF32->ToString((const char*)wstr, (int)(wcslen(wstr) * sizeof(wchar_t))); + return Slang::Encoding::UTF32->ToString((const char*)wstr, (int)(wcslen(wstr) * sizeof(wchar_t))); #endif - } + } - String String::fromWString(const wchar_t * wstr, const wchar_t * wend) - { + String String::fromWString(const wchar_t * wstr, const wchar_t * wend) + { #ifdef _WIN32 - return Slang::Encoding::UTF16->ToString((const char*)wstr, (int)((wend - wstr) * sizeof(wchar_t))); + return Slang::Encoding::UTF16->ToString((const char*)wstr, (int)((wend - wstr) * sizeof(wchar_t))); #else - return Slang::Encoding::UTF32->ToString((const char*)wstr, (int)((wend - wstr) * sizeof(wchar_t))); + return Slang::Encoding::UTF32->ToString((const char*)wstr, (int)((wend - wstr) * sizeof(wchar_t))); #endif - } + } - String String::fromWChar(const wchar_t ch) - { + String String::fromWChar(const wchar_t ch) + { #ifdef _WIN32 - return Slang::Encoding::UTF16->ToString((const char*)&ch, (int)(sizeof(wchar_t))); + return Slang::Encoding::UTF16->ToString((const char*)&ch, (int)(sizeof(wchar_t))); #else - return Slang::Encoding::UTF32->ToString((const char*)&ch, (int)(sizeof(wchar_t))); + return Slang::Encoding::UTF32->ToString((const char*)&ch, (int)(sizeof(wchar_t))); #endif - } - - String String::fromUnicodePoint(unsigned int codePoint) - { - char buf[6]; - int len = Slang::EncodeUnicodePointToUTF8(buf, (int)codePoint); - buf[len] = 0; - return String(buf); - } - - OSString String::toWString(Index* outLength) const - { - if (!m_buffer) - { + } + + String String::fromUnicodePoint(unsigned int codePoint) + { + char buf[6]; + int len = Slang::EncodeUnicodePointToUTF8(buf, (int)codePoint); + buf[len] = 0; + return String(buf); + } + + OSString String::toWString(Index* outLength) const + { + if (!m_buffer) + { return OSString(); - } - else - { - List<char> buf; + } + else + { + List<char> buf; switch(sizeof(wchar_t)) { case 2: @@ -268,20 +268,20 @@ namespace Slang } auto length = Index(buf.getCount() / sizeof(wchar_t)); - if (outLength) - *outLength = length; + if (outLength) + *outLength = length; for(int ii = 0; ii < sizeof(wchar_t); ++ii) - buf.add(0); + buf.add(0); wchar_t* beginData = (wchar_t*)buf.getBuffer(); wchar_t* endData = beginData + length; - buf.detachBuffer(); + buf.detachBuffer(); return OSString(beginData, endData); - } - } + } + } // diff --git a/source/core/slang-string.h b/source/core/slang-string.h index 75c282a58..9f6eaafa7 100644 --- a/source/core/slang-string.h +++ b/source/core/slang-string.h @@ -14,53 +14,53 @@ namespace Slang { - class _EndLine - {}; - extern _EndLine EndLine; - - // in-place reversion, works only for ascii string - inline void ReverseInternalAscii(char * buffer, int length) - { - int i, j; - char c; - for (i = 0, j = length - 1; i<j; i++, j--) - { - c = buffer[i]; - buffer[i] = buffer[j]; - buffer[j] = c; - } - } - template<typename IntType> - inline int IntToAscii(char * buffer, IntType val, int radix) - { - int i = 0; - IntType sign; - sign = val; - if (sign < 0) - val = (IntType)(0 - val); - do - { - int digit = (val % radix); - if (digit <= 9) - buffer[i++] = (char)(digit + '0'); - else - buffer[i++] = (char)(digit - 10 + 'A'); - } while ((val /= radix) > 0); - if (sign < 0) - buffer[i++] = '-'; - buffer[i] = '\0'; - return i; - } - - inline bool IsUtf8LeadingByte(char ch) - { - return (((unsigned char)ch) & 0xC0) == 0xC0; - } - - inline bool IsUtf8ContinuationByte(char ch) - { - return (((unsigned char)ch) & 0xC0) == 0x80; - } + class _EndLine + {}; + extern _EndLine EndLine; + + // in-place reversion, works only for ascii string + inline void ReverseInternalAscii(char * buffer, int length) + { + int i, j; + char c; + for (i = 0, j = length - 1; i<j; i++, j--) + { + c = buffer[i]; + buffer[i] = buffer[j]; + buffer[j] = c; + } + } + template<typename IntType> + inline int IntToAscii(char * buffer, IntType val, int radix) + { + int i = 0; + IntType sign; + sign = val; + if (sign < 0) + val = (IntType)(0 - val); + do + { + int digit = (val % radix); + if (digit <= 9) + buffer[i++] = (char)(digit + '0'); + else + buffer[i++] = (char)(digit - 10 + 'A'); + } while ((val /= radix) > 0); + if (sign < 0) + buffer[i++] = '-'; + buffer[i] = '\0'; + return i; + } + + inline bool IsUtf8LeadingByte(char ch) + { + return (((unsigned char)ch) & 0xC0) == 0xC0; + } + + inline bool IsUtf8ContinuationByte(char ch) + { + return (((unsigned char)ch) & 0xC0) == 0x80; + } struct UnownedStringSlice { @@ -166,14 +166,18 @@ namespace Slang return (*this) != UnownedStringSlice(str, str + ::strlen(str)); } + /// True if contents is a single char of c + SLANG_FORCE_INLINE bool isChar(char c) const { return getLength() == 1 && m_begin[0] == c; } + bool startsWith(UnownedStringSlice const& other) const; bool startsWith(char const* str) const; bool endsWith(UnownedStringSlice const& other) const; bool endsWith(char const* str) const; - + /// Trims any horizontal whitespace from the start and end and returns as a substring UnownedStringSlice trim() const; + /// Trims any 'c' from the start or the end, and returns as a substring UnownedStringSlice trim(char c) const; HashCode getHashCode() const @@ -383,15 +387,15 @@ namespace Slang wchar_t* m_end; ///< Points to terminating 0 }; - /*! - @brief Represents a UTF-8 encoded string. - */ + /*! + @brief Represents a UTF-8 encoded string. + */ - class String - { + class String + { friend struct StringSlice; - friend class StringBuilder; - private: + friend class StringBuilder; + private: char* getData() const @@ -410,13 +414,13 @@ namespace Slang : m_buffer(buffer) {} - static String fromWString(const wchar_t * wstr); - static String fromWString(const wchar_t * wstr, const wchar_t * wend); - static String fromWChar(const wchar_t ch); - static String fromUnicodePoint(unsigned int codePoint); - String() - { - } + static String fromWString(const wchar_t * wstr); + static String fromWString(const wchar_t * wstr, const wchar_t * wend); + static String fromWChar(const wchar_t ch); + static String fromUnicodePoint(unsigned int codePoint); + String() + { + } /// Returns a buffer which can hold at least count chars char* prepareForAppend(Index count); @@ -425,14 +429,14 @@ namespace Slang SLANG_FORCE_INLINE StringRepresentation* getStringRepresentation() const { return m_buffer; } - const char * begin() const - { - return getData(); - } - const char * end() const - { - return getData() + getLength(); - } + const char * begin() const + { + return getData(); + } + const char * end() const + { + return getData() + getLength(); + } void append(int32_t value, int radix = 10); void append(uint32_t value, int radix = 10); @@ -451,76 +455,79 @@ namespace Slang /// Append a character (to remove ambiguity with other integral types) void appendChar(char chr); - String(int32_t val, int radix = 10) - { - append(val, radix); - } - String(uint32_t val, int radix = 10) - { - append(val, radix); - } - String(int64_t val, int radix = 10) - { - append(val, radix); - } - String(uint64_t val, int radix = 10) - { - append(val, radix); - } - String(float val, const char * format = "%g") - { - append(val, format); - } - String(double val, const char * format = "%g") - { - append(val, format); - } - String(const char * str) - { + String(const char* str) + { append(str); #if 0 - if (str) - { + if (str) + { buffer = StringRepresentation::createWithLength(strlen(str)); - memcpy(buffer.Ptr(), str, getLength() + 1); - } + memcpy(buffer.Ptr(), str, getLength() + 1); + } #endif - } + } String(const char* textBegin, char const* textEnd) - { + { append(textBegin, textEnd); #if 0 - if (textBegin != textEnd) - { + if (textBegin != textEnd) + { buffer = StringRepresentation::createWithLength(textEnd - textBegin); - memcpy(buffer.Ptr(), textBegin, getLength()); + memcpy(buffer.Ptr(), textBegin, getLength()); buffer->getData()[getLength()] = 0; - } + } #endif - } - String(char chr) - { + } + + // Make all String ctors from a numeric explicit, to avoid unexpected/unnecessary conversions + explicit String(int32_t val, int radix = 10) + { + append(val, radix); + } + explicit String(uint32_t val, int radix = 10) + { + append(val, radix); + } + explicit String(int64_t val, int radix = 10) + { + append(val, radix); + } + explicit String(uint64_t val, int radix = 10) + { + append(val, radix); + } + explicit String(float val, const char * format = "%g") + { + append(val, format); + } + explicit String(double val, const char * format = "%g") + { + append(val, format); + } + + explicit String(char chr) + { append(chr); #if 0 - if (chr) - { + if (chr) + { buffer = StringRepresentation::createWithLength(1); buffer->getData()[0] = chr; buffer->getData()[1] = 0; - } + } #endif - } - String(String const& str) - { + } + String(String const& str) + { m_buffer = str.m_buffer; #if 0 - this->operator=(str); + this->operator=(str); #endif - } - String(String&& other) - { + } + String(String&& other) + { m_buffer = _Move(other.m_buffer); - } + } String(StringSlice const& slice) { @@ -532,152 +539,155 @@ namespace Slang append(slice); } - ~String() - { + ~String() + { m_buffer.setNull(); - } + } - String & operator=(const String & str) - { + String & operator=(const String & str) + { m_buffer = str.m_buffer; - return *this; - } - String & operator=(String&& other) - { + return *this; + } + String & operator=(String&& other) + { m_buffer = _Move(other.m_buffer); return *this; - } - char operator[](Index id) const - { + } + char operator[](Index id) const + { SLANG_ASSERT(id >= 0 && id < getLength()); - return begin()[id]; - } + return begin()[id]; + } Index getLength() const { return m_buffer ? m_buffer->getLength() : 0; } - friend String operator+(const char*op1, const String & op2); - friend String operator+(const String & op1, const char * op2); - friend String operator+(const String & op1, const String & op2); + friend String operator+(const char*op1, const String & op2); + friend String operator+(const String & op1, const char * op2); + friend String operator+(const String & op1, const String & op2); - StringSlice trimStart() const - { - if (!m_buffer) - return StringSlice(); - Index startIndex = 0; + StringSlice trimStart() const + { + if (!m_buffer) + return StringSlice(); + Index startIndex = 0; const char*const data = getData(); - while (startIndex < getLength() && - (data[startIndex] == ' ' || data[startIndex] == '\t' || data[startIndex] == '\r' || data[startIndex] == '\n')) - startIndex++; + while (startIndex < getLength() && + (data[startIndex] == ' ' || data[startIndex] == '\t' || data[startIndex] == '\r' || data[startIndex] == '\n')) + startIndex++; return StringSlice(m_buffer, startIndex, getLength()); - } + } - StringSlice trimEnd() const - { - if (!m_buffer) - return StringSlice(); + StringSlice trimEnd() const + { + if (!m_buffer) + return StringSlice(); - Index endIndex = getLength(); + Index endIndex = getLength(); const char*const data = getData(); - while (endIndex > 0 && - (data[endIndex-1] == ' ' || data[endIndex-1] == '\t' || data[endIndex-1] == '\r' || data[endIndex-1] == '\n')) - endIndex--; + while (endIndex > 0 && + (data[endIndex-1] == ' ' || data[endIndex-1] == '\t' || data[endIndex-1] == '\r' || data[endIndex-1] == '\n')) + endIndex--; return StringSlice(m_buffer, 0, endIndex); - } + } - StringSlice trim() const - { - if (!m_buffer) - return StringSlice(); + StringSlice trim() const + { + if (!m_buffer) + return StringSlice(); - Index startIndex = 0; + Index startIndex = 0; const char*const data = getData(); - while (startIndex < getLength() && - (data[startIndex] == ' ' || data[startIndex] == '\t')) - startIndex++; + while (startIndex < getLength() && + (data[startIndex] == ' ' || data[startIndex] == '\t')) + startIndex++; Index endIndex = getLength(); - while (endIndex > startIndex && - (data[endIndex-1] == ' ' || data[endIndex-1] == '\t')) - endIndex--; + while (endIndex > startIndex && + (data[endIndex-1] == ' ' || data[endIndex-1] == '\t')) + endIndex--; return StringSlice(m_buffer, startIndex, endIndex); - } + } - StringSlice subString(Index id, Index len) const - { - if (len == 0) - return StringSlice(); + StringSlice subString(Index id, Index len) const + { + if (len == 0) + return StringSlice(); if (id + len > getLength()) - len = getLength() - id; + len = getLength() - id; #if _DEBUG - if (id < 0 || id >= getLength() || (id + len) > getLength()) - throw "SubString: index out of range."; - if (len < 0) - throw "SubString: length less than zero."; + if (id < 0 || id >= getLength() || (id + len) > getLength()) + throw "SubString: index out of range."; + if (len < 0) + throw "SubString: length less than zero."; #endif return StringSlice(m_buffer, id, id + len); - } + } - char const* getBuffer() const - { + char const* getBuffer() const + { return getData(); - } + } OSString toWString(Index* len = 0) const; - bool equals(const String & str, bool caseSensitive = true) - { - if (caseSensitive) - return (strcmp(begin(), str.begin()) == 0); - else - { + bool equals(const String & str, bool caseSensitive = true) + { + if (caseSensitive) + return (strcmp(begin(), str.begin()) == 0); + else + { #ifdef _MSC_VER - return (_stricmp(begin(), str.begin()) == 0); + return (_stricmp(begin(), str.begin()) == 0); #else - return (strcasecmp(begin(), str.begin()) == 0); + return (strcasecmp(begin(), str.begin()) == 0); #endif - } - } - bool operator==(const char * strbuffer) const - { - return (strcmp(begin(), strbuffer) == 0); - } - - bool operator==(const String & str) const - { - return (strcmp(begin(), str.begin()) == 0); - } - bool operator!=(const char * strbuffer) const - { - return (strcmp(begin(), strbuffer) != 0); - } - bool operator!=(const String & str) const - { - return (strcmp(begin(), str.begin()) != 0); - } - bool operator>(const String & str) const - { - return (strcmp(begin(), str.begin()) > 0); - } - bool operator<(const String & str) const - { - return (strcmp(begin(), str.begin()) < 0); - } - bool operator>=(const String & str) const - { - return (strcmp(begin(), str.begin()) >= 0); - } - bool operator<=(const String & str) const - { - return (strcmp(begin(), str.begin()) <= 0); - } - - String toUpper() const - { + } + } + bool operator==(const char * strbuffer) const + { + return (strcmp(begin(), strbuffer) == 0); + } + + bool operator==(const String & str) const + { + return (strcmp(begin(), str.begin()) == 0); + } + bool operator!=(const char * strbuffer) const + { + return (strcmp(begin(), strbuffer) != 0); + } + bool operator!=(const String & str) const + { + return (strcmp(begin(), str.begin()) != 0); + } + bool operator>(const String & str) const + { + return (strcmp(begin(), str.begin()) > 0); + } + bool operator<(const String & str) const + { + return (strcmp(begin(), str.begin()) < 0); + } + bool operator>=(const String & str) const + { + return (strcmp(begin(), str.begin()) >= 0); + } + bool operator<=(const String & str) const + { + return (strcmp(begin(), str.begin()) <= 0); + } + + SLANG_FORCE_INLINE bool operator==(const UnownedStringSlice& slice) const { return getUnownedSlice() == slice; } + SLANG_FORCE_INLINE bool operator!=(const UnownedStringSlice& slice) const { return getUnownedSlice() != slice; } + + String toUpper() const + { String result; for (auto c : *this) { @@ -685,10 +695,10 @@ namespace Slang result.append(d); } return result; - } + } - String toLower() const - { + String toLower() const + { String result; for (auto c : *this) { @@ -696,321 +706,321 @@ namespace Slang result.append(d); } return result; - } + } Index indexOf(const char * str, Index id) const // String str - { - if (id >= getLength()) - return Index(-1); - auto findRs = strstr(begin() + id, str); - Index res = findRs ? findRs - begin() : Index(-1); - return res; - } + { + if (id >= getLength()) + return Index(-1); + auto findRs = strstr(begin() + id, str); + Index res = findRs ? findRs - begin() : Index(-1); + return res; + } Index indexOf(const String & str, Index id) const - { - return indexOf(str.begin(), id); - } + { + return indexOf(str.begin(), id); + } Index indexOf(const char * str) const - { - return indexOf(str, 0); - } + { + return indexOf(str, 0); + } Index indexOf(const String & str) const - { - return indexOf(str.begin(), 0); - } + { + return indexOf(str.begin(), 0); + } Index indexOf(char ch, Index id) const - { + { const Index length = getLength(); SLANG_ASSERT(id >= 0 && id <= length); - if (!m_buffer) - return Index(-1); + if (!m_buffer) + return Index(-1); const char* data = getData(); - for (Index i = id; i < length; i++) - if (data[i] == ch) - return i; - return Index(-1); - } + for (Index i = id; i < length; i++) + if (data[i] == ch) + return i; + return Index(-1); + } Index indexOf(char ch) const - { - return indexOf(ch, 0); - } + { + return indexOf(ch, 0); + } Index lastIndexOf(char ch) const - { + { const Index length = getLength(); const char* data = getData(); // TODO(JS): If we know Index is signed we can do this a bit more simply for (Index i = length; i > 0; i--) - if (data[i - 1] == ch) - return i - 1; - return Index(-1); - } - - bool startsWith(const char * str) const // String str - { - if (!m_buffer) - return false; + if (data[i - 1] == ch) + return i - 1; + return Index(-1); + } + + bool startsWith(const char * str) const // String str + { + if (!m_buffer) + return false; Index strLen = Index(::strlen(str)); - if (strLen > getLength()) - return false; + if (strLen > getLength()) + return false; const char*const data = getData(); - for (Index i = 0; i < strLen; i++) - if (str[i] != data[i]) - return false; - return true; - } + for (Index i = 0; i < strLen; i++) + if (str[i] != data[i]) + return false; + return true; + } - bool startsWith(const String& str) const - { - return startsWith(str.begin()); - } + bool startsWith(const String& str) const + { + return startsWith(str.begin()); + } - bool endsWith(char const * str) const // String str - { - if (!m_buffer) - return false; + bool endsWith(char const * str) const // String str + { + if (!m_buffer) + return false; - const Index strLen = Index(::strlen(str)); + const Index strLen = Index(::strlen(str)); const Index len = getLength(); - if (strLen > len) - return false; + if (strLen > len) + return false; const char* data = getData(); - for (Index i = strLen; i > 0; i--) - if (str[i-1] != data[len - strLen + i-1]) - return false; - return true; - } - - bool endsWith(const String & str) const - { - return endsWith(str.begin()); - } - - bool contains(const char * str) const // String str - { - return m_buffer && indexOf(str) != Index(-1); - } - - bool contains(const String & str) const - { - return contains(str.begin()); - } - - HashCode getHashCode() const - { - return Slang::getHashCode(StringRepresentation::asSlice(m_buffer)); - } + for (Index i = strLen; i > 0; i--) + if (str[i-1] != data[len - strLen + i-1]) + return false; + return true; + } + + bool endsWith(const String & str) const + { + return endsWith(str.begin()); + } + + bool contains(const char * str) const // String str + { + return m_buffer && indexOf(str) != Index(-1); + } + + bool contains(const String & str) const + { + return contains(str.begin()); + } + + HashCode getHashCode() const + { + return Slang::getHashCode(StringRepresentation::asSlice(m_buffer)); + } UnownedStringSlice getUnownedSlice() const { return StringRepresentation::asSlice(m_buffer); } - }; + }; - class StringBuilder : public String - { - private: + class StringBuilder : public String + { + private: enum { InitialSize = 1024 }; - public: - explicit StringBuilder(UInt bufferSize = InitialSize) - { + public: + explicit StringBuilder(UInt bufferSize = InitialSize) + { ensureUniqueStorageWithCapacity(bufferSize); - } - void EnsureCapacity(UInt size) - { + } + void EnsureCapacity(UInt size) + { ensureUniqueStorageWithCapacity(size); - } - StringBuilder & operator << (char ch) - { - Append(&ch, 1); - return *this; - } - StringBuilder & operator << (Int32 val) - { - Append(val); - return *this; - } - StringBuilder & operator << (UInt32 val) - { - Append(val); - return *this; - } - StringBuilder & operator << (Int64 val) - { - Append(val); - return *this; - } - StringBuilder & operator << (UInt64 val) - { - Append(val); - return *this; - } - StringBuilder & operator << (float val) - { - Append(val); - return *this; - } - StringBuilder & operator << (double val) - { - Append(val); - return *this; - } - StringBuilder & operator << (const char * str) - { - Append(str, strlen(str)); - return *this; - } - StringBuilder & operator << (const String & str) - { - Append(str); - return *this; - } - StringBuilder & operator << (UnownedStringSlice const& str) - { - append(str); - return *this; - } - StringBuilder & operator << (const _EndLine) - { - Append('\n'); - return *this; - } - void Append(char ch) - { - Append(&ch, 1); - } - void Append(float val) - { - char buf[128]; - sprintf_s(buf, 128, "%g", val); - int len = (int)strnlen_s(buf, 128); - Append(buf, len); - } - void Append(double val) - { - char buf[128]; - sprintf_s(buf, 128, "%g", val); - int len = (int)strnlen_s(buf, 128); - Append(buf, len); - } - void Append(Int32 value, int radix = 10) - { - char vBuffer[33]; - int len = IntToAscii(vBuffer, value, radix); - ReverseInternalAscii(vBuffer, len); - Append(vBuffer); - } - void Append(UInt32 value, int radix = 10) - { - char vBuffer[33]; - int len = IntToAscii(vBuffer, value, radix); - ReverseInternalAscii(vBuffer, len); - Append(vBuffer); - } - void Append(Int64 value, int radix = 10) - { - char vBuffer[65]; - int len = IntToAscii(vBuffer, value, radix); - ReverseInternalAscii(vBuffer, len); - Append(vBuffer); - } - void Append(UInt64 value, int radix = 10) - { - char vBuffer[65]; - int len = IntToAscii(vBuffer, value, radix); - ReverseInternalAscii(vBuffer, len); - Append(vBuffer); - } - void Append(const String & str) - { - Append(str.getBuffer(), str.getLength()); - } - void Append(const char * str) - { - Append(str, strlen(str)); - } - void Append(const char * str, UInt strLen) - { + } + StringBuilder & operator << (char ch) + { + Append(&ch, 1); + return *this; + } + StringBuilder & operator << (Int32 val) + { + Append(val); + return *this; + } + StringBuilder & operator << (UInt32 val) + { + Append(val); + return *this; + } + StringBuilder & operator << (Int64 val) + { + Append(val); + return *this; + } + StringBuilder & operator << (UInt64 val) + { + Append(val); + return *this; + } + StringBuilder & operator << (float val) + { + Append(val); + return *this; + } + StringBuilder & operator << (double val) + { + Append(val); + return *this; + } + StringBuilder & operator << (const char * str) + { + Append(str, strlen(str)); + return *this; + } + StringBuilder & operator << (const String & str) + { + Append(str); + return *this; + } + StringBuilder & operator << (UnownedStringSlice const& str) + { + append(str); + return *this; + } + StringBuilder & operator << (const _EndLine) + { + Append('\n'); + return *this; + } + void Append(char ch) + { + Append(&ch, 1); + } + void Append(float val) + { + char buf[128]; + sprintf_s(buf, 128, "%g", val); + int len = (int)strnlen_s(buf, 128); + Append(buf, len); + } + void Append(double val) + { + char buf[128]; + sprintf_s(buf, 128, "%g", val); + int len = (int)strnlen_s(buf, 128); + Append(buf, len); + } + void Append(Int32 value, int radix = 10) + { + char vBuffer[33]; + int len = IntToAscii(vBuffer, value, radix); + ReverseInternalAscii(vBuffer, len); + Append(vBuffer); + } + void Append(UInt32 value, int radix = 10) + { + char vBuffer[33]; + int len = IntToAscii(vBuffer, value, radix); + ReverseInternalAscii(vBuffer, len); + Append(vBuffer); + } + void Append(Int64 value, int radix = 10) + { + char vBuffer[65]; + int len = IntToAscii(vBuffer, value, radix); + ReverseInternalAscii(vBuffer, len); + Append(vBuffer); + } + void Append(UInt64 value, int radix = 10) + { + char vBuffer[65]; + int len = IntToAscii(vBuffer, value, radix); + ReverseInternalAscii(vBuffer, len); + Append(vBuffer); + } + void Append(const String & str) + { + Append(str.getBuffer(), str.getLength()); + } + void Append(const char * str) + { + Append(str, strlen(str)); + } + void Append(const char * str, UInt strLen) + { append(str, str + strLen); - } + } #if 0 - int Capacity() - { - return bufferSize; - } - - char * Buffer() - { - return buffer; - } - - int Length() - { - return length; - } + int Capacity() + { + return bufferSize; + } + + char * Buffer() + { + return buffer; + } + + int Length() + { + return length; + } #endif - String ToString() - { + String ToString() + { return *this; - } + } - String ProduceString() - { + String ProduceString() + { return *this; - } + } #if 0 - String GetSubString(int start, int count) - { - String rs; - rs.buffer = new char[count + 1]; - rs.length = count; - strncpy_s(rs.buffer.Ptr(), count + 1, buffer + start, count); - rs.buffer[count] = 0; - return rs; - } + String GetSubString(int start, int count) + { + String rs; + rs.buffer = new char[count + 1]; + rs.length = count; + strncpy_s(rs.buffer.Ptr(), count + 1, buffer + start, count); + rs.buffer[count] = 0; + return rs; + } #endif #if 0 - void Remove(int id, int len) - { + void Remove(int id, int len) + { #if _DEBUG - if (id >= length || id < 0) - throw "Remove: Index out of range."; - if (len < 0) - throw "Remove: remove length smaller than zero."; + if (id >= length || id < 0) + throw "Remove: Index out of range."; + if (len < 0) + throw "Remove: remove length smaller than zero."; #endif - int actualDelLength = ((id + len) >= length) ? (length - id) : len; - for (int i = id + actualDelLength; i <= length; i++) - buffer[i - actualDelLength] = buffer[i]; - length -= actualDelLength; - } + int actualDelLength = ((id + len) >= length) ? (length - id) : len; + for (int i = id + actualDelLength; i <= length; i++) + buffer[i - actualDelLength] = buffer[i]; + length -= actualDelLength; + } #endif - void Clear() - { + void Clear() + { m_buffer.setNull(); - } - }; + } + }; - int StringToInt(const String & str, int radix = 10); - unsigned int StringToUInt(const String & str, int radix = 10); - double StringToDouble(const String & str); - float StringToFloat(const String & str); + int StringToInt(const String & str, int radix = 10); + unsigned int StringToUInt(const String & str, int radix = 10); + double StringToDouble(const String & str); + float StringToFloat(const String & str); } #endif diff --git a/source/core/slang-token-reader.h b/source/core/slang-token-reader.h index 474db5c4a..0c2d390d2 100644 --- a/source/core/slang-token-reader.h +++ b/source/core/slang-token-reader.h @@ -103,7 +103,7 @@ namespace Slang { auto token = ReadToken(); bool neg = false; - if (token.Content == '-') + if (token.Content.getUnownedSlice().isChar('-')) { neg = true; token = ReadToken(); @@ -130,7 +130,7 @@ namespace Slang { auto token = ReadToken(); bool neg = false; - if (token.Content == '-') + if (token.Content.getUnownedSlice().isChar('-')) { neg = true; token = ReadToken(); diff --git a/source/slang/slang-ast-base.h b/source/slang/slang-ast-base.h index e9005212c..2bfa7940b 100644 --- a/source/slang/slang-ast-base.h +++ b/source/slang/slang-ast-base.h @@ -155,6 +155,8 @@ class Type: public Val bool _equalsImplOverride(Type* type); Type* _createCanonicalTypeOverride(); + void _setASTBuilder(ASTBuilder* astBuilder) { m_astBuilder = astBuilder; } + protected: bool equalsImpl(Type* type); Type* createCanonicalType(); @@ -276,10 +278,10 @@ class Modifier : public SyntaxNode Modifier* next = nullptr; // The keyword that was used to introduce t that was used to name this modifier. - Name* name = nullptr; + Name* keywordName = nullptr; - Name* getName() { return name; } - NameLoc getNameAndLoc() { return NameLoc(name, loc); } + Name* getKeywordName() { return keywordName; } + NameLoc getKeywordNameAndLoc() { return NameLoc(keywordName, loc); } }; // A syntax node which can have modifiers applied @@ -327,7 +329,6 @@ public: SourceLoc getNameLoc() { return nameAndLoc.loc ; } NameLoc getNameAndLoc() { return nameAndLoc ; } - DeclCheckStateExt checkState = DeclCheckState::Unchecked; // The next declaration defined in the same container with the same name diff --git a/source/slang/slang-ast-builder.cpp b/source/slang/slang-ast-builder.cpp index 54fe55478..3b97bfbb7 100644 --- a/source/slang/slang-ast-builder.cpp +++ b/source/slang/slang-ast-builder.cpp @@ -140,7 +140,7 @@ void SharedASTBuilder::registerMagicDecl(Decl* decl, MagicTypeModifier* modifier if (auto genericDecl = as<GenericDecl>(decl->parentDecl)) declToRegister = genericDecl; - m_magicDecls[modifier->name] = declToRegister; + m_magicDecls[modifier->magicName] = declToRegister; } Decl* SharedASTBuilder::findMagicDecl(const String& name) diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h index d707e9771..55b62483b 100644 --- a/source/slang/slang-ast-modifier.h +++ b/source/slang/slang-ast-modifier.h @@ -350,9 +350,10 @@ class BuiltinTypeModifier : public Modifier class MagicTypeModifier : public Modifier { SLANG_AST_CLASS(MagicTypeModifier) - - String name; - uint32_t tag; + + /// Modifier has a name so call this magicModifier to disambiguate + String magicName; + uint32_t tag = uint32_t(0); }; // A modifier applied to declarations of builtin types to indicate how they diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h index 10bf46b63..8338f0b21 100644 --- a/source/slang/slang-ast-support-types.h +++ b/source/slang/slang-ast-support-types.h @@ -1255,6 +1255,8 @@ namespace Slang // requirement by a particular declaration or value. struct RequirementWitness { + SLANG_VALUE_CLASS(RequirementWitness) + RequirementWitness() : m_flavor(Flavor::none) {} @@ -1305,8 +1307,10 @@ namespace Slang typedef Dictionary<Decl*, RequirementWitness> RequirementDictionary; - struct WitnessTable : RefObject + struct WitnessTable : SerialRefObject { + SLANG_OBJ_CLASS(WitnessTable) + List<KeyValuePair<Decl*, RequirementWitness>> requirementList; RequirementDictionary requirementDictionary; diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index d771e689c..e7c2a5853 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -1231,6 +1231,11 @@ namespace Slang } } + void registerBuiltinDecls(Session* session, Decl* decl) + { + _registerBuiltinDeclsRec(session, decl); + } + void SemanticsDeclVisitorBase::checkModule(ModuleDecl* moduleDecl) { // When we are dealing with code from the standard library, diff --git a/source/slang/slang-check-modifier.cpp b/source/slang/slang-check-modifier.cpp index b38018354..4594af28d 100644 --- a/source/slang/slang-check-modifier.cpp +++ b/source/slang/slang-check-modifier.cpp @@ -395,7 +395,7 @@ namespace Slang // Let it go thru iff single string attribute if (!hasStringArgs(attr, 1)) { - getSink()->diagnose(attr, Diagnostics::expectedSingleStringArg, attr->name); + getSink()->diagnose(attr, Diagnostics::expectedSingleStringArg, attr->keywordName); } } else if (as<OutputControlPointsAttribute>(attr)) @@ -403,7 +403,7 @@ namespace Slang // Let it go thru iff single integral attribute if (!hasIntArgs(attr, 1)) { - getSink()->diagnose(attr, Diagnostics::expectedSingleIntArg, attr->name); + getSink()->diagnose(attr, Diagnostics::expectedSingleIntArg, attr->keywordName); } } else if (as<PushConstantAttribute>(attr)) @@ -433,7 +433,7 @@ namespace Slang } else { - getSink()->diagnose(attr, Diagnostics::expectedSingleIntArg, attr->name); + getSink()->diagnose(attr, Diagnostics::expectedSingleIntArg, attr->keywordName); return false; } } @@ -551,7 +551,7 @@ namespace Slang UncheckedAttribute* uncheckedAttr, ModifiableSyntaxNode* attrTarget) { - auto attrName = uncheckedAttr->getName(); + auto attrName = uncheckedAttr->getKeywordName(); auto attrDecl = lookUpAttributeDecl( attrName, uncheckedAttr->scope); @@ -580,7 +580,7 @@ namespace Slang // We are going to replace the unchecked attribute with the checked one. // First copy all of the state over from the original attribute. - attr->name = uncheckedAttr->name; + attr->keywordName = uncheckedAttr->keywordName; attr->args = uncheckedAttr->args; attr->loc = uncheckedAttr->loc; diff --git a/source/slang/slang-check.h b/source/slang/slang-check.h index 94deba1aa..0309e5393 100644 --- a/source/slang/slang-check.h +++ b/source/slang/slang-check.h @@ -36,4 +36,6 @@ namespace Slang bool isGlobalShaderParameter(VarDeclBase* decl); bool isFromStdLib(Decl* decl); + + void registerBuiltinDecls(Session* session, Decl* decl); } diff --git a/source/slang/slang-compiler.cpp b/source/slang/slang-compiler.cpp index ea8540800..306119b5f 100755 --- a/source/slang/slang-compiler.cpp +++ b/source/slang/slang-compiler.cpp @@ -2346,7 +2346,7 @@ SlangResult dissassembleDXILUsingDXC( options.compressionType = linkage->serialCompressionType; if (linkage->debugInfoLevel != DebugInfoLevel::None) { - options.optionFlags |= SerialOptionFlag::DebugInfo; + options.optionFlags |= SerialOptionFlag::SourceLocation; } if (linkage->m_obfuscateCode) { @@ -2360,7 +2360,7 @@ SlangResult dissassembleDXILUsingDXC( RiffContainer container; { SerialContainerData data; - SLANG_RETURN_ON_FAIL(SerialContainerUtil::requestToData(this, options, data)); + SLANG_RETURN_ON_FAIL(SerialContainerUtil::addEndToEndRequestToData(this, options, data)); SLANG_RETURN_ON_FAIL(SerialContainerUtil::write(data, options, &container)); } // We now write the RiffContainer to the stream diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 56885ab46..1710baa6e 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -925,7 +925,7 @@ namespace Slang // /// Create a module (initially empty). - Module(Linkage* linkage); + Module(Linkage* linkage, ASTBuilder* astBuilder = nullptr); /// Get the AST for the module (if it has been parsed) ModuleDecl* getModuleDecl() { return m_moduleDecl; } @@ -978,7 +978,7 @@ namespace Slang NodeBase* findExportFromMangledName(const UnownedStringSlice& slice); /// Get the ASTBuilder - ASTBuilder* getASTBuilder() { return &m_astBuilder; } + ASTBuilder* getASTBuilder() { return m_astBuilder; } /// Collect information on the shader parameters of the module. /// @@ -1058,7 +1058,7 @@ namespace Slang // The builder that owns all of the AST nodes from parsing the source of // this module. - ASTBuilder m_astBuilder; + RefPtr<ASTBuilder> m_astBuilder; // Holds map of exported mangled names to symbols. m_mangledExportPool maps names to indices, // and m_mangledExportSymbols holds the NodeBase* values for each index. @@ -2170,6 +2170,8 @@ namespace Slang private: + SlangResult _readBuiltinModule(Scope* scope, String moduleName); + SlangResult _loadRequest(EndToEndCompileRequest* request, const void* data, size_t size); /// Linkage used for all built-in (stdlib) code. diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index e02ccf245..4d93c35a8 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -730,7 +730,7 @@ namespace Slang Token nameToken = parseAttributeName(parser); UncheckedAttribute* modifier = parser->astBuilder->create<UncheckedAttribute>(); - modifier->name = nameToken.getName(); + modifier->keywordName = nameToken.getName(); modifier->loc = nameToken.getLoc(); modifier->scope = parser->currentScope; @@ -903,7 +903,7 @@ namespace Slang Modifier* parsedModifier = nullptr; if (tryParseUsingSyntaxDecl<Modifier>(parser, &parsedModifier)) { - parsedModifier->name = nameToken.getName(); + parsedModifier->keywordName = nameToken.getName(); if (!parsedModifier->loc.isValid()) { parsedModifier->loc = nameToken.loc; @@ -5504,7 +5504,7 @@ namespace Slang numThreadsAttrib->args.setCount(3); // Just mark the loc and name from the first in the list - numThreadsAttrib->name = getName(parser, "numthreads"); + numThreadsAttrib->keywordName = getName(parser, "numthreads"); numThreadsAttrib->loc = nameAndLoc.loc; numThreadsAttrib->scope = parser->currentScope; } @@ -5566,7 +5566,7 @@ namespace Slang SLANG_ASSERT(modifier); #undef CASE - modifier->name = nameAndLoc.name; + modifier->keywordName = nameAndLoc.name; modifier->loc = nameAndLoc.loc; // Special handling for GLSLLayoutModifier @@ -5610,7 +5610,7 @@ namespace Slang { MagicTypeModifier* modifier = parser->astBuilder->create<MagicTypeModifier>(); parser->ReadToken(TokenType::LParent); - modifier->name = parser->ReadToken(TokenType::Identifier).getContent(); + modifier->magicName = parser->ReadToken(TokenType::Identifier).getContent(); if (AdvanceIf(parser, TokenType::Comma)) { modifier->tag = uint32_t(StringToInt(parser->ReadToken(TokenType::IntegerLiteral).getContent())); diff --git a/source/slang/slang-reflection.cpp b/source/slang/slang-reflection.cpp index 1b0a590cc..fd76c5e0b 100644 --- a/source/slang/slang-reflection.cpp +++ b/source/slang/slang-reflection.cpp @@ -114,7 +114,7 @@ SlangReflectionUserAttribute* findUserAttributeByName(Session* session, Decl* de auto nameObj = session->tryGetNameObj(name); for (auto x : decl->getModifiersOfType<UserDefinedAttribute>()) { - if (x->name == nameObj) + if (x->keywordName == nameObj) return (SlangReflectionUserAttribute*)(x); } return nullptr; @@ -136,7 +136,7 @@ SLANG_API char const* spReflectionUserAttribute_GetName(SlangReflectionUserAttri { auto userAttr = convert(attrib); if (!userAttr) return nullptr; - return userAttr->getName()->text.getBuffer(); + return userAttr->getKeywordName()->text.getBuffer(); } SLANG_API unsigned int spReflectionUserAttribute_GetArgumentCount(SlangReflectionUserAttribute* attrib) { diff --git a/source/slang/slang-serialize-ast-type-info.h b/source/slang/slang-serialize-ast-type-info.h index 733694e8a..400474046 100644 --- a/source/slang/slang-serialize-ast-type-info.h +++ b/source/slang/slang-serialize-ast-type-info.h @@ -92,6 +92,7 @@ SLANG_VALUE_TYPE_INFO(LookupResultItem) // QualType SLANG_VALUE_TYPE_INFO(QualType) + // LookupResult template <> struct SerialTypeInfo<LookupResult> @@ -205,6 +206,13 @@ struct SerialTypeInfo<LookupResultItem_Breadcrumb::ThisParameterMode> : public S template <> struct SerialTypeInfo<LookupResultItem_Breadcrumb::Kind> : public SerialConvertTypeInfo<LookupResultItem_Breadcrumb::Kind, uint8_t> {}; +// RequirementWitness::Flavor +template <> +struct SerialTypeInfo<RequirementWitness::Flavor> : public SerialConvertTypeInfo<RequirementWitness::Flavor, uint8_t> {}; + +// RequirementWitness +SLANG_VALUE_TYPE_INFO(RequirementWitness) + } // namespace Slang #endif diff --git a/source/slang/slang-serialize-container.cpp b/source/slang/slang-serialize-container.cpp index 8c4edb9a0..067e6637a 100644 --- a/source/slang/slang-serialize-container.cpp +++ b/source/slang/slang-serialize-container.cpp @@ -16,42 +16,100 @@ namespace Slang { -/* static */SlangResult SerialContainerUtil::requestToData(EndToEndCompileRequest* request, const WriteOptions& options, SerialContainerData& out) +/* static */SlangResult SerialContainerUtil::write(Module* module, const WriteOptions& options, Stream* stream) { - SLANG_UNUSED(options); - - out.clear(); - - auto linkage = request->getLinkage(); - auto sink = request->getSink(); - auto frontEndReq = request->getFrontEndReq(); - - for (TranslationUnitRequest* translationUnit : frontEndReq->translationUnits) + RiffContainer container; { - auto module = translationUnit->module; - auto irModule = module->getIRModule(); + SerialContainerData data; + SLANG_RETURN_ON_FAIL(SerialContainerUtil::addModuleToData(module, options, data)); + SLANG_RETURN_ON_FAIL(SerialContainerUtil::write(data, options, &container)); + } + // We now write the RiffContainer to the stream + SLANG_RETURN_ON_FAIL(RiffUtil::write(container.getRoot(), true, stream)); + return SLANG_OK; +} - // Root AST node - auto moduleDecl = translationUnit->getModuleDecl(); +/* static */SlangResult SerialContainerUtil::write(FrontEndCompileRequest* frontEndReq, const WriteOptions& options, Stream* stream) +{ + RiffContainer container; + { + SerialContainerData data; + SLANG_RETURN_ON_FAIL(SerialContainerUtil::addFrontEndRequestToData(frontEndReq, options, data)); + SLANG_RETURN_ON_FAIL(SerialContainerUtil::write(data, options, &container)); + } + // We now write the RiffContainer to the stream + SLANG_RETURN_ON_FAIL(RiffUtil::write(container.getRoot(), true, stream)); + return SLANG_OK; +} - SLANG_ASSERT(irModule || moduleDecl); +/* static */SlangResult SerialContainerUtil::write(EndToEndCompileRequest* request, const WriteOptions& options, Stream* stream) +{ + RiffContainer container; + { + SerialContainerData data; + SLANG_RETURN_ON_FAIL(SerialContainerUtil::addEndToEndRequestToData(request, options, data)); + SLANG_RETURN_ON_FAIL(SerialContainerUtil::write(data, options, &container)); + } + // We now write the RiffContainer to the stream + SLANG_RETURN_ON_FAIL(RiffUtil::write(container.getRoot(), true, stream)); + return SLANG_OK; +} +/* static */SlangResult SerialContainerUtil::addModuleToData(Module* module, const WriteOptions& options, SerialContainerData& outData) +{ + if (options.optionFlags & (SerialOptionFlag::ASTModule | SerialOptionFlag::IRModule)) + { SerialContainerData::Module dstModule; // NOTE: The astBuilder is not set here, as not needed to be scoped for serialization (it is assumed the // TranslationUnitRequest stays in scope) - dstModule.astRootNode = moduleDecl; - dstModule.irModule = irModule; + if (options.optionFlags & SerialOptionFlag::ASTModule) + { + // Root AST node + auto moduleDecl = module->getModuleDecl(); + SLANG_ASSERT(moduleDecl); - out.modules.add(dstModule); + dstModule.astRootNode = moduleDecl; + } + if (options.optionFlags & SerialOptionFlag::IRModule) + { + // IR module + dstModule.irModule = module->getIRModule(); + SLANG_ASSERT(dstModule.irModule); + } + + outData.modules.add(dstModule); + } + + return SLANG_OK; +} + + +/* static */SlangResult SerialContainerUtil::addFrontEndRequestToData(FrontEndCompileRequest* frontEndReq, const WriteOptions& options, SerialContainerData& outData) +{ + // Go through translation units, adding modules + for (TranslationUnitRequest* translationUnit : frontEndReq->translationUnits) + { + SLANG_RETURN_ON_FAIL(addModuleToData(translationUnit->module, options, outData)); } + return SLANG_OK; +} + +/* static */SlangResult SerialContainerUtil::addEndToEndRequestToData(EndToEndCompileRequest* request, const WriteOptions& options, SerialContainerData& out) +{ + auto linkage = request->getLinkage(); + auto sink = request->getSink(); + + // Output the front end request data + SLANG_RETURN_ON_FAIL(addFrontEndRequestToData(request->getFrontEndReq(), options, out)); + + // auto program = request->getSpecializedGlobalAndEntryPointsComponentType(); // Add all the target modules { - for (auto target : linkage->targets) { auto targetProgram = program->getTargetProgram(target); @@ -117,7 +175,7 @@ namespace Slang { // Module list RiffContainer::ScopeChunk moduleListScope(container, RiffContainer::Chunk::Kind::List, SerialBinary::kModuleListFourCc); - if (options.optionFlags & SerialOptionFlag::DebugInfo) + if (options.optionFlags & SerialOptionFlag::SourceLocation) { sourceLocWriter = new SerialSourceLocWriter(options.sourceManager); } @@ -226,6 +284,20 @@ namespace Slang { return SLANG_OK; } + +static List<ExtensionDecl*>& _getCandidateExtensionList( + AggTypeDecl* typeDecl, + Dictionary<AggTypeDecl*, RefPtr<CandidateExtensionList>>& mapTypeToCandidateExtensions) +{ + RefPtr<CandidateExtensionList> entry; + if (!mapTypeToCandidateExtensions.TryGetValue(typeDecl, entry)) + { + entry = new CandidateExtensionList(); + mapTypeToCandidateExtensions.Add(typeDecl, entry); + } + return entry->candidateExtensions; +} + /* static */Result SerialContainerUtil::read(RiffContainer* container, const ReadOptions& options, SerialContainerData& out) { out.clear(); @@ -396,6 +468,10 @@ namespace Slang { // Set the sourceLocReader before doing de-serialize, such can lookup the remapped sourceLocs reader.getExtraObjects().set(sourceLocReader); + // Go through all of the AST nodes + // 1) Set the ASTBuilder on Type nodes + + // TODO(JS): // If modules can have more complicated relationships (like a two modules can refer to symbols // from each other), then we can make this work by @@ -412,6 +488,34 @@ namespace Slang { // Get the root node. It's at index 1 (0 is the null value). astRootNode = reader.getPointer(SerialIndex(1)).dynamicCast<NodeBase>(); + + // 2) Add the extensions to the module mapTypeToCandidateExtensions cache + + { + ModuleDecl* moduleDecl = as<ModuleDecl>(astRootNode); + + for (auto& obj : reader.getObjects()) + { + if (Type* type = obj.dynamicCast<Type>()) + { + type->_setASTBuilder(astBuilder); + } + + if (ExtensionDecl* extensionDecl = obj.dynamicCast<ExtensionDecl>()) + { + if (auto targetDeclRefType = as<DeclRefType>(extensionDecl->targetType)) + { + // Attach our extension to that type as a candidate... + if (auto aggTypeDeclRef = targetDeclRefType->declRef.as<AggTypeDecl>()) + { + auto aggTypeDecl = aggTypeDeclRef.getDecl(); + + _getCandidateExtensionList(aggTypeDecl, moduleDecl->mapTypeToCandidateExtensions).add(extensionDecl); + } + } + } + } + } } // Onto next chunk @@ -489,7 +593,7 @@ namespace Slang { RefPtr<SerialSourceLocWriter> sourceLocWriter; - if (options.optionFlags & SerialOptionFlag::DebugInfo) + if (options.optionFlags & SerialOptionFlag::SourceLocation) { sourceLocWriter = new SerialSourceLocWriter(options.sourceManager); } @@ -530,7 +634,7 @@ namespace Slang { RefPtr<SerialSourceLocReader> sourceLocReader; // If we have debug info then find and read it - if (options.optionFlags & SerialOptionFlag::DebugInfo) + if (options.optionFlags & SerialOptionFlag::SourceLocation) { RiffContainer::ListChunk* debugList = rootList->findContainedList(SerialSourceLocData::kDebugFourCc); if (!debugList) @@ -593,7 +697,7 @@ namespace Slang { } } } - else if (options.optionFlags & SerialOptionFlag::DebugInfo) + else if (options.optionFlags & SerialOptionFlag::SourceLocation) { // They should be on the same line nos for (Index i = 1; i < readInsts.getCount(); ++i) diff --git a/source/slang/slang-serialize-container.h b/source/slang/slang-serialize-container.h index bc34982e7..5368f62e6 100644 --- a/source/slang/slang-serialize-container.h +++ b/source/slang/slang-serialize-container.h @@ -93,8 +93,14 @@ struct SerialContainerUtil DiagnosticSink* sink = nullptr; }; + /// Add module to outData + static SlangResult addModuleToData(Module* module, const WriteOptions& options, SerialContainerData& outData); + /// Get the serializable contents of the request as data - static SlangResult requestToData(EndToEndCompileRequest* request, const WriteOptions& options, SerialContainerData& outData); + static SlangResult addEndToEndRequestToData(EndToEndCompileRequest* request, const WriteOptions& options, SerialContainerData& outData); + + /// Convert front end request into something serializable + static SlangResult addFrontEndRequestToData(FrontEndCompileRequest* request, const WriteOptions& options, SerialContainerData& outData); /// Write the data into the container static SlangResult write(const SerialContainerData& data, const WriteOptions& options, RiffContainer* container); @@ -104,6 +110,12 @@ struct SerialContainerUtil /// Verify IR serialization static SlangResult verifyIRSerialize(IRModule* module, Session* session, const WriteOptions& options); + + /// Write the request to the stream + static SlangResult write(FrontEndCompileRequest* frontEndReq, const WriteOptions& options, Stream* stream); + static SlangResult write(EndToEndCompileRequest* request, const WriteOptions& options, Stream* stream); + static SlangResult write(Module* module, const WriteOptions& options, Stream* stream); + }; } // namespace Slang diff --git a/source/slang/slang-serialize-factory.cpp b/source/slang/slang-serialize-factory.cpp index f93fbba69..3ff536137 100644 --- a/source/slang/slang-serialize-factory.cpp +++ b/source/slang/slang-serialize-factory.cpp @@ -111,6 +111,9 @@ SerialIndex ModuleSerialFilter::writePointer(SerialWriter* writer, const NodeBas ASTSerialUtil::addSerialClasses(serialClasses); SerialRefObjects::addSerialClasses(serialClasses); + // Check if it seems ok + SLANG_ASSERT(serialClasses->isOk()); + return SLANG_OK; } diff --git a/source/slang/slang-serialize-ir.cpp b/source/slang/slang-serialize-ir.cpp index d923577f4..50e4467e3 100644 --- a/source/slang/slang-serialize-ir.cpp +++ b/source/slang/slang-serialize-ir.cpp @@ -307,7 +307,7 @@ Result IRSerialWriter::write(IRModule* module, SerialSourceLocWriter* sourceLocW } } - if ((options & SerialOptionFlag::DebugInfo) && sourceLocWriter) + if ((options & SerialOptionFlag::SourceLocation) && sourceLocWriter) { _calcDebugInfo(sourceLocWriter); } diff --git a/source/slang/slang-serialize-type-info.h b/source/slang/slang-serialize-type-info.h index 89097fc32..7ed45bb0b 100644 --- a/source/slang/slang-serialize-type-info.h +++ b/source/slang/slang-serialize-type-info.h @@ -150,11 +150,7 @@ struct SerialTypeInfo<T*> { typedef T* NativeType; typedef SerialIndex SerialType; - - enum - { - SerialAlignment = SLANG_ALIGN_OF(SerialType) - }; + enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) }; static void toSerial(SerialWriter* writer, const void* inNative, void* outSerial) { @@ -166,6 +162,25 @@ struct SerialTypeInfo<T*> } }; +// RefPtr (pretty much the same as T* - except for native rep) +template <typename T> +struct SerialTypeInfo<RefPtr<T>> +{ + typedef RefPtr<T> NativeType; + typedef SerialIndex SerialType; + enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) }; + + static void toSerial(SerialWriter* writer, const void* native, void* serial) + { + auto& src = *(const NativeType*)native; + *(SerialType*)serial = writer->addPointer(src); + } + static void toNative(SerialReader* reader, const void* serial, void* native) + { + *(NativeType*)native = reader->getPointer(*(const SerialType*)serial).dynamicCast<T>(); + } +}; + // Special case Name template <> struct SerialTypeInfo<Name*> : public SerialTypeInfo<RefObject*> @@ -208,6 +223,27 @@ struct SerialTypeInfo<List<T, ALLOCATOR>> } }; +// String +template <> +struct SerialTypeInfo<String> +{ + typedef String NativeType; + typedef SerialIndex SerialType; + enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) }; + + static void toSerial(SerialWriter* writer, const void* native, void* serial) + { + auto& src = *(const NativeType*)native; + *(SerialType*)serial = writer->addString(src); + } + static void toNative(SerialReader* reader, const void* serial, void* native) + { + auto& src = *(const SerialType*)serial; + auto& dst = *(NativeType*)native; + dst = reader->getString(src); + } +}; + // Dictionary template <typename KEY, typename VALUE> struct SerialTypeInfo<Dictionary<KEY, VALUE>> @@ -244,8 +280,9 @@ struct SerialTypeInfo<Dictionary<KEY, VALUE>> i++; } - dst.keys = writer->addArray(keys.getBuffer(), count); - dst.values = writer->addArray(values.getBuffer(), count); + // When we add the array it is already converted to a serializable type, so add as SerialArray + dst.keys = writer->addSerialArray<KEY>(keys.getBuffer(), count); + dst.values = writer->addSerialArray<VALUE>(values.getBuffer(), count); } static void toNative(SerialReader* reader, const void* serial, void* native) { @@ -271,49 +308,42 @@ struct SerialTypeInfo<Dictionary<KEY, VALUE>> } }; -// Handle RefPtr - just convert into * to do the conversion -template <typename T> -struct SerialTypeInfo<RefPtr<T>> +// KeyValuePair +template<typename KEY, typename VALUE> +struct SerialTypeInfo<KeyValuePair<KEY, VALUE>> { - typedef RefPtr<T> NativeType; - typedef typename SerialTypeInfo<T*>::SerialType SerialType; - enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) }; + typedef KeyValuePair<KEY, VALUE> NativeType; - static void toSerial(SerialWriter* writer, const void* native, void* serial) - { - auto& src = *(const NativeType*)native; - T* obj = src; - SerialTypeInfo<T*>::toSerial(writer, &obj, serial); - } - static void toNative(SerialReader* reader, const void* serial, void* native) + typedef typename SerialTypeInfo<KEY>::SerialType KeySerialType; + typedef typename SerialTypeInfo<VALUE>::SerialType ValueSerialType; + + struct SerialType { - T* obj = nullptr; - SerialTypeInfo<T*>::toNative(reader, serial, &obj); - *(NativeType*)native = obj; - } -}; + KeySerialType key; + ValueSerialType value; + }; -// String -template <> -struct SerialTypeInfo<String> -{ - typedef String NativeType; - typedef SerialIndex SerialType; enum { SerialAlignment = SLANG_ALIGN_OF(SerialType) }; static void toSerial(SerialWriter* writer, const void* native, void* serial) { auto& src = *(const NativeType*)native; - *(SerialType*)serial = writer->addString(src); + auto& dst = *(SerialType*)serial; + + SerialTypeInfo<KEY>::toSerial(writer, &src.Key, &dst.key); + SerialTypeInfo<VALUE>::toSerial(writer, &src.Value, &dst.value); } static void toNative(SerialReader* reader, const void* serial, void* native) { auto& src = *(const SerialType*)serial; auto& dst = *(NativeType*)native; - dst = reader->getString(src); + + SerialTypeInfo<KEY>::toNative(reader, &src.key, &dst.Key); + SerialTypeInfo<VALUE>::toNative(reader, &src.value, &dst.Value); } }; + } // namespace Slang #endif diff --git a/source/slang/slang-serialize-types.h b/source/slang/slang-serialize-types.h index 9bb84e290..fb0dd2f9d 100644 --- a/source/slang/slang-serialize-types.h +++ b/source/slang/slang-serialize-types.h @@ -27,7 +27,7 @@ struct SerialOptionFlag enum Enum : Type { RawSourceLocation = 0x01, ///< If set will store directly SourceLoc - only useful if current source locs will be identical when read in (typically this is *NOT* the case) - DebugInfo = 0x02, ///< If set will output debug information, that can be reconstructed when read after being stored. + SourceLocation = 0x02, ///< If set will output SourceLoc information, that can be reconstructed when read after being stored. ASTModule = 0x04, ///< If set will output AST modules - typically required, but potentially not desired (for example with obsfucation) IRModule = 0x08, ///< If set will output IR modules - typically required }; diff --git a/source/slang/slang-serialize.cpp b/source/slang/slang-serialize.cpp index 34680d860..4f8fdc546 100644 --- a/source/slang/slang-serialize.cpp +++ b/source/slang/slang-serialize.cpp @@ -151,6 +151,58 @@ SerialClass* SerialClasses::_createSerialClass(const SerialClass* cls) return dst; } +bool SerialClasses::isOk() const +{ + StringSlicePool pool(StringSlicePool::Style::Default); + + for (const auto& classes : m_classesByTypeKind) + { + for (const SerialClass* cls : classes) + { + // It is possible potentially to have gaps + if (cls == nullptr) + { + continue; + } + + if (cls->super && cls->super->typeKind != cls->typeKind) + { + // If has a super type, must be the same typeKind + return false; + } + + // Make sure the fields are uniquely named + + pool.clear(); + + { + const SerialClass* curCls = cls; + + do + { + for (Index i = 0; i < curCls->fieldsCount; ++i) + { + const SerialField& field = curCls->fields[i]; + + StringSlicePool::Handle handle; + if (pool.findOrAdd(UnownedStringSlice(field.name), handle)) + { + return false; + } + } + + // Add the fields of the parent + curCls = curCls->super; + } + while (curCls); + } + } + } + + return true; +} + + SerialClasses::SerialClasses(): m_arena(2048) { @@ -375,7 +427,7 @@ SerialIndex SerialWriter::addName(const Name* name) return index; } -SerialIndex SerialWriter::_addArray(size_t elementSize, size_t alignment, const void* elements, Index elementCount) +SerialIndex SerialWriter::addSerialArray(size_t elementSize, size_t alignment, const void* elements, Index elementCount) { typedef SerialInfo::ArrayEntry Entry; @@ -699,12 +751,19 @@ String SerialReader::getString(SerialIndex index) // Okay we need to construct as a string UnownedStringSlice slice = getStringSlice(index); - String string(slice); - StringRepresentation* stringRep = string.getStringRepresentation(); - m_scope.add(stringRep); + StringRepresentation* stringRep = nullptr; + + const Index length = slice.getLength(); + if (length) + { + stringRep = StringRepresentation::createWithCapacityAndLength(length, length); + memcpy(stringRep->getData(), slice.begin(), length * sizeof(char)); + addScope(stringRep); + } + m_objects[Index(index)] = stringRep; - return string; + return String(stringRep); } Name* SerialReader::getName(SerialIndex index) diff --git a/source/slang/slang-serialize.h b/source/slang/slang-serialize.h index a48a7e216..ff402b35c 100644 --- a/source/slang/slang-serialize.h +++ b/source/slang/slang-serialize.h @@ -246,7 +246,9 @@ public: const List<SerialPointer>& getObjects() const { return m_objects; } /// Add an object to be kept in scope - void addScope(const RefObject* obj) { m_scope.add(obj); } + void addScopeWithoutAddRef(const RefObject* obj) { m_scope.add(obj); } + /// Add obj with a reference + void addScope(const RefObject* obj) { const_cast<RefObject*>(obj)->addReference(); m_scope.add(obj); } /// Used for attaching extra objects necessary for serializing SerialExtraObjects& getExtraObjects() { return m_extraObjects; } @@ -324,9 +326,21 @@ public: SerialIndex writeObject(const NodeBase* ptr); SerialIndex writeObject(const RefObject* ptr); + /// Add an array - may need to convert to serialized format template <typename T> SerialIndex addArray(const T* in, Index count); + template <typename NATIVE_TYPE> + /// Add an array where all the elements are already in serialized format (ie there is no need to do a conversion) + SerialIndex addSerialArray(const void* elements, Index elementCount) + { + typedef SerialTypeInfo<NATIVE_TYPE> TypeInfo; + return addSerialArray(sizeof(typename TypeInfo::SerialType), SerialTypeInfo<NATIVE_TYPE>::SerialAlignment, elements, elementCount); + } + + /// Add an array where all the elements are already in serialized format (ie there is no need to do a conversion) + SerialIndex addSerialArray(size_t elementSize, size_t alignment, const void* elements, Index elementCount); + /// Add the string SerialIndex addString(const UnownedStringSlice& slice) { return _addStringSlice(SerialTypeKind::String, m_sliceMap, slice); } SerialIndex addString(const String& in); @@ -362,8 +376,6 @@ protected: SerialIndex _addStringSlice(SerialTypeKind typeKind, SliceMap& sliceMap, const UnownedStringSlice& slice); - SerialIndex _addArray(size_t elementSize, size_t alignment, const void* elements, Index elementCount); - SerialIndex _add(const void* nativePtr, SerialInfo::Entry* entry) { m_entries.add(entry); @@ -399,7 +411,7 @@ SerialIndex SerialWriter::addArray(const T* in, Index count) if (std::is_same<T, ElementSerialType>::value) { // If they are the same we can just write out - return _addArray(sizeof(T), SLANG_ALIGN_OF(ElementSerialType), in, count); + return addSerialArray(sizeof(T), SLANG_ALIGN_OF(ElementSerialType), in, count); } else { @@ -411,7 +423,7 @@ SerialIndex SerialWriter::addArray(const T* in, Index count) { ElementTypeInfo::toSerial(this, &in[i], &work[i]); } - return _addArray(sizeof(ElementSerialType), SLANG_ALIGN_OF(ElementSerialType), work.getBuffer(), count); + return addSerialArray(sizeof(ElementSerialType), SLANG_ALIGN_OF(ElementSerialType), work.getBuffer(), count); } } @@ -478,7 +490,6 @@ struct SerialClass class SerialClasses : public RefObject { public: - /// Will add it's own copy into m_classesByType /// In process will calculate alignment, offset etc for fields /// NOTE! the super set, *must* be an already added to this SerialClasses @@ -492,6 +503,9 @@ public: /// Returns true if this cls is *owned* by this SerialClasses bool isOwned(const SerialClass* cls) const; + /// Returns true if the SerialClasses structure appears ok + bool isOk() const; + /// Get a serial class based on its type/subType const SerialClass* getSerialClass(SerialTypeKind typeKind, SerialSubType subType) const { diff --git a/source/slang/slang-syntax.cpp b/source/slang/slang-syntax.cpp index ea17ad1d1..82e94fb6a 100644 --- a/source/slang/slang-syntax.cpp +++ b/source/slang/slang-syntax.cpp @@ -453,14 +453,14 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt } } - if (magicMod->name == "SamplerState") + if (magicMod->magicName == "SamplerState") { auto type = astBuilder->create<SamplerStateType>(); type->declRef = declRef; type->flavor = SamplerStateFlavor(magicMod->tag); return type; } - else if (magicMod->name == "Vector") + else if (magicMod->magicName == "Vector") { SLANG_ASSERT(subst && subst->args.getCount() == 2); auto vecType = astBuilder->create<VectorExpressionType>(); @@ -469,14 +469,14 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt vecType->elementCount = ExtractGenericArgInteger(subst->args[1]); return vecType; } - else if (magicMod->name == "Matrix") + else if (magicMod->magicName == "Matrix") { SLANG_ASSERT(subst && subst->args.getCount() == 3); auto matType = astBuilder->create<MatrixExpressionType>(); matType->declRef = declRef; return matType; } - else if (magicMod->name == "Texture") + else if (magicMod->magicName == "Texture") { SLANG_ASSERT(subst && subst->args.getCount() >= 1); auto textureType = astBuilder->create<TextureType>( @@ -485,7 +485,7 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt textureType->declRef = declRef; return textureType; } - else if (magicMod->name == "TextureSampler") + else if (magicMod->magicName == "TextureSampler") { SLANG_ASSERT(subst && subst->args.getCount() >= 1); auto textureType = astBuilder->create<TextureSamplerType>( @@ -494,7 +494,7 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt textureType->declRef = declRef; return textureType; } - else if (magicMod->name == "GLSLImageType") + else if (magicMod->magicName == "GLSLImageType") { SLANG_ASSERT(subst && subst->args.getCount() >= 1); auto textureType = astBuilder->create<GLSLImageType>( @@ -503,7 +503,7 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt textureType->declRef = declRef; return textureType; } - else if (magicMod->name == "FeedbackType") + else if (magicMod->magicName == "FeedbackType") { SLANG_ASSERT(subst == nullptr); auto type = astBuilder->create<FeedbackType>(); @@ -517,7 +517,7 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt // of this ridiculously slow `if` cascade. #define CASE(n,T) \ - else if(magicMod->name == #n) { \ + else if(magicMod->magicName == #n) { \ auto type = astBuilder->create<T>(); \ type->declRef = declRef; \ return type; \ @@ -529,7 +529,7 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt #undef CASE #define CASE(n,T) \ - else if(magicMod->name == #n) { \ + else if(magicMod->magicName == #n) { \ SLANG_ASSERT(subst && subst->args.getCount() == 1); \ auto type = astBuilder->create<T>(); \ type->elementType = ExtractGenericArgType(subst->args[0]); \ @@ -558,7 +558,7 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt // "magic" builtin types which have no generic parameters #define CASE(n,T) \ - else if(magicMod->name == #n) { \ + else if(magicMod->magicName == #n) { \ auto type = astBuilder->create<T>(); \ type->declRef = declRef; \ return type; \ @@ -575,7 +575,7 @@ Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filt else { - auto classInfo = astBuilder->findSyntaxClass(magicMod->name.getUnownedSlice()); + auto classInfo = astBuilder->findSyntaxClass(magicMod->magicName.getUnownedSlice()); if (!classInfo.classInfo) { SLANG_UNEXPECTED("unhandled type"); diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 90ddf030c..a66441948 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -136,7 +136,6 @@ void Session::init() // And the global ASTBuilder globalAstBuilder = new ASTBuilder(m_sharedASTBuilder, "globalAstBuilder"); - // Make sure our source manager is initialized builtinSourceManager.initialize(nullptr, nullptr); @@ -175,8 +174,41 @@ void Session::init() slangLanguageScope = new Scope(); slangLanguageScope->nextSibling = hlslLanguageScope; - addBuiltinSource(coreLanguageScope, "core", getCoreLibraryCode()); - addBuiltinSource(hlslLanguageScope, "hlsl", getHLSLLibraryCode()); + if (false) + { + // Let's try loading serialized modules and adding them + _readBuiltinModule(coreLanguageScope, "core"); + _readBuiltinModule(hlslLanguageScope, "hlsl"); + } + else + { + addBuiltinSource(coreLanguageScope, "core", getCoreLibraryCode()); + addBuiltinSource(hlslLanguageScope, "hlsl", getHLSLLibraryCode()); + + // Write out + if (false) + { + for (auto& pair : m_builtinLinkage->mapNameToLoadedModules) + { + const Name* moduleName = pair.Key; + Module* module = pair.Value; + + // Set up options + SerialContainerUtil::WriteOptions options; + //options.optionFlags |= SerialOptionFlag::SourceLocation; + options.sourceManager = m_builtinLinkage->getSourceManager(); + + StringBuilder builder; + builder << moduleName->text << ".slang-module"; + + FileStream stream(builder.ProduceString(), FileMode::Create, FileAccess::Write, FileShare::ReadWrite); + if (SLANG_FAILED(SerialContainerUtil::write(module, options, &stream))) + { + SLANG_UNEXPECTED("Unable to load stdlib"); + } + } + } + } { for (Index i = 0; i < Index(SourceLanguage::CountOf); ++i) @@ -194,6 +226,88 @@ void Session::init() m_languagePreludes[Index(SourceLanguage::HLSL)] = get_slang_hlsl_prelude(); } +SlangResult Session::_readBuiltinModule(Scope* scope, String moduleName) +{ + StringBuilder moduleFilename; + moduleFilename << moduleName << ".slang-module"; + + RiffContainer riffContainer; + try + { + FileStream stream(moduleFilename.ProduceString(), FileMode::Open, FileAccess::Read, FileShare::ReadOnly); + // Load the riff container + SLANG_RETURN_ON_FAIL(RiffUtil::read(&stream, riffContainer)); + } + catch (const IOException&) + { + return SLANG_FAIL; + } + + // Load up the module + + SerialContainerData containerData; + + Linkage* linkage = getBuiltinLinkage(); + + NamePool* sessionNamePool = &namePool; + NamePool* linkageNamePool = linkage->getNamePool(); + + SerialContainerUtil::ReadOptions options; + options.namePool = linkageNamePool; + options.session = this; + options.sharedASTBuilder = linkage->getASTBuilder()->getSharedASTBuilder(); + options.sourceManager = linkage->getSourceManager(); + options.linkage = linkage; + + // Hmm - don't have a suitable sink yet, so attempt to just not have one + options.sink = nullptr; + + SLANG_RETURN_ON_FAIL(SerialContainerUtil::read(&riffContainer, options, containerData)); + + for (auto& srcModule : containerData.modules) + { + RefPtr<Module> module(new Module(linkage, srcModule.astBuilder)); + + ModuleDecl* moduleDecl = as<ModuleDecl>(srcModule.astRootNode); + + if (moduleDecl) + { + if (isFromStdLib(moduleDecl)) + { + registerBuiltinDecls(this, moduleDecl); + } + + module->setModuleDecl(moduleDecl); + } + + module->setIRModule(srcModule.irModule); + + // Put in the loaded module map + linkage->mapNameToLoadedModules.Add(sessionNamePool->getName(moduleName), module); + + // Add the resulting code to the appropriate scope + if (!scope->containerDecl) + { + // We are the first chunk of code to be loaded for this scope + scope->containerDecl = moduleDecl; + } + else + { + // We need to create a new scope to link into the whole thing + auto subScope = new Scope(); + subScope->containerDecl = moduleDecl; + subScope->nextSibling = scope->nextSibling; + scope->nextSibling = subScope; + } + + // We need to retain this AST so that we can use it in other code + // (Note that the `Scope` type does not retain the AST it points to) + stdlibModules.add(module); + } + + return SLANG_OK; +} + ISlangUnknown* Session::getInterface(const Guid& guid) { if(guid == IID_ISlangUnknown || guid == IID_IGlobalSession) @@ -1240,7 +1354,7 @@ void FrontEndCompileRequest::generateIR() options.compressionType = SerialCompressionType::None; options.sourceManager = getSourceManager(); - options.optionFlags |= SerialOptionFlag::DebugInfo; + options.optionFlags |= SerialOptionFlag::SourceLocation; // Verify debug information if (SLANG_FAILED(SerialContainerUtil::verifyIRSerialize(irModule, getSession(), options))) @@ -1950,11 +2064,19 @@ void FilePathDependencyList::addDependency(Module* module) // Module // -Module::Module(Linkage* linkage) +Module::Module(Linkage* linkage, ASTBuilder* astBuilder) : ComponentType(linkage) - , m_astBuilder(linkage->getASTBuilder()->getSharedASTBuilder(), "Module") , m_mangledExportPool(StringSlicePool::Style::Empty) { + if (astBuilder) + { + m_astBuilder = astBuilder; + } + else + { + m_astBuilder = new ASTBuilder(linkage->getASTBuilder()->getSharedASTBuilder(), "Module"); + } + addModuleDependency(this); } @@ -2053,7 +2175,7 @@ void Module::_processFindDeclsExportSymbolsRec(Decl* decl) return; } - // process `decl` itself + // If it's a container process it's children if(auto containerDecl = as<ContainerDecl>(decl)) { for (auto child : containerDecl->members) @@ -2061,7 +2183,9 @@ void Module::_processFindDeclsExportSymbolsRec(Decl* decl) _processFindDeclsExportSymbolsRec(child); } } - else if (auto genericDecl = as<GenericDecl>(decl)) + + // GenericDecl is also a container, so do subsequent test + if (auto genericDecl = as<GenericDecl>(decl)) { _processFindDeclsExportSymbolsRec(genericDecl->inner); } |
